flutter_flow_language_selector.dart 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /*
  2. * Copyright (c) 2019 gomgom. https://www.gomgom.net
  3. *
  4. * Source code has been modified by FlutterFlow, Inc. and the below license
  5. * applies only to this file. Adapted from "language_picker" pub.dev package.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. import 'package:emoji_flag_converter/emoji_flag_converter.dart';
  26. import 'package:flutter/material.dart';
  27. class FlutterFlowLanguageSelector extends StatelessWidget {
  28. const FlutterFlowLanguageSelector({
  29. Key? key,
  30. required this.currentLanguage,
  31. required this.languages,
  32. required this.onChanged,
  33. this.width,
  34. this.height,
  35. this.backgroundColor,
  36. this.borderColor = const Color(0xFF262D34),
  37. this.borderRadius = 8.0,
  38. this.textStyle,
  39. this.hideFlags = false,
  40. this.flagSize = 24.0,
  41. this.flagTextGap = 8.0,
  42. this.dropdownColor,
  43. this.dropdownIconColor = const Color(0xFF14181B),
  44. this.dropdownIcon,
  45. }) : super(key: key);
  46. final double? width;
  47. final double? height;
  48. final String currentLanguage;
  49. final List<String> languages;
  50. final Function(String) onChanged;
  51. final Color? backgroundColor;
  52. final Color? borderColor;
  53. final double borderRadius;
  54. final TextStyle? textStyle;
  55. final bool hideFlags;
  56. final double flagSize;
  57. final double? flagTextGap;
  58. final Color? dropdownColor;
  59. final Color? dropdownIconColor;
  60. final IconData? dropdownIcon;
  61. @override
  62. Widget build(BuildContext context) => Container(
  63. width: width,
  64. height: height,
  65. child: _LanguagePickerDropdown(
  66. currentLanguage: currentLanguage,
  67. languages: _languageMap(languages.toSet()),
  68. onChanged: onChanged,
  69. backgroundColor: backgroundColor,
  70. borderColor: borderColor,
  71. borderRadius: borderRadius,
  72. dropdownColor: dropdownColor,
  73. dropdownIconColor: dropdownIconColor,
  74. dropdownIcon: dropdownIcon,
  75. itemBuilder: (language) => _LanguagePickerItem(
  76. language: language.isoCode,
  77. languages: languages,
  78. textStyle: textStyle,
  79. hideFlags: hideFlags,
  80. flagSize: flagSize,
  81. flagTextGap: flagTextGap,
  82. ),
  83. ),
  84. );
  85. }
  86. class _LanguagePickerItem extends StatelessWidget {
  87. const _LanguagePickerItem({
  88. Key? key,
  89. required this.language,
  90. required this.languages,
  91. this.textStyle,
  92. this.hideFlags = false,
  93. this.flagSize = 24.0,
  94. this.flagTextGap = 8.0,
  95. }) : super(key: key);
  96. final String language;
  97. final List<String> languages;
  98. final TextStyle? textStyle;
  99. final bool hideFlags;
  100. final double flagSize;
  101. final double? flagTextGap;
  102. @override
  103. Widget build(BuildContext context) {
  104. final flagInfo = languageToCountryInfo[language];
  105. Widget flagWidget = Container();
  106. if (flagInfo is String) {
  107. final flagEmoji = EmojiConverter.fromAlpha2CountryCode(flagInfo);
  108. flagWidget = Padding(
  109. padding: const EdgeInsets.only(bottom: 2.0),
  110. child: Text(
  111. flagEmoji,
  112. style: const TextStyle(fontSize: 20.0),
  113. ),
  114. );
  115. } else if (flagInfo is Map) {
  116. final flagUrl = flagInfo['flag'] as String;
  117. flagWidget = Image.network(
  118. flagUrl,
  119. width: 24,
  120. height: 20,
  121. );
  122. }
  123. flagWidget = Transform.scale(
  124. scale: flagSize / 24.0,
  125. child: Container(
  126. width: 24,
  127. child: flagWidget,
  128. ),
  129. );
  130. return Row(
  131. children: [
  132. if (!hideFlags) ...[
  133. flagWidget,
  134. SizedBox(width: flagTextGap),
  135. ],
  136. Text(
  137. _languageMap(languages.toSet())[language]?.name ?? '',
  138. style: textStyle ??
  139. const TextStyle(
  140. color: Colors.white,
  141. fontSize: 13,
  142. fontWeight: FontWeight.normal,
  143. ),
  144. ),
  145. ],
  146. );
  147. }
  148. }
  149. /// Provides a customizable [DropdownButton] for all languages
  150. class _LanguagePickerDropdown extends StatelessWidget {
  151. const _LanguagePickerDropdown({
  152. required this.itemBuilder,
  153. required this.currentLanguage,
  154. required this.onChanged,
  155. required this.languages,
  156. this.backgroundColor,
  157. this.borderColor = const Color(0xFF262D34),
  158. this.borderRadius = 8.0,
  159. this.dropdownColor,
  160. this.dropdownIconColor = const Color(0xFF14181B),
  161. this.dropdownIcon,
  162. });
  163. /// This function will be called to build the child of DropdownMenuItem.
  164. final Widget Function(Language) itemBuilder;
  165. /// The current ISO ALPHA-2 code.
  166. final String currentLanguage;
  167. /// This function will be called whenever a Language item is selected.
  168. final ValueChanged<String> onChanged;
  169. /// List of languages available in this picker.
  170. final Map<String, Language> languages;
  171. final Color? backgroundColor;
  172. final Color? borderColor;
  173. final double borderRadius;
  174. final Color? dropdownColor;
  175. final Color? dropdownIconColor;
  176. final IconData? dropdownIcon;
  177. @override
  178. Widget build(BuildContext context) {
  179. List<DropdownMenuItem<String>> items = languages.values
  180. .map(
  181. (language) => DropdownMenuItem<String>(
  182. value: language.isoCode,
  183. child: itemBuilder(language),
  184. ),
  185. )
  186. .toList();
  187. return Container(
  188. height: 44.0,
  189. decoration: BoxDecoration(
  190. color: backgroundColor,
  191. border: Border.all(color: borderColor ?? Colors.transparent),
  192. borderRadius: BorderRadius.circular(borderRadius),
  193. ),
  194. child: Padding(
  195. padding: const EdgeInsets.symmetric(horizontal: 15.0),
  196. child: Center(
  197. child: DropdownButton<String>(
  198. isExpanded: true,
  199. underline: Container(),
  200. dropdownColor: dropdownColor ?? backgroundColor,
  201. focusColor: Colors.transparent,
  202. iconEnabledColor: dropdownIconColor,
  203. iconDisabledColor: dropdownIconColor,
  204. icon: dropdownIcon != null
  205. ? Icon(
  206. dropdownIcon,
  207. size: 18.0,
  208. color: dropdownIconColor,
  209. )
  210. : null,
  211. hint: const Text(
  212. 'Unset',
  213. style: TextStyle(
  214. color: Colors.red,
  215. fontFamily: 'Product Sans',
  216. fontStyle: FontStyle.italic,
  217. fontSize: 15,
  218. ),
  219. ),
  220. onChanged: (val) {
  221. if (val != null) {
  222. onChanged(val);
  223. }
  224. },
  225. items: items,
  226. value: currentLanguage.isNotEmpty ? currentLanguage : null,
  227. ),
  228. ),
  229. ),
  230. );
  231. }
  232. }
  233. class Language {
  234. Language(this.isoCode, this.name);
  235. Language.fromMap(Map<String, String> map)
  236. : name = map['name']!,
  237. isoCode = map['isoCode']!;
  238. final String name;
  239. final String isoCode;
  240. }
  241. Map<String, Language> _languageMap(Set<String> languages) => Map.fromEntries(
  242. _defaultLanguagesList
  243. .where((element) => languages.contains(element['isoCode']))
  244. .map((e) => MapEntry(e['isoCode']!, Language.fromMap(e))),
  245. );
  246. final List<Map<String, String>> _defaultLanguagesList = [
  247. {"isoCode": "aa", "name": "Afaraf"},
  248. {"isoCode": "af", "name": "Afrikaans"},
  249. {"isoCode": "ak", "name": "Akan"},
  250. {"isoCode": "sq", "name": "Shqip"},
  251. {"isoCode": "am", "name": "አማርኛ"},
  252. {"isoCode": "ar", "name": "العربية"},
  253. {"isoCode": "hy", "name": "Հայերեն"},
  254. {"isoCode": "as", "name": "অসমীয়া"},
  255. {"isoCode": "ay", "name": "Aymar"},
  256. {"isoCode": "az", "name": "Azərbaycan"},
  257. {"isoCode": "bm", "name": "Bamanankan"},
  258. {"isoCode": "ba", "name": "Башҡорт теле"},
  259. {"isoCode": "eu", "name": "Euskara, Euskera"},
  260. {"isoCode": "be", "name": "Беларуская мова"},
  261. {"isoCode": "bn", "name": "বাংলা"},
  262. {"isoCode": "bh", "name": "भोजपुरी"},
  263. {"isoCode": "bi", "name": "Bislama"},
  264. {"isoCode": "nb", "name": "Norsk bokmål"},
  265. {"isoCode": "bs", "name": "Bosanski jezik"},
  266. {"isoCode": "br", "name": "Brezhoneg"},
  267. {"isoCode": "bg", "name": "Български език"},
  268. {"isoCode": "my", "name": "ဗမာစာ"},
  269. {"isoCode": "ca", "name": "Català"},
  270. {"isoCode": "km", "name": "ភាសាខ្មែរ"},
  271. {"isoCode": "ch", "name": "Chamoru"},
  272. {"isoCode": "ce", "name": "Нохчийн мотт"},
  273. {"isoCode": "ny", "name": "chiCheŵa"},
  274. {"isoCode": "zh_Hans", "name": "中文 (简体)"},
  275. {"isoCode": "zh_Hant", "name": "中文 (繁體)"},
  276. {"isoCode": "cv", "name": "чӑваш чӗлхи"},
  277. {"isoCode": "cr", "name": "ᓀᐦᐃᔭᐍᐏᐣ"},
  278. {"isoCode": "hr", "name": "Hrvatski jezik"},
  279. {"isoCode": "cs", "name": "Čeština"},
  280. {"isoCode": "da", "name": "Dansk"},
  281. {"isoCode": "dv", "name": "ދިވެހި"},
  282. {"isoCode": "nl", "name": "Nederlands"},
  283. {"isoCode": "dz", "name": "རྫོང་ཁ"},
  284. {"isoCode": "en", "name": "English"},
  285. {"isoCode": "eo", "name": "Esperanto"},
  286. {"isoCode": "et", "name": "Eesti"},
  287. {"isoCode": "ee", "name": "Eʋegbe"},
  288. {"isoCode": "fo", "name": "Føroyskt"},
  289. {"isoCode": "fj", "name": "vosa Vakaviti"},
  290. {"isoCode": "fi", "name": "Suomi"},
  291. {"isoCode": "fr", "name": "Français"},
  292. {"isoCode": "ff", "name": "Fulfulde"},
  293. {"isoCode": "gd", "name": "Gàidhlig"},
  294. {"isoCode": "gl", "name": "Galego"},
  295. {"isoCode": "lg", "name": "Luganda"},
  296. {"isoCode": "ka", "name": "ქართული"},
  297. {"isoCode": "de", "name": "Deutsch"},
  298. {"isoCode": "el", "name": "ελληνικά"},
  299. {"isoCode": "gn", "name": "Avañe'ẽ"},
  300. {"isoCode": "gu", "name": "ગુજરાતી"},
  301. {"isoCode": "ht", "name": "Kreyòl ayisyen"},
  302. {"isoCode": "ha", "name": "هَوُسَ"},
  303. {"isoCode": "he", "name": "עברית"},
  304. {"isoCode": "hz", "name": "Otjiherero"},
  305. {"isoCode": "hi", "name": "हिन्दी"},
  306. {"isoCode": "ho", "name": "Hiri Motu"},
  307. {"isoCode": "hu", "name": "Magyar"},
  308. {"isoCode": "is", "name": "Íslenska"},
  309. {"isoCode": "io", "name": "Ido"},
  310. {"isoCode": "ig", "name": "Asụsụ Igbo"},
  311. {"isoCode": "id", "name": "Bahasa Indonesia"},
  312. {"isoCode": "ia", "name": "Interlingua"},
  313. {"isoCode": "ie", "name": "Interlingue"},
  314. {"isoCode": "iu", "name": "ᐃᓄᒃᑎᑐᑦ"},
  315. {"isoCode": "ik", "name": "Iñupiaq"},
  316. {"isoCode": "ga", "name": "Gaeilge"},
  317. {"isoCode": "it", "name": "Italiano"},
  318. {"isoCode": "ja", "name": "日本語 (にほんご)"},
  319. {"isoCode": "jv", "name": "ꦧꦱꦗꦮ"},
  320. {"isoCode": "kl", "name": "Kalaallisut"},
  321. {"isoCode": "kn", "name": "ಕನ್ನಡ"},
  322. {"isoCode": "kr", "name": "Kanuri"},
  323. {"isoCode": "ks", "name": "कश्मीरी"},
  324. {"isoCode": "kk", "name": "қазақ тілі"},
  325. {"isoCode": "ki", "name": "Gĩkũyũ"},
  326. {"isoCode": "rw", "name": "Ikinyarwanda"},
  327. {"isoCode": "ky", "name": "Кыргызча"},
  328. {"isoCode": "kv", "name": "коми кыв"},
  329. {"isoCode": "kg", "name": "Kikongo"},
  330. {"isoCode": "ko", "name": "한국어"},
  331. {"isoCode": "kj", "name": "Kuanyama"},
  332. {"isoCode": "ku", "name": "Kurdî"},
  333. {"isoCode": "lo", "name": "ພາສາລາວ"},
  334. {"isoCode": "la", "name": "Latine"},
  335. {"isoCode": "lv", "name": "Latviešu valoda"},
  336. {"isoCode": "li", "name": "Limburgs"},
  337. {"isoCode": "ln", "name": "Lingála"},
  338. {"isoCode": "lt", "name": "Lietuvių kalba"},
  339. {"isoCode": "lu", "name": "Tshiluba"},
  340. {"isoCode": "lb", "name": "Lëtzebuergesch"},
  341. {"isoCode": "mk", "name": "Македонски јазик"},
  342. {"isoCode": "mg", "name": "Fiteny Malagasy"},
  343. {"isoCode": "ms", "name": "Bahasa Melayu"},
  344. {"isoCode": "ml", "name": "മലയാളം"},
  345. {"isoCode": "mt", "name": "Malti"},
  346. {"isoCode": "gv", "name": "Gaelg, Gailck"},
  347. {"isoCode": "mi", "name": "te reo Māori"},
  348. {"isoCode": "mr", "name": "मराठी"},
  349. {"isoCode": "mh", "name": "Kajin M̧ajeļ"},
  350. {"isoCode": "mn", "name": "Монгол хэл"},
  351. {"isoCode": "na", "name": "Dorerin Naoero"},
  352. {"isoCode": "nv", "name": "Diné bizaad"},
  353. {"isoCode": "nd", "name": "Ndebele (Southern)"},
  354. {"isoCode": "nr", "name": "Ndebele (Northern)"},
  355. {"isoCode": "ng", "name": "Owambo"},
  356. {"isoCode": "ne", "name": "नेपाली"},
  357. {"isoCode": "se", "name": "Davvisámegiella"},
  358. {"isoCode": "no", "name": "Norsk"},
  359. {"isoCode": "nn", "name": "Norsk nynorsk"},
  360. {"isoCode": "oc", "name": "Occitan"},
  361. {"isoCode": "oj", "name": "ᐊᓂᔑᓈᐯᒧᐎᓐ"},
  362. {"isoCode": "or", "name": "ଓଡ଼ିଆ"},
  363. {"isoCode": "om", "name": "Afaan Oromoo"},
  364. {"isoCode": "os", "name": "ирон æвзаг"},
  365. {"isoCode": "pi", "name": "पाऴि"},
  366. {"isoCode": "pa", "name": "ਪੰਜਾਬੀ"},
  367. {"isoCode": "fa", "name": "فارسی"},
  368. {"isoCode": "pl", "name": "Polski"},
  369. {"isoCode": "pt", "name": "Português"},
  370. {"isoCode": "ps", "name": "پښتو"},
  371. {"isoCode": "qu", "name": "Runa Simi, Kichwa"},
  372. {"isoCode": "ro", "name": "Română"},
  373. {"isoCode": "rm", "name": "rumantsch grischun"},
  374. {"isoCode": "rn", "name": "Ikirundi"},
  375. {"isoCode": "ru", "name": "Русский"},
  376. {"isoCode": "sm", "name": "gagana fa'a Samoa"},
  377. {"isoCode": "sg", "name": "yângâ tî sängö"},
  378. {"isoCode": "sa", "name": "संस्कृतम्"},
  379. {"isoCode": "sc", "name": "Sardu"},
  380. {"isoCode": "sr", "name": "српски језик"},
  381. {"isoCode": "sn", "name": "chiShona"},
  382. {"isoCode": "ii", "name": "ꆈꌠ꒿ Nuosuhxop"},
  383. {"isoCode": "sd", "name": "सिन्धी"},
  384. {"isoCode": "si", "name": "සිංහල"},
  385. {"isoCode": "sk", "name": "Slovenský jazyk"},
  386. {"isoCode": "sl", "name": "Slovenščina"},
  387. {"isoCode": "so", "name": "Soomaaliga"},
  388. {"isoCode": "st", "name": "Sesotho"},
  389. {"isoCode": "es", "name": "Español"},
  390. {"isoCode": "su", "name": "Basa Sunda"},
  391. {"isoCode": "sw", "name": "Kiswahili"},
  392. {"isoCode": "ss", "name": "SiSwati"},
  393. {"isoCode": "sv", "name": "Svenska"},
  394. {"isoCode": "tl", "name": "Tagalog"},
  395. {"isoCode": "ty", "name": "Reo Tahiti"},
  396. {"isoCode": "tg", "name": "тоҷикӣ"},
  397. {"isoCode": "ta", "name": "தமிழ்"},
  398. {"isoCode": "tt", "name": "татар теле"},
  399. {"isoCode": "te", "name": "తెలుగు"},
  400. {"isoCode": "th", "name": "ไทย"},
  401. {"isoCode": "bo", "name": "བོད་ཡིག"},
  402. {"isoCode": "ti", "name": "ትግርኛ"},
  403. {"isoCode": "to", "name": "faka Tonga"},
  404. {"isoCode": "ts", "name": "Xitsonga"},
  405. {"isoCode": "tn", "name": "Setswana"},
  406. {"isoCode": "tr", "name": "Türkçe"},
  407. {"isoCode": "tk", "name": "Түркмен"},
  408. {"isoCode": "tw", "name": "Twi"},
  409. {"isoCode": "ug", "name": "ئۇيغۇرچە"},
  410. {"isoCode": "uk", "name": "Українська"},
  411. {"isoCode": "ur", "name": "اردو"},
  412. {"isoCode": "uz", "name": "Oʻzbek"},
  413. {"isoCode": "ve", "name": "Tshivenḓa"},
  414. {"isoCode": "vi", "name": "Tiếng Việt"},
  415. {"isoCode": "vo", "name": "Volapük"},
  416. {"isoCode": "wa", "name": "Walon"},
  417. {"isoCode": "cy", "name": "Cymraeg"},
  418. {"isoCode": "fy", "name": "Frysk"},
  419. {"isoCode": "wo", "name": "Wollof"},
  420. {"isoCode": "xh", "name": "Xhosa"},
  421. {"isoCode": "yi", "name": "ייִדיש"},
  422. {"isoCode": "yo", "name": "Yorùbá"},
  423. {"isoCode": "za", "name": "Saɯ cueŋƅ"},
  424. {"isoCode": "zu", "name": "Zulu"},
  425. ];
  426. final Map<String, dynamic> languageToCountryInfo = {
  427. "aa": "dj",
  428. "af": "za",
  429. "ak": "gh",
  430. "sq": "al",
  431. "am": "et",
  432. "ar": {
  433. "proposed_iso_3166": "aa",
  434. "flag":
  435. "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2b/Flag_of_the_Arab_League.svg/400px-Flag_of_the_Arab_League.svg.png",
  436. "name": "Arab League"
  437. },
  438. "hy": "am",
  439. "ay": {
  440. "proposed_iso_3166": "wh",
  441. "flag":
  442. "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b7/Banner_of_the_Qulla_Suyu.svg/1920px-Banner_of_the_Qulla_Suyu.svg.png",
  443. "name": "Wiphala"
  444. },
  445. "az": "az",
  446. "bm": "ml",
  447. "be": "by",
  448. "bn": "bd",
  449. "bi": "vu",
  450. "bs": "ba",
  451. "bg": "bg",
  452. "my": "mm",
  453. "ca": "ad",
  454. "zh": "cn",
  455. "hr": "hr",
  456. "cs": "cz",
  457. "da": "dk",
  458. "dv": "mv",
  459. "nl": "nl",
  460. "dz": "bt",
  461. "en": "gb",
  462. "et": "ee",
  463. "ee": {
  464. "proposed_iso_3166": "ew",
  465. "flag":
  466. "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Flag_of_the_Ewe_people.svg/2880px-Flag_of_the_Ewe_people.svg.png",
  467. "name": "Ewe"
  468. },
  469. "fj": "fj",
  470. "fil": "ph",
  471. "fi": "fi",
  472. "fr": "fr",
  473. "gaa": "gh",
  474. "ka": "ge",
  475. "kl": "gl",
  476. "de": "de",
  477. "el": "gr",
  478. "gu": "in",
  479. "ht": "ht",
  480. "he": "il",
  481. "hi": "in",
  482. "ho": "pg",
  483. "hu": "hu",
  484. "is": "is",
  485. "ig": "ng",
  486. "id": "id",
  487. "ga": "ie",
  488. "it": "it",
  489. "ja": "jp",
  490. "kr": "ne",
  491. "kk": "kz",
  492. "km": "kh",
  493. "kmb": "ao",
  494. "rw": "rw",
  495. "kg": "cg",
  496. "ko": "kr",
  497. "kj": "ao",
  498. "ku": "iq",
  499. "ky": "kg",
  500. "lo": "la",
  501. "la": "va",
  502. "lv": "lv",
  503. "ln": "cg",
  504. "lt": "lt",
  505. "lu": "cd",
  506. "lb": "lu",
  507. "mk": "mk",
  508. "mg": "mg",
  509. "ms": "my",
  510. "mt": "mt",
  511. "mi": "nz",
  512. "mh": "mh",
  513. "mn": "mn",
  514. "mos": "bf",
  515. "ne": "np",
  516. "nd": "zw",
  517. "nso": "za",
  518. "no": "no",
  519. "nb": "no",
  520. "nn": "no",
  521. "ny": "mw",
  522. "pap": "aw",
  523. "ps": "af",
  524. "fa": "ir",
  525. "pl": "pl",
  526. "pt": "pt",
  527. "pa": "in",
  528. "qu": "wh",
  529. "ro": "ro",
  530. "rm": "ch",
  531. "rn": "bi",
  532. "ru": "ru",
  533. "sg": "cf",
  534. "sr": "rs",
  535. "srr": "sn",
  536. "sn": "zw",
  537. "si": "lk",
  538. "sk": "sk",
  539. "sl": "si",
  540. "so": "so",
  541. "snk": "sn",
  542. "nr": "za",
  543. "st": "ls",
  544. "es": "es",
  545. "sw": {
  546. "proposed_iso_3166": "sw",
  547. "flag":
  548. "https://upload.wikimedia.org/wikipedia/commons/d/de/Flag_of_Swahili.gif",
  549. "name": "Swahili"
  550. },
  551. "ss": "sz",
  552. "sv": "se",
  553. "tl": "ph",
  554. "tg": "tj",
  555. "ta": "lk",
  556. "te": "in",
  557. "tet": "tl",
  558. "th": "th",
  559. "ti": "er",
  560. "tpi": "pg",
  561. "ts": "za",
  562. "tn": "bw",
  563. "tr": "tr",
  564. "tk": "tm",
  565. "uk": "ua",
  566. "umb": "ao",
  567. "ur": "pk",
  568. "uz": "uz",
  569. "ve": "za",
  570. "vi": "vn",
  571. "cy": "gb",
  572. "wo": "sn",
  573. "xh": "za",
  574. "yo": {
  575. "proposed_iso_3166": "yo",
  576. "flag":
  577. "https://upload.wikimedia.org/wikipedia/commons/0/04/Flag_of_the_Yoruba_people.svg",
  578. "name": "Yoruba"
  579. },
  580. "zu": "za",
  581. // Custom
  582. "zh_Hans": "cn",
  583. "zh_Hant": "cn",
  584. "fo": "fo",
  585. "bo": "bo",
  586. "to": "to",
  587. };