~ubuntu-branches/ubuntu/karmic/notecase/karmic

« back to all changes in this revision

Viewing changes to src/gui/GuiLanguage.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Vijay(Vijay)
  • Date: 2007-06-14 00:13:48 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070614001348-z9e2vbgtenb9nhoo
Tags: 1.5.6-0ubuntu1
* New Upstream release 
*  The libgnomevfs2-dev is also added to Build-Depends 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
////////////////////////////////////////////////////////////////////////////
2
 
// NoteCase notes manager project <http://notecase.sf.net>
3
 
//
4
 
// This code is licensed under BSD license.See "license.txt" for more details.
5
 
//
6
 
// File: Class for handling internationalisation issues (message catalogs)
7
 
////////////////////////////////////////////////////////////////////////////
8
 
 
9
 
#include "GuiLanguage.h"
10
 
#include <algorithm>
11
 
#include <gtk/gtk.h>
12
 
#include <libintl.h>
13
 
#include "../lib/EnumDirectory.h"
14
 
 
15
 
#ifdef _WIN32
16
 
 #include <io.h> //access
17
 
 #include <windows.h> 
18
 
 #define access _access
19
 
#endif 
20
 
 
21
 
bool OnDirEnum(const char *szDir, void *data);
22
 
#define ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0]))
23
 
 
24
 
#ifndef _WIN32
25
 
        //define dummy versions of Windows language IDs
26
 
        #define LANG_AFRIKAANS  0
27
 
        #define LANG_ALBANIAN   0
28
 
        #define LANG_ARABIC             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
34
 
        #define LANG_CZECH              0
35
 
        #define LANG_DANISH             0
36
 
        #define LANG_DUTCH              0
37
 
        #define LANG_ENGLISH    0
38
 
        #define LANG_ESTONIAN   0
39
 
        #define LANG_FARSI              0
40
 
        #define LANG_FRENCH             0
41
 
        #define LANG_FINNISH    0
42
 
        #define LANG_GEORGIAN   0
43
 
        #define LANG_GERMAN             0
44
 
        #define LANG_GREEK              0
45
 
        #define LANG_HEBREW             0
46
 
        #define LANG_HINDI              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
52
 
        #define LANG_KOREAN             0
53
 
        #define LANG_LATVIAN    0
54
 
        #define LANG_LITHUANIAN 0
55
 
        #define LANG_MACEDONIAN 0
56
 
        #define LANG_MALAY              0
57
 
        #define LANG_NORWEGIAN  0
58
 
        #define LANG_POLISH             0
59
 
        #define LANG_PORTUGUESE 0
60
 
        #define LANG_ROMANIAN   0
61
 
        #define LANG_RUSSIAN    0
62
 
        #define LANG_SERBIAN    0
63
 
        #define LANG_SLOVAK             0
64
 
        #define LANG_SLOVENIAN  0
65
 
        #define LANG_SPANISH    0
66
 
        #define LANG_SWEDISH    0
67
 
        #define LANG_TAMIL              0
68
 
        #define LANG_THAI               0
69
 
        #define LANG_TURKISH    0
70
 
        #define LANG_UKRAINIAN  0
71
 
        #define LANG_URDU               0
72
 
        #define LANG_VIETNAMESE 0
73
 
        #define LANG_CHINESE    0
74
 
 
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
98
 
#endif
99
 
 
100
 
 
101
 
typedef struct {
102
 
    const char *iso, *locale, *lang;
103
 
        int nLangID_W32;
104
 
        int nSubLangID_W32;
105
 
} LanguageStruct;
106
 
 
107
 
//TOFIX add more languages, add native language name column?
108
 
static LanguageStruct isoLanguages[] = 
109
 
{
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
159
 
#ifdef _WIN32
160
 
    {"sr",      "sr_CS",        "Serbian (Latin)",      LANG_SERBIAN,   SUBLANG_SERBIAN_LATIN},
161
 
#else
162
 
        //TOFIX Can not find proper locale for Fedora Core 3
163
 
    {"sr",      "sr_YU.UTF-8",  "Serbian (Latin)",              LANG_SERBIAN,   SUBLANG_SERBIAN_LATIN},
164
 
#endif
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}, 
177
 
};
178
 
 
179
 
GuiLanguage::GuiLanguage(const char *szPackage, const char *szLocaleDir, const char *szSourceISO)
180
 
{
181
 
        m_strPackage    = szPackage;
182
 
        m_strLocaleDir  = szLocaleDir;
183
 
        m_strDefaultISO = (NULL != szSourceISO)? szSourceISO : "en";
184
 
}
185
 
 
186
 
GuiLanguage::~GuiLanguage()
187
 
{
188
 
}
189
 
 
190
 
//maps from locale code to the language name
191
 
const char *GuiLanguage::GetLangName(const char *locale)
192
 
{
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;
198
 
 
199
 
    return "";    // not found
200
 
}
201
 
 
202
 
const char *GuiLanguage::GetLocaleCode(const char *iso)
203
 
{
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;
208
 
 
209
 
    return "";    // not found
210
 
}
211
 
 
212
 
int GuiLanguage::GetLocaleTableIdx(const char *locale)
213
 
{
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))
218
 
            return i;
219
 
 
220
 
    return -1;    // not found
221
 
}
222
 
 
223
 
void GuiLanguage::Initialize(const char *szIsoCode)
224
 
{
225
 
#ifdef ENABLE_NLS
226
 
        ListAvailableCatalogs();
227
 
 
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)
231
 
 
232
 
        // convert language ISO code to locale code
233
 
        const char *szLocaleCode = GetLocaleCode(szIsoCode);
234
 
        if(strlen(szLocaleCode) > 0)
235
 
        {
236
 
                //ensure language catalog is available
237
 
                if( !IsLocaleAvailable(szIsoCode) &&
238
 
                        !IsLocaleAvailable(szLocaleCode) )
239
 
                {
240
 
                        szIsoCode        = m_strDefaultISO.c_str();     //default ISO (one used in the source code)
241
 
                        szLocaleCode = GetLocaleCode(szIsoCode);//default locale
242
 
                }
243
 
 
244
 
                //set language localisation for this program
245
 
                putenv( g_strconcat("LANG=", szLocaleCode, NULL) );
246
 
                setlocale(LC_ALL, "");
247
 
 
248
 
        #ifdef _WIN32
249
 
                //FIX for Windows code
250
 
                int nIdx = GetLocaleTableIdx(szIsoCode);
251
 
                if(nIdx >= 0)
252
 
                        SetThreadLocale(MAKELCID(MAKELANGID(isoLanguages[nIdx].nLangID_W32, isoLanguages[nIdx].nSubLangID_W32), SORT_DEFAULT));
253
 
        #endif
254
 
        }
255
 
 
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());
260
 
 
261
 
        //store locale code for later lookup
262
 
        m_strCurLang = szIsoCode;
263
 
#endif
264
 
}
265
 
 
266
 
void GuiLanguage::ListAvailableCatalogs()
267
 
{
268
 
        //clear catalog list
269
 
        m_lstCatalogs.erase(m_lstCatalogs.begin(), m_lstCatalogs.end());        //empty the list
270
 
 
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);
274
 
        
275
 
        //store each locale containing catalog for current package
276
 
        for( unsigned int i=0; i<lstDirs.size(); i++)
277
 
        {
278
 
                //check if message catalog exists for given locale subdirectory
279
 
                std::string strCatalog;
280
 
                #ifdef _WIN32
281
 
                        strCatalog  = m_strLocaleDir;
282
 
                        strCatalog += lstDirs[i];
283
 
                        strCatalog += "\\LC_MESSAGES\\";
284
 
                        strCatalog += m_strPackage;
285
 
                        strCatalog += ".mo";
286
 
                #else
287
 
                        char szBuffer[1024];
288
 
                        sprintf(szBuffer, "%s/%s/LC_MESSAGES/%s.mo",m_strLocaleDir.c_str(), lstDirs[i].c_str(), m_strPackage.c_str());
289
 
                        strCatalog  = szBuffer;
290
 
                #endif
291
 
                                
292
 
                if(0 == access(strCatalog.c_str(), 00))
293
 
                        m_lstCatalogs.push_back(lstDirs[i]);    //add locale into the list of available catalogs
294
 
        }
295
 
}
296
 
 
297
 
bool GuiLanguage::IsLocaleAvailable(const char *szLocale)
298
 
{
299
 
        return (-1 != GetLocaleIdx(szLocale));
300
 
}
301
 
 
302
 
int      GuiLanguage::GetLocaleIdx(const char *szLocale)
303
 
{
304
 
        for(unsigned int i=0; i<m_lstCatalogs.size(); i++)
305
 
        {
306
 
                const char *szCatalogEntry = m_lstCatalogs[i].c_str();
307
 
                if( 0 == strcmp(szCatalogEntry, szLocale) )
308
 
                        return i;
309
 
        }
310
 
 
311
 
        return -1; //not found
312
 
}
313
 
 
314
 
bool OnDirEnum(const char *szDir, void *data)
315
 
{
316
 
        std::vector<std::string> *lstDirs = (std::vector<std::string> *)data;   
317
 
        if(data)
318
 
        {
319
 
                //calcualte base name and add it into the list
320
 
                #ifdef _WIN32
321
 
                        //calculate base name
322
 
                        std::string strDir(szDir);
323
 
                        int nPos = strDir.find_last_of('\\');
324
 
                        if(nPos > 0)
325
 
                                strDir = strDir.substr(nPos+1, 1000);
326
 
                #else
327
 
                        std::string strDir(basename((char *)szDir));
328
 
                #endif  
329
 
                                
330
 
                lstDirs->push_back(strDir);
331
 
        }
332
 
        
333
 
        return true;    //keep enumerating
334
 
}
335
 
 
336
 
const char *GuiLanguage::QueryLocale(int category)
337
 
{
338
 
        //return current locale settings
339
 
        //WARNING: on Windows returns global system settings, not program ones
340
 
        return setlocale(category, NULL);
341
 
}
342
 
 
343
 
const char *GuiLanguage::GetLocale()
344
 
{
345
 
        return m_strCurLang.c_str();
346
 
}
347
 
 
 
1
////////////////////////////////////////////////////////////////////////////
 
2
// NoteCase notes manager project <http://notecase.sf.net>
 
3
//
 
4
// This code is licensed under BSD license.See "license.txt" for more details.
 
5
//
 
6
// File: Class for handling internationalisation issues (message catalogs)
 
7
////////////////////////////////////////////////////////////////////////////
 
8
 
 
9
#include "GuiLanguage.h"
 
10
#include <algorithm>
 
11
#include <gtk/gtk.h>
 
12
#ifdef ENABLE_NLS
 
13
#include <libintl.h>
 
14
#endif
 
15
#include "../lib/EnumDirectory.h"
 
16
 
 
17
#ifdef _WIN32
 
18
 #include <io.h> //access
 
19
 #include <windows.h> 
 
20
 #define access _access
 
21
#endif 
 
22
 
 
23
extern GuiLanguage g_lang;
 
24
 
 
25
bool OnDirEnum(const char *szDir, void *data);
 
26
#define ARRAY_COUNT(x) (sizeof(x)/sizeof(x[0]))
 
27
 
 
28
#ifndef _WIN32
 
29
        //define dummy versions of Windows language IDs
 
30
        #define LANG_AFRIKAANS  0
 
31
        #define LANG_ALBANIAN   0
 
32
        #define LANG_AMHARIC    0
 
33
        #define LANG_ARABIC             0
 
34
        #define LANG_ARMENIAN   0
 
35
        #define LANG_BASQUE     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
 
41
        #define LANG_CZECH              0
 
42
        #define LANG_DANISH             0
 
43
        #define LANG_DUTCH              0
 
44
        #define LANG_ENGLISH    0
 
45
        #define LANG_ESTONIAN   0
 
46
        #define LANG_ESPERANTO  0
 
47
        #define LANG_FARSI              0
 
48
        #define LANG_FRENCH             0
 
49
        #define LANG_FINNISH    0
 
50
        #define LANG_GEORGIAN   0
 
51
        #define LANG_GERMAN             0
 
52
        #define LANG_GREEK              0
 
53
        #define LANG_HEBREW             0
 
54
        #define LANG_HINDI              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
 
60
        #define LANG_KOREAN             0
 
61
        #define LANG_LATVIAN    0
 
62
        #define LANG_LITHUANIAN 0
 
63
        #define LANG_MACEDONIAN 0
 
64
        #define LANG_MONGOLIAN  0
 
65
        #define LANG_MALAY              0
 
66
        #define LANG_NORWEGIAN  0
 
67
        #define LANG_POLISH             0
 
68
        #define LANG_PORTUGUESE 0
 
69
        #define LANG_ROMANIAN   0
 
70
        #define LANG_RUSSIAN    0
 
71
        #define LANG_SERBIAN    0
 
72
        #define LANG_SLOVAK             0
 
73
        #define LANG_SLOVENIAN  0
 
74
        #define LANG_SPANISH    0
 
75
        #define LANG_SWEDISH    0
 
76
        #define LANG_TAMIL              0
 
77
        #define LANG_THAI               0
 
78
        #define LANG_TURKISH    0
 
79
        #define LANG_UKRAINIAN  0
 
80
        #define LANG_URDU               0
 
81
        #define LANG_VIETNAMESE 0
 
82
        #define LANG_CHINESE    0
 
83
 
 
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
 
111
#else
 
112
        //some codes are not defined in Visual C++ 6.0
 
113
        #ifndef LANG_AMHARIC
 
114
                #define LANG_AMHARIC 0x5e
 
115
        #endif
 
116
        #ifndef LANG_ESPERANTO
 
117
                #define LANG_ESPERANTO 0x8f
 
118
        #endif
 
119
        #ifndef LANG_MONGOLIAN
 
120
                #define LANG_MONGOLIAN 0x50
 
121
        #endif
 
122
        #ifndef SUBLANG_BENGALI_INDIA
 
123
                #define SUBLANG_BENGALI_INDIA 0x00
 
124
        #endif
 
125
        #ifndef SUBLANG_BENGALI_BANGLADESH
 
126
                #define SUBLANG_BENGALI_BANGLADESH 0x01
 
127
        #endif
 
128
#endif
 
129
 
 
130
 
 
131
typedef struct {
 
132
    const char *iso, *locale, *lang;
 
133
        int nLangID_W32;
 
134
        int nSubLangID_W32;
 
135
        bool bRTL;
 
136
} LanguageStruct;
 
137
 
 
138
//TOFIX add more languages, add native language name column?
 
139
static LanguageStruct isoLanguages[] = 
 
140
{
 
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
 
198
#ifdef _WIN32
 
199
    {"sr",      "sr_CS",        "Serbian (Latin)",      LANG_SERBIAN,   SUBLANG_SERBIAN_LATIN, false},
 
200
#else
 
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},
 
203
#endif
 
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}, 
 
216
};
 
217
 
 
218
// comparator class to sort locale list by language name (ascending)
 
219
class CmpLang
 
220
{
 
221
public:
 
222
        CmpLang(){};
 
223
        ~CmpLang(){};
 
224
 
 
225
        bool operator ()(const std::string &a, const std::string &b){
 
226
                #ifdef _WIN32
 
227
                        return (g_lang.GetLangName(a.c_str()) > g_lang.GetLangName(b.c_str()));
 
228
                #else
 
229
                        return (g_lang.GetLangName(a.c_str()) < g_lang.GetLangName(b.c_str()));
 
230
                #endif
 
231
        }
 
232
};
 
233
 
 
234
GuiLanguage::GuiLanguage(const char *szPackage, const char *szLocaleDir, const char *szSourceISO)
 
235
{
 
236
        m_strPackage    = szPackage;
 
237
        m_strLocaleDir  = szLocaleDir;
 
238
        m_strDefaultISO = (NULL != szSourceISO)? szSourceISO : "en";
 
239
        m_bCatalogsListed = false;
 
240
        m_nLangIdx = -1;
 
241
}
 
242
 
 
243
GuiLanguage::~GuiLanguage()
 
244
{
 
245
}
 
246
 
 
247
//maps from locale code to the language name
 
248
const char *GuiLanguage::GetLangName(const char *locale)
 
249
{
 
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;
 
255
 
 
256
    return "";    // not found
 
257
}
 
258
 
 
259
const char *GuiLanguage::GetLocaleCode(const char *iso)
 
260
{
 
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;
 
265
 
 
266
    return "";    // not found
 
267
}
 
268
 
 
269
int GuiLanguage::GetLocaleTableIdx(const char *locale)
 
270
{
 
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))
 
275
            return i;
 
276
 
 
277
    return -1;    // not found
 
278
}
 
279
 
 
280
void GuiLanguage::Initialize(const char *szIsoCode)
 
281
{
 
282
#ifdef ENABLE_NLS
 
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 ?
 
287
        }
 
288
 
 
289
        // convert language ISO code to locale code
 
290
        const char *szLocaleCode = GetLocaleCode(szIsoCode);
 
291
        if(strlen(szLocaleCode) > 0)
 
292
        {
 
293
                //ensure language catalog is available
 
294
                if( !IsLocaleAvailable(szIsoCode) &&
 
295
                        !IsLocaleAvailable(szLocaleCode) )
 
296
                {
 
297
                        szIsoCode        = m_strDefaultISO.c_str();     //default ISO (one used in the source code)
 
298
                        szLocaleCode = GetLocaleCode(szIsoCode);//default locale
 
299
                }
 
300
 
 
301
                //set language localisation for this program
 
302
                putenv( g_strconcat("LANG=", szLocaleCode, NULL) );
 
303
                setlocale(LC_ALL, "");
 
304
 
 
305
                m_nLangIdx = GetLocaleTableIdx(szIsoCode);
 
306
        #ifdef _WIN32
 
307
                //FIX for Windows code
 
308
                if(m_nLangIdx >= 0)
 
309
                        SetThreadLocale(MAKELCID(MAKELANGID(isoLanguages[m_nLangIdx].nLangID_W32, isoLanguages[m_nLangIdx].nSubLangID_W32), SORT_DEFAULT));
 
310
        #endif
 
311
        }
 
312
 
 
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());
 
317
 
 
318
        //store locale code for later lookup
 
319
        m_strCurLang = szIsoCode;
 
320
#endif
 
321
}
 
322
 
 
323
void GuiLanguage::ListAvailableCatalogs()
 
324
{
 
325
        if(m_bCatalogsListed)
 
326
                return;
 
327
        m_bCatalogsListed = true;
 
328
        
 
329
        //clear catalog list
 
330
        m_lstCatalogs.erase(m_lstCatalogs.begin(), m_lstCatalogs.end());        //empty the list
 
331
 
 
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);
 
335
        
 
336
        //store each locale containing catalog for current package
 
337
        for( unsigned int i=0; i<lstDirs.size(); i++)
 
338
        {
 
339
                //check if message catalog exists for given locale subdirectory
 
340
                std::string strCatalog;
 
341
                #ifdef _WIN32
 
342
                        strCatalog  = m_strLocaleDir;
 
343
                        strCatalog += lstDirs[i];
 
344
                        strCatalog += "\\LC_MESSAGES\\";
 
345
                        strCatalog += m_strPackage;
 
346
                        strCatalog += ".mo";
 
347
                #else
 
348
                        char szBuffer[1024];
 
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;
 
351
                #endif
 
352
                                
 
353
                if(0 == access(strCatalog.c_str(), 00))
 
354
                        m_lstCatalogs.push_back(lstDirs[i]);    //add locale into the list of available catalogs
 
355
        }
 
356
 
 
357
        //sort list by language names
 
358
        std::sort(m_lstCatalogs.begin(), m_lstCatalogs.end(), CmpLang());
 
359
}
 
360
 
 
361
bool GuiLanguage::IsLocaleAvailable(const char *szLocale)
 
362
{
 
363
        std::string strCatalog;
 
364
#ifdef _WIN32
 
365
        strCatalog  = m_strLocaleDir;
 
366
        strCatalog += szLocale;
 
367
        strCatalog += "\\LC_MESSAGES\\";
 
368
        strCatalog += m_strPackage;
 
369
        strCatalog += ".mo";
 
370
#else
 
371
        char szBuffer[1024];
 
372
        snprintf(szBuffer, sizeof(szBuffer), "%s/%s/LC_MESSAGES/%s.mo",m_strLocaleDir.c_str(), szLocale, m_strPackage.c_str());
 
373
        strCatalog  = szBuffer;
 
374
#endif                          
 
375
        
 
376
        return (0 == access(strCatalog.c_str(), 00));
 
377
        //return (-1 != GetLocaleIdx(szLocale)); //old implementation (slows the program startup)
 
378
}
 
379
 
 
380
int     GuiLanguage::GetLocaleIdx(const char *szLocale)
 
381
{
 
382
        for(unsigned int i=0; i<m_lstCatalogs.size(); i++)
 
383
        {
 
384
                const char *szCatalogEntry = m_lstCatalogs[i].c_str();
 
385
                if( 0 == strcmp(szCatalogEntry, szLocale) )
 
386
                        return i;
 
387
        }
 
388
 
 
389
        return -1; //not found
 
390
}
 
391
 
 
392
bool OnDirEnum(const char *szDir, void *data)
 
393
{
 
394
        std::vector<std::string> *lstDirs = (std::vector<std::string> *)data;   
 
395
        if(data)
 
396
        {
 
397
                //calculate directory base name and add it into the list
 
398
                #ifdef _WIN32
 
399
                        //calculate base name
 
400
                        std::string strDir(szDir);
 
401
                        int nPos = strDir.find_last_of('\\');
 
402
                        if(nPos > 0)
 
403
                                strDir = strDir.substr(nPos+1, 1000);
 
404
                #else
 
405
                        std::string strDir(basename((char *)szDir));
 
406
                #endif  
 
407
                                
 
408
                lstDirs->push_back(strDir);
 
409
        }
 
410
        
 
411
        return true;    //keep enumerating
 
412
}
 
413
 
 
414
const char *GuiLanguage::QueryLocale(int category)
 
415
{
 
416
        //return current locale settings
 
417
        //WARNING: on Windows this returns global system settings, not program's
 
418
        return setlocale(category, NULL);
 
419
}
 
420
 
 
421
const char *GuiLanguage::GetLocale()
 
422
{
 
423
        return m_strCurLang.c_str();
 
424
}
 
425
 
 
426
bool GuiLanguage::IsCurLangRTL()
 
427
{
 
428
        if(m_nLangIdx >= 0)
 
429
                return isoLanguages[m_nLangIdx].bRTL;
 
430
        return false;
 
431
}