translation.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194
  1. /*************************************************************************/
  2. /* translation.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "translation.h"
  31. #include "core/io/resource_loader.h"
  32. #include "core/os/os.h"
  33. #include "core/project_settings.h"
  34. // ISO 639-1 language codes, with the addition of glibc locales with their
  35. // regional identifiers. This list must match the language names (in English)
  36. // of locale_names.
  37. //
  38. // References:
  39. // - https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
  40. // - https://lh.2xlibre.net/locales/
  41. static const char *locale_list[] = {
  42. "aa", // Afar
  43. "aa_DJ", // Afar (Djibouti)
  44. "aa_ER", // Afar (Eritrea)
  45. "aa_ET", // Afar (Ethiopia)
  46. "af", // Afrikaans
  47. "af_ZA", // Afrikaans (South Africa)
  48. "agr_PE", // Aguaruna (Peru)
  49. "ak_GH", // Akan (Ghana)
  50. "am_ET", // Amharic (Ethiopia)
  51. "an_ES", // Aragonese (Spain)
  52. "anp_IN", // Angika (India)
  53. "ar", // Arabic
  54. "ar_AE", // Arabic (United Arab Emirates)
  55. "ar_BH", // Arabic (Bahrain)
  56. "ar_DZ", // Arabic (Algeria)
  57. "ar_EG", // Arabic (Egypt)
  58. "ar_IN", // Arabic (India)
  59. "ar_IQ", // Arabic (Iraq)
  60. "ar_JO", // Arabic (Jordan)
  61. "ar_KW", // Arabic (Kuwait)
  62. "ar_LB", // Arabic (Lebanon)
  63. "ar_LY", // Arabic (Libya)
  64. "ar_MA", // Arabic (Morocco)
  65. "ar_OM", // Arabic (Oman)
  66. "ar_QA", // Arabic (Qatar)
  67. "ar_SA", // Arabic (Saudi Arabia)
  68. "ar_SD", // Arabic (Sudan)
  69. "ar_SS", // Arabic (South Soudan)
  70. "ar_SY", // Arabic (Syria)
  71. "ar_TN", // Arabic (Tunisia)
  72. "ar_YE", // Arabic (Yemen)
  73. "as_IN", // Assamese (India)
  74. "ast_ES", // Asturian (Spain)
  75. "ayc_PE", // Southern Aymara (Peru)
  76. "ay_PE", // Aymara (Peru)
  77. "az_AZ", // Azerbaijani (Azerbaijan)
  78. "be", // Belarusian
  79. "be_BY", // Belarusian (Belarus)
  80. "bem_ZM", // Bemba (Zambia)
  81. "ber_DZ", // Berber languages (Algeria)
  82. "ber_MA", // Berber languages (Morocco)
  83. "bg", // Bulgarian
  84. "bg_BG", // Bulgarian (Bulgaria)
  85. "bhb_IN", // Bhili (India)
  86. "bho_IN", // Bhojpuri (India)
  87. "bi_TV", // Bislama (Tuvalu)
  88. "bn", // Bengali
  89. "bn_BD", // Bengali (Bangladesh)
  90. "bn_IN", // Bengali (India)
  91. "bo", // Tibetan
  92. "bo_CN", // Tibetan (China)
  93. "bo_IN", // Tibetan (India)
  94. "br_FR", // Breton (France)
  95. "brx_IN", // Bodo (India)
  96. "bs_BA", // Bosnian (Bosnia and Herzegovina)
  97. "byn_ER", // Bilin (Eritrea)
  98. "ca", // Catalan
  99. "ca_AD", // Catalan (Andorra)
  100. "ca_ES", // Catalan (Spain)
  101. "ca_FR", // Catalan (France)
  102. "ca_IT", // Catalan (Italy)
  103. "ce_RU", // Chechen (Russia)
  104. "chr_US", // Cherokee (United States)
  105. "cmn_TW", // Mandarin Chinese (Taiwan)
  106. "crh_UA", // Crimean Tatar (Ukraine)
  107. "csb_PL", // Kashubian (Poland)
  108. "cs", // Czech
  109. "cs_CZ", // Czech (Czech Republic)
  110. "cv_RU", // Chuvash (Russia)
  111. "cy_GB", // Welsh (United Kingdom)
  112. "da", // Danish
  113. "da_DK", // Danish (Denmark)
  114. "de", // German
  115. "de_AT", // German (Austria)
  116. "de_BE", // German (Belgium)
  117. "de_CH", // German (Switzerland)
  118. "de_DE", // German (Germany)
  119. "de_IT", // German (Italy)
  120. "de_LU", // German (Luxembourg)
  121. "doi_IN", // Dogri (India)
  122. "dv_MV", // Dhivehi (Maldives)
  123. "dz_BT", // Dzongkha (Bhutan)
  124. "el", // Greek
  125. "el_CY", // Greek (Cyprus)
  126. "el_GR", // Greek (Greece)
  127. "en", // English
  128. "en_AG", // English (Antigua and Barbuda)
  129. "en_AU", // English (Australia)
  130. "en_BW", // English (Botswana)
  131. "en_CA", // English (Canada)
  132. "en_DK", // English (Denmark)
  133. "en_GB", // English (United Kingdom)
  134. "en_HK", // English (Hong Kong)
  135. "en_IE", // English (Ireland)
  136. "en_IL", // English (Israel)
  137. "en_IN", // English (India)
  138. "en_NG", // English (Nigeria)
  139. "en_NZ", // English (New Zealand)
  140. "en_PH", // English (Philippines)
  141. "en_SG", // English (Singapore)
  142. "en_US", // English (United States)
  143. "en_ZA", // English (South Africa)
  144. "en_ZM", // English (Zambia)
  145. "en_ZW", // English (Zimbabwe)
  146. "eo", // Esperanto
  147. "es", // Spanish
  148. "es_AR", // Spanish (Argentina)
  149. "es_BO", // Spanish (Bolivia)
  150. "es_CL", // Spanish (Chile)
  151. "es_CO", // Spanish (Colombia)
  152. "es_CR", // Spanish (Costa Rica)
  153. "es_CU", // Spanish (Cuba)
  154. "es_DO", // Spanish (Dominican Republic)
  155. "es_EC", // Spanish (Ecuador)
  156. "es_ES", // Spanish (Spain)
  157. "es_GT", // Spanish (Guatemala)
  158. "es_HN", // Spanish (Honduras)
  159. "es_MX", // Spanish (Mexico)
  160. "es_NI", // Spanish (Nicaragua)
  161. "es_PA", // Spanish (Panama)
  162. "es_PE", // Spanish (Peru)
  163. "es_PR", // Spanish (Puerto Rico)
  164. "es_PY", // Spanish (Paraguay)
  165. "es_SV", // Spanish (El Salvador)
  166. "es_US", // Spanish (United States)
  167. "es_UY", // Spanish (Uruguay)
  168. "es_VE", // Spanish (Venezuela)
  169. "et", // Estonian
  170. "et_EE", // Estonian (Estonia)
  171. "eu", // Basque
  172. "eu_ES", // Basque (Spain)
  173. "fa", // Persian
  174. "fa_IR", // Persian (Iran)
  175. "ff_SN", // Fulah (Senegal)
  176. "fi", // Finnish
  177. "fi_FI", // Finnish (Finland)
  178. "fil_PH", // Filipino (Philippines)
  179. "fo_FO", // Faroese (Faroe Islands)
  180. "fr", // French
  181. "fr_BE", // French (Belgium)
  182. "fr_CA", // French (Canada)
  183. "fr_CH", // French (Switzerland)
  184. "fr_FR", // French (France)
  185. "fr_LU", // French (Luxembourg)
  186. "fur_IT", // Friulian (Italy)
  187. "fy_DE", // Western Frisian (Germany)
  188. "fy_NL", // Western Frisian (Netherlands)
  189. "ga", // Irish
  190. "ga_IE", // Irish (Ireland)
  191. "gd_GB", // Scottish Gaelic (United Kingdom)
  192. "gez_ER", // Geez (Eritrea)
  193. "gez_ET", // Geez (Ethiopia)
  194. "gl_ES", // Galician (Spain)
  195. "gu_IN", // Gujarati (India)
  196. "gv_GB", // Manx (United Kingdom)
  197. "hak_TW", // Hakka Chinese (Taiwan)
  198. "ha_NG", // Hausa (Nigeria)
  199. "he", // Hebrew
  200. "he_IL", // Hebrew (Israel)
  201. "hi", // Hindi
  202. "hi_IN", // Hindi (India)
  203. "hne_IN", // Chhattisgarhi (India)
  204. "hr", // Croatian
  205. "hr_HR", // Croatian (Croatia)
  206. "hsb_DE", // Upper Sorbian (Germany)
  207. "ht_HT", // Haitian (Haiti)
  208. "hu", // Hungarian
  209. "hu_HU", // Hungarian (Hungary)
  210. "hus_MX", // Huastec (Mexico)
  211. "hy_AM", // Armenian (Armenia)
  212. "ia_FR", // Interlingua (France)
  213. "id", // Indonesian
  214. "id_ID", // Indonesian (Indonesia)
  215. "ig_NG", // Igbo (Nigeria)
  216. "ik_CA", // Inupiaq (Canada)
  217. "is", // Icelandic
  218. "is_IS", // Icelandic (Iceland)
  219. "it", // Italian
  220. "it_CH", // Italian (Switzerland)
  221. "it_IT", // Italian (Italy)
  222. "iu_CA", // Inuktitut (Canada)
  223. "ja", // Japanese
  224. "ja_JP", // Japanese (Japan)
  225. "kab_DZ", // Kabyle (Algeria)
  226. "ka_GE", // Georgian (Georgia)
  227. "kk_KZ", // Kazakh (Kazakhstan)
  228. "kl_GL", // Kalaallisut (Greenland)
  229. "km_KH", // Central Khmer (Cambodia)
  230. "kn_IN", // Kannada (India)
  231. "kok_IN", // Konkani (India)
  232. "ko", // Korean
  233. "ko_KR", // Korean (South Korea)
  234. "ks_IN", // Kashmiri (India)
  235. "ku", // Kurdish
  236. "ku_TR", // Kurdish (Turkey)
  237. "kw_GB", // Cornish (United Kingdom)
  238. "ky_KG", // Kirghiz (Kyrgyzstan)
  239. "lb_LU", // Luxembourgish (Luxembourg)
  240. "lg_UG", // Ganda (Uganda)
  241. "li_BE", // Limburgan (Belgium)
  242. "li_NL", // Limburgan (Netherlands)
  243. "lij_IT", // Ligurian (Italy)
  244. "ln_CD", // Lingala (Congo)
  245. "lo_LA", // Lao (Laos)
  246. "lt", // Lithuanian
  247. "lt_LT", // Lithuanian (Lithuania)
  248. "lv", // Latvian
  249. "lv_LV", // Latvian (Latvia)
  250. "lzh_TW", // Literary Chinese (Taiwan)
  251. "mag_IN", // Magahi (India)
  252. "mai_IN", // Maithili (India)
  253. "mg_MG", // Malagasy (Madagascar)
  254. "mh_MH", // Marshallese (Marshall Islands)
  255. "mhr_RU", // Eastern Mari (Russia)
  256. "mi_NZ", // Maori (New Zealand)
  257. "miq_NI", // Mískito (Nicaragua)
  258. "mk", // Macedonian
  259. "mk_MK", // Macedonian (Macedonia)
  260. "ml_IN", // Malayalam (India)
  261. "mni_IN", // Manipuri (India)
  262. "mn_MN", // Mongolian (Mongolia)
  263. "mr_IN", // Marathi (India)
  264. "ms", // Malay
  265. "ms_MY", // Malay (Malaysia)
  266. "mt", // Maltese
  267. "mt_MT", // Maltese (Malta)
  268. "my_MM", // Burmese (Myanmar)
  269. "myv_RU", // Erzya (Russia)
  270. "nah_MX", // Nahuatl languages (Mexico)
  271. "nan_TW", // Min Nan Chinese (Taiwan)
  272. "nb", // Norwegian Bokmål
  273. "nb_NO", // Norwegian Bokmål (Norway)
  274. "nds_DE", // Low German (Germany)
  275. "nds_NL", // Low German (Netherlands)
  276. "ne_NP", // Nepali (Nepal)
  277. "nhn_MX", // Central Nahuatl (Mexico)
  278. "niu_NU", // Niuean (Niue)
  279. "niu_NZ", // Niuean (New Zealand)
  280. "nl", // Dutch
  281. "nl_AW", // Dutch (Aruba)
  282. "nl_BE", // Dutch (Belgium)
  283. "nl_NL", // Dutch (Netherlands)
  284. "nn", // Norwegian Nynorsk
  285. "nn_NO", // Norwegian Nynorsk (Norway)
  286. "nr_ZA", // South Ndebele (South Africa)
  287. "nso_ZA", // Pedi (South Africa)
  288. "oc_FR", // Occitan (France)
  289. "om", // Oromo
  290. "om_ET", // Oromo (Ethiopia)
  291. "om_KE", // Oromo (Kenya)
  292. "or_IN", // Oriya (India)
  293. "os_RU", // Ossetian (Russia)
  294. "pa_IN", // Panjabi (India)
  295. "pap", // Papiamento
  296. "pap_AN", // Papiamento (Netherlands Antilles)
  297. "pap_AW", // Papiamento (Aruba)
  298. "pap_CW", // Papiamento (Curaçao)
  299. "pa_PK", // Panjabi (Pakistan)
  300. "pl", // Polish
  301. "pl_PL", // Polish (Poland)
  302. "pr", // Pirate
  303. "ps_AF", // Pushto (Afghanistan)
  304. "pt", // Portuguese
  305. "pt_BR", // Portuguese (Brazil)
  306. "pt_PT", // Portuguese (Portugal)
  307. "quy_PE", // Ayacucho Quechua (Peru)
  308. "quz_PE", // Cusco Quechua (Peru)
  309. "raj_IN", // Rajasthani (India)
  310. "ro", // Romanian
  311. "ro_RO", // Romanian (Romania)
  312. "ru", // Russian
  313. "ru_RU", // Russian (Russia)
  314. "ru_UA", // Russian (Ukraine)
  315. "rw_RW", // Kinyarwanda (Rwanda)
  316. "sa_IN", // Sanskrit (India)
  317. "sat_IN", // Santali (India)
  318. "sc_IT", // Sardinian (Italy)
  319. "sco", // Scots
  320. "sd_IN", // Sindhi (India)
  321. "se_NO", // Northern Sami (Norway)
  322. "sgs_LT", // Samogitian (Lithuania)
  323. "shs_CA", // Shuswap (Canada)
  324. "sid_ET", // Sidamo (Ethiopia)
  325. "si_LK", // Sinhala (Sri Lanka)
  326. "sk", // Slovak
  327. "sk_SK", // Slovak (Slovakia)
  328. "sl", // Slovenian
  329. "sl_SI", // Slovenian (Slovenia)
  330. "so", // Somali
  331. "so_DJ", // Somali (Djibouti)
  332. "so_ET", // Somali (Ethiopia)
  333. "so_KE", // Somali (Kenya)
  334. "so_SO", // Somali (Somalia)
  335. "son_ML", // Songhai languages (Mali)
  336. "sq", // Albanian
  337. "sq_AL", // Albanian (Albania)
  338. "sq_KV", // Albanian (Kosovo)
  339. "sq_MK", // Albanian (Macedonia)
  340. "sr", // Serbian
  341. "sr_Cyrl", // Serbian (Cyrillic)
  342. "sr_ME", // Serbian (Montenegro)
  343. "sr_RS", // Serbian (Serbia)
  344. "ss_ZA", // Swati (South Africa)
  345. "st_ZA", // Southern Sotho (South Africa)
  346. "sv", // Swedish
  347. "sv_FI", // Swedish (Finland)
  348. "sv_SE", // Swedish (Sweden)
  349. "sw_KE", // Swahili (Kenya)
  350. "sw_TZ", // Swahili (Tanzania)
  351. "szl_PL", // Silesian (Poland)
  352. "ta", // Tamil
  353. "ta_IN", // Tamil (India)
  354. "ta_LK", // Tamil (Sri Lanka)
  355. "tcy_IN", // Tulu (India)
  356. "te_IN", // Telugu (India)
  357. "tg_TJ", // Tajik (Tajikistan)
  358. "the_NP", // Chitwania Tharu (Nepal)
  359. "th", // Thai
  360. "th_TH", // Thai (Thailand)
  361. "ti", // Tigrinya
  362. "ti_ER", // Tigrinya (Eritrea)
  363. "ti_ET", // Tigrinya (Ethiopia)
  364. "tig_ER", // Tigre (Eritrea)
  365. "tk_TM", // Turkmen (Turkmenistan)
  366. "tl_PH", // Tagalog (Philippines)
  367. "tn_ZA", // Tswana (South Africa)
  368. "tr", // Turkish
  369. "tr_CY", // Turkish (Cyprus)
  370. "tr_TR", // Turkish (Turkey)
  371. "ts_ZA", // Tsonga (South Africa)
  372. "tt_RU", // Tatar (Russia)
  373. "ug_CN", // Uighur (China)
  374. "uk", // Ukrainian
  375. "uk_UA", // Ukrainian (Ukraine)
  376. "unm_US", // Unami (United States)
  377. "ur", // Urdu
  378. "ur_IN", // Urdu (India)
  379. "ur_PK", // Urdu (Pakistan)
  380. "uz", // Uzbek
  381. "uz_UZ", // Uzbek (Uzbekistan)
  382. "ve_ZA", // Venda (South Africa)
  383. "vi", // Vietnamese
  384. "vi_VN", // Vietnamese (Vietnam)
  385. "wa_BE", // Walloon (Belgium)
  386. "wae_CH", // Walser (Switzerland)
  387. "wal_ET", // Wolaytta (Ethiopia)
  388. "wo_SN", // Wolof (Senegal)
  389. "xh_ZA", // Xhosa (South Africa)
  390. "yi_US", // Yiddish (United States)
  391. "yo_NG", // Yoruba (Nigeria)
  392. "yue_HK", // Yue Chinese (Hong Kong)
  393. "zh", // Chinese
  394. "zh_CN", // Chinese (China)
  395. "zh_HK", // Chinese (Hong Kong)
  396. "zh_SG", // Chinese (Singapore)
  397. "zh_TW", // Chinese (Taiwan)
  398. "zu_ZA", // Zulu (South Africa)
  399. 0
  400. };
  401. static const char *locale_names[] = {
  402. "Afar",
  403. "Afar (Djibouti)",
  404. "Afar (Eritrea)",
  405. "Afar (Ethiopia)",
  406. "Afrikaans",
  407. "Afrikaans (South Africa)",
  408. "Aguaruna (Peru)",
  409. "Akan (Ghana)",
  410. "Amharic (Ethiopia)",
  411. "Aragonese (Spain)",
  412. "Angika (India)",
  413. "Arabic",
  414. "Arabic (United Arab Emirates)",
  415. "Arabic (Bahrain)",
  416. "Arabic (Algeria)",
  417. "Arabic (Egypt)",
  418. "Arabic (India)",
  419. "Arabic (Iraq)",
  420. "Arabic (Jordan)",
  421. "Arabic (Kuwait)",
  422. "Arabic (Lebanon)",
  423. "Arabic (Libya)",
  424. "Arabic (Morocco)",
  425. "Arabic (Oman)",
  426. "Arabic (Qatar)",
  427. "Arabic (Saudi Arabia)",
  428. "Arabic (Sudan)",
  429. "Arabic (South Soudan)",
  430. "Arabic (Syria)",
  431. "Arabic (Tunisia)",
  432. "Arabic (Yemen)",
  433. "Assamese (India)",
  434. "Asturian (Spain)",
  435. "Southern Aymara (Peru)",
  436. "Aymara (Peru)",
  437. "Azerbaijani (Azerbaijan)",
  438. "Belarusian",
  439. "Belarusian (Belarus)",
  440. "Bemba (Zambia)",
  441. "Berber languages (Algeria)",
  442. "Berber languages (Morocco)",
  443. "Bulgarian",
  444. "Bulgarian (Bulgaria)",
  445. "Bhili (India)",
  446. "Bhojpuri (India)",
  447. "Bislama (Tuvalu)",
  448. "Bengali",
  449. "Bengali (Bangladesh)",
  450. "Bengali (India)",
  451. "Tibetan",
  452. "Tibetan (China)",
  453. "Tibetan (India)",
  454. "Breton (France)",
  455. "Bodo (India)",
  456. "Bosnian (Bosnia and Herzegovina)",
  457. "Bilin (Eritrea)",
  458. "Catalan",
  459. "Catalan (Andorra)",
  460. "Catalan (Spain)",
  461. "Catalan (France)",
  462. "Catalan (Italy)",
  463. "Chechen (Russia)",
  464. "Cherokee (United States)",
  465. "Mandarin Chinese (Taiwan)",
  466. "Crimean Tatar (Ukraine)",
  467. "Kashubian (Poland)",
  468. "Czech",
  469. "Czech (Czech Republic)",
  470. "Chuvash (Russia)",
  471. "Welsh (United Kingdom)",
  472. "Danish",
  473. "Danish (Denmark)",
  474. "German",
  475. "German (Austria)",
  476. "German (Belgium)",
  477. "German (Switzerland)",
  478. "German (Germany)",
  479. "German (Italy)",
  480. "German (Luxembourg)",
  481. "Dogri (India)",
  482. "Dhivehi (Maldives)",
  483. "Dzongkha (Bhutan)",
  484. "Greek",
  485. "Greek (Cyprus)",
  486. "Greek (Greece)",
  487. "English",
  488. "English (Antigua and Barbuda)",
  489. "English (Australia)",
  490. "English (Botswana)",
  491. "English (Canada)",
  492. "English (Denmark)",
  493. "English (United Kingdom)",
  494. "English (Hong Kong)",
  495. "English (Ireland)",
  496. "English (Israel)",
  497. "English (India)",
  498. "English (Nigeria)",
  499. "English (New Zealand)",
  500. "English (Philippines)",
  501. "English (Singapore)",
  502. "English (United States)",
  503. "English (South Africa)",
  504. "English (Zambia)",
  505. "English (Zimbabwe)",
  506. "Esperanto",
  507. "Spanish",
  508. "Spanish (Argentina)",
  509. "Spanish (Bolivia)",
  510. "Spanish (Chile)",
  511. "Spanish (Colombia)",
  512. "Spanish (Costa Rica)",
  513. "Spanish (Cuba)",
  514. "Spanish (Dominican Republic)",
  515. "Spanish (Ecuador)",
  516. "Spanish (Spain)",
  517. "Spanish (Guatemala)",
  518. "Spanish (Honduras)",
  519. "Spanish (Mexico)",
  520. "Spanish (Nicaragua)",
  521. "Spanish (Panama)",
  522. "Spanish (Peru)",
  523. "Spanish (Puerto Rico)",
  524. "Spanish (Paraguay)",
  525. "Spanish (El Salvador)",
  526. "Spanish (United States)",
  527. "Spanish (Uruguay)",
  528. "Spanish (Venezuela)",
  529. "Estonian",
  530. "Estonian (Estonia)",
  531. "Basque",
  532. "Basque (Spain)",
  533. "Persian",
  534. "Persian (Iran)",
  535. "Fulah (Senegal)",
  536. "Finnish",
  537. "Finnish (Finland)",
  538. "Filipino (Philippines)",
  539. "Faroese (Faroe Islands)",
  540. "French",
  541. "French (Belgium)",
  542. "French (Canada)",
  543. "French (Switzerland)",
  544. "French (France)",
  545. "French (Luxembourg)",
  546. "Friulian (Italy)",
  547. "Western Frisian (Germany)",
  548. "Western Frisian (Netherlands)",
  549. "Irish",
  550. "Irish (Ireland)",
  551. "Scottish Gaelic (United Kingdom)",
  552. "Geez (Eritrea)",
  553. "Geez (Ethiopia)",
  554. "Galician (Spain)",
  555. "Gujarati (India)",
  556. "Manx (United Kingdom)",
  557. "Hakka Chinese (Taiwan)",
  558. "Hausa (Nigeria)",
  559. "Hebrew",
  560. "Hebrew (Israel)",
  561. "Hindi",
  562. "Hindi (India)",
  563. "Chhattisgarhi (India)",
  564. "Croatian",
  565. "Croatian (Croatia)",
  566. "Upper Sorbian (Germany)",
  567. "Haitian (Haiti)",
  568. "Hungarian",
  569. "Hungarian (Hungary)",
  570. "Huastec (Mexico)",
  571. "Armenian (Armenia)",
  572. "Interlingua (France)",
  573. "Indonesian",
  574. "Indonesian (Indonesia)",
  575. "Igbo (Nigeria)",
  576. "Inupiaq (Canada)",
  577. "Icelandic",
  578. "Icelandic (Iceland)",
  579. "Italian",
  580. "Italian (Switzerland)",
  581. "Italian (Italy)",
  582. "Inuktitut (Canada)",
  583. "Japanese",
  584. "Japanese (Japan)",
  585. "Kabyle (Algeria)",
  586. "Georgian (Georgia)",
  587. "Kazakh (Kazakhstan)",
  588. "Kalaallisut (Greenland)",
  589. "Central Khmer (Cambodia)",
  590. "Kannada (India)",
  591. "Konkani (India)",
  592. "Korean",
  593. "Korean (South Korea)",
  594. "Kashmiri (India)",
  595. "Kurdish",
  596. "Kurdish (Turkey)",
  597. "Cornish (United Kingdom)",
  598. "Kirghiz (Kyrgyzstan)",
  599. "Luxembourgish (Luxembourg)",
  600. "Ganda (Uganda)",
  601. "Limburgan (Belgium)",
  602. "Limburgan (Netherlands)",
  603. "Ligurian (Italy)",
  604. "Lingala (Congo)",
  605. "Lao (Laos)",
  606. "Lithuanian",
  607. "Lithuanian (Lithuania)",
  608. "Latvian",
  609. "Latvian (Latvia)",
  610. "Literary Chinese (Taiwan)",
  611. "Magahi (India)",
  612. "Maithili (India)",
  613. "Malagasy (Madagascar)",
  614. "Marshallese (Marshall Islands)",
  615. "Eastern Mari (Russia)",
  616. "Maori (New Zealand)",
  617. "Mískito (Nicaragua)",
  618. "Macedonian",
  619. "Macedonian (Macedonia)",
  620. "Malayalam (India)",
  621. "Manipuri (India)",
  622. "Mongolian (Mongolia)",
  623. "Marathi (India)",
  624. "Malay",
  625. "Malay (Malaysia)",
  626. "Maltese",
  627. "Maltese (Malta)",
  628. "Burmese (Myanmar)",
  629. "Erzya (Russia)",
  630. "Nahuatl languages (Mexico)",
  631. "Min Nan Chinese (Taiwan)",
  632. "Norwegian Bokmål",
  633. "Norwegian Bokmål (Norway)",
  634. "Low German (Germany)",
  635. "Low German (Netherlands)",
  636. "Nepali (Nepal)",
  637. "Central Nahuatl (Mexico)",
  638. "Niuean (Niue)",
  639. "Niuean (New Zealand)",
  640. "Dutch",
  641. "Dutch (Aruba)",
  642. "Dutch (Belgium)",
  643. "Dutch (Netherlands)",
  644. "Norwegian Nynorsk",
  645. "Norwegian Nynorsk (Norway)",
  646. "South Ndebele (South Africa)",
  647. "Pedi (South Africa)",
  648. "Occitan (France)",
  649. "Oromo",
  650. "Oromo (Ethiopia)",
  651. "Oromo (Kenya)",
  652. "Oriya (India)",
  653. "Ossetian (Russia)",
  654. "Panjabi (India)",
  655. "Papiamento",
  656. "Papiamento (Netherlands Antilles)",
  657. "Papiamento (Aruba)",
  658. "Papiamento (Curaçao)",
  659. "Panjabi (Pakistan)",
  660. "Polish",
  661. "Polish (Poland)",
  662. "Pirate",
  663. "Pushto (Afghanistan)",
  664. "Portuguese",
  665. "Portuguese (Brazil)",
  666. "Portuguese (Portugal)",
  667. "Ayacucho Quechua (Peru)",
  668. "Cusco Quechua (Peru)",
  669. "Rajasthani (India)",
  670. "Romanian",
  671. "Romanian (Romania)",
  672. "Russian",
  673. "Russian (Russia)",
  674. "Russian (Ukraine)",
  675. "Kinyarwanda (Rwanda)",
  676. "Sanskrit (India)",
  677. "Santali (India)",
  678. "Sardinian (Italy)",
  679. "Scots (Scotland)",
  680. "Sindhi (India)",
  681. "Northern Sami (Norway)",
  682. "Samogitian (Lithuania)",
  683. "Shuswap (Canada)",
  684. "Sidamo (Ethiopia)",
  685. "Sinhala (Sri Lanka)",
  686. "Slovak",
  687. "Slovak (Slovakia)",
  688. "Slovenian",
  689. "Slovenian (Slovenia)",
  690. "Somali",
  691. "Somali (Djibouti)",
  692. "Somali (Ethiopia)",
  693. "Somali (Kenya)",
  694. "Somali (Somalia)",
  695. "Songhai languages (Mali)",
  696. "Albanian",
  697. "Albanian (Albania)",
  698. "Albanian (Kosovo)",
  699. "Albanian (Macedonia)",
  700. "Serbian",
  701. "Serbian (Cyrillic)",
  702. "Serbian (Montenegro)",
  703. "Serbian (Serbia)",
  704. "Swati (South Africa)",
  705. "Southern Sotho (South Africa)",
  706. "Swedish",
  707. "Swedish (Finland)",
  708. "Swedish (Sweden)",
  709. "Swahili (Kenya)",
  710. "Swahili (Tanzania)",
  711. "Silesian (Poland)",
  712. "Tamil",
  713. "Tamil (India)",
  714. "Tamil (Sri Lanka)",
  715. "Tulu (India)",
  716. "Telugu (India)",
  717. "Tajik (Tajikistan)",
  718. "Chitwania Tharu (Nepal)",
  719. "Thai",
  720. "Thai (Thailand)",
  721. "Tigrinya",
  722. "Tigrinya (Eritrea)",
  723. "Tigrinya (Ethiopia)",
  724. "Tigre (Eritrea)",
  725. "Turkmen (Turkmenistan)",
  726. "Tagalog (Philippines)",
  727. "Tswana (South Africa)",
  728. "Turkish",
  729. "Turkish (Cyprus)",
  730. "Turkish (Turkey)",
  731. "Tsonga (South Africa)",
  732. "Tatar (Russia)",
  733. "Uighur (China)",
  734. "Ukrainian",
  735. "Ukrainian (Ukraine)",
  736. "Unami (United States)",
  737. "Urdu",
  738. "Urdu (India)",
  739. "Urdu (Pakistan)",
  740. "Uzbek",
  741. "Uzbek (Uzbekistan)",
  742. "Venda (South Africa)",
  743. "Vietnamese",
  744. "Vietnamese (Vietnam)",
  745. "Walloon (Belgium)",
  746. "Walser (Switzerland)",
  747. "Wolaytta (Ethiopia)",
  748. "Wolof (Senegal)",
  749. "Xhosa (South Africa)",
  750. "Yiddish (United States)",
  751. "Yoruba (Nigeria)",
  752. "Yue Chinese (Hong Kong)",
  753. "Chinese",
  754. "Chinese (China)",
  755. "Chinese (Hong Kong)",
  756. "Chinese (Singapore)",
  757. "Chinese (Taiwan)",
  758. "Zulu (South Africa)",
  759. 0
  760. };
  761. // Windows has some weird locale identifiers which do not honor the ISO 639-1
  762. // standardized nomenclature. Whenever those don't conflict with existing ISO
  763. // identifiers, we override them.
  764. //
  765. // Reference:
  766. // - https://msdn.microsoft.com/en-us/library/windows/desktop/ms693062(v=vs.85).aspx
  767. static const char *locale_renames[][2] = {
  768. { "in", "id" }, // Indonesian
  769. { "iw", "he" }, // Hebrew
  770. { "no", "nb" }, // Norwegian Bokmål
  771. { NULL, NULL }
  772. };
  773. static String get_trimmed_locale(const String &p_locale) {
  774. return p_locale.substr(0, 2);
  775. }
  776. ///////////////////////////////////////////////
  777. PoolVector<String> Translation::_get_messages() const {
  778. PoolVector<String> msgs;
  779. msgs.resize(translation_map.size() * 2);
  780. int idx = 0;
  781. for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) {
  782. msgs.set(idx + 0, E->key());
  783. msgs.set(idx + 1, E->get());
  784. idx += 2;
  785. }
  786. return msgs;
  787. }
  788. PoolVector<String> Translation::_get_message_list() const {
  789. PoolVector<String> msgs;
  790. msgs.resize(translation_map.size());
  791. int idx = 0;
  792. for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) {
  793. msgs.set(idx, E->key());
  794. idx += 1;
  795. }
  796. return msgs;
  797. }
  798. void Translation::_set_messages(const PoolVector<String> &p_messages) {
  799. int msg_count = p_messages.size();
  800. ERR_FAIL_COND(msg_count % 2);
  801. PoolVector<String>::Read r = p_messages.read();
  802. for (int i = 0; i < msg_count; i += 2) {
  803. add_message(r[i + 0], r[i + 1]);
  804. }
  805. }
  806. void Translation::set_locale(const String &p_locale) {
  807. String univ_locale = TranslationServer::standardize_locale(p_locale);
  808. if (!TranslationServer::is_locale_valid(univ_locale)) {
  809. String trimmed_locale = get_trimmed_locale(univ_locale);
  810. ERR_EXPLAIN("Invalid locale: " + trimmed_locale);
  811. ERR_FAIL_COND(!TranslationServer::is_locale_valid(trimmed_locale));
  812. locale = trimmed_locale;
  813. } else {
  814. locale = univ_locale;
  815. }
  816. if (OS::get_singleton()->get_main_loop()) {
  817. OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED);
  818. }
  819. }
  820. void Translation::add_message(const StringName &p_src_text, const StringName &p_xlated_text) {
  821. translation_map[p_src_text] = p_xlated_text;
  822. }
  823. StringName Translation::get_message(const StringName &p_src_text) const {
  824. const Map<StringName, StringName>::Element *E = translation_map.find(p_src_text);
  825. if (!E)
  826. return StringName();
  827. return E->get();
  828. }
  829. void Translation::erase_message(const StringName &p_src_text) {
  830. translation_map.erase(p_src_text);
  831. }
  832. void Translation::get_message_list(List<StringName> *r_messages) const {
  833. for (const Map<StringName, StringName>::Element *E = translation_map.front(); E; E = E->next()) {
  834. r_messages->push_back(E->key());
  835. }
  836. }
  837. int Translation::get_message_count() const {
  838. return translation_map.size();
  839. };
  840. void Translation::_bind_methods() {
  841. ClassDB::bind_method(D_METHOD("set_locale", "locale"), &Translation::set_locale);
  842. ClassDB::bind_method(D_METHOD("get_locale"), &Translation::get_locale);
  843. ClassDB::bind_method(D_METHOD("add_message", "src_message", "xlated_message"), &Translation::add_message);
  844. ClassDB::bind_method(D_METHOD("get_message", "src_message"), &Translation::get_message);
  845. ClassDB::bind_method(D_METHOD("erase_message", "src_message"), &Translation::erase_message);
  846. ClassDB::bind_method(D_METHOD("get_message_list"), &Translation::_get_message_list);
  847. ClassDB::bind_method(D_METHOD("get_message_count"), &Translation::get_message_count);
  848. ClassDB::bind_method(D_METHOD("_set_messages"), &Translation::_set_messages);
  849. ClassDB::bind_method(D_METHOD("_get_messages"), &Translation::_get_messages);
  850. ADD_PROPERTY(PropertyInfo(Variant::POOL_STRING_ARRAY, "messages", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_messages", "_get_messages");
  851. ADD_PROPERTY(PropertyInfo(Variant::STRING, "locale"), "set_locale", "get_locale");
  852. }
  853. Translation::Translation() :
  854. locale("en") {
  855. }
  856. ///////////////////////////////////////////////
  857. bool TranslationServer::is_locale_valid(const String &p_locale) {
  858. const char **ptr = locale_list;
  859. while (*ptr) {
  860. if (*ptr == p_locale)
  861. return true;
  862. ptr++;
  863. }
  864. return false;
  865. }
  866. String TranslationServer::standardize_locale(const String &p_locale) {
  867. // Replaces '-' with '_' for macOS Sierra-style locales
  868. String univ_locale = p_locale.replace("-", "_");
  869. // Handles known non-ISO locale names used e.g. on Windows
  870. int idx = 0;
  871. while (locale_renames[idx][0] != NULL) {
  872. if (locale_renames[idx][0] == univ_locale) {
  873. univ_locale = locale_renames[idx][1];
  874. break;
  875. }
  876. idx++;
  877. }
  878. return univ_locale;
  879. }
  880. void TranslationServer::set_locale(const String &p_locale) {
  881. String univ_locale = standardize_locale(p_locale);
  882. if (!is_locale_valid(univ_locale)) {
  883. String trimmed_locale = get_trimmed_locale(univ_locale);
  884. print_verbose(vformat("Unsupported locale '%s', falling back to '%s'.", p_locale, trimmed_locale));
  885. if (!is_locale_valid(trimmed_locale)) {
  886. ERR_PRINTS(vformat("Unsupported locale '%s', falling back to 'en'.", trimmed_locale));
  887. locale = "en";
  888. } else {
  889. locale = trimmed_locale;
  890. }
  891. } else {
  892. locale = univ_locale;
  893. }
  894. if (OS::get_singleton()->get_main_loop()) {
  895. OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_TRANSLATION_CHANGED);
  896. }
  897. ResourceLoader::reload_translation_remaps();
  898. }
  899. String TranslationServer::get_locale() const {
  900. return locale;
  901. }
  902. String TranslationServer::get_locale_name(const String &p_locale) const {
  903. if (!locale_name_map.has(p_locale)) return String();
  904. return locale_name_map[p_locale];
  905. }
  906. Vector<String> TranslationServer::get_all_locales() {
  907. Vector<String> locales;
  908. const char **ptr = locale_list;
  909. while (*ptr) {
  910. locales.push_back(*ptr);
  911. ptr++;
  912. }
  913. return locales;
  914. }
  915. Vector<String> TranslationServer::get_all_locale_names() {
  916. Vector<String> locales;
  917. const char **ptr = locale_names;
  918. while (*ptr) {
  919. locales.push_back(String::utf8(*ptr));
  920. ptr++;
  921. }
  922. return locales;
  923. }
  924. void TranslationServer::add_translation(const Ref<Translation> &p_translation) {
  925. translations.insert(p_translation);
  926. }
  927. void TranslationServer::remove_translation(const Ref<Translation> &p_translation) {
  928. translations.erase(p_translation);
  929. }
  930. void TranslationServer::clear() {
  931. translations.clear();
  932. };
  933. StringName TranslationServer::translate(const StringName &p_message) const {
  934. //translate using locale
  935. if (!enabled)
  936. return p_message;
  937. StringName res;
  938. bool near_match = false;
  939. const CharType *lptr = &locale[0];
  940. for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) {
  941. const Ref<Translation> &t = E->get();
  942. String l = t->get_locale();
  943. if (lptr[0] != l[0] || lptr[1] != l[1])
  944. continue; // locale not match
  945. //near match
  946. bool match = (l != locale);
  947. if (near_match && !match)
  948. continue; //only near-match once
  949. StringName r = t->get_message(p_message);
  950. if (!r)
  951. continue;
  952. res = r;
  953. if (match)
  954. break;
  955. else
  956. near_match = true;
  957. }
  958. if (!res) {
  959. //try again with fallback
  960. if (fallback.length() >= 2) {
  961. const CharType *fptr = &fallback[0];
  962. bool near_match = false;
  963. for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) {
  964. const Ref<Translation> &t = E->get();
  965. String l = t->get_locale();
  966. if (fptr[0] != l[0] || fptr[1] != l[1])
  967. continue; // locale not match
  968. //near match
  969. bool match = (l != fallback);
  970. if (near_match && !match)
  971. continue; //only near-match once
  972. StringName r = t->get_message(p_message);
  973. if (!r)
  974. continue;
  975. res = r;
  976. if (match)
  977. break;
  978. else
  979. near_match = true;
  980. }
  981. }
  982. }
  983. if (!res)
  984. return p_message;
  985. return res;
  986. }
  987. TranslationServer *TranslationServer::singleton = NULL;
  988. bool TranslationServer::_load_translations(const String &p_from) {
  989. if (ProjectSettings::get_singleton()->has_setting(p_from)) {
  990. PoolVector<String> translations = ProjectSettings::get_singleton()->get(p_from);
  991. int tcount = translations.size();
  992. if (tcount) {
  993. PoolVector<String>::Read r = translations.read();
  994. for (int i = 0; i < tcount; i++) {
  995. Ref<Translation> tr = ResourceLoader::load(r[i]);
  996. if (tr.is_valid())
  997. add_translation(tr);
  998. }
  999. }
  1000. return true;
  1001. }
  1002. return false;
  1003. }
  1004. void TranslationServer::setup() {
  1005. String test = GLOBAL_DEF("locale/test", "");
  1006. test = test.strip_edges();
  1007. if (test != "")
  1008. set_locale(test);
  1009. else
  1010. set_locale(OS::get_singleton()->get_locale());
  1011. fallback = GLOBAL_DEF("locale/fallback", "en");
  1012. #ifdef TOOLS_ENABLED
  1013. {
  1014. String options = "";
  1015. int idx = 0;
  1016. while (locale_list[idx]) {
  1017. if (idx > 0)
  1018. options += ",";
  1019. options += locale_list[idx];
  1020. idx++;
  1021. }
  1022. ProjectSettings::get_singleton()->set_custom_property_info("locale/fallback", PropertyInfo(Variant::STRING, "locale/fallback", PROPERTY_HINT_ENUM, options));
  1023. }
  1024. #endif
  1025. //load translations
  1026. }
  1027. void TranslationServer::set_tool_translation(const Ref<Translation> &p_translation) {
  1028. tool_translation = p_translation;
  1029. }
  1030. StringName TranslationServer::tool_translate(const StringName &p_message) const {
  1031. if (tool_translation.is_valid()) {
  1032. StringName r = tool_translation->get_message(p_message);
  1033. if (r) {
  1034. return r;
  1035. }
  1036. }
  1037. return p_message;
  1038. }
  1039. void TranslationServer::_bind_methods() {
  1040. ClassDB::bind_method(D_METHOD("set_locale", "locale"), &TranslationServer::set_locale);
  1041. ClassDB::bind_method(D_METHOD("get_locale"), &TranslationServer::get_locale);
  1042. ClassDB::bind_method(D_METHOD("get_locale_name", "locale"), &TranslationServer::get_locale_name);
  1043. ClassDB::bind_method(D_METHOD("translate", "message"), &TranslationServer::translate);
  1044. ClassDB::bind_method(D_METHOD("add_translation", "translation"), &TranslationServer::add_translation);
  1045. ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationServer::remove_translation);
  1046. ClassDB::bind_method(D_METHOD("clear"), &TranslationServer::clear);
  1047. }
  1048. void TranslationServer::load_translations() {
  1049. String locale = get_locale();
  1050. _load_translations("locale/translations"); //all
  1051. _load_translations("locale/translations_" + locale.substr(0, 2));
  1052. if (locale.substr(0, 2) != locale) {
  1053. _load_translations("locale/translations_" + locale);
  1054. }
  1055. }
  1056. TranslationServer::TranslationServer() :
  1057. locale("en"),
  1058. enabled(true) {
  1059. singleton = this;
  1060. for (int i = 0; locale_list[i]; ++i) {
  1061. locale_name_map.insert(locale_list[i], String::utf8(locale_names[i]));
  1062. }
  1063. }