1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/intl.cpp 
   3 // Purpose:     Internationalization and localisation for wxWidgets 
   4 // Author:      Vadim Zeitlin 
   5 // Modified by: Michael N. Filippov <michael@idisys.iae.nsk.su> 
   6 //              (2003/09/30 - PluralForms support) 
   9 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 // ============================================================================ 
  15 // ============================================================================ 
  17 // ---------------------------------------------------------------------------- 
  19 // ---------------------------------------------------------------------------- 
  21 // For compilers that support precompilation, includes "wx.h". 
  22 #include "wx/wxprec.h" 
  29 // The following define is needed by Innotek's libc to 
  30 // make the definition of struct localeconv available. 
  31 #define __INTERNAL_DEFS 
  37     #include "wx/dynarray.h" 
  38     #include "wx/string.h" 
  43     #include "wx/hashmap.h" 
  44     #include "wx/module.h" 
  54 #ifdef HAVE_LANGINFO_H 
  59     #include "wx/msw/private.h" 
  60 #elif defined(__UNIX_LIKE__) 
  61     #include "wx/fontmap.h"         // for CharsetToEncoding() 
  65 #include "wx/filename.h" 
  66 #include "wx/tokenzr.h" 
  67 #include "wx/fontmap.h" 
  68 #include "wx/scopedptr.h" 
  69 #include "wx/apptrait.h" 
  70 #include "wx/stdpaths.h" 
  71 #include "wx/hashset.h" 
  73 #if defined(__WXOSX__) 
  74     #include "wx/osx/core/cfref.h" 
  75     #include <CoreFoundation/CFLocale.h> 
  76     #include <CoreFoundation/CFDateFormatter.h> 
  77     #include "wx/osx/core/cfstring.h" 
  80 // ---------------------------------------------------------------------------- 
  82 // ---------------------------------------------------------------------------- 
  84 // this should *not* be wxChar, this type must have exactly 8 bits! 
  85 typedef wxUint8 size_t8
; 
  86 typedef wxUint32 size_t32
; 
  88 // ---------------------------------------------------------------------------- 
  90 // ---------------------------------------------------------------------------- 
  92 // magic number identifying the .mo format file 
  93 const size_t32 MSGCATALOG_MAGIC    
= 0x950412de; 
  94 const size_t32 MSGCATALOG_MAGIC_SW 
= 0xde120495; 
  96 // the constants describing the format of ll_CC locale string 
  97 static const size_t LEN_LANG 
= 2; 
  98 static const size_t LEN_SUBLANG 
= 2; 
  99 static const size_t LEN_FULL 
= LEN_LANG 
+ 1 + LEN_SUBLANG
; // 1 for '_' 
 101 #define TRACE_I18N wxS("i18n") 
 103 // ---------------------------------------------------------------------------- 
 105 // ---------------------------------------------------------------------------- 
 107 static wxLocale 
*wxSetLocale(wxLocale 
*pLocale
); 
 112 // get just the language part 
 113 inline wxString 
ExtractLang(const wxString
& langFull
) 
 115     return langFull
.Left(LEN_LANG
); 
 118 // helper functions of GetSystemLanguage() 
 121 // get everything else (including the leading '_') 
 122 inline wxString 
ExtractNotLang(const wxString
& langFull
) 
 124     return langFull
.Mid(LEN_LANG
); 
 129 } // anonymous namespace 
 131 // ---------------------------------------------------------------------------- 
 132 // Plural forms parser 
 133 // ---------------------------------------------------------------------------- 
 139     LogicalOrExpression '?' Expression ':' Expression 
 143     LogicalAndExpression "||" LogicalOrExpression   // to (a || b) || c 
 146 LogicalAndExpression: 
 147     EqualityExpression "&&" LogicalAndExpression    // to (a && b) && c 
 151     RelationalExpression "==" RelationalExperession 
 152     RelationalExpression "!=" RelationalExperession 
 155 RelationalExpression: 
 156     MultiplicativeExpression '>' MultiplicativeExpression 
 157     MultiplicativeExpression '<' MultiplicativeExpression 
 158     MultiplicativeExpression ">=" MultiplicativeExpression 
 159     MultiplicativeExpression "<=" MultiplicativeExpression 
 160     MultiplicativeExpression 
 162 MultiplicativeExpression: 
 163     PmExpression '%' PmExpression 
 172 class wxPluralFormsToken
 
 177         T_ERROR
, T_EOF
, T_NUMBER
, T_N
, T_PLURAL
, T_NPLURALS
, T_EQUAL
, T_ASSIGN
, 
 178         T_GREATER
, T_GREATER_OR_EQUAL
, T_LESS
, T_LESS_OR_EQUAL
, 
 179         T_REMINDER
, T_NOT_EQUAL
, 
 180         T_LOGICAL_AND
, T_LOGICAL_OR
, T_QUESTION
, T_COLON
, T_SEMICOLON
, 
 181         T_LEFT_BRACKET
, T_RIGHT_BRACKET
 
 183     Type 
type() const { return m_type
; } 
 184     void setType(Type type
) { m_type 
= type
; } 
 187     Number 
number() const { return m_number
; } 
 188     void setNumber(Number num
) { m_number 
= num
; } 
 195 class wxPluralFormsScanner
 
 198     wxPluralFormsScanner(const char* s
); 
 199     const wxPluralFormsToken
& token() const { return m_token
; } 
 200     bool nextToken();  // returns false if error 
 203     wxPluralFormsToken m_token
; 
 206 wxPluralFormsScanner::wxPluralFormsScanner(const char* s
) : m_s(s
) 
 211 bool wxPluralFormsScanner::nextToken() 
 213     wxPluralFormsToken::Type type 
= wxPluralFormsToken::T_ERROR
; 
 214     while (isspace((unsigned char) *m_s
)) 
 220         type 
= wxPluralFormsToken::T_EOF
; 
 222     else if (isdigit((unsigned char) *m_s
)) 
 224         wxPluralFormsToken::Number number 
= *m_s
++ - '0'; 
 225         while (isdigit((unsigned char) *m_s
)) 
 227             number 
= number 
* 10 + (*m_s
++ - '0'); 
 229         m_token
.setNumber(number
); 
 230         type 
= wxPluralFormsToken::T_NUMBER
; 
 232     else if (isalpha((unsigned char) *m_s
)) 
 234         const char* begin 
= m_s
++; 
 235         while (isalnum((unsigned char) *m_s
)) 
 239         size_t size 
= m_s 
- begin
; 
 240         if (size 
== 1 && memcmp(begin
, "n", size
) == 0) 
 242             type 
= wxPluralFormsToken::T_N
; 
 244         else if (size 
== 6 && memcmp(begin
, "plural", size
) == 0) 
 246             type 
= wxPluralFormsToken::T_PLURAL
; 
 248         else if (size 
== 8 && memcmp(begin
, "nplurals", size
) == 0) 
 250             type 
= wxPluralFormsToken::T_NPLURALS
; 
 253     else if (*m_s 
== '=') 
 259             type 
= wxPluralFormsToken::T_EQUAL
; 
 263             type 
= wxPluralFormsToken::T_ASSIGN
; 
 266     else if (*m_s 
== '>') 
 272             type 
= wxPluralFormsToken::T_GREATER_OR_EQUAL
; 
 276             type 
= wxPluralFormsToken::T_GREATER
; 
 279     else if (*m_s 
== '<') 
 285             type 
= wxPluralFormsToken::T_LESS_OR_EQUAL
; 
 289             type 
= wxPluralFormsToken::T_LESS
; 
 292     else if (*m_s 
== '%') 
 295         type 
= wxPluralFormsToken::T_REMINDER
; 
 297     else if (*m_s 
== '!' && m_s
[1] == '=') 
 300         type 
= wxPluralFormsToken::T_NOT_EQUAL
; 
 302     else if (*m_s 
== '&' && m_s
[1] == '&') 
 305         type 
= wxPluralFormsToken::T_LOGICAL_AND
; 
 307     else if (*m_s 
== '|' && m_s
[1] == '|') 
 310         type 
= wxPluralFormsToken::T_LOGICAL_OR
; 
 312     else if (*m_s 
== '?') 
 315         type 
= wxPluralFormsToken::T_QUESTION
; 
 317     else if (*m_s 
== ':') 
 320         type 
= wxPluralFormsToken::T_COLON
; 
 321     } else if (*m_s 
== ';') { 
 323         type 
= wxPluralFormsToken::T_SEMICOLON
; 
 325     else if (*m_s 
== '(') 
 328         type 
= wxPluralFormsToken::T_LEFT_BRACKET
; 
 330     else if (*m_s 
== ')') 
 333         type 
= wxPluralFormsToken::T_RIGHT_BRACKET
; 
 335     m_token
.setType(type
); 
 336     return type 
!= wxPluralFormsToken::T_ERROR
; 
 339 class wxPluralFormsNode
; 
 341 // NB: Can't use wxDEFINE_SCOPED_PTR_TYPE because wxPluralFormsNode is not 
 342 //     fully defined yet: 
 343 class wxPluralFormsNodePtr
 
 346     wxPluralFormsNodePtr(wxPluralFormsNode 
*p 
= NULL
) : m_p(p
) {} 
 347     ~wxPluralFormsNodePtr(); 
 348     wxPluralFormsNode
& operator*() const { return *m_p
; } 
 349     wxPluralFormsNode
* operator->() const { return m_p
; } 
 350     wxPluralFormsNode
* get() const { return m_p
; } 
 351     wxPluralFormsNode
* release(); 
 352     void reset(wxPluralFormsNode 
*p
); 
 355     wxPluralFormsNode 
*m_p
; 
 358 class wxPluralFormsNode
 
 361     wxPluralFormsNode(const wxPluralFormsToken
& token
) : m_token(token
) {} 
 362     const wxPluralFormsToken
& token() const { return m_token
; } 
 363     const wxPluralFormsNode
* node(size_t i
) const 
 364         { return m_nodes
[i
].get(); } 
 365     void setNode(size_t i
, wxPluralFormsNode
* n
); 
 366     wxPluralFormsNode
* releaseNode(size_t i
); 
 367     wxPluralFormsToken::Number 
evaluate(wxPluralFormsToken::Number n
) const; 
 370     wxPluralFormsToken m_token
; 
 371     wxPluralFormsNodePtr m_nodes
[3]; 
 374 wxPluralFormsNodePtr::~wxPluralFormsNodePtr() 
 378 wxPluralFormsNode
* wxPluralFormsNodePtr::release() 
 380     wxPluralFormsNode 
*p 
= m_p
; 
 384 void wxPluralFormsNodePtr::reset(wxPluralFormsNode 
*p
) 
 394 void wxPluralFormsNode::setNode(size_t i
, wxPluralFormsNode
* n
) 
 399 wxPluralFormsNode
*  wxPluralFormsNode::releaseNode(size_t i
) 
 401     return m_nodes
[i
].release(); 
 404 wxPluralFormsToken::Number
 
 405 wxPluralFormsNode::evaluate(wxPluralFormsToken::Number n
) const 
 407     switch (token().type()) 
 410         case wxPluralFormsToken::T_NUMBER
: 
 411             return token().number(); 
 412         case wxPluralFormsToken::T_N
: 
 415         case wxPluralFormsToken::T_EQUAL
: 
 416             return node(0)->evaluate(n
) == node(1)->evaluate(n
); 
 417         case wxPluralFormsToken::T_NOT_EQUAL
: 
 418             return node(0)->evaluate(n
) != node(1)->evaluate(n
); 
 419         case wxPluralFormsToken::T_GREATER
: 
 420             return node(0)->evaluate(n
) > node(1)->evaluate(n
); 
 421         case wxPluralFormsToken::T_GREATER_OR_EQUAL
: 
 422             return node(0)->evaluate(n
) >= node(1)->evaluate(n
); 
 423         case wxPluralFormsToken::T_LESS
: 
 424             return node(0)->evaluate(n
) < node(1)->evaluate(n
); 
 425         case wxPluralFormsToken::T_LESS_OR_EQUAL
: 
 426             return node(0)->evaluate(n
) <= node(1)->evaluate(n
); 
 427         case wxPluralFormsToken::T_REMINDER
: 
 429                 wxPluralFormsToken::Number number 
= node(1)->evaluate(n
); 
 432                     return node(0)->evaluate(n
) % number
; 
 439         case wxPluralFormsToken::T_LOGICAL_AND
: 
 440             return node(0)->evaluate(n
) && node(1)->evaluate(n
); 
 441         case wxPluralFormsToken::T_LOGICAL_OR
: 
 442             return node(0)->evaluate(n
) || node(1)->evaluate(n
); 
 444         case wxPluralFormsToken::T_QUESTION
: 
 445             return node(0)->evaluate(n
) 
 446                 ? node(1)->evaluate(n
) 
 447                 : node(2)->evaluate(n
); 
 454 class wxPluralFormsCalculator
 
 457     wxPluralFormsCalculator() : m_nplurals(0), m_plural(0) {} 
 459     // input: number, returns msgstr index 
 460     int evaluate(int n
) const; 
 462     // input: text after "Plural-Forms:" (e.g. "nplurals=2; plural=(n != 1);"), 
 463     // if s == 0, creates default handler 
 464     // returns 0 if error 
 465     static wxPluralFormsCalculator
* make(const char* s 
= 0); 
 467     ~wxPluralFormsCalculator() {} 
 469     void  init(wxPluralFormsToken::Number nplurals
, wxPluralFormsNode
* plural
); 
 472     wxPluralFormsToken::Number m_nplurals
; 
 473     wxPluralFormsNodePtr m_plural
; 
 476 wxDEFINE_SCOPED_PTR_TYPE(wxPluralFormsCalculator
) 
 478 void wxPluralFormsCalculator::init(wxPluralFormsToken::Number nplurals
, 
 479                                 wxPluralFormsNode
* plural
) 
 481     m_nplurals 
= nplurals
; 
 482     m_plural
.reset(plural
); 
 485 int wxPluralFormsCalculator::evaluate(int n
) const 
 487     if (m_plural
.get() == 0) 
 491     wxPluralFormsToken::Number number 
= m_plural
->evaluate(n
); 
 492     if (number 
< 0 || number 
> m_nplurals
) 
 500 class wxPluralFormsParser
 
 503     wxPluralFormsParser(wxPluralFormsScanner
& scanner
) : m_scanner(scanner
) {} 
 504     bool parse(wxPluralFormsCalculator
& rCalculator
); 
 507     wxPluralFormsNode
* parsePlural(); 
 508     // stops at T_SEMICOLON, returns 0 if error 
 509     wxPluralFormsScanner
& m_scanner
; 
 510     const wxPluralFormsToken
& token() const; 
 513     wxPluralFormsNode
* expression(); 
 514     wxPluralFormsNode
* logicalOrExpression(); 
 515     wxPluralFormsNode
* logicalAndExpression(); 
 516     wxPluralFormsNode
* equalityExpression(); 
 517     wxPluralFormsNode
* multiplicativeExpression(); 
 518     wxPluralFormsNode
* relationalExpression(); 
 519     wxPluralFormsNode
* pmExpression(); 
 522 bool wxPluralFormsParser::parse(wxPluralFormsCalculator
& rCalculator
) 
 524     if (token().type() != wxPluralFormsToken::T_NPLURALS
) 
 528     if (token().type() != wxPluralFormsToken::T_ASSIGN
) 
 532     if (token().type() != wxPluralFormsToken::T_NUMBER
) 
 534     wxPluralFormsToken::Number nplurals 
= token().number(); 
 537     if (token().type() != wxPluralFormsToken::T_SEMICOLON
) 
 541     if (token().type() != wxPluralFormsToken::T_PLURAL
) 
 545     if (token().type() != wxPluralFormsToken::T_ASSIGN
) 
 549     wxPluralFormsNode
* plural 
= parsePlural(); 
 552     if (token().type() != wxPluralFormsToken::T_SEMICOLON
) 
 556     if (token().type() != wxPluralFormsToken::T_EOF
) 
 558     rCalculator
.init(nplurals
, plural
); 
 562 wxPluralFormsNode
* wxPluralFormsParser::parsePlural() 
 564     wxPluralFormsNode
* p 
= expression(); 
 569     wxPluralFormsNodePtr 
n(p
); 
 570     if (token().type() != wxPluralFormsToken::T_SEMICOLON
) 
 577 const wxPluralFormsToken
& wxPluralFormsParser::token() const 
 579     return m_scanner
.token(); 
 582 bool wxPluralFormsParser::nextToken() 
 584     if (!m_scanner
.nextToken()) 
 589 wxPluralFormsNode
* wxPluralFormsParser::expression() 
 591     wxPluralFormsNode
* p 
= logicalOrExpression(); 
 594     wxPluralFormsNodePtr 
n(p
); 
 595     if (token().type() == wxPluralFormsToken::T_QUESTION
) 
 597         wxPluralFormsNodePtr 
qn(new wxPluralFormsNode(token())); 
 608         if (token().type() != wxPluralFormsToken::T_COLON
) 
 622         qn
->setNode(0, n
.release()); 
 628 wxPluralFormsNode
*wxPluralFormsParser::logicalOrExpression() 
 630     wxPluralFormsNode
* p 
= logicalAndExpression(); 
 633     wxPluralFormsNodePtr 
ln(p
); 
 634     if (token().type() == wxPluralFormsToken::T_LOGICAL_OR
) 
 636         wxPluralFormsNodePtr 
un(new wxPluralFormsNode(token())); 
 641         p 
= logicalOrExpression(); 
 646         wxPluralFormsNodePtr 
rn(p
);    // right 
 647         if (rn
->token().type() == wxPluralFormsToken::T_LOGICAL_OR
) 
 649             // see logicalAndExpression comment 
 650             un
->setNode(0, ln
.release()); 
 651             un
->setNode(1, rn
->releaseNode(0)); 
 652             rn
->setNode(0, un
.release()); 
 657         un
->setNode(0, ln
.release()); 
 658         un
->setNode(1, rn
.release()); 
 664 wxPluralFormsNode
* wxPluralFormsParser::logicalAndExpression() 
 666     wxPluralFormsNode
* p 
= equalityExpression(); 
 669     wxPluralFormsNodePtr 
ln(p
);   // left 
 670     if (token().type() == wxPluralFormsToken::T_LOGICAL_AND
) 
 672         wxPluralFormsNodePtr 
un(new wxPluralFormsNode(token()));  // up 
 677         p 
= logicalAndExpression(); 
 682         wxPluralFormsNodePtr 
rn(p
);    // right 
 683         if (rn
->token().type() == wxPluralFormsToken::T_LOGICAL_AND
) 
 685 // transform 1 && (2 && 3) -> (1 && 2) && 3 
 689             un
->setNode(0, ln
.release()); 
 690             un
->setNode(1, rn
->releaseNode(0)); 
 691             rn
->setNode(0, un
.release()); 
 695         un
->setNode(0, ln
.release()); 
 696         un
->setNode(1, rn
.release()); 
 702 wxPluralFormsNode
* wxPluralFormsParser::equalityExpression() 
 704     wxPluralFormsNode
* p 
= relationalExpression(); 
 707     wxPluralFormsNodePtr 
n(p
); 
 708     if (token().type() == wxPluralFormsToken::T_EQUAL
 
 709         || token().type() == wxPluralFormsToken::T_NOT_EQUAL
) 
 711         wxPluralFormsNodePtr 
qn(new wxPluralFormsNode(token())); 
 716         p 
= relationalExpression(); 
 722         qn
->setNode(0, n
.release()); 
 728 wxPluralFormsNode
* wxPluralFormsParser::relationalExpression() 
 730     wxPluralFormsNode
* p 
= multiplicativeExpression(); 
 733     wxPluralFormsNodePtr 
n(p
); 
 734     if (token().type() == wxPluralFormsToken::T_GREATER
 
 735             || token().type() == wxPluralFormsToken::T_LESS
 
 736             || token().type() == wxPluralFormsToken::T_GREATER_OR_EQUAL
 
 737             || token().type() == wxPluralFormsToken::T_LESS_OR_EQUAL
) 
 739         wxPluralFormsNodePtr 
qn(new wxPluralFormsNode(token())); 
 744         p 
= multiplicativeExpression(); 
 750         qn
->setNode(0, n
.release()); 
 756 wxPluralFormsNode
* wxPluralFormsParser::multiplicativeExpression() 
 758     wxPluralFormsNode
* p 
= pmExpression(); 
 761     wxPluralFormsNodePtr 
n(p
); 
 762     if (token().type() == wxPluralFormsToken::T_REMINDER
) 
 764         wxPluralFormsNodePtr 
qn(new wxPluralFormsNode(token())); 
 775         qn
->setNode(0, n
.release()); 
 781 wxPluralFormsNode
* wxPluralFormsParser::pmExpression() 
 783     wxPluralFormsNodePtr n
; 
 784     if (token().type() == wxPluralFormsToken::T_N
 
 785         || token().type() == wxPluralFormsToken::T_NUMBER
) 
 787         n
.reset(new wxPluralFormsNode(token())); 
 793     else if (token().type() == wxPluralFormsToken::T_LEFT_BRACKET
) { 
 798         wxPluralFormsNode
* p 
= expression(); 
 804         if (token().type() != wxPluralFormsToken::T_RIGHT_BRACKET
) 
 820 wxPluralFormsCalculator
* wxPluralFormsCalculator::make(const char* s
) 
 822     wxPluralFormsCalculatorPtr 
calculator(new wxPluralFormsCalculator
); 
 825         wxPluralFormsScanner 
scanner(s
); 
 826         wxPluralFormsParser 
p(scanner
); 
 827         if (!p
.parse(*calculator
)) 
 832     return calculator
.release(); 
 838 // ---------------------------------------------------------------------------- 
 839 // wxMsgCatalogFile corresponds to one disk-file message catalog. 
 841 // This is a "low-level" class and is used only by wxMsgCatalog 
 842 // NOTE: for the documentation of the binary catalog (.MO) files refer to 
 843 //       the GNU gettext manual: 
 844 //       http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html 
 845 // ---------------------------------------------------------------------------- 
 847 WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxString
, wxMessagesHash
); 
 849 class wxMsgCatalogFile
 
 856     // load the catalog from disk 
 857     bool Load(const wxString
& filename
, 
 858               wxPluralFormsCalculatorPtr
& rPluralFormsCalculator
); 
 860     // fills the hash with string-translation pairs 
 861     bool FillHash(wxMessagesHash
& hash
, const wxString
& msgIdCharset
) const; 
 863     // return the charset of the strings in this catalog or empty string if 
 865     wxString 
GetCharset() const { return m_charset
; } 
 868     // this implementation is binary compatible with GNU gettext() version 0.10 
 870     // an entry in the string table 
 871     struct wxMsgTableEntry
 
 873         size_t32   nLen
;           // length of the string 
 874         size_t32   ofsString
;      // pointer to the string 
 877     // header of a .mo file 
 878     struct wxMsgCatalogHeader
 
 880         size_t32  magic
,          // offset +00:  magic id 
 881                   revision
,       //        +04:  revision 
 882                   numStrings
;     //        +08:  number of strings in the file 
 883         size_t32  ofsOrigTable
,   //        +0C:  start of original string table 
 884                   ofsTransTable
;  //        +10:  start of translated string table 
 885         size_t32  nHashSize
,      //        +14:  hash table size 
 886                   ofsHashTable
;   //        +18:  offset of hash table start 
 889     // all data is stored here 
 890     wxMemoryBuffer m_data
; 
 893     size_t32          m_numStrings
;   // number of strings in this domain 
 894     wxMsgTableEntry  
*m_pOrigTable
,   // pointer to original   strings 
 895                      *m_pTransTable
;  //            translated 
 897     wxString m_charset
;               // from the message catalog header 
 900     // swap the 2 halves of 32 bit integer if needed 
 901     size_t32 
Swap(size_t32 ui
) const 
 903         return m_bSwapped 
? (ui 
<< 24) | ((ui 
& 0xff00) << 8) | 
 904                             ((ui 
>> 8) & 0xff00) | (ui 
>> 24) 
 908     // just return the pointer to the start of the data as "char *" to 
 909     // facilitate doing pointer arithmetic with it 
 910     char *StringData() const 
 912         return static_cast<char *>(m_data
.GetData()); 
 915     const char *StringAtOfs(wxMsgTableEntry 
*pTable
, size_t32 n
) const 
 917         const wxMsgTableEntry 
* const ent 
= pTable 
+ n
; 
 919         // this check could fail for a corrupt message catalog 
 920         size_t32 ofsString 
= Swap(ent
->ofsString
); 
 921         if ( ofsString 
+ Swap(ent
->nLen
) > m_data
.GetDataLen()) 
 926         return StringData() + ofsString
; 
 929     bool m_bSwapped
;   // wrong endianness? 
 931     wxDECLARE_NO_COPY_CLASS(wxMsgCatalogFile
); 
 935 // ---------------------------------------------------------------------------- 
 936 // wxMsgCatalog corresponds to one loaded message catalog. 
 938 // This is a "low-level" class and is used only by wxLocale (that's why 
 939 // it's designed to be stored in a linked list) 
 940 // ---------------------------------------------------------------------------- 
 946     wxMsgCatalog() { m_conv 
= NULL
; } 
 950     // load the catalog from disk 
 951     bool Load(const wxString
& filename
, 
 952               const wxString
& domain
, 
 953               const wxString
& msgIdCharset
); 
 955     // get name of the catalog 
 956     wxString 
GetDomain() const { return m_domain
; } 
 958     // get the translated string: returns NULL if not found 
 959     const wxString 
*GetString(const wxString
& sz
, size_t n 
= size_t(-1)) const; 
 961     // public variable pointing to the next element in a linked list (or NULL) 
 962     wxMsgCatalog 
*m_pNext
; 
 965     wxMessagesHash  m_messages
; // all messages in the catalog 
 966     wxString        m_domain
;   // name of the domain 
 969     // the conversion corresponding to this catalog charset if we installed it 
 974     wxPluralFormsCalculatorPtr  m_pluralFormsCalculator
; 
 978 // ============================================================================ 
 980 // ============================================================================ 
 982 // ---------------------------------------------------------------------------- 
 984 // ---------------------------------------------------------------------------- 
 988 // helper used by wxLanguageInfo::GetLocaleName() and elsewhere to determine 
 989 // whether the locale is Unicode-only (it is if this function returns empty 
 991 static wxString 
wxGetANSICodePageForLocale(LCID lcid
) 
 996     if ( ::GetLocaleInfo(lcid
, LOCALE_IDEFAULTANSICODEPAGE
, 
 997                         buffer
, WXSIZEOF(buffer
)) > 0 ) 
 999         if ( buffer
[0] != wxT('0') || buffer
[1] != wxT('\0') ) 
1001         //else: this locale doesn't use ANSI code page 
1007 wxUint32 
wxLanguageInfo::GetLCID() const 
1009     return MAKELCID(MAKELANGID(WinLang
, WinSublang
), SORT_DEFAULT
); 
1012 wxString 
wxLanguageInfo::GetLocaleName() const 
1016     const LCID lcid 
= GetLCID(); 
1019     buffer
[0] = wxT('\0'); 
1020     if ( !::GetLocaleInfo(lcid
, LOCALE_SENGLANGUAGE
, buffer
, WXSIZEOF(buffer
)) ) 
1022         wxLogLastError(wxT("GetLocaleInfo(LOCALE_SENGLANGUAGE)")); 
1027     if ( ::GetLocaleInfo(lcid
, LOCALE_SENGCOUNTRY
, 
1028                         buffer
, WXSIZEOF(buffer
)) > 0 ) 
1030         locale 
<< wxT('_') << buffer
; 
1033     const wxString cp 
= wxGetANSICodePageForLocale(lcid
); 
1036         locale 
<< wxT('.') << cp
; 
1044 // ---------------------------------------------------------------------------- 
1045 // wxMsgCatalogFile clas 
1046 // ---------------------------------------------------------------------------- 
1048 wxMsgCatalogFile::wxMsgCatalogFile() 
1052 wxMsgCatalogFile::~wxMsgCatalogFile() 
1056 // open disk file and read in it's contents 
1057 bool wxMsgCatalogFile::Load(const wxString
& filename
, 
1058                             wxPluralFormsCalculatorPtr
& rPluralFormsCalculator
) 
1060     wxFile 
fileMsg(filename
); 
1061     if ( !fileMsg
.IsOpened() ) 
1064     // get the file size (assume it is less than 4Gb...) 
1065     wxFileOffset lenFile 
= fileMsg
.Length(); 
1066     if ( lenFile 
== wxInvalidOffset 
) 
1069     size_t nSize 
= wx_truncate_cast(size_t, lenFile
); 
1070     wxASSERT_MSG( nSize 
== lenFile 
+ size_t(0), wxS("message catalog bigger than 4GB?") ); 
1072     // read the whole file in memory 
1073     if ( fileMsg
.Read(m_data
.GetWriteBuf(nSize
), nSize
) != lenFile 
) 
1076     m_data
.UngetWriteBuf(nSize
); 
1080     bool bValid 
= m_data
.GetDataLen() > sizeof(wxMsgCatalogHeader
); 
1082     const wxMsgCatalogHeader 
*pHeader 
= (wxMsgCatalogHeader 
*)m_data
.GetData(); 
1084         // we'll have to swap all the integers if it's true 
1085         m_bSwapped 
= pHeader
->magic 
== MSGCATALOG_MAGIC_SW
; 
1087         // check the magic number 
1088         bValid 
= m_bSwapped 
|| pHeader
->magic 
== MSGCATALOG_MAGIC
; 
1092         // it's either too short or has incorrect magic number 
1093         wxLogWarning(_("'%s' is not a valid message catalog."), filename
.c_str()); 
1099     m_numStrings  
= Swap(pHeader
->numStrings
); 
1100     m_pOrigTable  
= (wxMsgTableEntry 
*)(StringData() + 
1101                     Swap(pHeader
->ofsOrigTable
)); 
1102     m_pTransTable 
= (wxMsgTableEntry 
*)(StringData() + 
1103                     Swap(pHeader
->ofsTransTable
)); 
1105     // now parse catalog's header and try to extract catalog charset and 
1106     // plural forms formula from it: 
1108     const char* headerData 
= StringAtOfs(m_pOrigTable
, 0); 
1109     if ( headerData 
&& headerData
[0] == '\0' ) 
1111         // Extract the charset: 
1112         const char * const header 
= StringAtOfs(m_pTransTable
, 0); 
1114             cset 
= strstr(header
, "Content-Type: text/plain; charset="); 
1117             cset 
+= 34; // strlen("Content-Type: text/plain; charset=") 
1119             const char * const csetEnd 
= strchr(cset
, '\n'); 
1122                 m_charset 
= wxString(cset
, csetEnd 
- cset
); 
1123                 if ( m_charset 
== wxS("CHARSET") ) 
1125                     // "CHARSET" is not valid charset, but lazy translator 
1130         // else: incorrectly filled Content-Type header 
1132         // Extract plural forms: 
1133         const char * plurals 
= strstr(header
, "Plural-Forms:"); 
1136             plurals 
+= 13; // strlen("Plural-Forms:") 
1137             const char * const pluralsEnd 
= strchr(plurals
, '\n'); 
1140                 const size_t pluralsLen 
= pluralsEnd 
- plurals
; 
1141                 wxCharBuffer 
buf(pluralsLen
); 
1142                 strncpy(buf
.data(), plurals
, pluralsLen
); 
1143                 wxPluralFormsCalculator 
* const 
1144                     pCalculator 
= wxPluralFormsCalculator::make(buf
); 
1147                     rPluralFormsCalculator
.reset(pCalculator
); 
1151                     wxLogVerbose(_("Failed to parse Plural-Forms: '%s'"), 
1157         if ( !rPluralFormsCalculator
.get() ) 
1158             rPluralFormsCalculator
.reset(wxPluralFormsCalculator::make()); 
1161     // everything is fine 
1165 bool wxMsgCatalogFile::FillHash(wxMessagesHash
& hash
, 
1166                                 const wxString
& msgIdCharset
) const 
1168     wxUnusedVar(msgIdCharset
); // silence warning in Unicode build 
1170     // conversion to use to convert catalog strings to the GUI encoding 
1171     wxMBConv 
*inputConv 
= NULL
; 
1172     wxMBConv 
*inputConvPtr 
= NULL
; // same as inputConv but safely deleteable 
1174     if ( !m_charset
.empty() ) 
1176 #if !wxUSE_UNICODE && wxUSE_FONTMAP 
1177         // determine if we need any conversion at all 
1178         wxFontEncoding encCat 
= wxFontMapperBase::GetEncodingFromName(m_charset
); 
1179         if ( encCat 
!= wxLocale::GetSystemEncoding() ) 
1183             inputConv 
= new wxCSConv(m_charset
); 
1186     else // no need or not possible to convert the encoding 
1189         // we must somehow convert the narrow strings in the message catalog to 
1190         // wide strings, so use the default conversion if we have no charset 
1191         inputConv 
= wxConvCurrent
; 
1196     // conversion to apply to msgid strings before looking them up: we only 
1197     // need it if the msgids are neither in 7 bit ASCII nor in the same 
1198     // encoding as the catalog 
1199     wxCSConv 
*sourceConv 
= msgIdCharset
.empty() || (msgIdCharset 
== m_charset
) 
1201                             : new wxCSConv(msgIdCharset
); 
1202 #endif // !wxUSE_UNICODE 
1204     for (size_t32 i 
= 0; i 
< m_numStrings
; i
++) 
1206         const char *data 
= StringAtOfs(m_pOrigTable
, i
); 
1208             return false; // may happen for invalid MO files 
1212         msgid 
= wxString(data
, *inputConv
); 
1214         if ( inputConv 
&& sourceConv 
) 
1215             msgid 
= wxString(inputConv
->cMB2WC(data
), *sourceConv
); 
1218 #endif // wxUSE_UNICODE 
1220         data 
= StringAtOfs(m_pTransTable
, i
); 
1222             return false; // may happen for invalid MO files 
1224         size_t length 
= Swap(m_pTransTable
[i
].nLen
); 
1227         while (offset 
< length
) 
1229             const char * const str 
= data 
+ offset
; 
1233             msgstr 
= wxString(str
, *inputConv
); 
1236                 msgstr 
= wxString(inputConv
->cMB2WC(str
), *wxConvUI
); 
1239 #endif // wxUSE_UNICODE/!wxUSE_UNICODE 
1241             if ( !msgstr
.empty() ) 
1243                 hash
[index 
== 0 ? msgid 
: msgid 
+ wxChar(index
)] = msgstr
; 
1247             // IMPORTANT: accesses to the 'data' pointer are valid only for 
1248             //            the first 'length+1' bytes (GNU specs says that the 
1249             //            final NUL is not counted in length); using wxStrnlen() 
1250             //            we make sure we don't access memory beyond the valid range 
1251             //            (which otherwise may happen for invalid MO files): 
1252             offset 
+= wxStrnlen(str
, length 
- offset
) + 1; 
1260     delete inputConvPtr
; 
1266 // ---------------------------------------------------------------------------- 
1267 // wxMsgCatalog class 
1268 // ---------------------------------------------------------------------------- 
1271 wxMsgCatalog::~wxMsgCatalog() 
1275         if ( wxConvUI 
== m_conv 
) 
1277             // we only change wxConvUI if it points to wxConvLocal so we reset 
1278             // it back to it too 
1279             wxConvUI 
= &wxConvLocal
; 
1285 #endif // !wxUSE_UNICODE 
1287 bool wxMsgCatalog::Load(const wxString
& filename
, 
1288                         const wxString
& domain
, 
1289                         const wxString
& msgIdCharset
) 
1291     wxMsgCatalogFile file
; 
1295     if ( !file
.Load(filename
, m_pluralFormsCalculator
) ) 
1298     if ( !file
.FillHash(m_messages
, msgIdCharset
) ) 
1304 const wxString 
*wxMsgCatalog::GetString(const wxString
& str
, size_t n
) const 
1307     if (n 
!= size_t(-1)) 
1309         index 
= m_pluralFormsCalculator
->evaluate(n
); 
1311     wxMessagesHash::const_iterator i
; 
1314         i 
= m_messages
.find(wxString(str
) + wxChar(index
));   // plural 
1318         i 
= m_messages
.find(str
); 
1321     if ( i 
!= m_messages
.end() ) 
1330 // ---------------------------------------------------------------------------- 
1332 // ---------------------------------------------------------------------------- 
1337 wxTranslations 
*gs_translations 
= NULL
; 
1338 bool gs_translationsOwned 
= false; 
1340 } // anonymous namespace 
1344 wxTranslations 
*wxTranslations::Get() 
1346     return gs_translations
; 
1350 void wxTranslations::Set(wxTranslations 
*t
) 
1352     if ( gs_translationsOwned 
) 
1353         delete gs_translations
; 
1354     gs_translations 
= t
; 
1355     gs_translationsOwned 
= true; 
1359 void wxTranslations::SetNonOwned(wxTranslations 
*t
) 
1361     if ( gs_translationsOwned 
) 
1362         delete gs_translations
; 
1363     gs_translations 
= t
; 
1364     gs_translationsOwned 
= false; 
1368 wxTranslations::wxTranslations() 
1371     m_loader 
= new wxFileTranslationsLoader
; 
1375 wxTranslations::~wxTranslations() 
1379     // free catalogs memory 
1380     wxMsgCatalog 
*pTmpCat
; 
1381     while ( m_pMsgCat 
!= NULL 
) 
1383         pTmpCat 
= m_pMsgCat
; 
1384         m_pMsgCat 
= m_pMsgCat
->m_pNext
; 
1390 void wxTranslations::SetLoader(wxTranslationsLoader 
*loader
) 
1392     wxCHECK_RET( loader
, "loader can't be NULL" ); 
1399 void wxTranslations::SetLanguage(wxLanguage lang
) 
1401     if ( lang 
== wxLANGUAGE_DEFAULT 
) 
1404         SetLanguage(wxLocale::GetLanguageCanonicalName(lang
)); 
1407 void wxTranslations::SetLanguage(const wxString
& lang
) 
1413 bool wxTranslations::AddStdCatalog() 
1415     if ( !AddCatalog(wxS("wxstd")) ) 
1418     // there may be a catalog with toolkit specific overrides, it is not 
1419     // an error if this does not exist 
1420     wxString 
port(wxPlatformInfo::Get().GetPortIdName()); 
1421     if ( !port
.empty() ) 
1423         AddCatalog(port
.BeforeFirst(wxS('/')).MakeLower()); 
1430 bool wxTranslations::AddCatalog(const wxString
& domain
) 
1432     return AddCatalog(domain
, wxLANGUAGE_ENGLISH_US
); 
1436 bool wxTranslations::AddCatalog(const wxString
& domain
, 
1437                                 wxLanguage msgIdLanguage
, 
1438                                 const wxString
& msgIdCharset
) 
1440     m_msgIdCharset
[domain
] = msgIdCharset
; 
1441     return AddCatalog(domain
, msgIdLanguage
); 
1443 #endif // !wxUSE_UNICODE 
1445 bool wxTranslations::AddCatalog(const wxString
& domain
, 
1446                                 wxLanguage msgIdLanguage
) 
1448     const wxString msgIdLang 
= wxLocale::GetLanguageCanonicalName(msgIdLanguage
); 
1449     const wxString domain_lang 
= ChooseLanguageForDomain(domain
, msgIdLang
); 
1451     if ( domain_lang
.empty() ) 
1453         wxLogTrace(TRACE_I18N
, 
1454                     wxS("no suitable translation for domain '%s' found"), 
1459     wxLogTrace(TRACE_I18N
, 
1460                 wxS("adding '%s' translation for domain '%s' (msgid language '%s')"), 
1461                 domain_lang
, domain
, msgIdLang
); 
1463     // It is OK to not load catalog if the msgid language and m_language match, 
1464     // in which case we can directly display the texts embedded in program's 
1466     if ( msgIdLang 
== domain_lang 
) 
1469     wxCHECK_MSG( m_loader
, false, "loader can't be NULL" ); 
1470     return m_loader
->LoadCatalog(this, domain
, domain_lang
); 
1474 // check if the given catalog is loaded 
1475 bool wxTranslations::IsLoaded(const wxString
& domain
) const 
1477     return FindCatalog(domain
) != NULL
; 
1481 bool wxTranslations::LoadCatalogFile(const wxString
& filename
, 
1482                                      const wxString
& domain
) 
1484     wxMsgCatalog 
*pMsgCat 
= new wxMsgCatalog
; 
1487     const bool ok 
= pMsgCat
->Load(filename
, domain
, wxEmptyString
/*unused*/); 
1489     const bool ok 
= pMsgCat
->Load(filename
, domain
, 
1490                                   m_msgIdCharset
[domain
]); 
1495         // don't add it because it couldn't be loaded anyway 
1500     // add it to the head of the list so that in GetString it will 
1501     // be searched before the catalogs added earlier 
1502     pMsgCat
->m_pNext 
= m_pMsgCat
; 
1503     m_pMsgCat 
= pMsgCat
; 
1509 wxString 
wxTranslations::ChooseLanguageForDomain(const wxString
& WXUNUSED(domain
), 
1510                                                  const wxString
& WXUNUSED(msgIdLang
)) 
1512     // explicitly set language should always be respected 
1513     if ( !m_lang
.empty() ) 
1516     // TODO: if the default language is used, pick the best (by comparing 
1517     //       available languages with user's preferences), instead of blindly 
1518     //       trusting availability of system language translation 
1519     return wxLocale::GetLanguageCanonicalName(wxLocale::GetSystemLanguage()); 
1525 WX_DECLARE_HASH_SET(wxString
, wxStringHash
, wxStringEqual
, 
1526                     wxLocaleUntranslatedStrings
); 
1530 const wxString
& wxTranslations::GetUntranslatedString(const wxString
& str
) 
1532     static wxLocaleUntranslatedStrings s_strings
; 
1534     wxLocaleUntranslatedStrings::iterator i 
= s_strings
.find(str
); 
1535     if ( i 
== s_strings
.end() ) 
1536         return *s_strings
.insert(str
).first
; 
1542 const wxString
& wxTranslations::GetString(const wxString
& origString
, 
1543                                           const wxString
& domain
) const 
1545     return GetString(origString
, origString
, size_t(-1), domain
); 
1548 const wxString
& wxTranslations::GetString(const wxString
& origString
, 
1549                                           const wxString
& origString2
, 
1551                                           const wxString
& domain
) const 
1553     if ( origString
.empty() ) 
1554         return GetUntranslatedString(origString
); 
1556     const wxString 
*trans 
= NULL
; 
1557     wxMsgCatalog 
*pMsgCat
; 
1559     if ( !domain
.empty() ) 
1561         pMsgCat 
= FindCatalog(domain
); 
1563         // does the catalog exist? 
1564         if ( pMsgCat 
!= NULL 
) 
1565             trans 
= pMsgCat
->GetString(origString
, n
); 
1569         // search in all domains 
1570         for ( pMsgCat 
= m_pMsgCat
; pMsgCat 
!= NULL
; pMsgCat 
= pMsgCat
->m_pNext 
) 
1572             trans 
= pMsgCat
->GetString(origString
, n
); 
1573             if ( trans 
!= NULL 
)   // take the first found 
1578     if ( trans 
== NULL 
) 
1583             "string \"%s\"%s not found in %slocale '%s'.", 
1585             ((long)n
) != -1 ? wxString::Format("[%ld]", (long)n
) : wxString(), 
1586             !domain
.empty() ? wxString::Format("domain '%s' ", domain
) : wxString(), 
1590         if (n 
== size_t(-1)) 
1591             return GetUntranslatedString(origString
); 
1593             return GetUntranslatedString(n 
== 1 ? origString 
: origString2
); 
1600 wxString 
wxTranslations::GetHeaderValue(const wxString
& header
, 
1601                                         const wxString
& domain
) const 
1603     if ( header
.empty() ) 
1604         return wxEmptyString
; 
1606     const wxString 
*trans 
= NULL
; 
1607     wxMsgCatalog 
*pMsgCat
; 
1609     if ( !domain
.empty() ) 
1611         pMsgCat 
= FindCatalog(domain
); 
1613         // does the catalog exist? 
1614         if ( pMsgCat 
== NULL 
) 
1615             return wxEmptyString
; 
1617         trans 
= pMsgCat
->GetString(wxEmptyString
, (size_t)-1); 
1621         // search in all domains 
1622         for ( pMsgCat 
= m_pMsgCat
; pMsgCat 
!= NULL
; pMsgCat 
= pMsgCat
->m_pNext 
) 
1624             trans 
= pMsgCat
->GetString(wxEmptyString
, (size_t)-1); 
1625             if ( trans 
!= NULL 
)   // take the first found 
1630     if ( !trans 
|| trans
->empty() ) 
1631         return wxEmptyString
; 
1633     size_t found 
= trans
->find(header
); 
1634     if ( found 
== wxString::npos 
) 
1635         return wxEmptyString
; 
1637     found 
+= header
.length() + 2 /* ': ' */; 
1639     // Every header is separated by \n 
1641     size_t endLine 
= trans
->find(wxS('\n'), found
); 
1642     size_t len 
= (endLine 
== wxString::npos
) ? 
1643                 wxString::npos 
: (endLine 
- found
); 
1645     return trans
->substr(found
, len
); 
1649 // find catalog by name in a linked list, return NULL if !found 
1650 wxMsgCatalog 
*wxTranslations::FindCatalog(const wxString
& domain
) const 
1652     // linear search in the linked list 
1653     wxMsgCatalog 
*pMsgCat
; 
1654     for ( pMsgCat 
= m_pMsgCat
; pMsgCat 
!= NULL
; pMsgCat 
= pMsgCat
->m_pNext 
) 
1656         if ( pMsgCat
->GetDomain() == domain 
) 
1663 // ---------------------------------------------------------------------------- 
1664 // wxFileTranslationsLoader 
1665 // ---------------------------------------------------------------------------- 
1670 // the list of the directories to search for message catalog files 
1671 wxArrayString gs_searchPrefixes
; 
1673 // return the directories to search for message catalogs under the given 
1674 // prefix, separated by wxPATH_SEP 
1675 wxString 
GetMsgCatalogSubdirs(const wxString
& prefix
, const wxString
& lang
) 
1677     // Search first in Unix-standard prefix/lang/LC_MESSAGES, then in 
1678     // prefix/lang and finally in just prefix. 
1680     // Note that we use LC_MESSAGES on all platforms and not just Unix, because 
1681     // it doesn't cost much to look into one more directory and doing it this 
1682     // way has two important benefits: 
1683     // a) we don't break compatibility with wx-2.6 and older by stopping to 
1684     //    look in a directory where the catalogs used to be and thus silently 
1685     //    breaking apps after they are recompiled against the latest wx 
1686     // b) it makes it possible to package app's support files in the same 
1687     //    way on all target platforms 
1688     const wxString pathPrefix 
= wxFileName(prefix
, lang
).GetFullPath(); 
1690     wxString searchPath
; 
1691     searchPath
.reserve(4*pathPrefix
.length()); 
1692     searchPath 
<< pathPrefix 
<< wxFILE_SEP_PATH 
<< "LC_MESSAGES" << wxPATH_SEP
 
1693             << prefix 
<< wxFILE_SEP_PATH 
<< wxPATH_SEP
 
1699 // construct the search path for the given language 
1700 static wxString 
GetFullSearchPath(const wxString
& lang
) 
1702     // first take the entries explicitly added by the program 
1703     wxArrayString paths
; 
1704     paths
.reserve(gs_searchPrefixes
.size() + 1); 
1706         count 
= gs_searchPrefixes
.size(); 
1707     for ( n 
= 0; n 
< count
; n
++ ) 
1709         paths
.Add(GetMsgCatalogSubdirs(gs_searchPrefixes
[n
], lang
)); 
1714     // then look in the standard location 
1715     const wxString stdp 
= wxStandardPaths::Get(). 
1716         GetLocalizedResourcesDir(lang
, wxStandardPaths::ResourceCat_Messages
); 
1718     if ( paths
.Index(stdp
) == wxNOT_FOUND 
) 
1720 #endif // wxUSE_STDPATHS 
1722     // last look in default locations 
1724     // LC_PATH is a standard env var containing the search path for the .mo 
1726     const char *pszLcPath 
= wxGetenv("LC_PATH"); 
1729         const wxString lcp 
= GetMsgCatalogSubdirs(pszLcPath
, lang
); 
1730         if ( paths
.Index(lcp
) == wxNOT_FOUND 
) 
1734     // also add the one from where wxWin was installed: 
1735     wxString wxp 
= wxGetInstallPrefix(); 
1738         wxp 
= GetMsgCatalogSubdirs(wxp 
+ wxS("/share/locale"), lang
); 
1739         if ( paths
.Index(wxp
) == wxNOT_FOUND 
) 
1745     // finally construct the full search path 
1746     wxString searchPath
; 
1747     searchPath
.reserve(500); 
1748     count 
= paths
.size(); 
1749     for ( n 
= 0; n 
< count
; n
++ ) 
1751         searchPath 
+= paths
[n
]; 
1752         if ( n 
!= count 
- 1 ) 
1753             searchPath 
+= wxPATH_SEP
; 
1759 } // anonymous namespace 
1762 void wxFileTranslationsLoader::AddCatalogLookupPathPrefix(const wxString
& prefix
) 
1764     if ( gs_searchPrefixes
.Index(prefix
) == wxNOT_FOUND 
) 
1766         gs_searchPrefixes
.Add(prefix
); 
1768     //else: already have it 
1772 bool wxFileTranslationsLoader::LoadCatalog(wxTranslations 
*translations
, 
1773                                            const wxString
& domain
, 
1774                                            const wxString
& lang
) 
1776     wxCHECK_MSG( lang
.length() >= LEN_LANG
, false, 
1777                  "invalid language specification" ); 
1779     wxString searchPath
; 
1782     // first look for the catalog for this language and the current locale: 
1783     // notice that we don't use the system name for the locale as this would 
1784     // force us to install catalogs in different locations depending on the 
1785     // system but always use the canonical name 
1786     wxFontEncoding encSys 
= wxLocale::GetSystemEncoding(); 
1787     if ( encSys 
!= wxFONTENCODING_SYSTEM 
) 
1789         wxString 
fullname(lang
); 
1790         fullname 
<< wxS('.') << wxFontMapperBase::GetEncodingName(encSys
); 
1791         searchPath 
<< GetFullSearchPath(fullname
) << wxPATH_SEP
; 
1793 #endif // wxUSE_FONTMAP 
1795     searchPath 
+= GetFullSearchPath(lang
); 
1796     if ( lang
.length() > LEN_LANG 
&& lang
[LEN_LANG
] == wxS('_') ) 
1798         // also add just base locale name: for things like "fr_BE" (Belgium 
1799         // French) we should use fall back on plain "fr" if no Belgium-specific 
1800         // message catalogs exist 
1801         searchPath 
<< wxPATH_SEP
 
1802                     << GetFullSearchPath(ExtractLang(lang
)); 
1805     wxLogTrace(TRACE_I18N
, wxS("Looking for \"%s.mo\" in search path \"%s\""), 
1806                 domain
, searchPath
); 
1808     wxFileName 
fn(domain
); 
1809     fn
.SetExt(wxS("mo")); 
1811     wxString strFullName
; 
1812     if ( !wxFindFileInPath(&strFullName
, searchPath
, fn
.GetFullPath()) ) 
1814         wxLogVerbose(_("catalog file for domain '%s' not found."), domain
); 
1815         wxLogTrace(TRACE_I18N
, wxS("Catalog \"%s.mo\" not found"), domain
); 
1819     // open file and read its data 
1820     wxLogVerbose(_("using catalog '%s' from '%s'."), domain
, strFullName
.c_str()); 
1821     wxLogTrace(TRACE_I18N
, wxS("Using catalog \"%s\"."), strFullName
.c_str()); 
1823     return translations
->LoadCatalogFile(strFullName
, domain
); 
1827 // ---------------------------------------------------------------------------- 
1829 // ---------------------------------------------------------------------------- 
1831 #include "wx/arrimpl.cpp" 
1832 WX_DECLARE_EXPORTED_OBJARRAY(wxLanguageInfo
, wxLanguageInfoArray
); 
1833 WX_DEFINE_OBJARRAY(wxLanguageInfoArray
) 
1835 wxLanguageInfoArray 
*wxLocale::ms_languagesDB 
= NULL
; 
1837 /*static*/ void wxLocale::CreateLanguagesDB() 
1839     if (ms_languagesDB 
== NULL
) 
1841         ms_languagesDB 
= new wxLanguageInfoArray
; 
1846 /*static*/ void wxLocale::DestroyLanguagesDB() 
1848     delete ms_languagesDB
; 
1849     ms_languagesDB 
= NULL
; 
1853 void wxLocale::DoCommonInit() 
1855     m_pszOldLocale 
= NULL
; 
1857     m_pOldLocale 
= wxSetLocale(this); 
1858     wxTranslations::SetNonOwned(&m_translations
); 
1860     m_language 
= wxLANGUAGE_UNKNOWN
; 
1861     m_initialized 
= false; 
1864 // NB: this function has (desired) side effect of changing current locale 
1865 bool wxLocale::Init(const wxString
& name
, 
1866                     const wxString
& shortName
, 
1867                     const wxString
& locale
, 
1869 #if WXWIN_COMPATIBILITY_2_8 
1870                    ,bool            bConvertEncoding
 
1874 #if WXWIN_COMPATIBILITY_2_8 
1875     wxASSERT_MSG( bConvertEncoding
, 
1876                   wxS("wxLocale::Init with bConvertEncoding=false is no longer supported, add charset to your catalogs") ); 
1879     bool ret 
= DoInit(name
, shortName
, locale
); 
1881     // NB: don't use 'lang' here, 'language' may be wxLANGUAGE_DEFAULT 
1882     m_translations
.SetLanguage(shortName
); 
1885         m_translations
.AddStdCatalog(); 
1890 bool wxLocale::DoInit(const wxString
& name
, 
1891                       const wxString
& shortName
, 
1892                       const wxString
& locale
) 
1894     wxASSERT_MSG( !m_initialized
, 
1895                     wxS("you can't call wxLocale::Init more than once") ); 
1897     m_initialized 
= true; 
1899     m_strShort 
= shortName
; 
1900     m_language 
= wxLANGUAGE_UNKNOWN
; 
1902     // change current locale (default: same as long name) 
1903     wxString 
szLocale(locale
); 
1904     if ( szLocale
.empty() ) 
1906         // the argument to setlocale() 
1907         szLocale 
= shortName
; 
1909         wxCHECK_MSG( !szLocale
.empty(), false, 
1910                     wxS("no locale to set in wxLocale::Init()") ); 
1913     const char *oldLocale 
= wxSetlocale(LC_ALL
, szLocale
); 
1915         m_pszOldLocale 
= wxStrdup(oldLocale
); 
1917         m_pszOldLocale 
= NULL
; 
1919     if ( m_pszOldLocale 
== NULL 
) 
1921         wxLogError(_("locale '%s' can not be set."), szLocale
); 
1924     // the short name will be used to look for catalog files as well, 
1925     // so we need something here 
1926     if ( m_strShort
.empty() ) { 
1927         // FIXME I don't know how these 2 letter abbreviations are formed, 
1928         //       this wild guess is surely wrong 
1929         if ( !szLocale
.empty() ) 
1931             m_strShort 
+= (wxChar
)wxTolower(szLocale
[0]); 
1932             if ( szLocale
.length() > 1 ) 
1933                 m_strShort 
+= (wxChar
)wxTolower(szLocale
[1]); 
1941 #if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__) 
1942 static const char *wxSetlocaleTryUTF8(int c
, const wxString
& lc
) 
1944     const char *l 
= NULL
; 
1946     // NB: We prefer to set UTF-8 locale if it's possible and only fall back to 
1947     //     non-UTF-8 locale if it fails 
1953         buf2 
= buf 
+ wxS(".UTF-8"); 
1954         l 
= wxSetlocale(c
, buf2
); 
1957             buf2 
= buf 
+ wxS(".utf-8"); 
1958             l 
= wxSetlocale(c
, buf2
); 
1962             buf2 
= buf 
+ wxS(".UTF8"); 
1963             l 
= wxSetlocale(c
, buf2
); 
1967             buf2 
= buf 
+ wxS(".utf8"); 
1968             l 
= wxSetlocale(c
, buf2
); 
1972     // if we can't set UTF-8 locale, try non-UTF-8 one: 
1974         l 
= wxSetlocale(c
, lc
); 
1979 #define wxSetlocaleTryUTF8(c, lc)  wxSetlocale(c, lc) 
1982 bool wxLocale::Init(int language
, int flags
) 
1984 #if WXWIN_COMPATIBILITY_2_8 
1985     wxASSERT_MSG( !(flags 
& wxLOCALE_CONV_ENCODING
), 
1986                   wxS("wxLOCALE_CONV_ENCODING is no longer supported, add charset to your catalogs") ); 
1991     int lang 
= language
; 
1992     if (lang 
== wxLANGUAGE_DEFAULT
) 
1994         // auto detect the language 
1995         lang 
= GetSystemLanguage(); 
1998     // We failed to detect system language, so we will use English: 
1999     if (lang 
== wxLANGUAGE_UNKNOWN
) 
2004     const wxLanguageInfo 
*info 
= GetLanguageInfo(lang
); 
2006     // Unknown language: 
2009         wxLogError(wxS("Unknown language %i."), lang
); 
2013     wxString name 
= info
->Description
; 
2014     wxString canonical 
= info
->CanonicalName
; 
2018 #if defined(__OS2__) 
2019     const char *retloc 
= wxSetlocale(LC_ALL 
, wxEmptyString
); 
2020 #elif defined(__UNIX__) && !defined(__WXMAC__) 
2021     if (language 
!= wxLANGUAGE_DEFAULT
) 
2022         locale 
= info
->CanonicalName
; 
2024     const char *retloc 
= wxSetlocaleTryUTF8(LC_ALL
, locale
); 
2026     const wxString langOnly 
= ExtractLang(locale
); 
2029         // Some C libraries don't like xx_YY form and require xx only 
2030         retloc 
= wxSetlocaleTryUTF8(LC_ALL
, langOnly
); 
2034     // some systems (e.g. FreeBSD and HP-UX) don't have xx_YY aliases but 
2035     // require the full xx_YY.encoding form, so try using UTF-8 because this is 
2036     // the only thing we can do generically 
2038     // TODO: add encodings applicable to each language to the lang DB and try 
2039     //       them all in turn here 
2042         const wxChar 
**names 
= 
2043             wxFontMapperBase::GetAllEncodingNames(wxFONTENCODING_UTF8
); 
2046             retloc 
= wxSetlocale(LC_ALL
, locale 
+ wxS('.') + *names
++); 
2051 #endif // wxUSE_FONTMAP 
2055         // Some C libraries (namely glibc) still use old ISO 639, 
2056         // so will translate the abbrev for them 
2058         if ( langOnly 
== wxS("he") ) 
2059             localeAlt 
= wxS("iw") + ExtractNotLang(locale
); 
2060         else if ( langOnly 
== wxS("id") ) 
2061             localeAlt 
= wxS("in") + ExtractNotLang(locale
); 
2062         else if ( langOnly 
== wxS("yi") ) 
2063             localeAlt 
= wxS("ji") + ExtractNotLang(locale
); 
2064         else if ( langOnly 
== wxS("nb") ) 
2065             localeAlt 
= wxS("no_NO"); 
2066         else if ( langOnly 
== wxS("nn") ) 
2067             localeAlt 
= wxS("no_NY"); 
2069         if ( !localeAlt
.empty() ) 
2071             retloc 
= wxSetlocaleTryUTF8(LC_ALL
, localeAlt
); 
2073                 retloc 
= wxSetlocaleTryUTF8(LC_ALL
, ExtractLang(localeAlt
)); 
2081     // at least in AIX 5.2 libc is buggy and the string returned from 
2082     // setlocale(LC_ALL) can't be passed back to it because it returns 6 
2083     // strings (one for each locale category), i.e. for C locale we get back 
2086     // this contradicts IBM own docs but this is not of much help, so just work 
2087     // around it in the crudest possible manner 
2088     char* p 
= const_cast<char*>(wxStrchr(retloc
, ' ')); 
2093 #elif defined(__WIN32__) 
2094     const char *retloc 
= "C"; 
2095     if ( language 
!= wxLANGUAGE_DEFAULT 
) 
2097         if ( info
->WinLang 
== 0 ) 
2099             wxLogWarning(wxS("Locale '%s' not supported by OS."), name
.c_str()); 
2100             // retloc already set to "C" 
2102         else // language supported by Windows 
2104             // Windows CE doesn't have SetThreadLocale() and there doesn't seem 
2105             // to be any equivalent 
2107             const wxUint32 lcid 
= info
->GetLCID(); 
2109             // change locale used by Windows functions 
2110             ::SetThreadLocale(lcid
); 
2113             // and also call setlocale() to change locale used by the CRT 
2114             locale 
= info
->GetLocaleName(); 
2115             if ( locale
.empty() ) 
2119             else // have a valid locale 
2121                 retloc 
= wxSetlocale(LC_ALL
, locale
); 
2125     else // language == wxLANGUAGE_DEFAULT 
2127         retloc 
= wxSetlocale(LC_ALL
, wxEmptyString
); 
2130 #if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__)) 
2131     // VC++ setlocale() (also used by Mingw) can't set locale to languages that 
2132     // can only be written using Unicode, therefore wxSetlocale() call fails 
2133     // for such languages but we don't want to report it as an error -- so that 
2134     // at least message catalogs can be used. 
2137         if ( wxGetANSICodePageForLocale(LOCALE_USER_DEFAULT
).empty() ) 
2139             // we set the locale to a Unicode-only language, don't treat the 
2140             // inability of CRT to use it as an error 
2144 #endif // CRT not handling Unicode-only languages 
2148 #elif defined(__WXMAC__) 
2149     if (lang 
== wxLANGUAGE_DEFAULT
) 
2150         locale 
= wxEmptyString
; 
2152         locale 
= info
->CanonicalName
; 
2154     const char *retloc 
= wxSetlocale(LC_ALL
, locale
); 
2158         // Some C libraries don't like xx_YY form and require xx only 
2159         retloc 
= wxSetlocale(LC_ALL
, ExtractLang(locale
)); 
2164     #define WX_NO_LOCALE_SUPPORT 
2167 #ifndef WX_NO_LOCALE_SUPPORT 
2170         wxLogWarning(_("Cannot set locale to language \"%s\"."), name
.c_str()); 
2172         // continue nevertheless and try to load at least the translations for 
2176     if ( !DoInit(name
, canonical
, retloc
) ) 
2181     if (IsOk()) // setlocale() succeeded 
2184     // NB: don't use 'lang' here, 'language' 
2185     m_translations
.SetLanguage(wx_static_cast(wxLanguage
, language
)); 
2187     if ( flags 
& wxLOCALE_LOAD_DEFAULT 
) 
2188         m_translations
.AddStdCatalog(); 
2191 #endif // !WX_NO_LOCALE_SUPPORT 
2194 /*static*/ int wxLocale::GetSystemLanguage() 
2196     CreateLanguagesDB(); 
2198     // init i to avoid compiler warning 
2200         count 
= ms_languagesDB
->GetCount(); 
2202 #if defined(__UNIX__) 
2203     // first get the string identifying the language from the environment 
2206     wxCFRef
<CFLocaleRef
> userLocaleRef(CFLocaleCopyCurrent()); 
2208     // because the locale identifier (kCFLocaleIdentifier) is formatted a little bit differently, eg 
2209     // az_Cyrl_AZ@calendar=buddhist;currency=JPY we just recreate the base info as expected by wx here 
2211     wxCFStringRef 
str(wxCFRetain((CFStringRef
)CFLocaleGetValue(userLocaleRef
, kCFLocaleLanguageCode
))); 
2212     langFull 
= str
.AsString()+"_"; 
2213     str
.reset(wxCFRetain((CFStringRef
)CFLocaleGetValue(userLocaleRef
, kCFLocaleCountryCode
))); 
2214     langFull 
+= str
.AsString(); 
2216     if (!wxGetEnv(wxS("LC_ALL"), &langFull
) && 
2217         !wxGetEnv(wxS("LC_MESSAGES"), &langFull
) && 
2218         !wxGetEnv(wxS("LANG"), &langFull
)) 
2220         // no language specified, treat it as English 
2221         return wxLANGUAGE_ENGLISH_US
; 
2224     if ( langFull 
== wxS("C") || langFull 
== wxS("POSIX") ) 
2226         // default C locale is English too 
2227         return wxLANGUAGE_ENGLISH_US
; 
2231     // the language string has the following form 
2233     //      lang[_LANG][.encoding][@modifier] 
2235     // (see environ(5) in the Open Unix specification) 
2237     // where lang is the primary language, LANG is a sublang/territory, 
2238     // encoding is the charset to use and modifier "allows the user to select 
2239     // a specific instance of localization data within a single category" 
2241     // for example, the following strings are valid: 
2246     //      de_DE.iso88591@euro 
2248     // for now we don't use the encoding, although we probably should (doing 
2249     // translations of the msg catalogs on the fly as required) (TODO) 
2251     // we need the modified for languages like Valencian: ca_ES@valencia 
2252     // though, remember it 
2254     size_t posModifier 
= langFull
.find_first_of(wxS("@")); 
2255     if ( posModifier 
!= wxString::npos 
) 
2256         modifier 
= langFull
.Mid(posModifier
); 
2258     size_t posEndLang 
= langFull
.find_first_of(wxS("@.")); 
2259     if ( posEndLang 
!= wxString::npos 
) 
2261         langFull
.Truncate(posEndLang
); 
2264     // in addition to the format above, we also can have full language names 
2265     // in LANG env var - for example, SuSE is known to use LANG="german" - so 
2268     // do we have just the language (or sublang too)? 
2269     bool justLang 
= langFull
.length() == LEN_LANG
; 
2271         (langFull
.length() == LEN_FULL 
&& langFull
[LEN_LANG
] == wxS('_')) ) 
2273         // 0. Make sure the lang is according to latest ISO 639 
2274         //    (this is necessary because glibc uses iw and in instead 
2275         //    of he and id respectively). 
2277         // the language itself (second part is the dialect/sublang) 
2278         wxString langOrig 
= ExtractLang(langFull
); 
2281         if ( langOrig 
== wxS("iw")) 
2283         else if (langOrig 
== wxS("in")) 
2285         else if (langOrig 
== wxS("ji")) 
2287         else if (langOrig 
== wxS("no_NO")) 
2288             lang 
= wxS("nb_NO"); 
2289         else if (langOrig 
== wxS("no_NY")) 
2290             lang 
= wxS("nn_NO"); 
2291         else if (langOrig 
== wxS("no")) 
2292             lang 
= wxS("nb_NO"); 
2296         // did we change it? 
2297         if ( lang 
!= langOrig 
) 
2299             langFull 
= lang 
+ ExtractNotLang(langFull
); 
2302         // 1. Try to find the language either as is: 
2303         // a) With modifier if set 
2304         if ( !modifier
.empty() ) 
2306             wxString langFullWithModifier 
= langFull 
+ modifier
; 
2307             for ( i 
= 0; i 
< count
; i
++ ) 
2309                 if ( ms_languagesDB
->Item(i
).CanonicalName 
== langFullWithModifier 
) 
2314         // b) Without modifier 
2315         if ( modifier
.empty() || i 
== count 
) 
2317             for ( i 
= 0; i 
< count
; i
++ ) 
2319                 if ( ms_languagesDB
->Item(i
).CanonicalName 
== langFull 
) 
2324         // 2. If langFull is of the form xx_YY, try to find xx: 
2325         if ( i 
== count 
&& !justLang 
) 
2327             for ( i 
= 0; i 
< count
; i
++ ) 
2329                 if ( ms_languagesDB
->Item(i
).CanonicalName 
== lang 
) 
2336         // 3. If langFull is of the form xx, try to find any xx_YY record: 
2337         if ( i 
== count 
&& justLang 
) 
2339             for ( i 
= 0; i 
< count
; i
++ ) 
2341                 if ( ExtractLang(ms_languagesDB
->Item(i
).CanonicalName
) 
2349     else // not standard format 
2351         // try to find the name in verbose description 
2352         for ( i 
= 0; i 
< count
; i
++ ) 
2354             if (ms_languagesDB
->Item(i
).Description
.CmpNoCase(langFull
) == 0) 
2360 #elif defined(__WIN32__) 
2361     LCID lcid 
= GetUserDefaultLCID(); 
2364         wxUint32 lang 
= PRIMARYLANGID(LANGIDFROMLCID(lcid
)); 
2365         wxUint32 sublang 
= SUBLANGID(LANGIDFROMLCID(lcid
)); 
2367         for ( i 
= 0; i 
< count
; i
++ ) 
2369             if (ms_languagesDB
->Item(i
).WinLang 
== lang 
&& 
2370                 ms_languagesDB
->Item(i
).WinSublang 
== sublang
) 
2376     //else: leave wxlang == wxLANGUAGE_UNKNOWN 
2377 #endif // Unix/Win32 
2381         // we did find a matching entry, use it 
2382         return ms_languagesDB
->Item(i
).Language
; 
2385     // no info about this language in the database 
2386     return wxLANGUAGE_UNKNOWN
; 
2389 // ---------------------------------------------------------------------------- 
2391 // ---------------------------------------------------------------------------- 
2393 // this is a bit strange as under Windows we get the encoding name using its 
2394 // numeric value and under Unix we do it the other way round, but this just 
2395 // reflects the way different systems provide the encoding info 
2398 wxString 
wxLocale::GetSystemEncodingName() 
2402 #if defined(__WIN32__) && !defined(__WXMICROWIN__) 
2403     // FIXME: what is the error return value for GetACP()? 
2404     UINT codepage 
= ::GetACP(); 
2405     encname
.Printf(wxS("windows-%u"), codepage
); 
2406 #elif defined(__WXMAC__) 
2407     // default is just empty string, this resolves to the default system 
2409 #elif defined(__UNIX_LIKE__) 
2411 #if defined(HAVE_LANGINFO_H) && defined(CODESET) 
2412     // GNU libc provides current character set this way (this conforms 
2414     char *oldLocale 
= strdup(setlocale(LC_CTYPE
, NULL
)); 
2415     setlocale(LC_CTYPE
, ""); 
2416     const char *alang 
= nl_langinfo(CODESET
); 
2417     setlocale(LC_CTYPE
, oldLocale
); 
2422         encname 
= wxString::FromAscii( alang 
); 
2424     else // nl_langinfo() failed 
2425 #endif // HAVE_LANGINFO_H 
2427         // if we can't get at the character set directly, try to see if it's in 
2428         // the environment variables (in most cases this won't work, but I was 
2430         char *lang 
= getenv( "LC_ALL"); 
2431         char *dot 
= lang 
? strchr(lang
, '.') : NULL
; 
2434             lang 
= getenv( "LC_CTYPE" ); 
2436                 dot 
= strchr(lang
, '.' ); 
2440             lang 
= getenv( "LANG"); 
2442                 dot 
= strchr(lang
, '.'); 
2447             encname 
= wxString::FromAscii( dot
+1 ); 
2450 #endif // Win32/Unix 
2456 wxFontEncoding 
wxLocale::GetSystemEncoding() 
2458 #if defined(__WIN32__) && !defined(__WXMICROWIN__) 
2459     UINT codepage 
= ::GetACP(); 
2461     // wxWidgets only knows about CP1250-1257, 874, 932, 936, 949, 950 
2462     if ( codepage 
>= 1250 && codepage 
<= 1257 ) 
2464         return (wxFontEncoding
)(wxFONTENCODING_CP1250 
+ codepage 
- 1250); 
2467     if ( codepage 
== 874 ) 
2469         return wxFONTENCODING_CP874
; 
2472     if ( codepage 
== 932 ) 
2474         return wxFONTENCODING_CP932
; 
2477     if ( codepage 
== 936 ) 
2479         return wxFONTENCODING_CP936
; 
2482     if ( codepage 
== 949 ) 
2484         return wxFONTENCODING_CP949
; 
2487     if ( codepage 
== 950 ) 
2489         return wxFONTENCODING_CP950
; 
2491 #elif defined(__WXMAC__) 
2492     CFStringEncoding encoding 
= 0 ; 
2493     encoding 
= CFStringGetSystemEncoding() ; 
2494     return wxMacGetFontEncFromSystemEnc( encoding 
) ; 
2495 #elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP 
2496     const wxString encname 
= GetSystemEncodingName(); 
2497     if ( !encname
.empty() ) 
2499         wxFontEncoding enc 
= wxFontMapperBase::GetEncodingFromName(encname
); 
2501         // on some modern Linux systems (RedHat 8) the default system locale 
2502         // is UTF8 -- but it isn't supported by wxGTK1 in ANSI build at all so 
2503         // don't even try to use it in this case 
2504 #if !wxUSE_UNICODE && \ 
2505         ((defined(__WXGTK__) && !defined(__WXGTK20__)) || defined(__WXMOTIF__)) 
2506         if ( enc 
== wxFONTENCODING_UTF8 
) 
2508             // the most similar supported encoding... 
2509             enc 
= wxFONTENCODING_ISO8859_1
; 
2511 #endif // !wxUSE_UNICODE 
2513         // GetEncodingFromName() returns wxFONTENCODING_DEFAULT for C locale 
2514         // (a.k.a. US-ASCII) which is arguably a bug but keep it like this for 
2515         // backwards compatibility and just take care to not return 
2516         // wxFONTENCODING_DEFAULT from here as this surely doesn't make sense 
2517         if ( enc 
== wxFONTENCODING_DEFAULT 
) 
2519             // we don't have wxFONTENCODING_ASCII, so use the closest one 
2520             return wxFONTENCODING_ISO8859_1
; 
2523         if ( enc 
!= wxFONTENCODING_MAX 
) 
2527         //else: return wxFONTENCODING_SYSTEM below 
2529 #endif // Win32/Unix 
2531     return wxFONTENCODING_SYSTEM
; 
2535 void wxLocale::AddLanguage(const wxLanguageInfo
& info
) 
2537     CreateLanguagesDB(); 
2538     ms_languagesDB
->Add(info
); 
2542 const wxLanguageInfo 
*wxLocale::GetLanguageInfo(int lang
) 
2544     CreateLanguagesDB(); 
2546     // calling GetLanguageInfo(wxLANGUAGE_DEFAULT) is a natural thing to do, so 
2548     if ( lang 
== wxLANGUAGE_DEFAULT 
) 
2549         lang 
= GetSystemLanguage(); 
2551     const size_t count 
= ms_languagesDB
->GetCount(); 
2552     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2554         if ( ms_languagesDB
->Item(i
).Language 
== lang 
) 
2556             // We need to create a temporary here in order to make this work with BCC in final build mode 
2557             wxLanguageInfo 
*ptr 
= &ms_languagesDB
->Item(i
); 
2566 wxString 
wxLocale::GetLanguageName(int lang
) 
2568     if ( lang 
== wxLANGUAGE_DEFAULT 
|| lang 
== wxLANGUAGE_UNKNOWN 
) 
2569         return wxEmptyString
; 
2571     const wxLanguageInfo 
*info 
= GetLanguageInfo(lang
); 
2573         return wxEmptyString
; 
2575         return info
->Description
; 
2579 wxString 
wxLocale::GetLanguageCanonicalName(int lang
) 
2581     if ( lang 
== wxLANGUAGE_DEFAULT 
|| lang 
== wxLANGUAGE_UNKNOWN 
) 
2582         return wxEmptyString
; 
2584     const wxLanguageInfo 
*info 
= GetLanguageInfo(lang
); 
2586         return wxEmptyString
; 
2588         return info
->CanonicalName
; 
2592 const wxLanguageInfo 
*wxLocale::FindLanguageInfo(const wxString
& locale
) 
2594     CreateLanguagesDB(); 
2596     const wxLanguageInfo 
*infoRet 
= NULL
; 
2598     const size_t count 
= ms_languagesDB
->GetCount(); 
2599     for ( size_t i 
= 0; i 
< count
; i
++ ) 
2601         const wxLanguageInfo 
*info 
= &ms_languagesDB
->Item(i
); 
2603         if ( wxStricmp(locale
, info
->CanonicalName
) == 0 || 
2604                 wxStricmp(locale
, info
->Description
) == 0 ) 
2606             // exact match, stop searching 
2611         if ( wxStricmp(locale
, info
->CanonicalName
.BeforeFirst(wxS('_'))) == 0 ) 
2613             // a match -- but maybe we'll find an exact one later, so continue 
2616             // OTOH, maybe we had already found a language match and in this 
2617             // case don't overwrite it because the entry for the default 
2618             // country always appears first in ms_languagesDB 
2627 wxString 
wxLocale::GetSysName() const 
2629     return wxSetlocale(LC_ALL
, NULL
); 
2633 wxLocale::~wxLocale() 
2635     // restore old translations object 
2636     if ( wxTranslations::Get() == &m_translations 
) 
2639             wxTranslations::SetNonOwned(&m_pOldLocale
->m_translations
); 
2641             wxTranslations::Set(NULL
); 
2644     // restore old locale pointer 
2645     wxSetLocale(m_pOldLocale
); 
2647     wxSetlocale(LC_ALL
, m_pszOldLocale
); 
2648     free((wxChar 
*)m_pszOldLocale
);     // const_cast 
2652 // check if the given locale is provided by OS and C run time 
2654 bool wxLocale::IsAvailable(int lang
) 
2656     const wxLanguageInfo 
*info 
= wxLocale::GetLanguageInfo(lang
); 
2657     wxCHECK_MSG( info
, false, wxS("invalid language") ); 
2659 #if defined(__WIN32__) 
2660     if ( !info
->WinLang 
) 
2663     if ( !::IsValidLocale(info
->GetLCID(), LCID_INSTALLED
) ) 
2666 #elif defined(__UNIX__) 
2668     // Test if setting the locale works, then set it back. 
2669     const char *oldLocale 
= wxSetlocaleTryUTF8(LC_ALL
, info
->CanonicalName
); 
2672         // Some C libraries don't like xx_YY form and require xx only 
2673         oldLocale 
= wxSetlocaleTryUTF8(LC_ALL
, ExtractLang(info
->CanonicalName
)); 
2677     // restore the original locale 
2678     wxSetlocale(LC_ALL
, oldLocale
); 
2684 // add a catalog to our linked list 
2685 bool wxLocale::AddCatalog(const wxString
& szDomain
, 
2686                         wxLanguage      msgIdLanguage
, 
2687                         const wxString
& msgIdCharset
) 
2690     wxUnusedVar(msgIdCharset
); 
2691     return m_translations
.AddCatalog(szDomain
, msgIdLanguage
); 
2693     return m_translations
.AddCatalog(szDomain
, msgIdLanguage
, msgIdCharset
); 
2697 // ---------------------------------------------------------------------------- 
2698 // accessors for locale-dependent data 
2699 // ---------------------------------------------------------------------------- 
2701 #if defined(__WXMSW__) || defined(__WXOSX__) 
2706 // This function translates from Unicode date formats described at 
2708 //      http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns 
2710 // to strftime()-like syntax. This translation is not lossless but we try to do 
2713 static wxString 
TranslateFromUnicodeFormat(const wxString
& fmt
) 
2716     fmtWX
.reserve(fmt
.length()); 
2719     size_t lastCount 
= 0; 
2721     const char* formatchars 
= 
2729     for ( wxString::const_iterator p 
= fmt
.begin(); /* end handled inside */; ++p 
) 
2731         if ( p 
!= fmt
.end() ) 
2739             const wxUniChar ch 
= (*p
).GetValue(); 
2740             if ( ch
.IsAscii() && strchr(formatchars
, ch
) ) 
2742                 // these characters come in groups, start counting them 
2749         // interpret any special characters we collected so far 
2755                     switch ( lastCount 
) 
2759                             // these two are the same as we don't distinguish 
2760                             // between 1 and 2 digits for days 
2773                             wxFAIL_MSG( "too many 'd's" ); 
2778                     switch ( lastCount 
) 
2787                             wxFAIL_MSG( "wrong number of 'D's" ); 
2791                     switch ( lastCount 
) 
2799                             wxFAIL_MSG( "wrong number of 'w's" ); 
2803                    switch ( lastCount 
) 
2818                             wxFAIL_MSG( "wrong number of 'E's" ); 
2823                     switch ( lastCount 
) 
2827                             // as for 'd' and 'dd' above 
2840                             wxFAIL_MSG( "too many 'M's" ); 
2845                     switch ( lastCount 
) 
2857                             wxFAIL_MSG( "wrong number of 'y's" ); 
2862                     switch ( lastCount 
) 
2870                             wxFAIL_MSG( "wrong number of 'H's" ); 
2875                     switch ( lastCount 
) 
2883                             wxFAIL_MSG( "wrong number of 'h's" ); 
2888                     switch ( lastCount 
) 
2896                             wxFAIL_MSG( "wrong number of 'm's" ); 
2901                     switch ( lastCount 
) 
2909                             wxFAIL_MSG( "wrong number of 's's" ); 
2914                     // strftime() doesn't have era string, 
2915                     // ignore this format 
2916                     wxASSERT_MSG( lastCount 
<= 2, "too many 'g's" ); 
2926                     switch ( lastCount 
) 
2934                             wxFAIL_MSG( "too many 't's" ); 
2939                     wxFAIL_MSG( "unreachable" ); 
2946         if ( p 
== fmt
.end() ) 
2949         // not a special character so must be just a separator, treat as is 
2950         if ( *p 
== wxT('%') ) 
2952             // this one needs to be escaped 
2962 } // anonymous namespace 
2964 #endif // __WXMSW__ || __WXOSX__ 
2966 #if defined(__WXMSW__) 
2971 LCTYPE 
GetLCTYPEFormatFromLocalInfo(wxLocaleInfo index
) 
2975         case wxLOCALE_SHORT_DATE_FMT
: 
2976             return LOCALE_SSHORTDATE
; 
2978         case wxLOCALE_LONG_DATE_FMT
: 
2979             return LOCALE_SLONGDATE
; 
2981         case wxLOCALE_TIME_FMT
: 
2982             return LOCALE_STIMEFORMAT
; 
2985             wxFAIL_MSG( "no matching LCTYPE" ); 
2991 } // anonymous namespace 
2994 wxString 
wxLocale::GetInfo(wxLocaleInfo index
, wxLocaleCategory 
WXUNUSED(cat
)) 
2996     wxUint32 lcid 
= LOCALE_USER_DEFAULT
; 
2997     if ( wxGetLocale() ) 
2999         const wxLanguageInfo 
* const 
3000             info 
= GetLanguageInfo(wxGetLocale()->GetLanguage()); 
3002             lcid 
= info
->GetLCID(); 
3012         case wxLOCALE_DECIMAL_POINT
: 
3013             if ( ::GetLocaleInfo(lcid
, LOCALE_SDECIMAL
, buf
, WXSIZEOF(buf
)) ) 
3017         case wxLOCALE_SHORT_DATE_FMT
: 
3018         case wxLOCALE_LONG_DATE_FMT
: 
3019         case wxLOCALE_TIME_FMT
: 
3020             if ( ::GetLocaleInfo(lcid
, GetLCTYPEFormatFromLocalInfo(index
), 
3021                                  buf
, WXSIZEOF(buf
)) ) 
3023                 return TranslateFromUnicodeFormat(buf
); 
3027         case wxLOCALE_DATE_TIME_FMT
: 
3028             // there doesn't seem to be any specific setting for this, so just 
3029             // combine date and time ones 
3031             // we use the short date because this is what "%c" uses by default 
3032             // ("%#c" uses long date but we have no way to specify the 
3033             // alternate representation here) 
3035                 const wxString datefmt 
= GetInfo(wxLOCALE_SHORT_DATE_FMT
); 
3036                 if ( datefmt
.empty() ) 
3039                 const wxString timefmt 
= GetInfo(wxLOCALE_TIME_FMT
); 
3040                 if ( timefmt
.empty() ) 
3043                 str 
<< datefmt 
<< ' ' << timefmt
; 
3048             wxFAIL_MSG( "unknown wxLocaleInfo" ); 
3054 #elif defined(__WXOSX__) 
3057 wxString 
wxLocale::GetInfo(wxLocaleInfo index
, wxLocaleCategory 
WXUNUSED(cat
)) 
3059     CFLocaleRef userLocaleRefRaw
; 
3060     if ( wxGetLocale() ) 
3062         userLocaleRefRaw 
= CFLocaleCreate
 
3064                                 kCFAllocatorDefault
, 
3065                                 wxCFStringRef(wxGetLocale()->GetCanonicalName()) 
3068     else // no current locale, use the default one 
3070         userLocaleRefRaw 
= CFLocaleCopyCurrent(); 
3073     wxCFRef
<CFLocaleRef
> userLocaleRef(userLocaleRefRaw
); 
3075     CFStringRef cfstr 
= 0; 
3078         case wxLOCALE_THOUSANDS_SEP
: 
3079             cfstr 
= (CFStringRef
) CFLocaleGetValue(userLocaleRef
, kCFLocaleGroupingSeparator
); 
3082         case wxLOCALE_DECIMAL_POINT
: 
3083             cfstr 
= (CFStringRef
) CFLocaleGetValue(userLocaleRef
, kCFLocaleDecimalSeparator
); 
3086         case wxLOCALE_SHORT_DATE_FMT
: 
3087         case wxLOCALE_LONG_DATE_FMT
: 
3088         case wxLOCALE_DATE_TIME_FMT
: 
3089         case wxLOCALE_TIME_FMT
: 
3091                 CFDateFormatterStyle dateStyle 
= kCFDateFormatterNoStyle
; 
3092                 CFDateFormatterStyle timeStyle 
= kCFDateFormatterNoStyle
; 
3095                     case wxLOCALE_SHORT_DATE_FMT
: 
3096                         dateStyle 
= kCFDateFormatterShortStyle
; 
3098                     case wxLOCALE_LONG_DATE_FMT
: 
3099                         dateStyle 
= kCFDateFormatterFullStyle
; 
3101                     case wxLOCALE_DATE_TIME_FMT
: 
3102                         dateStyle 
= kCFDateFormatterFullStyle
; 
3103                         timeStyle 
= kCFDateFormatterMediumStyle
; 
3105                     case wxLOCALE_TIME_FMT
: 
3106                         timeStyle 
= kCFDateFormatterMediumStyle
; 
3109                         wxFAIL_MSG( "unexpected time locale" ); 
3112                 wxCFRef
<CFDateFormatterRef
> dateFormatter( CFDateFormatterCreate
 
3113                     (NULL
, userLocaleRef
, dateStyle
, timeStyle
)); 
3114                 wxCFStringRef cfs 
= wxCFRetain( CFDateFormatterGetFormat(dateFormatter 
)); 
3115                 wxString format 
= TranslateFromUnicodeFormat(cfs
.AsString()); 
3116                 // we always want full years 
3117                 format
.Replace("%y","%Y"); 
3123             wxFAIL_MSG( "Unknown locale info" ); 
3127     wxCFStringRef 
str(wxCFRetain(cfstr
)); 
3128     return str
.AsString(); 
3131 #else // !__WXMSW__ && !__WXOSX__, assume generic POSIX 
3136 wxString 
GetDateFormatFromLangInfo(wxLocaleInfo index
) 
3138 #ifdef HAVE_LANGINFO_H 
3139     // array containing parameters for nl_langinfo() indexes by offset of index 
3140     // from wxLOCALE_SHORT_DATE_FMT 
3141     static const nl_item items
[] = 
3143         D_FMT
, D_T_FMT
, D_T_FMT
, T_FMT
, 
3146     const int nlidx 
= index 
- wxLOCALE_SHORT_DATE_FMT
; 
3147     if ( nlidx 
< 0 || nlidx 
>= (int)WXSIZEOF(items
) ) 
3149         wxFAIL_MSG( "logic error in GetInfo() code" ); 
3153     const wxString 
fmt(nl_langinfo(items
[nlidx
])); 
3155     // just return the format returned by nl_langinfo() except for long date 
3156     // format which we need to recover from date/time format ourselves (but not 
3157     // if we failed completely) 
3158     if ( fmt
.empty() || index 
!= wxLOCALE_LONG_DATE_FMT 
) 
3161     // this is not 100% precise but the idea is that a typical date/time format 
3162     // under POSIX systems is a combination of a long date format with time one 
3163     // so we should be able to get just the long date format by removing all 
3164     // time-specific format specifiers 
3165     static const char *timeFmtSpecs 
= "HIklMpPrRsSTXzZ"; 
3166     static const char *timeSep 
= " :./-"; 
3168     wxString fmtDateOnly
; 
3169     const wxString::const_iterator end 
= fmt
.end(); 
3170     wxString::const_iterator lastSep 
= end
; 
3171     for ( wxString::const_iterator p 
= fmt
.begin(); p 
!= end
; ++p 
) 
3173         if ( strchr(timeSep
, *p
) ) 
3175             if ( lastSep 
== end 
) 
3178             // skip it for now, we'll discard it if it's followed by a time 
3179             // specifier later or add it to fmtDateOnly if it is not 
3184                 (p 
+ 1 != end
) && strchr(timeFmtSpecs
, p
[1]) ) 
3186             // time specified found: skip it and any preceding separators 
3192         if ( lastSep 
!= end 
) 
3194             fmtDateOnly 
+= wxString(lastSep
, p
); 
3202 #else // !HAVE_LANGINFO_H 
3205     // no fallback, let the application deal with unavailability of 
3206     // nl_langinfo() itself as there is no good way for us to do it (well, we 
3207     // could try to reverse engineer the format from strftime() output but this 
3208     // looks like too much trouble considering the relatively small number of 
3209     // systems without nl_langinfo() still in use) 
3211 #endif // HAVE_LANGINFO_H/!HAVE_LANGINFO_H 
3214 } // anonymous namespace 
3217 wxString 
wxLocale::GetInfo(wxLocaleInfo index
, wxLocaleCategory cat
) 
3219     lconv 
* const lc 
= localeconv(); 
3225         case wxLOCALE_THOUSANDS_SEP
: 
3226             if ( cat 
== wxLOCALE_CAT_NUMBER 
) 
3227                 return lc
->thousands_sep
; 
3228             else if ( cat 
== wxLOCALE_CAT_MONEY 
) 
3229                 return lc
->mon_thousands_sep
; 
3231             wxFAIL_MSG( "invalid wxLocaleCategory" ); 
3235         case wxLOCALE_DECIMAL_POINT
: 
3236             if ( cat 
== wxLOCALE_CAT_NUMBER 
) 
3237                 return lc
->decimal_point
; 
3238             else if ( cat 
== wxLOCALE_CAT_MONEY 
) 
3239                 return lc
->mon_decimal_point
; 
3241             wxFAIL_MSG( "invalid wxLocaleCategory" ); 
3244         case wxLOCALE_SHORT_DATE_FMT
: 
3245         case wxLOCALE_LONG_DATE_FMT
: 
3246         case wxLOCALE_DATE_TIME_FMT
: 
3247         case wxLOCALE_TIME_FMT
: 
3248             if ( cat 
!= wxLOCALE_CAT_DATE 
&& cat 
!= wxLOCALE_CAT_DEFAULT 
) 
3250                 wxFAIL_MSG( "invalid wxLocaleCategory" ); 
3254             return GetDateFormatFromLangInfo(index
); 
3258             wxFAIL_MSG( "unknown wxLocaleInfo value" ); 
3266 // ---------------------------------------------------------------------------- 
3267 // global functions and variables 
3268 // ---------------------------------------------------------------------------- 
3270 // retrieve/change current locale 
3271 // ------------------------------ 
3273 // the current locale object 
3274 static wxLocale 
*g_pLocale 
= NULL
; 
3276 wxLocale 
*wxGetLocale() 
3281 wxLocale 
*wxSetLocale(wxLocale 
*pLocale
) 
3283     wxLocale 
*pOld 
= g_pLocale
; 
3284     g_pLocale 
= pLocale
; 
3290 // ---------------------------------------------------------------------------- 
3291 // wxLocale module (for lazy destruction of languagesDB) 
3292 // ---------------------------------------------------------------------------- 
3294 class wxLocaleModule
: public wxModule
 
3296     DECLARE_DYNAMIC_CLASS(wxLocaleModule
) 
3307             if ( gs_translationsOwned 
) 
3308                 delete gs_translations
; 
3309             gs_translations 
= NULL
; 
3310             gs_translationsOwned 
= true; 
3312             wxLocale::DestroyLanguagesDB(); 
3316 IMPLEMENT_DYNAMIC_CLASS(wxLocaleModule
, wxModule
) 
3320 // ---------------------------------------------------------------------------- 
3321 // default languages table & initialization 
3322 // ---------------------------------------------------------------------------- 
3325 // --- --- --- generated code begins here --- --- --- 
3327 // This table is generated by misc/languages/genlang.py 
3328 // When making changes, please put them into misc/languages/langtabl.txt 
3330 #if !defined(__WIN32__) || defined(__WXMICROWIN__) 
3332 #define SETWINLANG(info,lang,sublang) 
3336 #define SETWINLANG(info,lang,sublang) \ 
3337     info.WinLang = lang, info.WinSublang = sublang; 
3339 #ifndef LANG_AFRIKAANS 
3340 #define LANG_AFRIKAANS (0) 
3342 #ifndef LANG_ALBANIAN 
3343 #define LANG_ALBANIAN (0) 
3346 #define LANG_ARABIC (0) 
3348 #ifndef LANG_ARMENIAN 
3349 #define LANG_ARMENIAN (0) 
3351 #ifndef LANG_ASSAMESE 
3352 #define LANG_ASSAMESE (0) 
3355 #define LANG_AZERI (0) 
3358 #define LANG_BASQUE (0) 
3360 #ifndef LANG_BELARUSIAN 
3361 #define LANG_BELARUSIAN (0) 
3363 #ifndef LANG_BENGALI 
3364 #define LANG_BENGALI (0) 
3366 #ifndef LANG_BULGARIAN 
3367 #define LANG_BULGARIAN (0) 
3369 #ifndef LANG_CATALAN 
3370 #define LANG_CATALAN (0) 
3372 #ifndef LANG_CHINESE 
3373 #define LANG_CHINESE (0) 
3375 #ifndef LANG_CROATIAN 
3376 #define LANG_CROATIAN (0) 
3379 #define LANG_CZECH (0) 
3382 #define LANG_DANISH (0) 
3385 #define LANG_DUTCH (0) 
3387 #ifndef LANG_ENGLISH 
3388 #define LANG_ENGLISH (0) 
3390 #ifndef LANG_ESTONIAN 
3391 #define LANG_ESTONIAN (0) 
3393 #ifndef LANG_FAEROESE 
3394 #define LANG_FAEROESE (0) 
3397 #define LANG_FARSI (0) 
3399 #ifndef LANG_FINNISH 
3400 #define LANG_FINNISH (0) 
3403 #define LANG_FRENCH (0) 
3405 #ifndef LANG_GEORGIAN 
3406 #define LANG_GEORGIAN (0) 
3409 #define LANG_GERMAN (0) 
3412 #define LANG_GREEK (0) 
3414 #ifndef LANG_GUJARATI 
3415 #define LANG_GUJARATI (0) 
3418 #define LANG_HEBREW (0) 
3421 #define LANG_HINDI (0) 
3423 #ifndef LANG_HUNGARIAN 
3424 #define LANG_HUNGARIAN (0) 
3426 #ifndef LANG_ICELANDIC 
3427 #define LANG_ICELANDIC (0) 
3429 #ifndef LANG_INDONESIAN 
3430 #define LANG_INDONESIAN (0) 
3432 #ifndef LANG_ITALIAN 
3433 #define LANG_ITALIAN (0) 
3435 #ifndef LANG_JAPANESE 
3436 #define LANG_JAPANESE (0) 
3438 #ifndef LANG_KANNADA 
3439 #define LANG_KANNADA (0) 
3441 #ifndef LANG_KASHMIRI 
3442 #define LANG_KASHMIRI (0) 
3445 #define LANG_KAZAK (0) 
3447 #ifndef LANG_KONKANI 
3448 #define LANG_KONKANI (0) 
3451 #define LANG_KOREAN (0) 
3453 #ifndef LANG_LATVIAN 
3454 #define LANG_LATVIAN (0) 
3456 #ifndef LANG_LITHUANIAN 
3457 #define LANG_LITHUANIAN (0) 
3459 #ifndef LANG_MACEDONIAN 
3460 #define LANG_MACEDONIAN (0) 
3463 #define LANG_MALAY (0) 
3465 #ifndef LANG_MALAYALAM 
3466 #define LANG_MALAYALAM (0) 
3468 #ifndef LANG_MANIPURI 
3469 #define LANG_MANIPURI (0) 
3471 #ifndef LANG_MARATHI 
3472 #define LANG_MARATHI (0) 
3475 #define LANG_NEPALI (0) 
3477 #ifndef LANG_NORWEGIAN 
3478 #define LANG_NORWEGIAN (0) 
3481 #define LANG_ORIYA (0) 
3484 #define LANG_POLISH (0) 
3486 #ifndef LANG_PORTUGUESE 
3487 #define LANG_PORTUGUESE (0) 
3489 #ifndef LANG_PUNJABI 
3490 #define LANG_PUNJABI (0) 
3492 #ifndef LANG_ROMANIAN 
3493 #define LANG_ROMANIAN (0) 
3495 #ifndef LANG_RUSSIAN 
3496 #define LANG_RUSSIAN (0) 
3499 #define LANG_SAMI (0) 
3501 #ifndef LANG_SANSKRIT 
3502 #define LANG_SANSKRIT (0) 
3504 #ifndef LANG_SERBIAN 
3505 #define LANG_SERBIAN (0) 
3508 #define LANG_SINDHI (0) 
3511 #define LANG_SLOVAK (0) 
3513 #ifndef LANG_SLOVENIAN 
3514 #define LANG_SLOVENIAN (0) 
3516 #ifndef LANG_SPANISH 
3517 #define LANG_SPANISH (0) 
3519 #ifndef LANG_SWAHILI 
3520 #define LANG_SWAHILI (0) 
3522 #ifndef LANG_SWEDISH 
3523 #define LANG_SWEDISH (0) 
3526 #define LANG_TAMIL (0) 
3529 #define LANG_TATAR (0) 
3532 #define LANG_TELUGU (0) 
3535 #define LANG_THAI (0) 
3537 #ifndef LANG_TURKISH 
3538 #define LANG_TURKISH (0) 
3540 #ifndef LANG_UKRAINIAN 
3541 #define LANG_UKRAINIAN (0) 
3544 #define LANG_URDU (0) 
3547 #define LANG_UZBEK (0) 
3549 #ifndef LANG_VIETNAMESE 
3550 #define LANG_VIETNAMESE (0) 
3552 #ifndef SUBLANG_ARABIC_ALGERIA 
3553 #define SUBLANG_ARABIC_ALGERIA SUBLANG_DEFAULT 
3555 #ifndef SUBLANG_ARABIC_BAHRAIN 
3556 #define SUBLANG_ARABIC_BAHRAIN SUBLANG_DEFAULT 
3558 #ifndef SUBLANG_ARABIC_EGYPT 
3559 #define SUBLANG_ARABIC_EGYPT SUBLANG_DEFAULT 
3561 #ifndef SUBLANG_ARABIC_IRAQ 
3562 #define SUBLANG_ARABIC_IRAQ SUBLANG_DEFAULT 
3564 #ifndef SUBLANG_ARABIC_JORDAN 
3565 #define SUBLANG_ARABIC_JORDAN SUBLANG_DEFAULT 
3567 #ifndef SUBLANG_ARABIC_KUWAIT 
3568 #define SUBLANG_ARABIC_KUWAIT SUBLANG_DEFAULT 
3570 #ifndef SUBLANG_ARABIC_LEBANON 
3571 #define SUBLANG_ARABIC_LEBANON SUBLANG_DEFAULT 
3573 #ifndef SUBLANG_ARABIC_LIBYA 
3574 #define SUBLANG_ARABIC_LIBYA SUBLANG_DEFAULT 
3576 #ifndef SUBLANG_ARABIC_MOROCCO 
3577 #define SUBLANG_ARABIC_MOROCCO SUBLANG_DEFAULT 
3579 #ifndef SUBLANG_ARABIC_OMAN 
3580 #define SUBLANG_ARABIC_OMAN SUBLANG_DEFAULT 
3582 #ifndef SUBLANG_ARABIC_QATAR 
3583 #define SUBLANG_ARABIC_QATAR SUBLANG_DEFAULT 
3585 #ifndef SUBLANG_ARABIC_SAUDI_ARABIA 
3586 #define SUBLANG_ARABIC_SAUDI_ARABIA SUBLANG_DEFAULT 
3588 #ifndef SUBLANG_ARABIC_SYRIA 
3589 #define SUBLANG_ARABIC_SYRIA SUBLANG_DEFAULT 
3591 #ifndef SUBLANG_ARABIC_TUNISIA 
3592 #define SUBLANG_ARABIC_TUNISIA SUBLANG_DEFAULT 
3594 #ifndef SUBLANG_ARABIC_UAE 
3595 #define SUBLANG_ARABIC_UAE SUBLANG_DEFAULT 
3597 #ifndef SUBLANG_ARABIC_YEMEN 
3598 #define SUBLANG_ARABIC_YEMEN SUBLANG_DEFAULT 
3600 #ifndef SUBLANG_AZERI_CYRILLIC 
3601 #define SUBLANG_AZERI_CYRILLIC SUBLANG_DEFAULT 
3603 #ifndef SUBLANG_AZERI_LATIN 
3604 #define SUBLANG_AZERI_LATIN SUBLANG_DEFAULT 
3606 #ifndef SUBLANG_CHINESE_SIMPLIFIED 
3607 #define SUBLANG_CHINESE_SIMPLIFIED SUBLANG_DEFAULT 
3609 #ifndef SUBLANG_CHINESE_TRADITIONAL 
3610 #define SUBLANG_CHINESE_TRADITIONAL SUBLANG_DEFAULT 
3612 #ifndef SUBLANG_CHINESE_HONGKONG 
3613 #define SUBLANG_CHINESE_HONGKONG SUBLANG_DEFAULT 
3615 #ifndef SUBLANG_CHINESE_MACAU 
3616 #define SUBLANG_CHINESE_MACAU SUBLANG_DEFAULT 
3618 #ifndef SUBLANG_CHINESE_SINGAPORE 
3619 #define SUBLANG_CHINESE_SINGAPORE SUBLANG_DEFAULT 
3621 #ifndef SUBLANG_DUTCH 
3622 #define SUBLANG_DUTCH SUBLANG_DEFAULT 
3624 #ifndef SUBLANG_DUTCH_BELGIAN 
3625 #define SUBLANG_DUTCH_BELGIAN SUBLANG_DEFAULT 
3627 #ifndef SUBLANG_ENGLISH_UK 
3628 #define SUBLANG_ENGLISH_UK SUBLANG_DEFAULT 
3630 #ifndef SUBLANG_ENGLISH_US 
3631 #define SUBLANG_ENGLISH_US SUBLANG_DEFAULT 
3633 #ifndef SUBLANG_ENGLISH_AUS 
3634 #define SUBLANG_ENGLISH_AUS SUBLANG_DEFAULT 
3636 #ifndef SUBLANG_ENGLISH_BELIZE 
3637 #define SUBLANG_ENGLISH_BELIZE SUBLANG_DEFAULT 
3639 #ifndef SUBLANG_ENGLISH_CAN 
3640 #define SUBLANG_ENGLISH_CAN SUBLANG_DEFAULT 
3642 #ifndef SUBLANG_ENGLISH_CARIBBEAN 
3643 #define SUBLANG_ENGLISH_CARIBBEAN SUBLANG_DEFAULT 
3645 #ifndef SUBLANG_ENGLISH_EIRE 
3646 #define SUBLANG_ENGLISH_EIRE SUBLANG_DEFAULT 
3648 #ifndef SUBLANG_ENGLISH_JAMAICA 
3649 #define SUBLANG_ENGLISH_JAMAICA SUBLANG_DEFAULT 
3651 #ifndef SUBLANG_ENGLISH_NZ 
3652 #define SUBLANG_ENGLISH_NZ SUBLANG_DEFAULT 
3654 #ifndef SUBLANG_ENGLISH_PHILIPPINES 
3655 #define SUBLANG_ENGLISH_PHILIPPINES SUBLANG_DEFAULT 
3657 #ifndef SUBLANG_ENGLISH_SOUTH_AFRICA 
3658 #define SUBLANG_ENGLISH_SOUTH_AFRICA SUBLANG_DEFAULT 
3660 #ifndef SUBLANG_ENGLISH_TRINIDAD 
3661 #define SUBLANG_ENGLISH_TRINIDAD SUBLANG_DEFAULT 
3663 #ifndef SUBLANG_ENGLISH_ZIMBABWE 
3664 #define SUBLANG_ENGLISH_ZIMBABWE SUBLANG_DEFAULT 
3666 #ifndef SUBLANG_FRENCH 
3667 #define SUBLANG_FRENCH SUBLANG_DEFAULT 
3669 #ifndef SUBLANG_FRENCH_BELGIAN 
3670 #define SUBLANG_FRENCH_BELGIAN SUBLANG_DEFAULT 
3672 #ifndef SUBLANG_FRENCH_CANADIAN 
3673 #define SUBLANG_FRENCH_CANADIAN SUBLANG_DEFAULT 
3675 #ifndef SUBLANG_FRENCH_LUXEMBOURG 
3676 #define SUBLANG_FRENCH_LUXEMBOURG SUBLANG_DEFAULT 
3678 #ifndef SUBLANG_FRENCH_MONACO 
3679 #define SUBLANG_FRENCH_MONACO SUBLANG_DEFAULT 
3681 #ifndef SUBLANG_FRENCH_SWISS 
3682 #define SUBLANG_FRENCH_SWISS SUBLANG_DEFAULT 
3684 #ifndef SUBLANG_GERMAN 
3685 #define SUBLANG_GERMAN SUBLANG_DEFAULT 
3687 #ifndef SUBLANG_GERMAN_AUSTRIAN 
3688 #define SUBLANG_GERMAN_AUSTRIAN SUBLANG_DEFAULT 
3690 #ifndef SUBLANG_GERMAN_LIECHTENSTEIN 
3691 #define SUBLANG_GERMAN_LIECHTENSTEIN SUBLANG_DEFAULT 
3693 #ifndef SUBLANG_GERMAN_LUXEMBOURG 
3694 #define SUBLANG_GERMAN_LUXEMBOURG SUBLANG_DEFAULT 
3696 #ifndef SUBLANG_GERMAN_SWISS 
3697 #define SUBLANG_GERMAN_SWISS SUBLANG_DEFAULT 
3699 #ifndef SUBLANG_ITALIAN 
3700 #define SUBLANG_ITALIAN SUBLANG_DEFAULT 
3702 #ifndef SUBLANG_ITALIAN_SWISS 
3703 #define SUBLANG_ITALIAN_SWISS SUBLANG_DEFAULT 
3705 #ifndef SUBLANG_KASHMIRI_INDIA 
3706 #define SUBLANG_KASHMIRI_INDIA SUBLANG_DEFAULT 
3708 #ifndef SUBLANG_KOREAN 
3709 #define SUBLANG_KOREAN SUBLANG_DEFAULT 
3711 #ifndef SUBLANG_LITHUANIAN 
3712 #define SUBLANG_LITHUANIAN SUBLANG_DEFAULT 
3714 #ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM 
3715 #define SUBLANG_MALAY_BRUNEI_DARUSSALAM SUBLANG_DEFAULT 
3717 #ifndef SUBLANG_MALAY_MALAYSIA 
3718 #define SUBLANG_MALAY_MALAYSIA SUBLANG_DEFAULT 
3720 #ifndef SUBLANG_NEPALI_INDIA 
3721 #define SUBLANG_NEPALI_INDIA SUBLANG_DEFAULT 
3723 #ifndef SUBLANG_NORWEGIAN_BOKMAL 
3724 #define SUBLANG_NORWEGIAN_BOKMAL SUBLANG_DEFAULT 
3726 #ifndef SUBLANG_NORWEGIAN_NYNORSK 
3727 #define SUBLANG_NORWEGIAN_NYNORSK SUBLANG_DEFAULT 
3729 #ifndef SUBLANG_PORTUGUESE 
3730 #define SUBLANG_PORTUGUESE SUBLANG_DEFAULT 
3732 #ifndef SUBLANG_PORTUGUESE_BRAZILIAN 
3733 #define SUBLANG_PORTUGUESE_BRAZILIAN SUBLANG_DEFAULT 
3735 #ifndef SUBLANG_SERBIAN_CYRILLIC 
3736 #define SUBLANG_SERBIAN_CYRILLIC SUBLANG_DEFAULT 
3738 #ifndef SUBLANG_SERBIAN_LATIN 
3739 #define SUBLANG_SERBIAN_LATIN SUBLANG_DEFAULT 
3741 #ifndef SUBLANG_SPANISH 
3742 #define SUBLANG_SPANISH SUBLANG_DEFAULT 
3744 #ifndef SUBLANG_SPANISH_ARGENTINA 
3745 #define SUBLANG_SPANISH_ARGENTINA SUBLANG_DEFAULT 
3747 #ifndef SUBLANG_SPANISH_BOLIVIA 
3748 #define SUBLANG_SPANISH_BOLIVIA SUBLANG_DEFAULT 
3750 #ifndef SUBLANG_SPANISH_CHILE 
3751 #define SUBLANG_SPANISH_CHILE SUBLANG_DEFAULT 
3753 #ifndef SUBLANG_SPANISH_COLOMBIA 
3754 #define SUBLANG_SPANISH_COLOMBIA SUBLANG_DEFAULT 
3756 #ifndef SUBLANG_SPANISH_COSTA_RICA 
3757 #define SUBLANG_SPANISH_COSTA_RICA SUBLANG_DEFAULT 
3759 #ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC 
3760 #define SUBLANG_SPANISH_DOMINICAN_REPUBLIC SUBLANG_DEFAULT 
3762 #ifndef SUBLANG_SPANISH_ECUADOR 
3763 #define SUBLANG_SPANISH_ECUADOR SUBLANG_DEFAULT 
3765 #ifndef SUBLANG_SPANISH_EL_SALVADOR 
3766 #define SUBLANG_SPANISH_EL_SALVADOR SUBLANG_DEFAULT 
3768 #ifndef SUBLANG_SPANISH_GUATEMALA 
3769 #define SUBLANG_SPANISH_GUATEMALA SUBLANG_DEFAULT 
3771 #ifndef SUBLANG_SPANISH_HONDURAS 
3772 #define SUBLANG_SPANISH_HONDURAS SUBLANG_DEFAULT 
3774 #ifndef SUBLANG_SPANISH_MEXICAN 
3775 #define SUBLANG_SPANISH_MEXICAN SUBLANG_DEFAULT 
3777 #ifndef SUBLANG_SPANISH_MODERN 
3778 #define SUBLANG_SPANISH_MODERN SUBLANG_DEFAULT 
3780 #ifndef SUBLANG_SPANISH_NICARAGUA 
3781 #define SUBLANG_SPANISH_NICARAGUA SUBLANG_DEFAULT 
3783 #ifndef SUBLANG_SPANISH_PANAMA 
3784 #define SUBLANG_SPANISH_PANAMA SUBLANG_DEFAULT 
3786 #ifndef SUBLANG_SPANISH_PARAGUAY 
3787 #define SUBLANG_SPANISH_PARAGUAY SUBLANG_DEFAULT 
3789 #ifndef SUBLANG_SPANISH_PERU 
3790 #define SUBLANG_SPANISH_PERU SUBLANG_DEFAULT 
3792 #ifndef SUBLANG_SPANISH_PUERTO_RICO 
3793 #define SUBLANG_SPANISH_PUERTO_RICO SUBLANG_DEFAULT 
3795 #ifndef SUBLANG_SPANISH_URUGUAY 
3796 #define SUBLANG_SPANISH_URUGUAY SUBLANG_DEFAULT 
3798 #ifndef SUBLANG_SPANISH_VENEZUELA 
3799 #define SUBLANG_SPANISH_VENEZUELA SUBLANG_DEFAULT 
3801 #ifndef SUBLANG_SWEDISH 
3802 #define SUBLANG_SWEDISH SUBLANG_DEFAULT 
3804 #ifndef SUBLANG_SWEDISH_FINLAND 
3805 #define SUBLANG_SWEDISH_FINLAND SUBLANG_DEFAULT 
3807 #ifndef SUBLANG_URDU_INDIA 
3808 #define SUBLANG_URDU_INDIA SUBLANG_DEFAULT 
3810 #ifndef SUBLANG_URDU_PAKISTAN 
3811 #define SUBLANG_URDU_PAKISTAN SUBLANG_DEFAULT 
3813 #ifndef SUBLANG_UZBEK_CYRILLIC 
3814 #define SUBLANG_UZBEK_CYRILLIC SUBLANG_DEFAULT 
3816 #ifndef SUBLANG_UZBEK_LATIN 
3817 #define SUBLANG_UZBEK_LATIN SUBLANG_DEFAULT 
3823 #define LNG(wxlang, canonical, winlang, winsublang, layout, desc) \ 
3824     info.Language = wxlang;                               \ 
3825     info.CanonicalName = wxT(canonical);                  \ 
3826     info.LayoutDirection = layout;                        \ 
3827     info.Description = wxT(desc);                         \ 
3828     SETWINLANG(info, winlang, winsublang)                 \ 
3831 void wxLocale::InitLanguagesDB() 
3833    wxLanguageInfo info
; 
3834    wxStringTokenizer tkn
; 
3836    LNG(wxLANGUAGE_ABKHAZIAN
,                  "ab"   , 0              , 0                                 , wxLayout_LeftToRight
, "Abkhazian") 
3837    LNG(wxLANGUAGE_AFAR
,                       "aa"   , 0              , 0                                 , wxLayout_LeftToRight
, "Afar") 
3838    LNG(wxLANGUAGE_AFRIKAANS
,                  "af_ZA", LANG_AFRIKAANS 
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Afrikaans") 
3839    LNG(wxLANGUAGE_ALBANIAN
,                   "sq_AL", LANG_ALBANIAN  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Albanian") 
3840    LNG(wxLANGUAGE_AMHARIC
,                    "am"   , 0              , 0                                 , wxLayout_LeftToRight
, "Amharic") 
3841    LNG(wxLANGUAGE_ARABIC
,                     "ar"   , LANG_ARABIC    
, SUBLANG_DEFAULT                   
, wxLayout_RightToLeft
, "Arabic") 
3842    LNG(wxLANGUAGE_ARABIC_ALGERIA
,             "ar_DZ", LANG_ARABIC    
, SUBLANG_ARABIC_ALGERIA            
, wxLayout_RightToLeft
, "Arabic (Algeria)") 
3843    LNG(wxLANGUAGE_ARABIC_BAHRAIN
,             "ar_BH", LANG_ARABIC    
, SUBLANG_ARABIC_BAHRAIN            
, wxLayout_RightToLeft
, "Arabic (Bahrain)") 
3844    LNG(wxLANGUAGE_ARABIC_EGYPT
,               "ar_EG", LANG_ARABIC    
, SUBLANG_ARABIC_EGYPT              
, wxLayout_RightToLeft
, "Arabic (Egypt)") 
3845    LNG(wxLANGUAGE_ARABIC_IRAQ
,                "ar_IQ", LANG_ARABIC    
, SUBLANG_ARABIC_IRAQ               
, wxLayout_RightToLeft
, "Arabic (Iraq)") 
3846    LNG(wxLANGUAGE_ARABIC_JORDAN
,              "ar_JO", LANG_ARABIC    
, SUBLANG_ARABIC_JORDAN             
, wxLayout_RightToLeft
, "Arabic (Jordan)") 
3847    LNG(wxLANGUAGE_ARABIC_KUWAIT
,              "ar_KW", LANG_ARABIC    
, SUBLANG_ARABIC_KUWAIT             
, wxLayout_RightToLeft
, "Arabic (Kuwait)") 
3848    LNG(wxLANGUAGE_ARABIC_LEBANON
,             "ar_LB", LANG_ARABIC    
, SUBLANG_ARABIC_LEBANON            
, wxLayout_RightToLeft
, "Arabic (Lebanon)") 
3849    LNG(wxLANGUAGE_ARABIC_LIBYA
,               "ar_LY", LANG_ARABIC    
, SUBLANG_ARABIC_LIBYA              
, wxLayout_RightToLeft
, "Arabic (Libya)") 
3850    LNG(wxLANGUAGE_ARABIC_MOROCCO
,             "ar_MA", LANG_ARABIC    
, SUBLANG_ARABIC_MOROCCO            
, wxLayout_RightToLeft
, "Arabic (Morocco)") 
3851    LNG(wxLANGUAGE_ARABIC_OMAN
,                "ar_OM", LANG_ARABIC    
, SUBLANG_ARABIC_OMAN               
, wxLayout_RightToLeft
, "Arabic (Oman)") 
3852    LNG(wxLANGUAGE_ARABIC_QATAR
,               "ar_QA", LANG_ARABIC    
, SUBLANG_ARABIC_QATAR              
, wxLayout_RightToLeft
, "Arabic (Qatar)") 
3853    LNG(wxLANGUAGE_ARABIC_SAUDI_ARABIA
,        "ar_SA", LANG_ARABIC    
, SUBLANG_ARABIC_SAUDI_ARABIA       
, wxLayout_RightToLeft
, "Arabic (Saudi Arabia)") 
3854    LNG(wxLANGUAGE_ARABIC_SUDAN
,               "ar_SD", 0              , 0                                 , wxLayout_RightToLeft
, "Arabic (Sudan)") 
3855    LNG(wxLANGUAGE_ARABIC_SYRIA
,               "ar_SY", LANG_ARABIC    
, SUBLANG_ARABIC_SYRIA              
, wxLayout_RightToLeft
, "Arabic (Syria)") 
3856    LNG(wxLANGUAGE_ARABIC_TUNISIA
,             "ar_TN", LANG_ARABIC    
, SUBLANG_ARABIC_TUNISIA            
, wxLayout_RightToLeft
, "Arabic (Tunisia)") 
3857    LNG(wxLANGUAGE_ARABIC_UAE
,                 "ar_AE", LANG_ARABIC    
, SUBLANG_ARABIC_UAE                
, wxLayout_RightToLeft
, "Arabic (Uae)") 
3858    LNG(wxLANGUAGE_ARABIC_YEMEN
,               "ar_YE", LANG_ARABIC    
, SUBLANG_ARABIC_YEMEN              
, wxLayout_RightToLeft
, "Arabic (Yemen)") 
3859    LNG(wxLANGUAGE_ARMENIAN
,                   "hy"   , LANG_ARMENIAN  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Armenian") 
3860    LNG(wxLANGUAGE_ASSAMESE
,                   "as"   , LANG_ASSAMESE  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Assamese") 
3861    LNG(wxLANGUAGE_ASTURIAN
,                   "ast"  , 0              , 0                                 , wxLayout_LeftToRight
, "Asturian") 
3862    LNG(wxLANGUAGE_AYMARA
,                     "ay"   , 0              , 0                                 , wxLayout_LeftToRight
, "Aymara") 
3863    LNG(wxLANGUAGE_AZERI
,                      "az"   , LANG_AZERI     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Azeri") 
3864    LNG(wxLANGUAGE_AZERI_CYRILLIC
,             "az"   , LANG_AZERI     
, SUBLANG_AZERI_CYRILLIC            
, wxLayout_LeftToRight
, "Azeri (Cyrillic)") 
3865    LNG(wxLANGUAGE_AZERI_LATIN
,                "az"   , LANG_AZERI     
, SUBLANG_AZERI_LATIN               
, wxLayout_LeftToRight
, "Azeri (Latin)") 
3866    LNG(wxLANGUAGE_BASHKIR
,                    "ba"   , 0              , 0                                 , wxLayout_LeftToRight
, "Bashkir") 
3867    LNG(wxLANGUAGE_BASQUE
,                     "eu_ES", LANG_BASQUE    
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Basque") 
3868    LNG(wxLANGUAGE_BELARUSIAN
,                 "be_BY", LANG_BELARUSIAN
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Belarusian") 
3869    LNG(wxLANGUAGE_BENGALI
,                    "bn"   , LANG_BENGALI   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Bengali") 
3870    LNG(wxLANGUAGE_BHUTANI
,                    "dz"   , 0              , 0                                 , wxLayout_LeftToRight
, "Bhutani") 
3871    LNG(wxLANGUAGE_BIHARI
,                     "bh"   , 0              , 0                                 , wxLayout_LeftToRight
, "Bihari") 
3872    LNG(wxLANGUAGE_BISLAMA
,                    "bi"   , 0              , 0                                 , wxLayout_LeftToRight
, "Bislama") 
3873    LNG(wxLANGUAGE_BRETON
,                     "br"   , 0              , 0                                 , wxLayout_LeftToRight
, "Breton") 
3874    LNG(wxLANGUAGE_BULGARIAN
,                  "bg_BG", LANG_BULGARIAN 
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Bulgarian") 
3875    LNG(wxLANGUAGE_BURMESE
,                    "my"   , 0              , 0                                 , wxLayout_LeftToRight
, "Burmese") 
3876    LNG(wxLANGUAGE_CAMBODIAN
,                  "km"   , 0              , 0                                 , wxLayout_LeftToRight
, "Cambodian") 
3877    LNG(wxLANGUAGE_CATALAN
,                    "ca_ES", LANG_CATALAN   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Catalan") 
3878    LNG(wxLANGUAGE_CHINESE
,                    "zh_TW", LANG_CHINESE   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Chinese") 
3879    LNG(wxLANGUAGE_CHINESE_SIMPLIFIED
,         "zh_CN", LANG_CHINESE   
, SUBLANG_CHINESE_SIMPLIFIED        
, wxLayout_LeftToRight
, "Chinese (Simplified)") 
3880    LNG(wxLANGUAGE_CHINESE_TRADITIONAL
,        "zh_TW", LANG_CHINESE   
, SUBLANG_CHINESE_TRADITIONAL       
, wxLayout_LeftToRight
, "Chinese (Traditional)") 
3881    LNG(wxLANGUAGE_CHINESE_HONGKONG
,           "zh_HK", LANG_CHINESE   
, SUBLANG_CHINESE_HONGKONG          
, wxLayout_LeftToRight
, "Chinese (Hongkong)") 
3882    LNG(wxLANGUAGE_CHINESE_MACAU
,              "zh_MO", LANG_CHINESE   
, SUBLANG_CHINESE_MACAU             
, wxLayout_LeftToRight
, "Chinese (Macau)") 
3883    LNG(wxLANGUAGE_CHINESE_SINGAPORE
,          "zh_SG", LANG_CHINESE   
, SUBLANG_CHINESE_SINGAPORE         
, wxLayout_LeftToRight
, "Chinese (Singapore)") 
3884    LNG(wxLANGUAGE_CHINESE_TAIWAN
,             "zh_TW", LANG_CHINESE   
, SUBLANG_CHINESE_TRADITIONAL       
, wxLayout_LeftToRight
, "Chinese (Taiwan)") 
3885    LNG(wxLANGUAGE_CORSICAN
,                   "co"   , 0              , 0                                 , wxLayout_LeftToRight
, "Corsican") 
3886    LNG(wxLANGUAGE_CROATIAN
,                   "hr_HR", LANG_CROATIAN  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Croatian") 
3887    LNG(wxLANGUAGE_CZECH
,                      "cs_CZ", LANG_CZECH     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Czech") 
3888    LNG(wxLANGUAGE_DANISH
,                     "da_DK", LANG_DANISH    
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Danish") 
3889    LNG(wxLANGUAGE_DUTCH
,                      "nl_NL", LANG_DUTCH     
, SUBLANG_DUTCH                     
, wxLayout_LeftToRight
, "Dutch") 
3890    LNG(wxLANGUAGE_DUTCH_BELGIAN
,              "nl_BE", LANG_DUTCH     
, SUBLANG_DUTCH_BELGIAN             
, wxLayout_LeftToRight
, "Dutch (Belgian)") 
3891    LNG(wxLANGUAGE_ENGLISH
,                    "en_GB", LANG_ENGLISH   
, SUBLANG_ENGLISH_UK                
, wxLayout_LeftToRight
, "English") 
3892    LNG(wxLANGUAGE_ENGLISH_UK
,                 "en_GB", LANG_ENGLISH   
, SUBLANG_ENGLISH_UK                
, wxLayout_LeftToRight
, "English (U.K.)") 
3893    LNG(wxLANGUAGE_ENGLISH_US
,                 "en_US", LANG_ENGLISH   
, SUBLANG_ENGLISH_US                
, wxLayout_LeftToRight
, "English (U.S.)") 
3894    LNG(wxLANGUAGE_ENGLISH_AUSTRALIA
,          "en_AU", LANG_ENGLISH   
, SUBLANG_ENGLISH_AUS               
, wxLayout_LeftToRight
, "English (Australia)") 
3895    LNG(wxLANGUAGE_ENGLISH_BELIZE
,             "en_BZ", LANG_ENGLISH   
, SUBLANG_ENGLISH_BELIZE            
, wxLayout_LeftToRight
, "English (Belize)") 
3896    LNG(wxLANGUAGE_ENGLISH_BOTSWANA
,           "en_BW", 0              , 0                                 , wxLayout_LeftToRight
, "English (Botswana)") 
3897    LNG(wxLANGUAGE_ENGLISH_CANADA
,             "en_CA", LANG_ENGLISH   
, SUBLANG_ENGLISH_CAN               
, wxLayout_LeftToRight
, "English (Canada)") 
3898    LNG(wxLANGUAGE_ENGLISH_CARIBBEAN
,          "en_CB", LANG_ENGLISH   
, SUBLANG_ENGLISH_CARIBBEAN         
, wxLayout_LeftToRight
, "English (Caribbean)") 
3899    LNG(wxLANGUAGE_ENGLISH_DENMARK
,            "en_DK", 0              , 0                                 , wxLayout_LeftToRight
, "English (Denmark)") 
3900    LNG(wxLANGUAGE_ENGLISH_EIRE
,               "en_IE", LANG_ENGLISH   
, SUBLANG_ENGLISH_EIRE              
, wxLayout_LeftToRight
, "English (Eire)") 
3901    LNG(wxLANGUAGE_ENGLISH_JAMAICA
,            "en_JM", LANG_ENGLISH   
, SUBLANG_ENGLISH_JAMAICA           
, wxLayout_LeftToRight
, "English (Jamaica)") 
3902    LNG(wxLANGUAGE_ENGLISH_NEW_ZEALAND
,        "en_NZ", LANG_ENGLISH   
, SUBLANG_ENGLISH_NZ                
, wxLayout_LeftToRight
, "English (New Zealand)") 
3903    LNG(wxLANGUAGE_ENGLISH_PHILIPPINES
,        "en_PH", LANG_ENGLISH   
, SUBLANG_ENGLISH_PHILIPPINES       
, wxLayout_LeftToRight
, "English (Philippines)") 
3904    LNG(wxLANGUAGE_ENGLISH_SOUTH_AFRICA
,       "en_ZA", LANG_ENGLISH   
, SUBLANG_ENGLISH_SOUTH_AFRICA      
, wxLayout_LeftToRight
, "English (South Africa)") 
3905    LNG(wxLANGUAGE_ENGLISH_TRINIDAD
,           "en_TT", LANG_ENGLISH   
, SUBLANG_ENGLISH_TRINIDAD          
, wxLayout_LeftToRight
, "English (Trinidad)") 
3906    LNG(wxLANGUAGE_ENGLISH_ZIMBABWE
,           "en_ZW", LANG_ENGLISH   
, SUBLANG_ENGLISH_ZIMBABWE          
, wxLayout_LeftToRight
, "English (Zimbabwe)") 
3907    LNG(wxLANGUAGE_ESPERANTO
,                  "eo"   , 0              , 0                                 , wxLayout_LeftToRight
, "Esperanto") 
3908    LNG(wxLANGUAGE_ESTONIAN
,                   "et_EE", LANG_ESTONIAN  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Estonian") 
3909    LNG(wxLANGUAGE_FAEROESE
,                   "fo_FO", LANG_FAEROESE  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Faeroese") 
3910    LNG(wxLANGUAGE_FARSI
,                      "fa_IR", LANG_FARSI     
, SUBLANG_DEFAULT                   
, wxLayout_RightToLeft
, "Farsi") 
3911    LNG(wxLANGUAGE_FIJI
,                       "fj"   , 0              , 0                                 , wxLayout_LeftToRight
, "Fiji") 
3912    LNG(wxLANGUAGE_FINNISH
,                    "fi_FI", LANG_FINNISH   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Finnish") 
3913    LNG(wxLANGUAGE_FRENCH
,                     "fr_FR", LANG_FRENCH    
, SUBLANG_FRENCH                    
, wxLayout_LeftToRight
, "French") 
3914    LNG(wxLANGUAGE_FRENCH_BELGIAN
,             "fr_BE", LANG_FRENCH    
, SUBLANG_FRENCH_BELGIAN            
, wxLayout_LeftToRight
, "French (Belgian)") 
3915    LNG(wxLANGUAGE_FRENCH_CANADIAN
,            "fr_CA", LANG_FRENCH    
, SUBLANG_FRENCH_CANADIAN           
, wxLayout_LeftToRight
, "French (Canadian)") 
3916    LNG(wxLANGUAGE_FRENCH_LUXEMBOURG
,          "fr_LU", LANG_FRENCH    
, SUBLANG_FRENCH_LUXEMBOURG         
, wxLayout_LeftToRight
, "French (Luxembourg)") 
3917    LNG(wxLANGUAGE_FRENCH_MONACO
,              "fr_MC", LANG_FRENCH    
, SUBLANG_FRENCH_MONACO             
, wxLayout_LeftToRight
, "French (Monaco)") 
3918    LNG(wxLANGUAGE_FRENCH_SWISS
,               "fr_CH", LANG_FRENCH    
, SUBLANG_FRENCH_SWISS              
, wxLayout_LeftToRight
, "French (Swiss)") 
3919    LNG(wxLANGUAGE_FRISIAN
,                    "fy"   , 0              , 0                                 , wxLayout_LeftToRight
, "Frisian") 
3920    LNG(wxLANGUAGE_GALICIAN
,                   "gl_ES", 0              , 0                                 , wxLayout_LeftToRight
, "Galician") 
3921    LNG(wxLANGUAGE_GEORGIAN
,                   "ka_GE", LANG_GEORGIAN  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Georgian") 
3922    LNG(wxLANGUAGE_GERMAN
,                     "de_DE", LANG_GERMAN    
, SUBLANG_GERMAN                    
, wxLayout_LeftToRight
, "German") 
3923    LNG(wxLANGUAGE_GERMAN_AUSTRIAN
,            "de_AT", LANG_GERMAN    
, SUBLANG_GERMAN_AUSTRIAN           
, wxLayout_LeftToRight
, "German (Austrian)") 
3924    LNG(wxLANGUAGE_GERMAN_BELGIUM
,             "de_BE", 0              , 0                                 , wxLayout_LeftToRight
, "German (Belgium)") 
3925    LNG(wxLANGUAGE_GERMAN_LIECHTENSTEIN
,       "de_LI", LANG_GERMAN    
, SUBLANG_GERMAN_LIECHTENSTEIN      
, wxLayout_LeftToRight
, "German (Liechtenstein)") 
3926    LNG(wxLANGUAGE_GERMAN_LUXEMBOURG
,          "de_LU", LANG_GERMAN    
, SUBLANG_GERMAN_LUXEMBOURG         
, wxLayout_LeftToRight
, "German (Luxembourg)") 
3927    LNG(wxLANGUAGE_GERMAN_SWISS
,               "de_CH", LANG_GERMAN    
, SUBLANG_GERMAN_SWISS              
, wxLayout_LeftToRight
, "German (Swiss)") 
3928    LNG(wxLANGUAGE_GREEK
,                      "el_GR", LANG_GREEK     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Greek") 
3929    LNG(wxLANGUAGE_GREENLANDIC
,                "kl_GL", 0              , 0                                 , wxLayout_LeftToRight
, "Greenlandic") 
3930    LNG(wxLANGUAGE_GUARANI
,                    "gn"   , 0              , 0                                 , wxLayout_LeftToRight
, "Guarani") 
3931    LNG(wxLANGUAGE_GUJARATI
,                   "gu"   , LANG_GUJARATI  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Gujarati") 
3932    LNG(wxLANGUAGE_HAUSA
,                      "ha"   , 0              , 0                                 , wxLayout_LeftToRight
, "Hausa") 
3933    LNG(wxLANGUAGE_HEBREW
,                     "he_IL", LANG_HEBREW    
, SUBLANG_DEFAULT                   
, wxLayout_RightToLeft
, "Hebrew") 
3934    LNG(wxLANGUAGE_HINDI
,                      "hi_IN", LANG_HINDI     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Hindi") 
3935    LNG(wxLANGUAGE_HUNGARIAN
,                  "hu_HU", LANG_HUNGARIAN 
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Hungarian") 
3936    LNG(wxLANGUAGE_ICELANDIC
,                  "is_IS", LANG_ICELANDIC 
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Icelandic") 
3937    LNG(wxLANGUAGE_INDONESIAN
,                 "id_ID", LANG_INDONESIAN
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Indonesian") 
3938    LNG(wxLANGUAGE_INTERLINGUA
,                "ia"   , 0              , 0                                 , wxLayout_LeftToRight
, "Interlingua") 
3939    LNG(wxLANGUAGE_INTERLINGUE
,                "ie"   , 0              , 0                                 , wxLayout_LeftToRight
, "Interlingue") 
3940    LNG(wxLANGUAGE_INUKTITUT
,                  "iu"   , 0              , 0                                 , wxLayout_LeftToRight
, "Inuktitut") 
3941    LNG(wxLANGUAGE_INUPIAK
,                    "ik"   , 0              , 0                                 , wxLayout_LeftToRight
, "Inupiak") 
3942    LNG(wxLANGUAGE_IRISH
,                      "ga_IE", 0              , 0                                 , wxLayout_LeftToRight
, "Irish") 
3943    LNG(wxLANGUAGE_ITALIAN
,                    "it_IT", LANG_ITALIAN   
, SUBLANG_ITALIAN                   
, wxLayout_LeftToRight
, "Italian") 
3944    LNG(wxLANGUAGE_ITALIAN_SWISS
,              "it_CH", LANG_ITALIAN   
, SUBLANG_ITALIAN_SWISS             
, wxLayout_LeftToRight
, "Italian (Swiss)") 
3945    LNG(wxLANGUAGE_JAPANESE
,                   "ja_JP", LANG_JAPANESE  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Japanese") 
3946    LNG(wxLANGUAGE_JAVANESE
,                   "jw"   , 0              , 0                                 , wxLayout_LeftToRight
, "Javanese") 
3947    LNG(wxLANGUAGE_KANNADA
,                    "kn"   , LANG_KANNADA   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Kannada") 
3948    LNG(wxLANGUAGE_KASHMIRI
,                   "ks"   , LANG_KASHMIRI  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Kashmiri") 
3949    LNG(wxLANGUAGE_KASHMIRI_INDIA
,             "ks_IN", LANG_KASHMIRI  
, SUBLANG_KASHMIRI_INDIA            
, wxLayout_LeftToRight
, "Kashmiri (India)") 
3950    LNG(wxLANGUAGE_KAZAKH
,                     "kk"   , LANG_KAZAK     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Kazakh") 
3951    LNG(wxLANGUAGE_KERNEWEK
,                   "kw_GB", 0              , 0                                 , wxLayout_LeftToRight
, "Kernewek") 
3952    LNG(wxLANGUAGE_KINYARWANDA
,                "rw"   , 0              , 0                                 , wxLayout_LeftToRight
, "Kinyarwanda") 
3953    LNG(wxLANGUAGE_KIRGHIZ
,                    "ky"   , 0              , 0                                 , wxLayout_LeftToRight
, "Kirghiz") 
3954    LNG(wxLANGUAGE_KIRUNDI
,                    "rn"   , 0              , 0                                 , wxLayout_LeftToRight
, "Kirundi") 
3955    LNG(wxLANGUAGE_KONKANI
,                    ""     , LANG_KONKANI   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Konkani") 
3956    LNG(wxLANGUAGE_KOREAN
,                     "ko_KR", LANG_KOREAN    
, SUBLANG_KOREAN                    
, wxLayout_LeftToRight
, "Korean") 
3957    LNG(wxLANGUAGE_KURDISH
,                    "ku_TR", 0              , 0                                 , wxLayout_LeftToRight
, "Kurdish") 
3958    LNG(wxLANGUAGE_LAOTHIAN
,                   "lo"   , 0              , 0                                 , wxLayout_LeftToRight
, "Laothian") 
3959    LNG(wxLANGUAGE_LATIN
,                      "la"   , 0              , 0                                 , wxLayout_LeftToRight
, "Latin") 
3960    LNG(wxLANGUAGE_LATVIAN
,                    "lv_LV", LANG_LATVIAN   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Latvian") 
3961    LNG(wxLANGUAGE_LINGALA
,                    "ln"   , 0              , 0                                 , wxLayout_LeftToRight
, "Lingala") 
3962    LNG(wxLANGUAGE_LITHUANIAN
,                 "lt_LT", LANG_LITHUANIAN
, SUBLANG_LITHUANIAN                
, wxLayout_LeftToRight
, "Lithuanian") 
3963    LNG(wxLANGUAGE_MACEDONIAN
,                 "mk_MK", LANG_MACEDONIAN
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Macedonian") 
3964    LNG(wxLANGUAGE_MALAGASY
,                   "mg"   , 0              , 0                                 , wxLayout_LeftToRight
, "Malagasy") 
3965    LNG(wxLANGUAGE_MALAY
,                      "ms_MY", LANG_MALAY     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Malay") 
3966    LNG(wxLANGUAGE_MALAYALAM
,                  "ml"   , LANG_MALAYALAM 
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Malayalam") 
3967    LNG(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM
,    "ms_BN", LANG_MALAY     
, SUBLANG_MALAY_BRUNEI_DARUSSALAM   
, wxLayout_LeftToRight
, "Malay (Brunei Darussalam)") 
3968    LNG(wxLANGUAGE_MALAY_MALAYSIA
,             "ms_MY", LANG_MALAY     
, SUBLANG_MALAY_MALAYSIA            
, wxLayout_LeftToRight
, "Malay (Malaysia)") 
3969    LNG(wxLANGUAGE_MALTESE
,                    "mt_MT", 0              , 0                                 , wxLayout_LeftToRight
, "Maltese") 
3970    LNG(wxLANGUAGE_MANIPURI
,                   ""     , LANG_MANIPURI  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Manipuri") 
3971    LNG(wxLANGUAGE_MAORI
,                      "mi"   , 0              , 0                                 , wxLayout_LeftToRight
, "Maori") 
3972    LNG(wxLANGUAGE_MARATHI
,                    "mr_IN", LANG_MARATHI   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Marathi") 
3973    LNG(wxLANGUAGE_MOLDAVIAN
,                  "mo"   , 0              , 0                                 , wxLayout_LeftToRight
, "Moldavian") 
3974    LNG(wxLANGUAGE_MONGOLIAN
,                  "mn"   , 0              , 0                                 , wxLayout_LeftToRight
, "Mongolian") 
3975    LNG(wxLANGUAGE_NAURU
,                      "na"   , 0              , 0                                 , wxLayout_LeftToRight
, "Nauru") 
3976    LNG(wxLANGUAGE_NEPALI
,                     "ne_NP", LANG_NEPALI    
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Nepali") 
3977    LNG(wxLANGUAGE_NEPALI_INDIA
,               "ne_IN", LANG_NEPALI    
, SUBLANG_NEPALI_INDIA              
, wxLayout_LeftToRight
, "Nepali (India)") 
3978    LNG(wxLANGUAGE_NORWEGIAN_BOKMAL
,           "nb_NO", LANG_NORWEGIAN 
, SUBLANG_NORWEGIAN_BOKMAL          
, wxLayout_LeftToRight
, "Norwegian (Bokmal)") 
3979    LNG(wxLANGUAGE_NORWEGIAN_NYNORSK
,          "nn_NO", LANG_NORWEGIAN 
, SUBLANG_NORWEGIAN_NYNORSK         
, wxLayout_LeftToRight
, "Norwegian (Nynorsk)") 
3980    LNG(wxLANGUAGE_OCCITAN
,                    "oc"   , 0              , 0                                 , wxLayout_LeftToRight
, "Occitan") 
3981    LNG(wxLANGUAGE_ORIYA
,                      "or"   , LANG_ORIYA     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Oriya") 
3982    LNG(wxLANGUAGE_OROMO
,                      "om"   , 0              , 0                                 , wxLayout_LeftToRight
, "(Afan) Oromo") 
3983    LNG(wxLANGUAGE_PASHTO
,                     "ps"   , 0              , 0                                 , wxLayout_LeftToRight
, "Pashto, Pushto") 
3984    LNG(wxLANGUAGE_POLISH
,                     "pl_PL", LANG_POLISH    
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Polish") 
3985    LNG(wxLANGUAGE_PORTUGUESE
,                 "pt_PT", LANG_PORTUGUESE
, SUBLANG_PORTUGUESE                
, wxLayout_LeftToRight
, "Portuguese") 
3986    LNG(wxLANGUAGE_PORTUGUESE_BRAZILIAN
,       "pt_BR", LANG_PORTUGUESE
, SUBLANG_PORTUGUESE_BRAZILIAN      
, wxLayout_LeftToRight
, "Portuguese (Brazilian)") 
3987    LNG(wxLANGUAGE_PUNJABI
,                    "pa"   , LANG_PUNJABI   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Punjabi") 
3988    LNG(wxLANGUAGE_QUECHUA
,                    "qu"   , 0              , 0                                 , wxLayout_LeftToRight
, "Quechua") 
3989    LNG(wxLANGUAGE_RHAETO_ROMANCE
,             "rm"   , 0              , 0                                 , wxLayout_LeftToRight
, "Rhaeto-Romance") 
3990    LNG(wxLANGUAGE_ROMANIAN
,                   "ro_RO", LANG_ROMANIAN  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Romanian") 
3991    LNG(wxLANGUAGE_RUSSIAN
,                    "ru_RU", LANG_RUSSIAN   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Russian") 
3992    LNG(wxLANGUAGE_RUSSIAN_UKRAINE
,            "ru_UA", 0              , 0                                 , wxLayout_LeftToRight
, "Russian (Ukraine)") 
3993    LNG(wxLANGUAGE_SAMI
,                       "se_NO", LANG_SAMI      
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Northern Sami") 
3994    LNG(wxLANGUAGE_SAMOAN
,                     "sm"   , 0              , 0                                 , wxLayout_LeftToRight
, "Samoan") 
3995    LNG(wxLANGUAGE_SANGHO
,                     "sg"   , 0              , 0                                 , wxLayout_LeftToRight
, "Sangho") 
3996    LNG(wxLANGUAGE_SANSKRIT
,                   "sa"   , LANG_SANSKRIT  
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Sanskrit") 
3997    LNG(wxLANGUAGE_SCOTS_GAELIC
,               "gd"   , 0              , 0                                 , wxLayout_LeftToRight
, "Scots Gaelic") 
3998    LNG(wxLANGUAGE_SERBIAN
,                    "sr_RS", LANG_SERBIAN   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Serbian") 
3999    LNG(wxLANGUAGE_SERBIAN_CYRILLIC
,           "sr_RS", LANG_SERBIAN   
, SUBLANG_SERBIAN_CYRILLIC          
, wxLayout_LeftToRight
, "Serbian (Cyrillic)") 
4000    LNG(wxLANGUAGE_SERBIAN_LATIN
,              "sr_RS@latin", LANG_SERBIAN   
, SUBLANG_SERBIAN_LATIN             
, wxLayout_LeftToRight
, "Serbian (Latin)") 
4001    LNG(wxLANGUAGE_SERBIAN_CYRILLIC
,           "sr_YU", LANG_SERBIAN   
, SUBLANG_SERBIAN_CYRILLIC          
, wxLayout_LeftToRight
, "Serbian (Cyrillic)") 
4002    LNG(wxLANGUAGE_SERBIAN_LATIN
,              "sr_YU@latin", LANG_SERBIAN   
, SUBLANG_SERBIAN_LATIN             
, wxLayout_LeftToRight
, "Serbian (Latin)") 
4003    LNG(wxLANGUAGE_SERBO_CROATIAN
,             "sh"   , 0              , 0                                 , wxLayout_LeftToRight
, "Serbo-Croatian") 
4004    LNG(wxLANGUAGE_SESOTHO
,                    "st"   , 0              , 0                                 , wxLayout_LeftToRight
, "Sesotho") 
4005    LNG(wxLANGUAGE_SETSWANA
,                   "tn"   , 0              , 0                                 , wxLayout_LeftToRight
, "Setswana") 
4006    LNG(wxLANGUAGE_SHONA
,                      "sn"   , 0              , 0                                 , wxLayout_LeftToRight
, "Shona") 
4007    LNG(wxLANGUAGE_SINDHI
,                     "sd"   , LANG_SINDHI    
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Sindhi") 
4008    LNG(wxLANGUAGE_SINHALESE
,                  "si"   , 0              , 0                                 , wxLayout_LeftToRight
, "Sinhalese") 
4009    LNG(wxLANGUAGE_SISWATI
,                    "ss"   , 0              , 0                                 , wxLayout_LeftToRight
, "Siswati") 
4010    LNG(wxLANGUAGE_SLOVAK
,                     "sk_SK", LANG_SLOVAK    
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Slovak") 
4011    LNG(wxLANGUAGE_SLOVENIAN
,                  "sl_SI", LANG_SLOVENIAN 
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Slovenian") 
4012    LNG(wxLANGUAGE_SOMALI
,                     "so"   , 0              , 0                                 , wxLayout_LeftToRight
, "Somali") 
4013    LNG(wxLANGUAGE_SPANISH
,                    "es_ES", LANG_SPANISH   
, SUBLANG_SPANISH                   
, wxLayout_LeftToRight
, "Spanish") 
4014    LNG(wxLANGUAGE_SPANISH_ARGENTINA
,          "es_AR", LANG_SPANISH   
, SUBLANG_SPANISH_ARGENTINA         
, wxLayout_LeftToRight
, "Spanish (Argentina)") 
4015    LNG(wxLANGUAGE_SPANISH_BOLIVIA
,            "es_BO", LANG_SPANISH   
, SUBLANG_SPANISH_BOLIVIA           
, wxLayout_LeftToRight
, "Spanish (Bolivia)") 
4016    LNG(wxLANGUAGE_SPANISH_CHILE
,              "es_CL", LANG_SPANISH   
, SUBLANG_SPANISH_CHILE             
, wxLayout_LeftToRight
, "Spanish (Chile)") 
4017    LNG(wxLANGUAGE_SPANISH_COLOMBIA
,           "es_CO", LANG_SPANISH   
, SUBLANG_SPANISH_COLOMBIA          
, wxLayout_LeftToRight
, "Spanish (Colombia)") 
4018    LNG(wxLANGUAGE_SPANISH_COSTA_RICA
,         "es_CR", LANG_SPANISH   
, SUBLANG_SPANISH_COSTA_RICA        
, wxLayout_LeftToRight
, "Spanish (Costa Rica)") 
4019    LNG(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC
, "es_DO", LANG_SPANISH   
, SUBLANG_SPANISH_DOMINICAN_REPUBLIC
, wxLayout_LeftToRight
, "Spanish (Dominican republic)") 
4020    LNG(wxLANGUAGE_SPANISH_ECUADOR
,            "es_EC", LANG_SPANISH   
, SUBLANG_SPANISH_ECUADOR           
, wxLayout_LeftToRight
, "Spanish (Ecuador)") 
4021    LNG(wxLANGUAGE_SPANISH_EL_SALVADOR
,        "es_SV", LANG_SPANISH   
, SUBLANG_SPANISH_EL_SALVADOR       
, wxLayout_LeftToRight
, "Spanish (El Salvador)") 
4022    LNG(wxLANGUAGE_SPANISH_GUATEMALA
,          "es_GT", LANG_SPANISH   
, SUBLANG_SPANISH_GUATEMALA         
, wxLayout_LeftToRight
, "Spanish (Guatemala)") 
4023    LNG(wxLANGUAGE_SPANISH_HONDURAS
,           "es_HN", LANG_SPANISH   
, SUBLANG_SPANISH_HONDURAS          
, wxLayout_LeftToRight
, "Spanish (Honduras)") 
4024    LNG(wxLANGUAGE_SPANISH_MEXICAN
,            "es_MX", LANG_SPANISH   
, SUBLANG_SPANISH_MEXICAN           
, wxLayout_LeftToRight
, "Spanish (Mexican)") 
4025    LNG(wxLANGUAGE_SPANISH_MODERN
,             "es_ES", LANG_SPANISH   
, SUBLANG_SPANISH_MODERN            
, wxLayout_LeftToRight
, "Spanish (Modern)") 
4026    LNG(wxLANGUAGE_SPANISH_NICARAGUA
,          "es_NI", LANG_SPANISH   
, SUBLANG_SPANISH_NICARAGUA         
, wxLayout_LeftToRight
, "Spanish (Nicaragua)") 
4027    LNG(wxLANGUAGE_SPANISH_PANAMA
,             "es_PA", LANG_SPANISH   
, SUBLANG_SPANISH_PANAMA            
, wxLayout_LeftToRight
, "Spanish (Panama)") 
4028    LNG(wxLANGUAGE_SPANISH_PARAGUAY
,           "es_PY", LANG_SPANISH   
, SUBLANG_SPANISH_PARAGUAY          
, wxLayout_LeftToRight
, "Spanish (Paraguay)") 
4029    LNG(wxLANGUAGE_SPANISH_PERU
,               "es_PE", LANG_SPANISH   
, SUBLANG_SPANISH_PERU              
, wxLayout_LeftToRight
, "Spanish (Peru)") 
4030    LNG(wxLANGUAGE_SPANISH_PUERTO_RICO
,        "es_PR", LANG_SPANISH   
, SUBLANG_SPANISH_PUERTO_RICO       
, wxLayout_LeftToRight
, "Spanish (Puerto Rico)") 
4031    LNG(wxLANGUAGE_SPANISH_URUGUAY
,            "es_UY", LANG_SPANISH   
, SUBLANG_SPANISH_URUGUAY           
, wxLayout_LeftToRight
, "Spanish (Uruguay)") 
4032    LNG(wxLANGUAGE_SPANISH_US
,                 "es_US", 0              , 0                                 , wxLayout_LeftToRight
, "Spanish (U.S.)") 
4033    LNG(wxLANGUAGE_SPANISH_VENEZUELA
,          "es_VE", LANG_SPANISH   
, SUBLANG_SPANISH_VENEZUELA         
, wxLayout_LeftToRight
, "Spanish (Venezuela)") 
4034    LNG(wxLANGUAGE_SUNDANESE
,                  "su"   , 0              , 0                                 , wxLayout_LeftToRight
, "Sundanese") 
4035    LNG(wxLANGUAGE_SWAHILI
,                    "sw_KE", LANG_SWAHILI   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Swahili") 
4036    LNG(wxLANGUAGE_SWEDISH
,                    "sv_SE", LANG_SWEDISH   
, SUBLANG_SWEDISH                   
, wxLayout_LeftToRight
, "Swedish") 
4037    LNG(wxLANGUAGE_SWEDISH_FINLAND
,            "sv_FI", LANG_SWEDISH   
, SUBLANG_SWEDISH_FINLAND           
, wxLayout_LeftToRight
, "Swedish (Finland)") 
4038    LNG(wxLANGUAGE_TAGALOG
,                    "tl_PH", 0              , 0                                 , wxLayout_LeftToRight
, "Tagalog") 
4039    LNG(wxLANGUAGE_TAJIK
,                      "tg"   , 0              , 0                                 , wxLayout_LeftToRight
, "Tajik") 
4040    LNG(wxLANGUAGE_TAMIL
,                      "ta"   , LANG_TAMIL     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Tamil") 
4041    LNG(wxLANGUAGE_TATAR
,                      "tt"   , LANG_TATAR     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Tatar") 
4042    LNG(wxLANGUAGE_TELUGU
,                     "te"   , LANG_TELUGU    
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Telugu") 
4043    LNG(wxLANGUAGE_THAI
,                       "th_TH", LANG_THAI      
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Thai") 
4044    LNG(wxLANGUAGE_TIBETAN
,                    "bo"   , 0              , 0                                 , wxLayout_LeftToRight
, "Tibetan") 
4045    LNG(wxLANGUAGE_TIGRINYA
,                   "ti"   , 0              , 0                                 , wxLayout_LeftToRight
, "Tigrinya") 
4046    LNG(wxLANGUAGE_TONGA
,                      "to"   , 0              , 0                                 , wxLayout_LeftToRight
, "Tonga") 
4047    LNG(wxLANGUAGE_TSONGA
,                     "ts"   , 0              , 0                                 , wxLayout_LeftToRight
, "Tsonga") 
4048    LNG(wxLANGUAGE_TURKISH
,                    "tr_TR", LANG_TURKISH   
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Turkish") 
4049    LNG(wxLANGUAGE_TURKMEN
,                    "tk"   , 0              , 0                                 , wxLayout_LeftToRight
, "Turkmen") 
4050    LNG(wxLANGUAGE_TWI
,                        "tw"   , 0              , 0                                 , wxLayout_LeftToRight
, "Twi") 
4051    LNG(wxLANGUAGE_UIGHUR
,                     "ug"   , 0              , 0                                 , wxLayout_LeftToRight
, "Uighur") 
4052    LNG(wxLANGUAGE_UKRAINIAN
,                  "uk_UA", LANG_UKRAINIAN 
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Ukrainian") 
4053    LNG(wxLANGUAGE_URDU
,                       "ur"   , LANG_URDU      
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Urdu") 
4054    LNG(wxLANGUAGE_URDU_INDIA
,                 "ur_IN", LANG_URDU      
, SUBLANG_URDU_INDIA                
, wxLayout_LeftToRight
, "Urdu (India)") 
4055    LNG(wxLANGUAGE_URDU_PAKISTAN
,              "ur_PK", LANG_URDU      
, SUBLANG_URDU_PAKISTAN             
, wxLayout_LeftToRight
, "Urdu (Pakistan)") 
4056    LNG(wxLANGUAGE_UZBEK
,                      "uz"   , LANG_UZBEK     
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Uzbek") 
4057    LNG(wxLANGUAGE_UZBEK_CYRILLIC
,             "uz"   , LANG_UZBEK     
, SUBLANG_UZBEK_CYRILLIC            
, wxLayout_LeftToRight
, "Uzbek (Cyrillic)") 
4058    LNG(wxLANGUAGE_UZBEK_LATIN
,                "uz"   , LANG_UZBEK     
, SUBLANG_UZBEK_LATIN               
, wxLayout_LeftToRight
, "Uzbek (Latin)") 
4059    LNG(wxLANGUAGE_VALENCIAN
,                  "ca_ES@valencia", 0              , 0                                 , wxLayout_LeftToRight
, "Valencian (Southern Catalan)") 
4060    LNG(wxLANGUAGE_VIETNAMESE
,                 "vi_VN", LANG_VIETNAMESE
, SUBLANG_DEFAULT                   
, wxLayout_LeftToRight
, "Vietnamese") 
4061    LNG(wxLANGUAGE_VOLAPUK
,                    "vo"   , 0              , 0                                 , wxLayout_LeftToRight
, "Volapuk") 
4062    LNG(wxLANGUAGE_WELSH
,                      "cy"   , 0              , 0                                 , wxLayout_LeftToRight
, "Welsh") 
4063    LNG(wxLANGUAGE_WOLOF
,                      "wo"   , 0              , 0                                 , wxLayout_LeftToRight
, "Wolof") 
4064    LNG(wxLANGUAGE_XHOSA
,                      "xh"   , 0              , 0                                 , wxLayout_LeftToRight
, "Xhosa") 
4065    LNG(wxLANGUAGE_YIDDISH
,                    "yi"   , 0              , 0                                 , wxLayout_LeftToRight
, "Yiddish") 
4066    LNG(wxLANGUAGE_YORUBA
,                     "yo"   , 0              , 0                                 , wxLayout_LeftToRight
, "Yoruba") 
4067    LNG(wxLANGUAGE_ZHUANG
,                     "za"   , 0              , 0                                 , wxLayout_LeftToRight
, "Zhuang") 
4068    LNG(wxLANGUAGE_ZULU
,                       "zu"   , 0              , 0                                 , wxLayout_LeftToRight
, "Zulu") 
4073 // --- --- --- generated code ends here --- --- --- 
4075 #endif // wxUSE_INTL