1
////////////////////////////////////////////////////////////////////////////
2
// NoteCase notes manager project <http://notecase.sf.net>
4
// This code is licensed under BSD license.See "license.txt" for more details.
6
// File: Class for handling internationalisation issues (message catalogs)
7
////////////////////////////////////////////////////////////////////////////
9
#include "GuiLanguage.h"
13
#include "../lib/EnumDirectory.h"
16
#include <io.h> //access
18
#define access _access
21
bool OnDirEnum(const char *szDir, void *data);
22
#define ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0]))
25
//define dummy versions of Windows language IDs
26
#define LANG_AFRIKAANS 0
27
#define LANG_ALBANIAN 0
29
#define LANG_ARMENIAN 0
30
#define LANG_BELARUSIAN 0
31
#define LANG_BULGARIAN 0
32
#define LANG_CATALAN 0
33
#define LANG_CROATIAN 0
37
#define LANG_ENGLISH 0
38
#define LANG_ESTONIAN 0
41
#define LANG_FINNISH 0
42
#define LANG_GEORGIAN 0
47
#define LANG_HUNGARIAN 0
48
#define LANG_ICELANDIC 0
49
#define LANG_INDONESIAN 0
50
#define LANG_ITALIAN 0
51
#define LANG_JAPANESE 0
53
#define LANG_LATVIAN 0
54
#define LANG_LITHUANIAN 0
55
#define LANG_MACEDONIAN 0
57
#define LANG_NORWEGIAN 0
59
#define LANG_PORTUGUESE 0
60
#define LANG_ROMANIAN 0
61
#define LANG_RUSSIAN 0
62
#define LANG_SERBIAN 0
64
#define LANG_SLOVENIAN 0
65
#define LANG_SPANISH 0
66
#define LANG_SWEDISH 0
69
#define LANG_TURKISH 0
70
#define LANG_UKRAINIAN 0
72
#define LANG_VIETNAMESE 0
73
#define LANG_CHINESE 0
75
//define dummy versions of Windows sublanguage IDs
76
#define SUBLANG_DEFAULT 0
77
#define SUBLANG_DUTCH 0
78
#define SUBLANG_DUTCH_BELGIAN 0
79
#define SUBLANG_ENGLISH_UK 0
80
#define SUBLANG_ENGLISH_US 0
81
#define SUBLANG_FRENCH 0
82
#define SUBLANG_FRENCH_BELGIAN 0
83
#define SUBLANG_FRENCH_CANADIAN 0
84
#define SUBLANG_GERMAN 0
85
#define SUBLANG_GERMAN_AUSTRIAN 0
86
#define SUBLANG_GERMAN_SWISS 0
87
#define SUBLANG_LITHUANIAN 0
88
#define SUBLANG_KOREAN 0
89
#define SUBLANG_MALAY_MALAYSIA 0
90
#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0
91
#define SUBLANG_NORWEGIAN_BOKMAL 0
92
#define SUBLANG_NORWEGIAN_NYNORSK 0
93
#define SUBLANG_PORTUGUESE 0
94
#define SUBLANG_PORTUGUESE_BRAZILIAN 0
95
#define SUBLANG_SPANISH 0
96
#define SUBLANG_SWEDISH 0
97
#define SUBLANG_SERBIAN_LATIN 0
102
const char *iso, *locale, *lang;
107
//TOFIX add more languages, add native language name column?
108
static LanguageStruct isoLanguages[] =
110
{"af", "af_AF", "Afrikaans", LANG_AFRIKAANS, SUBLANG_DEFAULT},
111
{"sq", "sq_AL", "Albanian", LANG_ALBANIAN, SUBLANG_DEFAULT},
112
{"ar", "ar", "Arabic", LANG_ARABIC, SUBLANG_DEFAULT},
113
{"hy", "hy", "Armenian", LANG_ARMENIAN, SUBLANG_DEFAULT},
114
{"be", "be_BE", "Belarusian", LANG_BELARUSIAN,SUBLANG_DEFAULT},
115
{"bg", "bg_BG", "Bulgarian", LANG_BULGARIAN, SUBLANG_DEFAULT},
116
{"ca", "ca_CA", "Catalan", LANG_CATALAN, SUBLANG_DEFAULT},
117
{"zh", "zh_CN", "Chinese", LANG_CHINESE, SUBLANG_DEFAULT},
118
{"hr", "hr_HR", "Croatian", LANG_CROATIAN, SUBLANG_DEFAULT},
119
{"cs", "cs_CZ", "Czech", LANG_CZECH, SUBLANG_DEFAULT},
120
{"da", "da_DK", "Danish", LANG_DANISH, SUBLANG_DEFAULT},
121
{"nl", "nl_NL", "Dutch", LANG_DUTCH, SUBLANG_DUTCH},
122
{"nl_BE","nl_BE", "Dutch (Belgian)", LANG_DUTCH, SUBLANG_DUTCH_BELGIAN},
123
{"en", "en_GB", "English", LANG_ENGLISH, SUBLANG_ENGLISH_UK},
124
{"en_US","en_US", "English (American)",LANG_ENGLISH, SUBLANG_ENGLISH_US},
125
{"et", "et_EE", "Estonian", LANG_ESTONIAN, SUBLANG_DEFAULT},
126
{"fa", "fa_IR", "Farsi", LANG_FARSI, SUBLANG_DEFAULT},
127
{"fi", "fi_FI", "Finnish", LANG_FINNISH , SUBLANG_DEFAULT},
128
{"fr", "fr_FR", "French", LANG_FRENCH, SUBLANG_FRENCH},
129
{"fr_BE","fr_BE", "French (Belgian)", LANG_FRENCH, SUBLANG_FRENCH_BELGIAN},
130
{"fr_CA","fr_CA", "French (Canadian)", LANG_FRENCH, SUBLANG_FRENCH_CANADIAN},
131
{"ka", "ka", "Georgian", LANG_GEORGIAN, SUBLANG_DEFAULT},
132
{"de", "de_DE", "German", LANG_GERMAN, SUBLANG_GERMAN},
133
{"de_AT", "de_AT", "German (Austrian)", LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN},
134
{"de_CH", "de_CH", "German (Swiss)", LANG_GERMAN, SUBLANG_GERMAN_SWISS},
135
{"el", "el_GR", "Greek", LANG_GREEK, SUBLANG_DEFAULT},
136
{"he", "he_IL", "Hebrew", LANG_HEBREW, SUBLANG_DEFAULT},
137
{"hi", "hi_IN", "Hindi", LANG_HINDI, SUBLANG_DEFAULT},
138
{"hu", "hu_HU", "Hungarian", LANG_HUNGARIAN, SUBLANG_DEFAULT},
139
{"is", "is_IS", "Icelandic", LANG_ICELANDIC, SUBLANG_DEFAULT},
140
{"id", "id_ID", "Indonesian", LANG_INDONESIAN,SUBLANG_DEFAULT},
141
{"it", "it_IT", "Italian", LANG_ITALIAN, SUBLANG_DEFAULT},
142
{"ja", "ja_JP", "Japanese", LANG_JAPANESE, SUBLANG_DEFAULT},
143
{"ko", "ko_KR", "Korean", LANG_KOREAN, SUBLANG_KOREAN},
144
{"lv", "lv_LV", "Latvian", LANG_LATVIAN, SUBLANG_DEFAULT},
145
{"lt", "lt_LT", "Lithuanian", LANG_LITHUANIAN,SUBLANG_LITHUANIAN},
146
{"mk", "mk_MK", "Macedonian (FYROM)",LANG_MACEDONIAN,SUBLANG_DEFAULT},
147
{"ms", "ms_MY", "Malay (Malaysia)", LANG_MALAY, SUBLANG_MALAY_MALAYSIA},
148
{"ms_BN","ms_BN", "Malay (Brunei)",LANG_MALAY, SUBLANG_MALAY_BRUNEI_DARUSSALAM},
149
{"nb", "nb_NO", "Norwegian Bokmal", LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL},
150
{"nn", "nn_NO", "Norwegian Nynorsk",LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK},
151
{"no", "no_NO", "Norwegian", LANG_NORWEGIAN, SUBLANG_DEFAULT},
152
{"pl", "pl_PL", "Polish", LANG_POLISH, SUBLANG_DEFAULT},
153
{"pt", "pt_PT", "Portuguese", LANG_PORTUGUESE,SUBLANG_PORTUGUESE},
154
{"pt_BR", "pt_BR", "Portuguese (Brazilian)", LANG_PORTUGUESE,SUBLANG_PORTUGUESE_BRAZILIAN},
155
{"ro", "ro_RO", "Romanian", LANG_ROMANIAN, SUBLANG_DEFAULT},
156
{"ru", "ru_RU", "Russian", LANG_RUSSIAN, SUBLANG_DEFAULT},
157
//TOFIX there seems to be no cross-platform compatible locale for Serbian language
158
//"sr_CS@Latn" and "sr_CS" seem to be official codes, but do not work
160
{"sr", "sr_CS", "Serbian (Latin)", LANG_SERBIAN, SUBLANG_SERBIAN_LATIN},
162
//TOFIX Can not find proper locale for Fedora Core 3
163
{"sr", "sr_YU.UTF-8", "Serbian (Latin)", LANG_SERBIAN, SUBLANG_SERBIAN_LATIN},
165
//TOFIX {"sr_CS","sr_CS","Serbian (Cyrillic)", LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC},
166
{"sk", "sk_SK", "Slovak", LANG_SLOVAK, SUBLANG_DEFAULT},
167
{"sl", "sl_SI", "Slovenian", LANG_SLOVENIAN, SUBLANG_DEFAULT},
168
{"es", "es_ES", "Spanish", LANG_SPANISH, SUBLANG_SPANISH},
169
{"sv", "sv_SE", "Swedish", LANG_SWEDISH, SUBLANG_SWEDISH},
170
{"th", "th_TH", "Thai", LANG_THAI, SUBLANG_DEFAULT},
171
{"bo", "bo", "Tibetan", 0, 0},
172
{"ta", "ta_IN", "Tamil", LANG_TAMIL, SUBLANG_DEFAULT},
173
{"tr", "tr_TR", "Turkish", LANG_TURKISH, SUBLANG_DEFAULT},
174
{"uk", "uk_UA", "Ukrainian", LANG_UKRAINIAN, SUBLANG_DEFAULT},
175
{"ur", "ur", "Urdu", LANG_URDU, SUBLANG_DEFAULT},
176
{"vi", "vi_VN", "Vietnamese", LANG_VIETNAMESE,SUBLANG_DEFAULT},
179
GuiLanguage::GuiLanguage(const char *szPackage, const char *szLocaleDir, const char *szSourceISO)
181
m_strPackage = szPackage;
182
m_strLocaleDir = szLocaleDir;
183
m_strDefaultISO = (NULL != szSourceISO)? szSourceISO : "en";
186
GuiLanguage::~GuiLanguage()
190
//maps from locale code to the language name
191
const char *GuiLanguage::GetLangName(const char *locale)
193
//match either short or long version of the locale
194
for (unsigned int i=0; i<ARRAY_COUNT(isoLanguages); i++)
195
if (0 == strcmp (isoLanguages[i].iso, locale) ||
196
0 == strcmp (isoLanguages[i].locale, locale))
197
return isoLanguages[i].lang;
199
return ""; // not found
202
const char *GuiLanguage::GetLocaleCode(const char *iso)
204
//match either short or long version of the locale
205
for (unsigned int i=0; i<ARRAY_COUNT(isoLanguages); i++)
206
if (0 == strcmp (isoLanguages[i].iso, iso))
207
return isoLanguages[i].locale;
209
return ""; // not found
212
int GuiLanguage::GetLocaleTableIdx(const char *locale)
214
//match either short or long version of the locale
215
for (unsigned int i=0; i<ARRAY_COUNT(isoLanguages); i++)
216
if (0 == strcmp (isoLanguages[i].iso, locale) ||
217
0 == strcmp (isoLanguages[i].locale, locale))
220
return -1; // not found
223
void GuiLanguage::Initialize(const char *szIsoCode)
226
ListAvailableCatalogs();
228
//ensure some language is selected
229
if(NULL == szIsoCode || strlen(szIsoCode)==0)
230
szIsoCode = m_strDefaultISO.c_str(); //default ISO (one used in the source code)
232
// convert language ISO code to locale code
233
const char *szLocaleCode = GetLocaleCode(szIsoCode);
234
if(strlen(szLocaleCode) > 0)
236
//ensure language catalog is available
237
if( !IsLocaleAvailable(szIsoCode) &&
238
!IsLocaleAvailable(szLocaleCode) )
240
szIsoCode = m_strDefaultISO.c_str(); //default ISO (one used in the source code)
241
szLocaleCode = GetLocaleCode(szIsoCode);//default locale
244
//set language localisation for this program
245
putenv( g_strconcat("LANG=", szLocaleCode, NULL) );
246
setlocale(LC_ALL, "");
249
//FIX for Windows code
250
int nIdx = GetLocaleTableIdx(szIsoCode);
252
SetThreadLocale(MAKELCID(MAKELANGID(isoLanguages[nIdx].nLangID_W32, isoLanguages[nIdx].nSubLangID_W32), SORT_DEFAULT));
256
// init NLS system settings
257
bindtextdomain (m_strPackage.c_str(), m_strLocaleDir.c_str());
258
bind_textdomain_codeset (m_strPackage.c_str(), "UTF-8");
259
textdomain (m_strPackage.c_str());
261
//store locale code for later lookup
262
m_strCurLang = szIsoCode;
266
void GuiLanguage::ListAvailableCatalogs()
269
m_lstCatalogs.erase(m_lstCatalogs.begin(), m_lstCatalogs.end()); //empty the list
271
//list all subdirectories in the locale directory (subdirectory name matches the locale name)
272
std::vector<std::string> lstDirs;
273
EnumDirectory(m_strLocaleDir.c_str(), OnDirEnum, (void *)&lstDirs, ENUM_LST_DIRS);
275
//store each locale containing catalog for current package
276
for( unsigned int i=0; i<lstDirs.size(); i++)
278
//check if message catalog exists for given locale subdirectory
279
std::string strCatalog;
281
strCatalog = m_strLocaleDir;
282
strCatalog += lstDirs[i];
283
strCatalog += "\\LC_MESSAGES\\";
284
strCatalog += m_strPackage;
288
sprintf(szBuffer, "%s/%s/LC_MESSAGES/%s.mo",m_strLocaleDir.c_str(), lstDirs[i].c_str(), m_strPackage.c_str());
289
strCatalog = szBuffer;
292
if(0 == access(strCatalog.c_str(), 00))
293
m_lstCatalogs.push_back(lstDirs[i]); //add locale into the list of available catalogs
297
bool GuiLanguage::IsLocaleAvailable(const char *szLocale)
299
return (-1 != GetLocaleIdx(szLocale));
302
int GuiLanguage::GetLocaleIdx(const char *szLocale)
304
for(unsigned int i=0; i<m_lstCatalogs.size(); i++)
306
const char *szCatalogEntry = m_lstCatalogs[i].c_str();
307
if( 0 == strcmp(szCatalogEntry, szLocale) )
311
return -1; //not found
314
bool OnDirEnum(const char *szDir, void *data)
316
std::vector<std::string> *lstDirs = (std::vector<std::string> *)data;
319
//calcualte base name and add it into the list
321
//calculate base name
322
std::string strDir(szDir);
323
int nPos = strDir.find_last_of('\\');
325
strDir = strDir.substr(nPos+1, 1000);
327
std::string strDir(basename((char *)szDir));
330
lstDirs->push_back(strDir);
333
return true; //keep enumerating
336
const char *GuiLanguage::QueryLocale(int category)
338
//return current locale settings
339
//WARNING: on Windows returns global system settings, not program ones
340
return setlocale(category, NULL);
343
const char *GuiLanguage::GetLocale()
345
return m_strCurLang.c_str();
1
////////////////////////////////////////////////////////////////////////////
2
// NoteCase notes manager project <http://notecase.sf.net>
4
// This code is licensed under BSD license.See "license.txt" for more details.
6
// File: Class for handling internationalisation issues (message catalogs)
7
////////////////////////////////////////////////////////////////////////////
9
#include "GuiLanguage.h"
15
#include "../lib/EnumDirectory.h"
18
#include <io.h> //access
20
#define access _access
23
extern GuiLanguage g_lang;
25
bool OnDirEnum(const char *szDir, void *data);
26
#define ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0]))
29
//define dummy versions of Windows language IDs
30
#define LANG_AFRIKAANS 0
31
#define LANG_ALBANIAN 0
32
#define LANG_AMHARIC 0
34
#define LANG_ARMENIAN 0
36
#define LANG_BELARUSIAN 0
37
#define LANG_BENGALI 0
38
#define LANG_BULGARIAN 0
39
#define LANG_CATALAN 0
40
#define LANG_CROATIAN 0
44
#define LANG_ENGLISH 0
45
#define LANG_ESTONIAN 0
46
#define LANG_ESPERANTO 0
49
#define LANG_FINNISH 0
50
#define LANG_GEORGIAN 0
55
#define LANG_HUNGARIAN 0
56
#define LANG_ICELANDIC 0
57
#define LANG_INDONESIAN 0
58
#define LANG_ITALIAN 0
59
#define LANG_JAPANESE 0
61
#define LANG_LATVIAN 0
62
#define LANG_LITHUANIAN 0
63
#define LANG_MACEDONIAN 0
64
#define LANG_MONGOLIAN 0
66
#define LANG_NORWEGIAN 0
68
#define LANG_PORTUGUESE 0
69
#define LANG_ROMANIAN 0
70
#define LANG_RUSSIAN 0
71
#define LANG_SERBIAN 0
73
#define LANG_SLOVENIAN 0
74
#define LANG_SPANISH 0
75
#define LANG_SWEDISH 0
78
#define LANG_TURKISH 0
79
#define LANG_UKRAINIAN 0
81
#define LANG_VIETNAMESE 0
82
#define LANG_CHINESE 0
84
//define dummy versions of Windows sublanguage IDs
85
#define SUBLANG_DEFAULT 0
86
#define SUBLANG_BENGALI_INDIA 0
87
#define SUBLANG_BENGALI_BANGLADESH 0
88
#define SUBLANG_CHINESE_TRADITIONAL 0
89
#define SUBLANG_CHINESE_SIMPLIFIED 0
90
#define SUBLANG_DUTCH 0
91
#define SUBLANG_DUTCH_BELGIAN 0
92
#define SUBLANG_ENGLISH_UK 0
93
#define SUBLANG_ENGLISH_US 0
94
#define SUBLANG_FRENCH 0
95
#define SUBLANG_FRENCH_BELGIAN 0
96
#define SUBLANG_FRENCH_CANADIAN 0
97
#define SUBLANG_GERMAN 0
98
#define SUBLANG_GERMAN_AUSTRIAN 0
99
#define SUBLANG_GERMAN_SWISS 0
100
#define SUBLANG_LITHUANIAN 0
101
#define SUBLANG_KOREAN 0
102
#define SUBLANG_MALAY_MALAYSIA 0
103
#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0
104
#define SUBLANG_NORWEGIAN_BOKMAL 0
105
#define SUBLANG_NORWEGIAN_NYNORSK 0
106
#define SUBLANG_PORTUGUESE 0
107
#define SUBLANG_PORTUGUESE_BRAZILIAN 0
108
#define SUBLANG_SPANISH 0
109
#define SUBLANG_SWEDISH 0
110
#define SUBLANG_SERBIAN_LATIN 0
112
//some codes are not defined in Visual C++ 6.0
114
#define LANG_AMHARIC 0x5e
116
#ifndef LANG_ESPERANTO
117
#define LANG_ESPERANTO 0x8f
119
#ifndef LANG_MONGOLIAN
120
#define LANG_MONGOLIAN 0x50
122
#ifndef SUBLANG_BENGALI_INDIA
123
#define SUBLANG_BENGALI_INDIA 0x00
125
#ifndef SUBLANG_BENGALI_BANGLADESH
126
#define SUBLANG_BENGALI_BANGLADESH 0x01
132
const char *iso, *locale, *lang;
138
//TOFIX add more languages, add native language name column?
139
static LanguageStruct isoLanguages[] =
141
{"af", "af_AF", "Afrikaans", LANG_AFRIKAANS, SUBLANG_DEFAULT, false},
142
{"sq", "sq_AL", "Albanian", LANG_ALBANIAN, SUBLANG_DEFAULT, false},
143
{"am", "am_ET", "Amharic", LANG_AMHARIC, SUBLANG_DEFAULT, false},
144
{"ar", "ar", "Arabic", LANG_ARABIC, SUBLANG_DEFAULT, true},
145
{"hy", "hy", "Armenian", LANG_ARMENIAN, SUBLANG_DEFAULT, false},
146
{"eu", "eu", "Basque", LANG_BASQUE, SUBLANG_DEFAULT, false},
147
{"be", "be_BE", "Belarusian", LANG_BELARUSIAN,SUBLANG_DEFAULT, false},
148
{"bn", "bn", "Bengali", LANG_BENGALI, SUBLANG_DEFAULT, false},
149
{"bn_IN", "bn_IN", "Bengali (India)", LANG_BENGALI, SUBLANG_BENGALI_INDIA, false},
150
{"bn_BD", "bn_BD", "Bengali (Bangladesh)", LANG_BENGALI, SUBLANG_BENGALI_BANGLADESH, false},
151
{"bg", "bg_BG", "Bulgarian", LANG_BULGARIAN, SUBLANG_DEFAULT, false},
152
{"ca", "ca_ES", "Catalan", LANG_CATALAN, SUBLANG_DEFAULT, false},
153
{"zh_CN", "zh_CN", "Chinese (simplified)", LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED, false},
154
{"zh_TW", "zh_TW", "Chinese (traditional)", LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL, false},
155
{"hr", "hr_HR", "Croatian", LANG_CROATIAN, SUBLANG_DEFAULT, false},
156
{"cs", "cs_CZ", "Czech", LANG_CZECH, SUBLANG_DEFAULT, false},
157
{"da", "da_DK", "Danish", LANG_DANISH, SUBLANG_DEFAULT, false},
158
{"nl", "nl_NL", "Dutch", LANG_DUTCH, SUBLANG_DUTCH, false},
159
{"nl_BE","nl_BE", "Dutch (Belgian)", LANG_DUTCH, SUBLANG_DUTCH_BELGIAN, false},
160
{"en", "en_GB", "English", LANG_ENGLISH, SUBLANG_ENGLISH_UK, false},
161
{"en_US","en_US", "English (American)",LANG_ENGLISH, SUBLANG_ENGLISH_US, false},
162
{"et", "et_EE", "Estonian", LANG_ESTONIAN, SUBLANG_DEFAULT, false},
163
{"eo", "eo", "Esperanto", LANG_ESPERANTO, SUBLANG_DEFAULT, false},
164
{"fa", "fa_IR", "Farsi", LANG_FARSI, SUBLANG_DEFAULT, false},
165
{"fi", "fi_FI", "Finnish", LANG_FINNISH , SUBLANG_DEFAULT, false},
166
{"fr", "fr_FR", "French", LANG_FRENCH, SUBLANG_FRENCH, false},
167
{"fr_BE","fr_BE", "French (Belgian)", LANG_FRENCH, SUBLANG_FRENCH_BELGIAN, false},
168
{"fr_CA","fr_CA", "French (Canadian)", LANG_FRENCH, SUBLANG_FRENCH_CANADIAN, false},
169
{"ka", "ka", "Georgian", LANG_GEORGIAN, SUBLANG_DEFAULT, false},
170
{"de", "de_DE", "German", LANG_GERMAN, SUBLANG_GERMAN, false},
171
{"de_AT", "de_AT", "German (Austrian)", LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN, false},
172
{"de_CH", "de_CH", "German (Swiss)", LANG_GERMAN, SUBLANG_GERMAN_SWISS, false},
173
{"el", "el_GR", "Greek", LANG_GREEK, SUBLANG_DEFAULT, false},
174
{"he", "he_IL", "Hebrew", LANG_HEBREW, SUBLANG_DEFAULT, true},
175
{"hi", "hi_IN", "Hindi", LANG_HINDI, SUBLANG_DEFAULT, false},
176
{"hu", "hu_HU", "Hungarian", LANG_HUNGARIAN, SUBLANG_DEFAULT, false},
177
{"is", "is_IS", "Icelandic", LANG_ICELANDIC, SUBLANG_DEFAULT, false},
178
{"id", "id_ID", "Indonesian", LANG_INDONESIAN,SUBLANG_DEFAULT, false},
179
{"it", "it_IT", "Italian", LANG_ITALIAN, SUBLANG_DEFAULT, false},
180
{"ja", "ja_JP", "Japanese", LANG_JAPANESE, SUBLANG_DEFAULT, false},
181
{"ko", "ko_KR", "Korean", LANG_KOREAN, SUBLANG_KOREAN, false},
182
{"lv", "lv_LV", "Latvian", LANG_LATVIAN, SUBLANG_DEFAULT, false},
183
{"lt", "lt_LT", "Lithuanian", LANG_LITHUANIAN,SUBLANG_LITHUANIAN, false},
184
{"mk", "mk_MK", "Macedonian (FYROM)",LANG_MACEDONIAN,SUBLANG_DEFAULT, false},
185
{"mn", "mn", "Mongolian",LANG_MONGOLIAN,SUBLANG_DEFAULT, false},
186
{"ms", "ms_MY", "Malay (Malaysia)", LANG_MALAY, SUBLANG_MALAY_MALAYSIA, false},
187
{"ms_BN","ms_BN", "Malay (Brunei)",LANG_MALAY, SUBLANG_MALAY_BRUNEI_DARUSSALAM, false},
188
{"nb", "nb_NO", "Norwegian Bokmal", LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL, false},
189
{"nn", "nn_NO", "Norwegian Nynorsk",LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK, false},
190
{"no", "no_NO", "Norwegian", LANG_NORWEGIAN, SUBLANG_DEFAULT, false},
191
{"pl", "pl_PL", "Polish", LANG_POLISH, SUBLANG_DEFAULT, false},
192
{"pt", "pt_PT", "Portuguese", LANG_PORTUGUESE,SUBLANG_PORTUGUESE, false},
193
{"pt_BR", "pt_BR", "Portuguese (Brazilian)", LANG_PORTUGUESE,SUBLANG_PORTUGUESE_BRAZILIAN, false},
194
{"ro", "ro_RO", "Romanian", LANG_ROMANIAN, SUBLANG_DEFAULT, false},
195
{"ru", "ru_RU", "Russian", LANG_RUSSIAN, SUBLANG_DEFAULT, false},
196
//TOFIX there seems to be no cross-platform compatible locale for Serbian language
197
//"sr_CS@Latn" and "sr_CS" seem to be official codes, but do not work
199
{"sr", "sr_CS", "Serbian (Latin)", LANG_SERBIAN, SUBLANG_SERBIAN_LATIN, false},
201
//TOFIX Can not find proper locale for Fedora Core 3
202
{"sr", "sr_YU.UTF-8", "Serbian (Latin)", LANG_SERBIAN, SUBLANG_SERBIAN_LATIN, false},
204
//TOFIX {"sr_CS","sr_CS","Serbian (Cyrillic)", LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC, false},
205
{"sk", "sk_SK", "Slovak", LANG_SLOVAK, SUBLANG_DEFAULT, false},
206
{"sl", "sl_SI", "Slovenian", LANG_SLOVENIAN, SUBLANG_DEFAULT, false},
207
{"es", "es_ES", "Spanish", LANG_SPANISH, SUBLANG_SPANISH, false},
208
{"sv", "sv_SE", "Swedish", LANG_SWEDISH, SUBLANG_SWEDISH, false},
209
{"th", "th_TH", "Thai", LANG_THAI, SUBLANG_DEFAULT, false},
210
{"bo", "bo", "Tibetan", 0, 0, false},
211
{"ta", "ta_IN", "Tamil", LANG_TAMIL, SUBLANG_DEFAULT, false},
212
{"tr", "tr_TR", "Turkish", LANG_TURKISH, SUBLANG_DEFAULT, false},
213
{"uk", "uk_UA", "Ukrainian", LANG_UKRAINIAN, SUBLANG_DEFAULT, false},
214
{"ur", "ur", "Urdu", LANG_URDU, SUBLANG_DEFAULT, false},
215
{"vi", "vi_VN", "Vietnamese", LANG_VIETNAMESE,SUBLANG_DEFAULT, false},
218
// comparator class to sort locale list by language name (ascending)
225
bool operator ()(const std::string &a, const std::string &b){
227
return (g_lang.GetLangName(a.c_str()) > g_lang.GetLangName(b.c_str()));
229
return (g_lang.GetLangName(a.c_str()) < g_lang.GetLangName(b.c_str()));
234
GuiLanguage::GuiLanguage(const char *szPackage, const char *szLocaleDir, const char *szSourceISO)
236
m_strPackage = szPackage;
237
m_strLocaleDir = szLocaleDir;
238
m_strDefaultISO = (NULL != szSourceISO)? szSourceISO : "en";
239
m_bCatalogsListed = false;
243
GuiLanguage::~GuiLanguage()
247
//maps from locale code to the language name
248
const char *GuiLanguage::GetLangName(const char *locale)
250
//match either short or long version of the locale
251
for (unsigned int i=0; i<ARRAY_COUNT(isoLanguages); i++)
252
if (0 == strcmp (isoLanguages[i].iso, locale) ||
253
0 == strcmp (isoLanguages[i].locale, locale))
254
return isoLanguages[i].lang;
256
return ""; // not found
259
const char *GuiLanguage::GetLocaleCode(const char *iso)
261
//match either short or long version of the locale
262
for (unsigned int i=0; i<ARRAY_COUNT(isoLanguages); i++)
263
if (0 == strcmp (isoLanguages[i].iso, iso))
264
return isoLanguages[i].locale;
266
return ""; // not found
269
int GuiLanguage::GetLocaleTableIdx(const char *locale)
271
//match either short or long version of the locale
272
for (unsigned int i=0; i<ARRAY_COUNT(isoLanguages); i++)
273
if (0 == strcmp (isoLanguages[i].iso, locale) ||
274
0 == strcmp (isoLanguages[i].locale, locale))
277
return -1; // not found
280
void GuiLanguage::Initialize(const char *szIsoCode)
283
//ensure some language is selected
284
if(NULL == szIsoCode || strlen(szIsoCode)==0){
285
szIsoCode = m_strDefaultISO.c_str(); //default ISO (one used in the source code)
286
//TOFIX query LANG environment variable to set default locale ?
289
// convert language ISO code to locale code
290
const char *szLocaleCode = GetLocaleCode(szIsoCode);
291
if(strlen(szLocaleCode) > 0)
293
//ensure language catalog is available
294
if( !IsLocaleAvailable(szIsoCode) &&
295
!IsLocaleAvailable(szLocaleCode) )
297
szIsoCode = m_strDefaultISO.c_str(); //default ISO (one used in the source code)
298
szLocaleCode = GetLocaleCode(szIsoCode);//default locale
301
//set language localisation for this program
302
putenv( g_strconcat("LANG=", szLocaleCode, NULL) );
303
setlocale(LC_ALL, "");
305
m_nLangIdx = GetLocaleTableIdx(szIsoCode);
307
//FIX for Windows code
309
SetThreadLocale(MAKELCID(MAKELANGID(isoLanguages[m_nLangIdx].nLangID_W32, isoLanguages[m_nLangIdx].nSubLangID_W32), SORT_DEFAULT));
313
// init NLS system settings
314
bindtextdomain (m_strPackage.c_str(), m_strLocaleDir.c_str());
315
bind_textdomain_codeset (m_strPackage.c_str(), "UTF-8");
316
textdomain (m_strPackage.c_str());
318
//store locale code for later lookup
319
m_strCurLang = szIsoCode;
323
void GuiLanguage::ListAvailableCatalogs()
325
if(m_bCatalogsListed)
327
m_bCatalogsListed = true;
330
m_lstCatalogs.erase(m_lstCatalogs.begin(), m_lstCatalogs.end()); //empty the list
332
//list all subdirectories in the locale directory (subdirectory name matches the locale name)
333
std::vector<std::string> lstDirs;
334
EnumDirectory(m_strLocaleDir.c_str(), OnDirEnum, (void *)&lstDirs, ENUM_LST_DIRS);
336
//store each locale containing catalog for current package
337
for( unsigned int i=0; i<lstDirs.size(); i++)
339
//check if message catalog exists for given locale subdirectory
340
std::string strCatalog;
342
strCatalog = m_strLocaleDir;
343
strCatalog += lstDirs[i];
344
strCatalog += "\\LC_MESSAGES\\";
345
strCatalog += m_strPackage;
349
snprintf(szBuffer, sizeof(szBuffer), "%s/%s/LC_MESSAGES/%s.mo",m_strLocaleDir.c_str(), lstDirs[i].c_str(), m_strPackage.c_str());
350
strCatalog = szBuffer;
353
if(0 == access(strCatalog.c_str(), 00))
354
m_lstCatalogs.push_back(lstDirs[i]); //add locale into the list of available catalogs
357
//sort list by language names
358
std::sort(m_lstCatalogs.begin(), m_lstCatalogs.end(), CmpLang());
361
bool GuiLanguage::IsLocaleAvailable(const char *szLocale)
363
std::string strCatalog;
365
strCatalog = m_strLocaleDir;
366
strCatalog += szLocale;
367
strCatalog += "\\LC_MESSAGES\\";
368
strCatalog += m_strPackage;
372
snprintf(szBuffer, sizeof(szBuffer), "%s/%s/LC_MESSAGES/%s.mo",m_strLocaleDir.c_str(), szLocale, m_strPackage.c_str());
373
strCatalog = szBuffer;
376
return (0 == access(strCatalog.c_str(), 00));
377
//return (-1 != GetLocaleIdx(szLocale)); //old implementation (slows the program startup)
380
int GuiLanguage::GetLocaleIdx(const char *szLocale)
382
for(unsigned int i=0; i<m_lstCatalogs.size(); i++)
384
const char *szCatalogEntry = m_lstCatalogs[i].c_str();
385
if( 0 == strcmp(szCatalogEntry, szLocale) )
389
return -1; //not found
392
bool OnDirEnum(const char *szDir, void *data)
394
std::vector<std::string> *lstDirs = (std::vector<std::string> *)data;
397
//calculate directory base name and add it into the list
399
//calculate base name
400
std::string strDir(szDir);
401
int nPos = strDir.find_last_of('\\');
403
strDir = strDir.substr(nPos+1, 1000);
405
std::string strDir(basename((char *)szDir));
408
lstDirs->push_back(strDir);
411
return true; //keep enumerating
414
const char *GuiLanguage::QueryLocale(int category)
416
//return current locale settings
417
//WARNING: on Windows this returns global system settings, not program's
418
return setlocale(category, NULL);
421
const char *GuiLanguage::GetLocale()
423
return m_strCurLang.c_str();
426
bool GuiLanguage::IsCurLangRTL()
429
return isoLanguages[m_nLangIdx].bRTL;