]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/intl.cpp
wxChar -> char
[wxWidgets.git] / src / common / intl.cpp
index 0dcec7965268914baa6e5bb50b6317d28bd7eecc..58aaf5c0184307dc8d534ead0a146ab49a320884 100644 (file)
 // headers
 // ----------------------------------------------------------------------------
 
 // 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"
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
     #pragma hdrstop
 #endif
 
     #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
 #if wxUSE_INTL
 
 #ifndef WX_PRECOMP
 #include "wx/ptr_scpd.h"
 #include "wx/apptrait.h"
 #include "wx/stdpaths.h"
 #include "wx/ptr_scpd.h"
 #include "wx/apptrait.h"
 #include "wx/stdpaths.h"
+#include "wx/hashset.h"
+#include "wx/filesys.h"
 
 #if defined(__WXMAC__)
 
 #if defined(__WXMAC__)
-    #include  "wx/mac/private.h"  // includes mac headers
+    #include "wx/mac/private.h"  // includes mac headers
+#endif
+
+#if defined(__WXOSX__)
+    #include "wx/mac/corefoundation/cfstring.h"
+    #include "wx/mac/corefoundation/cfref.h"
 #endif
 
 // ----------------------------------------------------------------------------
 #endif
 
 // ----------------------------------------------------------------------------
@@ -872,7 +879,7 @@ public:
    ~wxMsgCatalogFile();
 
     // load the catalog from disk (szDirPrefix corresponds to language)
    ~wxMsgCatalogFile();
 
     // load the catalog from disk (szDirPrefix corresponds to language)
-    bool Load(const wxChar *szDirPrefix, const wxChar *szName,
+    bool Load(const wxString& szDirPrefix, const wxString& szName,
               wxPluralFormsCalculatorPtr& rPluralFormsCalculator);
 
     // fills the hash with string-translation pairs
               wxPluralFormsCalculatorPtr& rPluralFormsCalculator);
 
     // fills the hash with string-translation pairs
@@ -906,11 +913,8 @@ private:
                 ofsHashTable;   //        +18:  offset of hash table start
     };
 
                 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;
+    // all data is stored here
+    wxMemoryBuffer m_data;
 
     // data description
     size_t32          m_numStrings;   // number of strings in this domain
 
     // data description
     size_t32          m_numStrings;   // number of strings in this domain
@@ -928,18 +932,25 @@ private:
                             : ui;
     }
 
                             : ui;
     }
 
+    // just return the pointer to the start of the data as "char *" to
+    // facilitate doing pointer arithmetic with it
+    char *StringData() const
+    {
+        return wx_static_cast(char *, m_data.GetData());
+    }
+
     const char *StringAtOfs(wxMsgTableEntry *pTable, size_t32 n) const
     {
         const wxMsgTableEntry * const ent = pTable + n;
 
         // this check could fail for a corrupt message catalog
         size_t32 ofsString = Swap(ent->ofsString);
     const char *StringAtOfs(wxMsgTableEntry *pTable, size_t32 n) const
     {
         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 ( ofsString + Swap(ent->nLen) > m_data.GetDataLen())
         {
             return NULL;
         }
 
         {
             return NULL;
         }
 
-        return (const char *)(m_pData + ofsString);
+        return StringData() + ofsString;
     }
 
     bool m_bSwapped;   // wrong endianness?
     }
 
     bool m_bSwapped;   // wrong endianness?
@@ -1002,41 +1013,42 @@ static wxArrayString gs_searchPrefixes;
 
 wxMsgCatalogFile::wxMsgCatalogFile()
 {
 
 wxMsgCatalogFile::wxMsgCatalogFile()
 {
-    m_pData = NULL;
-    m_nSize = 0;
 }
 
 wxMsgCatalogFile::~wxMsgCatalogFile()
 {
 }
 
 wxMsgCatalogFile::~wxMsgCatalogFile()
 {
-    delete [] m_pData;
 }
 
 // return the directories to search for message catalogs under the given
 // prefix, separated by wxPATH_SEP
 static
 }
 
 // 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)
+wxString GetMsgCatalogSubdirs(const wxString& prefix, const wxString& lang)
 {
 {
-    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:
+    // Search first in Unix-standard prefix/lang/LC_MESSAGES, then in
+    // prefix/lang and finally in just prefix.
+    //
+    // Note that we use LC_MESSAGES 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
     // 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;
+    wxString pathPrefix;
+    pathPrefix << prefix << wxFILE_SEP_PATH << lang;
+
+    wxString searchPath;
+    searchPath.reserve(4*pathPrefix.length());
+    searchPath << pathPrefix << wxFILE_SEP_PATH << "LC_MESSAGES" << wxPATH_SEP
+               << prefix << wxFILE_SEP_PATH << wxPATH_SEP
+               << pathPrefix;
 
     return searchPath;
 }
 
 // construct the search path for the given language
 
     return searchPath;
 }
 
 // construct the search path for the given language
-static wxString GetFullSearchPath(const wxChar *lang)
+static wxString GetFullSearchPath(const wxString& lang)
 {
     // first take the entries explicitly added by the program
     wxArrayString paths;
 {
     // first take the entries explicitly added by the program
     wxArrayString paths;
@@ -1096,7 +1108,7 @@ static wxString GetFullSearchPath(const wxChar *lang)
 }
 
 // open disk file and read in it's contents
 }
 
 // open disk file and read in it's contents
-bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName,
+bool wxMsgCatalogFile::Load(const wxString& szDirPrefix, const wxString& szName,
                             wxPluralFormsCalculatorPtr& rPluralFormsCalculator)
 {
   wxString searchPath;
                             wxPluralFormsCalculatorPtr& rPluralFormsCalculator)
 {
   wxString searchPath;
@@ -1117,15 +1129,14 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName,
 
 
   searchPath += GetFullSearchPath(szDirPrefix);
 
 
   searchPath += GetFullSearchPath(szDirPrefix);
-  const wxChar *sublocale = wxStrchr(szDirPrefix, wxT('_'));
-  if ( sublocale )
+  size_t sublocaleIndex = szDirPrefix.find(wxT('_'));
+  if ( sublocaleIndex != wxString::npos )
   {
       // 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
   {
       // 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)));
+                 << GetFullSearchPath(szDirPrefix.Left(sublocaleIndex));
   }
 
   // don't give translation errors here because the wxstd catalog might
   }
 
   // don't give translation errors here because the wxstd catalog might
@@ -1141,17 +1152,40 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName,
 
   wxFileName fn(szName);
   fn.SetExt(_T("mo"));
 
   wxFileName fn(szName);
   fn.SetExt(_T("mo"));
+
   wxString strFullName;
   wxString strFullName;
-  if ( !wxFindFileInPath(&strFullName, searchPath, fn.GetFullPath()) ) {
+#if wxUSE_FILESYSTEM
+  wxFileSystem fileSys;
+  if ( !fileSys.FindFileInPath(&strFullName, searchPath, fn.GetFullPath()) )
+#else // !wxUSE_FILESYSTEM
+  if ( !wxFindFileInPath(&strFullName, searchPath, fn.GetFullPath()) )
+#endif // wxUSE_FILESYSTEM/!wxUSE_FILESYSTEM
+  {
     wxLogVerbose(_("catalog file for domain '%s' not found."), szName);
     wxLogTrace(TRACE_I18N, _T("Catalog \"%s.mo\" not found"), szName);
     return false;
   }
 
     wxLogVerbose(_("catalog file for domain '%s' not found."), szName);
     wxLogTrace(TRACE_I18N, _T("Catalog \"%s.mo\" not found"), szName);
     return false;
   }
 
-  // open file
+  // open file and read its data
   wxLogVerbose(_("using catalog '%s' from '%s'."), szName, strFullName.c_str());
   wxLogTrace(TRACE_I18N, _T("Using catalog \"%s\"."), strFullName.c_str());
 
   wxLogVerbose(_("using catalog '%s' from '%s'."), szName, strFullName.c_str());
   wxLogTrace(TRACE_I18N, _T("Using catalog \"%s\"."), strFullName.c_str());
 
+#if wxUSE_FILESYSTEM
+  wxFSFile * const fileMsg = fileSys.OpenFile(strFullName);
+  if ( !fileMsg )
+    return false;
+
+  wxInputStream *fileStream = fileMsg->GetStream();
+  m_data.SetDataLen(0);
+
+  static const size_t chunkSize = 4096;
+  while ( !fileStream->Eof() ) {
+    fileStream->Read(m_data.GetAppendBuf(chunkSize), chunkSize);
+    m_data.UngetAppendBuf(fileStream->LastRead());
+  }
+
+  delete fileMsg;
+#else // !wxUSE_FILESYSTEM
   wxFile fileMsg(strFullName);
   if ( !fileMsg.IsOpened() )
     return false;
   wxFile fileMsg(strFullName);
   if ( !fileMsg.IsOpened() )
     return false;
@@ -1165,16 +1199,15 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName,
   wxASSERT_MSG( nSize == lenFile + size_t(0), _T("message catalog bigger than 4GB?") );
 
   // read the whole file in memory
   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);
+  if ( fileMsg.Read(m_data.GetWriteBuf(nSize), nSize) != lenFile )
     return false;
     return false;
-  }
+#endif // wxUSE_FILESYSTEM/!wxUSE_FILESYSTEM
+
 
   // examine header
 
   // examine header
-  bool bValid = nSize + (size_t)0 > sizeof(wxMsgCatalogHeader);
+  bool bValid = m_data.GetDataLen() > sizeof(wxMsgCatalogHeader);
 
 
-  wxMsgCatalogHeader *pHeader = (wxMsgCatalogHeader *)m_pData;
+  const wxMsgCatalogHeader *pHeader = (wxMsgCatalogHeader *)m_data.GetData();
   if ( bValid ) {
     // we'll have to swap all the integers if it's true
     m_bSwapped = pHeader->magic == MSGCATALOG_MAGIC_SW;
   if ( bValid ) {
     // we'll have to swap all the integers if it's true
     m_bSwapped = pHeader->magic == MSGCATALOG_MAGIC_SW;
@@ -1187,17 +1220,15 @@ bool wxMsgCatalogFile::Load(const wxChar *szDirPrefix, const wxChar *szName,
     // it's either too short or has incorrect magic number
     wxLogWarning(_("'%s' is not a valid message catalog."), strFullName.c_str());
 
     // 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);
     return false;
   }
 
   // initialize
   m_numStrings  = Swap(pHeader->numStrings);
-  m_pOrigTable  = (wxMsgTableEntry *)(m_pData +
+  m_pOrigTable  = (wxMsgTableEntry *)(StringData() +
                    Swap(pHeader->ofsOrigTable));
                    Swap(pHeader->ofsOrigTable));
-  m_pTransTable = (wxMsgTableEntry *)(m_pData +
+  m_pTransTable = (wxMsgTableEntry *)(StringData() +
                    Swap(pHeader->ofsTransTable));
                    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:
 
   // now parse catalog's header and try to extract catalog charset and
   // plural forms formula from it:
@@ -1534,7 +1565,8 @@ bool wxLocale::Init(const wxString& name,
     // the argument to setlocale()
     szLocale = shortName;
 
     // the argument to setlocale()
     szLocale = shortName;
 
-    wxCHECK_MSG( szLocale, false, _T("no locale to set in wxLocale::Init()") );
+    wxCHECK_MSG( !szLocale.empty(), false,
+                 _T("no locale to set in wxLocale::Init()") );
   }
 
 #ifdef __WXWINCE__
   }
 
 #ifdef __WXWINCE__
@@ -1544,7 +1576,7 @@ bool wxLocale::Init(const wxString& name,
       256);
   if (ret != 0)
   {
       256);
   if (ret != 0)
   {
-    m_pszOldLocale = wxStrdup(localeName);
+    m_pszOldLocale = wxStrdup(wxConvLibc.cWC2MB(localeName));
   }
   else
     m_pszOldLocale = NULL;
   }
   else
     m_pszOldLocale = NULL;
@@ -1552,7 +1584,7 @@ bool wxLocale::Init(const wxString& name,
   // TODO: how to find languageId
   // SetLocaleInfo(languageId, SORT_DEFAULT, localeName);
 #else
   // TODO: how to find languageId
   // SetLocaleInfo(languageId, SORT_DEFAULT, localeName);
 #else
-  wxMB2WXbuf oldLocale = wxSetlocale(LC_ALL, szLocale);
+  const char *oldLocale = wxSetlocale(LC_ALL, szLocale);
   if ( oldLocale )
       m_pszOldLocale = wxStrdup(oldLocale);
   else
   if ( oldLocale )
       m_pszOldLocale = wxStrdup(oldLocale);
   else
@@ -1599,39 +1631,50 @@ bool wxLocale::Init(const wxString& name,
 
 
 #if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__)
 
 
 #if defined(__UNIX__) && wxUSE_UNICODE && !defined(__WXMAC__)
-static wxWCharBuffer wxSetlocaleTryUTF(int c, const wxChar *lc)
+static const char *wxSetlocaleTryUTF8(int c, const wxString& lc)
 {
 {
-    wxMB2WXbuf l = wxSetlocale(c, lc);
-    if ( !l && lc && lc[0] != 0 )
+    const char *l = NULL;
+
+    // NB: We prefer to set UTF-8 locale if it's possible and only fall back to
+    //     non-UTF-8 locale if it fails
+
+    if ( !lc.empty() )
     {
         wxString buf(lc);
         wxString buf2;
         buf2 = buf + wxT(".UTF-8");
     {
         wxString buf(lc);
         wxString buf2;
         buf2 = buf + wxT(".UTF-8");
-        l = wxSetlocale(c, buf2.c_str());
+        l = wxSetlocale(c, buf2);
         if ( !l )
         {
             buf2 = buf + wxT(".utf-8");
         if ( !l )
         {
             buf2 = buf + wxT(".utf-8");
-            l = wxSetlocale(c, buf2.c_str());
+            l = wxSetlocale(c, buf2);
         }
         if ( !l )
         {
             buf2 = buf + wxT(".UTF8");
         }
         if ( !l )
         {
             buf2 = buf + wxT(".UTF8");
-            l = wxSetlocale(c, buf2.c_str());
+            l = wxSetlocale(c, buf2);
         }
         if ( !l )
         {
             buf2 = buf + wxT(".utf8");
         }
         if ( !l )
         {
             buf2 = buf + wxT(".utf8");
-            l = wxSetlocale(c, buf2.c_str());
+            l = wxSetlocale(c, buf2);
         }
     }
         }
     }
+
+    // if we can't set UTF-8 locale, try non-UTF-8 one:
+    if ( !l )
+        l = wxSetlocale(c, lc);
+
     return l;
 }
 #else
     return l;
 }
 #else
-#define wxSetlocaleTryUTF(c, lc)  wxSetlocale(c, lc)
+#define wxSetlocaleTryUTF8(c, lc)  wxSetlocale(c, lc)
 #endif
 
 bool wxLocale::Init(int language, int flags)
 {
 #endif
 
 bool wxLocale::Init(int language, int flags)
 {
+    bool ret = true;
+
     int lang = language;
     if (lang == wxLANGUAGE_DEFAULT)
     {
     int lang = language;
     if (lang == wxLANGUAGE_DEFAULT)
     {
@@ -1660,18 +1703,18 @@ bool wxLocale::Init(int language, int flags)
 
     // Set the locale:
 #if defined(__OS2__)
 
     // Set the locale:
 #if defined(__OS2__)
-    wxMB2WXbuf retloc = wxSetlocale(LC_ALL , wxEmptyString);
+    const char *retloc = wxSetlocale(LC_ALL , wxEmptyString);
 #elif defined(__UNIX__) && !defined(__WXMAC__)
     if (language != wxLANGUAGE_DEFAULT)
         locale = info->CanonicalName;
 
 #elif defined(__UNIX__) && !defined(__WXMAC__)
     if (language != wxLANGUAGE_DEFAULT)
         locale = info->CanonicalName;
 
-    wxMB2WXbuf retloc = wxSetlocaleTryUTF(LC_ALL, locale);
+    const char *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
 
     const wxString langOnly = locale.Left(2);
     if ( !retloc )
     {
         // Some C libraries don't like xx_YY form and require xx only
-        retloc = wxSetlocaleTryUTF(LC_ALL, langOnly);
+        retloc = wxSetlocaleTryUTF8(LC_ALL, langOnly);
     }
 
 #if wxUSE_FONTMAP
     }
 
 #if wxUSE_FONTMAP
@@ -1712,17 +1755,14 @@ bool wxLocale::Init(int language, int flags)
 
         if ( !localeAlt.empty() )
         {
 
         if ( !localeAlt.empty() )
         {
-            retloc = wxSetlocaleTryUTF(LC_ALL, localeAlt);
+            retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt);
             if ( !retloc )
             if ( !retloc )
-                retloc = wxSetlocaleTryUTF(LC_ALL, localeAlt.Left(2));
+                retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt.Left(2));
         }
     }
 
     if ( !retloc )
         }
     }
 
     if ( !retloc )
-    {
-        wxLogError(wxT("Cannot set locale to '%s'."), locale.c_str());
-        return false;
-    }
+        ret = false;
 
 #ifdef __AIX__
     // at least in AIX 5.2 libc is buggy and the string returned from
 
 #ifdef __AIX__
     // at least in AIX 5.2 libc is buggy and the string returned from
@@ -1732,9 +1772,9 @@ bool wxLocale::Init(int language, int flags)
     //
     // this contradicts IBM own docs but this is not of much help, so just work
     // around it in the crudest possible manner
     //
     // 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(' '));
+    char* p = const_cast<char*>(wxStrchr(retloc, ' '));
     if ( p )
     if ( p )
-        *p = _T('\0');
+        *p = '\0';
 #endif // __AIX__
 
 #elif defined(__WIN32__)
 #endif // __AIX__
 
 #elif defined(__WIN32__)
@@ -1749,10 +1789,7 @@ bool wxLocale::Init(int language, int flags)
         #define SETLOCALE_FAILS_ON_UNICODE_LANGS
     #endif
 
         #define SETLOCALE_FAILS_ON_UNICODE_LANGS
     #endif
 
-#if !wxUSE_UNICODE
-    const
-#endif
-    wxMB2WXbuf retloc = wxT("C");
+    const char *retloc = "C";
     if (language != wxLANGUAGE_DEFAULT)
     {
         if (info->WinLang == 0)
     if (language != wxLANGUAGE_DEFAULT)
     {
         if (info->WinLang == 0)
@@ -1791,8 +1828,7 @@ bool wxLocale::Init(int language, int flags)
             if (locale.empty())
             {
                 wxLogLastError(wxT("SetThreadLocale"));
             if (locale.empty())
             {
                 wxLogLastError(wxT("SetThreadLocale"));
-                wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
-                return false;
+                ret = false;
             }
             else
             {
             }
             else
             {
@@ -1801,9 +1837,9 @@ bool wxLocale::Init(int language, int flags)
                 retloc = wxSetlocale(LC_ALL, locale);
 #endif
 #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
                 retloc = wxSetlocale(LC_ALL, locale);
 #endif
 #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
-                if (codepage == 0 && (const wxChar*)retloc == NULL)
+                if (codepage == 0 && retloc == NULL)
                 {
                 {
-                    retloc = wxT("C");
+                    retloc = "C";
                 }
 #endif
             }
                 }
 #endif
             }
@@ -1818,42 +1854,34 @@ bool wxLocale::Init(int language, int flags)
         retloc = NULL;
 #endif
 #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
         retloc = NULL;
 #endif
 #ifdef SETLOCALE_FAILS_ON_UNICODE_LANGS
-        if ((const wxChar*)retloc == NULL)
+        if (retloc == NULL)
         {
             wxChar buffer[16];
             if (GetLocaleInfo(LOCALE_USER_DEFAULT,
                               LOCALE_IDEFAULTANSICODEPAGE, buffer, 16) > 0 &&
                  wxStrcmp(buffer, wxT("0")) == 0)
             {
         {
             wxChar buffer[16];
             if (GetLocaleInfo(LOCALE_USER_DEFAULT,
                               LOCALE_IDEFAULTANSICODEPAGE, buffer, 16) > 0 &&
                  wxStrcmp(buffer, wxT("0")) == 0)
             {
-                retloc = wxT("C");
+                retloc = "C";
             }
         }
 #endif
     }
 
     if ( !retloc )
             }
         }
 #endif
     }
 
     if ( !retloc )
-    {
-        wxLogError(wxT("Cannot set locale to language %s."), name.c_str());
-        return false;
-    }
+        ret = false;
 #elif defined(__WXMAC__)
     if (lang == wxLANGUAGE_DEFAULT)
         locale = wxEmptyString;
     else
         locale = info->CanonicalName;
 
 #elif defined(__WXMAC__)
     if (lang == wxLANGUAGE_DEFAULT)
         locale = wxEmptyString;
     else
         locale = info->CanonicalName;
 
-    wxMB2WXbuf retloc = wxSetlocale(LC_ALL, locale);
+    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, locale.Mid(0,2));
     }
 
     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;
 #else
     wxUnusedVar(flags);
     return false;
@@ -1861,9 +1889,20 @@ bool wxLocale::Init(int language, int flags)
 #endif
 
 #ifndef 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 ( !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 ( !Init(name, canonical, retloc,
+               (flags & wxLOCALE_LOAD_DEFAULT) != 0,
+               (flags & wxLOCALE_CONV_ENCODING) != 0) )
+    {
+        ret = false;
+    }
 
     if (IsOk()) // setlocale() succeeded
         m_language = lang;
 
     if (IsOk()) // setlocale() succeeded
         m_language = lang;
@@ -2550,7 +2589,7 @@ const wxLanguageInfo *wxLocale::FindLanguageInfo(const wxString& locale)
             // looking
             //
             // OTOH, maybe we had already found a language match and in this
             // looking
             //
             // OTOH, maybe we had already found a language match and in this
-            // case don't overwrite it becauce the entry for the default
+            // case don't overwrite it because the entry for the default
             // country always appears first in ms_languagesDB
             if ( !infoRet )
                 infoRet = info;
             // country always appears first in ms_languagesDB
             if ( !infoRet )
                 infoRet = info;
@@ -2604,7 +2643,7 @@ const wxString& wxLocale::GetString(const wxString& origString,
                                     const wxString& domain) const
 {
     if ( origString.empty() )
                                     const wxString& domain) const
 {
     if ( origString.empty() )
-        return origString;
+        return GetUntranslatedString(origString);
 
     const wxString *trans = NULL;
     wxMsgCatalog *pMsgCat;
 
     const wxString *trans = NULL;
     wxMsgCatalog *pMsgCat;
@@ -2646,14 +2685,29 @@ const wxString& wxLocale::GetString(const wxString& origString,
 #endif // __WXDEBUG__
 
         if (n == size_t(-1))
 #endif // __WXDEBUG__
 
         if (n == size_t(-1))
-            return origString;
+            return GetUntranslatedString(origString);
         else
         else
-            return n == 1 ? origString : origString2;
+            return GetUntranslatedString(n == 1 ? origString : origString2);
     }
 
     return *trans;
 }
 
     }
 
     return *trans;
 }
 
+WX_DECLARE_HASH_SET(wxString, wxStringHash, wxStringEqual,
+                    wxLocaleUntranslatedStrings);
+
+/* static */
+const wxString& wxLocale::GetUntranslatedString(const wxString& str)
+{
+    static wxLocaleUntranslatedStrings s_strings;
+
+    wxLocaleUntranslatedStrings::iterator i = s_strings.find(str);
+    if ( i == s_strings.end() )
+        return *s_strings.insert(str).first;
+
+    return *i;
+}
+
 wxString wxLocale::GetHeaderValue(const wxString& header,
                                   const wxString& domain) const
 {
 wxString wxLocale::GetHeaderValue(const wxString& header,
                                   const wxString& domain) const
 {
@@ -2737,20 +2791,20 @@ bool wxLocale::IsAvailable(int lang)
         return false;
 
 #elif defined(__UNIX__)
         return false;
 
 #elif defined(__UNIX__)
-    
-    // Test if setting the locale works, then set it back. 
-    wxMB2WXbuf oldLocale = wxSetlocale(LC_ALL, wxEmptyString);
-    wxMB2WXbuf tmp = wxSetlocaleTryUTF(LC_ALL, info->CanonicalName);
+
+    // Test if setting the locale works, then set it back.
+    const char *oldLocale = wxSetlocale(LC_ALL, "");
+    const char *tmp = wxSetlocaleTryUTF8(LC_ALL, info->CanonicalName);
     if ( !tmp )
     {
         // Some C libraries don't like xx_YY form and require xx only
     if ( !tmp )
     {
         // Some C libraries don't like xx_YY form and require xx only
-        tmp = wxSetlocaleTryUTF(LC_ALL, info->CanonicalName.Left(2));
+        tmp = wxSetlocaleTryUTF8(LC_ALL, info->CanonicalName.Left(2));
         if ( !tmp )
             return false;
     }
     // restore the original locale
         if ( !tmp )
             return false;
     }
     // restore the original locale
-    wxSetlocale(LC_ALL, oldLocale);    
-#endif 
+    wxSetlocale(LC_ALL, oldLocale);
+#endif
 
     return true;
 }
 
     return true;
 }
@@ -2811,7 +2865,7 @@ bool wxLocale::AddCatalog(const wxString& szDomain,
 // accessors for locale-dependent data
 // ----------------------------------------------------------------------------
 
 // accessors for locale-dependent data
 // ----------------------------------------------------------------------------
 
-#ifdef __WXMSW__
+#if defined(__WXMSW__)
 
 /* static */
 wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
 
 /* static */
 wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
@@ -2851,7 +2905,33 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
     return str;
 }
 
     return str;
 }
 
-#else // !__WXMSW__
+#elif defined(__WXOSX__)
+
+/* static */
+wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
+{
+    wxCFRef<CFLocaleRef> userLocaleRef(CFLocaleCopyCurrent());
+    CFTypeRef cfstr;
+    switch ( index )
+    {
+        case wxLOCALE_THOUSANDS_SEP:
+            cfstr = CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator);
+            break;
+
+        case wxLOCALE_DECIMAL_POINT:
+            cfstr = CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator);
+            break;
+
+        default:
+            wxFAIL_MSG( "Unknown locale info" );
+    }
+
+    wxMacCFStringHolder
+        str(CFStringCreateCopy(NULL, static_cast<CFStringRef>(cfstr)));
+    return str.AsString();
+}
+
+#else // !__WXMSW__ && !__WXMAC__
 
 /* static */
 wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
 
 /* static */
 wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
@@ -2888,7 +2968,7 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
     }
 }
 
     }
 }
 
-#endif // __WXMSW__/!__WXMSW__
+#endif // platform
 
 // ----------------------------------------------------------------------------
 // global functions and variables
 
 // ----------------------------------------------------------------------------
 // global functions and variables