X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3fe737557344dcf31299aea827e4b87c998ec940..2cdd63c6b1d473ffd7726f619085997b0737952e:/src/common/intl.cpp diff --git a/src/common/intl.cpp b/src/common/intl.cpp index e3f2208e59..ad9d29f161 100644 --- a/src/common/intl.cpp +++ b/src/common/intl.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/common/intl.cpp -// Purpose: Internationalization and localisation for wxWindows +// Purpose: Internationalization and localisation for wxWidgets // Author: Vadim Zeitlin // Modified by: Michael N. Filippov // (2003/09/30 - PluralForms support) @@ -28,6 +28,12 @@ #pragma option -O1 #endif +#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" @@ -49,7 +55,7 @@ #include #endif -// wxWindows +// wxWidgets #ifndef WX_PRECOMP #include "wx/string.h" #include "wx/intl.h" @@ -157,7 +163,7 @@ static inline wxString ExtractNotLang(const wxString& langFull) // Plural forms parser // ---------------------------------------------------------------------------- -/* +/* Simplified Grammar Expression: @@ -183,7 +189,7 @@ RelationalExpression: MultiplicativeExpression ">=" MultiplicativeExpression MultiplicativeExpression "<=" MultiplicativeExpression MultiplicativeExpression - + MultiplicativeExpression: PmExpression '%' PmExpression PmExpression @@ -395,7 +401,7 @@ private: wxPluralFormsToken m_token; wxPluralFormsNodePtr m_nodes[3]; }; - + wxPluralFormsNodePtr::~wxPluralFormsNodePtr() { delete m_p; @@ -480,7 +486,7 @@ class wxPluralFormsCalculator { public: wxPluralFormsCalculator() : m_nplurals(0), m_plural(0) {} - + // input: number, returns msgstr index int evaluate(int n) const; @@ -493,7 +499,7 @@ public: void init(wxPluralFormsToken::Number nplurals, wxPluralFormsNode* plural); wxString getString() const; - + private: wxPluralFormsToken::Number m_nplurals; wxPluralFormsNodePtr m_plural; @@ -535,7 +541,7 @@ private: wxPluralFormsScanner& m_scanner; const wxPluralFormsToken& token() const; bool nextToken(); - + wxPluralFormsNode* expression(); wxPluralFormsNode* logicalOrExpression(); wxPluralFormsNode* logicalAndExpression(); @@ -881,7 +887,8 @@ public: wxPluralFormsCalculatorPtr& rPluralFormsCalculator); // fills the hash with string-translation pairs - void FillHash(wxMessagesHash& hash, bool convertEncoding) const; + void FillHash(wxMessagesHash& hash, const wxString& msgIdCharset, + bool convertEncoding) const; private: // this implementation is binary compatible with GNU gettext() version 0.10 @@ -917,7 +924,7 @@ private: *m_pTransTable; // translated wxString m_charset; - + // swap the 2 halves of 32 bit integer if needed size_t32 Swap(size_t32 ui) const { @@ -938,7 +945,7 @@ private: } return (const char *)(m_pData + ofsString); - } + } bool m_bSwapped; // wrong endianness? @@ -957,7 +964,8 @@ class wxMsgCatalog { public: // load the catalog from disk (szDirPrefix corresponds to language) - bool Load(const wxChar *szDirPrefix, const wxChar *szName, bool bConvertEncoding = FALSE); + bool Load(const wxChar *szDirPrefix, const wxChar *szName, + const wxChar *msgIdCharset = NULL, bool bConvertEncoding = false); // get name of the catalog wxString GetName() const { return m_name; } @@ -1029,6 +1037,8 @@ static wxString GetFullSearchPath(const wxChar *lang) << wxPATH_SEP; } + // TODO: use wxStandardPaths instead of all this mess!! + // LC_PATH is a standard env var containing the search path for the .mo // files #ifndef __WXWINCE__ @@ -1048,14 +1058,16 @@ static wxString GetFullSearchPath(const wxChar *lang) // then take the current directory // FIXME it should be the directory of the executable -#ifdef __WXMAC__ - wxChar cwd[512] ; - wxGetWorkingDirectory( cwd , sizeof( cwd ) ) ; - searchPath << GetAllMsgCatalogSubdirs(cwd, lang); +#if defined(__WXMAC__) + searchPath << GetAllMsgCatalogSubdirs(wxGetCwd(), lang); // generic search paths could be somewhere in the system folder preferences -#else // !Mac +#elif defined(__WXMSW__) + // look in the directory of the executable + wxString path; + wxSplitPath(wxGetFullModuleName(), &path, NULL, NULL); + searchPath << GetAllMsgCatalogSubdirs(path, lang); +#else // !Mac, !MSW searchPath << GetAllMsgCatalogSubdirs(wxT("."), lang); - #endif // platform return searchPath; @@ -1070,7 +1082,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, FIXME: UNICODE SUPPORT: must use CHARSET specifier! */ wxString szName = szName0; - if(szName.Find(wxT('.')) != -1) // contains a dot + if(szName.Find(wxT('.')) != wxNOT_FOUND) // contains a dot szName = szName.Left(szName.Find(wxT('.'))); wxString searchPath = GetFullSearchPath(szDirPrefix); @@ -1100,7 +1112,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, wxString strFullName; if ( !wxFindFileInPath(&strFullName, searchPath, strFile) ) { wxLogVerbose(_("catalog file for domain '%s' not found."), szName.c_str()); - return FALSE; + return false; } // open file @@ -1109,22 +1121,22 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, wxFile fileMsg(strFullName); if ( !fileMsg.IsOpened() ) - return FALSE; + return false; - // get the file size - off_t nSize = fileMsg.Length(); + // get the file size (assume it is less than 4Gb...) + wxFileOffset nSize = fileMsg.Length(); if ( nSize == wxInvalidOffset ) - return FALSE; + return false; // read the whole file in memory m_pData = new size_t8[nSize]; - if ( fileMsg.Read(m_pData, nSize) != nSize ) { + if ( fileMsg.Read(m_pData, (size_t)nSize) != nSize ) { wxDELETEA(m_pData); - return FALSE; + return false; } // examine header - bool bValid = (size_t)nSize > sizeof(wxMsgCatalogHeader); + bool bValid = nSize + (size_t)0 > sizeof(wxMsgCatalogHeader); wxMsgCatalogHeader *pHeader = (wxMsgCatalogHeader *)m_pData; if ( bValid ) { @@ -1140,7 +1152,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, wxLogWarning(_("'%s' is not a valid message catalog."), strFullName.c_str()); wxDELETEA(m_pData); - return FALSE; + return false; } // initialize @@ -1149,8 +1161,8 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, Swap(pHeader->ofsOrigTable)); m_pTransTable = (wxMsgTableEntry *)(m_pData + Swap(pHeader->ofsTransTable)); - m_nSize = nSize; - + m_nSize = (size_t32)nSize; + // now parse catalog's header and try to extract catalog charset and // plural forms formula from it: @@ -1175,7 +1187,7 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, } } // else: incorrectly filled Content-Type header - + // Extract plural forms: begin = header.Find(wxT("Plural-Forms:")); if (begin != wxNOT_FOUND) @@ -1208,23 +1220,33 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName0, return true; } -void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) const +void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, + const wxString& msgIdCharset, + bool convertEncoding) const { #if wxUSE_WCHAR_T wxCSConv *csConv = NULL; - if ( !!m_charset ) + if ( !m_charset.empty() ) csConv = new wxCSConv(m_charset); wxMBConv& inputConv = csConv ? *((wxMBConv*)csConv) : *wxConvCurrent; + + wxCSConv *sourceConv = NULL; + if ( !msgIdCharset.empty() && (m_charset != msgIdCharset) ) + sourceConv = new wxCSConv(msgIdCharset); + #elif wxUSE_FONTMAP + wxASSERT_MSG( msgIdCharset == NULL, + _T("non-ASCII msgid languages only supported if wxUSE_WCHAR_T=1") ); + wxEncodingConverter converter; if ( convertEncoding ) { wxFontEncoding targetEnc = wxFONTENCODING_SYSTEM; - wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(m_charset, FALSE); + wxFontEncoding enc = wxFontMapper::Get()->CharsetToEncoding(m_charset, false); if ( enc == wxFONTENCODING_SYSTEM ) { - convertEncoding = FALSE; // unknown encoding + convertEncoding = false; // unknown encoding } else { @@ -1234,10 +1256,10 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) cons wxFontEncodingArray a = wxEncodingConverter::GetPlatformEquivalents(enc); if (a[0] == enc) // no conversion needed, locale uses native encoding - convertEncoding = FALSE; + convertEncoding = false; if (a.GetCount() == 0) // we don't know common equiv. under this platform - convertEncoding = FALSE; + convertEncoding = false; targetEnc = a[0]; } } @@ -1253,11 +1275,17 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) cons for (size_t i = 0; i < m_numStrings; i++) { const char *data = StringAtOfs(m_pOrigTable, i); -#if wxUSE_WCHAR_T +#if wxUSE_UNICODE wxString msgid(data, inputConv); #else - wxString msgid(data); + wxString msgid; +#if wxUSE_WCHAR_T + if ( convertEncoding && 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); @@ -1294,6 +1322,7 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) cons } #if wxUSE_WCHAR_T + delete sourceConv; delete csConv; #endif } @@ -1304,7 +1333,7 @@ void wxMsgCatalogFile::FillHash(wxMessagesHash& hash, bool convertEncoding) cons // ---------------------------------------------------------------------------- bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName, - bool bConvertEncoding) + const wxChar *msgIdCharset, bool bConvertEncoding) { wxMsgCatalogFile file; @@ -1312,11 +1341,11 @@ bool wxMsgCatalog::Load(const wxChar *szDirPrefix, const wxChar *szName, if ( file.Load(szDirPrefix, szName, m_pluralFormsCalculator) ) { - file.FillHash(m_messages, bConvertEncoding); - return TRUE; + file.FillHash(m_messages, msgIdCharset, bConvertEncoding); + return true; } - return FALSE; + return false; } const wxChar *wxMsgCatalog::GetString(const wxChar *sz, size_t n) const @@ -1370,9 +1399,12 @@ wxLanguageInfoArray *wxLocale::ms_languagesDB = NULL; } -wxLocale::wxLocale() +void wxLocale::DoCommonInit() { m_pszOldLocale = NULL; + + m_pOldLocale = wxSetLocale(this); + m_pMsgCat = NULL; m_language = wxLANGUAGE_UNKNOWN; m_initialized = false; @@ -1387,7 +1419,7 @@ bool wxLocale::Init(const wxChar *szName, { wxASSERT_MSG( !m_initialized, _T("you can't call wxLocale::Init more than once") ); - + m_initialized = true; m_strLocale = szName; m_strShort = szShort; @@ -1400,7 +1432,7 @@ bool wxLocale::Init(const wxChar *szName, // the argument to setlocale() szLocale = szShort; - wxCHECK_MSG( szLocale, FALSE, _T("no locale to set in wxLocale::Init()") ); + wxCHECK_MSG( szLocale, false, _T("no locale to set in wxLocale::Init()") ); } #ifdef __WXWINCE__ @@ -1410,7 +1442,7 @@ bool wxLocale::Init(const wxChar *szName, 256); if (ret != 0) { - m_pszOldLocale = wxStrdup(localeName); + m_pszOldLocale = wxStrdup(localeName); } else m_pszOldLocale = NULL; @@ -1418,9 +1450,11 @@ bool wxLocale::Init(const wxChar *szName, // TODO: how to find languageId // SetLocaleInfo(languageId, SORT_DEFAULT, localeName); #else - m_pszOldLocale = wxSetlocale(LC_ALL, szLocale); - if ( m_pszOldLocale ) - m_pszOldLocale = wxStrdup(m_pszOldLocale); + wxMB2WXbuf oldLocale = wxSetlocale(LC_ALL, szLocale); + if ( oldLocale ) + m_pszOldLocale = wxStrdup(oldLocale); + else + m_pszOldLocale = NULL; #endif if ( m_pszOldLocale == NULL ) @@ -1428,7 +1462,7 @@ bool wxLocale::Init(const wxChar *szName, // the short name will be used to look for catalog files as well, // so we need something here - if ( m_strShort.IsEmpty() ) { + if ( m_strShort.empty() ) { // FIXME I don't know how these 2 letter abbreviations are formed, // this wild guess is surely wrong if ( szLocale && szLocale[0] ) @@ -1439,12 +1473,9 @@ bool wxLocale::Init(const wxChar *szName, } } - // save the old locale to be able to restore it later - m_pOldLocale = wxSetLocale(this); - - // load the default catalog with wxWindows standard messages + // load the default catalog with wxWidgets standard messages m_pMsgCat = NULL; - bool bOk = TRUE; + bool bOk = true; if ( bLoadDefault ) bOk = AddCatalog(wxT("wxstd")); @@ -1452,30 +1483,30 @@ bool wxLocale::Init(const wxChar *szName, } -#if defined(__UNIX__) && wxUSE_UNICODE +#if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__) static wxWCharBuffer wxSetlocaleTryUTF(int c, const wxChar *lc) { wxMB2WXbuf l = wxSetlocale(c, lc); if ( !l && lc && lc[0] != 0 ) { - wxString buf(lc); + wxString buf(lc); wxString buf2; - buf2 = buf + wxT(".UTF-8"); - l = wxSetlocale(c, buf2.c_str()); + buf2 = buf + wxT(".UTF-8"); + l = wxSetlocale(c, buf2.c_str()); if ( !l ) { buf2 = buf + wxT(".utf-8"); - l = wxSetlocale(c, buf2.c_str()); + l = wxSetlocale(c, buf2.c_str()); } if ( !l ) { buf2 = buf + wxT(".UTF8"); - l = wxSetlocale(c, buf2.c_str()); + l = wxSetlocale(c, buf2.c_str()); } if ( !l ) { buf2 = buf + wxT(".utf8"); - l = wxSetlocale(c, buf2.c_str()); + l = wxSetlocale(c, buf2.c_str()); } } return l; @@ -1496,7 +1527,7 @@ bool wxLocale::Init(int language, int flags) // We failed to detect system language, so we will use English: if (lang == wxLANGUAGE_UNKNOWN) { - return FALSE; + return false; } const wxLanguageInfo *info = GetLanguageInfo(lang); @@ -1505,7 +1536,7 @@ bool wxLocale::Init(int language, int flags) if (info == NULL) { wxLogError(wxT("Unknown language %i."), lang); - return FALSE; + return false; } wxString name = info->Description; @@ -1553,7 +1584,7 @@ bool wxLocale::Init(int language, int flags) if ( !retloc ) { wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str()); - return FALSE; + return false; } #elif defined(__WIN32__) @@ -1566,7 +1597,10 @@ bool wxLocale::Init(int language, int flags) // #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) { @@ -1577,7 +1611,7 @@ bool wxLocale::Init(int language, int flags) } else { - int codepage + int codepage #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS = -1 #endif @@ -1603,11 +1637,11 @@ bool wxLocale::Init(int language, int flags) if (codepage != 0) locale << wxT(".") << buffer; } - if (locale.IsEmpty()) + if (locale.empty()) { wxLogLastError(wxT("SetThreadLocale")); wxLogError(wxT("Cannot set locale to language %s."), name.c_str()); - return FALSE; + return false; } else { @@ -1649,12 +1683,30 @@ bool wxLocale::Init(int language, int flags) if ( !retloc ) { wxLogError(wxT("Cannot set locale to language %s."), name.c_str()); - return FALSE; + 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; } -#elif defined(__WXMAC__) || defined(__WXPM__) +#elif defined(__WXPM__) wxMB2WXbuf retloc = wxSetlocale(LC_ALL , wxEmptyString); #else - return FALSE; + return false; #define WX_NO_LOCALE_SUPPORT #endif @@ -2140,7 +2192,7 @@ void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix) // 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 he encoding info +// reflects the way different systems provide the encoding info /* static */ wxString wxLocale::GetSystemEncodingName() @@ -2151,6 +2203,9 @@ wxString wxLocale::GetSystemEncodingName() // 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) @@ -2172,8 +2227,18 @@ wxString wxLocale::GetSystemEncodingName() // ISO-646, i.e. 7 bit ASCII // // and recent glibc call it ANSI_X3.4-1968... - if ( strcmp(alang, "646") == 0 || - strcmp(alang, "ANSI_X3.4-1968") == 0 ) + // + // HP-UX uses HP-Roman8 cset which is not the same as ASCII (see RFC + // 1345 for its definition) but must be recognized as otherwise HP + // users get a warning about it on each program startup, so handle it + // here -- but it would be obviously better to add real supprot to it, + // of course! + if ( strcmp(alang, "646") == 0 + || strcmp(alang, "ANSI_X3.4-1968") == 0 +#ifdef __HPUX__ + || strcmp(alang, "roman8") == 0 +#endif // __HPUX__ + ) { encname = _T("US-ASCII"); } @@ -2219,7 +2284,7 @@ wxFontEncoding wxLocale::GetSystemEncoding() #if defined(__WIN32__) && !defined(__WXMICROWIN__) UINT codepage = ::GetACP(); - // wxWindows only knows about CP1250-1257, 932, 936, 949, 950 + // wxWidgets only knows about CP1250-1257, 932, 936, 949, 950 if ( codepage >= 1250 && codepage <= 1257 ) { return (wxFontEncoding)(wxFONTENCODING_CP1250 + codepage - 1250); @@ -2245,11 +2310,11 @@ wxFontEncoding wxLocale::GetSystemEncoding() return wxFONTENCODING_CP950; } #elif defined(__WXMAC__) - TextEncoding encoding = 0 ; + TextEncoding encoding = 0 ; #if TARGET_CARBON - encoding = CFStringGetSystemEncoding() ; + encoding = CFStringGetSystemEncoding() ; #else - UpgradeScriptInfoToTextEncoding ( smSystemScript , kTextLanguageDontCare , kTextRegionDontCare , NULL , &encoding ) ; + UpgradeScriptInfoToTextEncoding ( smSystemScript , kTextLanguageDontCare , kTextRegionDontCare , NULL , &encoding ) ; #endif return wxMacGetFontEncFromSystemEnc( encoding ) ; #elif defined(__UNIX_LIKE__) && wxUSE_FONTMAP @@ -2257,7 +2322,7 @@ wxFontEncoding wxLocale::GetSystemEncoding() if ( !encname.empty() ) { wxFontEncoding enc = wxFontMapper::Get()-> - CharsetToEncoding(encname, FALSE /* not interactive */); + CharsetToEncoding(encname, false /* not interactive */); // on some modern Linux systems (RedHat 8) the default system locale // is UTF8 -- but it isn't supported by wxGTK in ANSI build at all so @@ -2299,6 +2364,11 @@ const wxLanguageInfo *wxLocale::GetLanguageInfo(int lang) { 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++ ) { @@ -2378,8 +2448,9 @@ wxLocale::~wxLocale() delete pTmpCat; } - // restore old locale + // restore old locale pointer wxSetLocale(m_pOldLocale); + // FIXME #ifndef __WXWINCE__ wxSetlocale(LC_ALL, m_pszOldLocale); @@ -2457,6 +2528,58 @@ const wxChar *wxLocale::GetString(const wxChar *szOrigString, return pszTrans; } +wxString wxLocale::GetHeaderValue( const wxChar* szHeader, + const wxChar* szDomain ) const +{ + if ( wxIsEmpty(szHeader) ) + return wxEmptyString; + + wxChar const * pszTrans = NULL; + wxMsgCatalog *pMsgCat; + + if ( szDomain != NULL ) + { + pMsgCat = FindCatalog(szDomain); + + // does the catalog exist? + if ( pMsgCat == NULL ) + return wxEmptyString; + + pszTrans = pMsgCat->GetString(wxEmptyString, (size_t)-1); + } + else + { + // search in all domains + for ( pMsgCat = m_pMsgCat; pMsgCat != NULL; pMsgCat = pMsgCat->m_pNext ) + { + pszTrans = pMsgCat->GetString(wxEmptyString, (size_t)-1); + if ( pszTrans != NULL ) // take the first found + break; + } + } + + if ( wxIsEmpty(pszTrans) ) + return wxEmptyString; + + wxChar const * pszFound = wxStrstr(pszTrans, szHeader); + if ( pszFound == NULL ) + return wxEmptyString; + + pszFound += wxStrlen(szHeader) + 2 /* ': ' */; + + // Every header is separated by \n + + wxChar const * pszEndLine = wxStrchr(pszFound, wxT('\n')); + if ( pszEndLine == NULL ) pszEndLine = pszFound + wxStrlen(pszFound); + + + // wxString( wxChar*, length); + wxString retVal( pszFound, pszEndLine - pszFound ); + + return retVal; +} + + // find catalog by name in a linked list, return NULL if !found wxMsgCatalog *wxLocale::FindCatalog(const wxChar *szDomain) const { @@ -2479,27 +2602,47 @@ bool wxLocale::IsLoaded(const wxChar *szDomain) const // add a catalog to our linked list bool wxLocale::AddCatalog(const wxChar *szDomain) +{ + return AddCatalog(szDomain, wxLANGUAGE_ENGLISH, NULL); +} + +// add a catalog to our linked list +bool wxLocale::AddCatalog(const wxChar *szDomain, + wxLanguage msgIdLanguage, + const wxChar *msgIdCharset) + { wxMsgCatalog *pMsgCat = new wxMsgCatalog; - if ( pMsgCat->Load(m_strShort, szDomain, m_bConvertEncoding) ) { + 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; - return TRUE; + return true; } else { // don't add it because it couldn't be loaded anyway delete pMsgCat; - // it's OK to not load English catalog, the texts are embedded in - // the program: - if (m_strShort.Mid(0, 2) == wxT("en")) - return TRUE; + // 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) ) + { + return true; + } - return FALSE; + return false; } } @@ -2582,7 +2725,7 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) default: return wxEmptyString; } -} +} #endif // __WXMSW__/!__WXMSW__ @@ -2619,7 +2762,7 @@ class wxLocaleModule: public wxModule DECLARE_DYNAMIC_CLASS(wxLocaleModule) public: wxLocaleModule() {} - bool OnInit() { return TRUE; } + bool OnInit() { return true; } void OnExit() { wxLocale::DestroyLanguagesDB(); } }; @@ -3181,7 +3324,7 @@ void wxLocale::InitLanguagesDB() LNG(wxLANGUAGE_BURMESE, "my" , 0 , 0 , "Burmese") LNG(wxLANGUAGE_CAMBODIAN, "km" , 0 , 0 , "Cambodian") LNG(wxLANGUAGE_CATALAN, "ca_ES", LANG_CATALAN , SUBLANG_DEFAULT , "Catalan") - LNG(wxLANGUAGE_CHINESE, "zh_CN", LANG_CHINESE , SUBLANG_DEFAULT , "Chinese") + LNG(wxLANGUAGE_CHINESE, "zh_TW", LANG_CHINESE , SUBLANG_DEFAULT , "Chinese") LNG(wxLANGUAGE_CHINESE_SIMPLIFIED, "zh_CN", LANG_CHINESE , SUBLANG_CHINESE_SIMPLIFIED , "Chinese (Simplified)") LNG(wxLANGUAGE_CHINESE_TRADITIONAL, "zh_TW", LANG_CHINESE , SUBLANG_CHINESE_TRADITIONAL , "Chinese (Traditional)") LNG(wxLANGUAGE_CHINESE_HONGKONG, "zh_HK", LANG_CHINESE , SUBLANG_CHINESE_HONGKONG , "Chinese (Hongkong)")