]> git.saurik.com Git - wxWidgets.git/commitdiff
Fix incorrect assumptions about locales codes.
authorVáclav Slavík <vslavik@fastmail.fm>
Wed, 5 May 2010 13:50:15 +0000 (13:50 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Wed, 5 May 2010 13:50:15 +0000 (13:50 +0000)
wx incorrectly assumes that Unix locale codes have the form of xx_YY,
where both xx and yy are two characters long. This is wrong, xx is
ISO 639 code, which can often have 3 characters ("ast", "gez" etc.);
future ISO 639-6 will have up to 4 chars. Similarly, ISO 3166 has
alpha-3 variant of country codes too (even though they aren't used in
this context today).

For parsing needs, we can just look for '_' in the code. The only place
where a check for xx_YY code was performed was GetSystemLanguage().
Instead of bothering with correct check (or a heuristic), let's simply
assume locale is xx_YY code and only do alternative handling if that
assumption fails. According to the comments, this alternative handling
was for cases such as LANG=german environment on SuSE, but it's safe to
say that no modern systems do that anymore, so it's OK that this patch
is marginally less efficient on such legacy systems.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64218 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/common/intl.cpp
src/common/translation.cpp

index d27fc4899d0c29586a618b91fcf5b1ab30eaa630..cffa1cd034f8304b37c14a8f31d4e07e99fce198 100644 (file)
 // constants
 // ----------------------------------------------------------------------------
 
-// the constants describing the format of ll_CC 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")
 
 // ============================================================================
@@ -99,10 +94,10 @@ static wxLocale *wxSetLocale(wxLocale *pLocale);
 namespace
 {
 
-// get just the language part
+// get just the language part ("en" in "en_GB")
 inline wxString ExtractLang(const wxString& langFull)
 {
-    return langFull.Left(LEN_LANG);
+    return langFull.BeforeFirst('_');
 }
 
 // helper functions of GetSystemLanguage()
@@ -111,7 +106,11 @@ inline wxString ExtractLang(const wxString& langFull)
 // get everything else (including the leading '_')
 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__
@@ -642,94 +641,92 @@ bool wxLocale::Init(int language, int flags)
         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] == wxS('_')) )
-    {
-        // 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;
+    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;
 
-        // did we change it?
-        if ( lang != langOrig )
-        {
-            langFull = lang + ExtractNotLang(langFull);
-        }
+    // did we change it?
+    if ( lang != langOrig )
+    {
+        langFull = lang + ExtractNotLang(langFull);
+    }
 
-        // 1. Try to find the language either as is:
-        // a) With modifier if set
-        if ( !modifier.empty() )
+    // 1. Try to find the language either as is:
+    // a) With modifier if set
+    if ( !modifier.empty() )
+    {
+        wxString langFullWithModifier = langFull + modifier;
+        for ( i = 0; i < count; i++ )
         {
-            wxString langFullWithModifier = langFull + modifier;
-            for ( i = 0; i < count; i++ )
-            {
-                if ( ms_languagesDB->Item(i).CanonicalName == langFullWithModifier )
-                    break;
-            }
+            if ( ms_languagesDB->Item(i).CanonicalName == langFullWithModifier )
+                break;
         }
+    }
 
-        // b) Without modifier
-        if ( modifier.empty() || i == count )
+    // b) Without modifier
+    if ( modifier.empty() || i == count )
+    {
+        for ( i = 0; i < count; i++ )
         {
-            for ( i = 0; i < count; i++ )
-            {
-                if ( ms_languagesDB->Item(i).CanonicalName == langFull )
-                    break;
-            }
+            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 )
+    // 2. If langFull is of the form xx_YY, try to find xx:
+    if ( i == count && !justLang )
+    {
+        for ( i = 0; i < count; i++ )
         {
-            for ( i = 0; i < count; i++ )
+            if ( ms_languagesDB->Item(i).CanonicalName == lang )
             {
-                if ( ms_languagesDB->Item(i).CanonicalName == lang )
-                {
-                    break;
-                }
+                break;
             }
         }
+    }
 
-        // 3. If langFull is of the form xx, try to find any xx_YY record:
-        if ( i == count && justLang )
+    // 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++ )
         {
-            for ( i = 0; i < count; i++ )
+            if ( ExtractLang(ms_languagesDB->Item(i).CanonicalName)
+                    == langFull )
             {
-                if ( ExtractLang(ms_languagesDB->Item(i).CanonicalName)
-                        == langFull )
-                {
-                    break;
-                }
+                break;
             }
         }
     }
-    else // not standard format
+
+
+    if ( i == count )
     {
-        // try to find the name in verbose description
+        // 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++ )
         {
             if (ms_languagesDB->Item(i).Description.CmpNoCase(langFull) == 0)
index b34173f063614bc1c9fa29ae16e0c9c28ee72064..5e259574d5c22c816c7e3d839b80d9571ce54851 100644 (file)
@@ -65,25 +65,6 @@ const size_t32 MSGCATALOG_MAGIC_SW = 0xde120495;
 
 #define TRACE_I18N wxS("i18n")
 
-// the constants describing the format of ll_CC locale string
-static const size_t LEN_LANG = 2;
-
-// ----------------------------------------------------------------------------
-// global functions
-// ----------------------------------------------------------------------------
-
-namespace
-{
-
-// get just the language part
-inline wxString ExtractLang(const wxString& langFull)
-{
-    return langFull.Left(LEN_LANG);
-}
-
-} // anonymous namespace
-
-
 // ============================================================================
 // implementation
 // ============================================================================
@@ -1428,9 +1409,10 @@ bool wxTranslations::LoadCatalog(const wxString& domain, const wxString& lang)
     // Also try just base locale name: for things like "fr_BE" (Belgium
     // French) we should use fall back on plain "fr" if no Belgium-specific
     // message catalogs exist
-    if ( lang.length() > LEN_LANG && lang[LEN_LANG] == wxS('_') )
+    wxString baselang = lang.BeforeFirst('_');
+    if ( lang != baselang )
     {
-        if ( m_loader->LoadCatalog(this, domain, ExtractLang(lang)) )
+        if ( m_loader->LoadCatalog(this, domain, baselang) )
             return true;
     }
 
@@ -1772,9 +1754,6 @@ bool wxFileTranslationsLoader::LoadCatalog(wxTranslations *translations,
                                            const wxString& domain,
                                            const wxString& lang)
 {
-    wxCHECK_MSG( lang.length() >= LEN_LANG, false,
-                 "invalid language specification" );
-
     wxString searchPath = GetFullSearchPath(lang);
 
     wxLogTrace(TRACE_I18N, wxS("Looking for \"%s.mo\" in search path \"%s\""),