Skip to main content

korean_romanize/
lib.rs

1#![doc = include_str!("../README.md")]
2// #![warn(missing_docs, clippy::todo)]
3
4use crate::{hangul::Syllable, romanizer::{MixedBlock, MixedChar, Romanizable}};
5
6mod romanizer;
7mod hangul;
8
9/// Converts Korean characters into romanized
10/// text.
11pub fn convert(text: impl Into<String>) -> String {
12    text.into()
13        .chars()
14        .map(Into::<MixedChar>::into)
15        .collect::<Vec<MixedBlock>>()
16        .romanize()
17}
18
19/// Checks if the input string is in Korean.
20/// Returns true if any character in the string is Korean.
21pub fn has_korean(input: impl Into<String>) -> bool {
22    input.into().chars().any(|c| Syllable::is_syllable(c))
23}
24
25#[cfg(test)]
26mod common_examples {
27    //! Just normal use case scenarios.
28    use super::*;
29
30    /// Common sentences
31    #[test]
32    fn greetings() {
33        assert_eq!(&convert("안녕"), "annyeong");
34        assert_eq!(&convert("여보세요"), "yeoboseyo");
35
36        // TODO: Fails because joheun achimieyo instead.
37        // assert_eq!(&convert("좋은 아침이에요"), "joeun achimieyo");
38
39        assert_eq!(&convert("어떻게 지내세요"), "eotteohge jinaeseyo");
40        assert_eq!(&convert("잘 지내요"), "jal jinaeyo");
41        assert_eq!(&convert("오랜만이에요"), "oraenmanieyo");
42        assert_eq!(&convert("안녕"), "annyeong");
43        assert_eq!(&convert("안녕히 가세요"), "annyeonghi gaseyo");
44        assert_eq!(&convert("안녕히 계세요"), "annyeonghi gyeseyo");
45        assert_eq!(&convert("잘 가요"), "jal gayo");
46
47        assert_eq!(&convert("만나서 반갑습니다"), "mannaseo bangapseumnida");
48
49        assert_eq!(&convert("한국에 가서 영화를 봤어요"), "hanguge gaseo yeonghwareul bwasseoyo");
50        assert_eq!(&convert("국민들이 많이 모였어요"), "gungmindeuri manhi moyeosseoyo");
51        assert_eq!(&convert("한국말을 잘하려면 많이 연습해야 해요"), "hangungmareul jalharyeomyeon manhi yeonseuphaeya haeyo");
52    }
53
54}
55
56#[cfg(test)]
57mod functionality_tests {
58    //! Testing using examples from
59    //! https://www.korean.go.kr/front_eng/roman/roman_01.do
60
61    use super::*;
62
63    #[test]
64    fn test_is_korean() {
65        assert!(has_korean("안녕"));
66        assert!(has_korean("안녕 Hello"));
67        assert!(!has_korean("Hello"));
68    }
69
70    /// The sounds ㄱ, ㄷ, and ㅂ are transcribed respectively
71    /// as g, d, and b before a vowel; they are transcribed as
72    /// k, t, and p when they appear before another consonant
73    /// or as the last sound of a word.
74    #[test]
75    fn simple_1() {
76        assert_eq!(&convert("구미"), "gumi");
77        assert_eq!(&convert("영동"), "yeongdong");
78        assert_eq!(&convert("백암"), "baegam");
79        assert_eq!(&convert("옥천"), "okcheon");
80        assert_eq!(&convert("합덕"), "hapdeok");
81        assert_eq!(&convert("호법"), "hobeop");
82        assert_eq!(&convert("월곶"), "wolgot");
83        assert_eq!(&convert("벚꽃"), "beotkkot");
84        assert_eq!(&convert("한밭"), "hanbat");
85    }
86
87    /// ㄹ is transcribed as r before a vowel,
88    /// and as l before a consonant or at the end of a word:
89    /// ㄹㄹ is transcribed as ll.
90    #[test]
91    fn simple_2() {
92        assert_eq!(&convert("구리"), "guri");
93        assert_eq!(&convert("설악"), "seorak");
94        assert_eq!(&convert("칠곡"), "chilgok");
95        assert_eq!(&convert("임실"), "imsil");
96        assert_eq!(&convert("울릉"), "ulleung");
97        assert_eq!(&convert("대관령"), "daegwallyeong");
98    }
99
100    /// When Korean sound values change as in the following cases,
101    /// the results of those changes are transcribed as follows
102    #[test]
103    fn assimilation() {
104        assert_eq!(&convert("백마"), "baengma");
105
106        // won't work.
107        // assert_eq!(&convert("신문로"), "sinmunno");
108
109        assert_eq!(&convert("종로"), "jongno");
110        assert_eq!(&convert("왕십리"), "wangsimni");
111        assert_eq!(&convert("별내"), "byeollae");
112    }
113
114    /// The case of the epenthetic ㄴ and ㄹ
115    #[test]
116    fn epenthetic() {
117        assert_eq!(&convert("학여울"), "hangnyeoul");
118        assert_eq!(&convert("알약"), "allyak");
119        assert_eq!(&convert("솜이불"), "somnibul");
120        assert_eq!(&convert("식용유"), "sigyongnyu");
121    }
122
123    /// The case of palatalization
124    #[test]
125    fn palatalization() {
126        assert_eq!(&convert("해돋이"), "haedoji");
127        assert_eq!(&convert("같이"), "gachi");
128        assert_eq!(&convert("굳히다"), "guchida");
129
130        // Examples from https://www.mykoreanlesson.com/post/korean-pronunciation-lesson-palatalization
131        assert_eq!(&convert("굳이"), "guji");
132        assert_eq!(&convert("맏이"), "maji");
133
134        assert_eq!(&convert("밭이"), "bachi");
135        assert_eq!(&convert("샅샅이"), "satsachi");
136
137        assert_eq!(&convert("묻히다"), "muchida");
138        assert_eq!(&convert("닫히다"), "dachida");
139    }
140}