~ubuntu-branches/ubuntu/raring/notecase/raring

« back to all changes in this revision

Viewing changes to src/gui/GuiLanguage.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Nathan Handler
  • Date: 2008-12-21 13:09:58 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20081221130958-0ri77h0x7j1dclkq
Tags: 1.9.8-0ubuntu1
New upstream release (LP: #307752)

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