22 #include <freerdp/config.h>
24 #if defined(__APPLE__)
25 #include <CoreFoundation/CFString.h>
26 #include <CoreFoundation/CFLocale.h>
33 #include <winpr/crt.h>
34 #include <winpr/assert.h>
35 #include <winpr/environment.h>
37 #include "liblocale.h"
39 #include <freerdp/locale/locale.h>
47 {
"af",
"ZA", AFRIKAANS },
48 {
"sq",
"AL", ALBANIAN },
49 {
"gsw",
"FR", ALSATIAN },
50 {
"am",
"ET", AMHARIC },
51 {
"ar",
"DZ", ARABIC_ALGERIA },
52 {
"ar",
"BH", ARABIC_BAHRAIN },
53 {
"ar",
"EG", ARABIC_EGYPT },
54 {
"ar",
"IQ", ARABIC_IRAQ },
55 {
"ar",
"JO", ARABIC_JORDAN },
56 {
"ar",
"KW", ARABIC_KUWAIT },
57 {
"ar",
"LB", ARABIC_LEBANON },
58 {
"ar",
"LY", ARABIC_LIBYA },
59 {
"ar",
"MA", ARABIC_MOROCCO },
60 {
"ar",
"OM", ARABIC_OMAN },
61 {
"ar",
"QA", ARABIC_QATAR },
62 {
"ar",
"SA", ARABIC_SAUDI_ARABIA },
63 {
"ar",
"SY", ARABIC_SYRIA },
64 {
"ar",
"TN", ARABIC_TUNISIA },
65 {
"ar",
"AE", ARABIC_UAE },
66 {
"ar",
"YE", ARABIC_YEMEN },
67 {
"az",
"AZ", AZERI_LATIN },
68 {
"az",
"Cyrl_AZ", AZERI_CYRILLIC },
69 {
"hy",
"AM", ARMENIAN },
70 {
"as",
"IN", ASSAMESE },
71 {
"ba",
"RU", BASHKIR },
72 {
"eu",
"ES", BASQUE },
73 {
"be",
"BY", BELARUSIAN },
74 {
"bn",
"IN", BENGALI_INDIA },
75 {
"br",
"FR", BRETON },
76 {
"bs",
"BA", BOSNIAN_LATIN },
77 {
"bg",
"BG", BULGARIAN },
78 {
"ca",
"ES", CATALAN },
79 {
"zh",
"HK", CHINESE_HONG_KONG },
80 {
"zh",
"MO", CHINESE_MACAU },
81 {
"zh",
"CN", CHINESE_PRC },
82 {
"zh",
"SG", CHINESE_SINGAPORE },
83 {
"zh",
"TW", CHINESE_TAIWAN },
84 {
"hr",
"BA", CROATIAN_BOSNIA_HERZEGOVINA },
86 {
"hr",
"HR", CROATIAN },
87 {
"cs",
"CZ", CZECH },
88 {
"da",
"DK", DANISH },
89 {
"prs",
"AF", DARI },
90 {
"dv",
"MV", DIVEHI },
91 {
"nl",
"BE", DUTCH_BELGIAN },
92 {
"nl",
"NL", DUTCH_STANDARD },
93 {
"en",
"AU", ENGLISH_AUSTRALIAN },
94 {
"en",
"BZ", ENGLISH_BELIZE },
95 {
"en",
"CA", ENGLISH_CANADIAN },
96 {
"en",
"CB", ENGLISH_CARIBBEAN },
97 {
"en",
"IN", ENGLISH_INDIA },
98 {
"en",
"IE", ENGLISH_IRELAND },
99 {
"en",
"JM", ENGLISH_JAMAICA },
100 {
"en",
"MY", ENGLISH_MALAYSIA },
101 {
"en",
"NZ", ENGLISH_NEW_ZEALAND },
103 ENGLISH_PHILIPPINES },
104 {
"en",
"SG", ENGLISH_SINGAPORE },
105 {
"en",
"ZA", ENGLISH_SOUTH_AFRICA },
106 {
"en",
"TT", ENGLISH_TRINIDAD },
107 {
"en",
"GB", ENGLISH_UNITED_KINGDOM },
108 {
"en",
"US", ENGLISH_UNITED_STATES },
111 {
"et",
"EE", ESTONIAN },
112 {
"fo",
"FO", FAEROESE },
113 {
"fil",
"PH", FILIPINO },
115 {
"fi",
"FI", FINNISH },
116 {
"fr",
"BE", FRENCH_BELGIAN },
117 {
"fr",
"CA", FRENCH_CANADIAN },
118 {
"fr",
"FR", FRENCH_STANDARD },
119 {
"fr",
"LU", FRENCH_LUXEMBOURG },
120 {
"fr",
"MC", FRENCH_MONACO },
121 {
"fr",
"CH", FRENCH_SWISS },
122 {
"fy",
"NL", FRISIAN },
124 {
"gl",
"ES", GALICIAN },
125 {
"ka",
"GE", GEORGIAN },
126 {
"de",
"AT", GERMAN_AUSTRIAN },
127 {
"de",
"DE", GERMAN_STANDARD },
128 {
"de",
"LI", GERMAN_LIECHTENSTEIN },
129 {
"de",
"LU", GERMAN_LUXEMBOURG },
130 {
"de",
"CH", GERMAN_SWISS },
131 {
"el",
"GR", GREEK },
132 {
"kl",
"GL", GREENLANDIC },
133 {
"gu",
"IN", GUJARATI },
134 {
"he",
"IL", HEBREW },
135 {
"hi",
"IN", HINDI },
136 {
"hu",
"HU", HUNGARIAN },
137 {
"is",
"IS", ICELANDIC },
138 {
"ig",
"NG", IGBO },
139 {
"id",
"ID", INDONESIAN },
140 {
"ga",
"IE", IRISH },
142 {
"it",
"IT", ITALIAN_STANDARD },
143 {
"it",
"CH", ITALIAN_SWISS },
144 {
"ja",
"JP", JAPANESE },
145 {
"kn",
"IN", KANNADA },
146 {
"kk",
"KZ", KAZAKH },
147 {
"kh",
"KH", KHMER },
148 {
"qut",
"GT", KICHE },
149 {
"rw",
"RW", KINYARWANDA },
150 {
"kok",
"IN", KONKANI },
151 {
"ko",
"KR", KOREAN },
152 {
"ky",
"KG", KYRGYZ },
154 {
"lv",
"LV", LATVIAN },
155 {
"lt",
"LT", LITHUANIAN },
156 {
"dsb",
"DE", LOWER_SORBIAN },
157 {
"lb",
"LU", LUXEMBOURGISH },
159 {
"mk",
"MK", MACEDONIAN },
160 {
"ms",
"BN", MALAY_BRUNEI_DARUSSALAM },
161 {
"ms",
"MY", MALAY_MALAYSIA },
162 {
"ml",
"IN", MALAYALAM },
163 {
"mt",
"MT", MALTESE },
164 {
"mi",
"NZ", MAORI },
165 {
"arn",
"CL", MAPUDUNGUN },
167 {
"mr",
"IN", MARATHI },
168 {
"moh",
"CA", MOHAWK },
170 {
"mn",
"MN", MONGOLIAN },
171 {
"ne",
"NP", NEPALI },
173 {
"nb",
"NO", NORWEGIAN_BOKMAL },
174 {
"nn",
"NO", NORWEGIAN_NYNORSK },
175 {
"oc",
"FR", OCCITAN },
176 {
"or",
"IN", ORIYA },
177 {
"ps",
"AF", PASHTO },
179 {
"fa",
"IR", FARSI },
180 {
"pl",
"PL", POLISH },
181 {
"pt",
"BR", PORTUGUESE_BRAZILIAN },
182 {
"pt",
"PT", PORTUGUESE_STANDARD },
183 {
"pa",
"IN", PUNJABI },
184 {
"quz",
"BO", QUECHUA_BOLIVIA },
185 {
"quz",
"EC", QUECHUA_ECUADOR },
186 {
"quz",
"PE", QUECHUA_PERU },
187 {
"ro",
"RO", ROMANIAN },
188 {
"rm",
"CH", ROMANSH },
190 {
"ru",
"RU", RUSSIAN },
191 {
"smn",
"FI", SAMI_INARI },
192 {
"smj",
"NO", SAMI_LULE_NORWAY },
193 {
"smj",
"SE", SAMI_LULE_SWEDEN },
194 {
"se",
"FI", SAMI_NORTHERN_FINLAND },
195 {
"se",
"NO", SAMI_NORTHERN_NORWAY },
196 {
"se",
"SE", SAMI_NORTHERN_SWEDEN },
197 {
"sms",
"FI", SAMI_SKOLT },
198 {
"sma",
"NO", SAMI_SOUTHERN_NORWAY },
199 {
"sma",
"SE", SAMI_SOUTHERN_SWEDEN },
200 {
"sa",
"IN", SANSKRIT },
201 {
"sr",
"SP", SERBIAN_LATIN },
203 SERBIAN_LATIN_BOSNIA_HERZEGOVINA },
204 {
"sr",
"Cyrl_SP", SERBIAN_CYRILLIC },
206 SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA },
207 {
"ns",
"ZA", SESOTHO_SA_LEBOA },
209 {
"tn",
"ZA", TSWANA },
210 {
"si",
"LK", SINHALA },
211 {
"sk",
"SK", SLOVAK },
212 {
"sl",
"SI", SLOVENIAN },
213 {
"es",
"AR", SPANISH_ARGENTINA },
214 {
"es",
"BO", SPANISH_BOLIVIA },
215 {
"es",
"CL", SPANISH_CHILE },
216 {
"es",
"CO", SPANISH_COLOMBIA },
217 {
"es",
"CR", SPANISH_COSTA_RICA },
218 {
"es",
"DO", SPANISH_DOMINICAN_REPUBLIC },
219 {
"es",
"EC", SPANISH_ECUADOR },
220 {
"es",
"SV", SPANISH_EL_SALVADOR },
221 {
"es",
"GT", SPANISH_GUATEMALA },
222 {
"es",
"HN", SPANISH_HONDURAS },
223 {
"es",
"MX", SPANISH_MEXICAN },
224 {
"es",
"NI", SPANISH_NICARAGUA },
225 {
"es",
"PA", SPANISH_PANAMA },
226 {
"es",
"PY", SPANISH_PARAGUAY },
227 {
"es",
"PE", SPANISH_PERU },
228 {
"es",
"PR", SPANISH_PUERTO_RICO },
229 {
"es",
"ES", SPANISH_MODERN_SORT },
230 {
"es",
"ES", SPANISH_TRADITIONAL_SORT },
231 {
"es",
"US", SPANISH_UNITED_STATES },
232 {
"es",
"UY", SPANISH_URUGUAY },
233 {
"es",
"VE", SPANISH_VENEZUELA },
234 {
"sw",
"KE", SWAHILI },
235 {
"sv",
"FI", SWEDISH_FINLAND },
236 {
"sv",
"SE", SWEDISH },
237 {
"syr",
"SY", SYRIAC },
238 {
"ta",
"IN", TAMIL },
239 {
"tt",
"RU", TATAR },
240 {
"te",
"IN", TELUGU },
241 {
"th",
"TH", THAI },
242 {
"bo",
"BT", TIBETAN_BHUTAN },
243 {
"bo",
"CN", TIBETAN_PRC },
244 {
"tr",
"TR", TURKISH },
245 {
"tk",
"TM", TURKMEN },
246 {
"ug",
"CN", UIGHUR },
247 {
"uk",
"UA", UKRAINIAN },
248 {
"wen",
"DE", UPPER_SORBIAN },
249 {
"tr",
"IN", URDU_INDIA },
250 {
"ur",
"PK", URDU },
251 {
"uz",
"UZ", UZBEK_LATIN },
252 {
"uz",
"Cyrl_UZ", UZBEK_CYRILLIC },
253 {
"vi",
"VN", VIETNAMESE },
254 {
"cy",
"GB", WELSH },
255 {
"wo",
"SN", WOLOF },
256 {
"xh",
"ZA", XHOSA },
257 {
"sah",
"RU", YAKUT },
259 {
"yo",
"NG", YORUBA },
269 static const LOCALE_NAME LOCALE_NAME_TABLE[] = {
270 { AFRIKAANS,
"AFRIKAANS" },
271 { ALBANIAN,
"ALBANIAN" },
272 { ALSATIAN,
"ALSATIAN" },
273 { AMHARIC,
"AMHARIC" },
274 { ARABIC_SAUDI_ARABIA,
"ARABIC_SAUDI_ARABIA" },
275 { ARABIC_IRAQ,
"ARABIC_IRAQ" },
276 { ARABIC_EGYPT,
"ARABIC_EGYPT" },
277 { ARABIC_LIBYA,
"ARABIC_LIBYA" },
278 { ARABIC_ALGERIA,
"ARABIC_ALGERIA" },
279 { ARABIC_MOROCCO,
"ARABIC_MOROCCO" },
280 { ARABIC_TUNISIA,
"ARABIC_TUNISIA" },
281 { ARABIC_OMAN,
"ARABIC_OMAN" },
282 { ARABIC_YEMEN,
"ARABIC_YEMEN" },
283 { ARABIC_SYRIA,
"ARABIC_SYRIA" },
284 { ARABIC_JORDAN,
"ARABIC_JORDAN" },
285 { ARABIC_LEBANON,
"ARABIC_LEBANON" },
286 { ARABIC_KUWAIT,
"ARABIC_KUWAIT" },
287 { ARABIC_UAE,
"ARABIC_UAE" },
288 { ARABIC_BAHRAIN,
"ARABIC_BAHRAIN" },
289 { ARABIC_QATAR,
"ARABIC_QATAR" },
290 { ARMENIAN,
"ARMENIAN" },
291 { ASSAMESE,
"ASSAMESE" },
292 { AZERI_LATIN,
"AZERI_LATIN" },
293 { AZERI_CYRILLIC,
"AZERI_CYRILLIC" },
294 { BASHKIR,
"BASHKIR" },
295 { BASQUE,
"BASQUE" },
296 { BELARUSIAN,
"BELARUSIAN" },
297 { BENGALI_INDIA,
"BENGALI_INDIA" },
298 { BOSNIAN_LATIN,
"BOSNIAN_LATIN" },
299 { BRETON,
"BRETON" },
300 { BULGARIAN,
"BULGARIAN" },
301 { CATALAN,
"CATALAN" },
302 { CHINESE_TAIWAN,
"CHINESE_TAIWAN" },
303 { CHINESE_PRC,
"CHINESE_PRC" },
304 { CHINESE_HONG_KONG,
"CHINESE_HONG_KONG" },
305 { CHINESE_SINGAPORE,
"CHINESE_SINGAPORE" },
306 { CHINESE_MACAU,
"CHINESE_MACAU" },
307 { CROATIAN,
"CROATIAN" },
308 { CROATIAN_BOSNIA_HERZEGOVINA,
"CROATIAN_BOSNIA_HERZEGOVINA" },
310 { DANISH,
"DANISH" },
312 { DIVEHI,
"DIVEHI" },
313 { DUTCH_STANDARD,
"DUTCH_STANDARD" },
314 { DUTCH_BELGIAN,
"DUTCH_BELGIAN" },
315 { ENGLISH_UNITED_STATES,
"ENGLISH_UNITED_STATES" },
316 { ENGLISH_UNITED_KINGDOM,
"ENGLISH_UNITED_KINGDOM" },
317 { ENGLISH_AUSTRALIAN,
"ENGLISH_AUSTRALIAN" },
318 { ENGLISH_CANADIAN,
"ENGLISH_CANADIAN" },
319 { ENGLISH_NEW_ZEALAND,
"ENGLISH_NEW_ZEALAND" },
320 { ENGLISH_INDIA,
"ENGLISH_INDIA" },
321 { ENGLISH_IRELAND,
"ENGLISH_IRELAND" },
322 { ENGLISH_MALAYSIA,
"ENGLISH_MALAYSIA" },
323 { ENGLISH_SOUTH_AFRICA,
"ENGLISH_SOUTH_AFRICA" },
324 { ENGLISH_JAMAICA,
"ENGLISH_JAMAICA" },
325 { ENGLISH_CARIBBEAN,
"ENGLISH_CARIBBEAN" },
326 { ENGLISH_BELIZE,
"ENGLISH_BELIZE" },
327 { ENGLISH_TRINIDAD,
"ENGLISH_TRINIDAD" },
328 { ENGLISH_ZIMBABWE,
"ENGLISH_ZIMBABWE" },
329 { ENGLISH_PHILIPPINES,
"ENGLISH_PHILIPPINES" },
330 { ENGLISH_SINGAPORE,
"ENGLISH_SINGAPORE" },
331 { ESTONIAN,
"ESTONIAN" },
332 { FAEROESE,
"FAEROESE" },
334 { FILIPINO,
"FILIPINO" },
335 { FINNISH,
"FINNISH" },
336 { FRENCH_STANDARD,
"FRENCH_STANDARD" },
337 { FRENCH_BELGIAN,
"FRENCH_BELGIAN" },
338 { FRENCH_CANADIAN,
"FRENCH_CANADIAN" },
339 { FRENCH_SWISS,
"FRENCH_SWISS" },
340 { FRENCH_LUXEMBOURG,
"FRENCH_LUXEMBOURG" },
341 { FRENCH_MONACO,
"FRENCH_MONACO" },
342 { FRISIAN,
"FRISIAN" },
343 { GEORGIAN,
"GEORGIAN" },
344 { GALICIAN,
"GALICIAN" },
345 { GERMAN_STANDARD,
"GERMAN_STANDARD" },
346 { GERMAN_SWISS,
"GERMAN_SWISS" },
347 { GERMAN_AUSTRIAN,
"GERMAN_AUSTRIAN" },
348 { GERMAN_LUXEMBOURG,
"GERMAN_LUXEMBOURG" },
349 { GERMAN_LIECHTENSTEIN,
"GERMAN_LIECHTENSTEIN" },
351 { GREENLANDIC,
"GREENLANDIC" },
352 { GUJARATI,
"GUJARATI" },
353 { HEBREW,
"HEBREW" },
355 { HUNGARIAN,
"HUNGARIAN" },
356 { ICELANDIC,
"ICELANDIC" },
358 { INDONESIAN,
"INDONESIAN" },
360 { ITALIAN_STANDARD,
"ITALIAN_STANDARD" },
361 { ITALIAN_SWISS,
"ITALIAN_SWISS" },
362 { JAPANESE,
"JAPANESE" },
363 { KANNADA,
"KANNADA" },
364 { KAZAKH,
"KAZAKH" },
367 { KINYARWANDA,
"KINYARWANDA" },
368 { KONKANI,
"KONKANI" },
369 { KOREAN,
"KOREAN" },
370 { KYRGYZ,
"KYRGYZ" },
372 { LATVIAN,
"LATVIAN" },
373 { LITHUANIAN,
"LITHUANIAN" },
374 { LOWER_SORBIAN,
"LOWER_SORBIAN" },
375 { LUXEMBOURGISH,
"LUXEMBOURGISH" },
376 { MACEDONIAN,
"MACEDONIAN" },
377 { MALAY_MALAYSIA,
"MALAY_MALAYSIA" },
378 { MALAY_BRUNEI_DARUSSALAM,
"MALAY_BRUNEI_DARUSSALAM" },
379 { MALAYALAM,
"MALAYALAM" },
380 { MALTESE,
"MALTESE" },
381 { MAPUDUNGUN,
"MAPUDUNGUN" },
383 { MARATHI,
"MARATHI" },
384 { MOHAWK,
"MOHAWK" },
385 { MONGOLIAN,
"MONGOLIAN" },
386 { NEPALI,
"NEPALI" },
387 { NORWEGIAN_BOKMAL,
"NORWEGIAN_BOKMAL" },
388 { NORWEGIAN_NYNORSK,
"NORWEGIAN_NYNORSK" },
389 { OCCITAN,
"OCCITAN" },
391 { PASHTO,
"PASHTO" },
392 { POLISH,
"POLISH" },
393 { PORTUGUESE_BRAZILIAN,
"PORTUGUESE_BRAZILIAN" },
394 { PORTUGUESE_STANDARD,
"PORTUGUESE_STANDARD" },
395 { PUNJABI,
"PUNJABI" },
396 { QUECHUA_BOLIVIA,
"QUECHUA_BOLIVIA" },
397 { QUECHUA_ECUADOR,
"QUECHUA_ECUADOR" },
398 { QUECHUA_PERU,
"QUECHUA_PERU" },
399 { ROMANIAN,
"ROMANIAN" },
400 { ROMANSH,
"ROMANSH" },
401 { RUSSIAN,
"RUSSIAN" },
402 { SAMI_INARI,
"SAMI_INARI" },
403 { SAMI_LULE_NORWAY,
"SAMI_LULE_NORWAY" },
404 { SAMI_LULE_SWEDEN,
"SAMI_LULE_SWEDEN" },
405 { SAMI_NORTHERN_FINLAND,
"SAMI_NORTHERN_FINLAND" },
406 { SAMI_NORTHERN_NORWAY,
"SAMI_NORTHERN_NORWAY" },
407 { SAMI_NORTHERN_SWEDEN,
"SAMI_NORTHERN_SWEDEN" },
408 { SAMI_SKOLT,
"SAMI_SKOLT" },
409 { SAMI_SOUTHERN_NORWAY,
"SAMI_SOUTHERN_NORWAY" },
410 { SAMI_SOUTHERN_SWEDEN,
"SAMI_SOUTHERN_SWEDEN" },
411 { SANSKRIT,
"SANSKRIT" },
412 { SERBIAN_LATIN,
"SERBIAN_LATIN" },
413 { SERBIAN_LATIN_BOSNIA_HERZEGOVINA,
"SERBIAN_LATIN_BOSNIA_HERZEGOVINA" },
414 { SERBIAN_CYRILLIC,
"SERBIAN_CYRILLIC" },
415 { SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA,
"SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA" },
416 { SESOTHO_SA_LEBOA,
"SESOTHO_SA_LEBOA" },
417 { SINHALA,
"SINHALA" },
418 { SLOVAK,
"SLOVAK" },
419 { SLOVENIAN,
"SLOVENIAN" },
420 { SPANISH_TRADITIONAL_SORT,
"SPANISH_TRADITIONAL_SORT" },
421 { SPANISH_MEXICAN,
"SPANISH_MEXICAN" },
422 { SPANISH_MODERN_SORT,
"SPANISH_MODERN_SORT" },
423 { SPANISH_GUATEMALA,
"SPANISH_GUATEMALA" },
424 { SPANISH_COSTA_RICA,
"SPANISH_COSTA_RICA" },
425 { SPANISH_PANAMA,
"SPANISH_PANAMA" },
426 { SPANISH_DOMINICAN_REPUBLIC,
"SPANISH_DOMINICAN_REPUBLIC" },
427 { SPANISH_VENEZUELA,
"SPANISH_VENEZUELA" },
428 { SPANISH_COLOMBIA,
"SPANISH_COLOMBIA" },
429 { SPANISH_PERU,
"SPANISH_PERU" },
430 { SPANISH_ARGENTINA,
"SPANISH_ARGENTINA" },
431 { SPANISH_ECUADOR,
"SPANISH_ECUADOR" },
432 { SPANISH_CHILE,
"SPANISH_CHILE" },
433 { SPANISH_UNITED_STATES,
"SPANISH_UNITED_STATES" },
434 { SPANISH_URUGUAY,
"SPANISH_URUGUAY" },
435 { SPANISH_PARAGUAY,
"SPANISH_PARAGUAY" },
436 { SPANISH_BOLIVIA,
"SPANISH_BOLIVIA" },
437 { SPANISH_EL_SALVADOR,
"SPANISH_EL_SALVADOR" },
438 { SPANISH_HONDURAS,
"SPANISH_HONDURAS" },
439 { SPANISH_NICARAGUA,
"SPANISH_NICARAGUA" },
440 { SPANISH_PUERTO_RICO,
"SPANISH_PUERTO_RICO" },
441 { SWAHILI,
"SWAHILI" },
442 { SWEDISH,
"SWEDISH" },
443 { SWEDISH_FINLAND,
"SWEDISH_FINLAND" },
444 { SYRIAC,
"SYRIAC" },
447 { TELUGU,
"TELUGU" },
449 { TIBETAN_BHUTAN,
"TIBETAN_BHUTAN" },
450 { TIBETAN_PRC,
"TIBETAN_PRC" },
451 { TSWANA,
"TSWANA" },
452 { UKRAINIAN,
"UKRAINIAN" },
453 { TURKISH,
"TURKISH" },
454 { TURKMEN,
"TURKMEN" },
455 { UIGHUR,
"UIGHUR" },
456 { UPPER_SORBIAN,
"UPPER_SORBIAN" },
458 { URDU_INDIA,
"URDU_INDIA" },
459 { UZBEK_LATIN,
"UZBEK_LATIN" },
460 { UZBEK_CYRILLIC,
"UZBEK_CYRILLIC" },
461 { VIETNAMESE,
"VIETNAMESE" },
467 { YORUBA,
"YORUBA" },
474 DWORD keyboardLayouts[5];
475 } LOCALE_KEYBOARD_LAYOUTS;
479 static const LOCALE_KEYBOARD_LAYOUTS LOCALE_KEYBOARD_LAYOUTS_TABLE[] = {
480 { AFRIKAANS, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } },
481 { ALBANIAN, { 0x0000041c, 0x00000409, 0x0, 0x0, 0x0 } },
482 { ARABIC_SAUDI_ARABIA, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
483 { ARABIC_IRAQ, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
484 { ARABIC_EGYPT, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
485 { ARABIC_LIBYA, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } },
486 { ARABIC_ALGERIA, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } },
487 { ARABIC_MOROCCO, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } },
488 { ARABIC_TUNISIA, { 0x0000040c, 0x00020401, 0x0, 0x0, 0x0 } },
489 { ARABIC_OMAN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
490 { ARABIC_YEMEN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
491 { ARABIC_SYRIA, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
492 { ARABIC_JORDAN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
493 { ARABIC_LEBANON, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
494 { ARABIC_KUWAIT, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
495 { ARABIC_UAE, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
496 { ARABIC_BAHRAIN, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
497 { ARABIC_QATAR, { 0x00000409, 0x00000401, 0x0, 0x0, 0x0 } },
498 { ARMENIAN, { 0x0000042b, 0x00000409, 0x00000419, 0x0, 0x0 } },
499 { AZERI_LATIN, { 0x0000042c, 0x0000082c, 0x00000419, 0x0, 0x0 } },
500 { AZERI_CYRILLIC, { 0x0000082c, 0x0000042c, 0x00000419, 0x0, 0x0 } },
501 { BASQUE, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
502 { BELARUSIAN, { 0x00000423, 0x00000409, 0x00000419, 0x0, 0x0 } },
503 { BENGALI_INDIA, { 0x00000445, 0x00000409, 0x0, 0x0, 0x0 } },
504 { BOSNIAN_LATIN, { 0x0000141A, 0x00000409, 0x0, 0x0, 0x0 } },
505 { BULGARIAN, { 0x00000402, 0x00000409, 0x0, 0x0, 0x0 } },
506 { CATALAN, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
507 { CHINESE_TAIWAN, { 0x00000404, 0xe0080404, 0xE0010404, 0x0, 0x0 } },
508 { CHINESE_PRC, { 0x00000804, 0xe00e0804, 0xe0010804, 0xe0030804, 0xe0040804 } },
509 { CHINESE_HONG_KONG, { 0x00000409, 0xe0080404, 0x0, 0x0, 0x0 } },
510 { CHINESE_SINGAPORE, { 0x00000409, 0xe00e0804, 0xe0010804, 0xe0030804, 0xe0040804 } },
511 { CHINESE_MACAU, { 0x00000409, 0xe00e0804, 0xe0020404, 0xe0080404 } },
512 { CROATIAN, { 0x0000041a, 0x00000409, 0x0, 0x0, 0x0 } },
513 { CROATIAN_BOSNIA_HERZEGOVINA, { 0x0000041a, 0x00000409, 0x0, 0x0, 0x0 } },
514 { CZECH, { 0x00000405, 0x00000409, 0x0, 0x0, 0x0 } },
515 { DANISH, { 0x00000406, 0x00000409, 0x0, 0x0, 0x0 } },
516 { DIVEHI, { 0x00000409, 0x00000465, 0x0, 0x0, 0x0 } },
517 { DUTCH_STANDARD, { 0x00020409, 0x00000413, 0x00000409, 0x0, 0x0 } },
518 { DUTCH_BELGIAN, { 0x00000813, 0x00000409, 0x0, 0x0, 0x0 } },
519 { ENGLISH_UNITED_STATES, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
520 { ENGLISH_UNITED_KINGDOM, { 0x00000809, 0x0, 0x0, 0x0, 0x0 } },
521 { ENGLISH_AUSTRALIAN, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
522 { ENGLISH_CANADIAN, { 0x00000409, 0x00011009, 0x00001009, 0x0, 0x0 } },
523 { ENGLISH_NEW_ZEALAND, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
524 { ENGLISH_IRELAND, { 0x00001809, 0x00011809, 0x0, 0x0, 0x0 } },
525 { ENGLISH_SOUTH_AFRICA, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
526 { ENGLISH_JAMAICA, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
527 { ENGLISH_CARIBBEAN, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
528 { ENGLISH_BELIZE, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
529 { ENGLISH_TRINIDAD, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
530 { ENGLISH_ZIMBABWE, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
531 { ENGLISH_PHILIPPINES, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
532 { ESTONIAN, { 0x00000425, 0x0, 0x0, 0x0, 0x0 } },
533 { FAEROESE, { 0x00000406, 0x00000409, 0x0, 0x0, 0x0 } },
534 { FARSI, { 0x00000409, 0x00000429, 0x00000401, 0x0, 0x0 } },
535 { FINNISH, { 0x0000040b, 0x00000409, 0x0, 0x0, 0x0 } },
536 { FRENCH_STANDARD, { 0x0000040c, 0x00000409, 0x0, 0x0, 0x0 } },
537 { FRENCH_BELGIAN, { 0x0000080c, 0x00000409, 0x0, 0x0, 0x0 } },
538 { FRENCH_CANADIAN, { 0x00000C0C, 0x00011009, 0x00000409, 0x0, 0x0 } },
539 { FRENCH_SWISS, { 0x0000100c, 0x00000409, 0x0, 0x0, 0x0 } },
540 { FRENCH_LUXEMBOURG, { 0x0000040c, 0x00000409, 0x0, 0x0, 0x0 } },
541 { FRENCH_MONACO, { 0x0000040c, 0x00000409, 0x0, 0x0, 0x0 } },
542 { GEORGIAN, { 0x00000437, 0x00000409, 0x00000419, 0x0, 0x0 } },
543 { GALICIAN, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
544 { GERMAN_STANDARD, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } },
545 { GERMAN_SWISS, { 0x00000807, 0x00000409, 0x0, 0x0, 0x0 } },
546 { GERMAN_AUSTRIAN, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } },
547 { GERMAN_LUXEMBOURG, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } },
548 { GERMAN_LIECHTENSTEIN, { 0x00000407, 0x00000409, 0x0, 0x0, 0x0 } },
549 { GREEK, { 0x00000408, 0x00000409, 0x0, 0x0, 0x0 } },
550 { GUJARATI, { 0x00000409, 0x00000447, 0x00010439, 0x0, 0x0 } },
551 { HEBREW, { 0x00000409, 0x0000040d, 0x0, 0x0, 0x0 } },
552 { HINDI, { 0x00000409, 0x00010439, 0x00000439, 0x0, 0x0 } },
553 { HUNGARIAN, { 0x0000040e, 0x00000409, 0x0, 0x0, 0x0 } },
554 { ICELANDIC, { 0x0000040f, 0x00000409, 0x0, 0x0, 0x0 } },
555 { INDONESIAN, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } },
556 { ITALIAN_STANDARD, { 0x00000410, 0x00000409, 0x0, 0x0, 0x0 } },
557 { ITALIAN_SWISS, { 0x00000410, 0x00000409, 0x0, 0x0, 0x0 } },
558 { JAPANESE, { 0xe0010411, 0x0, 0x0, 0x0, 0x0 } },
559 { KANNADA, { 0x00000409, 0x0000044b, 0x00010439, 0x0, 0x0 } },
560 { KAZAKH, { 0x0000043f, 0x00000409, 0x00000419, 0x0, 0x0 } },
561 { KONKANI, { 0x00000409, 0x00000439, 0x0, 0x0, 0x0 } },
562 { KOREAN, { 0xE0010412, 0x0, 0x0, 0x0, 0x0 } },
563 { KYRGYZ, { 0x00000440, 0x00000409, 0x0, 0x0, 0x0 } },
564 { LATVIAN, { 0x00010426, 0x0, 0x0, 0x0, 0x0 } },
565 { LITHUANIAN, { 0x00010427, 0x0, 0x0, 0x0, 0x0 } },
566 { MACEDONIAN, { 0x0000042f, 0x00000409, 0x0, 0x0, 0x0 } },
567 { MALAY_MALAYSIA, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
568 { MALAY_BRUNEI_DARUSSALAM, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
569 { MALAYALAM, { 0x00000409, 0x0000044c, 0x0, 0x0, 0x0 } },
570 { MALTESE, { 0x00000409, 0x0000043a, 0x0, 0x0, 0x0 } },
571 { MAORI, { 0x00000409, 0x00000481, 0x0, 0x0, 0x0 } },
572 { MARATHI, { 0x00000409, 0x0000044e, 0x00000439, 0x0, 0x0 } },
573 { MONGOLIAN, { 0x00000450, 0x00000409, 0x0, 0x0, 0x0 } },
574 { NORWEGIAN_BOKMAL, { 0x00000414, 0x00000409, 0x0, 0x0, 0x0 } },
575 { NORWEGIAN_NYNORSK, { 0x00000414, 0x00000409, 0x0, 0x0, 0x0 } },
576 { POLISH, { 0x00010415, 0x00000415, 0x00000409, 0x0, 0x0 } },
577 { PORTUGUESE_BRAZILIAN, { 0x00000416, 0x00000409, 0x0, 0x0, 0x0 } },
578 { PORTUGUESE_STANDARD, { 0x00000816, 0x00000409, 0x0, 0x0, 0x0 } },
579 { PUNJABI, { 0x00000409, 0x00000446, 0x00010439, 0x0, 0x0 } },
580 { QUECHUA_BOLIVIA, { 0x00000409, 0x0000080A, 0x0, 0x0, 0x0 } },
581 { QUECHUA_ECUADOR, { 0x00000409, 0x0000080A, 0x0, 0x0, 0x0 } },
582 { QUECHUA_PERU, { 0x00000409, 0x0000080A, 0x0, 0x0, 0x0 } },
583 { ROMANIAN, { 0x00000418, 0x00000409, 0x0, 0x0, 0x0 } },
584 { RUSSIAN, { 0x00000419, 0x00000409, 0x0, 0x0, 0x0 } },
585 { SAMI_INARI, { 0x0001083b, 0x00000409, 0x0, 0x0, 0x0 } },
586 { SAMI_LULE_NORWAY, { 0x0000043b, 0x00000409, 0x0, 0x0, 0x0 } },
587 { SAMI_LULE_SWEDEN, { 0x0000083b, 0x00000409, 0x0, 0x0, 0x0 } },
588 { SAMI_NORTHERN_FINLAND, { 0x0001083b, 0x00000409, 0x0, 0x0, 0x0 } },
589 { SAMI_NORTHERN_NORWAY, { 0x0000043b, 0x00000409, 0x0, 0x0, 0x0 } },
590 { SAMI_NORTHERN_SWEDEN, { 0x0000083b, 0x00000409, 0x0, 0x0, 0x0 } },
591 { SAMI_SKOLT, { 0x0001083b, 0x00000409, 0x0, 0x0, 0x0 } },
592 { SAMI_SOUTHERN_NORWAY, { 0x0000043b, 0x00000409, 0x0, 0x0, 0x0 } },
593 { SAMI_SOUTHERN_SWEDEN, { 0x0000083b, 0x00000409, 0x0, 0x0, 0x0 } },
594 { SANSKRIT, { 0x00000409, 0x00000439, 0x0, 0x0, 0x0 } },
595 { SERBIAN_LATIN, { 0x0000081a, 0x00000409, 0x0, 0x0, 0x0 } },
596 { SERBIAN_LATIN_BOSNIA_HERZEGOVINA, { 0x0000081a, 0x00000409, 0x0, 0x0, 0x0 } },
597 { SERBIAN_CYRILLIC, { 0x00000c1a, 0x00000409, 0x0, 0x0, 0x0 } },
598 { SERBIAN_CYRILLIC_BOSNIA_HERZEGOVINA, { 0x00000c1a, 0x00000409, 0x0, 0x0, 0x0 } },
599 { SLOVAK, { 0x0000041b, 0x00000409, 0x0, 0x0, 0x0 } },
600 { SLOVENIAN, { 0x00000424, 0x00000409, 0x0, 0x0, 0x0 } },
601 { SPANISH_TRADITIONAL_SORT, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
602 { SPANISH_MEXICAN, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
603 { SPANISH_MODERN_SORT, { 0x0000040a, 0x00000409, 0x0, 0x0, 0x0 } },
604 { SPANISH_GUATEMALA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
605 { SPANISH_COSTA_RICA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
606 { SPANISH_PANAMA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
607 { SPANISH_DOMINICAN_REPUBLIC, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
608 { SPANISH_VENEZUELA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
609 { SPANISH_COLOMBIA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
610 { SPANISH_PERU, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
611 { SPANISH_ARGENTINA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
612 { SPANISH_ECUADOR, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
613 { SPANISH_CHILE, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
614 { SPANISH_URUGUAY, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
615 { SPANISH_PARAGUAY, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
616 { SPANISH_BOLIVIA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
617 { SPANISH_EL_SALVADOR, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
618 { SPANISH_HONDURAS, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
619 { SPANISH_NICARAGUA, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
620 { SPANISH_PUERTO_RICO, { 0x0000080a, 0x00000409, 0x0, 0x0, 0x0 } },
621 { SWAHILI, { 0x00000409, 0x0, 0x0, 0x0, 0x0 } },
622 { SWEDISH, { 0x0000041d, 0x00000409, 0x0, 0x0, 0x0 } },
623 { SWEDISH_FINLAND, { 0x0000041d, 0x00000409, 0x0, 0x0, 0x0 } },
624 { SYRIAC, { 0x00000409, 0x0000045a, 0x0, 0x0, 0x0 } },
625 { TAMIL, { 0x00000409, 0x00000449, 0x0, 0x0, 0x0 } },
626 { TATAR, { 0x00000444, 0x00000409, 0x00000419, 0x0, 0x0 } },
627 { TELUGU, { 0x00000409, 0x0000044a, 0x00010439, 0x0, 0x0 } },
628 { THAI, { 0x00000409, 0x0000041e, 0x0, 0x0, 0x0 } },
629 { TSWANA, { 0x00000409, 0x0000041f, 0x0, 0x0, 0x0 } },
630 { UKRAINIAN, { 0x00000422, 0x00000409, 0x0, 0x0, 0x0 } },
631 { TURKISH, { 0x0000041f, 0x0000041f, 0x0, 0x0, 0x0 } },
632 { UKRAINIAN, { 0x00000422, 0x00000409, 0x0, 0x0, 0x0 } },
633 { URDU, { 0x00000401, 0x00000409, 0x0, 0x0, 0x0 } },
634 { UZBEK_LATIN, { 0x00000409, 0x00000843, 0x00000419, 0x0, 0x0 } },
635 { UZBEK_CYRILLIC, { 0x00000843, 0x00000409, 0x00000419, 0x0, 0x0 } },
636 { VIETNAMESE, { 0x00000409, 0x0000042a, 0x0, 0x0, 0x0 } },
637 { WELSH, { 0x00000452, 0x00000809, 0x0, 0x0, 0x0 } },
638 { XHOSA, { 0x00000409, 0x00000409, 0x0, 0x0, 0x0 } },
641 static BOOL freerdp_get_system_language_and_country_codes(
char* language,
size_t languageLen,
642 char* country,
size_t countryLen)
644 WINPR_ASSERT(language);
645 WINPR_ASSERT(languageLen > 0);
646 WINPR_ASSERT(country);
647 WINPR_ASSERT(countryLen);
649 #if defined(__APPLE__)
651 CFStringRef langRef, countryRef;
652 CFLocaleRef localeRef = CFLocaleCopyCurrent();
656 langRef = (CFStringRef)CFLocaleGetValue(localeRef, kCFLocaleLanguageCode);
657 countryRef = (CFStringRef)CFLocaleGetValue(localeRef, kCFLocaleCountryCode);
658 if (!langRef || !countryRef)
660 CFRelease(localeRef);
664 if (!CFStringGetCString(langRef, language, languageLen, kCFStringEncodingUTF8) ||
665 !CFStringGetCString(countryRef, country, countryLen, kCFStringEncodingUTF8))
667 CFRelease(localeRef);
671 CFRelease(localeRef);
678 size_t underscore = 0;
679 char* env_lang = NULL;
680 LPCSTR lang =
"LANG";
682 nSize = GetEnvironmentVariableA(lang, NULL, 0);
687 env_lang = (
char*)malloc(nSize);
692 if (GetEnvironmentVariableA(lang, env_lang, nSize) !=
699 underscore = strcspn(env_lang,
"_");
709 size_t len = MIN(languageLen - 1u, underscore);
710 strncpy(language, env_lang, len);
711 language[len] =
'\0';
714 dot = strcspn(env_lang,
".");
717 if (dot > underscore)
719 size_t len = MIN(countryLen - 1, dot - underscore - 1);
720 strncpy(country, &env_lang[underscore + 1], len);
735 static const SYSTEM_LOCALE* freerdp_detect_system_locale(
void)
737 char language[LOCALE_LANGUAGE_LEN] = { 0 };
738 char country[LOCALE_COUNTRY_LEN] = { 0 };
741 freerdp_get_system_language_and_country_codes(language, ARRAYSIZE(language), country,
744 for (
size_t i = 0; i < ARRAYSIZE(SYSTEM_LOCALE_TABLE); i++)
748 if ((strcmp(language, current->language) == 0) && (strcmp(country, current->country) == 0))
758 DWORD freerdp_get_system_locale_id(
void)
761 locale = freerdp_detect_system_locale();
769 static const SYSTEM_LOCALE* get_locale_from_str(
const char* name)
771 for (
size_t i = 0; i < ARRAYSIZE(SYSTEM_LOCALE_TABLE); i++)
773 char buffer[LOCALE_LANGUAGE_LEN + LOCALE_COUNTRY_LEN + 2] = { 0 };
776 (void)_snprintf(buffer,
sizeof(buffer),
"%s_%s", current->language, current->country);
778 if ((strcmp(name, buffer) == 0))
781 else if ((strcmp(name, current->language) == 0))
787 static INT64 get_layout_from_locale(
const SYSTEM_LOCALE* locale)
789 for (
size_t i = 0; i < ARRAYSIZE(LOCALE_KEYBOARD_LAYOUTS_TABLE); i++)
791 const LOCALE_KEYBOARD_LAYOUTS* current = &LOCALE_KEYBOARD_LAYOUTS_TABLE[i];
792 WINPR_ASSERT(current);
794 if (current->locale == locale->code)
797 for (
size_t j = 0; j < 5; j++)
799 if (current->keyboardLayouts[j] == ENGLISH_UNITED_STATES)
803 else if (current->keyboardLayouts[j] == 0)
811 return ENGLISH_UNITED_STATES;
817 return current->keyboardLayouts[j];
824 const char* freerdp_get_system_locale_name_from_id(DWORD localeId)
826 for (
size_t index = 0; index < ARRAYSIZE(LOCALE_NAME_TABLE); index++)
828 const LOCALE_NAME* current = &LOCALE_NAME_TABLE[index];
830 if (localeId == current->localeId)
831 return current->name;
837 INT64 freerdp_get_locale_id_from_string(
const char* locale)
845 int freerdp_detect_keyboard_layout_from_system_locale(DWORD* keyboardLayoutId)
847 char language[LOCALE_LANGUAGE_LEN] = { 0 };
848 char country[LOCALE_COUNTRY_LEN] = { 0 };
850 freerdp_get_system_language_and_country_codes(language, ARRAYSIZE(language), country,
853 if ((strcmp(language,
"C") == 0) || (strcmp(language,
"POSIX") == 0))
855 *keyboardLayoutId = ENGLISH_UNITED_STATES;
859 const SYSTEM_LOCALE* locale = freerdp_detect_system_locale();
864 DEBUG_KBD(
"Found locale : %s_%s", locale->language, locale->country);
865 INT64 rc = get_layout_from_locale(locale);
868 *keyboardLayoutId = (DWORD)rc;
872 const SYSTEM_LOCALE* freerdp_get_system_locale_list(
size_t* count)
875 *count = ARRAYSIZE(SYSTEM_LOCALE_TABLE);
876 return SYSTEM_LOCALE_TABLE;
879 DWORD freerdp_get_keyboard_default_layout_for_locale(DWORD locale)
881 for (
size_t x = 0; x < ARRAYSIZE(LOCALE_KEYBOARD_LAYOUTS_TABLE); x++)
883 const LOCALE_KEYBOARD_LAYOUTS* cur = &LOCALE_KEYBOARD_LAYOUTS_TABLE[x];
884 if (cur->locale == locale)
885 return cur->keyboardLayouts[0];
A SYSTEM_LOCALE holding details about a locale.