X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a64be16ef8aac40c68ed53cbe0f79979f8f6a898..931d6a47c32a5b4c283243cb553ce71ee2b535d5:/src/common/intl.cpp diff --git a/src/common/intl.cpp b/src/common/intl.cpp index dec5ce8daa..f8b011a917 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -5,7 +5,6 @@ // Modified by: Michael N. Filippov // (2003/09/30 - PluralForms support) // Created: 29/01/98 -// RCS-ID: $Id$ // Copyright: (c) 1998 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -18,12 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __EMX__ -// The following define is needed by Innotek's libc to -// make the definition of struct localeconv available. -#define __INTERNAL_DEFS -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -31,6 +24,12 @@ #pragma hdrstop #endif +#ifdef __EMX__ +// The following define is needed by Innotek's libc to +// make the definition of struct localeconv available. +#define __INTERNAL_DEFS +#endif + #if wxUSE_INTL #ifndef WX_PRECOMP @@ -57,2866 +56,1717 @@ #ifdef __WIN32__ #include "wx/msw/private.h" -#elif defined(__UNIX_LIKE__) - #include "wx/fontmap.h" // for CharsetToEncoding() #endif #include "wx/file.h" #include "wx/filename.h" #include "wx/tokenzr.h" #include "wx/fontmap.h" -#include "wx/encconv.h" -#include "wx/ptr_scpd.h" +#include "wx/scopedptr.h" #include "wx/apptrait.h" #include "wx/stdpaths.h" #include "wx/hashset.h" -#if defined(__WXMAC__) - #include "wx/mac/private.h" // includes mac headers +#if defined(__WXOSX__) + #include "wx/osx/core/cfref.h" + #include + #include + #include "wx/osx/core/cfstring.h" #endif -// ---------------------------------------------------------------------------- -// simple types -// ---------------------------------------------------------------------------- - -// this should *not* be wxChar, this type must have exactly 8 bits! -typedef wxUint8 size_t8; -typedef wxUint32 size_t32; - // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- -// magic number identifying the .mo format file -const size_t32 MSGCATALOG_MAGIC = 0x950412de; -const size_t32 MSGCATALOG_MAGIC_SW = 0xde120495; - -// the constants describing the format of lang_LANG locale string -static const size_t LEN_LANG = 2; -static const size_t LEN_SUBLANG = 2; -static const size_t LEN_FULL = LEN_LANG + 1 + LEN_SUBLANG; // 1 for '_' +#define TRACE_I18N wxS("i18n") -#define TRACE_I18N _T("i18n") +// ============================================================================ +// implementation +// ============================================================================ // ---------------------------------------------------------------------------- // global functions // ---------------------------------------------------------------------------- -#ifdef __WXDEBUG__ +static wxLocale *wxSetLocale(wxLocale *pLocale); -// small class to suppress the translation erros until exit from current scope -class NoTransErr +namespace { -public: - NoTransErr() { ms_suppressCount++; } - ~NoTransErr() { ms_suppressCount--; } - - static bool Suppress() { return ms_suppressCount > 0; } - -private: - static size_t ms_suppressCount; -}; - -size_t NoTransErr::ms_suppressCount = 0; -#else // !Debug - -class NoTransErr +// get just the language part ("en" in "en_GB") +inline wxString ExtractLang(const wxString& langFull) { -public: - NoTransErr() { } - ~NoTransErr() { } -}; - -#endif // Debug/!Debug - -static wxLocale *wxSetLocale(wxLocale *pLocale); + return langFull.BeforeFirst('_'); +} // helper functions of GetSystemLanguage() #ifdef __UNIX__ -// get just the language part -static inline wxString ExtractLang(const wxString& langFull) -{ - return langFull.Left(LEN_LANG); -} - // get everything else (including the leading '_') -static inline wxString ExtractNotLang(const wxString& langFull) +inline wxString ExtractNotLang(const wxString& langFull) { - return langFull.Mid(LEN_LANG); + size_t pos = langFull.find('_'); + if ( pos != wxString::npos ) + return langFull.substr(pos); + else + return wxString(); } #endif // __UNIX__ +} // anonymous namespace // ---------------------------------------------------------------------------- -// Plural forms parser +// wxLanguageInfo // ---------------------------------------------------------------------------- -/* - Simplified Grammar - -Expression: - LogicalOrExpression '?' Expression ':' Expression - LogicalOrExpression - -LogicalOrExpression: - LogicalAndExpression "||" LogicalOrExpression // to (a || b) || c - LogicalAndExpression - -LogicalAndExpression: - EqualityExpression "&&" LogicalAndExpression // to (a && b) && c - EqualityExpression - -EqualityExpression: - RelationalExpression "==" RelationalExperession - RelationalExpression "!=" RelationalExperession - RelationalExpression +#ifdef __WINDOWS__ -RelationalExpression: - MultiplicativeExpression '>' MultiplicativeExpression - MultiplicativeExpression '<' MultiplicativeExpression - MultiplicativeExpression ">=" MultiplicativeExpression - MultiplicativeExpression "<=" MultiplicativeExpression - MultiplicativeExpression - -MultiplicativeExpression: - PmExpression '%' PmExpression - PmExpression - -PmExpression: - N - Number - '(' Expression ')' -*/ - -class wxPluralFormsToken +// helper used by wxLanguageInfo::GetLocaleName() and elsewhere to determine +// whether the locale is Unicode-only (it is if this function returns empty +// string) +static wxString wxGetANSICodePageForLocale(LCID lcid) { -public: - enum Type - { - T_ERROR, T_EOF, T_NUMBER, T_N, T_PLURAL, T_NPLURALS, T_EQUAL, T_ASSIGN, - T_GREATER, T_GREATER_OR_EQUAL, T_LESS, T_LESS_OR_EQUAL, - T_REMINDER, T_NOT_EQUAL, - T_LOGICAL_AND, T_LOGICAL_OR, T_QUESTION, T_COLON, T_SEMICOLON, - T_LEFT_BRACKET, T_RIGHT_BRACKET - }; - Type type() const { return m_type; } - void setType(Type type) { m_type = type; } - // for T_NUMBER only - typedef int Number; - Number number() const { return m_number; } - void setNumber(Number num) { m_number = num; } -private: - Type m_type; - Number m_number; -}; + wxString cp; + wxChar buffer[16]; + if ( ::GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, + buffer, WXSIZEOF(buffer)) > 0 ) + { + if ( buffer[0] != wxT('0') || buffer[1] != wxT('\0') ) + cp = buffer; + //else: this locale doesn't use ANSI code page + } -class wxPluralFormsScanner -{ -public: - wxPluralFormsScanner(const char* s); - const wxPluralFormsToken& token() const { return m_token; } - bool nextToken(); // returns false if error -private: - const char* m_s; - wxPluralFormsToken m_token; -}; + return cp; +} -wxPluralFormsScanner::wxPluralFormsScanner(const char* s) : m_s(s) +wxUint32 wxLanguageInfo::GetLCID() const { - nextToken(); + return MAKELCID(MAKELANGID(WinLang, WinSublang), SORT_DEFAULT); } -bool wxPluralFormsScanner::nextToken() +wxString wxLanguageInfo::GetLocaleName() const { - wxPluralFormsToken::Type type = wxPluralFormsToken::T_ERROR; - while (isspace(*m_s)) - { - ++m_s; - } - if (*m_s == 0) - { - type = wxPluralFormsToken::T_EOF; - } - else if (isdigit(*m_s)) - { - wxPluralFormsToken::Number number = *m_s++ - '0'; - while (isdigit(*m_s)) - { - number = number * 10 + (*m_s++ - '0'); - } - m_token.setNumber(number); - type = wxPluralFormsToken::T_NUMBER; - } - else if (isalpha(*m_s)) - { - const char* begin = m_s++; - while (isalnum(*m_s)) - { - ++m_s; - } - size_t size = m_s - begin; - if (size == 1 && memcmp(begin, "n", size) == 0) - { - type = wxPluralFormsToken::T_N; - } - else if (size == 6 && memcmp(begin, "plural", size) == 0) - { - type = wxPluralFormsToken::T_PLURAL; - } - else if (size == 8 && memcmp(begin, "nplurals", size) == 0) - { - type = wxPluralFormsToken::T_NPLURALS; - } - } - else if (*m_s == '=') - { - ++m_s; - if (*m_s == '=') - { - ++m_s; - type = wxPluralFormsToken::T_EQUAL; - } - else - { - type = wxPluralFormsToken::T_ASSIGN; - } - } - else if (*m_s == '>') - { - ++m_s; - if (*m_s == '=') - { - ++m_s; - type = wxPluralFormsToken::T_GREATER_OR_EQUAL; - } - else - { - type = wxPluralFormsToken::T_GREATER; - } - } - else if (*m_s == '<') - { - ++m_s; - if (*m_s == '=') - { - ++m_s; - type = wxPluralFormsToken::T_LESS_OR_EQUAL; - } - else - { - type = wxPluralFormsToken::T_LESS; - } - } - else if (*m_s == '%') - { - ++m_s; - type = wxPluralFormsToken::T_REMINDER; - } - else if (*m_s == '!' && m_s[1] == '=') - { - m_s += 2; - type = wxPluralFormsToken::T_NOT_EQUAL; - } - else if (*m_s == '&' && m_s[1] == '&') - { - m_s += 2; - type = wxPluralFormsToken::T_LOGICAL_AND; - } - else if (*m_s == '|' && m_s[1] == '|') - { - m_s += 2; - type = wxPluralFormsToken::T_LOGICAL_OR; - } - else if (*m_s == '?') - { - ++m_s; - type = wxPluralFormsToken::T_QUESTION; - } - else if (*m_s == ':') + wxString locale; + + const LCID lcid = GetLCID(); + + wxChar buffer[256]; + buffer[0] = wxT('\0'); + if ( !::GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, buffer, WXSIZEOF(buffer)) ) { - ++m_s; - type = wxPluralFormsToken::T_COLON; - } else if (*m_s == ';') { - ++m_s; - type = wxPluralFormsToken::T_SEMICOLON; + wxLogLastError(wxT("GetLocaleInfo(LOCALE_SENGLANGUAGE)")); + return locale; } - else if (*m_s == '(') + + locale << buffer; + if ( ::GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY, + buffer, WXSIZEOF(buffer)) > 0 ) { - ++m_s; - type = wxPluralFormsToken::T_LEFT_BRACKET; + locale << wxT('_') << buffer; } - else if (*m_s == ')') + + const wxString cp = wxGetANSICodePageForLocale(lcid); + if ( !cp.empty() ) { - ++m_s; - type = wxPluralFormsToken::T_RIGHT_BRACKET; + locale << wxT('.') << cp; } - m_token.setType(type); - return type != wxPluralFormsToken::T_ERROR; + + return locale; } -class wxPluralFormsNode; +#endif // __WINDOWS__ -// NB: Can't use wxDEFINE_SCOPED_PTR_TYPE because wxPluralFormsNode is not -// fully defined yet: -class wxPluralFormsNodePtr -{ -public: - wxPluralFormsNodePtr(wxPluralFormsNode *p = NULL) : m_p(p) {} - ~wxPluralFormsNodePtr(); - wxPluralFormsNode& operator*() const { return *m_p; } - wxPluralFormsNode* operator->() const { return m_p; } - wxPluralFormsNode* get() const { return m_p; } - wxPluralFormsNode* release(); - void reset(wxPluralFormsNode *p); - -private: - wxPluralFormsNode *m_p; -}; +// ---------------------------------------------------------------------------- +// wxLocale +// ---------------------------------------------------------------------------- -class wxPluralFormsNode -{ -public: - wxPluralFormsNode(const wxPluralFormsToken& token) : m_token(token) {} - const wxPluralFormsToken& token() const { return m_token; } - const wxPluralFormsNode* node(size_t i) const - { return m_nodes[i].get(); } - void setNode(size_t i, wxPluralFormsNode* n); - wxPluralFormsNode* releaseNode(size_t i); - wxPluralFormsToken::Number evaluate(wxPluralFormsToken::Number n) const; - -private: - wxPluralFormsToken m_token; - wxPluralFormsNodePtr m_nodes[3]; -}; +#include "wx/arrimpl.cpp" +WX_DECLARE_EXPORTED_OBJARRAY(wxLanguageInfo, wxLanguageInfoArray); +WX_DEFINE_OBJARRAY(wxLanguageInfoArray) -wxPluralFormsNodePtr::~wxPluralFormsNodePtr() -{ - delete m_p; -} -wxPluralFormsNode* wxPluralFormsNodePtr::release() -{ - wxPluralFormsNode *p = m_p; - m_p = NULL; - return p; -} -void wxPluralFormsNodePtr::reset(wxPluralFormsNode *p) +wxLanguageInfoArray *wxLocale::ms_languagesDB = NULL; + +/*static*/ void wxLocale::CreateLanguagesDB() { - if (p != m_p) + if (ms_languagesDB == NULL) { - delete m_p; - m_p = p; + ms_languagesDB = new wxLanguageInfoArray; + InitLanguagesDB(); } } - -void wxPluralFormsNode::setNode(size_t i, wxPluralFormsNode* n) +/*static*/ void wxLocale::DestroyLanguagesDB() { - m_nodes[i].reset(n); + wxDELETE(ms_languagesDB); } -wxPluralFormsNode* wxPluralFormsNode::releaseNode(size_t i) -{ - return m_nodes[i].release(); -} -wxPluralFormsToken::Number -wxPluralFormsNode::evaluate(wxPluralFormsToken::Number n) const +void wxLocale::DoCommonInit() { - switch (token().type()) - { - // leaf - case wxPluralFormsToken::T_NUMBER: - return token().number(); - case wxPluralFormsToken::T_N: - return n; - // 2 args - case wxPluralFormsToken::T_EQUAL: - return node(0)->evaluate(n) == node(1)->evaluate(n); - case wxPluralFormsToken::T_NOT_EQUAL: - return node(0)->evaluate(n) != node(1)->evaluate(n); - case wxPluralFormsToken::T_GREATER: - return node(0)->evaluate(n) > node(1)->evaluate(n); - case wxPluralFormsToken::T_GREATER_OR_EQUAL: - return node(0)->evaluate(n) >= node(1)->evaluate(n); - case wxPluralFormsToken::T_LESS: - return node(0)->evaluate(n) < node(1)->evaluate(n); - case wxPluralFormsToken::T_LESS_OR_EQUAL: - return node(0)->evaluate(n) <= node(1)->evaluate(n); - case wxPluralFormsToken::T_REMINDER: - { - wxPluralFormsToken::Number number = node(1)->evaluate(n); - if (number != 0) - { - return node(0)->evaluate(n) % number; - } - else - { - return 0; - } - } - case wxPluralFormsToken::T_LOGICAL_AND: - return node(0)->evaluate(n) && node(1)->evaluate(n); - case wxPluralFormsToken::T_LOGICAL_OR: - return node(0)->evaluate(n) || node(1)->evaluate(n); - // 3 args - case wxPluralFormsToken::T_QUESTION: - return node(0)->evaluate(n) - ? node(1)->evaluate(n) - : node(2)->evaluate(n); - default: - return 0; - } -} + // Store the current locale in order to be able to restore it in the dtor. + m_pszOldLocale = wxSetlocale(LC_ALL, NULL); + if ( m_pszOldLocale ) + m_pszOldLocale = wxStrdup(m_pszOldLocale); -class wxPluralFormsCalculator -{ -public: - wxPluralFormsCalculator() : m_nplurals(0), m_plural(0) {} + m_pOldLocale = wxSetLocale(this); - // input: number, returns msgstr index - int evaluate(int n) const; + // Set translations object, but only if the user didn't do so yet. + // This is to preserve compatibility with wx-2.8 where wxLocale was + // the only API for translations. wxLocale works as a stack, with + // latest-created one being the active one: + // wxLocale loc_fr(wxLANGUAGE_FRENCH); + // // _() returns French + // { + // wxLocale loc_cs(wxLANGUAGE_CZECH); + // // _() returns Czech + // } + // // _() returns French again + wxTranslations *oldTrans = wxTranslations::Get(); + if ( !oldTrans || + (m_pOldLocale && oldTrans == &m_pOldLocale->m_translations) ) + { + wxTranslations::SetNonOwned(&m_translations); + } - // input: text after "Plural-Forms:" (e.g. "nplurals=2; plural=(n != 1);"), - // if s == 0, creates default handler - // returns 0 if error - static wxPluralFormsCalculator* make(const char* s = 0); + m_language = wxLANGUAGE_UNKNOWN; + m_initialized = false; +} - ~wxPluralFormsCalculator() {} +// NB: this function has (desired) side effect of changing current locale +bool wxLocale::Init(const wxString& name, + const wxString& shortName, + const wxString& locale, + bool bLoadDefault +#if WXWIN_COMPATIBILITY_2_8 + ,bool WXUNUSED_UNLESS_DEBUG(bConvertEncoding) +#endif + ) +{ +#if WXWIN_COMPATIBILITY_2_8 + wxASSERT_MSG( bConvertEncoding, + wxS("wxLocale::Init with bConvertEncoding=false is no longer supported, add charset to your catalogs") ); +#endif - void init(wxPluralFormsToken::Number nplurals, wxPluralFormsNode* plural); + bool ret = DoInit(name, shortName, locale); -private: - wxPluralFormsToken::Number m_nplurals; - wxPluralFormsNodePtr m_plural; -}; + // NB: don't use 'lang' here, 'language' may be wxLANGUAGE_DEFAULT + wxTranslations *t = wxTranslations::Get(); + if ( t ) + { + t->SetLanguage(shortName); -wxDEFINE_SCOPED_PTR_TYPE(wxPluralFormsCalculator) + if ( bLoadDefault ) + t->AddStdCatalog(); + } -void wxPluralFormsCalculator::init(wxPluralFormsToken::Number nplurals, - wxPluralFormsNode* plural) -{ - m_nplurals = nplurals; - m_plural.reset(plural); + return ret; } -int wxPluralFormsCalculator::evaluate(int n) const +bool wxLocale::DoInit(const wxString& name, + const wxString& shortName, + const wxString& locale) { - if (m_plural.get() == 0) + wxASSERT_MSG( !m_initialized, + wxS("you can't call wxLocale::Init more than once") ); + + m_initialized = true; + m_strLocale = name; + m_strShort = shortName; + m_language = wxLANGUAGE_UNKNOWN; + + // change current locale (default: same as long name) + wxString szLocale(locale); + if ( szLocale.empty() ) { - return 0; + // the argument to setlocale() + szLocale = shortName; + + wxCHECK_MSG( !szLocale.empty(), false, + wxS("no locale to set in wxLocale::Init()") ); } - wxPluralFormsToken::Number number = m_plural->evaluate(n); - if (number < 0 || number > m_nplurals) + + if ( !wxSetlocale(LC_ALL, szLocale) ) { - return 0; + wxLogError(_("locale '%s' cannot be set."), szLocale); } - return number; -} + // the short name will be used to look for catalog files as well, + // so we need something here + if ( m_strShort.empty() ) { + // FIXME I don't know how these 2 letter abbreviations are formed, + // this wild guess is surely wrong + if ( !szLocale.empty() ) + { + m_strShort += (wxChar)wxTolower(szLocale[0]); + if ( szLocale.length() > 1 ) + m_strShort += (wxChar)wxTolower(szLocale[1]); + } + } -class wxPluralFormsParser -{ -public: - wxPluralFormsParser(wxPluralFormsScanner& scanner) : m_scanner(scanner) {} - bool parse(wxPluralFormsCalculator& rCalculator); - -private: - wxPluralFormsNode* parsePlural(); - // stops at T_SEMICOLON, returns 0 if error - wxPluralFormsScanner& m_scanner; - const wxPluralFormsToken& token() const; - bool nextToken(); - - wxPluralFormsNode* expression(); - wxPluralFormsNode* logicalOrExpression(); - wxPluralFormsNode* logicalAndExpression(); - wxPluralFormsNode* equalityExpression(); - wxPluralFormsNode* multiplicativeExpression(); - wxPluralFormsNode* relationalExpression(); - wxPluralFormsNode* pmExpression(); -}; - -bool wxPluralFormsParser::parse(wxPluralFormsCalculator& rCalculator) -{ - if (token().type() != wxPluralFormsToken::T_NPLURALS) - return false; - if (!nextToken()) - return false; - if (token().type() != wxPluralFormsToken::T_ASSIGN) - return false; - if (!nextToken()) - return false; - if (token().type() != wxPluralFormsToken::T_NUMBER) - return false; - wxPluralFormsToken::Number nplurals = token().number(); - if (!nextToken()) - return false; - if (token().type() != wxPluralFormsToken::T_SEMICOLON) - return false; - if (!nextToken()) - return false; - if (token().type() != wxPluralFormsToken::T_PLURAL) - return false; - if (!nextToken()) - return false; - if (token().type() != wxPluralFormsToken::T_ASSIGN) - return false; - if (!nextToken()) - return false; - wxPluralFormsNode* plural = parsePlural(); - if (plural == 0) - return false; - if (token().type() != wxPluralFormsToken::T_SEMICOLON) - return false; - if (!nextToken()) - return false; - if (token().type() != wxPluralFormsToken::T_EOF) - return false; - rCalculator.init(nplurals, plural); return true; } -wxPluralFormsNode* wxPluralFormsParser::parsePlural() -{ - wxPluralFormsNode* p = expression(); - if (p == NULL) - { - return NULL; - } - wxPluralFormsNodePtr n(p); - if (token().type() != wxPluralFormsToken::T_SEMICOLON) - { - return NULL; - } - return n.release(); -} -const wxPluralFormsToken& wxPluralFormsParser::token() const +#if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__) +static const char *wxSetlocaleTryUTF8(int c, const wxString& lc) { - return m_scanner.token(); -} + const char *l = NULL; -bool wxPluralFormsParser::nextToken() -{ - if (!m_scanner.nextToken()) - return false; - return true; -} + // NB: We prefer to set UTF-8 locale if it's possible and only fall back to + // non-UTF-8 locale if it fails -wxPluralFormsNode* wxPluralFormsParser::expression() -{ - wxPluralFormsNode* p = logicalOrExpression(); - if (p == NULL) - return NULL; - wxPluralFormsNodePtr n(p); - if (token().type() == wxPluralFormsToken::T_QUESTION) + if ( !lc.empty() ) { - wxPluralFormsNodePtr qn(new wxPluralFormsNode(token())); - if (!nextToken()) - { - return 0; - } - p = expression(); - if (p == 0) - { - return 0; - } - qn->setNode(1, p); - if (token().type() != wxPluralFormsToken::T_COLON) + wxString buf(lc); + wxString buf2; + buf2 = buf + wxS(".UTF-8"); + l = wxSetlocale(c, buf2); + if ( !l ) { - return 0; + buf2 = buf + wxS(".utf-8"); + l = wxSetlocale(c, buf2); } - if (!nextToken()) + if ( !l ) { - return 0; + buf2 = buf + wxS(".UTF8"); + l = wxSetlocale(c, buf2); } - p = expression(); - if (p == 0) + if ( !l ) { - return 0; + buf2 = buf + wxS(".utf8"); + l = wxSetlocale(c, buf2); } - qn->setNode(2, p); - qn->setNode(0, n.release()); - return qn.release(); } - return n.release(); -} - -wxPluralFormsNode*wxPluralFormsParser::logicalOrExpression() -{ - wxPluralFormsNode* p = logicalAndExpression(); - if (p == NULL) - return NULL; - wxPluralFormsNodePtr ln(p); - if (token().type() == wxPluralFormsToken::T_LOGICAL_OR) - { - wxPluralFormsNodePtr un(new wxPluralFormsNode(token())); - if (!nextToken()) - { - return 0; - } - p = logicalOrExpression(); - if (p == 0) - { - return 0; - } - wxPluralFormsNodePtr rn(p); // right - if (rn->token().type() == wxPluralFormsToken::T_LOGICAL_OR) - { - // see logicalAndExpression comment - un->setNode(0, ln.release()); - un->setNode(1, rn->releaseNode(0)); - rn->setNode(0, un.release()); - return rn.release(); - } + // if we can't set UTF-8 locale, try non-UTF-8 one: + if ( !l ) + l = wxSetlocale(c, lc); - un->setNode(0, ln.release()); - un->setNode(1, rn.release()); - return un.release(); - } - return ln.release(); + return l; } +#else +#define wxSetlocaleTryUTF8(c, lc) wxSetlocale(c, lc) +#endif -wxPluralFormsNode* wxPluralFormsParser::logicalAndExpression() +bool wxLocale::Init(int language, int flags) { - wxPluralFormsNode* p = equalityExpression(); - if (p == NULL) - return NULL; - wxPluralFormsNodePtr ln(p); // left - if (token().type() == wxPluralFormsToken::T_LOGICAL_AND) - { - wxPluralFormsNodePtr un(new wxPluralFormsNode(token())); // up - if (!nextToken()) - { - return NULL; - } - p = logicalAndExpression(); - if (p == 0) - { - return NULL; - } - wxPluralFormsNodePtr rn(p); // right - if (rn->token().type() == wxPluralFormsToken::T_LOGICAL_AND) - { -// transform 1 && (2 && 3) -> (1 && 2) && 3 -// u r -// l r -> u 3 -// 2 3 l 2 - un->setNode(0, ln.release()); - un->setNode(1, rn->releaseNode(0)); - rn->setNode(0, un.release()); - return rn.release(); - } +#if WXWIN_COMPATIBILITY_2_8 + wxASSERT_MSG( !(flags & wxLOCALE_CONV_ENCODING), + wxS("wxLOCALE_CONV_ENCODING is no longer supported, add charset to your catalogs") ); +#endif - un->setNode(0, ln.release()); - un->setNode(1, rn.release()); - return un.release(); - } - return ln.release(); -} + bool ret = true; -wxPluralFormsNode* wxPluralFormsParser::equalityExpression() -{ - wxPluralFormsNode* p = relationalExpression(); - if (p == NULL) - return NULL; - wxPluralFormsNodePtr n(p); - if (token().type() == wxPluralFormsToken::T_EQUAL - || token().type() == wxPluralFormsToken::T_NOT_EQUAL) + int lang = language; + if (lang == wxLANGUAGE_DEFAULT) { - wxPluralFormsNodePtr qn(new wxPluralFormsNode(token())); - if (!nextToken()) - { - return NULL; - } - p = relationalExpression(); - if (p == NULL) - { - return NULL; - } - qn->setNode(1, p); - qn->setNode(0, n.release()); - return qn.release(); + // auto detect the language + lang = GetSystemLanguage(); } - return n.release(); -} -wxPluralFormsNode* wxPluralFormsParser::relationalExpression() -{ - wxPluralFormsNode* p = multiplicativeExpression(); - if (p == NULL) - return NULL; - wxPluralFormsNodePtr n(p); - if (token().type() == wxPluralFormsToken::T_GREATER - || token().type() == wxPluralFormsToken::T_LESS - || token().type() == wxPluralFormsToken::T_GREATER_OR_EQUAL - || token().type() == wxPluralFormsToken::T_LESS_OR_EQUAL) + // We failed to detect system language, so we will use English: + if (lang == wxLANGUAGE_UNKNOWN) { - wxPluralFormsNodePtr qn(new wxPluralFormsNode(token())); - if (!nextToken()) - { - return NULL; - } - p = multiplicativeExpression(); - if (p == NULL) - { - return NULL; - } - qn->setNode(1, p); - qn->setNode(0, n.release()); - return qn.release(); + return false; } - return n.release(); -} -wxPluralFormsNode* wxPluralFormsParser::multiplicativeExpression() -{ - wxPluralFormsNode* p = pmExpression(); - if (p == NULL) - return NULL; - wxPluralFormsNodePtr n(p); - if (token().type() == wxPluralFormsToken::T_REMINDER) + const wxLanguageInfo *info = GetLanguageInfo(lang); + + // Unknown language: + if (info == NULL) { - wxPluralFormsNodePtr qn(new wxPluralFormsNode(token())); - if (!nextToken()) - { - return NULL; - } - p = pmExpression(); - if (p == NULL) - { - return NULL; - } - qn->setNode(1, p); - qn->setNode(0, n.release()); - return qn.release(); + wxLogError(wxS("Unknown language %i."), lang); + return false; } - return n.release(); -} -wxPluralFormsNode* wxPluralFormsParser::pmExpression() -{ - wxPluralFormsNodePtr n; - if (token().type() == wxPluralFormsToken::T_N - || token().type() == wxPluralFormsToken::T_NUMBER) + wxString name = info->Description; + wxString canonical = info->CanonicalName; + wxString locale; + + // Set the locale: +#if defined(__OS2__) + const char *retloc = wxSetlocale(LC_ALL , wxEmptyString); +#elif defined(__UNIX__) && !defined(__WXMAC__) + if (language != wxLANGUAGE_DEFAULT) + locale = info->CanonicalName; + + const char *retloc = wxSetlocaleTryUTF8(LC_ALL, locale); + + const wxString langOnly = ExtractLang(locale); + if ( !retloc ) { - n.reset(new wxPluralFormsNode(token())); - if (!nextToken()) - { - return NULL; - } + // Some C libraries don't like xx_YY form and require xx only + retloc = wxSetlocaleTryUTF8(LC_ALL, langOnly); } - else if (token().type() == wxPluralFormsToken::T_LEFT_BRACKET) { - if (!nextToken()) - { - return NULL; - } - wxPluralFormsNode* p = expression(); - if (p == NULL) - { - return NULL; - } - n.reset(p); - if (token().type() != wxPluralFormsToken::T_RIGHT_BRACKET) - { - return NULL; - } - if (!nextToken()) + +#if wxUSE_FONTMAP + // some systems (e.g. FreeBSD and HP-UX) don't have xx_YY aliases but + // require the full xx_YY.encoding form, so try using UTF-8 because this is + // the only thing we can do generically + // + // TODO: add encodings applicable to each language to the lang DB and try + // them all in turn here + if ( !retloc ) + { + const wxChar **names = + wxFontMapperBase::GetAllEncodingNames(wxFONTENCODING_UTF8); + while ( *names ) { - return NULL; + retloc = wxSetlocale(LC_ALL, locale + wxS('.') + *names++); + if ( retloc ) + break; } } - else - { - return NULL; - } - return n.release(); -} +#endif // wxUSE_FONTMAP -wxPluralFormsCalculator* wxPluralFormsCalculator::make(const char* s) -{ - wxPluralFormsCalculatorPtr calculator(new wxPluralFormsCalculator); - if (s != NULL) + if ( !retloc ) { - wxPluralFormsScanner scanner(s); - wxPluralFormsParser p(scanner); - if (!p.parse(*calculator)) + // Some C libraries (namely glibc) still use old ISO 639, + // so will translate the abbrev for them + wxString localeAlt; + if ( langOnly == wxS("he") ) + localeAlt = wxS("iw") + ExtractNotLang(locale); + else if ( langOnly == wxS("id") ) + localeAlt = wxS("in") + ExtractNotLang(locale); + else if ( langOnly == wxS("yi") ) + localeAlt = wxS("ji") + ExtractNotLang(locale); + else if ( langOnly == wxS("nb") ) + localeAlt = wxS("no_NO"); + else if ( langOnly == wxS("nn") ) + localeAlt = wxS("no_NY"); + + if ( !localeAlt.empty() ) { - return NULL; + retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt); + if ( !retloc ) + retloc = wxSetlocaleTryUTF8(LC_ALL, ExtractLang(localeAlt)); } } - return calculator.release(); -} - - - - -// ---------------------------------------------------------------------------- -// wxMsgCatalogFile corresponds to one disk-file message catalog. -// -// This is a "low-level" class and is used only by wxMsgCatalog -// ---------------------------------------------------------------------------- - -WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxString, wxMessagesHash); - -class wxMsgCatalogFile -{ -public: - // ctor & dtor - wxMsgCatalogFile(); - ~wxMsgCatalogFile(); - - // load the catalog from disk (szDirPrefix corresponds to language) - bool Load(const wxChar *szDirPrefix, const wxChar *szName, - wxPluralFormsCalculatorPtr& rPluralFormsCalculator); - - // fills the hash with string-translation pairs - void FillHash(wxMessagesHash& hash, - const wxString& msgIdCharset, - bool convertEncoding) const; - - // return the charset of the strings in this catalog or empty string if - // none/unknown - wxString GetCharset() const { return m_charset; } -private: - // this implementation is binary compatible with GNU gettext() version 0.10 + if ( !retloc ) + ret = false; - // an entry in the string table - struct wxMsgTableEntry - { - size_t32 nLen; // length of the string - size_t32 ofsString; // pointer to the string - }; +#ifdef __AIX__ + // at least in AIX 5.2 libc is buggy and the string returned from + // setlocale(LC_ALL) can't be passed back to it because it returns 6 + // strings (one for each locale category), i.e. for C locale we get back + // "C C C C C C" + // + // this contradicts IBM own docs but this is not of much help, so just work + // around it in the crudest possible manner + char* p = const_cast(wxStrchr(retloc, ' ')); + if ( p ) + *p = '\0'; +#endif // __AIX__ - // header of a .mo file - struct wxMsgCatalogHeader +#elif defined(__WIN32__) + const char *retloc = "C"; + if ( language != wxLANGUAGE_DEFAULT ) { - size_t32 magic, // offset +00: magic id - revision, // +04: revision - numStrings; // +08: number of strings in the file - size_t32 ofsOrigTable, // +0C: start of original string table - ofsTransTable; // +10: start of translated string table - size_t32 nHashSize, // +14: hash table size - ofsHashTable; // +18: offset of hash table start - }; - - // all data is stored here, NULL if no data loaded - size_t8 *m_pData; - - // amount of memory pointed to by m_pData. - size_t32 m_nSize; - - // data description - size_t32 m_numStrings; // number of strings in this domain - wxMsgTableEntry *m_pOrigTable, // pointer to original strings - *m_pTransTable; // translated - - wxString m_charset; // from the message catalog header + if ( info->WinLang == 0 ) + { + wxLogWarning(wxS("Locale '%s' not supported by OS."), name.c_str()); + // retloc already set to "C" + } + else // language supported by Windows + { + // Windows CE doesn't have SetThreadLocale() and there doesn't seem + // to be any equivalent +#ifndef __WXWINCE__ + const wxUint32 lcid = info->GetLCID(); + // change locale used by Windows functions + ::SetThreadLocale(lcid); +#endif - // swap the 2 halves of 32 bit integer if needed - size_t32 Swap(size_t32 ui) const + // and also call setlocale() to change locale used by the CRT + locale = info->GetLocaleName(); + if ( locale.empty() ) + { + ret = false; + } + else // have a valid locale + { + retloc = wxSetlocale(LC_ALL, locale); + } + } + } + else // language == wxLANGUAGE_DEFAULT { - return m_bSwapped ? (ui << 24) | ((ui & 0xff00) << 8) | - ((ui >> 8) & 0xff00) | (ui >> 24) - : ui; + retloc = wxSetlocale(LC_ALL, wxEmptyString); } - const char *StringAtOfs(wxMsgTableEntry *pTable, size_t32 n) const +#if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__)) + // VC++ setlocale() (also used by Mingw) can't set locale to languages that + // can only be written using Unicode, therefore wxSetlocale() call fails + // for such languages but we don't want to report it as an error -- so that + // at least message catalogs can be used. + if ( !retloc ) { - const wxMsgTableEntry * const ent = pTable + n; - - // this check could fail for a corrupt message catalog - size_t32 ofsString = Swap(ent->ofsString); - if ( ofsString + Swap(ent->nLen) > m_nSize) + if ( wxGetANSICodePageForLocale(LOCALE_USER_DEFAULT).empty() ) { - return NULL; + // we set the locale to a Unicode-only language, don't treat the + // inability of CRT to use it as an error + retloc = "C"; } - - return (const char *)(m_pData + ofsString); } +#endif // CRT not handling Unicode-only languages - bool m_bSwapped; // wrong endianness? - - DECLARE_NO_COPY_CLASS(wxMsgCatalogFile) -}; - - -// ---------------------------------------------------------------------------- -// wxMsgCatalog corresponds to one loaded message catalog. -// -// This is a "low-level" class and is used only by wxLocale (that's why -// it's designed to be stored in a linked list) -// ---------------------------------------------------------------------------- - -class wxMsgCatalog -{ -public: - wxMsgCatalog() { m_conv = NULL; } - ~wxMsgCatalog(); - - // load the catalog from disk (szDirPrefix corresponds to language) - bool Load(const wxString& dirPrefix, const wxString& name, - const wxString& msgIdCharset, bool bConvertEncoding = false); - - // get name of the catalog - wxString GetName() const { return m_name; } - - // get the translated string: returns NULL if not found - const wxString *GetString(const wxString& sz, size_t n = size_t(-1)) const; + if ( !retloc ) + ret = false; +#elif defined(__WXMAC__) + if (lang == wxLANGUAGE_DEFAULT) + locale = wxEmptyString; + else + locale = info->CanonicalName; - // public variable pointing to the next element in a linked list (or NULL) - wxMsgCatalog *m_pNext; + const char *retloc = wxSetlocale(LC_ALL, locale); -private: - wxMessagesHash m_messages; // all messages in the catalog - wxString m_name; // name of the domain + if ( !retloc ) + { + // Some C libraries don't like xx_YY form and require xx only + retloc = wxSetlocale(LC_ALL, ExtractLang(locale)); + } +#else + wxUnusedVar(flags); + return false; + #define WX_NO_LOCALE_SUPPORT +#endif - // the conversion corresponding to this catalog charset if we installed it - // as the global one - wxCSConv *m_conv; +#ifndef WX_NO_LOCALE_SUPPORT + if ( !ret ) + { + wxLogWarning(_("Cannot set locale to language \"%s\"."), name.c_str()); - wxPluralFormsCalculatorPtr m_pluralFormsCalculator; -}; + // continue nevertheless and try to load at least the translations for + // this language + } -// ---------------------------------------------------------------------------- -// global variables -// ---------------------------------------------------------------------------- + if ( !DoInit(name, canonical, retloc) ) + { + ret = false; + } -// the list of the directories to search for message catalog files -static wxArrayString gs_searchPrefixes; + if (IsOk()) // setlocale() succeeded + m_language = lang; -// ============================================================================ -// implementation -// ============================================================================ + // NB: don't use 'lang' here, 'language' + wxTranslations *t = wxTranslations::Get(); + if ( t ) + { + t->SetLanguage(static_cast(language)); -// ---------------------------------------------------------------------------- -// wxMsgCatalogFile class -// ---------------------------------------------------------------------------- + if ( flags & wxLOCALE_LOAD_DEFAULT ) + t->AddStdCatalog(); + } -wxMsgCatalogFile::wxMsgCatalogFile() -{ - m_pData = NULL; - m_nSize = 0; + return ret; +#endif // !WX_NO_LOCALE_SUPPORT } -wxMsgCatalogFile::~wxMsgCatalogFile() +namespace { - delete [] m_pData; -} -// return the directories to search for message catalogs under the given -// prefix, separated by wxPATH_SEP -static -wxString GetMsgCatalogSubdirs(const wxChar *prefix, const wxChar *lang) +#ifndef __WXOSX__ +// Small helper function: get the value of the given environment variable and +// return true only if the variable was found and has non-empty value. +inline bool wxGetNonEmptyEnvVar(const wxString& name, wxString* value) { - wxString searchPath; - searchPath << prefix << wxFILE_SEP_PATH << lang; - - // Under Unix, the message catalogs are supposed to go into LC_MESSAGES - // subdirectory so look there too. Note that we do it on all platforms - // and not just Unix, because it doesn't cost much to look into one more - // directory and doing it this way has two important benefits: - // a) we don't break compatibility with wx-2.6 and older by stopping to - // look in a directory where the catalogs used to be and thus silently - // breaking apps after they are recompiled against the latest wx - // b) it makes it possible to package app's support files in the same - // way on all target platforms - const wxString searchPathOrig(searchPath); - searchPath << wxFILE_SEP_PATH << wxT("LC_MESSAGES") - << wxPATH_SEP << searchPathOrig; - - return searchPath; + return wxGetEnv(name, value) && !value->empty(); } +#endif + +} // anonymous namespace -// construct the search path for the given language -static wxString GetFullSearchPath(const wxChar *lang) +/*static*/ int wxLocale::GetSystemLanguage() { - // first take the entries explicitly added by the program - wxArrayString paths; - paths.reserve(gs_searchPrefixes.size() + 1); - size_t n, - count = gs_searchPrefixes.size(); - for ( n = 0; n < count; n++ ) - { - paths.Add(GetMsgCatalogSubdirs(gs_searchPrefixes[n], lang)); - } + CreateLanguagesDB(); + // init i to avoid compiler warning + size_t i = 0, + count = ms_languagesDB->GetCount(); -#if wxUSE_STDPATHS - // then look in the standard location - const wxString stdp = wxStandardPaths::Get(). - GetLocalizedResourcesDir(lang, wxStandardPaths::ResourceCat_Messages); +#if defined(__UNIX__) + // first get the string identifying the language from the environment + wxString langFull; +#ifdef __WXOSX__ + wxCFRef userLocaleRef(CFLocaleCopyCurrent()); - if ( paths.Index(stdp) == wxNOT_FOUND ) - paths.Add(stdp); -#endif // wxUSE_STDPATHS + // because the locale identifier (kCFLocaleIdentifier) is formatted a little bit differently, eg + // az_Cyrl_AZ@calendar=buddhist;currency=JPY we just recreate the base info as expected by wx here - // last look in default locations -#ifdef __UNIX__ - // LC_PATH is a standard env var containing the search path for the .mo - // files - const wxChar *pszLcPath = wxGetenv(wxT("LC_PATH")); - if ( pszLcPath ) + wxCFStringRef str(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleLanguageCode))); + langFull = str.AsString()+"_"; + str.reset(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleCountryCode))); + langFull += str.AsString(); +#else + if (!wxGetNonEmptyEnvVar(wxS("LC_ALL"), &langFull) && + !wxGetNonEmptyEnvVar(wxS("LC_MESSAGES"), &langFull) && + !wxGetNonEmptyEnvVar(wxS("LANG"), &langFull)) { - const wxString lcp = GetMsgCatalogSubdirs(pszLcPath, lang); - if ( paths.Index(lcp) == wxNOT_FOUND ) - paths.Add(lcp); + // no language specified, treat it as English + return wxLANGUAGE_ENGLISH_US; } - // also add the one from where wxWin was installed: - wxString wxp = wxGetInstallPrefix(); - if ( !wxp.empty() ) + if ( langFull == wxS("C") || langFull == wxS("POSIX") ) { - wxp = GetMsgCatalogSubdirs(wxp + _T("/share/locale"), lang); - if ( paths.Index(wxp) == wxNOT_FOUND ) - paths.Add(wxp); + // default C locale is English too + return wxLANGUAGE_ENGLISH_US; } -#endif // __UNIX__ +#endif + // the language string has the following form + // + // lang[_LANG][.encoding][@modifier] + // + // (see environ(5) in the Open Unix specification) + // + // where lang is the primary language, LANG is a sublang/territory, + // encoding is the charset to use and modifier "allows the user to select + // a specific instance of localization data within a single category" + // + // for example, the following strings are valid: + // fr + // fr_FR + // de_DE.iso88591 + // de_DE@euro + // de_DE.iso88591@euro - // finally construct the full search path - wxString searchPath; - searchPath.reserve(500); - count = paths.size(); - for ( n = 0; n < count; n++ ) + // for now we don't use the encoding, although we probably should (doing + // translations of the msg catalogs on the fly as required) (TODO) + // + // we need the modified for languages like Valencian: ca_ES@valencia + // though, remember it + wxString modifier; + size_t posModifier = langFull.find_first_of(wxS("@")); + if ( posModifier != wxString::npos ) + modifier = langFull.Mid(posModifier); + + size_t posEndLang = langFull.find_first_of(wxS("@.")); + if ( posEndLang != wxString::npos ) { - searchPath += paths[n]; - if ( n != count - 1 ) - searchPath += wxPATH_SEP; + langFull.Truncate(posEndLang); } - return searchPath; -} - -// open disk file and read in it's contents -bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName, - wxPluralFormsCalculatorPtr& rPluralFormsCalculator) -{ - wxString searchPath; - -#if wxUSE_FONTMAP - // first look for the catalog for this language and the current locale: - // notice that we don't use the system name for the locale as this would - // force us to install catalogs in different locations depending on the - // system but always use the canonical name - wxFontEncoding encSys = wxLocale::GetSystemEncoding(); - if ( encSys != wxFONTENCODING_SYSTEM ) - { - wxString fullname(szDirPrefix); - fullname << _T('.') << wxFontMapperBase::GetEncodingName(encSys); - searchPath << GetFullSearchPath(fullname) << wxPATH_SEP; - } -#endif // wxUSE_FONTMAP - - - searchPath += GetFullSearchPath(szDirPrefix); - const wxChar *sublocale = wxStrchr(szDirPrefix, wxT('_')); - if ( sublocale ) - { - // also add just base locale name: for things like "fr_BE" (belgium - // french) we should use "fr" if no belgium specific message catalogs - // exist - searchPath << wxPATH_SEP - << GetFullSearchPath(wxString(szDirPrefix). - Left((size_t)(sublocale - szDirPrefix))); - } - - // don't give translation errors here because the wxstd catalog might - // not yet be loaded (and it's normal) - // - // (we're using an object because we have several return paths) - - NoTransErr noTransErr; - wxLogVerbose(_("looking for catalog '%s' in path '%s'."), - szName, searchPath.c_str()); - wxLogTrace(TRACE_I18N, _T("Looking for \"%s.mo\" in \"%s\""), - szName, searchPath.c_str()); - - wxFileName fn(szName); - fn.SetExt(_T("mo")); - wxString strFullName; - if ( !wxFindFileInPath(&strFullName, searchPath, fn.GetFullPath()) ) { - wxLogVerbose(_("catalog file for domain '%s' not found."), szName); - wxLogTrace(TRACE_I18N, _T("Catalog \"%s.mo\" not found"), szName); - return false; - } - - // open file - wxLogVerbose(_("using catalog '%s' from '%s'."), szName, strFullName.c_str()); - wxLogTrace(TRACE_I18N, _T("Using catalog \"%s\"."), strFullName.c_str()); - - wxFile fileMsg(strFullName); - if ( !fileMsg.IsOpened() ) - return false; - - // get the file size (assume it is less than 4Gb...) - wxFileOffset lenFile = fileMsg.Length(); - if ( lenFile == wxInvalidOffset ) - return false; - - size_t nSize = wx_truncate_cast(size_t, lenFile); - wxASSERT_MSG( nSize == lenFile + size_t(0), _T("message catalog bigger than 4GB?") ); - - // read the whole file in memory - m_pData = new size_t8[nSize]; - if ( fileMsg.Read(m_pData, nSize) != lenFile ) { - wxDELETEA(m_pData); - return false; - } - - // examine header - bool bValid = nSize + (size_t)0 > sizeof(wxMsgCatalogHeader); - - wxMsgCatalogHeader *pHeader = (wxMsgCatalogHeader *)m_pData; - if ( bValid ) { - // we'll have to swap all the integers if it's true - m_bSwapped = pHeader->magic == MSGCATALOG_MAGIC_SW; - - // check the magic number - bValid = m_bSwapped || pHeader->magic == MSGCATALOG_MAGIC; - } - - if ( !bValid ) { - // it's either too short or has incorrect magic number - wxLogWarning(_("'%s' is not a valid message catalog."), strFullName.c_str()); + // do we have just the language (or sublang too)? + const bool justLang = langFull.find('_') == wxString::npos; + + // 0. Make sure the lang is according to latest ISO 639 + // (this is necessary because glibc uses iw and in instead + // of he and id respectively). + + // the language itself (second part is the dialect/sublang) + wxString langOrig = ExtractLang(langFull); + + wxString lang; + if ( langOrig == wxS("iw")) + lang = wxS("he"); + else if (langOrig == wxS("in")) + lang = wxS("id"); + else if (langOrig == wxS("ji")) + lang = wxS("yi"); + else if (langOrig == wxS("no_NO")) + lang = wxS("nb_NO"); + else if (langOrig == wxS("no_NY")) + lang = wxS("nn_NO"); + else if (langOrig == wxS("no")) + lang = wxS("nb_NO"); + else + lang = langOrig; - wxDELETEA(m_pData); - return false; - } - - // initialize - m_numStrings = Swap(pHeader->numStrings); - m_pOrigTable = (wxMsgTableEntry *)(m_pData + - Swap(pHeader->ofsOrigTable)); - m_pTransTable = (wxMsgTableEntry *)(m_pData + - Swap(pHeader->ofsTransTable)); - m_nSize = (size_t32)nSize; - - // now parse catalog's header and try to extract catalog charset and - // plural forms formula from it: - - const char* headerData = StringAtOfs(m_pOrigTable, 0); - if (headerData && headerData[0] == 0) - { - // Extract the charset: - wxString header = wxString::FromAscii(StringAtOfs(m_pTransTable, 0)); - int begin = header.Find(wxT("Content-Type: text/plain; charset=")); - if (begin != wxNOT_FOUND) - { - begin += 34; //strlen("Content-Type: text/plain; charset=") - size_t end = header.find('\n', begin); - if (end != size_t(-1)) - { - m_charset.assign(header, begin, end - begin); - if (m_charset == wxT("CHARSET")) - { - // "CHARSET" is not valid charset, but lazy translator - m_charset.Clear(); - } - } - } - // else: incorrectly filled Content-Type header - - // Extract plural forms: - begin = header.Find(wxT("Plural-Forms:")); - if (begin != wxNOT_FOUND) - { - begin += 13; - size_t end = header.find('\n', begin); - if (end != size_t(-1)) - { - wxString pfs(header, begin, end - begin); - wxPluralFormsCalculator* pCalculator = wxPluralFormsCalculator - ::make(pfs.ToAscii()); - if (pCalculator != 0) - { - rPluralFormsCalculator.reset(pCalculator); - } - else - { - wxLogVerbose(_("Cannot parse Plural-Forms:'%s'"), pfs.c_str()); - } - } - } - if (rPluralFormsCalculator.get() == NULL) - { - rPluralFormsCalculator.reset(wxPluralFormsCalculator::make()); - } - } - - // everything is fine - return true; -} + // did we change it? + if ( lang != langOrig ) + { + langFull = lang + ExtractNotLang(langFull); + } -void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, - const wxString& msgIdCharset, - bool convertEncoding) const -{ -#if wxUSE_UNICODE - // this parameter doesn't make sense, we always must convert encoding in - // Unicode build - convertEncoding = true; -#elif wxUSE_FONTMAP - if ( convertEncoding ) + // 1. Try to find the language either as is: + // a) With modifier if set + if ( !modifier.empty() ) { - // determine if we need any conversion at all - wxFontEncoding encCat = wxFontMapperBase::GetEncodingFromName(m_charset); - if ( encCat == wxLocale::GetSystemEncoding() ) + wxString langFullWithModifier = langFull + modifier; + for ( i = 0; i < count; i++ ) { - // no need to convert - convertEncoding = false; + if ( ms_languagesDB->Item(i).CanonicalName == langFullWithModifier ) + break; } } -#endif // wxUSE_UNICODE/wxUSE_FONTMAP -#if wxUSE_WCHAR_T - // conversion to use to convert catalog strings to the GUI encoding - wxMBConv *inputConv, - *inputConvPtr = NULL; // same as inputConv but safely deleteable - if ( convertEncoding && !m_charset.empty() ) - { - inputConvPtr = - inputConv = new wxCSConv(m_charset); - } - else // no need or not possible to convert the encoding + // b) Without modifier + if ( modifier.empty() || i == count ) { -#if wxUSE_UNICODE - // we must somehow convert the narrow strings in the message catalog to - // wide strings, so use the default conversion if we have no charset - inputConv = wxConvCurrent; -#else // !wxUSE_UNICODE - inputConv = NULL; -#endif // wxUSE_UNICODE/!wxUSE_UNICODE + for ( i = 0; i < count; i++ ) + { + if ( ms_languagesDB->Item(i).CanonicalName == langFull ) + break; + } } - // conversion to apply to msgid strings before looking them up: we only - // need it if the msgids are neither in 7 bit ASCII nor in the same - // encoding as the catalog - wxCSConv *sourceConv = msgIdCharset.empty() || (msgIdCharset == m_charset) - ? NULL - : new wxCSConv(msgIdCharset); - -#elif wxUSE_FONTMAP - wxASSERT_MSG( msgIdCharset.empty(), - _T("non-ASCII msgid languages only supported if wxUSE_WCHAR_T=1") ); - - wxEncodingConverter converter; - if ( convertEncoding ) + // 2. If langFull is of the form xx_YY, try to find xx: + if ( i == count && !justLang ) { - wxFontEncoding targetEnc = wxFONTENCODING_SYSTEM; - wxFontEncoding enc = wxFontMapperBase::Get()->CharsetToEncoding(m_charset, false); - if ( enc == wxFONTENCODING_SYSTEM ) - { - convertEncoding = false; // unknown encoding - } - else + for ( i = 0; i < count; i++ ) { - targetEnc = wxLocale::GetSystemEncoding(); - if (targetEnc == wxFONTENCODING_SYSTEM) + if ( ms_languagesDB->Item(i).CanonicalName == lang ) { - wxFontEncodingArray a = wxEncodingConverter::GetPlatformEquivalents(enc); - if (a[0] == enc) - // no conversion needed, locale uses native encoding - convertEncoding = false; - if (a.GetCount() == 0) - // we don't know common equiv. under this platform - convertEncoding = false; - targetEnc = a[0]; + break; } } + } - if ( convertEncoding ) + // 3. If langFull is of the form xx, try to find any xx_YY record: + if ( i == count && justLang ) + { + for ( i = 0; i < count; i++ ) { - converter.Init(enc, targetEnc); + if ( ExtractLang(ms_languagesDB->Item(i).CanonicalName) + == langFull ) + { + break; + } } } -#endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T - (void)convertEncoding; // get rid of warnings about unused parameter - for (size_t32 i = 0; i < m_numStrings; i++) - { - const char *data = StringAtOfs(m_pOrigTable, i); - wxString msgid; -#if wxUSE_UNICODE - msgid = wxString(data, *inputConv); -#else // ASCII - #if wxUSE_WCHAR_T - if ( inputConv && sourceConv ) - msgid = wxString(inputConv->cMB2WC(data), *sourceConv); - else - #endif - msgid = data; -#endif // wxUSE_UNICODE - - data = StringAtOfs(m_pTransTable, i); - size_t length = Swap(m_pTransTable[i].nLen); - size_t offset = 0; - size_t index = 0; - while (offset < length) + if ( i == count ) + { + // In addition to the format above, we also can have full language + // names in LANG env var - for example, SuSE is known to use + // LANG="german" - so check for use of non-standard format and try to + // find the name in verbose description. + for ( i = 0; i < count; i++ ) { - const char * const str = data + offset; - - wxString msgstr; -#if wxUSE_UNICODE - msgstr = wxString(str, *inputConv); -#elif wxUSE_WCHAR_T - if ( inputConv ) - msgstr = wxString(inputConv->cMB2WC(str), *wxConvUI); - else - msgstr = str; -#else // !wxUSE_WCHAR_T - #if wxUSE_FONTMAP - if ( bConvertEncoding ) - msgstr = wxString(converter.Convert(str)); - else - #endif - msgstr = str; -#endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T - - if ( !msgstr.empty() ) + if (ms_languagesDB->Item(i).Description.CmpNoCase(langFull) == 0) { - hash[index == 0 ? msgid : msgid + wxChar(index)] = msgstr; + break; } + } + } +#elif defined(__WIN32__) + LCID lcid = GetUserDefaultLCID(); + if ( lcid != 0 ) + { + wxUint32 lang = PRIMARYLANGID(LANGIDFROMLCID(lcid)); + wxUint32 sublang = SUBLANGID(LANGIDFROMLCID(lcid)); - // skip this string - offset += strlen(str) + 1; - ++index; + for ( i = 0; i < count; i++ ) + { + if (ms_languagesDB->Item(i).WinLang == lang && + ms_languagesDB->Item(i).WinSublang == sublang) + { + break; + } } } + //else: leave wxlang == wxLANGUAGE_UNKNOWN +#endif // Unix/Win32 -#if wxUSE_WCHAR_T - delete sourceConv; - delete inputConvPtr; -#endif // wxUSE_WCHAR_T -} + if ( i < count ) + { + // we did find a matching entry, use it + return ms_languagesDB->Item(i).Language; + } + // no info about this language in the database + return wxLANGUAGE_UNKNOWN; +} // ---------------------------------------------------------------------------- -// wxMsgCatalog class +// encoding stuff // ---------------------------------------------------------------------------- -wxMsgCatalog::~wxMsgCatalog() +// this is a bit strange as under Windows we get the encoding name using its +// numeric value and under Unix we do it the other way round, but this just +// reflects the way different systems provide the encoding info + +/* static */ +wxString wxLocale::GetSystemEncodingName() { - if ( m_conv ) + wxString encname; + +#if defined(__WIN32__) && !defined(__WXMICROWIN__) + // FIXME: what is the error return value for GetACP()? + UINT codepage = ::GetACP(); + encname.Printf(wxS("windows-%u"), codepage); +#elif defined(__WXMAC__) + encname = wxCFStringRef::AsString( + CFStringGetNameOfEncoding(CFStringGetSystemEncoding()) + ); +#elif defined(__UNIX_LIKE__) + +#if defined(HAVE_LANGINFO_H) && defined(CODESET) + // GNU libc provides current character set this way (this conforms + // to Unix98) + char *oldLocale = strdup(setlocale(LC_CTYPE, NULL)); + setlocale(LC_CTYPE, ""); + const char *alang = nl_langinfo(CODESET); + setlocale(LC_CTYPE, oldLocale); + free(oldLocale); + + if ( alang ) + { + encname = wxString::FromAscii( alang ); + } + else // nl_langinfo() failed +#endif // HAVE_LANGINFO_H { - if ( wxConvUI == m_conv ) + // if we can't get at the character set directly, try to see if it's in + // the environment variables (in most cases this won't work, but I was + // out of ideas) + char *lang = getenv( "LC_ALL"); + char *dot = lang ? strchr(lang, '.') : NULL; + if (!dot) + { + lang = getenv( "LC_CTYPE" ); + if ( lang ) + dot = strchr(lang, '.' ); + } + if (!dot) { - // we only change wxConvUI if it points to wxConvLocal so we reset - // it back to it too - wxConvUI = &wxConvLocal; + lang = getenv( "LANG"); + if ( lang ) + dot = strchr(lang, '.'); } - delete m_conv; + if ( dot ) + { + encname = wxString::FromAscii( dot+1 ); + } } +#endif // Win32/Unix + + return encname; } -bool wxMsgCatalog::Load(const wxString& dirPrefix, const wxString& name, - const wxString& msgIdCharset, bool bConvertEncoding) +/* static */ +wxFontEncoding wxLocale::GetSystemEncoding() { - wxMsgCatalogFile file; - - m_name = name; - - if ( !file.Load(dirPrefix, name, m_pluralFormsCalculator) ) - return false; - - file.FillHash(m_messages, msgIdCharset, bConvertEncoding); +#if defined(__WIN32__) && !defined(__WXMICROWIN__) + UINT codepage = ::GetACP(); - // we should use a conversion compatible with the message catalog encoding - // in the GUI if we don't convert the strings to the current conversion but - // as the encoding is global, only change it once, otherwise we could get - // into trouble if we use several message catalogs with different encodings - // - // this is, of course, a hack but it at least allows the program to use - // message catalogs in any encodings without asking the user to change his - // locale - if ( !bConvertEncoding && - !file.GetCharset().empty() && - wxConvUI == &wxConvLocal ) + // wxWidgets only knows about CP1250-1257, 874, 932, 936, 949, 950 + if ( codepage >= 1250 && codepage <= 1257 ) { - wxConvUI = - m_conv = new wxCSConv(file.GetCharset()); + return (wxFontEncoding)(wxFONTENCODING_CP1250 + codepage - 1250); } - return true; -} - -const wxString *wxMsgCatalog::GetString(const wxString& str, size_t n) const -{ - int index = 0; - if (n != size_t(-1)) + if ( codepage == 874 ) { - index = m_pluralFormsCalculator->evaluate(n); + return wxFONTENCODING_CP874; } - wxMessagesHash::const_iterator i; - if (index != 0) + + if ( codepage == 932 ) { - i = m_messages.find(wxString(str) + wxChar(index)); // plural + return wxFONTENCODING_CP932; } - else + + if ( codepage == 936 ) { - i = m_messages.find(str); + return wxFONTENCODING_CP936; } - if ( i != m_messages.end() ) + if ( codepage == 949 ) { - return &i->second; + return wxFONTENCODING_CP949; } - else - return NULL; -} -// ---------------------------------------------------------------------------- -// wxLocale -// ---------------------------------------------------------------------------- + if ( codepage == 950 ) + { + return wxFONTENCODING_CP950; + } +#elif defined(__WXMAC__) + CFStringEncoding encoding = 0 ; + encoding = CFStringGetSystemEncoding() ; + return wxMacGetFontEncFromSystemEnc( encoding ) ; +#elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP + const wxString encname = GetSystemEncodingName(); + if ( !encname.empty() ) + { + wxFontEncoding enc = wxFontMapperBase::GetEncodingFromName(encname); -#include "wx/arrimpl.cpp" -WX_DECLARE_EXPORTED_OBJARRAY(wxLanguageInfo, wxLanguageInfoArray); -WX_DEFINE_OBJARRAY(wxLanguageInfoArray) + // on some modern Linux systems (RedHat 8) the default system locale + // is UTF8 -- but it isn't supported by wxGTK1 in ANSI build at all so + // don't even try to use it in this case +#if !wxUSE_UNICODE && \ + ((defined(__WXGTK__) && !defined(__WXGTK20__)) || defined(__WXMOTIF__)) + if ( enc == wxFONTENCODING_UTF8 ) + { + // the most similar supported encoding... + enc = wxFONTENCODING_ISO8859_1; + } +#endif // !wxUSE_UNICODE -wxLanguageInfoArray *wxLocale::ms_languagesDB = NULL; + // GetEncodingFromName() returns wxFONTENCODING_DEFAULT for C locale + // (a.k.a. US-ASCII) which is arguably a bug but keep it like this for + // backwards compatibility and just take care to not return + // wxFONTENCODING_DEFAULT from here as this surely doesn't make sense + if ( enc == wxFONTENCODING_DEFAULT ) + { + // we don't have wxFONTENCODING_ASCII, so use the closest one + return wxFONTENCODING_ISO8859_1; + } -/*static*/ void wxLocale::CreateLanguagesDB() -{ - if (ms_languagesDB == NULL) - { - ms_languagesDB = new wxLanguageInfoArray; - InitLanguagesDB(); + if ( enc != wxFONTENCODING_MAX ) + { + return enc; + } + //else: return wxFONTENCODING_SYSTEM below } +#endif // Win32/Unix + + return wxFONTENCODING_SYSTEM; } -/*static*/ void wxLocale::DestroyLanguagesDB() +/* static */ +void wxLocale::AddLanguage(const wxLanguageInfo& info) { - delete ms_languagesDB; - ms_languagesDB = NULL; + CreateLanguagesDB(); + ms_languagesDB->Add(info); } - -void wxLocale::DoCommonInit() +/* static */ +const wxLanguageInfo *wxLocale::GetLanguageInfo(int lang) { - m_pszOldLocale = NULL; + CreateLanguagesDB(); - m_pOldLocale = wxSetLocale(this); + // calling GetLanguageInfo(wxLANGUAGE_DEFAULT) is a natural thing to do, so + // make it work + if ( lang == wxLANGUAGE_DEFAULT ) + lang = GetSystemLanguage(); + + const size_t count = ms_languagesDB->GetCount(); + for ( size_t i = 0; i < count; i++ ) + { + if ( ms_languagesDB->Item(i).Language == lang ) + { + // We need to create a temporary here in order to make this work with BCC in final build mode + wxLanguageInfo *ptr = &ms_languagesDB->Item(i); + return ptr; + } + } - m_pMsgCat = NULL; - m_language = wxLANGUAGE_UNKNOWN; - m_initialized = false; + return NULL; } -// NB: this function has (desired) side effect of changing current locale -bool wxLocale::Init(const wxString& name, - const wxString& shortName, - const wxString& locale, - bool bLoadDefault, - bool bConvertEncoding) +/* static */ +wxString wxLocale::GetLanguageName(int lang) { - wxASSERT_MSG( !m_initialized, - _T("you can't call wxLocale::Init more than once") ); - - m_initialized = true; - m_strLocale = name; - m_strShort = shortName; - m_bConvertEncoding = bConvertEncoding; - m_language = wxLANGUAGE_UNKNOWN; - - // change current locale (default: same as long name) - wxString szLocale(locale); - if ( szLocale.empty() ) - { - // the argument to setlocale() - szLocale = shortName; - - wxCHECK_MSG( !szLocale.empty(), false, - _T("no locale to set in wxLocale::Init()") ); - } - -#ifdef __WXWINCE__ - // FIXME: I'm guessing here - wxChar localeName[256]; - int ret = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLANGUAGE, localeName, - 256); - if (ret != 0) - { - m_pszOldLocale = wxStrdup(localeName); - } - else - m_pszOldLocale = NULL; - - // TODO: how to find languageId - // SetLocaleInfo(languageId, SORT_DEFAULT, localeName); -#else - wxMB2WXbuf oldLocale = wxSetlocale(LC_ALL, szLocale); - if ( oldLocale ) - m_pszOldLocale = wxStrdup(oldLocale); - else - m_pszOldLocale = NULL; -#endif + if ( lang == wxLANGUAGE_DEFAULT || lang == wxLANGUAGE_UNKNOWN ) + return wxEmptyString; - if ( m_pszOldLocale == NULL ) - wxLogError(_("locale '%s' can not be set."), szLocale); + const wxLanguageInfo *info = GetLanguageInfo(lang); + if ( !info ) + return wxEmptyString; + else + return info->Description; +} - // the short name will be used to look for catalog files as well, - // so we need something here - if ( m_strShort.empty() ) { - // FIXME I don't know how these 2 letter abbreviations are formed, - // this wild guess is surely wrong - if ( !szLocale.empty() ) - { - m_strShort += (wxChar)wxTolower(szLocale[0]); - if ( szLocale.length() > 1 ) - m_strShort += (wxChar)wxTolower(szLocale[1]); - } - } - - // load the default catalog with wxWidgets standard messages - m_pMsgCat = NULL; - bool bOk = true; - if ( bLoadDefault ) - { - bOk = AddCatalog(wxT("wxstd")); - - // there may be a catalog with toolkit specific overrides, it is not - // an error if this does not exist - if ( bOk ) - { - wxString port(wxPlatformInfo::Get().GetPortIdName()); - if ( !port.empty() ) - { - AddCatalog(port.BeforeFirst(wxT('/')).MakeLower()); - } - } - } +/* static */ +wxString wxLocale::GetLanguageCanonicalName(int lang) +{ + if ( lang == wxLANGUAGE_DEFAULT || lang == wxLANGUAGE_UNKNOWN ) + return wxEmptyString; - return bOk; + const wxLanguageInfo *info = GetLanguageInfo(lang); + if ( !info ) + return wxEmptyString; + else + return info->CanonicalName; } - -#if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__) -static wxWCharBuffer wxSetlocaleTryUTF8(int c, const wxChar *lc) +/* static */ +const wxLanguageInfo *wxLocale::FindLanguageInfo(const wxString& locale) { - wxMB2WXbuf l; + CreateLanguagesDB(); - // NB: We prefer to set UTF-8 locale if it's possible and only fall back to - // non-UTF-8 locale if it fails + const wxLanguageInfo *infoRet = NULL; - if ( lc && lc[0] != 0 ) + const size_t count = ms_languagesDB->GetCount(); + for ( size_t i = 0; i < count; i++ ) { - wxString buf(lc); - wxString buf2; - buf2 = buf + wxT(".UTF-8"); - l = wxSetlocale(c, buf2.c_str()); - if ( !l ) - { - buf2 = buf + wxT(".utf-8"); - l = wxSetlocale(c, buf2.c_str()); - } - if ( !l ) + const wxLanguageInfo *info = &ms_languagesDB->Item(i); + + if ( wxStricmp(locale, info->CanonicalName) == 0 || + wxStricmp(locale, info->Description) == 0 ) { - buf2 = buf + wxT(".UTF8"); - l = wxSetlocale(c, buf2.c_str()); + // exact match, stop searching + infoRet = info; + break; } - if ( !l ) + + if ( wxStricmp(locale, info->CanonicalName.BeforeFirst(wxS('_'))) == 0 ) { - buf2 = buf + wxT(".utf8"); - l = wxSetlocale(c, buf2.c_str()); + // a match -- but maybe we'll find an exact one later, so continue + // looking + // + // OTOH, maybe we had already found a language match and in this + // case don't overwrite it because the entry for the default + // country always appears first in ms_languagesDB + if ( !infoRet ) + infoRet = info; } } - // if we can't set UTF-8 locale, try non-UTF-8 one: - if ( !l ) - l = wxSetlocale(c, lc); - - return l; -} -#else -#define wxSetlocaleTryUTF8(c, lc) wxSetlocale(c, lc) -#endif - -bool wxLocale::Init(int language, int flags) -{ - int lang = language; - if (lang == wxLANGUAGE_DEFAULT) - { - // auto detect the language - lang = GetSystemLanguage(); - } - - // We failed to detect system language, so we will use English: - if (lang == wxLANGUAGE_UNKNOWN) - { - return false; - } - - const wxLanguageInfo *info = GetLanguageInfo(lang); - - // Unknown language: - if (info == NULL) - { - wxLogError(wxT("Unknown language %i."), lang); - return false; - } - - wxString name = info->Description; - wxString canonical = info->CanonicalName; - wxString locale; - - // Set the locale: -#if defined(__OS2__) - wxMB2WXbuf retloc = wxSetlocale(LC_ALL , wxEmptyString); -#elif defined(__UNIX__) && !defined(__WXMAC__) - if (language != wxLANGUAGE_DEFAULT) - locale = info->CanonicalName; - - wxMB2WXbuf retloc = wxSetlocaleTryUTF8(LC_ALL, locale); - - const wxString langOnly = locale.Left(2); - if ( !retloc ) - { - // Some C libraries don't like xx_YY form and require xx only - retloc = wxSetlocaleTryUTF8(LC_ALL, langOnly); - } - -#if wxUSE_FONTMAP - // some systems (e.g. FreeBSD and HP-UX) don't have xx_YY aliases but - // require the full xx_YY.encoding form, so try using UTF-8 because this is - // the only thing we can do generically - // - // TODO: add encodings applicable to each language to the lang DB and try - // them all in turn here - if ( !retloc ) - { - const wxChar **names = - wxFontMapperBase::GetAllEncodingNames(wxFONTENCODING_UTF8); - while ( *names ) - { - retloc = wxSetlocale(LC_ALL, locale + _T('.') + *names++); - if ( retloc ) - break; - } - } -#endif // wxUSE_FONTMAP - - if ( !retloc ) - { - // Some C libraries (namely glibc) still use old ISO 639, - // so will translate the abbrev for them - wxString localeAlt; - if ( langOnly == wxT("he") ) - localeAlt = wxT("iw") + locale.Mid(3); - else if ( langOnly == wxT("id") ) - localeAlt = wxT("in") + locale.Mid(3); - else if ( langOnly == wxT("yi") ) - localeAlt = wxT("ji") + locale.Mid(3); - else if ( langOnly == wxT("nb") ) - localeAlt = wxT("no_NO"); - else if ( langOnly == wxT("nn") ) - localeAlt = wxT("no_NY"); - - if ( !localeAlt.empty() ) - { - retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt); - if ( !retloc ) - retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt.Left(2)); - } - } - - if ( !retloc ) - { - wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str()); - return false; - } - -#ifdef __AIX__ - // at least in AIX 5.2 libc is buggy and the string returned from - // setlocale(LC_ALL) can't be passed back to it because it returns 6 - // strings (one for each locale category), i.e. for C locale we get back - // "C C C C C C" - // - // this contradicts IBM own docs but this is not of much help, so just work - // around it in the crudest possible manner - wxChar *p = wxStrchr((wxChar *)retloc, _T(' ')); - if ( p ) - *p = _T('\0'); -#endif // __AIX__ - -#elif defined(__WIN32__) - - #if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__)) - // NB: setlocale() from msvcrt.dll (used by VC++ and Mingw) - // can't set locale to language that can only be written using - // Unicode. Therefore wxSetlocale call failed, but we don't want - // to report it as an error -- so that at least message catalogs - // can be used. Watch for code marked with - // #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS bellow. - #define SETLOCALE_FAILS_ON_UNICODE_LANGS - #endif - -#if !wxUSE_UNICODE - const -#endif - wxMB2WXbuf retloc = wxT("C"); - if (language != wxLANGUAGE_DEFAULT) - { - if (info->WinLang == 0) - { - wxLogWarning(wxT("Locale '%s' not supported by OS."), name.c_str()); - // retloc already set to "C" - } - else - { - int codepage - #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS - = -1 - #endif - ; - wxUint32 lcid = MAKELCID(MAKELANGID(info->WinLang, info->WinSublang), - SORT_DEFAULT); - // FIXME -#ifndef __WXWINCE__ - SetThreadLocale(lcid); -#endif - // NB: we must translate LCID to CRT's setlocale string ourselves, - // because SetThreadLocale does not modify change the - // interpretation of setlocale(LC_ALL, "") call: - wxChar buffer[256]; - buffer[0] = wxT('\0'); - GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, buffer, 256); - locale << buffer; - if (GetLocaleInfo(lcid, LOCALE_SENGCOUNTRY, buffer, 256) > 0) - locale << wxT("_") << buffer; - if (GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, buffer, 256) > 0) - { - codepage = wxAtoi(buffer); - if (codepage != 0) - locale << wxT(".") << buffer; - } - if (locale.empty()) - { - wxLogLastError(wxT("SetThreadLocale")); - wxLogError(wxT("Cannot set locale to language %s."), name.c_str()); - return false; - } - else - { - // FIXME -#ifndef __WXWINCE__ - retloc = wxSetlocale(LC_ALL, locale); -#endif -#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS - if (codepage == 0 && (const wxChar*)retloc == NULL) - { - retloc = wxT("C"); - } -#endif - } - } - } - else - { - // FIXME -#ifndef __WXWINCE__ - retloc = wxSetlocale(LC_ALL, wxEmptyString); -#else - retloc = NULL; -#endif -#ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS - if ((const wxChar*)retloc == NULL) - { - wxChar buffer[16]; - if (GetLocaleInfo(LOCALE_USER_DEFAULT, - LOCALE_IDEFAULTANSICODEPAGE, buffer, 16) > 0 && - wxStrcmp(buffer, wxT("0")) == 0) - { - retloc = wxT("C"); - } - } -#endif - } - - if ( !retloc ) - { - wxLogError(wxT("Cannot set locale to language %s."), name.c_str()); - return false; - } -#elif defined(__WXMAC__) - if (lang == wxLANGUAGE_DEFAULT) - locale = wxEmptyString; - else - locale = info->CanonicalName; - - wxMB2WXbuf retloc = wxSetlocale(LC_ALL, locale); - - if ( !retloc ) - { - // Some C libraries don't like xx_YY form and require xx only - retloc = wxSetlocale(LC_ALL, locale.Mid(0,2)); - } - if ( !retloc ) - { - wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str()); - return false; - } -#else - wxUnusedVar(flags); - return false; - #define WX_NO_LOCALE_SUPPORT -#endif - -#ifndef WX_NO_LOCALE_SUPPORT - bool ret = Init(name, canonical, retloc, - (flags & wxLOCALE_LOAD_DEFAULT) != 0, - (flags & wxLOCALE_CONV_ENCODING) != 0); - - if (IsOk()) // setlocale() succeeded - m_language = lang; - - return ret; -#endif // !WX_NO_LOCALE_SUPPORT -} - - - -void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix) -{ - if ( gs_searchPrefixes.Index(prefix) == wxNOT_FOUND ) - { - gs_searchPrefixes.Add(prefix); - } - //else: already have it -} - -/*static*/ int wxLocale::GetSystemLanguage() -{ - CreateLanguagesDB(); - - // init i to avoid compiler warning - size_t i = 0, - count = ms_languagesDB->GetCount(); - -#if defined(__UNIX__) && !defined(__WXMAC__) - // first get the string identifying the language from the environment - wxString langFull; - if (!wxGetEnv(wxT("LC_ALL"), &langFull) && - !wxGetEnv(wxT("LC_MESSAGES"), &langFull) && - !wxGetEnv(wxT("LANG"), &langFull)) - { - // no language specified, treat it as English - return wxLANGUAGE_ENGLISH_US; - } - - if ( langFull == _T("C") || langFull == _T("POSIX") ) - { - // default C locale is English too - return wxLANGUAGE_ENGLISH_US; - } - - // the language string has the following form - // - // lang[_LANG][.encoding][@modifier] - // - // (see environ(5) in the Open Unix specification) - // - // where lang is the primary language, LANG is a sublang/territory, - // encoding is the charset to use and modifier "allows the user to select - // a specific instance of localization data within a single category" - // - // for example, the following strings are valid: - // fr - // fr_FR - // de_DE.iso88591 - // de_DE@euro - // de_DE.iso88591@euro - - // for now we don't use the encoding, although we probably should (doing - // translations of the msg catalogs on the fly as required) (TODO) - // - // we don't use the modifiers neither but we probably should translate - // "euro" into iso885915 - size_t posEndLang = langFull.find_first_of(_T("@.")); - if ( posEndLang != wxString::npos ) - { - langFull.Truncate(posEndLang); - } - - // in addition to the format above, we also can have full language names - // in LANG env var - for example, SuSE is known to use LANG="german" - so - // check for this - - // do we have just the language (or sublang too)? - bool justLang = langFull.length() == LEN_LANG; - if ( justLang || - (langFull.length() == LEN_FULL && langFull[LEN_LANG] == wxT('_')) ) - { - // 0. Make sure the lang is according to latest ISO 639 - // (this is necessary because glibc uses iw and in instead - // of he and id respectively). - - // the language itself (second part is the dialect/sublang) - wxString langOrig = ExtractLang(langFull); - - wxString lang; - if ( langOrig == wxT("iw")) - lang = _T("he"); - else if (langOrig == wxT("in")) - lang = wxT("id"); - else if (langOrig == wxT("ji")) - lang = wxT("yi"); - else if (langOrig == wxT("no_NO")) - lang = wxT("nb_NO"); - else if (langOrig == wxT("no_NY")) - lang = wxT("nn_NO"); - else if (langOrig == wxT("no")) - lang = wxT("nb_NO"); - else - lang = langOrig; - - // did we change it? - if ( lang != langOrig ) - { - langFull = lang + ExtractNotLang(langFull); - } - - // 1. Try to find the language either as is: - for ( i = 0; i < count; i++ ) - { - if ( ms_languagesDB->Item(i).CanonicalName == langFull ) - { - break; - } - } - - // 2. If langFull is of the form xx_YY, try to find xx: - if ( i == count && !justLang ) - { - for ( i = 0; i < count; i++ ) - { - if ( ms_languagesDB->Item(i).CanonicalName == lang ) - { - break; - } - } - } - - // 3. If langFull is of the form xx, try to find any xx_YY record: - if ( i == count && justLang ) - { - for ( i = 0; i < count; i++ ) - { - if ( ExtractLang(ms_languagesDB->Item(i).CanonicalName) - == langFull ) - { - break; - } - } - } - } - else // not standard format - { - // try to find the name in verbose description - for ( i = 0; i < count; i++ ) - { - if (ms_languagesDB->Item(i).Description.CmpNoCase(langFull) == 0) - { - break; - } - } - } -#elif defined(__WXMAC__) - const wxChar * lc = NULL ; - long lang = GetScriptVariable( smSystemScript, smScriptLang) ; - switch( GetScriptManagerVariable( smRegionCode ) ) { - case verUS : - lc = wxT("en_US") ; - break ; - case verFrance : - lc = wxT("fr_FR") ; - break ; - case verBritain : - lc = wxT("en_GB") ; - break ; - case verGermany : - lc = wxT("de_DE") ; - break ; - case verItaly : - lc = wxT("it_IT") ; - break ; - case verNetherlands : - lc = wxT("nl_NL") ; - break ; - case verFlemish : - lc = wxT("nl_BE") ; - break ; - case verSweden : - lc = wxT("sv_SE" ); - break ; - case verSpain : - lc = wxT("es_ES" ); - break ; - case verDenmark : - lc = wxT("da_DK") ; - break ; - case verPortugal : - lc = wxT("pt_PT") ; - break ; - case verFrCanada: - lc = wxT("fr_CA") ; - break ; - case verNorway: - lc = wxT("nb_NO") ; - break ; - case verIsrael: - lc = wxT("iw_IL") ; - break ; - case verJapan: - lc = wxT("ja_JP") ; - break ; - case verAustralia: - lc = wxT("en_AU") ; - break ; - case verArabic: - lc = wxT("ar") ; - break ; - case verFinland: - lc = wxT("fi_FI") ; - break ; - case verFrSwiss: - lc = wxT("fr_CH") ; - break ; - case verGrSwiss: - lc = wxT("de_CH") ; - break ; - case verGreece: - lc = wxT("el_GR") ; - break ; - case verIceland: - lc = wxT("is_IS") ; - break ; - case verMalta: - lc = wxT("mt_MT") ; - break ; - case verCyprus: - // _CY is not part of wx, so we have to translate according to the system language - if ( lang == langGreek ) { - lc = wxT("el_GR") ; - } - else if ( lang == langTurkish ) { - lc = wxT("tr_TR") ; - } - break ; - case verTurkey: - lc = wxT("tr_TR") ; - break ; - case verYugoCroatian: - lc = wxT("hr_HR") ; - break ; - case verIndiaHindi: - lc = wxT("hi_IN") ; - break ; - case verPakistanUrdu: - lc = wxT("ur_PK") ; - break ; - case verTurkishModified: - lc = wxT("tr_TR") ; - break ; - case verItalianSwiss: - lc = wxT("it_CH") ; - break ; - case verInternational: - lc = wxT("en") ; - break ; - case verRomania: - lc = wxT("ro_RO") ; - break ; - case verGreecePoly: - lc = wxT("el_GR") ; - break ; - case verLithuania: - lc = wxT("lt_LT") ; - break ; - case verPoland: - lc = wxT("pl_PL") ; - break ; - case verMagyar : - case verHungary: - lc = wxT("hu_HU") ; - break ; - case verEstonia: - lc = wxT("et_EE") ; - break ; - case verLatvia: - lc = wxT("lv_LV") ; - break ; - case verSami: - // not known - break ; - case verFaroeIsl: - lc = wxT("fo_FO") ; - break ; - case verIran: - lc = wxT("fa_IR") ; - break ; - case verRussia: - lc = wxT("ru_RU") ; - break ; - case verIreland: - lc = wxT("ga_IE") ; - break ; - case verKorea: - lc = wxT("ko_KR") ; - break ; - case verChina: - lc = wxT("zh_CN") ; - break ; - case verTaiwan: - lc = wxT("zh_TW") ; - break ; - case verThailand: - lc = wxT("th_TH") ; - break ; - case verCzech: - lc = wxT("cs_CZ") ; - break ; - case verSlovak: - lc = wxT("sk_SK") ; - break ; - case verBengali: - lc = wxT("bn") ; - break ; - case verByeloRussian: - lc = wxT("be_BY") ; - break ; - case verUkraine: - lc = wxT("uk_UA") ; - break ; - case verGreeceAlt: - lc = wxT("el_GR") ; - break ; - case verSerbian: - lc = wxT("sr_YU") ; - break ; - case verSlovenian: - lc = wxT("sl_SI") ; - break ; - case verMacedonian: - lc = wxT("mk_MK") ; - break ; - case verCroatia: - lc = wxT("hr_HR") ; - break ; - case verBrazil: - lc = wxT("pt_BR ") ; - break ; - case verBulgaria: - lc = wxT("bg_BG") ; - break ; - case verCatalonia: - lc = wxT("ca_ES") ; - break ; - case verScottishGaelic: - lc = wxT("gd") ; - break ; - case verManxGaelic: - lc = wxT("gv") ; - break ; - case verBreton: - lc = wxT("br") ; - break ; - case verNunavut: - lc = wxT("iu_CA") ; - break ; - case verWelsh: - lc = wxT("cy") ; - break ; - case verIrishGaelicScript: - lc = wxT("ga_IE") ; - break ; - case verEngCanada: - lc = wxT("en_CA") ; - break ; - case verBhutan: - lc = wxT("dz_BT") ; - break ; - case verArmenian: - lc = wxT("hy_AM") ; - break ; - case verGeorgian: - lc = wxT("ka_GE") ; - break ; - case verSpLatinAmerica: - lc = wxT("es_AR") ; - break ; - case verTonga: - lc = wxT("to_TO" ); - break ; - case verFrenchUniversal: - lc = wxT("fr_FR") ; - break ; - case verAustria: - lc = wxT("de_AT") ; - break ; - case verGujarati: - lc = wxT("gu_IN") ; - break ; - case verPunjabi: - lc = wxT("pa") ; - break ; - case verIndiaUrdu: - lc = wxT("ur_IN") ; - break ; - case verVietnam: - lc = wxT("vi_VN") ; - break ; - case verFrBelgium: - lc = wxT("fr_BE") ; - break ; - case verUzbek: - lc = wxT("uz_UZ") ; - break ; - case verSingapore: - lc = wxT("zh_SG") ; - break ; - case verNynorsk: - lc = wxT("nn_NO") ; - break ; - case verAfrikaans: - lc = wxT("af_ZA") ; - break ; - case verEsperanto: - lc = wxT("eo") ; - break ; - case verMarathi: - lc = wxT("mr_IN") ; - break ; - case verTibetan: - lc = wxT("bo") ; - break ; - case verNepal: - lc = wxT("ne_NP") ; - break ; - case verGreenland: - lc = wxT("kl_GL") ; - break ; - default : - break ; - } - for ( i = 0; i < count; i++ ) - { - if ( ms_languagesDB->Item(i).CanonicalName == lc ) - { - break; - } - } - -#elif defined(__WIN32__) - LCID lcid = GetUserDefaultLCID(); - if ( lcid != 0 ) - { - wxUint32 lang = PRIMARYLANGID(LANGIDFROMLCID(lcid)); - wxUint32 sublang = SUBLANGID(LANGIDFROMLCID(lcid)); - - for ( i = 0; i < count; i++ ) - { - if (ms_languagesDB->Item(i).WinLang == lang && - ms_languagesDB->Item(i).WinSublang == sublang) - { - break; - } - } - } - //else: leave wxlang == wxLANGUAGE_UNKNOWN -#endif // Unix/Win32 - - if ( i < count ) - { - // we did find a matching entry, use it - return ms_languagesDB->Item(i).Language; - } - - // no info about this language in the database - return wxLANGUAGE_UNKNOWN; -} - -// ---------------------------------------------------------------------------- -// encoding stuff -// ---------------------------------------------------------------------------- - -// this is a bit strange as under Windows we get the encoding name using its -// numeric value and under Unix we do it the other way round, but this just -// reflects the way different systems provide the encoding info - -/* static */ -wxString wxLocale::GetSystemEncodingName() -{ - wxString encname; - -#if defined(__WIN32__) && !defined(__WXMICROWIN__) - // FIXME: what is the error return value for GetACP()? - UINT codepage = ::GetACP(); - encname.Printf(_T("windows-%u"), codepage); -#elif defined(__WXMAC__) - // default is just empty string, this resolves to the default system - // encoding later -#elif defined(__UNIX_LIKE__) - -#if defined(HAVE_LANGINFO_H) && defined(CODESET) - // GNU libc provides current character set this way (this conforms - // to Unix98) - char *oldLocale = strdup(setlocale(LC_CTYPE, NULL)); - setlocale(LC_CTYPE, ""); - const char *alang = nl_langinfo(CODESET); - setlocale(LC_CTYPE, oldLocale); - free(oldLocale); - - if ( alang ) - { - encname = wxString::FromAscii( alang ); - } - else // nl_langinfo() failed -#endif // HAVE_LANGINFO_H - { - // if we can't get at the character set directly, try to see if it's in - // the environment variables (in most cases this won't work, but I was - // out of ideas) - char *lang = getenv( "LC_ALL"); - char *dot = lang ? strchr(lang, '.') : (char *)NULL; - if (!dot) - { - lang = getenv( "LC_CTYPE" ); - if ( lang ) - dot = strchr(lang, '.' ); - } - if (!dot) - { - lang = getenv( "LANG"); - if ( lang ) - dot = strchr(lang, '.'); - } - - if ( dot ) - { - encname = wxString::FromAscii( dot+1 ); - } - } -#endif // Win32/Unix - - return encname; -} - -/* static */ -wxFontEncoding wxLocale::GetSystemEncoding() -{ -#if defined(__WIN32__) && !defined(__WXMICROWIN__) - UINT codepage = ::GetACP(); - - // wxWidgets only knows about CP1250-1257, 874, 932, 936, 949, 950 - if ( codepage >= 1250 && codepage <= 1257 ) - { - return (wxFontEncoding)(wxFONTENCODING_CP1250 + codepage - 1250); - } - - if ( codepage == 874 ) - { - return wxFONTENCODING_CP874; - } - - if ( codepage == 932 ) - { - return wxFONTENCODING_CP932; - } - - if ( codepage == 936 ) - { - return wxFONTENCODING_CP936; - } - - if ( codepage == 949 ) - { - return wxFONTENCODING_CP949; - } - - if ( codepage == 950 ) - { - return wxFONTENCODING_CP950; - } -#elif defined(__WXMAC__) - TextEncoding encoding = 0 ; -#if TARGET_CARBON - encoding = CFStringGetSystemEncoding() ; -#else - UpgradeScriptInfoToTextEncoding ( smSystemScript , kTextLanguageDontCare , kTextRegionDontCare , NULL , &encoding ) ; -#endif - return wxMacGetFontEncFromSystemEnc( encoding ) ; -#elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP - const wxString encname = GetSystemEncodingName(); - if ( !encname.empty() ) - { - wxFontEncoding enc = wxFontMapperBase::GetEncodingFromName(encname); - - // on some modern Linux systems (RedHat 8) the default system locale - // is UTF8 -- but it isn't supported by wxGTK1 in ANSI build at all so - // don't even try to use it in this case -#if !wxUSE_UNICODE && \ - ((defined(__WXGTK__) && !defined(__WXGTK20__)) || defined(__WXMOTIF__)) - if ( enc == wxFONTENCODING_UTF8 ) - { - // the most similar supported encoding... - enc = wxFONTENCODING_ISO8859_1; - } -#endif // !wxUSE_UNICODE - - // GetEncodingFromName() returns wxFONTENCODING_DEFAULT for C locale - // (a.k.a. US-ASCII) which is arguably a bug but keep it like this for - // backwards compatibility and just take care to not return - // wxFONTENCODING_DEFAULT from here as this surely doesn't make sense - if ( enc == wxFONTENCODING_DEFAULT ) - { - // we don't have wxFONTENCODING_ASCII, so use the closest one - return wxFONTENCODING_ISO8859_1; - } - - if ( enc != wxFONTENCODING_MAX ) - { - return enc; - } - //else: return wxFONTENCODING_SYSTEM below - } -#endif // Win32/Unix - - return wxFONTENCODING_SYSTEM; + return infoRet; } -/* static */ -void wxLocale::AddLanguage(const wxLanguageInfo& info) +wxString wxLocale::GetSysName() const { - CreateLanguagesDB(); - ms_languagesDB->Add(info); + return wxSetlocale(LC_ALL, NULL); } -/* static */ -const wxLanguageInfo *wxLocale::GetLanguageInfo(int lang) +// clean up +wxLocale::~wxLocale() { - CreateLanguagesDB(); - - // calling GetLanguageInfo(wxLANGUAGE_DEFAULT) is a natural thing to do, so - // make it work - if ( lang == wxLANGUAGE_DEFAULT ) - lang = GetSystemLanguage(); - - const size_t count = ms_languagesDB->GetCount(); - for ( size_t i = 0; i < count; i++ ) + // Restore old translations object. + // See DoCommonInit() for explanation of why this is needed for backward + // compatibility. + if ( wxTranslations::Get() == &m_translations ) { - if ( ms_languagesDB->Item(i).Language == lang ) - { - // We need to create a temporary here in order to make this work with BCC in final build mode - wxLanguageInfo *ptr = &ms_languagesDB->Item(i); - return ptr; - } + if ( m_pOldLocale ) + wxTranslations::SetNonOwned(&m_pOldLocale->m_translations); + else + wxTranslations::Set(NULL); } - return NULL; + // restore old locale pointer + wxSetLocale(m_pOldLocale); + + wxSetlocale(LC_ALL, m_pszOldLocale); + free(const_cast(m_pszOldLocale)); } + +// check if the given locale is provided by OS and C run time /* static */ -wxString wxLocale::GetLanguageName(int lang) +bool wxLocale::IsAvailable(int lang) { - const wxLanguageInfo *info = GetLanguageInfo(lang); + const wxLanguageInfo *info = wxLocale::GetLanguageInfo(lang); if ( !info ) - return wxEmptyString; - else - return info->Description; -} + { + // The language is unknown (this normally only happens when we're + // passed wxLANGUAGE_DEFAULT), so we can't support it. + wxASSERT_MSG( lang == wxLANGUAGE_DEFAULT, + wxS("No info for a valid language?") ); + return false; + } -/* static */ -const wxLanguageInfo *wxLocale::FindLanguageInfo(const wxString& locale) -{ - CreateLanguagesDB(); +#if defined(__WIN32__) + if ( !info->WinLang ) + return false; - const wxLanguageInfo *infoRet = NULL; + if ( !::IsValidLocale(info->GetLCID(), LCID_INSTALLED) ) + return false; - const size_t count = ms_languagesDB->GetCount(); - for ( size_t i = 0; i < count; i++ ) - { - const wxLanguageInfo *info = &ms_languagesDB->Item(i); +#elif defined(__UNIX__) - if ( wxStricmp(locale, info->CanonicalName) == 0 || - wxStricmp(locale, info->Description) == 0 ) - { - // exact match, stop searching - infoRet = info; - break; - } + // Test if setting the locale works, then set it back. + char * const oldLocale = wxStrdupA(setlocale(LC_ALL, NULL)); - if ( wxStricmp(locale, info->CanonicalName.BeforeFirst(_T('_'))) == 0 ) - { - // a match -- but maybe we'll find an exact one later, so continue - // looking - // - // OTOH, maybe we had already found a language match and in this - // case don't overwrite it becauce the entry for the default - // country always appears first in ms_languagesDB - if ( !infoRet ) - infoRet = info; - } - } + // Some platforms don't like xx_YY form and require xx only so test for + // it too. + const bool + available = wxSetlocaleTryUTF8(LC_ALL, info->CanonicalName) || + wxSetlocaleTryUTF8(LC_ALL, ExtractLang(info->CanonicalName)); - return infoRet; -} + // restore the original locale + wxSetlocale(LC_ALL, oldLocale); -wxString wxLocale::GetSysName() const -{ - // FIXME -#ifndef __WXWINCE__ - return wxSetlocale(LC_ALL, NULL); -#else - return wxEmptyString; + free(oldLocale); + + if ( !available ) + return false; #endif + + return true; } -// clean up -wxLocale::~wxLocale() + +bool wxLocale::AddCatalog(const wxString& domain) { - // free memory - wxMsgCatalog *pTmpCat; - while ( m_pMsgCat != NULL ) { - pTmpCat = m_pMsgCat; - m_pMsgCat = m_pMsgCat->m_pNext; - delete pTmpCat; - } + wxTranslations *t = wxTranslations::Get(); + if ( !t ) + return false; + return t->AddCatalog(domain); +} - // restore old locale pointer - wxSetLocale(m_pOldLocale); +bool wxLocale::AddCatalog(const wxString& domain, wxLanguage msgIdLanguage) +{ + wxTranslations *t = wxTranslations::Get(); + if ( !t ) + return false; + return t->AddCatalog(domain, msgIdLanguage); +} - // FIXME -#ifndef __WXWINCE__ - wxSetlocale(LC_ALL, m_pszOldLocale); +// add a catalog to our linked list +bool wxLocale::AddCatalog(const wxString& szDomain, + wxLanguage msgIdLanguage, + const wxString& msgIdCharset) +{ + wxTranslations *t = wxTranslations::Get(); + if ( !t ) + return false; +#if wxUSE_UNICODE + wxUnusedVar(msgIdCharset); + return t->AddCatalog(szDomain, msgIdLanguage); +#else + return t->AddCatalog(szDomain, msgIdLanguage, msgIdCharset); #endif - free((wxChar *)m_pszOldLocale); // const_cast } -// get the translation of given string in current locale -const wxString& wxLocale::GetString(const wxString& origString, - const wxString& domain) const +bool wxLocale::IsLoaded(const wxString& domain) const { - return GetString(origString, origString, size_t(-1), domain); + wxTranslations *t = wxTranslations::Get(); + if ( !t ) + return false; + return t->IsLoaded(domain); } -const wxString& wxLocale::GetString(const wxString& origString, - const wxString& origString2, - size_t n, - const wxString& domain) const +wxString wxLocale::GetHeaderValue(const wxString& header, + const wxString& domain) const { - if ( origString.empty() ) - return GetUntranslatedString(origString); + wxTranslations *t = wxTranslations::Get(); + if ( !t ) + return wxEmptyString; + return t->GetHeaderValue(header, domain); +} - const wxString *trans = NULL; - wxMsgCatalog *pMsgCat; +// ---------------------------------------------------------------------------- +// accessors for locale-dependent data +// ---------------------------------------------------------------------------- - if ( !domain.empty() ) - { - pMsgCat = FindCatalog(domain); +#if defined(__WINDOWS__) || defined(__WXOSX__) - // does the catalog exist? - if ( pMsgCat != NULL ) - trans = pMsgCat->GetString(origString, n); - } - else +namespace +{ + +// This function translates from Unicode date formats described at +// +// http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns +// +// to strftime()-like syntax. This translation is not lossless but we try to do +// our best. + +static wxString TranslateFromUnicodeFormat(const wxString& fmt) +{ + wxString fmtWX; + fmtWX.reserve(fmt.length()); + + char chLast = '\0'; + size_t lastCount = 0; + + const char* formatchars = + "dghHmMsSy" +#ifdef __WINDOWS__ + "t" +#else + "EawD" +#endif + ; + for ( wxString::const_iterator p = fmt.begin(); /* end handled inside */; ++p ) { - // search in all domains - for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext ) + if ( p != fmt.end() ) { - trans = pMsgCat->GetString(origString, n); - if ( trans != NULL ) // take the first found - break; + if ( *p == chLast ) + { + lastCount++; + continue; + } + + const wxUniChar ch = (*p).GetValue(); + if ( ch.IsAscii() && strchr(formatchars, ch) ) + { + // these characters come in groups, start counting them + chLast = ch; + lastCount = 1; + continue; + } } - } - if ( trans == NULL ) - { -#ifdef __WXDEBUG__ - if ( !NoTransErr::Suppress() ) + // interpret any special characters we collected so far + if ( lastCount ) + { + switch ( chLast ) + { + case 'd': + switch ( lastCount ) + { + case 1: // d + case 2: // dd + // these two are the same as we don't distinguish + // between 1 and 2 digits for days + fmtWX += "%d"; + break; +#ifdef __WINDOWS__ + case 3: // ddd + fmtWX += "%a"; + break; + + case 4: // dddd + fmtWX += "%A"; + break; +#endif + default: + wxFAIL_MSG( "too many 'd's" ); + } + break; +#ifndef __WINDOWS__ + case 'D': + switch ( lastCount ) + { + case 1: // D + case 2: // DD + case 3: // DDD + fmtWX += "%j"; + break; + + default: + wxFAIL_MSG( "wrong number of 'D's" ); + } + break; + case 'w': + switch ( lastCount ) + { + case 1: // w + case 2: // ww + fmtWX += "%W"; + break; + + default: + wxFAIL_MSG( "wrong number of 'w's" ); + } + break; + case 'E': + switch ( lastCount ) + { + case 1: // E + case 2: // EE + case 3: // EEE + fmtWX += "%a"; + break; + case 4: // EEEE + fmtWX += "%A"; + break; + case 5: // EEEEE + fmtWX += "%a"; + break; + + default: + wxFAIL_MSG( "wrong number of 'E's" ); + } + break; +#endif + case 'M': + switch ( lastCount ) + { + case 1: // M + case 2: // MM + // as for 'd' and 'dd' above + fmtWX += "%m"; + break; + + case 3: + fmtWX += "%b"; + break; + + case 4: + fmtWX += "%B"; + break; + + default: + wxFAIL_MSG( "too many 'M's" ); + } + break; + + case 'y': + switch ( lastCount ) + { + case 1: // y + case 2: // yy + fmtWX += "%y"; + break; + + case 4: // yyyy + fmtWX += "%Y"; + break; + + default: + wxFAIL_MSG( "wrong number of 'y's" ); + } + break; + + case 'H': + switch ( lastCount ) + { + case 1: // H + case 2: // HH + fmtWX += "%H"; + break; + + default: + wxFAIL_MSG( "wrong number of 'H's" ); + } + break; + + case 'h': + switch ( lastCount ) + { + case 1: // h + case 2: // hh + fmtWX += "%I"; + break; + + default: + wxFAIL_MSG( "wrong number of 'h's" ); + } + break; + + case 'm': + switch ( lastCount ) + { + case 1: // m + case 2: // mm + fmtWX += "%M"; + break; + + default: + wxFAIL_MSG( "wrong number of 'm's" ); + } + break; + + case 's': + switch ( lastCount ) + { + case 1: // s + case 2: // ss + fmtWX += "%S"; + break; + + default: + wxFAIL_MSG( "wrong number of 's's" ); + } + break; + + case 'g': + // strftime() doesn't have era string, + // ignore this format + wxASSERT_MSG( lastCount <= 2, "too many 'g's" ); + + break; +#ifndef __WINDOWS__ + case 'a': + fmtWX += "%p"; + break; +#endif +#ifdef __WINDOWS__ + case 't': + switch ( lastCount ) + { + case 1: // t + case 2: // tt + fmtWX += "%p"; + break; + + default: + wxFAIL_MSG( "too many 't's" ); + } + break; +#endif + default: + wxFAIL_MSG( "unreachable" ); + } + + chLast = '\0'; + lastCount = 0; + } + + if ( p == fmt.end() ) + break; + + // not a special character so must be just a separator, treat as is + if ( *p == wxT('%') ) { - NoTransErr noTransErr; - - wxLogTrace(TRACE_I18N, - _T("string \"%s\"[%ld] not found in %slocale '%s'."), - origString, (long)n, - domain.empty() - ? (const wxChar*)wxString::Format(_T("domain '%s' "), domain).c_str() - : _T(""), - m_strLocale.c_str()); + // this one needs to be escaped + fmtWX += wxT('%'); } -#endif // __WXDEBUG__ - if (n == size_t(-1)) - return GetUntranslatedString(origString); - else - return GetUntranslatedString(n == 1 ? origString : origString2); + fmtWX += *p; } - return *trans; + return fmtWX; } -WX_DECLARE_HASH_SET(wxString, wxStringHash, wxStringEqual, - wxLocaleUntranslatedStrings); - -/* static */ -const wxString& wxLocale::GetUntranslatedString(const wxString& str) -{ - static wxLocaleUntranslatedStrings s_strings; +} // anonymous namespace - wxLocaleUntranslatedStrings::iterator i = s_strings.find(str); - if ( i != s_strings.end() ) - return *i; - else - return *s_strings.insert(str).first; +#endif // __WINDOWS__ || __WXOSX__ - return *i; -} +#if defined(__WINDOWS__) -wxString wxLocale::GetHeaderValue(const wxString& header, - const wxString& domain) const +namespace { - if ( header.empty() ) - return wxEmptyString; - - const wxString *trans = NULL; - wxMsgCatalog *pMsgCat; - if ( !domain.empty() ) +LCTYPE GetLCTYPEFormatFromLocalInfo(wxLocaleInfo index) +{ + switch ( index ) { - pMsgCat = FindCatalog(domain); + case wxLOCALE_SHORT_DATE_FMT: + return LOCALE_SSHORTDATE; + + case wxLOCALE_LONG_DATE_FMT: + return LOCALE_SLONGDATE; - // does the catalog exist? - if ( pMsgCat == NULL ) - return wxEmptyString; + case wxLOCALE_TIME_FMT: + return LOCALE_STIMEFORMAT; - trans = pMsgCat->GetString(wxEmptyString, (size_t)-1); + default: + wxFAIL_MSG( "no matching LCTYPE" ); } - else + + return 0; +} + +} // anonymous namespace + +/* static */ +wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) +{ + const wxLanguageInfo * const + info = wxGetLocale() ? GetLanguageInfo(wxGetLocale()->GetLanguage()) + : NULL; + if ( !info ) { - // search in all domains - for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext ) + // wxSetLocale() hadn't been called yet of failed, hence CRT must be + // using "C" locale -- but check it to detect bugs that would happen if + // this were not the case. + wxASSERT_MSG( strcmp(setlocale(LC_ALL, NULL), "C") == 0, + wxS("You probably called setlocale() directly instead ") + wxS("of using wxLocale and now there is a ") + wxS("mismatch between C/C++ and Windows locale.\n") + wxS("Things are going to break, please only change ") + wxS("locale by creating wxLocale objects to avoid this!") ); + + + // Return the hard coded values for C locale. This is really the right + // thing to do as there is no LCID we can use in the code below in this + // case, even LOCALE_INVARIANT is not quite the same as C locale (the + // only difference is that it uses %Y instead of %y in the date format + // but this difference is significant enough). + switch ( index ) { - trans = pMsgCat->GetString(wxEmptyString, (size_t)-1); - if ( trans != NULL ) // take the first found - break; + case wxLOCALE_THOUSANDS_SEP: + return wxString(); + + case wxLOCALE_DECIMAL_POINT: + return "."; + + case wxLOCALE_SHORT_DATE_FMT: + return "%m/%d/%y"; + + case wxLOCALE_LONG_DATE_FMT: + return "%A, %B %d, %Y"; + + case wxLOCALE_TIME_FMT: + return "%H:%M:%S"; + + case wxLOCALE_DATE_TIME_FMT: + return "%m/%d/%y %H:%M:%S"; + + default: + wxFAIL_MSG( "unknown wxLocaleInfo" ); } } - if ( !trans || trans->empty() ) - return wxEmptyString; + const wxUint32 lcid = info->GetLCID(); + + wxString str; - size_t found = trans->find(header); - if ( found == wxString::npos ) - return wxEmptyString; + wxChar buf[256]; + buf[0] = wxT('\0'); - found += header.length() + 2 /* ': ' */; + switch ( index ) + { + case wxLOCALE_THOUSANDS_SEP: + if ( ::GetLocaleInfo(lcid, LOCALE_STHOUSAND, buf, WXSIZEOF(buf)) ) + str = buf; + break; - // Every header is separated by \n + case wxLOCALE_DECIMAL_POINT: + if ( ::GetLocaleInfo(lcid, + cat == wxLOCALE_CAT_MONEY + ? LOCALE_SMONDECIMALSEP + : LOCALE_SDECIMAL, + buf, + WXSIZEOF(buf)) ) + { + str = buf; + + // As we get our decimal point separator from Win32 and not the + // CRT there is a possibility of mismatch between them and this + // can easily happen if the user code called setlocale() + // instead of using wxLocale to change the locale. And this can + // result in very strange bugs elsewhere in the code as the + // assumptions that formatted strings do use the decimal + // separator actually fail, so check for it here. + wxASSERT_MSG + ( + wxString::Format("%.3f", 1.23).find(str) != wxString::npos, + "Decimal separator mismatch -- did you use setlocale()?" + "If so, use wxLocale to change the locale instead." + ); + } + break; - size_t endLine = trans->find(wxT('\n'), found); - size_t len = (endLine == wxString::npos) ? - wxString::npos : (endLine - found); + case wxLOCALE_SHORT_DATE_FMT: + case wxLOCALE_LONG_DATE_FMT: + case wxLOCALE_TIME_FMT: + if ( ::GetLocaleInfo(lcid, GetLCTYPEFormatFromLocalInfo(index), + buf, WXSIZEOF(buf)) ) + { + return TranslateFromUnicodeFormat(buf); + } + break; - return trans->substr(found, len); -} + case wxLOCALE_DATE_TIME_FMT: + // there doesn't seem to be any specific setting for this, so just + // combine date and time ones + // + // we use the short date because this is what "%c" uses by default + // ("%#c" uses long date but we have no way to specify the + // alternate representation here) + { + const wxString datefmt = GetInfo(wxLOCALE_SHORT_DATE_FMT); + if ( datefmt.empty() ) + break; + const wxString timefmt = GetInfo(wxLOCALE_TIME_FMT); + if ( timefmt.empty() ) + break; -// find catalog by name in a linked list, return NULL if !found -wxMsgCatalog *wxLocale::FindCatalog(const wxString& domain) const -{ - // linear search in the linked list - wxMsgCatalog *pMsgCat; - for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext ) - { - if ( pMsgCat->GetName() == domain ) - return pMsgCat; + str << datefmt << ' ' << timefmt; + } + break; + + default: + wxFAIL_MSG( "unknown wxLocaleInfo" ); } - return NULL; + return str; } -// check if the given locale is provided by OS and C run time +#elif defined(__WXOSX__) + /* static */ -bool wxLocale::IsAvailable(int lang) +wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat)) { - const wxLanguageInfo *info = wxLocale::GetLanguageInfo(lang); - wxCHECK_MSG( info, false, _T("invalid language") ); + CFLocaleRef userLocaleRefRaw; + if ( wxGetLocale() ) + { + userLocaleRefRaw = CFLocaleCreate + ( + kCFAllocatorDefault, + wxCFStringRef(wxGetLocale()->GetCanonicalName()) + ); + } + else // no current locale, use the default one + { + userLocaleRefRaw = CFLocaleCopyCurrent(); + } -#if defined(__WIN32__) - if ( !info->WinLang ) - return false; + wxCFRef userLocaleRef(userLocaleRefRaw); - if ( !::IsValidLocale - ( - MAKELCID(MAKELANGID(info->WinLang, info->WinSublang), - SORT_DEFAULT), - LCID_INSTALLED - ) ) - return false; + CFStringRef cfstr = 0; + switch ( index ) + { + case wxLOCALE_THOUSANDS_SEP: + cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator); + break; + + case wxLOCALE_DECIMAL_POINT: + cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator); + break; + + case wxLOCALE_SHORT_DATE_FMT: + case wxLOCALE_LONG_DATE_FMT: + case wxLOCALE_DATE_TIME_FMT: + case wxLOCALE_TIME_FMT: + { + CFDateFormatterStyle dateStyle = kCFDateFormatterNoStyle; + CFDateFormatterStyle timeStyle = kCFDateFormatterNoStyle; + switch (index ) + { + case wxLOCALE_SHORT_DATE_FMT: + dateStyle = kCFDateFormatterShortStyle; + break; + case wxLOCALE_LONG_DATE_FMT: + dateStyle = kCFDateFormatterFullStyle; + break; + case wxLOCALE_DATE_TIME_FMT: + dateStyle = kCFDateFormatterFullStyle; + timeStyle = kCFDateFormatterMediumStyle; + break; + case wxLOCALE_TIME_FMT: + timeStyle = kCFDateFormatterMediumStyle; + break; + default: + wxFAIL_MSG( "unexpected time locale" ); + return wxString(); + } + wxCFRef dateFormatter( CFDateFormatterCreate + (NULL, userLocaleRef, dateStyle, timeStyle)); + wxCFStringRef cfs = wxCFRetain( CFDateFormatterGetFormat(dateFormatter )); + wxString format = TranslateFromUnicodeFormat(cfs.AsString()); + // we always want full years + format.Replace("%y","%Y"); + return format; + } + break; -#elif defined(__UNIX__) - - // Test if setting the locale works, then set it back. - wxMB2WXbuf oldLocale = wxSetlocale(LC_ALL, wxEmptyString); - wxMB2WXbuf tmp = wxSetlocaleTryUTF8(LC_ALL, info->CanonicalName); - if ( !tmp ) - { - // Some C libraries don't like xx_YY form and require xx only - tmp = wxSetlocaleTryUTF8(LC_ALL, info->CanonicalName.Left(2)); - if ( !tmp ) - return false; + default: + wxFAIL_MSG( "Unknown locale info" ); + return wxString(); } - // restore the original locale - wxSetlocale(LC_ALL, oldLocale); -#endif - return true; + wxCFStringRef str(wxCFRetain(cfstr)); + return str.AsString(); } -// check if the given catalog is loaded -bool wxLocale::IsLoaded(const wxString& szDomain) const -{ - return FindCatalog(szDomain) != NULL; -} +#else // !__WINDOWS__ && !__WXOSX__, assume generic POSIX -// add a catalog to our linked list -bool wxLocale::AddCatalog(const wxString& szDomain) +namespace { - return AddCatalog(szDomain, wxLANGUAGE_ENGLISH_US, wxEmptyString); -} - -// add a catalog to our linked list -bool wxLocale::AddCatalog(const wxString& szDomain, - wxLanguage msgIdLanguage, - const wxString& msgIdCharset) +wxString GetDateFormatFromLangInfo(wxLocaleInfo index) { - wxMsgCatalog *pMsgCat = new wxMsgCatalog; - - if ( pMsgCat->Load(m_strShort, szDomain, msgIdCharset, m_bConvertEncoding) ) { - // add it to the head of the list so that in GetString it will - // be searched before the catalogs added earlier - pMsgCat->m_pNext = m_pMsgCat; - m_pMsgCat = pMsgCat; +#ifdef HAVE_LANGINFO_H + // array containing parameters for nl_langinfo() indexes by offset of index + // from wxLOCALE_SHORT_DATE_FMT + static const nl_item items[] = + { + D_FMT, D_T_FMT, D_T_FMT, T_FMT, + }; - return true; - } - else { - // don't add it because it couldn't be loaded anyway - delete pMsgCat; - - // It is OK to not load catalog if the msgid language and m_language match, - // in which case we can directly display the texts embedded in program's - // source code: - if (m_language == msgIdLanguage) - return true; - - // If there's no exact match, we may still get partial match where the - // (basic) language is same, but the country differs. For example, it's - // permitted to use en_US strings from sources even if m_language is en_GB: - const wxLanguageInfo *msgIdLangInfo = GetLanguageInfo(msgIdLanguage); - if ( msgIdLangInfo && - msgIdLangInfo->CanonicalName.Mid(0, 2) == m_strShort.Mid(0, 2) ) + const int nlidx = index - wxLOCALE_SHORT_DATE_FMT; + if ( nlidx < 0 || nlidx >= (int)WXSIZEOF(items) ) { - return true; + wxFAIL_MSG( "logic error in GetInfo() code" ); + return wxString(); } - return false; - } -} + const wxString fmt(nl_langinfo(items[nlidx])); -// ---------------------------------------------------------------------------- -// accessors for locale-dependent data -// ---------------------------------------------------------------------------- + // just return the format returned by nl_langinfo() except for long date + // format which we need to recover from date/time format ourselves (but not + // if we failed completely) + if ( fmt.empty() || index != wxLOCALE_LONG_DATE_FMT ) + return fmt; -#ifdef __WXMSW__ + // this is not 100% precise but the idea is that a typical date/time format + // under POSIX systems is a combination of a long date format with time one + // so we should be able to get just the long date format by removing all + // time-specific format specifiers + static const char *timeFmtSpecs = "HIklMpPrRsSTXzZ"; + static const char *timeSep = " :./-"; -/* static */ -wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat)) -{ - wxString str; - wxChar buffer[256]; - size_t count; - buffer[0] = wxT('\0'); - switch (index) + wxString fmtDateOnly; + const wxString::const_iterator end = fmt.end(); + wxString::const_iterator lastSep = end; + for ( wxString::const_iterator p = fmt.begin(); p != end; ++p ) { - case wxLOCALE_DECIMAL_POINT: - count = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buffer, 256); - if (!count) - str << wxT("."); - else - str << buffer; - break; -#if 0 - case wxSYS_LIST_SEPARATOR: - count = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLIST, buffer, 256); - if (!count) - str << wxT(","); - else - str << buffer; - break; - case wxSYS_LEADING_ZERO: // 0 means no leading zero, 1 means leading zero - count = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILZERO, buffer, 256); - if (!count) - str << wxT("0"); - else - str << buffer; - break; -#endif - default: - wxFAIL_MSG(wxT("Unknown System String !")); + if ( strchr(timeSep, *p) ) + { + if ( lastSep == end ) + lastSep = p; + + // skip it for now, we'll discard it if it's followed by a time + // specifier later or add it to fmtDateOnly if it is not + continue; + } + + if ( *p == '%' && + (p + 1 != end) && strchr(timeFmtSpecs, p[1]) ) + { + // time specified found: skip it and any preceding separators + ++p; + lastSep = end; + continue; + } + + if ( lastSep != end ) + { + fmtDateOnly += wxString(lastSep, p); + lastSep = end; + } + + fmtDateOnly += *p; } - return str; + + return fmtDateOnly; +#else // !HAVE_LANGINFO_H + wxUnusedVar(index); + + // no fallback, let the application deal with unavailability of + // nl_langinfo() itself as there is no good way for us to do it (well, we + // could try to reverse engineer the format from strftime() output but this + // looks like too much trouble considering the relatively small number of + // systems without nl_langinfo() still in use) + return wxString(); +#endif // HAVE_LANGINFO_H/!HAVE_LANGINFO_H } -#else // !__WXMSW__ +} // anonymous namespace /* static */ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) { - struct lconv *locale_info = localeconv(); - switch (cat) + lconv * const lc = localeconv(); + if ( !lc ) + return wxString(); + + switch ( index ) { - case wxLOCALE_CAT_NUMBER: - switch (index) - { - case wxLOCALE_THOUSANDS_SEP: - return wxString(locale_info->thousands_sep, - *wxConvCurrent); - case wxLOCALE_DECIMAL_POINT: - return wxString(locale_info->decimal_point, - *wxConvCurrent); - default: - return wxEmptyString; - } - case wxLOCALE_CAT_MONEY: - switch (index) + case wxLOCALE_THOUSANDS_SEP: + if ( cat == wxLOCALE_CAT_NUMBER ) + return lc->thousands_sep; + else if ( cat == wxLOCALE_CAT_MONEY ) + return lc->mon_thousands_sep; + + wxFAIL_MSG( "invalid wxLocaleCategory" ); + break; + + + case wxLOCALE_DECIMAL_POINT: + if ( cat == wxLOCALE_CAT_NUMBER ) + return lc->decimal_point; + else if ( cat == wxLOCALE_CAT_MONEY ) + return lc->mon_decimal_point; + + wxFAIL_MSG( "invalid wxLocaleCategory" ); + break; + + case wxLOCALE_SHORT_DATE_FMT: + case wxLOCALE_LONG_DATE_FMT: + case wxLOCALE_DATE_TIME_FMT: + case wxLOCALE_TIME_FMT: + if ( cat != wxLOCALE_CAT_DATE && cat != wxLOCALE_CAT_DEFAULT ) { - case wxLOCALE_THOUSANDS_SEP: - return wxString(locale_info->mon_thousands_sep, - *wxConvCurrent); - case wxLOCALE_DECIMAL_POINT: - return wxString(locale_info->mon_decimal_point, - *wxConvCurrent); - default: - return wxEmptyString; + wxFAIL_MSG( "invalid wxLocaleCategory" ); + break; } + + return GetDateFormatFromLangInfo(index); + + default: - return wxEmptyString; + wxFAIL_MSG( "unknown wxLocaleInfo value" ); } + + return wxString(); } -#endif // __WXMSW__/!__WXMSW__ +#endif // platform // ---------------------------------------------------------------------------- // global functions and variables @@ -2930,14 +1780,14 @@ static wxLocale *g_pLocale = NULL; wxLocale *wxGetLocale() { - return g_pLocale; + return g_pLocale; } wxLocale *wxSetLocale(wxLocale *pLocale) { - wxLocale *pOld = g_pLocale; - g_pLocale = pLocale; - return pOld; + wxLocale *pOld = g_pLocale; + g_pLocale = pLocale; + return pOld; } @@ -2951,758 +1801,18 @@ class wxLocaleModule: public wxModule DECLARE_DYNAMIC_CLASS(wxLocaleModule) public: wxLocaleModule() {} - bool OnInit() { return true; } - void OnExit() { wxLocale::DestroyLanguagesDB(); } -}; - -IMPLEMENT_DYNAMIC_CLASS(wxLocaleModule, wxModule) - - - -// ---------------------------------------------------------------------------- -// default languages table & initialization -// ---------------------------------------------------------------------------- - - - -// --- --- --- generated code begins here --- --- --- - -// This table is generated by misc/languages/genlang.py -// When making changes, please put them into misc/languages/langtabl.txt - -#if !defined(__WIN32__) || defined(__WXMICROWIN__) - -#define SETWINLANG(info,lang,sublang) - -#else - -#define SETWINLANG(info,lang,sublang) \ - info.WinLang = lang, info.WinSublang = sublang; - -#ifndef LANG_AFRIKAANS -#define LANG_AFRIKAANS (0) -#endif -#ifndef LANG_ALBANIAN -#define LANG_ALBANIAN (0) -#endif -#ifndef LANG_ARABIC -#define LANG_ARABIC (0) -#endif -#ifndef LANG_ARMENIAN -#define LANG_ARMENIAN (0) -#endif -#ifndef LANG_ASSAMESE -#define LANG_ASSAMESE (0) -#endif -#ifndef LANG_AZERI -#define LANG_AZERI (0) -#endif -#ifndef LANG_BASQUE -#define LANG_BASQUE (0) -#endif -#ifndef LANG_BELARUSIAN -#define LANG_BELARUSIAN (0) -#endif -#ifndef LANG_BENGALI -#define LANG_BENGALI (0) -#endif -#ifndef LANG_BULGARIAN -#define LANG_BULGARIAN (0) -#endif -#ifndef LANG_CATALAN -#define LANG_CATALAN (0) -#endif -#ifndef LANG_CHINESE -#define LANG_CHINESE (0) -#endif -#ifndef LANG_CROATIAN -#define LANG_CROATIAN (0) -#endif -#ifndef LANG_CZECH -#define LANG_CZECH (0) -#endif -#ifndef LANG_DANISH -#define LANG_DANISH (0) -#endif -#ifndef LANG_DUTCH -#define LANG_DUTCH (0) -#endif -#ifndef LANG_ENGLISH -#define LANG_ENGLISH (0) -#endif -#ifndef LANG_ESTONIAN -#define LANG_ESTONIAN (0) -#endif -#ifndef LANG_FAEROESE -#define LANG_FAEROESE (0) -#endif -#ifndef LANG_FARSI -#define LANG_FARSI (0) -#endif -#ifndef LANG_FINNISH -#define LANG_FINNISH (0) -#endif -#ifndef LANG_FRENCH -#define LANG_FRENCH (0) -#endif -#ifndef LANG_GEORGIAN -#define LANG_GEORGIAN (0) -#endif -#ifndef LANG_GERMAN -#define LANG_GERMAN (0) -#endif -#ifndef LANG_GREEK -#define LANG_GREEK (0) -#endif -#ifndef LANG_GUJARATI -#define LANG_GUJARATI (0) -#endif -#ifndef LANG_HEBREW -#define LANG_HEBREW (0) -#endif -#ifndef LANG_HINDI -#define LANG_HINDI (0) -#endif -#ifndef LANG_HUNGARIAN -#define LANG_HUNGARIAN (0) -#endif -#ifndef LANG_ICELANDIC -#define LANG_ICELANDIC (0) -#endif -#ifndef LANG_INDONESIAN -#define LANG_INDONESIAN (0) -#endif -#ifndef LANG_ITALIAN -#define LANG_ITALIAN (0) -#endif -#ifndef LANG_JAPANESE -#define LANG_JAPANESE (0) -#endif -#ifndef LANG_KANNADA -#define LANG_KANNADA (0) -#endif -#ifndef LANG_KASHMIRI -#define LANG_KASHMIRI (0) -#endif -#ifndef LANG_KAZAK -#define LANG_KAZAK (0) -#endif -#ifndef LANG_KONKANI -#define LANG_KONKANI (0) -#endif -#ifndef LANG_KOREAN -#define LANG_KOREAN (0) -#endif -#ifndef LANG_LATVIAN -#define LANG_LATVIAN (0) -#endif -#ifndef LANG_LITHUANIAN -#define LANG_LITHUANIAN (0) -#endif -#ifndef LANG_MACEDONIAN -#define LANG_MACEDONIAN (0) -#endif -#ifndef LANG_MALAY -#define LANG_MALAY (0) -#endif -#ifndef LANG_MALAYALAM -#define LANG_MALAYALAM (0) -#endif -#ifndef LANG_MANIPURI -#define LANG_MANIPURI (0) -#endif -#ifndef LANG_MARATHI -#define LANG_MARATHI (0) -#endif -#ifndef LANG_NEPALI -#define LANG_NEPALI (0) -#endif -#ifndef LANG_NORWEGIAN -#define LANG_NORWEGIAN (0) -#endif -#ifndef LANG_ORIYA -#define LANG_ORIYA (0) -#endif -#ifndef LANG_POLISH -#define LANG_POLISH (0) -#endif -#ifndef LANG_PORTUGUESE -#define LANG_PORTUGUESE (0) -#endif -#ifndef LANG_PUNJABI -#define LANG_PUNJABI (0) -#endif -#ifndef LANG_ROMANIAN -#define LANG_ROMANIAN (0) -#endif -#ifndef LANG_RUSSIAN -#define LANG_RUSSIAN (0) -#endif -#ifndef LANG_SANSKRIT -#define LANG_SANSKRIT (0) -#endif -#ifndef LANG_SERBIAN -#define LANG_SERBIAN (0) -#endif -#ifndef LANG_SINDHI -#define LANG_SINDHI (0) -#endif -#ifndef LANG_SLOVAK -#define LANG_SLOVAK (0) -#endif -#ifndef LANG_SLOVENIAN -#define LANG_SLOVENIAN (0) -#endif -#ifndef LANG_SPANISH -#define LANG_SPANISH (0) -#endif -#ifndef LANG_SWAHILI -#define LANG_SWAHILI (0) -#endif -#ifndef LANG_SWEDISH -#define LANG_SWEDISH (0) -#endif -#ifndef LANG_TAMIL -#define LANG_TAMIL (0) -#endif -#ifndef LANG_TATAR -#define LANG_TATAR (0) -#endif -#ifndef LANG_TELUGU -#define LANG_TELUGU (0) -#endif -#ifndef LANG_THAI -#define LANG_THAI (0) -#endif -#ifndef LANG_TURKISH -#define LANG_TURKISH (0) -#endif -#ifndef LANG_UKRAINIAN -#define LANG_UKRAINIAN (0) -#endif -#ifndef LANG_URDU -#define LANG_URDU (0) -#endif -#ifndef LANG_UZBEK -#define LANG_UZBEK (0) -#endif -#ifndef LANG_VIETNAMESE -#define LANG_VIETNAMESE (0) -#endif -#ifndef SUBLANG_ARABIC_ALGERIA -#define SUBLANG_ARABIC_ALGERIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_BAHRAIN -#define SUBLANG_ARABIC_BAHRAIN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_EGYPT -#define SUBLANG_ARABIC_EGYPT SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_IRAQ -#define SUBLANG_ARABIC_IRAQ SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_JORDAN -#define SUBLANG_ARABIC_JORDAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_KUWAIT -#define SUBLANG_ARABIC_KUWAIT SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_LEBANON -#define SUBLANG_ARABIC_LEBANON SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_LIBYA -#define SUBLANG_ARABIC_LIBYA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_MOROCCO -#define SUBLANG_ARABIC_MOROCCO SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_OMAN -#define SUBLANG_ARABIC_OMAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_QATAR -#define SUBLANG_ARABIC_QATAR SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_SAUDI_ARABIA -#define SUBLANG_ARABIC_SAUDI_ARABIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_SYRIA -#define SUBLANG_ARABIC_SYRIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_TUNISIA -#define SUBLANG_ARABIC_TUNISIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_UAE -#define SUBLANG_ARABIC_UAE SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ARABIC_YEMEN -#define SUBLANG_ARABIC_YEMEN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_AZERI_CYRILLIC -#define SUBLANG_AZERI_CYRILLIC SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_AZERI_LATIN -#define SUBLANG_AZERI_LATIN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_CHINESE_SIMPLIFIED -#define SUBLANG_CHINESE_SIMPLIFIED SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_CHINESE_TRADITIONAL -#define SUBLANG_CHINESE_TRADITIONAL SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_CHINESE_HONGKONG -#define SUBLANG_CHINESE_HONGKONG SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_CHINESE_MACAU -#define SUBLANG_CHINESE_MACAU SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_CHINESE_SINGAPORE -#define SUBLANG_CHINESE_SINGAPORE SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_DUTCH -#define SUBLANG_DUTCH SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_DUTCH_BELGIAN -#define SUBLANG_DUTCH_BELGIAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_UK -#define SUBLANG_ENGLISH_UK SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_US -#define SUBLANG_ENGLISH_US SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_AUS -#define SUBLANG_ENGLISH_AUS SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_BELIZE -#define SUBLANG_ENGLISH_BELIZE SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_CAN -#define SUBLANG_ENGLISH_CAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_CARIBBEAN -#define SUBLANG_ENGLISH_CARIBBEAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_EIRE -#define SUBLANG_ENGLISH_EIRE SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_JAMAICA -#define SUBLANG_ENGLISH_JAMAICA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_NZ -#define SUBLANG_ENGLISH_NZ SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_PHILIPPINES -#define SUBLANG_ENGLISH_PHILIPPINES SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_SOUTH_AFRICA -#define SUBLANG_ENGLISH_SOUTH_AFRICA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_TRINIDAD -#define SUBLANG_ENGLISH_TRINIDAD SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ENGLISH_ZIMBABWE -#define SUBLANG_ENGLISH_ZIMBABWE SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_FRENCH -#define SUBLANG_FRENCH SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_FRENCH_BELGIAN -#define SUBLANG_FRENCH_BELGIAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_FRENCH_CANADIAN -#define SUBLANG_FRENCH_CANADIAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_FRENCH_LUXEMBOURG -#define SUBLANG_FRENCH_LUXEMBOURG SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_FRENCH_MONACO -#define SUBLANG_FRENCH_MONACO SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_FRENCH_SWISS -#define SUBLANG_FRENCH_SWISS SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_GERMAN -#define SUBLANG_GERMAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_GERMAN_AUSTRIAN -#define SUBLANG_GERMAN_AUSTRIAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_GERMAN_LIECHTENSTEIN -#define SUBLANG_GERMAN_LIECHTENSTEIN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_GERMAN_LUXEMBOURG -#define SUBLANG_GERMAN_LUXEMBOURG SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_GERMAN_SWISS -#define SUBLANG_GERMAN_SWISS SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ITALIAN -#define SUBLANG_ITALIAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_ITALIAN_SWISS -#define SUBLANG_ITALIAN_SWISS SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_KASHMIRI_INDIA -#define SUBLANG_KASHMIRI_INDIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_KOREAN -#define SUBLANG_KOREAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_LITHUANIAN -#define SUBLANG_LITHUANIAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM -#define SUBLANG_MALAY_BRUNEI_DARUSSALAM SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_MALAY_MALAYSIA -#define SUBLANG_MALAY_MALAYSIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_NEPALI_INDIA -#define SUBLANG_NEPALI_INDIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_NORWEGIAN_BOKMAL -#define SUBLANG_NORWEGIAN_BOKMAL SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_NORWEGIAN_NYNORSK -#define SUBLANG_NORWEGIAN_NYNORSK SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_PORTUGUESE -#define SUBLANG_PORTUGUESE SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_PORTUGUESE_BRAZILIAN -#define SUBLANG_PORTUGUESE_BRAZILIAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SERBIAN_CYRILLIC -#define SUBLANG_SERBIAN_CYRILLIC SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SERBIAN_LATIN -#define SUBLANG_SERBIAN_LATIN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH -#define SUBLANG_SPANISH SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_ARGENTINA -#define SUBLANG_SPANISH_ARGENTINA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_BOLIVIA -#define SUBLANG_SPANISH_BOLIVIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_CHILE -#define SUBLANG_SPANISH_CHILE SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_COLOMBIA -#define SUBLANG_SPANISH_COLOMBIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_COSTA_RICA -#define SUBLANG_SPANISH_COSTA_RICA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC -#define SUBLANG_SPANISH_DOMINICAN_REPUBLIC SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_ECUADOR -#define SUBLANG_SPANISH_ECUADOR SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_EL_SALVADOR -#define SUBLANG_SPANISH_EL_SALVADOR SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_GUATEMALA -#define SUBLANG_SPANISH_GUATEMALA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_HONDURAS -#define SUBLANG_SPANISH_HONDURAS SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_MEXICAN -#define SUBLANG_SPANISH_MEXICAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_MODERN -#define SUBLANG_SPANISH_MODERN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_NICARAGUA -#define SUBLANG_SPANISH_NICARAGUA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_PANAMA -#define SUBLANG_SPANISH_PANAMA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_PARAGUAY -#define SUBLANG_SPANISH_PARAGUAY SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_PERU -#define SUBLANG_SPANISH_PERU SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_PUERTO_RICO -#define SUBLANG_SPANISH_PUERTO_RICO SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_URUGUAY -#define SUBLANG_SPANISH_URUGUAY SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SPANISH_VENEZUELA -#define SUBLANG_SPANISH_VENEZUELA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SWEDISH -#define SUBLANG_SWEDISH SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_SWEDISH_FINLAND -#define SUBLANG_SWEDISH_FINLAND SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_URDU_INDIA -#define SUBLANG_URDU_INDIA SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_URDU_PAKISTAN -#define SUBLANG_URDU_PAKISTAN SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_UZBEK_CYRILLIC -#define SUBLANG_UZBEK_CYRILLIC SUBLANG_DEFAULT -#endif -#ifndef SUBLANG_UZBEK_LATIN -#define SUBLANG_UZBEK_LATIN SUBLANG_DEFAULT -#endif - - -#endif // __WIN32__ -#define LNG(wxlang, canonical, winlang, winsublang, layout, desc) \ - info.Language = wxlang; \ - info.CanonicalName = wxT(canonical); \ - info.LayoutDirection = layout; \ - info.Description = wxT(desc); \ - SETWINLANG(info, winlang, winsublang) \ - AddLanguage(info); + bool OnInit() + { + return true; + } -void wxLocale::InitLanguagesDB() -{ - wxLanguageInfo info; - wxStringTokenizer tkn; - - LNG(wxLANGUAGE_ABKHAZIAN, "ab" , 0 , 0 , wxLayout_LeftToRight, "Abkhazian") - LNG(wxLANGUAGE_AFAR, "aa" , 0 , 0 , wxLayout_LeftToRight, "Afar") - LNG(wxLANGUAGE_AFRIKAANS, "af_ZA", LANG_AFRIKAANS , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Afrikaans") - LNG(wxLANGUAGE_ALBANIAN, "sq_AL", LANG_ALBANIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Albanian") - LNG(wxLANGUAGE_AMHARIC, "am" , 0 , 0 , wxLayout_LeftToRight, "Amharic") - LNG(wxLANGUAGE_ARABIC, "ar" , LANG_ARABIC , SUBLANG_DEFAULT , wxLayout_RightToLeft, "Arabic") - LNG(wxLANGUAGE_ARABIC_ALGERIA, "ar_DZ", LANG_ARABIC , SUBLANG_ARABIC_ALGERIA , wxLayout_RightToLeft, "Arabic (Algeria)") - LNG(wxLANGUAGE_ARABIC_BAHRAIN, "ar_BH", LANG_ARABIC , SUBLANG_ARABIC_BAHRAIN , wxLayout_RightToLeft, "Arabic (Bahrain)") - LNG(wxLANGUAGE_ARABIC_EGYPT, "ar_EG", LANG_ARABIC , SUBLANG_ARABIC_EGYPT , wxLayout_RightToLeft, "Arabic (Egypt)") - LNG(wxLANGUAGE_ARABIC_IRAQ, "ar_IQ", LANG_ARABIC , SUBLANG_ARABIC_IRAQ , wxLayout_RightToLeft, "Arabic (Iraq)") - LNG(wxLANGUAGE_ARABIC_JORDAN, "ar_JO", LANG_ARABIC , SUBLANG_ARABIC_JORDAN , wxLayout_RightToLeft, "Arabic (Jordan)") - LNG(wxLANGUAGE_ARABIC_KUWAIT, "ar_KW", LANG_ARABIC , SUBLANG_ARABIC_KUWAIT , wxLayout_RightToLeft, "Arabic (Kuwait)") - LNG(wxLANGUAGE_ARABIC_LEBANON, "ar_LB", LANG_ARABIC , SUBLANG_ARABIC_LEBANON , wxLayout_RightToLeft, "Arabic (Lebanon)") - LNG(wxLANGUAGE_ARABIC_LIBYA, "ar_LY", LANG_ARABIC , SUBLANG_ARABIC_LIBYA , wxLayout_RightToLeft, "Arabic (Libya)") - LNG(wxLANGUAGE_ARABIC_MOROCCO, "ar_MA", LANG_ARABIC , SUBLANG_ARABIC_MOROCCO , wxLayout_RightToLeft, "Arabic (Morocco)") - LNG(wxLANGUAGE_ARABIC_OMAN, "ar_OM", LANG_ARABIC , SUBLANG_ARABIC_OMAN , wxLayout_RightToLeft, "Arabic (Oman)") - LNG(wxLANGUAGE_ARABIC_QATAR, "ar_QA", LANG_ARABIC , SUBLANG_ARABIC_QATAR , wxLayout_RightToLeft, "Arabic (Qatar)") - LNG(wxLANGUAGE_ARABIC_SAUDI_ARABIA, "ar_SA", LANG_ARABIC , SUBLANG_ARABIC_SAUDI_ARABIA , wxLayout_RightToLeft, "Arabic (Saudi Arabia)") - LNG(wxLANGUAGE_ARABIC_SUDAN, "ar_SD", 0 , 0 , wxLayout_RightToLeft, "Arabic (Sudan)") - LNG(wxLANGUAGE_ARABIC_SYRIA, "ar_SY", LANG_ARABIC , SUBLANG_ARABIC_SYRIA , wxLayout_RightToLeft, "Arabic (Syria)") - LNG(wxLANGUAGE_ARABIC_TUNISIA, "ar_TN", LANG_ARABIC , SUBLANG_ARABIC_TUNISIA , wxLayout_RightToLeft, "Arabic (Tunisia)") - LNG(wxLANGUAGE_ARABIC_UAE, "ar_AE", LANG_ARABIC , SUBLANG_ARABIC_UAE , wxLayout_RightToLeft, "Arabic (Uae)") - LNG(wxLANGUAGE_ARABIC_YEMEN, "ar_YE", LANG_ARABIC , SUBLANG_ARABIC_YEMEN , wxLayout_RightToLeft, "Arabic (Yemen)") - LNG(wxLANGUAGE_ARMENIAN, "hy" , LANG_ARMENIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Armenian") - LNG(wxLANGUAGE_ASSAMESE, "as" , LANG_ASSAMESE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Assamese") - LNG(wxLANGUAGE_AYMARA, "ay" , 0 , 0 , wxLayout_LeftToRight, "Aymara") - LNG(wxLANGUAGE_AZERI, "az" , LANG_AZERI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Azeri") - LNG(wxLANGUAGE_AZERI_CYRILLIC, "az" , LANG_AZERI , SUBLANG_AZERI_CYRILLIC , wxLayout_LeftToRight, "Azeri (Cyrillic)") - LNG(wxLANGUAGE_AZERI_LATIN, "az" , LANG_AZERI , SUBLANG_AZERI_LATIN , wxLayout_LeftToRight, "Azeri (Latin)") - LNG(wxLANGUAGE_BASHKIR, "ba" , 0 , 0 , wxLayout_LeftToRight, "Bashkir") - LNG(wxLANGUAGE_BASQUE, "eu_ES", LANG_BASQUE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Basque") - LNG(wxLANGUAGE_BELARUSIAN, "be_BY", LANG_BELARUSIAN, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Belarusian") - LNG(wxLANGUAGE_BENGALI, "bn" , LANG_BENGALI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Bengali") - LNG(wxLANGUAGE_BHUTANI, "dz" , 0 , 0 , wxLayout_LeftToRight, "Bhutani") - LNG(wxLANGUAGE_BIHARI, "bh" , 0 , 0 , wxLayout_LeftToRight, "Bihari") - LNG(wxLANGUAGE_BISLAMA, "bi" , 0 , 0 , wxLayout_LeftToRight, "Bislama") - LNG(wxLANGUAGE_BRETON, "br" , 0 , 0 , wxLayout_LeftToRight, "Breton") - LNG(wxLANGUAGE_BULGARIAN, "bg_BG", LANG_BULGARIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Bulgarian") - LNG(wxLANGUAGE_BURMESE, "my" , 0 , 0 , wxLayout_LeftToRight, "Burmese") - LNG(wxLANGUAGE_CAMBODIAN, "km" , 0 , 0 , wxLayout_LeftToRight, "Cambodian") - LNG(wxLANGUAGE_CATALAN, "ca_ES", LANG_CATALAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Catalan") - LNG(wxLANGUAGE_CHINESE, "zh_TW", LANG_CHINESE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Chinese") - LNG(wxLANGUAGE_CHINESE_SIMPLIFIED, "zh_CN", LANG_CHINESE , SUBLANG_CHINESE_SIMPLIFIED , wxLayout_LeftToRight, "Chinese (Simplified)") - LNG(wxLANGUAGE_CHINESE_TRADITIONAL, "zh_TW", LANG_CHINESE , SUBLANG_CHINESE_TRADITIONAL , wxLayout_LeftToRight, "Chinese (Traditional)") - LNG(wxLANGUAGE_CHINESE_HONGKONG, "zh_HK", LANG_CHINESE , SUBLANG_CHINESE_HONGKONG , wxLayout_LeftToRight, "Chinese (Hongkong)") - LNG(wxLANGUAGE_CHINESE_MACAU, "zh_MO", LANG_CHINESE , SUBLANG_CHINESE_MACAU , wxLayout_LeftToRight, "Chinese (Macau)") - LNG(wxLANGUAGE_CHINESE_SINGAPORE, "zh_SG", LANG_CHINESE , SUBLANG_CHINESE_SINGAPORE , wxLayout_LeftToRight, "Chinese (Singapore)") - LNG(wxLANGUAGE_CHINESE_TAIWAN, "zh_TW", LANG_CHINESE , SUBLANG_CHINESE_TRADITIONAL , wxLayout_LeftToRight, "Chinese (Taiwan)") - LNG(wxLANGUAGE_CORSICAN, "co" , 0 , 0 , wxLayout_LeftToRight, "Corsican") - LNG(wxLANGUAGE_CROATIAN, "hr_HR", LANG_CROATIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Croatian") - LNG(wxLANGUAGE_CZECH, "cs_CZ", LANG_CZECH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Czech") - LNG(wxLANGUAGE_DANISH, "da_DK", LANG_DANISH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Danish") - LNG(wxLANGUAGE_DUTCH, "nl_NL", LANG_DUTCH , SUBLANG_DUTCH , wxLayout_LeftToRight, "Dutch") - LNG(wxLANGUAGE_DUTCH_BELGIAN, "nl_BE", LANG_DUTCH , SUBLANG_DUTCH_BELGIAN , wxLayout_LeftToRight, "Dutch (Belgian)") - LNG(wxLANGUAGE_ENGLISH, "en_GB", LANG_ENGLISH , SUBLANG_ENGLISH_UK , wxLayout_LeftToRight, "English") - LNG(wxLANGUAGE_ENGLISH_UK, "en_GB", LANG_ENGLISH , SUBLANG_ENGLISH_UK , wxLayout_LeftToRight, "English (U.K.)") - LNG(wxLANGUAGE_ENGLISH_US, "en_US", LANG_ENGLISH , SUBLANG_ENGLISH_US , wxLayout_LeftToRight, "English (U.S.)") - LNG(wxLANGUAGE_ENGLISH_AUSTRALIA, "en_AU", LANG_ENGLISH , SUBLANG_ENGLISH_AUS , wxLayout_LeftToRight, "English (Australia)") - LNG(wxLANGUAGE_ENGLISH_BELIZE, "en_BZ", LANG_ENGLISH , SUBLANG_ENGLISH_BELIZE , wxLayout_LeftToRight, "English (Belize)") - LNG(wxLANGUAGE_ENGLISH_BOTSWANA, "en_BW", 0 , 0 , wxLayout_LeftToRight, "English (Botswana)") - LNG(wxLANGUAGE_ENGLISH_CANADA, "en_CA", LANG_ENGLISH , SUBLANG_ENGLISH_CAN , wxLayout_LeftToRight, "English (Canada)") - LNG(wxLANGUAGE_ENGLISH_CARIBBEAN, "en_CB", LANG_ENGLISH , SUBLANG_ENGLISH_CARIBBEAN , wxLayout_LeftToRight, "English (Caribbean)") - LNG(wxLANGUAGE_ENGLISH_DENMARK, "en_DK", 0 , 0 , wxLayout_LeftToRight, "English (Denmark)") - LNG(wxLANGUAGE_ENGLISH_EIRE, "en_IE", LANG_ENGLISH , SUBLANG_ENGLISH_EIRE , wxLayout_LeftToRight, "English (Eire)") - LNG(wxLANGUAGE_ENGLISH_JAMAICA, "en_JM", LANG_ENGLISH , SUBLANG_ENGLISH_JAMAICA , wxLayout_LeftToRight, "English (Jamaica)") - LNG(wxLANGUAGE_ENGLISH_NEW_ZEALAND, "en_NZ", LANG_ENGLISH , SUBLANG_ENGLISH_NZ , wxLayout_LeftToRight, "English (New Zealand)") - LNG(wxLANGUAGE_ENGLISH_PHILIPPINES, "en_PH", LANG_ENGLISH , SUBLANG_ENGLISH_PHILIPPINES , wxLayout_LeftToRight, "English (Philippines)") - LNG(wxLANGUAGE_ENGLISH_SOUTH_AFRICA, "en_ZA", LANG_ENGLISH , SUBLANG_ENGLISH_SOUTH_AFRICA , wxLayout_LeftToRight, "English (South Africa)") - LNG(wxLANGUAGE_ENGLISH_TRINIDAD, "en_TT", LANG_ENGLISH , SUBLANG_ENGLISH_TRINIDAD , wxLayout_LeftToRight, "English (Trinidad)") - LNG(wxLANGUAGE_ENGLISH_ZIMBABWE, "en_ZW", LANG_ENGLISH , SUBLANG_ENGLISH_ZIMBABWE , wxLayout_LeftToRight, "English (Zimbabwe)") - LNG(wxLANGUAGE_ESPERANTO, "eo" , 0 , 0 , wxLayout_LeftToRight, "Esperanto") - LNG(wxLANGUAGE_ESTONIAN, "et_EE", LANG_ESTONIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Estonian") - LNG(wxLANGUAGE_FAEROESE, "fo_FO", LANG_FAEROESE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Faeroese") - LNG(wxLANGUAGE_FARSI, "fa_IR", LANG_FARSI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Farsi") - LNG(wxLANGUAGE_FIJI, "fj" , 0 , 0 , wxLayout_LeftToRight, "Fiji") - LNG(wxLANGUAGE_FINNISH, "fi_FI", LANG_FINNISH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Finnish") - LNG(wxLANGUAGE_FRENCH, "fr_FR", LANG_FRENCH , SUBLANG_FRENCH , wxLayout_LeftToRight, "French") - LNG(wxLANGUAGE_FRENCH_BELGIAN, "fr_BE", LANG_FRENCH , SUBLANG_FRENCH_BELGIAN , wxLayout_LeftToRight, "French (Belgian)") - LNG(wxLANGUAGE_FRENCH_CANADIAN, "fr_CA", LANG_FRENCH , SUBLANG_FRENCH_CANADIAN , wxLayout_LeftToRight, "French (Canadian)") - LNG(wxLANGUAGE_FRENCH_LUXEMBOURG, "fr_LU", LANG_FRENCH , SUBLANG_FRENCH_LUXEMBOURG , wxLayout_LeftToRight, "French (Luxembourg)") - LNG(wxLANGUAGE_FRENCH_MONACO, "fr_MC", LANG_FRENCH , SUBLANG_FRENCH_MONACO , wxLayout_LeftToRight, "French (Monaco)") - LNG(wxLANGUAGE_FRENCH_SWISS, "fr_CH", LANG_FRENCH , SUBLANG_FRENCH_SWISS , wxLayout_LeftToRight, "French (Swiss)") - LNG(wxLANGUAGE_FRISIAN, "fy" , 0 , 0 , wxLayout_LeftToRight, "Frisian") - LNG(wxLANGUAGE_GALICIAN, "gl_ES", 0 , 0 , wxLayout_LeftToRight, "Galician") - LNG(wxLANGUAGE_GEORGIAN, "ka" , LANG_GEORGIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Georgian") - LNG(wxLANGUAGE_GERMAN, "de_DE", LANG_GERMAN , SUBLANG_GERMAN , wxLayout_LeftToRight, "German") - LNG(wxLANGUAGE_GERMAN_AUSTRIAN, "de_AT", LANG_GERMAN , SUBLANG_GERMAN_AUSTRIAN , wxLayout_LeftToRight, "German (Austrian)") - LNG(wxLANGUAGE_GERMAN_BELGIUM, "de_BE", 0 , 0 , wxLayout_LeftToRight, "German (Belgium)") - LNG(wxLANGUAGE_GERMAN_LIECHTENSTEIN, "de_LI", LANG_GERMAN , SUBLANG_GERMAN_LIECHTENSTEIN , wxLayout_LeftToRight, "German (Liechtenstein)") - LNG(wxLANGUAGE_GERMAN_LUXEMBOURG, "de_LU", LANG_GERMAN , SUBLANG_GERMAN_LUXEMBOURG , wxLayout_LeftToRight, "German (Luxembourg)") - LNG(wxLANGUAGE_GERMAN_SWISS, "de_CH", LANG_GERMAN , SUBLANG_GERMAN_SWISS , wxLayout_LeftToRight, "German (Swiss)") - LNG(wxLANGUAGE_GREEK, "el_GR", LANG_GREEK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Greek") - LNG(wxLANGUAGE_GREENLANDIC, "kl_GL", 0 , 0 , wxLayout_LeftToRight, "Greenlandic") - LNG(wxLANGUAGE_GUARANI, "gn" , 0 , 0 , wxLayout_LeftToRight, "Guarani") - LNG(wxLANGUAGE_GUJARATI, "gu" , LANG_GUJARATI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Gujarati") - LNG(wxLANGUAGE_HAUSA, "ha" , 0 , 0 , wxLayout_LeftToRight, "Hausa") - LNG(wxLANGUAGE_HEBREW, "he_IL", LANG_HEBREW , SUBLANG_DEFAULT , wxLayout_RightToLeft, "Hebrew") - LNG(wxLANGUAGE_HINDI, "hi_IN", LANG_HINDI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Hindi") - LNG(wxLANGUAGE_HUNGARIAN, "hu_HU", LANG_HUNGARIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Hungarian") - LNG(wxLANGUAGE_ICELANDIC, "is_IS", LANG_ICELANDIC , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Icelandic") - LNG(wxLANGUAGE_INDONESIAN, "id_ID", LANG_INDONESIAN, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Indonesian") - LNG(wxLANGUAGE_INTERLINGUA, "ia" , 0 , 0 , wxLayout_LeftToRight, "Interlingua") - LNG(wxLANGUAGE_INTERLINGUE, "ie" , 0 , 0 , wxLayout_LeftToRight, "Interlingue") - LNG(wxLANGUAGE_INUKTITUT, "iu" , 0 , 0 , wxLayout_LeftToRight, "Inuktitut") - LNG(wxLANGUAGE_INUPIAK, "ik" , 0 , 0 , wxLayout_LeftToRight, "Inupiak") - LNG(wxLANGUAGE_IRISH, "ga_IE", 0 , 0 , wxLayout_LeftToRight, "Irish") - LNG(wxLANGUAGE_ITALIAN, "it_IT", LANG_ITALIAN , SUBLANG_ITALIAN , wxLayout_LeftToRight, "Italian") - LNG(wxLANGUAGE_ITALIAN_SWISS, "it_CH", LANG_ITALIAN , SUBLANG_ITALIAN_SWISS , wxLayout_LeftToRight, "Italian (Swiss)") - LNG(wxLANGUAGE_JAPANESE, "ja_JP", LANG_JAPANESE , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Japanese") - LNG(wxLANGUAGE_JAVANESE, "jw" , 0 , 0 , wxLayout_LeftToRight, "Javanese") - LNG(wxLANGUAGE_KANNADA, "kn" , LANG_KANNADA , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Kannada") - LNG(wxLANGUAGE_KASHMIRI, "ks" , LANG_KASHMIRI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Kashmiri") - LNG(wxLANGUAGE_KASHMIRI_INDIA, "ks_IN", LANG_KASHMIRI , SUBLANG_KASHMIRI_INDIA , wxLayout_LeftToRight, "Kashmiri (India)") - LNG(wxLANGUAGE_KAZAKH, "kk" , LANG_KAZAK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Kazakh") - LNG(wxLANGUAGE_KERNEWEK, "kw_GB", 0 , 0 , wxLayout_LeftToRight, "Kernewek") - LNG(wxLANGUAGE_KINYARWANDA, "rw" , 0 , 0 , wxLayout_LeftToRight, "Kinyarwanda") - LNG(wxLANGUAGE_KIRGHIZ, "ky" , 0 , 0 , wxLayout_LeftToRight, "Kirghiz") - LNG(wxLANGUAGE_KIRUNDI, "rn" , 0 , 0 , wxLayout_LeftToRight, "Kirundi") - LNG(wxLANGUAGE_KONKANI, "" , LANG_KONKANI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Konkani") - LNG(wxLANGUAGE_KOREAN, "ko_KR", LANG_KOREAN , SUBLANG_KOREAN , wxLayout_LeftToRight, "Korean") - LNG(wxLANGUAGE_KURDISH, "ku" , 0 , 0 , wxLayout_LeftToRight, "Kurdish") - LNG(wxLANGUAGE_LAOTHIAN, "lo" , 0 , 0 , wxLayout_LeftToRight, "Laothian") - LNG(wxLANGUAGE_LATIN, "la" , 0 , 0 , wxLayout_LeftToRight, "Latin") - LNG(wxLANGUAGE_LATVIAN, "lv_LV", LANG_LATVIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Latvian") - LNG(wxLANGUAGE_LINGALA, "ln" , 0 , 0 , wxLayout_LeftToRight, "Lingala") - LNG(wxLANGUAGE_LITHUANIAN, "lt_LT", LANG_LITHUANIAN, SUBLANG_LITHUANIAN , wxLayout_LeftToRight, "Lithuanian") - LNG(wxLANGUAGE_MACEDONIAN, "mk_MK", LANG_MACEDONIAN, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Macedonian") - LNG(wxLANGUAGE_MALAGASY, "mg" , 0 , 0 , wxLayout_LeftToRight, "Malagasy") - LNG(wxLANGUAGE_MALAY, "ms_MY", LANG_MALAY , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Malay") - LNG(wxLANGUAGE_MALAYALAM, "ml" , LANG_MALAYALAM , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Malayalam") - LNG(wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM, "ms_BN", LANG_MALAY , SUBLANG_MALAY_BRUNEI_DARUSSALAM , wxLayout_LeftToRight, "Malay (Brunei Darussalam)") - LNG(wxLANGUAGE_MALAY_MALAYSIA, "ms_MY", LANG_MALAY , SUBLANG_MALAY_MALAYSIA , wxLayout_LeftToRight, "Malay (Malaysia)") - LNG(wxLANGUAGE_MALTESE, "mt_MT", 0 , 0 , wxLayout_LeftToRight, "Maltese") - LNG(wxLANGUAGE_MANIPURI, "" , LANG_MANIPURI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Manipuri") - LNG(wxLANGUAGE_MAORI, "mi" , 0 , 0 , wxLayout_LeftToRight, "Maori") - LNG(wxLANGUAGE_MARATHI, "mr_IN", LANG_MARATHI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Marathi") - LNG(wxLANGUAGE_MOLDAVIAN, "mo" , 0 , 0 , wxLayout_LeftToRight, "Moldavian") - LNG(wxLANGUAGE_MONGOLIAN, "mn" , 0 , 0 , wxLayout_LeftToRight, "Mongolian") - LNG(wxLANGUAGE_NAURU, "na" , 0 , 0 , wxLayout_LeftToRight, "Nauru") - LNG(wxLANGUAGE_NEPALI, "ne" , LANG_NEPALI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Nepali") - LNG(wxLANGUAGE_NEPALI_INDIA, "ne_IN", LANG_NEPALI , SUBLANG_NEPALI_INDIA , wxLayout_LeftToRight, "Nepali (India)") - LNG(wxLANGUAGE_NORWEGIAN_BOKMAL, "nb_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_BOKMAL , wxLayout_LeftToRight, "Norwegian (Bokmal)") - LNG(wxLANGUAGE_NORWEGIAN_NYNORSK, "nn_NO", LANG_NORWEGIAN , SUBLANG_NORWEGIAN_NYNORSK , wxLayout_LeftToRight, "Norwegian (Nynorsk)") - LNG(wxLANGUAGE_OCCITAN, "oc" , 0 , 0 , wxLayout_LeftToRight, "Occitan") - LNG(wxLANGUAGE_ORIYA, "or" , LANG_ORIYA , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Oriya") - LNG(wxLANGUAGE_OROMO, "om" , 0 , 0 , wxLayout_LeftToRight, "(Afan) Oromo") - LNG(wxLANGUAGE_PASHTO, "ps" , 0 , 0 , wxLayout_LeftToRight, "Pashto, Pushto") - LNG(wxLANGUAGE_POLISH, "pl_PL", LANG_POLISH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Polish") - LNG(wxLANGUAGE_PORTUGUESE, "pt_PT", LANG_PORTUGUESE, SUBLANG_PORTUGUESE , wxLayout_LeftToRight, "Portuguese") - LNG(wxLANGUAGE_PORTUGUESE_BRAZILIAN, "pt_BR", LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN , wxLayout_LeftToRight, "Portuguese (Brazilian)") - LNG(wxLANGUAGE_PUNJABI, "pa" , LANG_PUNJABI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Punjabi") - LNG(wxLANGUAGE_QUECHUA, "qu" , 0 , 0 , wxLayout_LeftToRight, "Quechua") - LNG(wxLANGUAGE_RHAETO_ROMANCE, "rm" , 0 , 0 , wxLayout_LeftToRight, "Rhaeto-Romance") - LNG(wxLANGUAGE_ROMANIAN, "ro_RO", LANG_ROMANIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Romanian") - LNG(wxLANGUAGE_RUSSIAN, "ru_RU", LANG_RUSSIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Russian") - LNG(wxLANGUAGE_RUSSIAN_UKRAINE, "ru_UA", 0 , 0 , wxLayout_LeftToRight, "Russian (Ukraine)") - LNG(wxLANGUAGE_SAMOAN, "sm" , 0 , 0 , wxLayout_LeftToRight, "Samoan") - LNG(wxLANGUAGE_SANGHO, "sg" , 0 , 0 , wxLayout_LeftToRight, "Sangho") - LNG(wxLANGUAGE_SANSKRIT, "sa" , LANG_SANSKRIT , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Sanskrit") - LNG(wxLANGUAGE_SCOTS_GAELIC, "gd" , 0 , 0 , wxLayout_LeftToRight, "Scots Gaelic") - LNG(wxLANGUAGE_SERBIAN_CYRILLIC, "sr_YU", LANG_SERBIAN , SUBLANG_SERBIAN_CYRILLIC , wxLayout_LeftToRight, "Serbian (Cyrillic)") - LNG(wxLANGUAGE_SERBIAN_LATIN, "sr_YU", LANG_SERBIAN , SUBLANG_SERBIAN_LATIN , wxLayout_LeftToRight, "Serbian (Latin)") - LNG(wxLANGUAGE_SERBO_CROATIAN, "sh" , 0 , 0 , wxLayout_LeftToRight, "Serbo-Croatian") - LNG(wxLANGUAGE_SESOTHO, "st" , 0 , 0 , wxLayout_LeftToRight, "Sesotho") - LNG(wxLANGUAGE_SETSWANA, "tn" , 0 , 0 , wxLayout_LeftToRight, "Setswana") - LNG(wxLANGUAGE_SHONA, "sn" , 0 , 0 , wxLayout_LeftToRight, "Shona") - LNG(wxLANGUAGE_SINDHI, "sd" , LANG_SINDHI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Sindhi") - LNG(wxLANGUAGE_SINHALESE, "si" , 0 , 0 , wxLayout_LeftToRight, "Sinhalese") - LNG(wxLANGUAGE_SISWATI, "ss" , 0 , 0 , wxLayout_LeftToRight, "Siswati") - LNG(wxLANGUAGE_SLOVAK, "sk_SK", LANG_SLOVAK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Slovak") - LNG(wxLANGUAGE_SLOVENIAN, "sl_SI", LANG_SLOVENIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Slovenian") - LNG(wxLANGUAGE_SOMALI, "so" , 0 , 0 , wxLayout_LeftToRight, "Somali") - LNG(wxLANGUAGE_SPANISH, "es_ES", LANG_SPANISH , SUBLANG_SPANISH , wxLayout_LeftToRight, "Spanish") - LNG(wxLANGUAGE_SPANISH_ARGENTINA, "es_AR", LANG_SPANISH , SUBLANG_SPANISH_ARGENTINA , wxLayout_LeftToRight, "Spanish (Argentina)") - LNG(wxLANGUAGE_SPANISH_BOLIVIA, "es_BO", LANG_SPANISH , SUBLANG_SPANISH_BOLIVIA , wxLayout_LeftToRight, "Spanish (Bolivia)") - LNG(wxLANGUAGE_SPANISH_CHILE, "es_CL", LANG_SPANISH , SUBLANG_SPANISH_CHILE , wxLayout_LeftToRight, "Spanish (Chile)") - LNG(wxLANGUAGE_SPANISH_COLOMBIA, "es_CO", LANG_SPANISH , SUBLANG_SPANISH_COLOMBIA , wxLayout_LeftToRight, "Spanish (Colombia)") - LNG(wxLANGUAGE_SPANISH_COSTA_RICA, "es_CR", LANG_SPANISH , SUBLANG_SPANISH_COSTA_RICA , wxLayout_LeftToRight, "Spanish (Costa Rica)") - LNG(wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC, "es_DO", LANG_SPANISH , SUBLANG_SPANISH_DOMINICAN_REPUBLIC, wxLayout_LeftToRight, "Spanish (Dominican republic)") - LNG(wxLANGUAGE_SPANISH_ECUADOR, "es_EC", LANG_SPANISH , SUBLANG_SPANISH_ECUADOR , wxLayout_LeftToRight, "Spanish (Ecuador)") - LNG(wxLANGUAGE_SPANISH_EL_SALVADOR, "es_SV", LANG_SPANISH , SUBLANG_SPANISH_EL_SALVADOR , wxLayout_LeftToRight, "Spanish (El Salvador)") - LNG(wxLANGUAGE_SPANISH_GUATEMALA, "es_GT", LANG_SPANISH , SUBLANG_SPANISH_GUATEMALA , wxLayout_LeftToRight, "Spanish (Guatemala)") - LNG(wxLANGUAGE_SPANISH_HONDURAS, "es_HN", LANG_SPANISH , SUBLANG_SPANISH_HONDURAS , wxLayout_LeftToRight, "Spanish (Honduras)") - LNG(wxLANGUAGE_SPANISH_MEXICAN, "es_MX", LANG_SPANISH , SUBLANG_SPANISH_MEXICAN , wxLayout_LeftToRight, "Spanish (Mexican)") - LNG(wxLANGUAGE_SPANISH_MODERN, "es_ES", LANG_SPANISH , SUBLANG_SPANISH_MODERN , wxLayout_LeftToRight, "Spanish (Modern)") - LNG(wxLANGUAGE_SPANISH_NICARAGUA, "es_NI", LANG_SPANISH , SUBLANG_SPANISH_NICARAGUA , wxLayout_LeftToRight, "Spanish (Nicaragua)") - LNG(wxLANGUAGE_SPANISH_PANAMA, "es_PA", LANG_SPANISH , SUBLANG_SPANISH_PANAMA , wxLayout_LeftToRight, "Spanish (Panama)") - LNG(wxLANGUAGE_SPANISH_PARAGUAY, "es_PY", LANG_SPANISH , SUBLANG_SPANISH_PARAGUAY , wxLayout_LeftToRight, "Spanish (Paraguay)") - LNG(wxLANGUAGE_SPANISH_PERU, "es_PE", LANG_SPANISH , SUBLANG_SPANISH_PERU , wxLayout_LeftToRight, "Spanish (Peru)") - LNG(wxLANGUAGE_SPANISH_PUERTO_RICO, "es_PR", LANG_SPANISH , SUBLANG_SPANISH_PUERTO_RICO , wxLayout_LeftToRight, "Spanish (Puerto Rico)") - LNG(wxLANGUAGE_SPANISH_URUGUAY, "es_UY", LANG_SPANISH , SUBLANG_SPANISH_URUGUAY , wxLayout_LeftToRight, "Spanish (Uruguay)") - LNG(wxLANGUAGE_SPANISH_US, "es_US", 0 , 0 , wxLayout_LeftToRight, "Spanish (U.S.)") - LNG(wxLANGUAGE_SPANISH_VENEZUELA, "es_VE", LANG_SPANISH , SUBLANG_SPANISH_VENEZUELA , wxLayout_LeftToRight, "Spanish (Venezuela)") - LNG(wxLANGUAGE_SUNDANESE, "su" , 0 , 0 , wxLayout_LeftToRight, "Sundanese") - LNG(wxLANGUAGE_SWAHILI, "sw_KE", LANG_SWAHILI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Swahili") - LNG(wxLANGUAGE_SWEDISH, "sv_SE", LANG_SWEDISH , SUBLANG_SWEDISH , wxLayout_LeftToRight, "Swedish") - LNG(wxLANGUAGE_SWEDISH_FINLAND, "sv_FI", LANG_SWEDISH , SUBLANG_SWEDISH_FINLAND , wxLayout_LeftToRight, "Swedish (Finland)") - LNG(wxLANGUAGE_TAGALOG, "tl_PH", 0 , 0 , wxLayout_LeftToRight, "Tagalog") - LNG(wxLANGUAGE_TAJIK, "tg" , 0 , 0 , wxLayout_LeftToRight, "Tajik") - LNG(wxLANGUAGE_TAMIL, "ta" , LANG_TAMIL , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Tamil") - LNG(wxLANGUAGE_TATAR, "tt" , LANG_TATAR , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Tatar") - LNG(wxLANGUAGE_TELUGU, "te" , LANG_TELUGU , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Telugu") - LNG(wxLANGUAGE_THAI, "th_TH", LANG_THAI , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Thai") - LNG(wxLANGUAGE_TIBETAN, "bo" , 0 , 0 , wxLayout_LeftToRight, "Tibetan") - LNG(wxLANGUAGE_TIGRINYA, "ti" , 0 , 0 , wxLayout_LeftToRight, "Tigrinya") - LNG(wxLANGUAGE_TONGA, "to" , 0 , 0 , wxLayout_LeftToRight, "Tonga") - LNG(wxLANGUAGE_TSONGA, "ts" , 0 , 0 , wxLayout_LeftToRight, "Tsonga") - LNG(wxLANGUAGE_TURKISH, "tr_TR", LANG_TURKISH , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Turkish") - LNG(wxLANGUAGE_TURKMEN, "tk" , 0 , 0 , wxLayout_LeftToRight, "Turkmen") - LNG(wxLANGUAGE_TWI, "tw" , 0 , 0 , wxLayout_LeftToRight, "Twi") - LNG(wxLANGUAGE_UIGHUR, "ug" , 0 , 0 , wxLayout_LeftToRight, "Uighur") - LNG(wxLANGUAGE_UKRAINIAN, "uk_UA", LANG_UKRAINIAN , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Ukrainian") - LNG(wxLANGUAGE_URDU, "ur" , LANG_URDU , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Urdu") - LNG(wxLANGUAGE_URDU_INDIA, "ur_IN", LANG_URDU , SUBLANG_URDU_INDIA , wxLayout_LeftToRight, "Urdu (India)") - LNG(wxLANGUAGE_URDU_PAKISTAN, "ur_PK", LANG_URDU , SUBLANG_URDU_PAKISTAN , wxLayout_LeftToRight, "Urdu (Pakistan)") - LNG(wxLANGUAGE_UZBEK, "uz" , LANG_UZBEK , SUBLANG_DEFAULT , wxLayout_LeftToRight, "Uzbek") - LNG(wxLANGUAGE_UZBEK_CYRILLIC, "uz" , LANG_UZBEK , SUBLANG_UZBEK_CYRILLIC , wxLayout_LeftToRight, "Uzbek (Cyrillic)") - LNG(wxLANGUAGE_UZBEK_LATIN, "uz" , LANG_UZBEK , SUBLANG_UZBEK_LATIN , wxLayout_LeftToRight, "Uzbek (Latin)") - LNG(wxLANGUAGE_VIETNAMESE, "vi_VN", LANG_VIETNAMESE, SUBLANG_DEFAULT , wxLayout_LeftToRight, "Vietnamese") - LNG(wxLANGUAGE_VOLAPUK, "vo" , 0 , 0 , wxLayout_LeftToRight, "Volapuk") - LNG(wxLANGUAGE_WELSH, "cy" , 0 , 0 , wxLayout_LeftToRight, "Welsh") - LNG(wxLANGUAGE_WOLOF, "wo" , 0 , 0 , wxLayout_LeftToRight, "Wolof") - LNG(wxLANGUAGE_XHOSA, "xh" , 0 , 0 , wxLayout_LeftToRight, "Xhosa") - LNG(wxLANGUAGE_YIDDISH, "yi" , 0 , 0 , wxLayout_LeftToRight, "Yiddish") - LNG(wxLANGUAGE_YORUBA, "yo" , 0 , 0 , wxLayout_LeftToRight, "Yoruba") - LNG(wxLANGUAGE_ZHUANG, "za" , 0 , 0 , wxLayout_LeftToRight, "Zhuang") - LNG(wxLANGUAGE_ZULU, "zu" , 0 , 0 , wxLayout_LeftToRight, "Zulu") -} -#undef LNG + void OnExit() + { + wxLocale::DestroyLanguagesDB(); + } +}; -// --- --- --- generated code ends here --- --- --- +IMPLEMENT_DYNAMIC_CLASS(wxLocaleModule, wxModule) #endif // wxUSE_INTL