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) 7// Created: 29/01/98 8// RCS-ID: $Id: intl.cpp 61340 2009-07-06 21:19:58Z VZ $ 9// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 10// Licence: wxWindows licence 11///////////////////////////////////////////////////////////////////////////// 12 13// ============================================================================ 14// declaration 15// ============================================================================ 16 17// ---------------------------------------------------------------------------- 18// headers 19// ---------------------------------------------------------------------------- 20 21// For compilers that support precompilation, includes "wx.h". 22#include "wx/wxprec.h" 23 24#ifdef __BORLANDC__ 25 #pragma hdrstop 26#endif 27 28#ifdef __EMX__ 29// The following define is needed by Innotek's libc to 30// make the definition of struct localeconv available. 31#define __INTERNAL_DEFS 32#endif 33 34#if wxUSE_INTL 35 36#ifndef WX_PRECOMP 37 #include "wx/dynarray.h" 38 #include "wx/string.h" 39 #include "wx/intl.h" 40 #include "wx/log.h" 41 #include "wx/utils.h" 42 #include "wx/app.h" 43 #include "wx/hashmap.h" 44 #include "wx/module.h" 45#endif // WX_PRECOMP 46 47#ifndef __WXWINCE__ 48 #include <locale.h> 49#endif 50 51// standard headers 52#include <ctype.h> 53#include <stdlib.h> 54#ifdef HAVE_LANGINFO_H 55 #include <langinfo.h> 56#endif 57 58#ifdef __WIN32__ 59 #include "wx/msw/private.h" 60#elif defined(__UNIX_LIKE__) 61 #include "wx/fontmap.h" // for CharsetToEncoding() 62#endif 63 64#include "wx/file.h" 65#include "wx/filename.h" 66#include "wx/tokenzr.h" 67#include "wx/fontmap.h" 68#include "wx/encconv.h" 69#include "wx/ptr_scpd.h" 70#include "wx/apptrait.h" 71#include "wx/stdpaths.h" 72 73#if defined(__WXMAC__) 74 #include "wx/mac/private.h" // includes mac headers 75#endif 76 77#if defined(__DARWIN__) 78 #include "wx/mac/corefoundation/cfref.h" 79 #include <CoreFoundation/CFLocale.h> 80 #include "wx/mac/corefoundation/cfstring.h" 81#endif 82 83// ---------------------------------------------------------------------------- 84// simple types 85// ---------------------------------------------------------------------------- 86 87// this should *not* be wxChar, this type must have exactly 8 bits! 88typedef wxUint8 size_t8; 89typedef wxUint32 size_t32; 90 91// ---------------------------------------------------------------------------- 92// constants 93// ---------------------------------------------------------------------------- 94 95// magic number identifying the .mo format file 96const size_t32 MSGCATALOG_MAGIC = 0x950412de; 97const size_t32 MSGCATALOG_MAGIC_SW = 0xde120495; 98 99// the constants describing the format of lang_LANG locale string 100static const size_t LEN_LANG = 2; 101static const size_t LEN_SUBLANG = 2; 102static const size_t LEN_FULL = LEN_LANG + 1 + LEN_SUBLANG; // 1 for '_' 103 104#define TRACE_I18N _T("i18n") 105 106// ---------------------------------------------------------------------------- 107// global functions 108// ---------------------------------------------------------------------------- 109 110#ifdef __WXDEBUG__ 111 112// small class to suppress the translation erros until exit from current scope 113class NoTransErr 114{ 115public: 116 NoTransErr() { ms_suppressCount++; } 117 ~NoTransErr() { ms_suppressCount--; } 118 119 static bool Suppress() { return ms_suppressCount > 0; } 120 121private: 122 static size_t ms_suppressCount; 123}; 124 125size_t NoTransErr::ms_suppressCount = 0; 126 127#else // !Debug 128 129class NoTransErr 130{ 131public: 132 NoTransErr() { } 133 ~NoTransErr() { } 134}; 135 136#endif // Debug/!Debug 137 138static wxLocale *wxSetLocale(wxLocale *pLocale); 139 140// helper functions of GetSystemLanguage() 141#ifdef __UNIX__ 142 143// get just the language part 144static inline wxString ExtractLang(const wxString& langFull) 145{ 146 return langFull.Left(LEN_LANG); 147} 148 149// get everything else (including the leading '_') 150static inline wxString ExtractNotLang(const wxString& langFull) 151{ 152 return langFull.Mid(LEN_LANG); 153} 154 155#endif // __UNIX__ 156 157 158// ---------------------------------------------------------------------------- 159// Plural forms parser 160// ---------------------------------------------------------------------------- 161 162/* 163 Simplified Grammar 164 165Expression: 166 LogicalOrExpression '?' Expression ':' Expression 167 LogicalOrExpression 168 169LogicalOrExpression: 170 LogicalAndExpression "||" LogicalOrExpression // to (a || b) || c 171 LogicalAndExpression 172 173LogicalAndExpression: 174 EqualityExpression "&&" LogicalAndExpression // to (a && b) && c 175 EqualityExpression 176 177EqualityExpression: 178 RelationalExpression "==" RelationalExperession 179 RelationalExpression "!=" RelationalExperession 180 RelationalExpression 181 182RelationalExpression: 183 MultiplicativeExpression '>' MultiplicativeExpression 184 MultiplicativeExpression '<' MultiplicativeExpression 185 MultiplicativeExpression ">=" MultiplicativeExpression 186 MultiplicativeExpression "<=" MultiplicativeExpression 187 MultiplicativeExpression 188 189MultiplicativeExpression: 190 PmExpression '%' PmExpression 191 PmExpression 192 193PmExpression: 194 N 195 Number 196 '(' Expression ')' 197*/ 198 199class wxPluralFormsToken 200{ 201public: 202 enum Type 203 { 204 T_ERROR, T_EOF, T_NUMBER, T_N, T_PLURAL, T_NPLURALS, T_EQUAL, T_ASSIGN, 205 T_GREATER, T_GREATER_OR_EQUAL, T_LESS, T_LESS_OR_EQUAL, 206 T_REMINDER, T_NOT_EQUAL, 207 T_LOGICAL_AND, T_LOGICAL_OR, T_QUESTION, T_COLON, T_SEMICOLON, 208 T_LEFT_BRACKET, T_RIGHT_BRACKET 209 }; 210 Type type() const { return m_type; } 211 void setType(Type type) { m_type = type; } 212 // for T_NUMBER only 213 typedef int Number; 214 Number number() const { return m_number; } 215 void setNumber(Number num) { m_number = num; } 216private: 217 Type m_type; 218 Number m_number; 219}; 220 221 222class wxPluralFormsScanner 223{ 224public: 225 wxPluralFormsScanner(const char* s); 226 const wxPluralFormsToken& token() const { return m_token; } 227 bool nextToken(); // returns false if error 228private: 229 const char* m_s; 230 wxPluralFormsToken m_token; 231}; 232 233wxPluralFormsScanner::wxPluralFormsScanner(const char* s) : m_s(s) 234{ 235 nextToken(); 236} 237 238bool wxPluralFormsScanner::nextToken() 239{ 240 wxPluralFormsToken::Type type = wxPluralFormsToken::T_ERROR; 241 while (isspace((unsigned char) *m_s)) 242 { 243 ++m_s; 244 } 245 if (*m_s == 0) 246 { 247 type = wxPluralFormsToken::T_EOF; 248 } 249 else if (isdigit((unsigned char) *m_s)) 250 { 251 wxPluralFormsToken::Number number = *m_s++ - '0'; 252 while (isdigit((unsigned char) *m_s)) 253 { 254 number = number * 10 + (*m_s++ - '0'); 255 } 256 m_token.setNumber(number); 257 type = wxPluralFormsToken::T_NUMBER; 258 } 259 else if (isalpha((unsigned char) *m_s)) 260 { 261 const char* begin = m_s++; 262 while (isalnum((unsigned char) *m_s)) 263 { 264 ++m_s; 265 } 266 size_t size = m_s - begin; 267 if (size == 1 && memcmp(begin, "n", size) == 0) 268 { 269 type = wxPluralFormsToken::T_N; 270 } 271 else if (size == 6 && memcmp(begin, "plural", size) == 0) 272 { 273 type = wxPluralFormsToken::T_PLURAL; 274 } 275 else if (size == 8 && memcmp(begin, "nplurals", size) == 0) 276 { 277 type = wxPluralFormsToken::T_NPLURALS; 278 } 279 } 280 else if (*m_s == '=') 281 { 282 ++m_s; 283 if (*m_s == '=') 284 { 285 ++m_s; 286 type = wxPluralFormsToken::T_EQUAL; 287 } 288 else 289 { 290 type = wxPluralFormsToken::T_ASSIGN; 291 } 292 } 293 else if (*m_s == '>') 294 { 295 ++m_s; 296 if (*m_s == '=') 297 { 298 ++m_s; 299 type = wxPluralFormsToken::T_GREATER_OR_EQUAL; 300 } 301 else 302 { 303 type = wxPluralFormsToken::T_GREATER; 304 } 305 } 306 else if (*m_s == '<') 307 { 308 ++m_s; 309 if (*m_s == '=') 310 { 311 ++m_s; 312 type = wxPluralFormsToken::T_LESS_OR_EQUAL; 313 } 314 else 315 { 316 type = wxPluralFormsToken::T_LESS; 317 } 318 } 319 else if (*m_s == '%') 320 { 321 ++m_s; 322 type = wxPluralFormsToken::T_REMINDER; 323 } 324 else if (*m_s == '!' && m_s[1] == '=') 325 { 326 m_s += 2; 327 type = wxPluralFormsToken::T_NOT_EQUAL; 328 } 329 else if (*m_s == '&' && m_s[1] == '&') 330 { 331 m_s += 2; 332 type = wxPluralFormsToken::T_LOGICAL_AND; 333 } 334 else if (*m_s == '|' && m_s[1] == '|') 335 { 336 m_s += 2; 337 type = wxPluralFormsToken::T_LOGICAL_OR; 338 } 339 else if (*m_s == '?') 340 { 341 ++m_s; 342 type = wxPluralFormsToken::T_QUESTION; 343 } 344 else if (*m_s == ':') 345 { 346 ++m_s; 347 type = wxPluralFormsToken::T_COLON; 348 } else if (*m_s == ';') { 349 ++m_s; 350 type = wxPluralFormsToken::T_SEMICOLON; 351 } 352 else if (*m_s == '(') 353 { 354 ++m_s; 355 type = wxPluralFormsToken::T_LEFT_BRACKET; 356 } 357 else if (*m_s == ')') 358 { 359 ++m_s; 360 type = wxPluralFormsToken::T_RIGHT_BRACKET; 361 } 362 m_token.setType(type); 363 return type != wxPluralFormsToken::T_ERROR; 364} 365 366class wxPluralFormsNode; 367 368// NB: Can't use wxDEFINE_SCOPED_PTR_TYPE because wxPluralFormsNode is not 369// fully defined yet: 370class wxPluralFormsNodePtr 371{ 372public: 373 wxPluralFormsNodePtr(wxPluralFormsNode *p = NULL) : m_p(p) {} 374 ~wxPluralFormsNodePtr(); 375 wxPluralFormsNode& operator*() const { return *m_p; } 376 wxPluralFormsNode* operator->() const { return m_p; } 377 wxPluralFormsNode* get() const { return m_p; } 378 wxPluralFormsNode* release(); 379 void reset(wxPluralFormsNode *p); 380 381private: 382 wxPluralFormsNode *m_p; 383}; 384 385class wxPluralFormsNode 386{ 387public: 388 wxPluralFormsNode(const wxPluralFormsToken& token) : m_token(token) {} 389 const wxPluralFormsToken& token() const { return m_token; } 390 const wxPluralFormsNode* node(size_t i) const 391 { return m_nodes[i].get(); } 392 void setNode(size_t i, wxPluralFormsNode* n); 393 wxPluralFormsNode* releaseNode(size_t i); 394 wxPluralFormsToken::Number evaluate(wxPluralFormsToken::Number n) const; 395 396private: 397 wxPluralFormsToken m_token; 398 wxPluralFormsNodePtr m_nodes[3]; 399}; 400 401wxPluralFormsNodePtr::~wxPluralFormsNodePtr() 402{ 403 delete m_p; 404} 405wxPluralFormsNode* wxPluralFormsNodePtr::release() 406{ 407 wxPluralFormsNode *p = m_p; 408 m_p = NULL; 409 return p; 410} 411void wxPluralFormsNodePtr::reset(wxPluralFormsNode *p) 412{ 413 if (p != m_p) 414 { 415 delete m_p; 416 m_p = p; 417 } 418} 419 420 421void wxPluralFormsNode::setNode(size_t i, wxPluralFormsNode* n) 422{ 423 m_nodes[i].reset(n); 424} 425 426wxPluralFormsNode* wxPluralFormsNode::releaseNode(size_t i) 427{ 428 return m_nodes[i].release(); 429} 430 431wxPluralFormsToken::Number 432wxPluralFormsNode::evaluate(wxPluralFormsToken::Number n) const 433{ 434 switch (token().type()) 435 { 436 // leaf 437 case wxPluralFormsToken::T_NUMBER: 438 return token().number(); 439 case wxPluralFormsToken::T_N: 440 return n; 441 // 2 args 442 case wxPluralFormsToken::T_EQUAL: 443 return node(0)->evaluate(n) == node(1)->evaluate(n); 444 case wxPluralFormsToken::T_NOT_EQUAL: 445 return node(0)->evaluate(n) != node(1)->evaluate(n); 446 case wxPluralFormsToken::T_GREATER: 447 return node(0)->evaluate(n) > node(1)->evaluate(n); 448 case wxPluralFormsToken::T_GREATER_OR_EQUAL: 449 return node(0)->evaluate(n) >= node(1)->evaluate(n); 450 case wxPluralFormsToken::T_LESS: 451 return node(0)->evaluate(n) < node(1)->evaluate(n); 452 case wxPluralFormsToken::T_LESS_OR_EQUAL: 453 return node(0)->evaluate(n) <= node(1)->evaluate(n); 454 case wxPluralFormsToken::T_REMINDER: 455 { 456 wxPluralFormsToken::Number number = node(1)->evaluate(n); 457 if (number != 0) 458 { 459 return node(0)->evaluate(n) % number; 460 } 461 else 462 { 463 return 0; 464 } 465 } 466 case wxPluralFormsToken::T_LOGICAL_AND: 467 return node(0)->evaluate(n) && node(1)->evaluate(n); 468 case wxPluralFormsToken::T_LOGICAL_OR: 469 return node(0)->evaluate(n) || node(1)->evaluate(n); 470 // 3 args 471 case wxPluralFormsToken::T_QUESTION: 472 return node(0)->evaluate(n) 473 ? node(1)->evaluate(n) 474 : node(2)->evaluate(n); 475 default: 476 return 0; 477 } 478} 479 480 481class wxPluralFormsCalculator 482{ 483public: 484 wxPluralFormsCalculator() : m_nplurals(0), m_plural(0) {} 485 486 // input: number, returns msgstr index 487 int evaluate(int n) const; 488 489 // input: text after "Plural-Forms:" (e.g. "nplurals=2; plural=(n != 1);"), 490 // if s == 0, creates default handler 491 // returns 0 if error 492 static wxPluralFormsCalculator* make(const char* s = 0); 493 494 ~wxPluralFormsCalculator() {} 495 496 void init(wxPluralFormsToken::Number nplurals, wxPluralFormsNode* plural); 497 498private: 499 wxPluralFormsToken::Number m_nplurals; 500 wxPluralFormsNodePtr m_plural; 501}; 502 503wxDEFINE_SCOPED_PTR_TYPE(wxPluralFormsCalculator) 504 505void wxPluralFormsCalculator::init(wxPluralFormsToken::Number nplurals, 506 wxPluralFormsNode* plural) 507{ 508 m_nplurals = nplurals; 509 m_plural.reset(plural); 510} 511 512int wxPluralFormsCalculator::evaluate(int n) const 513{ 514 if (m_plural.get() == 0) 515 { 516 return 0; 517 } 518 wxPluralFormsToken::Number number = m_plural->evaluate(n); 519 if (number < 0 || number > m_nplurals) 520 { 521 return 0; 522 } 523 return number; 524} 525 526 527class wxPluralFormsParser 528{ 529public: 530 wxPluralFormsParser(wxPluralFormsScanner& scanner) : m_scanner(scanner) {} 531 bool parse(wxPluralFormsCalculator& rCalculator); 532 533private: 534 wxPluralFormsNode* parsePlural(); 535 // stops at T_SEMICOLON, returns 0 if error 536 wxPluralFormsScanner& m_scanner; 537 const wxPluralFormsToken& token() const; 538 bool nextToken(); 539 540 wxPluralFormsNode* expression(); 541 wxPluralFormsNode* logicalOrExpression(); 542 wxPluralFormsNode* logicalAndExpression(); 543 wxPluralFormsNode* equalityExpression(); 544 wxPluralFormsNode* multiplicativeExpression(); 545 wxPluralFormsNode* relationalExpression(); 546 wxPluralFormsNode* pmExpression(); 547}; 548 549bool wxPluralFormsParser::parse(wxPluralFormsCalculator& rCalculator) 550{ 551 if (token().type() != wxPluralFormsToken::T_NPLURALS) 552 return false; 553 if (!nextToken()) 554 return false; 555 if (token().type() != wxPluralFormsToken::T_ASSIGN) 556 return false; 557 if (!nextToken()) 558 return false; 559 if (token().type() != wxPluralFormsToken::T_NUMBER) 560 return false; 561 wxPluralFormsToken::Number nplurals = token().number(); 562 if (!nextToken()) 563 return false; 564 if (token().type() != wxPluralFormsToken::T_SEMICOLON) 565 return false; 566 if (!nextToken()) 567 return false; 568 if (token().type() != wxPluralFormsToken::T_PLURAL) 569 return false; 570 if (!nextToken()) 571 return false; 572 if (token().type() != wxPluralFormsToken::T_ASSIGN) 573 return false; 574 if (!nextToken()) 575 return false; 576 wxPluralFormsNode* plural = parsePlural(); 577 if (plural == 0) 578 return false; 579 if (token().type() != wxPluralFormsToken::T_SEMICOLON) 580 return false; 581 if (!nextToken()) 582 return false; 583 if (token().type() != wxPluralFormsToken::T_EOF) 584 return false; 585 rCalculator.init(nplurals, plural); 586 return true; 587} 588 589wxPluralFormsNode* wxPluralFormsParser::parsePlural() 590{ 591 wxPluralFormsNode* p = expression(); 592 if (p == NULL) 593 { 594 return NULL; 595 } 596 wxPluralFormsNodePtr n(p); 597 if (token().type() != wxPluralFormsToken::T_SEMICOLON) 598 { 599 return NULL; 600 } 601 return n.release(); 602} 603 604const wxPluralFormsToken& wxPluralFormsParser::token() const 605{ 606 return m_scanner.token(); 607} 608 609bool wxPluralFormsParser::nextToken() 610{ 611 if (!m_scanner.nextToken()) 612 return false; 613 return true; 614} 615 616wxPluralFormsNode* wxPluralFormsParser::expression() 617{ 618 wxPluralFormsNode* p = logicalOrExpression(); 619 if (p == NULL) 620 return NULL; 621 wxPluralFormsNodePtr n(p); 622 if (token().type() == wxPluralFormsToken::T_QUESTION) 623 { 624 wxPluralFormsNodePtr qn(new wxPluralFormsNode(token())); 625 if (!nextToken()) 626 { 627 return 0; 628 } 629 p = expression(); 630 if (p == 0) 631 { 632 return 0; 633 } 634 qn->setNode(1, p); 635 if (token().type() != wxPluralFormsToken::T_COLON) 636 { 637 return 0; 638 } 639 if (!nextToken()) 640 { 641 return 0; 642 } 643 p = expression(); 644 if (p == 0) 645 { 646 return 0; 647 } 648 qn->setNode(2, p); 649 qn->setNode(0, n.release()); 650 return qn.release(); 651 } 652 return n.release(); 653} 654 655wxPluralFormsNode*wxPluralFormsParser::logicalOrExpression() 656{ 657 wxPluralFormsNode* p = logicalAndExpression(); 658 if (p == NULL) 659 return NULL; 660 wxPluralFormsNodePtr ln(p); 661 if (token().type() == wxPluralFormsToken::T_LOGICAL_OR) 662 { 663 wxPluralFormsNodePtr un(new wxPluralFormsNode(token())); 664 if (!nextToken()) 665 { 666 return 0; 667 } 668 p = logicalOrExpression(); 669 if (p == 0) 670 { 671 return 0; 672 } 673 wxPluralFormsNodePtr rn(p); // right 674 if (rn->token().type() == wxPluralFormsToken::T_LOGICAL_OR) 675 { 676 // see logicalAndExpression comment 677 un->setNode(0, ln.release()); 678 un->setNode(1, rn->releaseNode(0)); 679 rn->setNode(0, un.release()); 680 return rn.release(); 681 } 682 683 684 un->setNode(0, ln.release()); 685 un->setNode(1, rn.release()); 686 return un.release(); 687 } 688 return ln.release(); 689} 690 691wxPluralFormsNode* wxPluralFormsParser::logicalAndExpression() 692{ 693 wxPluralFormsNode* p = equalityExpression(); 694 if (p == NULL) 695 return NULL; 696 wxPluralFormsNodePtr ln(p); // left 697 if (token().type() == wxPluralFormsToken::T_LOGICAL_AND) 698 { 699 wxPluralFormsNodePtr un(new wxPluralFormsNode(token())); // up 700 if (!nextToken()) 701 { 702 return NULL; 703 } 704 p = logicalAndExpression(); 705 if (p == 0) 706 { 707 return NULL; 708 } 709 wxPluralFormsNodePtr rn(p); // right 710 if (rn->token().type() == wxPluralFormsToken::T_LOGICAL_AND) 711 { 712// transform 1 && (2 && 3) -> (1 && 2) && 3 713// u r 714// l r -> u 3 715// 2 3 l 2 716 un->setNode(0, ln.release()); 717 un->setNode(1, rn->releaseNode(0)); 718 rn->setNode(0, un.release()); 719 return rn.release(); 720 } 721 722 un->setNode(0, ln.release()); 723 un->setNode(1, rn.release()); 724 return un.release(); 725 } 726 return ln.release(); 727} 728 729wxPluralFormsNode* wxPluralFormsParser::equalityExpression() 730{ 731 wxPluralFormsNode* p = relationalExpression(); 732 if (p == NULL) 733 return NULL; 734 wxPluralFormsNodePtr n(p); 735 if (token().type() == wxPluralFormsToken::T_EQUAL 736 || token().type() == wxPluralFormsToken::T_NOT_EQUAL) 737 { 738 wxPluralFormsNodePtr qn(new wxPluralFormsNode(token())); 739 if (!nextToken()) 740 { 741 return NULL; 742 } 743 p = relationalExpression(); 744 if (p == NULL) 745 { 746 return NULL; 747 } 748 qn->setNode(1, p); 749 qn->setNode(0, n.release()); 750 return qn.release(); 751 } 752 return n.release(); 753} 754 755wxPluralFormsNode* wxPluralFormsParser::relationalExpression() 756{ 757 wxPluralFormsNode* p = multiplicativeExpression(); 758 if (p == NULL) 759 return NULL; 760 wxPluralFormsNodePtr n(p); 761 if (token().type() == wxPluralFormsToken::T_GREATER 762 || token().type() == wxPluralFormsToken::T_LESS 763 || token().type() == wxPluralFormsToken::T_GREATER_OR_EQUAL 764 || token().type() == wxPluralFormsToken::T_LESS_OR_EQUAL) 765 { 766 wxPluralFormsNodePtr qn(new wxPluralFormsNode(token())); 767 if (!nextToken()) 768 { 769 return NULL; 770 } 771 p = multiplicativeExpression(); 772 if (p == NULL) 773 { 774 return NULL; 775 } 776 qn->setNode(1, p); 777 qn->setNode(0, n.release()); 778 return qn.release(); 779 } 780 return n.release(); 781} 782 783wxPluralFormsNode* wxPluralFormsParser::multiplicativeExpression() 784{ 785 wxPluralFormsNode* p = pmExpression(); 786 if (p == NULL) 787 return NULL; 788 wxPluralFormsNodePtr n(p); 789 if (token().type() == wxPluralFormsToken::T_REMINDER) 790 { 791 wxPluralFormsNodePtr qn(new wxPluralFormsNode(token())); 792 if (!nextToken()) 793 { 794 return NULL; 795 } 796 p = pmExpression(); 797 if (p == NULL) 798 { 799 return NULL; 800 } 801 qn->setNode(1, p); 802 qn->setNode(0, n.release()); 803 return qn.release(); 804 } 805 return n.release(); 806} 807 808wxPluralFormsNode* wxPluralFormsParser::pmExpression() 809{ 810 wxPluralFormsNodePtr n; 811 if (token().type() == wxPluralFormsToken::T_N 812 || token().type() == wxPluralFormsToken::T_NUMBER) 813 { 814 n.reset(new wxPluralFormsNode(token())); 815 if (!nextToken()) 816 { 817 return NULL; 818 } 819 } 820 else if (token().type() == wxPluralFormsToken::T_LEFT_BRACKET) { 821 if (!nextToken()) 822 { 823 return NULL; 824 } 825 wxPluralFormsNode* p = expression(); 826 if (p == NULL) 827 { 828 return NULL; 829 } 830 n.reset(p); 831 if (token().type() != wxPluralFormsToken::T_RIGHT_BRACKET) 832 { 833 return NULL; 834 } 835 if (!nextToken()) 836 { 837 return NULL; 838 } 839 } 840 else 841 { 842 return NULL; 843 } 844 return n.release(); 845} 846 847wxPluralFormsCalculator* wxPluralFormsCalculator::make(const char* s) 848{ 849 wxPluralFormsCalculatorPtr calculator(new wxPluralFormsCalculator); 850 if (s != NULL) 851 { 852 wxPluralFormsScanner scanner(s); 853 wxPluralFormsParser p(scanner); 854 if (!p.parse(*calculator)) 855 { 856 return NULL; 857 } 858 } 859 return calculator.release(); 860} 861 862 863 864 865// ---------------------------------------------------------------------------- 866// wxMsgCatalogFile corresponds to one disk-file message catalog. 867// 868// This is a "low-level" class and is used only by wxMsgCatalog 869// ---------------------------------------------------------------------------- 870 871WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxString, wxMessagesHash); 872 873class wxMsgCatalogFile 874{ 875public: 876 // ctor & dtor 877 wxMsgCatalogFile(); 878 ~wxMsgCatalogFile(); 879 880 // load the catalog from disk (szDirPrefix corresponds to language) 881 bool Load(const wxChar *szDirPrefix, const wxChar *szName, 882 wxPluralFormsCalculatorPtr& rPluralFormsCalculator); 883 884 // fills the hash with string-translation pairs 885 void FillHash(wxMessagesHash& hash, 886 const wxString& msgIdCharset, 887 bool convertEncoding) const; 888 889 // return the charset of the strings in this catalog or empty string if 890 // none/unknown 891 wxString GetCharset() const { return m_charset; } 892 893private: 894 // this implementation is binary compatible with GNU gettext() version 0.10 895 896 // an entry in the string table 897 struct wxMsgTableEntry 898 { 899 size_t32 nLen; // length of the string 900 size_t32 ofsString; // pointer to the string 901 }; 902 903 // header of a .mo file 904 struct wxMsgCatalogHeader 905 { 906 size_t32 magic, // offset +00: magic id 907 revision, // +04: revision 908 numStrings; // +08: number of strings in the file 909 size_t32 ofsOrigTable, // +0C: start of original string table 910 ofsTransTable; // +10: start of translated string table 911 size_t32 nHashSize, // +14: hash table size 912 ofsHashTable; // +18: offset of hash table start 913 }; 914 915 // all data is stored here, NULL if no data loaded 916 size_t8 *m_pData; 917 918 // amount of memory pointed to by m_pData. 919 size_t32 m_nSize; 920 921 // data description 922 size_t32 m_numStrings; // number of strings in this domain 923 wxMsgTableEntry *m_pOrigTable, // pointer to original strings 924 *m_pTransTable; // translated 925 926 wxString m_charset; // from the message catalog header 927 928 929 // swap the 2 halves of 32 bit integer if needed 930 size_t32 Swap(size_t32 ui) const 931 { 932 return m_bSwapped ? (ui << 24) | ((ui & 0xff00) << 8) | 933 ((ui >> 8) & 0xff00) | (ui >> 24) 934 : ui; 935 } 936 937 const char *StringAtOfs(wxMsgTableEntry *pTable, size_t32 n) const 938 { 939 const wxMsgTableEntry * const ent = pTable + n; 940 941 // this check could fail for a corrupt message catalog 942 size_t32 ofsString = Swap(ent->ofsString); 943 if ( ofsString + Swap(ent->nLen) > m_nSize) 944 { 945 return NULL; 946 } 947 948 return (const char *)(m_pData + ofsString); 949 } 950 951 bool m_bSwapped; // wrong endianness? 952 953 DECLARE_NO_COPY_CLASS(wxMsgCatalogFile) 954}; 955 956 957// ---------------------------------------------------------------------------- 958// wxMsgCatalog corresponds to one loaded message catalog. 959// 960// This is a "low-level" class and is used only by wxLocale (that's why 961// it's designed to be stored in a linked list) 962// ---------------------------------------------------------------------------- 963 964class wxMsgCatalog 965{ 966public: 967#if !wxUSE_UNICODE 968 wxMsgCatalog() { m_conv = NULL; } 969 ~wxMsgCatalog(); 970#endif 971 972 // load the catalog from disk (szDirPrefix corresponds to language) 973 bool Load(const wxChar *szDirPrefix, const wxChar *szName, 974 const wxChar *msgIdCharset = NULL, bool bConvertEncoding = false); 975 976 // get name of the catalog 977 wxString GetName() const { return m_name; } 978 979 // get the translated string: returns NULL if not found 980 const wxChar *GetString(const wxChar *sz, size_t n = size_t(-1)) const; 981 982 // public variable pointing to the next element in a linked list (or NULL) 983 wxMsgCatalog *m_pNext; 984 985private: 986 wxMessagesHash m_messages; // all messages in the catalog 987 wxString m_name; // name of the domain 988 989#if !wxUSE_UNICODE 990 // the conversion corresponding to this catalog charset if we installed it 991 // as the global one 992 wxCSConv *m_conv; 993#endif 994 995 wxPluralFormsCalculatorPtr m_pluralFormsCalculator; 996}; 997 998// ---------------------------------------------------------------------------- 999// global variables 1000// ---------------------------------------------------------------------------- 1001 1002// the list of the directories to search for message catalog files 1003static wxArrayString gs_searchPrefixes; 1004 1005// ============================================================================ 1006// implementation 1007// ============================================================================ 1008 1009// ---------------------------------------------------------------------------- 1010// wxMsgCatalogFile class 1011// ---------------------------------------------------------------------------- 1012 1013wxMsgCatalogFile::wxMsgCatalogFile() 1014{ 1015 m_pData = NULL; 1016 m_nSize = 0; 1017} 1018 1019wxMsgCatalogFile::~wxMsgCatalogFile() 1020{ 1021 delete [] m_pData; 1022} 1023 1024// return the directories to search for message catalogs under the given 1025// prefix, separated by wxPATH_SEP 1026static 1027wxString GetMsgCatalogSubdirs(const wxChar *prefix, const wxChar *lang) 1028{ 1029 // Search first in Unix-standard prefix/lang/LC_MESSAGES, then in 1030 // prefix/lang and finally in just prefix. 1031 // 1032 // Note that we use LC_MESSAGES on all platforms and not just Unix, because 1033 // it doesn't cost much to look into one more directory and doing it this 1034 // way has two important benefits: 1035 // a) we don't break compatibility with wx-2.6 and older by stopping to 1036 // look in a directory where the catalogs used to be and thus silently 1037 // breaking apps after they are recompiled against the latest wx 1038 // b) it makes it possible to package app's support files in the same 1039 // way on all target platforms 1040 wxString pathPrefix; 1041 pathPrefix << prefix << wxFILE_SEP_PATH << lang; 1042 1043 wxString searchPath; 1044 searchPath.reserve(4*pathPrefix.length()); 1045 searchPath << pathPrefix << wxFILE_SEP_PATH << wxT("LC_MESSAGES") << wxPATH_SEP 1046 << prefix << wxFILE_SEP_PATH << wxPATH_SEP 1047 << pathPrefix; 1048 1049 return searchPath; 1050} 1051 1052// construct the search path for the given language 1053static wxString GetFullSearchPath(const wxChar *lang) 1054{ 1055 // first take the entries explicitly added by the program 1056 wxArrayString paths; 1057 paths.reserve(gs_searchPrefixes.size() + 1); 1058 size_t n, 1059 count = gs_searchPrefixes.size(); 1060 for ( n = 0; n < count; n++ ) 1061 { 1062 paths.Add(GetMsgCatalogSubdirs(gs_searchPrefixes[n], lang)); 1063 } 1064 1065 1066#if wxUSE_STDPATHS 1067 // then look in the standard location 1068 const wxString stdp = wxStandardPaths::Get(). 1069 GetLocalizedResourcesDir(lang, wxStandardPaths::ResourceCat_Messages); 1070 1071 if ( paths.Index(stdp) == wxNOT_FOUND ) 1072 paths.Add(stdp); 1073#endif // wxUSE_STDPATHS 1074 1075 // last look in default locations 1076#ifdef __UNIX__ 1077 // LC_PATH is a standard env var containing the search path for the .mo 1078 // files 1079 const wxChar *pszLcPath = wxGetenv(wxT("LC_PATH")); 1080 if ( pszLcPath ) 1081 { 1082 const wxString lcp = GetMsgCatalogSubdirs(pszLcPath, lang); 1083 if ( paths.Index(lcp) == wxNOT_FOUND ) 1084 paths.Add(lcp); 1085 } 1086 1087 // also add the one from where wxWin was installed: 1088 wxString wxp = wxGetInstallPrefix(); 1089 if ( !wxp.empty() ) 1090 { 1091 wxp = GetMsgCatalogSubdirs(wxp + _T("/share/locale"), lang); 1092 if ( paths.Index(wxp) == wxNOT_FOUND ) 1093 paths.Add(wxp); 1094 } 1095#endif // __UNIX__ 1096 1097 1098 // finally construct the full search path 1099 wxString searchPath; 1100 searchPath.reserve(500); 1101 count = paths.size(); 1102 for ( n = 0; n < count; n++ ) 1103 { 1104 searchPath += paths[n]; 1105 if ( n != count - 1 ) 1106 searchPath += wxPATH_SEP; 1107 } 1108 1109 return searchPath; 1110} 1111 1112// open disk file and read in it's contents 1113bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName, 1114 wxPluralFormsCalculatorPtr& rPluralFormsCalculator) 1115{ 1116 wxString searchPath; 1117 1118#if wxUSE_FONTMAP 1119 // first look for the catalog for this language and the current locale: 1120 // notice that we don't use the system name for the locale as this would 1121 // force us to install catalogs in different locations depending on the 1122 // system but always use the canonical name 1123 wxFontEncoding encSys = wxLocale::GetSystemEncoding(); 1124 if ( encSys != wxFONTENCODING_SYSTEM ) 1125 { 1126 wxString fullname(szDirPrefix); 1127 fullname << _T('.') << wxFontMapperBase::GetEncodingName(encSys); 1128 searchPath << GetFullSearchPath(fullname) << wxPATH_SEP; 1129 } 1130#endif // wxUSE_FONTMAP 1131 1132 1133 searchPath += GetFullSearchPath(szDirPrefix); 1134 const wxChar *sublocale = wxStrchr(szDirPrefix, wxT('_')); 1135 if ( sublocale ) 1136 { 1137 // also add just base locale name: for things like "fr_BE" (belgium 1138 // french) we should use "fr" if no belgium specific message catalogs 1139 // exist 1140 searchPath << wxPATH_SEP 1141 << GetFullSearchPath(wxString(szDirPrefix). 1142 Left((size_t)(sublocale - szDirPrefix))); 1143 } 1144 1145 // don't give translation errors here because the wxstd catalog might 1146 // not yet be loaded (and it's normal) 1147 // 1148 // (we're using an object because we have several return paths) 1149 1150 NoTransErr noTransErr; 1151 wxLogVerbose(_("looking for catalog '%s' in path '%s'."), 1152 szName, searchPath.c_str()); 1153 wxLogTrace(TRACE_I18N, _T("Looking for \"%s.mo\" in \"%s\""), 1154 szName, searchPath.c_str()); 1155 1156 wxFileName fn(szName); 1157 fn.SetExt(_T("mo")); 1158 wxString strFullName; 1159 if ( !wxFindFileInPath(&strFullName, searchPath, fn.GetFullPath()) ) { 1160 wxLogVerbose(_("catalog file for domain '%s' not found."), szName); 1161 wxLogTrace(TRACE_I18N, _T("Catalog \"%s.mo\" not found"), szName); 1162 return false; 1163 } 1164 1165 // open file 1166 wxLogVerbose(_("using catalog '%s' from '%s'."), szName, strFullName.c_str()); 1167 wxLogTrace(TRACE_I18N, _T("Using catalog \"%s\"."), strFullName.c_str()); 1168 1169 wxFile fileMsg(strFullName); 1170 if ( !fileMsg.IsOpened() ) 1171 return false; 1172 1173 // get the file size (assume it is less than 4Gb...) 1174 wxFileOffset lenFile = fileMsg.Length(); 1175 if ( lenFile == wxInvalidOffset ) 1176 return false; 1177 1178 size_t nSize = wx_truncate_cast(size_t, lenFile); 1179 wxASSERT_MSG( nSize == lenFile + size_t(0), _T("message catalog bigger than 4GB?") ); 1180 1181 // read the whole file in memory 1182 m_pData = new size_t8[nSize]; 1183 if ( fileMsg.Read(m_pData, nSize) != lenFile ) { 1184 wxDELETEA(m_pData); 1185 return false; 1186 } 1187 1188 // examine header 1189 bool bValid = nSize + (size_t)0 > sizeof(wxMsgCatalogHeader); 1190 1191 wxMsgCatalogHeader *pHeader = (wxMsgCatalogHeader *)m_pData; 1192 if ( bValid ) { 1193 // we'll have to swap all the integers if it's true 1194 m_bSwapped = pHeader->magic == MSGCATALOG_MAGIC_SW; 1195 1196 // check the magic number 1197 bValid = m_bSwapped || pHeader->magic == MSGCATALOG_MAGIC; 1198 } 1199 1200 if ( !bValid ) { 1201 // it's either too short or has incorrect magic number 1202 wxLogWarning(_("'%s' is not a valid message catalog."), strFullName.c_str()); 1203 1204 wxDELETEA(m_pData); 1205 return false; 1206 } 1207 1208 // initialize 1209 m_numStrings = Swap(pHeader->numStrings); 1210 m_pOrigTable = (wxMsgTableEntry *)(m_pData + 1211 Swap(pHeader->ofsOrigTable)); 1212 m_pTransTable = (wxMsgTableEntry *)(m_pData + 1213 Swap(pHeader->ofsTransTable)); 1214 m_nSize = (size_t32)nSize; 1215 1216 // now parse catalog's header and try to extract catalog charset and 1217 // plural forms formula from it: 1218 1219 const char* headerData = StringAtOfs(m_pOrigTable, 0); 1220 if (headerData && headerData[0] == 0) 1221 { 1222 // Extract the charset: 1223 wxString header = wxString::FromAscii(StringAtOfs(m_pTransTable, 0)); 1224 int begin = header.Find(wxT("Content-Type: text/plain; charset=")); 1225 if (begin != wxNOT_FOUND) 1226 { 1227 begin += 34; //strlen("Content-Type: text/plain; charset=") 1228 size_t end = header.find('\n', begin); 1229 if (end != size_t(-1)) 1230 { 1231 m_charset.assign(header, begin, end - begin); 1232 if (m_charset == wxT("CHARSET")) 1233 { 1234 // "CHARSET" is not valid charset, but lazy translator 1235 m_charset.Clear(); 1236 } 1237 } 1238 } 1239 // else: incorrectly filled Content-Type header 1240 1241 // Extract plural forms: 1242 begin = header.Find(wxT("Plural-Forms:")); 1243 if (begin != wxNOT_FOUND) 1244 { 1245 begin += 13; 1246 size_t end = header.find('\n', begin); 1247 if (end != size_t(-1)) 1248 { 1249 wxString pfs(header, begin, end - begin); 1250 wxPluralFormsCalculator* pCalculator = wxPluralFormsCalculator 1251 ::make(pfs.ToAscii()); 1252 if (pCalculator != 0) 1253 { 1254 rPluralFormsCalculator.reset(pCalculator); 1255 } 1256 else 1257 { 1258 wxLogVerbose(_("Cannot parse Plural-Forms:'%s'"), pfs.c_str()); 1259 } 1260 } 1261 } 1262 if (rPluralFormsCalculator.get() == NULL) 1263 { 1264 rPluralFormsCalculator.reset(wxPluralFormsCalculator::make()); 1265 } 1266 } 1267 1268 // everything is fine 1269 return true; 1270} 1271 1272void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, 1273 const wxString& msgIdCharset, 1274 bool convertEncoding) const 1275{ 1276#if wxUSE_UNICODE 1277 // this parameter doesn't make sense, we always must convert encoding in 1278 // Unicode build 1279 convertEncoding = true; 1280#elif wxUSE_FONTMAP 1281 if ( convertEncoding ) 1282 { 1283 // determine if we need any conversion at all 1284 wxFontEncoding encCat = wxFontMapperBase::GetEncodingFromName(m_charset); 1285 if ( encCat == wxLocale::GetSystemEncoding() ) 1286 { 1287 // no need to convert 1288 convertEncoding = false; 1289 } 1290 } 1291#endif // wxUSE_UNICODE/wxUSE_FONTMAP 1292 1293#if wxUSE_WCHAR_T 1294 // conversion to use to convert catalog strings to the GUI encoding 1295 wxMBConv *inputConv, 1296 *inputConvPtr = NULL; // same as inputConv but safely deleteable 1297 if ( convertEncoding && !m_charset.empty() ) 1298 { 1299 inputConvPtr = 1300 inputConv = new wxCSConv(m_charset); 1301 } 1302 else // no need or not possible to convert the encoding 1303 { 1304#if wxUSE_UNICODE 1305 // we must somehow convert the narrow strings in the message catalog to 1306 // wide strings, so use the default conversion if we have no charset 1307 inputConv = wxConvCurrent; 1308#else // !wxUSE_UNICODE 1309 inputConv = NULL; 1310#endif // wxUSE_UNICODE/!wxUSE_UNICODE 1311 } 1312 1313 // conversion to apply to msgid strings before looking them up: we only 1314 // need it if the msgids are neither in 7 bit ASCII nor in the same 1315 // encoding as the catalog 1316 wxCSConv *sourceConv = msgIdCharset.empty() || (msgIdCharset == m_charset) 1317 ? NULL 1318 : new wxCSConv(msgIdCharset); 1319 1320#elif wxUSE_FONTMAP 1321 wxASSERT_MSG( msgIdCharset.empty(), 1322 _T("non-ASCII msgid languages only supported if wxUSE_WCHAR_T=1") ); 1323 1324 wxEncodingConverter converter; 1325 if ( convertEncoding ) 1326 { 1327 wxFontEncoding targetEnc = wxFONTENCODING_SYSTEM; 1328 wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(m_charset, false); 1329 if ( enc == wxFONTENCODING_SYSTEM ) 1330 { 1331 convertEncoding = false; // unknown encoding 1332 } 1333 else 1334 { 1335 targetEnc = wxLocale::GetSystemEncoding(); 1336 if (targetEnc == wxFONTENCODING_SYSTEM) 1337 { 1338 wxFontEncodingArray a = wxEncodingConverter::GetPlatformEquivalents(enc); 1339 if (a[0] == enc) 1340 // no conversion needed, locale uses native encoding 1341 convertEncoding = false; 1342 if (a.GetCount() == 0) 1343 // we don't know common equiv. under this platform 1344 convertEncoding = false; 1345 targetEnc = a[0]; 1346 } 1347 } 1348 1349 if ( convertEncoding ) 1350 { 1351 converter.Init(enc, targetEnc); 1352 } 1353 } 1354#endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T 1355 (void)convertEncoding; // get rid of warnings about unused parameter 1356 1357 for (size_t32 i = 0; i < m_numStrings; i++) 1358 { 1359 const char *data = StringAtOfs(m_pOrigTable, i); 1360 1361 wxString msgid; 1362#if wxUSE_UNICODE 1363 msgid = wxString(data, *inputConv); 1364#else // ASCII 1365 #if wxUSE_WCHAR_T 1366 if ( inputConv && sourceConv ) 1367 msgid = wxString(inputConv->cMB2WC(data), *sourceConv); 1368 else 1369 #endif 1370 msgid = data; 1371#endif // wxUSE_UNICODE 1372 1373 data = StringAtOfs(m_pTransTable, i); 1374 size_t length = Swap(m_pTransTable[i].nLen); 1375 size_t offset = 0; 1376 size_t index = 0; 1377 while (offset < length) 1378 { 1379 const char * const str = data + offset; 1380 1381 wxString msgstr; 1382#if wxUSE_UNICODE 1383 msgstr = wxString(str, *inputConv); 1384#elif wxUSE_WCHAR_T 1385 if ( inputConv ) 1386 msgstr = wxString(inputConv->cMB2WC(str), *wxConvUI); 1387 else 1388 msgstr = str; 1389#else // !wxUSE_WCHAR_T 1390 #if wxUSE_FONTMAP 1391 if ( convertEncoding ) 1392 msgstr = wxString(converter.Convert(str)); 1393 else 1394 #endif 1395 msgstr = str; 1396#endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T 1397 1398 if ( !msgstr.empty() ) 1399 { 1400 hash[index == 0 ? msgid : msgid + wxChar(index)] = msgstr; 1401 } 1402 1403 // skip this string 1404 offset += strlen(str) + 1; 1405 ++index; 1406 } 1407 } 1408 1409#if wxUSE_WCHAR_T 1410 delete sourceConv; 1411 delete inputConvPtr; 1412#endif // wxUSE_WCHAR_T 1413} 1414 1415 1416// ---------------------------------------------------------------------------- 1417// wxMsgCatalog class 1418// ---------------------------------------------------------------------------- 1419 1420#if !wxUSE_UNICODE 1421wxMsgCatalog::~wxMsgCatalog() 1422{ 1423 if ( m_conv ) 1424 { 1425 if ( wxConvUI == m_conv ) 1426 { 1427 // we only change wxConvUI if it points to wxConvLocal so we reset 1428 // it back to it too 1429 wxConvUI = &wxConvLocal; 1430 } 1431 1432 delete m_conv; 1433 } 1434} 1435#endif // !wxUSE_UNICODE 1436 1437bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName, 1438 const wxChar *msgIdCharset, bool bConvertEncoding) 1439{ 1440 wxMsgCatalogFile file; 1441 1442 m_name = szName; 1443 1444 if ( !file.Load(szDirPrefix, szName, m_pluralFormsCalculator) ) 1445 return false; 1446 1447 file.FillHash(m_messages, msgIdCharset, bConvertEncoding); 1448 1449#if !wxUSE_UNICODE && wxUSE_WCHAR_T 1450 // we should use a conversion compatible with the message catalog encoding 1451 // in the GUI if we don't convert the strings to the current conversion but 1452 // as the encoding is global, only change it once, otherwise we could get 1453 // into trouble if we use several message catalogs with different encodings 1454 // 1455 // this is, of course, a hack but it at least allows the program to use 1456 // message catalogs in any encodings without asking the user to change his 1457 // locale 1458 if ( !bConvertEncoding && 1459 !file.GetCharset().empty() && 1460 wxConvUI == &wxConvLocal ) 1461 { 1462 wxConvUI = 1463 m_conv = new wxCSConv(file.GetCharset()); 1464 } 1465#endif // !wxUSE_UNICODE && wxUSE_WCHAR_T 1466 1467 return true; 1468} 1469 1470const wxChar *wxMsgCatalog::GetString(const wxChar *sz, size_t n) const 1471{ 1472 int index = 0; 1473 if (n != size_t(-1)) 1474 { 1475 index = m_pluralFormsCalculator->evaluate(n); 1476 } 1477 wxMessagesHash::const_iterator i; 1478 if (index != 0) 1479 { 1480 i = m_messages.find(wxString(sz) + wxChar(index)); // plural 1481 } 1482 else 1483 { 1484 i = m_messages.find(sz); 1485 } 1486 1487 if ( i != m_messages.end() ) 1488 { 1489 return i->second.c_str(); 1490 } 1491 else 1492 return NULL; 1493} 1494 1495// ---------------------------------------------------------------------------- 1496// wxLocale 1497// ---------------------------------------------------------------------------- 1498 1499#include "wx/arrimpl.cpp" 1500WX_DECLARE_EXPORTED_OBJARRAY(wxLanguageInfo, wxLanguageInfoArray); 1501WX_DEFINE_OBJARRAY(wxLanguageInfoArray) 1502 1503wxLanguageInfoArray *wxLocale::ms_languagesDB = NULL; 1504 1505/*static*/ void wxLocale::CreateLanguagesDB() 1506{ 1507 if (ms_languagesDB == NULL) 1508 { 1509 ms_languagesDB = new wxLanguageInfoArray; 1510 InitLanguagesDB(); 1511 } 1512} 1513 1514/*static*/ void wxLocale::DestroyLanguagesDB() 1515{ 1516 delete ms_languagesDB; 1517 ms_languagesDB = NULL; 1518} 1519 1520 1521void wxLocale::DoCommonInit() 1522{ 1523 m_pszOldLocale = NULL; 1524 1525 m_pOldLocale = wxSetLocale(this); 1526 1527 m_pMsgCat = NULL; 1528 m_language = wxLANGUAGE_UNKNOWN; 1529 m_initialized = false; 1530} 1531 1532// NB: this function has (desired) side effect of changing current locale 1533bool wxLocale::Init(const wxChar *szName, 1534 const wxChar *szShort, 1535 const wxChar *szLocale, 1536 bool bLoadDefault, 1537 bool bConvertEncoding) 1538{ 1539 wxASSERT_MSG( !m_initialized, 1540 _T("you can't call wxLocale::Init more than once") ); 1541 1542 m_initialized = true; 1543 m_strLocale = szName; 1544 m_strShort = szShort; 1545 m_bConvertEncoding = bConvertEncoding; 1546 m_language = wxLANGUAGE_UNKNOWN; 1547 1548 // change current locale (default: same as long name) 1549 if ( szLocale == NULL ) 1550 { 1551 // the argument to setlocale() 1552 szLocale = szShort; 1553 1554 wxCHECK_MSG( szLocale, false, _T("no locale to set in wxLocale::Init()") ); 1555 } 1556 1557#ifdef __WXWINCE__ 1558 // FIXME: I'm guessing here 1559 wxChar localeName[256]; 1560 int ret = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLANGUAGE, localeName, 1561 256); 1562 if (ret != 0) 1563 { 1564 m_pszOldLocale = wxStrdup(localeName); 1565 } 1566 else 1567 m_pszOldLocale = NULL; 1568 1569 // TODO: how to find languageId 1570 // SetLocaleInfo(languageId, SORT_DEFAULT, localeName); 1571#else 1572 wxMB2WXbuf oldLocale = wxSetlocale(LC_ALL, szLocale); 1573 if ( oldLocale ) 1574 m_pszOldLocale = wxStrdup(oldLocale); 1575 else 1576 m_pszOldLocale = NULL; 1577#endif 1578 1579 if ( m_pszOldLocale == NULL ) 1580 wxLogError(_("locale '%s' can not be set."), szLocale); 1581 1582 // the short name will be used to look for catalog files as well, 1583 // so we need something here 1584 if ( m_strShort.empty() ) { 1585 // FIXME I don't know how these 2 letter abbreviations are formed, 1586 // this wild guess is surely wrong 1587 if ( szLocale && szLocale[0] ) 1588 { 1589 m_strShort += (wxChar)wxTolower(szLocale[0]); 1590 if ( szLocale[1] ) 1591 m_strShort += (wxChar)wxTolower(szLocale[1]); 1592 } 1593 } 1594 1595 // load the default catalog with wxWidgets standard messages 1596 m_pMsgCat = NULL; 1597 bool bOk = true; 1598 if ( bLoadDefault ) 1599 { 1600 bOk = AddCatalog(wxT("wxstd")); 1601 1602 // there may be a catalog with toolkit specific overrides, it is not 1603 // an error if this does not exist 1604 if ( bOk ) 1605 { 1606 wxString port(wxPlatformInfo::Get().GetPortIdName()); 1607 if ( !port.empty() ) 1608 { 1609 AddCatalog(port.BeforeFirst(wxT('/')).MakeLower()); 1610 } 1611 } 1612 } 1613 1614 return bOk; 1615} 1616 1617 1618#if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__) 1619static wxWCharBuffer wxSetlocaleTryUTF(int c, const wxChar *lc) 1620{ 1621 wxMB2WXbuf l = wxSetlocale(c, lc); 1622 if ( !l && lc && lc[0] != 0 ) 1623 { 1624 wxString buf(lc); 1625 wxString buf2; 1626 buf2 = buf + wxT(".UTF-8"); 1627 l = wxSetlocale(c, buf2.c_str()); 1628 if ( !l ) 1629 { 1630 buf2 = buf + wxT(".utf-8"); 1631 l = wxSetlocale(c, buf2.c_str()); 1632 } 1633 if ( !l ) 1634 { 1635 buf2 = buf + wxT(".UTF8"); 1636 l = wxSetlocale(c, buf2.c_str()); 1637 } 1638 if ( !l ) 1639 { 1640 buf2 = buf + wxT(".utf8"); 1641 l = wxSetlocale(c, buf2.c_str()); 1642 } 1643 } 1644 return l; 1645} 1646#else 1647#define wxSetlocaleTryUTF(c, lc) wxSetlocale(c, lc) 1648#endif 1649 1650bool wxLocale::Init(int language, int flags) 1651{ 1652 int lang = language; 1653 if (lang == wxLANGUAGE_DEFAULT) 1654 { 1655 // auto detect the language 1656 lang = GetSystemLanguage(); 1657 } 1658 1659 // We failed to detect system language, so we will use English: 1660 if (lang == wxLANGUAGE_UNKNOWN) 1661 { 1662 return false; 1663 } 1664 1665 const wxLanguageInfo *info = GetLanguageInfo(lang); 1666 1667 // Unknown language: 1668 if (info == NULL) 1669 { 1670 wxLogError(wxT("Unknown language %i."), lang); 1671 return false; 1672 } 1673 1674 wxString name = info->Description; 1675 wxString canonical = info->CanonicalName; 1676 wxString locale; 1677 1678 // Set the locale: 1679#if defined(__OS2__) 1680 wxMB2WXbuf retloc = wxSetlocale(LC_ALL , wxEmptyString); 1681#elif defined(__UNIX__) && !defined(__WXMAC__) 1682 if (language != wxLANGUAGE_DEFAULT) 1683 locale = info->CanonicalName; 1684 1685 wxMB2WXbuf retloc = wxSetlocaleTryUTF(LC_ALL, locale); 1686 1687 const wxString langOnly = locale.Left(2); 1688 if ( !retloc ) 1689 { 1690 // Some C libraries don't like xx_YY form and require xx only 1691 retloc = wxSetlocaleTryUTF(LC_ALL, langOnly); 1692 } 1693 1694#if wxUSE_FONTMAP 1695 // some systems (e.g. FreeBSD and HP-UX) don't have xx_YY aliases but 1696 // require the full xx_YY.encoding form, so try using UTF-8 because this is 1697 // the only thing we can do generically 1698 // 1699 // TODO: add encodings applicable to each language to the lang DB and try 1700 // them all in turn here 1701 if ( !retloc ) 1702 { 1703 const wxChar **names = 1704 wxFontMapperBase::GetAllEncodingNames(wxFONTENCODING_UTF8); 1705 while ( *names ) 1706 { 1707 retloc = wxSetlocale(LC_ALL, locale + _T('.') + *names++); 1708 if ( retloc ) 1709 break; 1710 } 1711 } 1712#endif // wxUSE_FONTMAP 1713 1714 if ( !retloc ) 1715 { 1716 // Some C libraries (namely glibc) still use old ISO 639, 1717 // so will translate the abbrev for them 1718 wxString localeAlt; 1719 if ( langOnly == wxT("he") ) 1720 localeAlt = wxT("iw") + locale.Mid(3); 1721 else if ( langOnly == wxT("id") ) 1722 localeAlt = wxT("in") + locale.Mid(3); 1723 else if ( langOnly == wxT("yi") ) 1724 localeAlt = wxT("ji") + locale.Mid(3); 1725 else if ( langOnly == wxT("nb") ) 1726 localeAlt = wxT("no_NO"); 1727 else if ( langOnly == wxT("nn") ) 1728 localeAlt = wxT("no_NY"); 1729 1730 if ( !localeAlt.empty() ) 1731 { 1732 retloc = wxSetlocaleTryUTF(LC_ALL, localeAlt); 1733 if ( !retloc ) 1734 retloc = wxSetlocaleTryUTF(LC_ALL, localeAlt.Left(2)); 1735 } 1736 } 1737 1738 if ( !retloc ) 1739 { 1740 wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str()); 1741 return false; 1742 } 1743 1744#ifdef __AIX__ 1745 // at least in AIX 5.2 libc is buggy and the string returned from setlocale(LC_ALL) 1746 // can't be passed back to it because it returns 6 strings (one for each locale 1747 // category), i.e. for C locale we get back "C C C C C C" 1748 // 1749 // this contradicts IBM own docs but this is not of much help, so just work around 1750 // it in the crudest possible manner 1751 wxChar *p = wxStrchr((wxChar *)retloc, _T(' ')); 1752 if ( p ) 1753 *p = _T('\0'); 1754#endif // __AIX__ 1755 1756#elif defined(__WIN32__) 1757 1758 #if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__)) 1759 // NB: setlocale() from msvcrt.dll (used by VC++ and Mingw) 1760 // can't set locale to language that can only be written using 1761 // Unicode. Therefore wxSetlocale call failed, but we don't want 1762 // to report it as an error -- so that at least message catalogs 1763 // can be used. Watch for code marked with 1764 // #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS bellow. 1765 #define SETLOCALE_FAILS_ON_UNICODE_LANGS 1766 #endif 1767 1768#if !wxUSE_UNICODE 1769 const 1770#endif 1771 wxMB2WXbuf retloc = wxT("C"); 1772 if (language != wxLANGUAGE_DEFAULT) 1773 { 1774 if (info->WinLang == 0) 1775 { 1776 wxLogWarning(wxT("Locale '%s' not supported by OS."), name.c_str()); 1777 // retloc already set to "C" 1778 } 1779 else 1780 { 1781 int codepage 1782 #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS 1783 = -1 1784 #endif 1785 ; 1786 wxUint32 lcid = MAKELCID(MAKELANGID(info->WinLang, info->WinSublang), 1787 SORT_DEFAULT); 1788 // FIXME 1789#ifndef __WXWINCE__ 1790 SetThreadLocale(lcid); 1791#endif 1792 // NB: we must translate LCID to CRT's setlocale string ourselves, 1793 // because SetThreadLocale does not modify change the 1794 // interpretation of setlocale(LC_ALL, "") call: 1795 wxChar buffer[256]; 1796 buffer[0] = wxT('\0'); 1797 GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, buffer, 256); 1798 locale << buffer; 1799 if (GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY, buffer, 256) > 0) 1800 locale << wxT("_") << buffer; 1801 if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buffer, 256) > 0) 1802 { 1803 codepage = wxAtoi(buffer); 1804 if (codepage != 0) 1805 locale << wxT(".") << buffer; 1806 } 1807 if (locale.empty()) 1808 { 1809 wxLogLastError(wxT("SetThreadLocale")); 1810 wxLogError(wxT("Cannot set locale to language %s."), name.c_str()); 1811 return false; 1812 } 1813 else 1814 { 1815 // FIXME 1816#ifndef __WXWINCE__ 1817 retloc = wxSetlocale(LC_ALL, locale); 1818#endif 1819#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS 1820 if (codepage == 0 && (const wxChar*)retloc == NULL) 1821 { 1822 retloc = wxT("C"); 1823 } 1824#endif 1825 } 1826 } 1827 } 1828 else 1829 { 1830 // FIXME 1831#ifndef __WXWINCE__ 1832 retloc = wxSetlocale(LC_ALL, wxEmptyString); 1833#else 1834 retloc = NULL; 1835#endif 1836#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS 1837 if ((const wxChar*)retloc == NULL) 1838 { 1839 wxChar buffer[16]; 1840 if (GetLocaleInfo(LOCALE_USER_DEFAULT, 1841 LOCALE_IDEFAULTANSICODEPAGE, buffer, 16) > 0 && 1842 wxStrcmp(buffer, wxT("0")) == 0) 1843 { 1844 retloc = wxT("C"); 1845 } 1846 } 1847#endif 1848 } 1849 1850 if ( !retloc ) 1851 { 1852 wxLogError(wxT("Cannot set locale to language %s."), name.c_str()); 1853 return false; 1854 } 1855#elif defined(__WXMAC__) 1856 if (lang == wxLANGUAGE_DEFAULT) 1857 locale = wxEmptyString; 1858 else 1859 locale = info->CanonicalName; 1860 1861 wxMB2WXbuf retloc = wxSetlocale(LC_ALL, locale); 1862 1863 if ( !retloc ) 1864 { 1865 // Some C libraries don't like xx_YY form and require xx only 1866 retloc = wxSetlocale(LC_ALL, locale.Mid(0,2)); 1867 } 1868 if ( !retloc ) 1869 { 1870 wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str()); 1871 return false; 1872 } 1873#else 1874 wxUnusedVar(flags); 1875 return false; 1876 #define WX_NO_LOCALE_SUPPORT 1877#endif 1878 1879#ifndef WX_NO_LOCALE_SUPPORT 1880 wxChar *szLocale = retloc ? wxStrdup(retloc) : NULL; 1881 bool ret = Init(name, canonical, szLocale, 1882 (flags & wxLOCALE_LOAD_DEFAULT) != 0, 1883 (flags & wxLOCALE_CONV_ENCODING) != 0); 1884 free(szLocale); 1885 1886 if (IsOk()) // setlocale() succeeded 1887 m_language = lang; 1888 1889 return ret; 1890#endif // !WX_NO_LOCALE_SUPPORT 1891} 1892 1893 1894 1895void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix) 1896{ 1897 if ( gs_searchPrefixes.Index(prefix) == wxNOT_FOUND ) 1898 { 1899 gs_searchPrefixes.Add(prefix); 1900 } 1901 //else: already have it 1902} 1903 1904/*static*/ int wxLocale::GetSystemLanguage() 1905{ 1906 CreateLanguagesDB(); 1907 1908 // init i to avoid compiler warning 1909 size_t i = 0, 1910 count = ms_languagesDB->GetCount(); 1911 1912#if defined(__UNIX__) && !defined(__WXMAC__) 1913 // first get the string identifying the language from the environment 1914 wxString langFull; 1915 if (!wxGetEnv(wxT("LC_ALL"), &langFull) && 1916 !wxGetEnv(wxT("LC_MESSAGES"), &langFull) && 1917 !wxGetEnv(wxT("LANG"), &langFull)) 1918 { 1919 // no language specified, treat it as English 1920 return wxLANGUAGE_ENGLISH_US; 1921 } 1922 1923 if ( langFull == _T("C") || langFull == _T("POSIX") ) 1924 { 1925 // default C locale is English too 1926 return wxLANGUAGE_ENGLISH_US; 1927 } 1928 1929 // the language string has the following form 1930 // 1931 // lang[_LANG][.encoding][@modifier] 1932 // 1933 // (see environ(5) in the Open Unix specification) 1934 // 1935 // where lang is the primary language, LANG is a sublang/territory, 1936 // encoding is the charset to use and modifier "allows the user to select 1937 // a specific instance of localization data within a single category" 1938 // 1939 // for example, the following strings are valid: 1940 // fr 1941 // fr_FR 1942 // de_DE.iso88591 1943 // de_DE@euro 1944 // de_DE.iso88591@euro 1945 1946 // for now we don't use the encoding, although we probably should (doing 1947 // translations of the msg catalogs on the fly as required) (TODO) 1948 // 1949 // we need the modified for languages like Valencian: ca_ES@valencia 1950 // though, remember it 1951 wxString modifier; 1952 size_t posModifier = langFull.find_first_of(_T("@")); 1953 if ( posModifier != wxString::npos ) 1954 modifier = langFull.Mid(posModifier); 1955 1956 size_t posEndLang = langFull.find_first_of(_T("@.")); 1957 if ( posEndLang != wxString::npos ) 1958 { 1959 langFull.Truncate(posEndLang); 1960 } 1961 1962 // in addition to the format above, we also can have full language names 1963 // in LANG env var - for example, SuSE is known to use LANG="german" - so 1964 // check for this 1965 1966 // do we have just the language (or sublang too)? 1967 bool justLang = langFull.length() == LEN_LANG; 1968 if ( justLang || 1969 (langFull.length() == LEN_FULL && langFull[LEN_LANG] == wxT('_')) ) 1970 { 1971 // 0. Make sure the lang is according to latest ISO 639 1972 // (this is necessary because glibc uses iw and in instead 1973 // of he and id respectively). 1974 1975 // the language itself (second part is the dialect/sublang) 1976 wxString langOrig = ExtractLang(langFull); 1977 1978 wxString lang; 1979 if ( langOrig == wxT("iw")) 1980 lang = _T("he"); 1981 else if (langOrig == wxT("in")) 1982 lang = wxT("id"); 1983 else if (langOrig == wxT("ji")) 1984 lang = wxT("yi"); 1985 else if (langOrig == wxT("no_NO")) 1986 lang = wxT("nb_NO"); 1987 else if (langOrig == wxT("no_NY")) 1988 lang = wxT("nn_NO"); 1989 else if (langOrig == wxT("no")) 1990 lang = wxT("nb_NO"); 1991 else 1992 lang = langOrig; 1993 1994 // did we change it? 1995 if ( lang != langOrig ) 1996 { 1997 langFull = lang + ExtractNotLang(langFull); 1998 } 1999 2000 // 1. Try to find the language either as is: 2001 // a) With modifier if set 2002 if ( !modifier.empty() ) 2003 { 2004 wxString langFullWithModifier = langFull + modifier; 2005 for ( i = 0; i < count; i++ ) 2006 { 2007 if ( ms_languagesDB->Item(i).CanonicalName == langFullWithModifier ) 2008 break; 2009 } 2010 } 2011 2012 // b) Without modifier 2013 if ( modifier.empty() || i == count ) 2014 { 2015 for ( i = 0; i < count; i++ ) 2016 { 2017 if ( ms_languagesDB->Item(i).CanonicalName == langFull ) 2018 break; 2019 } 2020 } 2021 2022 // 2. If langFull is of the form xx_YY, try to find xx: 2023 if ( i == count && !justLang ) 2024 { 2025 for ( i = 0; i < count; i++ ) 2026 { 2027 if ( ms_languagesDB->Item(i).CanonicalName == lang ) 2028 { 2029 break; 2030 } 2031 } 2032 } 2033 2034 // 3. If langFull is of the form xx, try to find any xx_YY record: 2035 if ( i == count && justLang ) 2036 { 2037 for ( i = 0; i < count; i++ ) 2038 { 2039 if ( ExtractLang(ms_languagesDB->Item(i).CanonicalName) 2040 == langFull ) 2041 { 2042 break; 2043 } 2044 } 2045 } 2046 } 2047 else // not standard format 2048 { 2049 // try to find the name in verbose description 2050 for ( i = 0; i < count; i++ ) 2051 { 2052 if (ms_languagesDB->Item(i).Description.CmpNoCase(langFull) == 0) 2053 { 2054 break; 2055 } 2056 } 2057 } 2058#elif defined(__WXMAC__) 2059 const wxChar * lc = NULL ; 2060 long lang = GetScriptVariable( smSystemScript, smScriptLang) ; 2061 switch( GetScriptManagerVariable( smRegionCode ) ) { 2062 case verUS : 2063 lc = wxT("en_US") ; 2064 break ; 2065 case verFrance : 2066 lc = wxT("fr_FR") ; 2067 break ; 2068 case verBritain : 2069 lc = wxT("en_GB") ; 2070 break ; 2071 case verGermany : 2072 lc = wxT("de_DE") ; 2073 break ; 2074 case verItaly : 2075 lc = wxT("it_IT") ; 2076 break ; 2077 case verNetherlands : 2078 lc = wxT("nl_NL") ; 2079 break ; 2080 case verFlemish : 2081 lc = wxT("nl_BE") ; 2082 break ; 2083 case verSweden : 2084 lc = wxT("sv_SE" ); 2085 break ; 2086 case verSpain : 2087 lc = wxT("es_ES" ); 2088 break ; 2089 case verDenmark : 2090 lc = wxT("da_DK") ; 2091 break ; 2092 case verPortugal : 2093 lc = wxT("pt_PT") ; 2094 break ; 2095 case verFrCanada: 2096 lc = wxT("fr_CA") ; 2097 break ; 2098 case verNorway: 2099 lc = wxT("nb_NO") ; 2100 break ; 2101 case verIsrael: 2102 lc = wxT("iw_IL") ; 2103 break ; 2104 case verJapan: 2105 lc = wxT("ja_JP") ; 2106 break ; 2107 case verAustralia: 2108 lc = wxT("en_AU") ; 2109 break ; 2110 case verArabic: 2111 lc = wxT("ar") ; 2112 break ; 2113 case verFinland: 2114 lc = wxT("fi_FI") ; 2115 break ; 2116 case verFrSwiss: 2117 lc = wxT("fr_CH") ; 2118 break ; 2119 case verGrSwiss: 2120 lc = wxT("de_CH") ; 2121 break ; 2122 case verGreece: 2123 lc = wxT("el_GR") ; 2124 break ; 2125 case verIceland: 2126 lc = wxT("is_IS") ; 2127 break ; 2128 case verMalta: 2129 lc = wxT("mt_MT") ; 2130 break ; 2131 case verCyprus: 2132 // _CY is not part of wx, so we have to translate according to the system language 2133 if ( lang == langGreek ) { 2134 lc = wxT("el_GR") ; 2135 } 2136 else if ( lang == langTurkish ) { 2137 lc = wxT("tr_TR") ; 2138 } 2139 break ; 2140 case verTurkey: 2141 lc = wxT("tr_TR") ; 2142 break ; 2143 case verYugoCroatian: 2144 lc = wxT("hr_HR") ; 2145 break ; 2146 case verIndiaHindi: 2147 lc = wxT("hi_IN") ; 2148 break ; 2149 case verPakistanUrdu: 2150 lc = wxT("ur_PK") ; 2151 break ; 2152 case verTurkishModified: 2153 lc = wxT("tr_TR") ; 2154 break ; 2155 case verItalianSwiss: 2156 lc = wxT("it_CH") ; 2157 break ; 2158 case verInternational: 2159 lc = wxT("en") ; 2160 break ; 2161 case verRomania: 2162 lc = wxT("ro_RO") ; 2163 break ; 2164 case verGreecePoly: 2165 lc = wxT("el_GR") ; 2166 break ; 2167 case verLithuania: 2168 lc = wxT("lt_LT") ; 2169 break ; 2170 case verPoland: 2171 lc = wxT("pl_PL") ; 2172 break ; 2173 case verMagyar : 2174 case verHungary: 2175 lc = wxT("hu_HU") ; 2176 break ; 2177 case verEstonia: 2178 lc = wxT("et_EE") ; 2179 break ; 2180 case verLatvia: 2181 lc = wxT("lv_LV") ; 2182 break ; 2183 case verSami: 2184 lc = wxT("se_NO") ; 2185 break ; 2186 case verFaroeIsl: 2187 lc = wxT("fo_FO") ; 2188 break ; 2189 case verIran: 2190 lc = wxT("fa_IR") ; 2191 break ; 2192 case verRussia: 2193 lc = wxT("ru_RU") ; 2194 break ; 2195 case verIreland: 2196 lc = wxT("ga_IE") ; 2197 break ; 2198 case verKorea: 2199 lc = wxT("ko_KR") ; 2200 break ; 2201 case verChina: 2202 lc = wxT("zh_CN") ; 2203 break ; 2204 case verTaiwan: 2205 lc = wxT("zh_TW") ; 2206 break ; 2207 case verThailand: 2208 lc = wxT("th_TH") ; 2209 break ; 2210 case verCzech: 2211 lc = wxT("cs_CZ") ; 2212 break ; 2213 case verSlovak: 2214 lc = wxT("sk_SK") ; 2215 break ; 2216 case verBengali: 2217 lc = wxT("bn") ; 2218 break ; 2219 case verByeloRussian: 2220 lc = wxT("be_BY") ; 2221 break ; 2222 case verUkraine: 2223 lc = wxT("uk_UA") ; 2224 break ; 2225 case verGreeceAlt: 2226 lc = wxT("el_GR") ; 2227 break ; 2228 case verSerbian: 2229 lc = wxT("sr_YU") ; 2230 break ; 2231 case verSlovenian: 2232 lc = wxT("sl_SI") ; 2233 break ; 2234 case verMacedonian: 2235 lc = wxT("mk_MK") ; 2236 break ; 2237 case verCroatia: 2238 lc = wxT("hr_HR") ; 2239 break ; 2240 case verBrazil: 2241 lc = wxT("pt_BR ") ; 2242 break ; 2243 case verBulgaria: 2244 lc = wxT("bg_BG") ; 2245 break ; 2246 case verCatalonia: 2247 lc = wxT("ca_ES") ; 2248 break ; 2249 case verScottishGaelic: 2250 lc = wxT("gd") ; 2251 break ; 2252 case verManxGaelic: 2253 lc = wxT("gv") ; 2254 break ; 2255 case verBreton: 2256 lc = wxT("br") ; 2257 break ; 2258 case verNunavut: 2259 lc = wxT("iu_CA") ; 2260 break ; 2261 case verWelsh: 2262 lc = wxT("cy") ; 2263 break ; 2264 case verIrishGaelicScript: 2265 lc = wxT("ga_IE") ; 2266 break ; 2267 case verEngCanada: 2268 lc = wxT("en_CA") ; 2269 break ; 2270 case verBhutan: 2271 lc = wxT("dz_BT") ; 2272 break ; 2273 case verArmenian: 2274 lc = wxT("hy_AM") ; 2275 break ; 2276 case verGeorgian: 2277 lc = wxT("ka_GE") ; 2278 break ; 2279 case verSpLatinAmerica: 2280 lc = wxT("es_AR") ; 2281 break ; 2282 case verTonga: 2283 lc = wxT("to_TO" ); 2284 break ; 2285 case verFrenchUniversal: 2286 lc = wxT("fr_FR") ; 2287 break ; 2288 case verAustria: 2289 lc = wxT("de_AT") ; 2290 break ; 2291 case verGujarati: 2292 lc = wxT("gu_IN") ; 2293 break ; 2294 case verPunjabi: 2295 lc = wxT("pa") ; 2296 break ; 2297 case verIndiaUrdu: 2298 lc = wxT("ur_IN") ; 2299 break ; 2300 case verVietnam: 2301 lc = wxT("vi_VN") ; 2302 break ; 2303 case verFrBelgium: 2304 lc = wxT("fr_BE") ; 2305 break ; 2306 case verUzbek: 2307 lc = wxT("uz_UZ") ; 2308 break ; 2309 case verSingapore: 2310 lc = wxT("zh_SG") ; 2311 break ; 2312 case verNynorsk: 2313 lc = wxT("nn_NO") ; 2314 break ; 2315 case verAfrikaans: 2316 lc = wxT("af_ZA") ; 2317 break ; 2318 case verEsperanto: 2319 lc = wxT("eo") ; 2320 break ; 2321 case verMarathi: 2322 lc = wxT("mr_IN") ; 2323 break ; 2324 case verTibetan: 2325 lc = wxT("bo") ; 2326 break ; 2327 case verNepal: 2328 lc = wxT("ne_NP") ; 2329 break ; 2330 case verGreenland: 2331 lc = wxT("kl_GL") ; 2332 break ; 2333 default : 2334 break ; 2335 } 2336 if ( !lc ) 2337 return wxLANGUAGE_UNKNOWN; 2338 for ( i = 0; i < count; i++ ) 2339 { 2340 if ( ms_languagesDB->Item(i).CanonicalName == lc ) 2341 { 2342 break; 2343 } 2344 } 2345 2346#elif defined(__WIN32__) 2347 LCID lcid = GetUserDefaultLCID(); 2348 if ( lcid != 0 ) 2349 { 2350 wxUint32 lang = PRIMARYLANGID(LANGIDFROMLCID(lcid)); 2351 wxUint32 sublang = SUBLANGID(LANGIDFROMLCID(lcid)); 2352 2353 for ( i = 0; i < count; i++ ) 2354 { 2355 if (ms_languagesDB->Item(i).WinLang == lang && 2356 ms_languagesDB->Item(i).WinSublang == sublang) 2357 { 2358 break; 2359 } 2360 } 2361 } 2362 //else: leave wxlang == wxLANGUAGE_UNKNOWN 2363#endif // Unix/Win32 2364 2365 if ( i < count ) 2366 { 2367 // we did find a matching entry, use it 2368 return ms_languagesDB->Item(i).Language; 2369 } 2370 2371 // no info about this language in the database 2372 return wxLANGUAGE_UNKNOWN; 2373} 2374 2375// ---------------------------------------------------------------------------- 2376// encoding stuff 2377// ---------------------------------------------------------------------------- 2378 2379// this is a bit strange as under Windows we get the encoding name using its 2380// numeric value and under Unix we do it the other way round, but this just 2381// reflects the way different systems provide the encoding info 2382 2383/* static */ 2384wxString wxLocale::GetSystemEncodingName() 2385{ 2386 wxString encname; 2387 2388#if defined(__WIN32__) && !defined(__WXMICROWIN__) 2389 // FIXME: what is the error return value for GetACP()? 2390 UINT codepage = ::GetACP(); 2391 encname.Printf(_T("windows-%u"), codepage); 2392#elif defined(__WXMAC__) 2393 // default is just empty string, this resolves to the default system 2394 // encoding later 2395#elif defined(__UNIX_LIKE__) 2396 2397#if defined(HAVE_LANGINFO_H) && defined(CODESET) 2398 // GNU libc provides current character set this way (this conforms 2399 // to Unix98) 2400 char *oldLocale = strdup(setlocale(LC_CTYPE, NULL)); 2401 setlocale(LC_CTYPE, ""); 2402 const char *alang = nl_langinfo(CODESET); 2403 setlocale(LC_CTYPE, oldLocale); 2404 free(oldLocale); 2405 2406 if ( alang ) 2407 { 2408 encname = wxString::FromAscii( alang ); 2409 } 2410 else // nl_langinfo() failed 2411#endif // HAVE_LANGINFO_H 2412 { 2413 // if we can't get at the character set directly, try to see if it's in 2414 // the environment variables (in most cases this won't work, but I was 2415 // out of ideas) 2416 char *lang = getenv( "LC_ALL"); 2417 char *dot = lang ? strchr(lang, '.') : (char *)NULL; 2418 if (!dot) 2419 { 2420 lang = getenv( "LC_CTYPE" ); 2421 if ( lang ) 2422 dot = strchr(lang, '.' ); 2423 } 2424 if (!dot) 2425 { 2426 lang = getenv( "LANG"); 2427 if ( lang ) 2428 dot = strchr(lang, '.'); 2429 } 2430 2431 if ( dot ) 2432 { 2433 encname = wxString::FromAscii( dot+1 ); 2434 } 2435 } 2436#endif // Win32/Unix 2437 2438 return encname; 2439} 2440 2441/* static */ 2442wxFontEncoding wxLocale::GetSystemEncoding() 2443{ 2444#if defined(__WIN32__) && !defined(__WXMICROWIN__) 2445 UINT codepage = ::GetACP(); 2446 2447 // wxWidgets only knows about CP1250-1257, 874, 932, 936, 949, 950 2448 if ( codepage >= 1250 && codepage <= 1257 ) 2449 { 2450 return (wxFontEncoding)(wxFONTENCODING_CP1250 + codepage - 1250); 2451 } 2452 2453 if ( codepage == 874 ) 2454 { 2455 return wxFONTENCODING_CP874; 2456 } 2457 2458 if ( codepage == 932 ) 2459 { 2460 return wxFONTENCODING_CP932; 2461 } 2462 2463 if ( codepage == 936 ) 2464 { 2465 return wxFONTENCODING_CP936; 2466 } 2467 2468 if ( codepage == 949 ) 2469 { 2470 return wxFONTENCODING_CP949; 2471 } 2472 2473 if ( codepage == 950 ) 2474 { 2475 return wxFONTENCODING_CP950; 2476 } 2477#elif defined(__WXMAC__) 2478 TextEncoding encoding = 0 ; 2479#if TARGET_CARBON 2480 encoding = CFStringGetSystemEncoding() ; 2481#else 2482 UpgradeScriptInfoToTextEncoding ( smSystemScript , kTextLanguageDontCare , kTextRegionDontCare , NULL , &encoding ) ; 2483#endif 2484 return wxMacGetFontEncFromSystemEnc( encoding ) ; 2485#elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP 2486 const wxString encname = GetSystemEncodingName(); 2487 if ( !encname.empty() ) 2488 { 2489 wxFontEncoding enc = wxFontMapperBase::GetEncodingFromName(encname); 2490 2491 // on some modern Linux systems (RedHat 8) the default system locale 2492 // is UTF8 -- but it isn't supported by wxGTK1 in ANSI build at all so 2493 // don't even try to use it in this case 2494#if !wxUSE_UNICODE && \ 2495 ((defined(__WXGTK__) && !defined(__WXGTK20__)) || defined(__WXMOTIF__)) 2496 if ( enc == wxFONTENCODING_UTF8 ) 2497 { 2498 // the most similar supported encoding... 2499 enc = wxFONTENCODING_ISO8859_1; 2500 } 2501#endif // !wxUSE_UNICODE 2502 2503 // GetEncodingFromName() returns wxFONTENCODING_DEFAULT for C locale 2504 // (a.k.a. US-ASCII) which is arguably a bug but keep it like this for 2505 // backwards compatibility and just take care to not return 2506 // wxFONTENCODING_DEFAULT from here as this surely doesn't make sense 2507 if ( enc == wxFONTENCODING_DEFAULT ) 2508 { 2509 // we don't have wxFONTENCODING_ASCII, so use the closest one 2510 return wxFONTENCODING_ISO8859_1; 2511 } 2512 2513 if ( enc != wxFONTENCODING_MAX ) 2514 { 2515 return enc; 2516 } 2517 //else: return wxFONTENCODING_SYSTEM below 2518 } 2519#endif // Win32/Unix 2520 2521 return wxFONTENCODING_SYSTEM; 2522} 2523 2524/* static */ 2525void wxLocale::AddLanguage(const wxLanguageInfo& info) 2526{ 2527 CreateLanguagesDB(); 2528 ms_languagesDB->Add(info); 2529} 2530 2531/* static */ 2532const wxLanguageInfo *wxLocale::GetLanguageInfo(int lang) 2533{ 2534 CreateLanguagesDB(); 2535 2536 // calling GetLanguageInfo(wxLANGUAGE_DEFAULT) is a natural thing to do, so 2537 // make it work 2538 if ( lang == wxLANGUAGE_DEFAULT ) 2539 lang = GetSystemLanguage(); 2540 2541 const size_t count = ms_languagesDB->GetCount(); 2542 for ( size_t i = 0; i < count; i++ ) 2543 { 2544 if ( ms_languagesDB->Item(i).Language == lang ) 2545 { 2546 // We need to create a temporary here in order to make this work with BCC in final build mode 2547 wxLanguageInfo *ptr = &ms_languagesDB->Item(i); 2548 return ptr; 2549 } 2550 } 2551 2552 return NULL; 2553} 2554 2555/* static */ 2556wxString wxLocale::GetLanguageName(int lang) 2557{ 2558 const wxLanguageInfo *info = GetLanguageInfo(lang); 2559 if ( !info ) 2560 return wxEmptyString; 2561 else 2562 return info->Description; 2563} 2564 2565/* static */ 2566const wxLanguageInfo *wxLocale::FindLanguageInfo(const wxString& locale) 2567{ 2568 CreateLanguagesDB(); 2569 2570 const wxLanguageInfo *infoRet = NULL; 2571 2572 const size_t count = ms_languagesDB->GetCount(); 2573 for ( size_t i = 0; i < count; i++ ) 2574 { 2575 const wxLanguageInfo *info = &ms_languagesDB->Item(i); 2576 2577 if ( wxStricmp(locale, info->CanonicalName) == 0 || 2578 wxStricmp(locale, info->Description) == 0 ) 2579 { 2580 // exact match, stop searching 2581 infoRet = info; 2582 break; 2583 } 2584 2585 if ( wxStricmp(locale, info->CanonicalName.BeforeFirst(_T('_'))) == 0 ) 2586 { 2587 // a match -- but maybe we'll find an exact one later, so continue 2588 // looking 2589 // 2590 // OTOH, maybe we had already found a language match and in this 2591 // case don't overwrite it becauce the entry for the default 2592 // country always appears first in ms_languagesDB 2593 if ( !infoRet ) 2594 infoRet = info; 2595 } 2596 } 2597 2598 return infoRet; 2599} 2600 2601wxString wxLocale::GetSysName() const 2602{ 2603 // FIXME 2604#ifndef __WXWINCE__ 2605 return wxSetlocale(LC_ALL, NULL); 2606#else 2607 return wxEmptyString; 2608#endif 2609} 2610 2611// clean up 2612wxLocale::~wxLocale() 2613{ 2614 // free memory 2615 wxMsgCatalog *pTmpCat; 2616 while ( m_pMsgCat != NULL ) { 2617 pTmpCat = m_pMsgCat; 2618 m_pMsgCat = m_pMsgCat->m_pNext; 2619 delete pTmpCat; 2620 } 2621 2622 // restore old locale pointer 2623 wxSetLocale(m_pOldLocale); 2624 2625 // FIXME 2626#ifndef __WXWINCE__ 2627 wxSetlocale(LC_ALL, m_pszOldLocale); 2628#endif 2629 free((wxChar *)m_pszOldLocale); // const_cast 2630} 2631 2632// get the translation of given string in current locale 2633const wxChar *wxLocale::GetString(const wxChar *szOrigString, 2634 const wxChar *szDomain) const 2635{ 2636 return GetString(szOrigString, szOrigString, size_t(-1), szDomain); 2637} 2638 2639const wxChar *wxLocale::GetString(const wxChar *szOrigString, 2640 const wxChar *szOrigString2, 2641 size_t n, 2642 const wxChar *szDomain) const 2643{ 2644 if ( wxIsEmpty(szOrigString) ) 2645 return wxEmptyString; 2646 2647 const wxChar *pszTrans = NULL; 2648 wxMsgCatalog *pMsgCat; 2649 2650 if ( szDomain != NULL && szDomain[0] ) 2651 { 2652 pMsgCat = FindCatalog(szDomain); 2653 2654 // does the catalog exist? 2655 if ( pMsgCat != NULL ) 2656 pszTrans = pMsgCat->GetString(szOrigString, n); 2657 } 2658 else 2659 { 2660 // search in all domains 2661 for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext ) 2662 { 2663 pszTrans = pMsgCat->GetString(szOrigString, n); 2664 if ( pszTrans != NULL ) // take the first found 2665 break; 2666 } 2667 } 2668 2669 if ( pszTrans == NULL ) 2670 { 2671#ifdef __WXDEBUG__ 2672 if ( !NoTransErr::Suppress() ) 2673 { 2674 NoTransErr noTransErr; 2675 2676 wxLogTrace(TRACE_I18N, 2677 _T("string \"%s\"[%ld] not found in %slocale '%s'."), 2678 szOrigString, (long)n, 2679 szDomain ? wxString::Format(_T("domain '%s' "), szDomain).c_str() 2680 : _T(""), 2681 m_strLocale.c_str()); 2682 } 2683#endif // __WXDEBUG__ 2684 2685 if (n == size_t(-1)) 2686 return szOrigString; 2687 else 2688 return n == 1 ? szOrigString : szOrigString2; 2689 } 2690 2691 return pszTrans; 2692} 2693 2694wxString wxLocale::GetHeaderValue( const wxChar* szHeader, 2695 const wxChar* szDomain ) const 2696{ 2697 if ( wxIsEmpty(szHeader) ) 2698 return wxEmptyString; 2699 2700 wxChar const * pszTrans = NULL; 2701 wxMsgCatalog *pMsgCat; 2702 2703 if ( szDomain != NULL ) 2704 { 2705 pMsgCat = FindCatalog(szDomain); 2706 2707 // does the catalog exist? 2708 if ( pMsgCat == NULL ) 2709 return wxEmptyString; 2710 2711 pszTrans = pMsgCat->GetString(wxEmptyString, (size_t)-1); 2712 } 2713 else 2714 { 2715 // search in all domains 2716 for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext ) 2717 { 2718 pszTrans = pMsgCat->GetString(wxEmptyString, (size_t)-1); 2719 if ( pszTrans != NULL ) // take the first found 2720 break; 2721 } 2722 } 2723 2724 if ( wxIsEmpty(pszTrans) ) 2725 return wxEmptyString; 2726 2727 wxChar const * pszFound = wxStrstr(pszTrans, szHeader); 2728 if ( pszFound == NULL ) 2729 return wxEmptyString; 2730 2731 pszFound += wxStrlen(szHeader) + 2 /* ': ' */; 2732 2733 // Every header is separated by \n 2734 2735 wxChar const * pszEndLine = wxStrchr(pszFound, wxT('\n')); 2736 if ( pszEndLine == NULL ) pszEndLine = pszFound + wxStrlen(pszFound); 2737 2738 2739 // wxString( wxChar*, length); 2740 wxString retVal( pszFound, pszEndLine - pszFound ); 2741 2742 return retVal; 2743} 2744 2745 2746// find catalog by name in a linked list, return NULL if !found 2747wxMsgCatalog *wxLocale::FindCatalog(const wxChar *szDomain) const 2748{ 2749 // linear search in the linked list 2750 wxMsgCatalog *pMsgCat; 2751 for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext ) 2752 { 2753 if ( wxStricmp(pMsgCat->GetName(), szDomain) == 0 ) 2754 return pMsgCat; 2755 } 2756 2757 return NULL; 2758} 2759 2760// check if the given locale is provided by OS and C run time 2761/* static */ 2762bool wxLocale::IsAvailable(int lang) 2763{ 2764 const wxLanguageInfo *info = wxLocale::GetLanguageInfo(lang); 2765 wxCHECK_MSG( info, false, _T("invalid language") ); 2766 2767#if defined(__WIN32__) 2768 if ( !info->WinLang ) 2769 return false; 2770 2771 if ( !::IsValidLocale 2772 ( 2773 MAKELCID(MAKELANGID(info->WinLang, info->WinSublang), 2774 SORT_DEFAULT), 2775 LCID_INSTALLED 2776 ) ) 2777 return false; 2778 2779#elif defined(__UNIX__) 2780 2781 // Test if setting the locale works, then set it back. 2782 wxMB2WXbuf oldLocale = wxSetlocale(LC_ALL, wxEmptyString); 2783 wxMB2WXbuf tmp = wxSetlocaleTryUTF(LC_ALL, info->CanonicalName); 2784 if ( !tmp ) 2785 { 2786 // Some C libraries don't like xx_YY form and require xx only 2787 tmp = wxSetlocaleTryUTF(LC_ALL, info->CanonicalName.Left(2)); 2788 if ( !tmp ) 2789 return false; 2790 } 2791 // restore the original locale 2792 wxSetlocale(LC_ALL, oldLocale); 2793#endif 2794 2795 return true; 2796} 2797 2798// check if the given catalog is loaded 2799bool wxLocale::IsLoaded(const wxChar *szDomain) const 2800{ 2801 return FindCatalog(szDomain) != NULL; 2802} 2803 2804// add a catalog to our linked list 2805bool wxLocale::AddCatalog(const wxChar *szDomain) 2806{ 2807 return AddCatalog(szDomain, wxLANGUAGE_ENGLISH_US, NULL); 2808} 2809 2810// add a catalog to our linked list 2811bool wxLocale::AddCatalog(const wxChar *szDomain, 2812 wxLanguage msgIdLanguage, 2813 const wxChar *msgIdCharset) 2814 2815{ 2816 wxMsgCatalog *pMsgCat = new wxMsgCatalog; 2817 2818 if ( pMsgCat->Load(m_strShort, szDomain, msgIdCharset, m_bConvertEncoding) ) { 2819 // add it to the head of the list so that in GetString it will 2820 // be searched before the catalogs added earlier 2821 pMsgCat->m_pNext = m_pMsgCat; 2822 m_pMsgCat = pMsgCat; 2823 2824 return true; 2825 } 2826 else { 2827 // don't add it because it couldn't be loaded anyway 2828 delete pMsgCat; 2829 2830 // It is OK to not load catalog if the msgid language and m_language match, 2831 // in which case we can directly display the texts embedded in program's 2832 // source code: 2833 if (m_language == msgIdLanguage) 2834 return true; 2835 2836 // If there's no exact match, we may still get partial match where the 2837 // (basic) language is same, but the country differs. For example, it's 2838 // permitted to use en_US strings from sources even if m_language is en_GB: 2839 const wxLanguageInfo *msgIdLangInfo = GetLanguageInfo(msgIdLanguage); 2840 if ( msgIdLangInfo && 2841 msgIdLangInfo->CanonicalName.Mid(0, 2) == m_strShort.Mid(0, 2) ) 2842 { 2843 return true; 2844 } 2845 2846 return false; 2847 } 2848} 2849 2850// ---------------------------------------------------------------------------- 2851// accessors for locale-dependent data 2852// ---------------------------------------------------------------------------- 2853 2854#ifdef __WXMSW__ 2855 2856/* static */ 2857wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat)) 2858{ 2859 wxUint32 lcid = LOCALE_USER_DEFAULT; 2860 2861 if (wxGetLocale()) 2862 { 2863 const wxLanguageInfo *info = GetLanguageInfo(wxGetLocale()->GetLanguage()); 2864 if (info) 2865 { ; 2866 lcid = MAKELCID(MAKELANGID(info->WinLang, info->WinSublang), 2867 SORT_DEFAULT); 2868 } 2869 } 2870 2871 wxString str; 2872 wxChar buffer[256]; 2873 size_t count; 2874 buffer[0] = wxT('\0'); 2875 switch (index) 2876 { 2877 case wxLOCALE_DECIMAL_POINT: 2878 count = ::GetLocaleInfo(lcid, LOCALE_SDECIMAL, buffer, 256); 2879 if (!count) 2880 str << wxT("."); 2881 else 2882 str << buffer; 2883 break; 2884#if 0 2885 case wxSYS_LIST_SEPARATOR: 2886 count = ::GetLocaleInfo(lcid, LOCALE_SLIST, buffer, 256); 2887 if (!count) 2888 str << wxT(","); 2889 else 2890 str << buffer; 2891 break; 2892 case wxSYS_LEADING_ZERO: // 0 means no leading zero, 1 means leading zero 2893 count = ::GetLocaleInfo(lcid, LOCALE_ILZERO, buffer, 256); 2894 if (!count) 2895 str << wxT("0"); 2896 else 2897 str << buffer; 2898 break; 2899#endif 2900 default: 2901 wxFAIL_MSG(wxT("Unknown System String !")); 2902 } 2903 return str; 2904} 2905 2906#elif defined(__DARWIN__) 2907 2908/* static */ 2909wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat)) 2910{ 2911 CFLocaleRef userLocaleRefRaw; 2912 if ( wxGetLocale() ) 2913 { 2914 userLocaleRefRaw = CFLocaleCreate 2915 ( 2916 kCFAllocatorDefault, 2917 wxMacCFStringHolder(wxGetLocale()->GetCanonicalName()) 2918 ); 2919 } 2920 else // no current locale, use the default one 2921 { 2922 userLocaleRefRaw = CFLocaleCopyCurrent(); 2923 } 2924 2925 wxCFRef<CFLocaleRef> userLocaleRef(userLocaleRefRaw); 2926 2927 CFTypeRef cfstr; 2928 switch ( index ) 2929 { 2930 case wxLOCALE_THOUSANDS_SEP: 2931 cfstr = CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator); 2932 break; 2933 2934 case wxLOCALE_DECIMAL_POINT: 2935 cfstr = CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator); 2936 break; 2937 2938 default: 2939 wxFAIL_MSG( _T("Unknown locale info") ); 2940 } 2941 2942 wxMacCFStringHolder 2943 str(CFStringCreateCopy(NULL, static_cast<CFStringRef>(cfstr))); 2944 return str.AsString(); 2945} 2946 2947#else // !__WXMSW__ && !__DARWIN__ 2948 2949/* static */ 2950wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) 2951{ 2952 struct lconv *locale_info = localeconv(); 2953 switch (cat) 2954 { 2955 case wxLOCALE_CAT_NUMBER: 2956 switch (index) 2957 { 2958 case wxLOCALE_THOUSANDS_SEP: 2959 return wxString(locale_info->thousands_sep, 2960 *wxConvCurrent); 2961 case wxLOCALE_DECIMAL_POINT: 2962 return wxString(locale_info->decimal_point, 2963 *wxConvCurrent); 2964 default: 2965 return wxEmptyString; 2966 } 2967 case wxLOCALE_CAT_MONEY: 2968 switch (index) 2969 { 2970 case wxLOCALE_THOUSANDS_SEP: 2971 return wxString(locale_info->mon_thousands_sep, 2972 *wxConvCurrent); 2973 case wxLOCALE_DECIMAL_POINT: 2974 return wxString(locale_info->mon_decimal_point, 2975 *wxConvCurrent); 2976 default: 2977 return wxEmptyString; 2978 } 2979 default: 2980 return wxEmptyString; 2981 } 2982} 2983 2984#endif // __WXMSW__/!__WXMSW__ 2985 2986// ---------------------------------------------------------------------------- 2987// global functions and variables 2988// ---------------------------------------------------------------------------- 2989 2990// retrieve/change current locale 2991// ------------------------------ 2992 2993// the current locale object 2994static wxLocale *g_pLocale = NULL; 2995 2996wxLocale *wxGetLocale() 2997{ 2998 return g_pLocale; 2999} 3000 3001wxLocale *wxSetLocale(wxLocale *pLocale) 3002{ 3003 wxLocale *pOld = g_pLocale; 3004 g_pLocale = pLocale; 3005 return pOld; 3006} 3007 3008 3009 3010// ---------------------------------------------------------------------------- 3011// wxLocale module (for lazy destruction of languagesDB) 3012// ---------------------------------------------------------------------------- 3013 3014class wxLocaleModule: public wxModule 3015{ 3016 DECLARE_DYNAMIC_CLASS(wxLocaleModule) 3017 public: 3018 wxLocaleModule() {} 3019 bool OnInit() { return true; } 3020 void OnExit() { wxLocale::DestroyLanguagesDB(); } 3021}; 3022 3023IMPLEMENT_DYNAMIC_CLASS(wxLocaleModule, wxModule) 3024 3025 3026 3027// ---------------------------------------------------------------------------- 3028// default languages table & initialization 3029// ---------------------------------------------------------------------------- 3030 3031 3032 3033// --- --- --- generated code begins here --- --- --- 3034 3035// This table is generated by misc/languages/genlang.py 3036// When making changes, please put them into misc/languages/langtabl.txt 3037 3038#if !defined(__WIN32__) || defined(__WXMICROWIN__) 3039 3040#define SETWINLANG(info,lang,sublang) 3041 3042#else 3043 3044#define SETWINLANG(info,lang,sublang) \ 3045 info.WinLang = lang, info.WinSublang = sublang; 3046 3047#ifndef LANG_AFRIKAANS 3048#define LANG_AFRIKAANS (0) 3049#endif 3050#ifndef LANG_ALBANIAN 3051#define LANG_ALBANIAN (0) 3052#endif 3053#ifndef LANG_ARABIC 3054#define LANG_ARABIC (0) 3055#endif 3056#ifndef LANG_ARMENIAN 3057#define LANG_ARMENIAN (0) 3058#endif 3059#ifndef LANG_ASSAMESE 3060#define LANG_ASSAMESE (0) 3061#endif 3062#ifndef LANG_AZERI 3063#define LANG_AZERI (0) 3064#endif 3065#ifndef LANG_BASQUE 3066#define LANG_BASQUE (0) 3067#endif 3068#ifndef LANG_BELARUSIAN 3069#define LANG_BELARUSIAN (0) 3070#endif 3071#ifndef LANG_BENGALI 3072#define LANG_BENGALI (0) 3073#endif 3074#ifndef LANG_BULGARIAN 3075#define LANG_BULGARIAN (0) 3076#endif 3077#ifndef LANG_CATALAN 3078#define LANG_CATALAN (0) 3079#endif 3080#ifndef LANG_CHINESE 3081#define LANG_CHINESE (0) 3082#endif 3083#ifndef LANG_CROATIAN 3084#define LANG_CROATIAN (0) 3085#endif 3086#ifndef LANG_CZECH 3087#define LANG_CZECH (0) 3088#endif 3089#ifndef LANG_DANISH 3090#define LANG_DANISH (0) 3091#endif 3092#ifndef LANG_DUTCH 3093#define LANG_DUTCH (0) 3094#endif 3095#ifndef LANG_ENGLISH 3096#define LANG_ENGLISH (0) 3097#endif 3098#ifndef LANG_ESTONIAN 3099#define LANG_ESTONIAN (0) 3100#endif 3101#ifndef LANG_FAEROESE 3102#define LANG_FAEROESE (0) 3103#endif 3104#ifndef LANG_FARSI 3105#define LANG_FARSI (0) 3106#endif 3107#ifndef LANG_FINNISH 3108#define LANG_FINNISH (0) 3109#endif 3110#ifndef LANG_FRENCH 3111#define LANG_FRENCH (0) 3112#endif 3113#ifndef LANG_GEORGIAN 3114#define LANG_GEORGIAN (0) 3115#endif 3116#ifndef LANG_GERMAN 3117#define LANG_GERMAN (0) 3118#endif 3119#ifndef LANG_GREEK 3120#define LANG_GREEK (0) 3121#endif 3122#ifndef LANG_GUJARATI 3123#define LANG_GUJARATI (0) 3124#endif 3125#ifndef LANG_HEBREW 3126#define LANG_HEBREW (0) 3127#endif 3128#ifndef LANG_HINDI 3129#define LANG_HINDI (0) 3130#endif 3131#ifndef LANG_HUNGARIAN 3132#define LANG_HUNGARIAN (0) 3133#endif 3134#ifndef LANG_ICELANDIC 3135#define LANG_ICELANDIC (0) 3136#endif 3137#ifndef LANG_INDONESIAN 3138#define LANG_INDONESIAN (0) 3139#endif 3140#ifndef LANG_ITALIAN 3141#define LANG_ITALIAN (0) 3142#endif 3143#ifndef LANG_JAPANESE 3144#define LANG_JAPANESE (0) 3145#endif 3146#ifndef LANG_KANNADA 3147#define LANG_KANNADA (0) 3148#endif 3149#ifndef LANG_KASHMIRI 3150#define LANG_KASHMIRI (0) 3151#endif 3152#ifndef LANG_KAZAK 3153#define LANG_KAZAK (0) 3154#endif 3155#ifndef LANG_KONKANI 3156#define LANG_KONKANI (0) 3157#endif 3158#ifndef LANG_KOREAN 3159#define LANG_KOREAN (0) 3160#endif 3161#ifndef LANG_LATVIAN 3162#define LANG_LATVIAN (0) 3163#endif 3164#ifndef LANG_LITHUANIAN 3165#define LANG_LITHUANIAN (0) 3166#endif 3167#ifndef LANG_MACEDONIAN 3168#define LANG_MACEDONIAN (0) 3169#endif 3170#ifndef LANG_MALAY 3171#define LANG_MALAY (0) 3172#endif 3173#ifndef LANG_MALAYALAM 3174#define LANG_MALAYALAM (0) 3175#endif 3176#ifndef LANG_MANIPURI 3177#define LANG_MANIPURI (0) 3178#endif 3179#ifndef LANG_MARATHI 3180#define LANG_MARATHI (0) 3181#endif 3182#ifndef LANG_NEPALI 3183#define LANG_NEPALI (0) 3184#endif 3185#ifndef LANG_NORWEGIAN 3186#define LANG_NORWEGIAN (0) 3187#endif 3188#ifndef LANG_ORIYA 3189#define LANG_ORIYA (0) 3190#endif 3191#ifndef LANG_POLISH 3192#define LANG_POLISH (0) 3193#endif 3194#ifndef LANG_PORTUGUESE 3195#define LANG_PORTUGUESE (0) 3196#endif 3197#ifndef LANG_PUNJABI 3198#define LANG_PUNJABI (0) 3199#endif 3200#ifndef LANG_ROMANIAN 3201#define LANG_ROMANIAN (0) 3202#endif 3203#ifndef LANG_RUSSIAN 3204#define LANG_RUSSIAN (0) 3205#endif 3206#ifndef LANG_SAMI 3207#define LANG_SAMI (0) 3208#endif 3209#ifndef LANG_SANSKRIT 3210#define LANG_SANSKRIT (0) 3211#endif 3212#ifndef LANG_SERBIAN 3213#define LANG_SERBIAN (0) 3214#endif 3215#ifndef LANG_SINDHI 3216#define LANG_SINDHI (0) 3217#endif 3218#ifndef LANG_SLOVAK 3219#define LANG_SLOVAK (0) 3220#endif 3221#ifndef LANG_SLOVENIAN 3222#define LANG_SLOVENIAN (0) 3223#endif 3224#ifndef LANG_SPANISH 3225#define LANG_SPANISH (0) 3226#endif 3227#ifndef LANG_SWAHILI 3228#define LANG_SWAHILI (0) 3229#endif 3230#ifndef LANG_SWEDISH 3231#define LANG_SWEDISH (0) 3232#endif 3233#ifndef LANG_TAMIL 3234#define LANG_TAMIL (0) 3235#endif 3236#ifndef LANG_TATAR 3237#define LANG_TATAR (0) 3238#endif 3239#ifndef LANG_TELUGU 3240#define LANG_TELUGU (0) 3241#endif 3242#ifndef LANG_THAI 3243#define LANG_THAI (0) 3244#endif 3245#ifndef LANG_TURKISH 3246#define LANG_TURKISH (0) 3247#endif 3248#ifndef LANG_UKRAINIAN 3249#define LANG_UKRAINIAN (0) 3250#endif 3251#ifndef LANG_URDU 3252#define LANG_URDU (0) 3253#endif 3254#ifndef LANG_UZBEK 3255#define LANG_UZBEK (0) 3256#endif 3257#ifndef LANG_VALENCIAN 3258#define LANG_VALENCIAN (0) 3259#endif 3260#ifndef LANG_VIETNAMESE 3261#define LANG_VIETNAMESE (0) 3262#endif 3263#ifndef SUBLANG_ARABIC_ALGERIA 3264#define SUBLANG_ARABIC_ALGERIA SUBLANG_DEFAULT 3265#endif 3266#ifndef SUBLANG_ARABIC_BAHRAIN 3267#define SUBLANG_ARABIC_BAHRAIN SUBLANG_DEFAULT 3268#endif 3269#ifndef SUBLANG_ARABIC_EGYPT 3270#define SUBLANG_ARABIC_EGYPT SUBLANG_DEFAULT 3271#endif 3272#ifndef SUBLANG_ARABIC_IRAQ 3273#define SUBLANG_ARABIC_IRAQ SUBLANG_DEFAULT 3274#endif 3275#ifndef SUBLANG_ARABIC_JORDAN 3276#define SUBLANG_ARABIC_JORDAN SUBLANG_DEFAULT 3277#endif 3278#ifndef SUBLANG_ARABIC_KUWAIT 3279#define SUBLANG_ARABIC_KUWAIT SUBLANG_DEFAULT 3280#endif 3281#ifndef SUBLANG_ARABIC_LEBANON 3282#define SUBLANG_ARABIC_LEBANON SUBLANG_DEFAULT 3283#endif 3284#ifndef SUBLANG_ARABIC_LIBYA 3285#define SUBLANG_ARABIC_LIBYA SUBLANG_DEFAULT 3286#endif 3287#ifndef SUBLANG_ARABIC_MOROCCO 3288#define SUBLANG_ARABIC_MOROCCO SUBLANG_DEFAULT 3289#endif 3290#ifndef SUBLANG_ARABIC_OMAN 3291#define SUBLANG_ARABIC_OMAN SUBLANG_DEFAULT 3292#endif 3293#ifndef SUBLANG_ARABIC_QATAR 3294#define SUBLANG_ARABIC_QATAR SUBLANG_DEFAULT 3295#endif 3296#ifndef SUBLANG_ARABIC_SAUDI_ARABIA 3297#define SUBLANG_ARABIC_SAUDI_ARABIA SUBLANG_DEFAULT 3298#endif 3299#ifndef SUBLANG_ARABIC_SYRIA 3300#define SUBLANG_ARABIC_SYRIA SUBLANG_DEFAULT 3301#endif 3302#ifndef SUBLANG_ARABIC_TUNISIA 3303#define SUBLANG_ARABIC_TUNISIA SUBLANG_DEFAULT 3304#endif 3305#ifndef SUBLANG_ARABIC_UAE 3306#define SUBLANG_ARABIC_UAE SUBLANG_DEFAULT 3307#endif 3308#ifndef SUBLANG_ARABIC_YEMEN 3309#define SUBLANG_ARABIC_YEMEN SUBLANG_DEFAULT 3310#endif 3311#ifndef SUBLANG_AZERI_CYRILLIC 3312#define SUBLANG_AZERI_CYRILLIC SUBLANG_DEFAULT 3313#endif 3314#ifndef SUBLANG_AZERI_LATIN 3315#define SUBLANG_AZERI_LATIN SUBLANG_DEFAULT 3316#endif 3317#ifndef SUBLANG_CHINESE_SIMPLIFIED 3318#define SUBLANG_CHINESE_SIMPLIFIED SUBLANG_DEFAULT 3319#endif 3320#ifndef SUBLANG_CHINESE_TRADITIONAL 3321#define SUBLANG_CHINESE_TRADITIONAL SUBLANG_DEFAULT 3322#endif 3323#ifndef SUBLANG_CHINESE_HONGKONG 3324#define SUBLANG_CHINESE_HONGKONG SUBLANG_DEFAULT 3325#endif 3326#ifndef SUBLANG_CHINESE_MACAU 3327#define SUBLANG_CHINESE_MACAU SUBLANG_DEFAULT 3328#endif 3329#ifndef SUBLANG_CHINESE_SINGAPORE 3330#define SUBLANG_CHINESE_SINGAPORE SUBLANG_DEFAULT 3331#endif 3332#ifndef SUBLANG_DUTCH 3333#define SUBLANG_DUTCH SUBLANG_DEFAULT 3334#endif 3335#ifndef SUBLANG_DUTCH_BELGIAN 3336#define SUBLANG_DUTCH_BELGIAN SUBLANG_DEFAULT 3337#endif 3338#ifndef SUBLANG_ENGLISH_UK 3339#define SUBLANG_ENGLISH_UK SUBLANG_DEFAULT 3340#endif 3341#ifndef SUBLANG_ENGLISH_US 3342#define SUBLANG_ENGLISH_US SUBLANG_DEFAULT 3343#endif 3344#ifndef SUBLANG_ENGLISH_AUS 3345#define SUBLANG_ENGLISH_AUS SUBLANG_DEFAULT 3346#endif 3347#ifndef SUBLANG_ENGLISH_BELIZE 3348#define SUBLANG_ENGLISH_BELIZE SUBLANG_DEFAULT 3349#endif 3350#ifndef SUBLANG_ENGLISH_CAN 3351#define SUBLANG_ENGLISH_CAN SUBLANG_DEFAULT 3352#endif 3353#ifndef SUBLANG_ENGLISH_CARIBBEAN 3354#define SUBLANG_ENGLISH_CARIBBEAN SUBLANG_DEFAULT 3355#endif 3356#ifndef SUBLANG_ENGLISH_EIRE 3357#define SUBLANG_ENGLISH_EIRE SUBLANG_DEFAULT 3358#endif 3359#ifndef SUBLANG_ENGLISH_JAMAICA 3360#define SUBLANG_ENGLISH_JAMAICA SUBLANG_DEFAULT 3361#endif 3362#ifndef SUBLANG_ENGLISH_NZ 3363#define SUBLANG_ENGLISH_NZ SUBLANG_DEFAULT 3364#endif 3365#ifndef SUBLANG_ENGLISH_PHILIPPINES 3366#define SUBLANG_ENGLISH_PHILIPPINES SUBLANG_DEFAULT 3367#endif 3368#ifndef SUBLANG_ENGLISH_SOUTH_AFRICA 3369#define SUBLANG_ENGLISH_SOUTH_AFRICA SUBLANG_DEFAULT 3370#endif 3371#ifndef SUBLANG_ENGLISH_TRINIDAD 3372#define SUBLANG_ENGLISH_TRINIDAD SUBLANG_DEFAULT 3373#endif 3374#ifndef SUBLANG_ENGLISH_ZIMBABWE 3375#define SUBLANG_ENGLISH_ZIMBABWE SUBLANG_DEFAULT 3376#endif 3377#ifndef SUBLANG_FRENCH 3378#define SUBLANG_FRENCH SUBLANG_DEFAULT 3379#endif 3380#ifndef SUBLANG_FRENCH_BELGIAN 3381#define SUBLANG_FRENCH_BELGIAN SUBLANG_DEFAULT 3382#endif 3383#ifndef SUBLANG_FRENCH_CANADIAN 3384#define SUBLANG_FRENCH_CANADIAN SUBLANG_DEFAULT 3385#endif 3386#ifndef SUBLANG_FRENCH_LUXEMBOURG 3387#define SUBLANG_FRENCH_LUXEMBOURG SUBLANG_DEFAULT 3388#endif 3389#ifndef SUBLANG_FRENCH_MONACO 3390#define SUBLANG_FRENCH_MONACO SUBLANG_DEFAULT 3391#endif 3392#ifndef SUBLANG_FRENCH_SWISS 3393#define SUBLANG_FRENCH_SWISS SUBLANG_DEFAULT 3394#endif 3395#ifndef SUBLANG_GERMAN 3396#define SUBLANG_GERMAN SUBLANG_DEFAULT 3397#endif 3398#ifndef SUBLANG_GERMAN_AUSTRIAN 3399#define SUBLANG_GERMAN_AUSTRIAN SUBLANG_DEFAULT 3400#endif 3401#ifndef SUBLANG_GERMAN_LIECHTENSTEIN 3402#define SUBLANG_GERMAN_LIECHTENSTEIN SUBLANG_DEFAULT 3403#endif 3404#ifndef SUBLANG_GERMAN_LUXEMBOURG 3405#define SUBLANG_GERMAN_LUXEMBOURG SUBLANG_DEFAULT 3406#endif 3407#ifndef SUBLANG_GERMAN_SWISS 3408#define SUBLANG_GERMAN_SWISS SUBLANG_DEFAULT 3409#endif 3410#ifndef SUBLANG_ITALIAN 3411#define SUBLANG_ITALIAN SUBLANG_DEFAULT 3412#endif 3413#ifndef SUBLANG_ITALIAN_SWISS 3414#define SUBLANG_ITALIAN_SWISS SUBLANG_DEFAULT 3415#endif 3416#ifndef SUBLANG_KASHMIRI_INDIA 3417#define SUBLANG_KASHMIRI_INDIA SUBLANG_DEFAULT 3418#endif 3419#ifndef SUBLANG_KOREAN 3420#define SUBLANG_KOREAN SUBLANG_DEFAULT 3421#endif 3422#ifndef SUBLANG_LITHUANIAN 3423#define SUBLANG_LITHUANIAN SUBLANG_DEFAULT 3424#endif 3425#ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM 3426#define SUBLANG_MALAY_BRUNEI_DARUSSALAM SUBLANG_DEFAULT 3427#endif 3428#ifndef SUBLANG_MALAY_MALAYSIA 3429#define SUBLANG_MALAY_MALAYSIA SUBLANG_DEFAULT 3430#endif 3431#ifndef SUBLANG_NEPALI_INDIA 3432#define SUBLANG_NEPALI_INDIA SUBLANG_DEFAULT 3433#endif 3434#ifndef SUBLANG_NORWEGIAN_BOKMAL 3435#define SUBLANG_NORWEGIAN_BOKMAL SUBLANG_DEFAULT 3436#endif 3437#ifndef SUBLANG_NORWEGIAN_NYNORSK 3438#define SUBLANG_NORWEGIAN_NYNORSK SUBLANG_DEFAULT 3439#endif 3440#ifndef SUBLANG_PORTUGUESE 3441#define SUBLANG_PORTUGUESE SUBLANG_DEFAULT 3442#endif 3443#ifndef SUBLANG_PORTUGUESE_BRAZILIAN 3444#define SUBLANG_PORTUGUESE_BRAZILIAN SUBLANG_DEFAULT 3445#endif 3446#ifndef SUBLANG_SERBIAN_CYRILLIC 3447#define SUBLANG_SERBIAN_CYRILLIC SUBLANG_DEFAULT 3448#endif 3449#ifndef SUBLANG_SERBIAN_LATIN 3450#define SUBLANG_SERBIAN_LATIN SUBLANG_DEFAULT 3451#endif 3452#ifndef SUBLANG_SPANISH 3453#define SUBLANG_SPANISH SUBLANG_DEFAULT 3454#endif 3455#ifndef SUBLANG_SPANISH_ARGENTINA 3456#define SUBLANG_SPANISH_ARGENTINA SUBLANG_DEFAULT 3457#endif 3458#ifndef SUBLANG_SPANISH_BOLIVIA 3459#define SUBLANG_SPANISH_BOLIVIA SUBLANG_DEFAULT 3460#endif 3461#ifndef SUBLANG_SPANISH_CHILE 3462#define SUBLANG_SPANISH_CHILE SUBLANG_DEFAULT 3463#endif 3464#ifndef SUBLANG_SPANISH_COLOMBIA 3465#define SUBLANG_SPANISH_COLOMBIA SUBLANG_DEFAULT 3466#endif 3467#ifndef SUBLANG_SPANISH_COSTA_RICA 3468#define SUBLANG_SPANISH_COSTA_RICA SUBLANG_DEFAULT 3469#endif 3470#ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC 3471#define SUBLANG_SPANISH_DOMINICAN_REPUBLIC SUBLANG_DEFAULT 3472#endif 3473#ifndef SUBLANG_SPANISH_ECUADOR 3474#define SUBLANG_SPANISH_ECUADOR SUBLANG_DEFAULT 3475#endif 3476#ifndef SUBLANG_SPANISH_EL_SALVADOR 3477#define SUBLANG_SPANISH_EL_SALVADOR SUBLANG_DEFAULT 3478#endif 3479#ifndef SUBLANG_SPANISH_GUATEMALA 3480#define SUBLANG_SPANISH_GUATEMALA SUBLANG_DEFAULT 3481#endif 3482#ifndef SUBLANG_SPANISH_HONDURAS 3483#define SUBLANG_SPANISH_HONDURAS SUBLANG_DEFAULT 3484#endif 3485#ifndef SUBLANG_SPANISH_MEXICAN 3486#define SUBLANG_SPANISH_MEXICAN SUBLANG_DEFAULT 3487#endif 3488#ifndef SUBLANG_SPANISH_MODERN 3489#define SUBLANG_SPANISH_MODERN SUBLANG_DEFAULT 3490#endif 3491#ifndef SUBLANG_SPANISH_NICARAGUA 3492#define SUBLANG_SPANISH_NICARAGUA SUBLANG_DEFAULT 3493#endif 3494#ifndef SUBLANG_SPANISH_PANAMA 3495#define SUBLANG_SPANISH_PANAMA SUBLANG_DEFAULT 3496#endif 3497#ifndef SUBLANG_SPANISH_PARAGUAY 3498#define SUBLANG_SPANISH_PARAGUAY SUBLANG_DEFAULT 3499#endif 3500#ifndef SUBLANG_SPANISH_PERU 3501#define SUBLANG_SPANISH_PERU SUBLANG_DEFAULT 3502#endif 3503#ifndef SUBLANG_SPANISH_PUERTO_RICO 3504#define SUBLANG_SPANISH_PUERTO_RICO SUBLANG_DEFAULT 3505#endif 3506#ifndef SUBLANG_SPANISH_URUGUAY 3507#define SUBLANG_SPANISH_URUGUAY SUBLANG_DEFAULT 3508#endif 3509#ifndef SUBLANG_SPANISH_VENEZUELA 3510#define SUBLANG_SPANISH_VENEZUELA SUBLANG_DEFAULT 3511#endif 3512#ifndef SUBLANG_SWEDISH 3513#define SUBLANG_SWEDISH SUBLANG_DEFAULT 3514#endif 3515#ifndef SUBLANG_SWEDISH_FINLAND 3516#define SUBLANG_SWEDISH_FINLAND SUBLANG_DEFAULT 3517#endif 3518#ifndef SUBLANG_URDU_INDIA 3519#define SUBLANG_URDU_INDIA SUBLANG_DEFAULT 3520#endif 3521#ifndef SUBLANG_URDU_PAKISTAN 3522#define SUBLANG_URDU_PAKISTAN SUBLANG_DEFAULT 3523#endif 3524#ifndef SUBLANG_UZBEK_CYRILLIC 3525#define SUBLANG_UZBEK_CYRILLIC SUBLANG_DEFAULT 3526#endif 3527#ifndef SUBLANG_UZBEK_LATIN 3528#define SUBLANG_UZBEK_LATIN SUBLANG_DEFAULT 3529#endif 3530 3531 3532#endif // __WIN32__ 3533 3534#define LNG(wxlang, canonical, winlang, winsublang, layout, desc) \ 3535 info.Language = wxlang; \ 3536 info.CanonicalName = wxT(canonical); \ 3537 info.LayoutDirection = layout; \ 3538 info.Description = wxT(desc); \ 3539 SETWINLANG(info, winlang, winsublang) \ 3540 AddLanguage(info); 3541 3542void wxLocale::InitLanguagesDB() 3543{ 3544 wxLanguageInfo info; 3545 wxStringTokenizer tkn; 3546 3547 LNG(wxLANGUAGE_ABKHAZIAN, "ab" , 0 , 0 , wxLayout_LeftToRight, "Abkhazian") 3548 LNG(wxLANGUAGE_AFAR, "aa" , 0 , 0 , wxLayout_LeftToRight, "Afar") 3549 LNG(wxLANGUAGE_AFRIKAANS, "af_ZA", LANG_AFRIKAANS , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Afrikaans") 3550 LNG(wxLANGUAGE_ALBANIAN, "sq_AL", LANG_ALBANIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Albanian") 3551 LNG(wxLANGUAGE_AMHARIC, "am" , 0 , 0 , wxLayout_LeftToRight, "Amharic") 3552 LNG(wxLANGUAGE_ARABIC, "ar" , LANG_ARABIC , SUBLANG_DEFAULT , wxLayout_RightToLeft, "Arabic") 3553 LNG(wxLANGUAGE_ARABIC_ALGERIA, "ar_DZ", LANG_ARABIC , SUBLANG_ARABIC_ALGERIA , wxLayout_RightToLeft, "Arabic (Algeria)") 3554 LNG(wxLANGUAGE_ARABIC_BAHRAIN, "ar_BH", LANG_ARABIC , SUBLANG_ARABIC_BAHRAIN , wxLayout_RightToLeft, "Arabic (Bahrain)") 3555 LNG(wxLANGUAGE_ARABIC_EGYPT, "ar_EG", LANG_ARABIC , SUBLANG_ARABIC_EGYPT , wxLayout_RightToLeft, "Arabic (Egypt)") 3556 LNG(wxLANGUAGE_ARABIC_IRAQ, "ar_IQ", LANG_ARABIC , SUBLANG_ARABIC_IRAQ , wxLayout_RightToLeft, "Arabic (Iraq)") 3557 LNG(wxLANGUAGE_ARABIC_JORDAN, "ar_JO", LANG_ARABIC , SUBLANG_ARABIC_JORDAN , wxLayout_RightToLeft, "Arabic (Jordan)") 3558 LNG(wxLANGUAGE_ARABIC_KUWAIT, "ar_KW", LANG_ARABIC , SUBLANG_ARABIC_KUWAIT , wxLayout_RightToLeft, "Arabic (Kuwait)") 3559 LNG(wxLANGUAGE_ARABIC_LEBANON, "ar_LB", LANG_ARABIC , SUBLANG_ARABIC_LEBANON , wxLayout_RightToLeft, "Arabic (Lebanon)") 3560 LNG(wxLANGUAGE_ARABIC_LIBYA, "ar_LY", LANG_ARABIC , SUBLANG_ARABIC_LIBYA , wxLayout_RightToLeft, "Arabic (Libya)") 3561 LNG(wxLANGUAGE_ARABIC_MOROCCO, "ar_MA", LANG_ARABIC , SUBLANG_ARABIC_MOROCCO , wxLayout_RightToLeft, "Arabic (Morocco)") 3562 LNG(wxLANGUAGE_ARABIC_OMAN, "ar_OM", LANG_ARABIC , SUBLANG_ARABIC_OMAN , wxLayout_RightToLeft, "Arabic (Oman)") 3563 LNG(wxLANGUAGE_ARABIC_QATAR, "ar_QA", LANG_ARABIC , SUBLANG_ARABIC_QATAR , wxLayout_RightToLeft, "Arabic (Qatar)") 3564 LNG(wxLANGUAGE_ARABIC_SAUDI_ARABIA, "ar_SA", LANG_ARABIC , SUBLANG_ARABIC_SAUDI_ARABIA , wxLayout_RightToLeft, "Arabic (Saudi Arabia)") 3565 LNG(wxLANGUAGE_ARABIC_SUDAN, "ar_SD", 0 , 0 , wxLayout_RightToLeft, "Arabic (Sudan)") 3566 LNG(wxLANGUAGE_ARABIC_SYRIA, "ar_SY", LANG_ARABIC , SUBLANG_ARABIC_SYRIA , wxLayout_RightToLeft, "Arabic (Syria)") 3567 LNG(wxLANGUAGE_ARABIC_TUNISIA, "ar_TN", LANG_ARABIC , SUBLANG_ARABIC_TUNISIA , wxLayout_RightToLeft, "Arabic (Tunisia)") 3568 LNG(wxLANGUAGE_ARABIC_UAE, "ar_AE", LANG_ARABIC , SUBLANG_ARABIC_UAE , wxLayout_RightToLeft, "Arabic (Uae)") 3569 LNG(wxLANGUAGE_ARABIC_YEMEN, "ar_YE", LANG_ARABIC , SUBLANG_ARABIC_YEMEN , wxLayout_RightToLeft, "Arabic (Yemen)") 3570 LNG(wxLANGUAGE_ARMENIAN, "hy" , LANG_ARMENIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Armenian") 3571 LNG(wxLANGUAGE_ASSAMESE, "as" , LANG_ASSAMESE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Assamese") 3572 LNG(wxLANGUAGE_AYMARA, "ay" , 0 , 0 , wxLayout_LeftToRight, "Aymara") 3573 LNG(wxLANGUAGE_AZERI, "az" , LANG_AZERI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Azeri") 3574 LNG(wxLANGUAGE_AZERI_CYRILLIC, "az" , LANG_AZERI , SUBLANG_AZERI_CYRILLIC , wxLayout_LeftToRight, "Azeri (Cyrillic)") 3575 LNG(wxLANGUAGE_AZERI_LATIN, "az" , LANG_AZERI , SUBLANG_AZERI_LATIN , wxLayout_LeftToRight, "Azeri (Latin)") 3576 LNG(wxLANGUAGE_BASHKIR, "ba" , 0 , 0 , wxLayout_LeftToRight, "Bashkir") 3577 LNG(wxLANGUAGE_BASQUE, "eu_ES", LANG_BASQUE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Basque") 3578 LNG(wxLANGUAGE_BELARUSIAN, "be_BY", LANG_BELARUSIAN, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Belarusian") 3579 LNG(wxLANGUAGE_BENGALI, "bn" , LANG_BENGALI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Bengali") 3580 LNG(wxLANGUAGE_BHUTANI, "dz" , 0 , 0 , wxLayout_LeftToRight, "Bhutani") 3581 LNG(wxLANGUAGE_BIHARI, "bh" , 0 , 0 , wxLayout_LeftToRight, "Bihari") 3582 LNG(wxLANGUAGE_BISLAMA, "bi" , 0 , 0 , wxLayout_LeftToRight, "Bislama") 3583 LNG(wxLANGUAGE_BRETON, "br" , 0 , 0 , wxLayout_LeftToRight, "Breton") 3584 LNG(wxLANGUAGE_BULGARIAN, "bg_BG", LANG_BULGARIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Bulgarian") 3585 LNG(wxLANGUAGE_BURMESE, "my" , 0 , 0 , wxLayout_LeftToRight, "Burmese") 3586 LNG(wxLANGUAGE_CAMBODIAN, "km" , 0 , 0 , wxLayout_LeftToRight, "Cambodian") 3587 LNG(wxLANGUAGE_CATALAN, "ca_ES", LANG_CATALAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Catalan") 3588 LNG(wxLANGUAGE_CHINESE, "zh_TW", LANG_CHINESE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Chinese") 3589 LNG(wxLANGUAGE_CHINESE_SIMPLIFIED, "zh_CN", LANG_CHINESE , SUBLANG_CHINESE_SIMPLIFIED , wxLayout_LeftToRight, "Chinese (Simplified)") 3590 LNG(wxLANGUAGE_CHINESE_TRADITIONAL, "zh_TW", LANG_CHINESE , SUBLANG_CHINESE_TRADITIONAL , wxLayout_LeftToRight, "Chinese (Traditional)") 3591 LNG(wxLANGUAGE_CHINESE_HONGKONG, "zh_HK", LANG_CHINESE , SUBLANG_CHINESE_HONGKONG , wxLayout_LeftToRight, "Chinese (Hongkong)") 3592 LNG(wxLANGUAGE_CHINESE_MACAU, "zh_MO", LANG_CHINESE , SUBLANG_CHINESE_MACAU , wxLayout_LeftToRight, "Chinese (Macau)") 3593 LNG(wxLANGUAGE_CHINESE_SINGAPORE, "zh_SG", LANG_CHINESE , SUBLANG_CHINESE_SINGAPORE , wxLayout_LeftToRight, "Chinese (Singapore)") 3594 LNG(wxLANGUAGE_CHINESE_TAIWAN, "zh_TW", LANG_CHINESE , SUBLANG_CHINESE_TRADITIONAL , wxLayout_LeftToRight, "Chinese (Taiwan)") 3595 LNG(wxLANGUAGE_CORSICAN, "co" , 0 , 0 , wxLayout_LeftToRight, "Corsican") 3596 LNG(wxLANGUAGE_CROATIAN, "hr_HR", LANG_CROATIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Croatian") 3597 LNG(wxLANGUAGE_CZECH, "cs_CZ", LANG_CZECH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Czech") 3598 LNG(wxLANGUAGE_DANISH, "da_DK", LANG_DANISH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Danish") 3599 LNG(wxLANGUAGE_DUTCH, "nl_NL", LANG_DUTCH , SUBLANG_DUTCH , wxLayout_LeftToRight, "Dutch") 3600 LNG(wxLANGUAGE_DUTCH_BELGIAN, "nl_BE", LANG_DUTCH , SUBLANG_DUTCH_BELGIAN , wxLayout_LeftToRight, "Dutch (Belgian)") 3601 LNG(wxLANGUAGE_ENGLISH, "en_GB", LANG_ENGLISH , SUBLANG_ENGLISH_UK , wxLayout_LeftToRight, "English") 3602 LNG(wxLANGUAGE_ENGLISH_UK, "en_GB", LANG_ENGLISH , SUBLANG_ENGLISH_UK , wxLayout_LeftToRight, "English (U.K.)") 3603 LNG(wxLANGUAGE_ENGLISH_US, "en_US", LANG_ENGLISH , SUBLANG_ENGLISH_US , wxLayout_LeftToRight, "English (U.S.)") 3604 LNG(wxLANGUAGE_ENGLISH_AUSTRALIA, "en_AU", LANG_ENGLISH , SUBLANG_ENGLISH_AUS , wxLayout_LeftToRight, "English (Australia)") 3605 LNG(wxLANGUAGE_ENGLISH_BELIZE, "en_BZ", LANG_ENGLISH , SUBLANG_ENGLISH_BELIZE , wxLayout_LeftToRight, "English (Belize)") 3606 LNG(wxLANGUAGE_ENGLISH_BOTSWANA, "en_BW", 0 , 0 , wxLayout_LeftToRight, "English (Botswana)") 3607 LNG(wxLANGUAGE_ENGLISH_CANADA, "en_CA", LANG_ENGLISH , SUBLANG_ENGLISH_CAN , wxLayout_LeftToRight, "English (Canada)") 3608 LNG(wxLANGUAGE_ENGLISH_CARIBBEAN, "en_CB", LANG_ENGLISH , SUBLANG_ENGLISH_CARIBBEAN , wxLayout_LeftToRight, "English (Caribbean)") 3609 LNG(wxLANGUAGE_ENGLISH_DENMARK, "en_DK", 0 , 0 , wxLayout_LeftToRight, "English (Denmark)") 3610 LNG(wxLANGUAGE_ENGLISH_EIRE, "en_IE", LANG_ENGLISH , SUBLANG_ENGLISH_EIRE , wxLayout_LeftToRight, "English (Eire)") 3611 LNG(wxLANGUAGE_ENGLISH_JAMAICA, "en_JM", LANG_ENGLISH , SUBLANG_ENGLISH_JAMAICA , wxLayout_LeftToRight, "English (Jamaica)") 3612 LNG(wxLANGUAGE_ENGLISH_NEW_ZEALAND, "en_NZ", LANG_ENGLISH , SUBLANG_ENGLISH_NZ , wxLayout_LeftToRight, "English (New Zealand)") 3613 LNG(wxLANGUAGE_ENGLISH_PHILIPPINES, "en_PH", LANG_ENGLISH , SUBLANG_ENGLISH_PHILIPPINES , wxLayout_LeftToRight, "English (Philippines)") 3614 LNG(wxLANGUAGE_ENGLISH_SOUTH_AFRICA, "en_ZA", LANG_ENGLISH , SUBLANG_ENGLISH_SOUTH_AFRICA , wxLayout_LeftToRight, "English (South Africa)") 3615 LNG(wxLANGUAGE_ENGLISH_TRINIDAD, "en_TT", LANG_ENGLISH , SUBLANG_ENGLISH_TRINIDAD , wxLayout_LeftToRight, "English (Trinidad)") 3616 LNG(wxLANGUAGE_ENGLISH_ZIMBABWE, "en_ZW", LANG_ENGLISH , SUBLANG_ENGLISH_ZIMBABWE , wxLayout_LeftToRight, "English (Zimbabwe)") 3617 LNG(wxLANGUAGE_ESPERANTO, "eo" , 0 , 0 , wxLayout_LeftToRight, "Esperanto") 3618 LNG(wxLANGUAGE_ESTONIAN, "et_EE", LANG_ESTONIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Estonian") 3619 LNG(wxLANGUAGE_FAEROESE, "fo_FO", LANG_FAEROESE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Faeroese") 3620 LNG(wxLANGUAGE_FARSI, "fa_IR", LANG_FARSI , SUBLANG_DEFAULT , wxLayout_RightToLeft, "Farsi") 3621 LNG(wxLANGUAGE_FIJI, "fj" , 0 , 0 , wxLayout_LeftToRight, "Fiji") 3622 LNG(wxLANGUAGE_FINNISH, "fi_FI", LANG_FINNISH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Finnish") 3623 LNG(wxLANGUAGE_FRENCH, "fr_FR", LANG_FRENCH , SUBLANG_FRENCH , wxLayout_LeftToRight, "French") 3624 LNG(wxLANGUAGE_FRENCH_BELGIAN, "fr_BE", LANG_FRENCH , SUBLANG_FRENCH_BELGIAN , wxLayout_LeftToRight, "French (Belgian)") 3625 LNG(wxLANGUAGE_FRENCH_CANADIAN, "fr_CA", LANG_FRENCH , SUBLANG_FRENCH_CANADIAN , wxLayout_LeftToRight, "French (Canadian)") 3626 LNG(wxLANGUAGE_FRENCH_LUXEMBOURG, "fr_LU", LANG_FRENCH , SUBLANG_FRENCH_LUXEMBOURG , wxLayout_LeftToRight, "French (Luxembourg)") 3627 LNG(wxLANGUAGE_FRENCH_MONACO, "fr_MC", LANG_FRENCH , SUBLANG_FRENCH_MONACO , wxLayout_LeftToRight, "French (Monaco)") 3628 LNG(wxLANGUAGE_FRENCH_SWISS, "fr_CH", LANG_FRENCH , SUBLANG_FRENCH_SWISS , wxLayout_LeftToRight, "French (Swiss)") 3629 LNG(wxLANGUAGE_FRISIAN, "fy" , 0 , 0 , wxLayout_LeftToRight, "Frisian") 3630 LNG(wxLANGUAGE_GALICIAN, "gl_ES", 0 , 0 , wxLayout_LeftToRight, "Galician") 3631 LNG(wxLANGUAGE_GEORGIAN, "ka_GE", LANG_GEORGIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Georgian") 3632 LNG(wxLANGUAGE_GERMAN, "de_DE", LANG_GERMAN , SUBLANG_GERMAN , wxLayout_LeftToRight, "German") 3633 LNG(wxLANGUAGE_GERMAN_AUSTRIAN, "de_AT", LANG_GERMAN , SUBLANG_GERMAN_AUSTRIAN , wxLayout_LeftToRight, "German (Austrian)") 3634 LNG(wxLANGUAGE_GERMAN_BELGIUM, "de_BE", 0 , 0 , wxLayout_LeftToRight, "German (Belgium)") 3635 LNG(wxLANGUAGE_GERMAN_LIECHTENSTEIN, "de_LI", LANG_GERMAN , SUBLANG_GERMAN_LIECHTENSTEIN , wxLayout_LeftToRight, "German (Liechtenstein)") 3636 LNG(wxLANGUAGE_GERMAN_LUXEMBOURG, "de_LU", LANG_GERMAN , SUBLANG_GERMAN_LUXEMBOURG , wxLayout_LeftToRight, "German (Luxembourg)") 3637 LNG(wxLANGUAGE_GERMAN_SWISS, "de_CH", LANG_GERMAN , SUBLANG_GERMAN_SWISS , wxLayout_LeftToRight, "German (Swiss)") 3638 LNG(wxLANGUAGE_GREEK, "el_GR", LANG_GREEK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Greek") 3639 LNG(wxLANGUAGE_GREENLANDIC, "kl_GL", 0 , 0 , wxLayout_LeftToRight, "Greenlandic") 3640 LNG(wxLANGUAGE_GUARANI, "gn" , 0 , 0 , wxLayout_LeftToRight, "Guarani") 3641 LNG(wxLANGUAGE_GUJARATI, "gu" , LANG_GUJARATI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Gujarati") 3642 LNG(wxLANGUAGE_HAUSA, "ha" , 0 , 0 , wxLayout_LeftToRight, "Hausa") 3643 LNG(wxLANGUAGE_HEBREW, "he_IL", LANG_HEBREW , SUBLANG_DEFAULT , wxLayout_RightToLeft, "Hebrew") 3644 LNG(wxLANGUAGE_HINDI, "hi_IN", LANG_HINDI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Hindi") 3645 LNG(wxLANGUAGE_HUNGARIAN, "hu_HU", LANG_HUNGARIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Hungarian") 3646 LNG(wxLANGUAGE_ICELANDIC, "is_IS", LANG_ICELANDIC , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Icelandic") 3647 LNG(wxLANGUAGE_INDONESIAN, "id_ID", LANG_INDONESIAN, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Indonesian") 3648 LNG(wxLANGUAGE_INTERLINGUA, "ia" , 0 , 0 , wxLayout_LeftToRight, "Interlingua") 3649 LNG(wxLANGUAGE_INTERLINGUE, "ie" , 0 , 0 , wxLayout_LeftToRight, "Interlingue") 3650 LNG(wxLANGUAGE_INUKTITUT, "iu" , 0 , 0 , wxLayout_LeftToRight, "Inuktitut") 3651 LNG(wxLANGUAGE_INUPIAK, "ik" , 0 , 0 , wxLayout_LeftToRight, "Inupiak") 3652 LNG(wxLANGUAGE_IRISH, "ga_IE", 0 , 0 , wxLayout_LeftToRight, "Irish") 3653 LNG(wxLANGUAGE_ITALIAN, "it_IT", LANG_ITALIAN , SUBLANG_ITALIAN , wxLayout_LeftToRight, "Italian") 3654 LNG(wxLANGUAGE_ITALIAN_SWISS, "it_CH", LANG_ITALIAN , SUBLANG_ITALIAN_SWISS , wxLayout_LeftToRight, "Italian (Swiss)") 3655 LNG(wxLANGUAGE_JAPANESE, "ja_JP", LANG_JAPANESE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Japanese") 3656 LNG(wxLANGUAGE_JAVANESE, "jw" , 0 , 0 , wxLayout_LeftToRight, "Javanese") 3657 LNG(wxLANGUAGE_KANNADA, "kn" , LANG_KANNADA , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Kannada") 3658 LNG(wxLANGUAGE_KASHMIRI, "ks" , LANG_KASHMIRI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Kashmiri") 3659 LNG(wxLANGUAGE_KASHMIRI_INDIA, "ks_IN", LANG_KASHMIRI , SUBLANG_KASHMIRI_INDIA , wxLayout_LeftToRight, "Kashmiri (India)") 3660 LNG(wxLANGUAGE_KAZAKH, "kk" , LANG_KAZAK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Kazakh") 3661 LNG(wxLANGUAGE_KERNEWEK, "kw_GB", 0 , 0 , wxLayout_LeftToRight, "Kernewek") 3662 LNG(wxLANGUAGE_KINYARWANDA, "rw" , 0 , 0 , wxLayout_LeftToRight, "Kinyarwanda") 3663 LNG(wxLANGUAGE_KIRGHIZ, "ky" , 0 , 0 , wxLayout_LeftToRight, "Kirghiz") 3664 LNG(wxLANGUAGE_KIRUNDI, "rn" , 0 , 0 , wxLayout_LeftToRight, "Kirundi") 3665 LNG(wxLANGUAGE_KONKANI, "" , LANG_KONKANI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Konkani") 3666 LNG(wxLANGUAGE_KOREAN, "ko_KR", LANG_KOREAN , SUBLANG_KOREAN , wxLayout_LeftToRight, "Korean") 3667 LNG(wxLANGUAGE_KURDISH, "ku_TR", 0 , 0 , wxLayout_LeftToRight, "Kurdish") 3668 LNG(wxLANGUAGE_LAOTHIAN, "lo" , 0 , 0 , wxLayout_LeftToRight, "Laothian") 3669 LNG(wxLANGUAGE_LATIN, "la" , 0 , 0 , wxLayout_LeftToRight, "Latin") 3670 LNG(wxLANGUAGE_LATVIAN, "lv_LV", LANG_LATVIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Latvian") 3671 LNG(wxLANGUAGE_LINGALA, "ln" , 0 , 0 , wxLayout_LeftToRight, "Lingala") 3672 LNG(wxLANGUAGE_LITHUANIAN, "lt_LT", LANG_LITHUANIAN, SUBLANG_LITHUANIAN , wxLayout_LeftToRight, "Lithuanian") 3673 LNG(wxLANGUAGE_MACEDONIAN, "mk_MK", LANG_MACEDONIAN, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Macedonian") 3674 LNG(wxLANGUAGE_MALAGASY, "mg" , 0 , 0 , wxLayout_LeftToRight, "Malagasy") 3675 LNG(wxLANGUAGE_MALAY, "ms_MY", LANG_MALAY , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Malay") 3676 LNG(wxLANGUAGE_MALAYALAM, "ml" , LANG_MALAYALAM , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Malayalam") 3677 LNG(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM, "ms_BN", LANG_MALAY , SUBLANG_MALAY_BRUNEI_DARUSSALAM , wxLayout_LeftToRight, "Malay (Brunei Darussalam)") 3678 LNG(wxLANGUAGE_MALAY_MALAYSIA, "ms_MY", LANG_MALAY , SUBLANG_MALAY_MALAYSIA , wxLayout_LeftToRight, "Malay (Malaysia)") 3679 LNG(wxLANGUAGE_MALTESE, "mt_MT", 0 , 0 , wxLayout_LeftToRight, "Maltese") 3680 LNG(wxLANGUAGE_MANIPURI, "" , LANG_MANIPURI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Manipuri") 3681 LNG(wxLANGUAGE_MAORI, "mi" , 0 , 0 , wxLayout_LeftToRight, "Maori") 3682 LNG(wxLANGUAGE_MARATHI, "mr_IN", LANG_MARATHI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Marathi") 3683 LNG(wxLANGUAGE_MOLDAVIAN, "mo" , 0 , 0 , wxLayout_LeftToRight, "Moldavian") 3684 LNG(wxLANGUAGE_MONGOLIAN, "mn" , 0 , 0 , wxLayout_LeftToRight, "Mongolian") 3685 LNG(wxLANGUAGE_NAURU, "na" , 0 , 0 , wxLayout_LeftToRight, "Nauru") 3686 LNG(wxLANGUAGE_NEPALI, "ne_NP", LANG_NEPALI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Nepali") 3687 LNG(wxLANGUAGE_NEPALI_INDIA, "ne_IN", LANG_NEPALI , SUBLANG_NEPALI_INDIA , wxLayout_LeftToRight, "Nepali (India)") 3688 LNG(wxLANGUAGE_NORWEGIAN_BOKMAL, "nb_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_BOKMAL , wxLayout_LeftToRight, "Norwegian (Bokmal)") 3689 LNG(wxLANGUAGE_NORWEGIAN_NYNORSK, "nn_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_NYNORSK , wxLayout_LeftToRight, "Norwegian (Nynorsk)") 3690 LNG(wxLANGUAGE_OCCITAN, "oc" , 0 , 0 , wxLayout_LeftToRight, "Occitan") 3691 LNG(wxLANGUAGE_ORIYA, "or" , LANG_ORIYA , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Oriya") 3692 LNG(wxLANGUAGE_OROMO, "om" , 0 , 0 , wxLayout_LeftToRight, "(Afan) Oromo") 3693 LNG(wxLANGUAGE_PASHTO, "ps" , 0 , 0 , wxLayout_LeftToRight, "Pashto, Pushto") 3694 LNG(wxLANGUAGE_POLISH, "pl_PL", LANG_POLISH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Polish") 3695 LNG(wxLANGUAGE_PORTUGUESE, "pt_PT", LANG_PORTUGUESE, SUBLANG_PORTUGUESE , wxLayout_LeftToRight, "Portuguese") 3696 LNG(wxLANGUAGE_PORTUGUESE_BRAZILIAN, "pt_BR", LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN , wxLayout_LeftToRight, "Portuguese (Brazilian)") 3697 LNG(wxLANGUAGE_PUNJABI, "pa" , LANG_PUNJABI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Punjabi") 3698 LNG(wxLANGUAGE_QUECHUA, "qu" , 0 , 0 , wxLayout_LeftToRight, "Quechua") 3699 LNG(wxLANGUAGE_RHAETO_ROMANCE, "rm" , 0 , 0 , wxLayout_LeftToRight, "Rhaeto-Romance") 3700 LNG(wxLANGUAGE_ROMANIAN, "ro_RO", LANG_ROMANIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Romanian") 3701 LNG(wxLANGUAGE_RUSSIAN, "ru_RU", LANG_RUSSIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Russian") 3702 LNG(wxLANGUAGE_RUSSIAN_UKRAINE, "ru_UA", 0 , 0 , wxLayout_LeftToRight, "Russian (Ukraine)") 3703 LNG(wxLANGUAGE_SAMI, "se_NO", LANG_SAMI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Northern Sami") 3704 LNG(wxLANGUAGE_SAMOAN, "sm" , 0 , 0 , wxLayout_LeftToRight, "Samoan") 3705 LNG(wxLANGUAGE_SANGHO, "sg" , 0 , 0 , wxLayout_LeftToRight, "Sangho") 3706 LNG(wxLANGUAGE_SANSKRIT, "sa" , LANG_SANSKRIT , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Sanskrit") 3707 LNG(wxLANGUAGE_SCOTS_GAELIC, "gd" , 0 , 0 , wxLayout_LeftToRight, "Scots Gaelic") 3708 LNG(wxLANGUAGE_SERBIAN, "sr_RS", LANG_SERBIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Serbian") 3709 LNG(wxLANGUAGE_SERBIAN_CYRILLIC, "sr_RS", LANG_SERBIAN , SUBLANG_SERBIAN_CYRILLIC , wxLayout_LeftToRight, "Serbian (Cyrillic)") 3710 LNG(wxLANGUAGE_SERBIAN_LATIN, "sr_RS@latin", LANG_SERBIAN , SUBLANG_SERBIAN_LATIN , wxLayout_LeftToRight, "Serbian (Latin)") 3711 LNG(wxLANGUAGE_SERBIAN_CYRILLIC, "sr_YU", LANG_SERBIAN , SUBLANG_SERBIAN_CYRILLIC , wxLayout_LeftToRight, "Serbian (Cyrillic)") 3712 LNG(wxLANGUAGE_SERBIAN_LATIN, "sr_YU@latin", LANG_SERBIAN , SUBLANG_SERBIAN_LATIN , wxLayout_LeftToRight, "Serbian (Latin)") 3713 LNG(wxLANGUAGE_SERBO_CROATIAN, "sh" , 0 , 0 , wxLayout_LeftToRight, "Serbo-Croatian") 3714 LNG(wxLANGUAGE_SESOTHO, "st" , 0 , 0 , wxLayout_LeftToRight, "Sesotho") 3715 LNG(wxLANGUAGE_SETSWANA, "tn" , 0 , 0 , wxLayout_LeftToRight, "Setswana") 3716 LNG(wxLANGUAGE_SHONA, "sn" , 0 , 0 , wxLayout_LeftToRight, "Shona") 3717 LNG(wxLANGUAGE_SINDHI, "sd" , LANG_SINDHI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Sindhi") 3718 LNG(wxLANGUAGE_SINHALESE, "si" , 0 , 0 , wxLayout_LeftToRight, "Sinhalese") 3719 LNG(wxLANGUAGE_SISWATI, "ss" , 0 , 0 , wxLayout_LeftToRight, "Siswati") 3720 LNG(wxLANGUAGE_SLOVAK, "sk_SK", LANG_SLOVAK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Slovak") 3721 LNG(wxLANGUAGE_SLOVENIAN, "sl_SI", LANG_SLOVENIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Slovenian") 3722 LNG(wxLANGUAGE_SOMALI, "so" , 0 , 0 , wxLayout_LeftToRight, "Somali") 3723 LNG(wxLANGUAGE_SPANISH, "es_ES", LANG_SPANISH , SUBLANG_SPANISH , wxLayout_LeftToRight, "Spanish") 3724 LNG(wxLANGUAGE_SPANISH_ARGENTINA, "es_AR", LANG_SPANISH , SUBLANG_SPANISH_ARGENTINA , wxLayout_LeftToRight, "Spanish (Argentina)") 3725 LNG(wxLANGUAGE_SPANISH_BOLIVIA, "es_BO", LANG_SPANISH , SUBLANG_SPANISH_BOLIVIA , wxLayout_LeftToRight, "Spanish (Bolivia)") 3726 LNG(wxLANGUAGE_SPANISH_CHILE, "es_CL", LANG_SPANISH , SUBLANG_SPANISH_CHILE , wxLayout_LeftToRight, "Spanish (Chile)") 3727 LNG(wxLANGUAGE_SPANISH_COLOMBIA, "es_CO", LANG_SPANISH , SUBLANG_SPANISH_COLOMBIA , wxLayout_LeftToRight, "Spanish (Colombia)") 3728 LNG(wxLANGUAGE_SPANISH_COSTA_RICA, "es_CR", LANG_SPANISH , SUBLANG_SPANISH_COSTA_RICA , wxLayout_LeftToRight, "Spanish (Costa Rica)") 3729 LNG(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC, "es_DO", LANG_SPANISH , SUBLANG_SPANISH_DOMINICAN_REPUBLIC, wxLayout_LeftToRight, "Spanish (Dominican republic)") 3730 LNG(wxLANGUAGE_SPANISH_ECUADOR, "es_EC", LANG_SPANISH , SUBLANG_SPANISH_ECUADOR , wxLayout_LeftToRight, "Spanish (Ecuador)") 3731 LNG(wxLANGUAGE_SPANISH_EL_SALVADOR, "es_SV", LANG_SPANISH , SUBLANG_SPANISH_EL_SALVADOR , wxLayout_LeftToRight, "Spanish (El Salvador)") 3732 LNG(wxLANGUAGE_SPANISH_GUATEMALA, "es_GT", LANG_SPANISH , SUBLANG_SPANISH_GUATEMALA , wxLayout_LeftToRight, "Spanish (Guatemala)") 3733 LNG(wxLANGUAGE_SPANISH_HONDURAS, "es_HN", LANG_SPANISH , SUBLANG_SPANISH_HONDURAS , wxLayout_LeftToRight, "Spanish (Honduras)") 3734 LNG(wxLANGUAGE_SPANISH_MEXICAN, "es_MX", LANG_SPANISH , SUBLANG_SPANISH_MEXICAN , wxLayout_LeftToRight, "Spanish (Mexican)") 3735 LNG(wxLANGUAGE_SPANISH_MODERN, "es_ES", LANG_SPANISH , SUBLANG_SPANISH_MODERN , wxLayout_LeftToRight, "Spanish (Modern)") 3736 LNG(wxLANGUAGE_SPANISH_NICARAGUA, "es_NI", LANG_SPANISH , SUBLANG_SPANISH_NICARAGUA , wxLayout_LeftToRight, "Spanish (Nicaragua)") 3737 LNG(wxLANGUAGE_SPANISH_PANAMA, "es_PA", LANG_SPANISH , SUBLANG_SPANISH_PANAMA , wxLayout_LeftToRight, "Spanish (Panama)") 3738 LNG(wxLANGUAGE_SPANISH_PARAGUAY, "es_PY", LANG_SPANISH , SUBLANG_SPANISH_PARAGUAY , wxLayout_LeftToRight, "Spanish (Paraguay)") 3739 LNG(wxLANGUAGE_SPANISH_PERU, "es_PE", LANG_SPANISH , SUBLANG_SPANISH_PERU , wxLayout_LeftToRight, "Spanish (Peru)") 3740 LNG(wxLANGUAGE_SPANISH_PUERTO_RICO, "es_PR", LANG_SPANISH , SUBLANG_SPANISH_PUERTO_RICO , wxLayout_LeftToRight, "Spanish (Puerto Rico)") 3741 LNG(wxLANGUAGE_SPANISH_URUGUAY, "es_UY", LANG_SPANISH , SUBLANG_SPANISH_URUGUAY , wxLayout_LeftToRight, "Spanish (Uruguay)") 3742 LNG(wxLANGUAGE_SPANISH_US, "es_US", 0 , 0 , wxLayout_LeftToRight, "Spanish (U.S.)") 3743 LNG(wxLANGUAGE_SPANISH_VENEZUELA, "es_VE", LANG_SPANISH , SUBLANG_SPANISH_VENEZUELA , wxLayout_LeftToRight, "Spanish (Venezuela)") 3744 LNG(wxLANGUAGE_SUNDANESE, "su" , 0 , 0 , wxLayout_LeftToRight, "Sundanese") 3745 LNG(wxLANGUAGE_SWAHILI, "sw_KE", LANG_SWAHILI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Swahili") 3746 LNG(wxLANGUAGE_SWEDISH, "sv_SE", LANG_SWEDISH , SUBLANG_SWEDISH , wxLayout_LeftToRight, "Swedish") 3747 LNG(wxLANGUAGE_SWEDISH_FINLAND, "sv_FI", LANG_SWEDISH , SUBLANG_SWEDISH_FINLAND , wxLayout_LeftToRight, "Swedish (Finland)") 3748 LNG(wxLANGUAGE_TAGALOG, "tl_PH", 0 , 0 , wxLayout_LeftToRight, "Tagalog") 3749 LNG(wxLANGUAGE_TAJIK, "tg" , 0 , 0 , wxLayout_LeftToRight, "Tajik") 3750 LNG(wxLANGUAGE_TAMIL, "ta" , LANG_TAMIL , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Tamil") 3751 LNG(wxLANGUAGE_TATAR, "tt" , LANG_TATAR , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Tatar") 3752 LNG(wxLANGUAGE_TELUGU, "te" , LANG_TELUGU , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Telugu") 3753 LNG(wxLANGUAGE_THAI, "th_TH", LANG_THAI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Thai") 3754 LNG(wxLANGUAGE_TIBETAN, "bo" , 0 , 0 , wxLayout_LeftToRight, "Tibetan") 3755 LNG(wxLANGUAGE_TIGRINYA, "ti" , 0 , 0 , wxLayout_LeftToRight, "Tigrinya") 3756 LNG(wxLANGUAGE_TONGA, "to" , 0 , 0 , wxLayout_LeftToRight, "Tonga") 3757 LNG(wxLANGUAGE_TSONGA, "ts" , 0 , 0 , wxLayout_LeftToRight, "Tsonga") 3758 LNG(wxLANGUAGE_TURKISH, "tr_TR", LANG_TURKISH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Turkish") 3759 LNG(wxLANGUAGE_TURKMEN, "tk" , 0 , 0 , wxLayout_LeftToRight, "Turkmen") 3760 LNG(wxLANGUAGE_TWI, "tw" , 0 , 0 , wxLayout_LeftToRight, "Twi") 3761 LNG(wxLANGUAGE_UIGHUR, "ug" , 0 , 0 , wxLayout_LeftToRight, "Uighur") 3762 LNG(wxLANGUAGE_UKRAINIAN, "uk_UA", LANG_UKRAINIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Ukrainian") 3763 LNG(wxLANGUAGE_URDU, "ur" , LANG_URDU , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Urdu") 3764 LNG(wxLANGUAGE_URDU_INDIA, "ur_IN", LANG_URDU , SUBLANG_URDU_INDIA , wxLayout_LeftToRight, "Urdu (India)") 3765 LNG(wxLANGUAGE_URDU_PAKISTAN, "ur_PK", LANG_URDU , SUBLANG_URDU_PAKISTAN , wxLayout_LeftToRight, "Urdu (Pakistan)") 3766 LNG(wxLANGUAGE_UZBEK, "uz" , LANG_UZBEK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Uzbek") 3767 LNG(wxLANGUAGE_UZBEK_CYRILLIC, "uz" , LANG_UZBEK , SUBLANG_UZBEK_CYRILLIC , wxLayout_LeftToRight, "Uzbek (Cyrillic)") 3768 LNG(wxLANGUAGE_UZBEK_LATIN, "uz" , LANG_UZBEK , SUBLANG_UZBEK_LATIN , wxLayout_LeftToRight, "Uzbek (Latin)") 3769 LNG(wxLANGUAGE_VALENCIAN, "ca_ES@valencia", LANG_VALENCIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Valencian") 3770 LNG(wxLANGUAGE_VIETNAMESE, "vi_VN", LANG_VIETNAMESE, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Vietnamese") 3771 LNG(wxLANGUAGE_VOLAPUK, "vo" , 0 , 0 , wxLayout_LeftToRight, "Volapuk") 3772 LNG(wxLANGUAGE_WELSH, "cy" , 0 , 0 , wxLayout_LeftToRight, "Welsh") 3773 LNG(wxLANGUAGE_WOLOF, "wo" , 0 , 0 , wxLayout_LeftToRight, "Wolof") 3774 LNG(wxLANGUAGE_XHOSA, "xh" , 0 , 0 , wxLayout_LeftToRight, "Xhosa") 3775 LNG(wxLANGUAGE_YIDDISH, "yi" , 0 , 0 , wxLayout_LeftToRight, "Yiddish") 3776 LNG(wxLANGUAGE_YORUBA, "yo" , 0 , 0 , wxLayout_LeftToRight, "Yoruba") 3777 LNG(wxLANGUAGE_ZHUANG, "za" , 0 , 0 , wxLayout_LeftToRight, "Zhuang") 3778 LNG(wxLANGUAGE_ZULU, "zu" , 0 , 0 , wxLayout_LeftToRight, "Zulu") 3779} 3780#undef LNG 3781 3782// --- --- --- generated code ends here --- --- --- 3783 3784#endif // wxUSE_INTL 3785