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