-public:
- NoTransErr() { wxSuppressTransErrors(); }
- ~NoTransErr() { wxRestoreTransErrors(); }
-};
-
-// return all directories to search for given prefix
-static wxString GetAllMsgCatalogSubdirs(const char *prefix,
- const char *lang)
-{
- wxString searchPath;
-
- // search first in prefix/fr/LC_MESSAGES, then in prefix/fr and finally in
- // prefix (assuming the language is 'fr')
- searchPath << prefix << FILE_SEP_PATH << lang << FILE_SEP_PATH
- << "LC_MESSAGES" << PATH_SEP
- << prefix << FILE_SEP_PATH << lang << PATH_SEP
- << prefix << PATH_SEP;
-
- return searchPath;
-}
-
-// construct the search path for the given language
-static wxString GetFullSearchPath(const char *lang)
-{
- wxString searchPath;
-
- // first take the entries explicitly added by the program
- size_t count = s_searchPrefixes.Count();
- for ( size_t n = 0; n < count; n++ )
- {
- searchPath << GetAllMsgCatalogSubdirs(s_searchPrefixes[n], lang)
- << PATH_SEP;
- }
-
- // then take the current directory
- // FIXME it should be the directory of the executable
- searchPath << GetAllMsgCatalogSubdirs(".", lang) << PATH_SEP;
-
- // and finally add some standard ones
- searchPath
- << GetAllMsgCatalogSubdirs("/usr/share/locale", lang) << PATH_SEP
- << GetAllMsgCatalogSubdirs("/usr/lib/locale", lang) << PATH_SEP
- << GetAllMsgCatalogSubdirs("/usr/local/share/locale", lang);
-
- return searchPath;
-}
-
-// open disk file and read in it's contents
-bool wxMsgCatalog::Load(const char *szDirPrefix, const char *szName)
-{
- // FIXME VZ: I forgot the exact meaning of LC_PATH - anyone to remind me?
-#if 0
- const char *pszLcPath = getenv("LC_PATH");
- if ( pszLcPath != NULL )
- strPath += pszLcPath + wxString(szDirPrefix) + MSG_PATH;
-#endif // 0
-
- wxString searchPath = GetFullSearchPath(szDirPrefix);
- const char *sublocale = strchr(szDirPrefix, '_');
- 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 << GetFullSearchPath(wxString(szDirPrefix).
- Left((size_t)(sublocale - szDirPrefix)))
- << PATH_SEP;
- }
-
- wxString strFile = szName;
- strFile += MSGCATALOG_EXTENSION;
-
- // 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());
-
- wxString strFullName;
- if ( !wxFindFileInPath(&strFullName, searchPath, strFile) ) {
- wxLogWarning(_("catalog file for domain '%s' not found."), szName);
- return FALSE;
- }
-
- // open file
- wxLogVerbose(_("using catalog '%s' from '%s'."),
- szName, strFullName.c_str());
-
- wxFile fileMsg(strFullName);
- if ( !fileMsg.IsOpened() )
- return FALSE;
-
- // get the file size
- off_t nSize = fileMsg.Length();
- if ( nSize == wxInvalidOffset )
- return FALSE;
-
- // read the whole file in memory
- m_pData = new size_t8[nSize];
- if ( fileMsg.Read(m_pData, nSize) != nSize ) {
- wxDELETEA(m_pData);
- return FALSE;
- }
-
- // examine header
- bool bValid = (size_t)nSize > 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());
-
- 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_nHashSize = Swap(pHeader->nHashSize);
- m_pHashTable = (size_t32 *)(m_pData + Swap(pHeader->ofsHashTable));
-
- m_pszName = new char[strlen(szName) + 1];
- strcpy(m_pszName, szName);
-
- // everything is fine
- return TRUE;
-}
-
-// search for a string
-const char *wxMsgCatalog::GetString(const char *szOrig) const
-{
- if ( szOrig == NULL )
- return NULL;
+#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
+
+ bool ret = true;
+
+ 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(wxS("Unknown language %i."), lang);
+ return false;
+ }
+
+ 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 )
+ {
+ // 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 + wxS('.') + *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 == 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() )
+ {
+ retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt);
+ if ( !retloc )
+ retloc = wxSetlocaleTryUTF8(LC_ALL, ExtractLang(localeAlt));
+ }
+ }
+
+ if ( !retloc )
+ ret = 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
+ char* p = const_cast<char*>(wxStrchr(retloc, ' '));
+ if ( p )
+ *p = '\0';
+#endif // __AIX__
+
+#elif defined(__WIN32__)
+ const char *retloc = "C";
+ if ( language != wxLANGUAGE_DEFAULT )
+ {
+ 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
+
+ // 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
+ {
+ retloc = wxSetlocale(LC_ALL, wxEmptyString);
+ }
+
+#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 )
+ {
+ if ( wxGetANSICodePageForLocale(LOCALE_USER_DEFAULT).empty() )
+ {
+ // we set the locale to a Unicode-only language, don't treat the
+ // inability of CRT to use it as an error
+ retloc = "C";
+ }
+ }
+#endif // CRT not handling Unicode-only languages
+
+ if ( !retloc )
+ ret = false;
+#elif defined(__WXMAC__)
+ if (lang == wxLANGUAGE_DEFAULT)
+ locale = wxEmptyString;
+ else
+ locale = info->CanonicalName;
+
+ const char *retloc = wxSetlocale(LC_ALL, locale);
+
+ 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
+
+#ifndef WX_NO_LOCALE_SUPPORT
+ if ( !ret )
+ {
+ wxLogWarning(_("Cannot set locale to language \"%s\"."), name.c_str());
+
+ // continue nevertheless and try to load at least the translations for
+ // this language
+ }
+
+ if ( !DoInit(name, canonical, retloc) )
+ {
+ ret = false;
+ }
+
+ if (IsOk()) // setlocale() succeeded
+ m_language = lang;
+
+ // NB: don't use 'lang' here, 'language'
+ wxTranslations *t = wxTranslations::Get();
+ if ( t )
+ {
+ t->SetLanguage(static_cast<wxLanguage>(language));