language_code/
iso639_1.rs

1//! [List of ISO 639-1 codes - Wikipedia](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
2
3use country_code::iso3166_1::alpha_2::CountryCode;
4
5use crate::{language_code, language_tag};
6
7language_code! {
8    length = 2;
9    #[derive(Debug, Clone)]
10    #[allow(non_camel_case_types)]
11    pub enum LanguageCode {
12        ab,
13        aa,
14        af,
15        ak,
16        sq,
17        am,
18        ar,
19        an,
20        hy,
21        r#as,
22        av,
23        ae,
24        ay,
25        az,
26        bm,
27        ba,
28        eu,
29        be,
30        bn,
31        bi,
32        bs,
33        br,
34        bg,
35        my,
36        ca,
37        ch,
38        ce,
39        ny,
40        zh,
41        cu,
42        cv,
43        kw,
44        co,
45        cr,
46        hr,
47        cs,
48        da,
49        dv,
50        nl,
51        dz,
52        en,
53        eo,
54        et,
55        ee,
56        fo,
57        fj,
58        fi,
59        fr,
60        fy,
61        ff,
62        gd,
63        gl,
64        lg,
65        ka,
66        de,
67        el,
68        kl,
69        gn,
70        gu,
71        ht,
72        ha,
73        he,
74        hz,
75        hi,
76        ho,
77        hu,
78        is,
79        io,
80        ig,
81        id,
82        ia,
83        ie,
84        iu,
85        ik,
86        ga,
87        it,
88        ja,
89        jv,
90        kn,
91        kr,
92        ks,
93        kk,
94        km,
95        ki,
96        rw,
97        ky,
98        kv,
99        kg,
100        ko,
101        kj,
102        ku,
103        lo,
104        la,
105        lv,
106        li,
107        ln,
108        lt,
109        lu,
110        lb,
111        mk,
112        mg,
113        ms,
114        ml,
115        mt,
116        gv,
117        mi,
118        mr,
119        mh,
120        mn,
121        na,
122        nv,
123        nd,
124        nr,
125        ng,
126        ne,
127        no,
128        nb,
129        nn,
130        ii,
131        oc,
132        oj,
133        or,
134        om,
135        os,
136        pi,
137        ps,
138        fa,
139        pl,
140        pt,
141        pa,
142        qu,
143        ro,
144        rm,
145        rn,
146        ru,
147        se,
148        sm,
149        sg,
150        sa,
151        sc,
152        sr,
153        sn,
154        sd,
155        si,
156        sk,
157        sl,
158        so,
159        st,
160        es,
161        su,
162        sw,
163        ss,
164        sv,
165        tl,
166        ty,
167        tg,
168        ta,
169        tt,
170        te,
171        th,
172        bo,
173        ti,
174        to,
175        ts,
176        tn,
177        tr,
178        tk,
179        tw,
180        ug,
181        uk,
182        ur,
183        uz,
184        ve,
185        vi,
186        vo,
187        wa,
188        cy,
189        wo,
190        xh,
191        yi,
192        yo,
193        za,
194        zu,
195    }
196}
197
198//
199impl Default for LanguageCode {
200    fn default() -> Self {
201        Self::en
202    }
203}
204
205language_tag! {
206    #[derive(Debug, Clone)]
207    pub struct LanguageTag {
208        pub language_code: LanguageCode,
209        pub country_code: Option<CountryCode>,
210    }
211}
212
213impl Default for LanguageTag {
214    fn default() -> Self {
215        Self::new(LanguageCode::en, None)
216    }
217}
218
219#[cfg(test)]
220mod tests {
221    use super::*;
222
223    use alloc::string::ToString as _;
224
225    use csv::Reader;
226
227    #[test]
228    fn test_language_code() {
229        // Wikipedia
230        let mut rdr = Reader::from_reader(
231            include_str!("../tests/List_of_ISO_639-1_codes/list.csv").as_bytes(),
232        );
233
234        let mut n = 0;
235        for record in rdr.records() {
236            let record = record.unwrap();
237
238            let code = &record[1];
239            assert_eq!(code.parse::<LanguageCode>().unwrap().to_string(), code);
240            n += 1;
241        }
242
243        assert_eq!(LanguageCode::VARS.len(), n);
244
245        // FromStr
246        assert_eq!(
247            "zz".parse::<LanguageCode>().unwrap(),
248            LanguageCode::Other("zz".into())
249        );
250        assert_eq!(
251            "x".parse::<LanguageCode>().err().unwrap(),
252            crate::error::ParseError::Invalid("x".into())
253        );
254        #[cfg(feature = "std")]
255        {
256            std::println!("{}", "x".parse::<LanguageCode>().err().unwrap());
257        }
258
259        // PartialEq
260        assert_eq!(LanguageCode::en, LanguageCode::en);
261        assert_eq!(LanguageCode::en, LanguageCode::Other("en".into()));
262        assert_eq!(LanguageCode::en, "en");
263
264        #[cfg(feature = "std")]
265        {
266            // Hash
267            let mut h = std::collections::HashSet::new();
268            h.insert(LanguageCode::en);
269            h.insert(LanguageCode::Other("en".into()));
270            assert_eq!(h.len(), 1);
271        }
272
273        // Default
274        assert_eq!(LanguageCode::default(), LanguageCode::en);
275
276        #[cfg(feature = "serde")]
277        {
278            #[derive(serde::Serialize, serde::Deserialize)]
279            struct Foo {
280                code: LanguageCode,
281            }
282
283            assert_eq!(
284                serde_json::from_str::<Foo>(r#"{"code":"en"}"#)
285                    .unwrap()
286                    .code,
287                LanguageCode::en
288            );
289            assert_eq!(
290                serde_json::to_string(&Foo {
291                    code: LanguageCode::en
292                })
293                .unwrap(),
294                r#"{"code":"en"}"#
295            );
296        }
297    }
298
299    #[test]
300    fn test_language_tag() {
301        // FromStr
302        assert_eq!(
303            "en".parse::<LanguageTag>().unwrap(),
304            LanguageTag::new(LanguageCode::en, None)
305        );
306        assert_eq!(LanguageTag::new(LanguageCode::en, None).to_string(), "en",);
307
308        assert_eq!(
309            "zh-CN".parse::<LanguageTag>().unwrap(),
310            LanguageTag::new(LanguageCode::zh, Some(CountryCode::CN))
311        );
312        assert_eq!(
313            LanguageTag::new(LanguageCode::zh, Some(CountryCode::CN)).to_string(),
314            "zh-CN"
315        );
316        assert_eq!(
317            "zh-TW".parse::<LanguageTag>().unwrap(),
318            LanguageTag::new(LanguageCode::zh, Some(CountryCode::TW))
319        );
320
321        assert_eq!(
322            "x-y".parse::<LanguageTag>().err().unwrap(),
323            crate::error::LanguageTagParseError::LanguageCodeInvalid("x".into())
324        );
325        assert_eq!(
326            "en-y".parse::<LanguageTag>().err().unwrap(),
327            crate::error::LanguageTagParseError::CountryCodeInvalid("y".into())
328        );
329
330        // PartialEq
331        assert_eq!(
332            LanguageTag::new(LanguageCode::en, None),
333            LanguageTag::new(LanguageCode::en, None)
334        );
335        assert_eq!(LanguageTag::new(LanguageCode::en, None), "en");
336
337        // Default
338        assert_eq!(
339            LanguageTag::default(),
340            LanguageTag::new(LanguageCode::en, None)
341        );
342
343        #[cfg(feature = "serde")]
344        {
345            #[derive(serde::Serialize, serde::Deserialize)]
346            struct Foo {
347                tag: LanguageTag,
348            }
349
350            assert_eq!(
351                serde_json::from_str::<Foo>(r#"{"tag":"en"}"#).unwrap().tag,
352                LanguageTag::new(LanguageCode::en, None),
353            );
354            assert_eq!(
355                serde_json::to_string(&Foo {
356                    tag: LanguageTag::new(LanguageCode::en, None)
357                })
358                .unwrap(),
359                r#"{"tag":"en"}"#
360            );
361        }
362    }
363}