Localization in iOS not working properly

HortensiaMusetescuHortensiaMusetescu USMember
edited March 2016 in Xamarin.Forms

Dear All,

While trying to add translated strings to my iOS forms project, the translated strings will not display. I have done every step from the tutorials available so far.

The catch is that in my Output I get the language codes as es-US, ro-US, and so on. These are not valid language codes and the resource files do not contain them.

My question is: is this behavior normal? To return the language code as es-US?

This is in the iPhoneSimulator so far. Thank you!

Bellow is a code snipped for the GetCulture and SetLocale methods:

      public System.Globalization.CultureInfo GetCurrentCultureInfo()
      {
        var netLanguage = "en";
        var prefLanguageOnly = "en";
        if (NSLocale.PreferredLanguages.Length > 0)
        {
            var pref = NSLocale.PreferredLanguages[0];
            prefLanguageOnly = pref.Substring(0, 2);
            if (prefLanguageOnly == "pt")
            {
                if (pref == "pt")
                    pref = "pt-BR"; // get the correct Brazilian language strings from the PCL RESX (note the local iOS folder is still "pt")
                else
                    pref = "pt-PT"; // Portugal
            }
            netLanguage = pref.Replace("_", "-");
            Console.WriteLine("preferred language:" + netLanguage);
        }
        System.Globalization.CultureInfo ci = null;
        try
        {
            ci = new System.Globalization.CultureInfo(netLanguage);
        }
        catch
        {
            // iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
            // fallback to first characters, in this case "en"
            ci = new System.Globalization.CultureInfo(prefLanguageOnly);
        }
        return ci;
    }

     public void SetLocale()
    { 
            var ci = new CultureInfo (GetCurrentCultureInfo());
        Thread.CurrentThread.CurrentCulture = ci;
        Thread.CurrentThread.CurrentUICulture = ci;
    }

Answers

  • HortensiaMusetescuHortensiaMusetescu USMember

    Still need some help with this guys ....

  • AllisonTaylorAllisonTaylor USUniversity

    Hello,
    I have noticed that NSLocale.PreferredLanguages contains specific culture values constructed using whatever combination of Language and Location you have set on the device. So if your Language is set to Spanish and your Location is set to United States, then yes, "es-US" is expected. But as you mentioned, this code could very well not exist in the list of .NET Framework culture values. What I do for RESX translations in this case is just use the language only portion (your value prefLanguageOnly). In other words, if the value is not in CultureTypes.AllCultures, I just use the 1st 2 chars for the translation. Hope this helps.

  • TonyDTonyD ✭✭✭ USMember ✭✭✭

    @HortensiaMusetescu

    We get this as well (various combos of culture). We had to do some hacky things to make it work. I am attaching a snippet below. I'm not proud of this but it worked:

    `public System.Globalization.CultureInfo GetCurrentCultureInfo ()
    {
    var netLanguage = "en";
    System.Globalization.CultureInfo result = new System.Globalization.CultureInfo ("en-us");
    if (NSLocale.PreferredLanguages.Length > 0) {
    var pref = NSLocale.PreferredLanguages [0];
    netLanguage = pref.Replace ("_", "-"); // turns pt_BR into pt-BR
    } else
    return result;

            bool bHadException = false;
            try
            {
                result = new System.Globalization.CultureInfo (netLanguage);
    
            }
            catch (Exception ex) {
                if (!(ex is System.Globalization.CultureNotFoundException)) {
                    App.Report (ex);
    
                }
                bHadException = true;
            }
    
            if (bHadException) {
                try
                {
                    bHadException = false;
                    string[] vParts = netLanguage.Split(new char[] {'-'});
                    if (vParts.Length == 2)
                    {
                        // de-US -> de-de
                        result = new System.Globalization.CultureInfo (vParts[0] + "-" + vParts[0]);
                    }
    
                }
                catch (Exception ex) {
                    if (!(ex is System.Globalization.CultureNotFoundException)) {
                        App.Report (ex);
    
                    }
                    bHadException = true;
                }
            }
    
            return result == null ? new System.Globalization.CultureInfo ("en-us") : result;
        }`
    
  • SteveShaw.5557SteveShaw.5557 ✭✭✭ USMember ✭✭✭
    edited September 2016

    FWIW, both the answers don't distinguish between Language (English, French) and Region or Culture (date and currency formatting).

    Language is CurrentUICulture in .Net, NSLocale.PreferredLanguages[0] in iOS.

    Region or Culture is CurrentCulture in .Net, NSLocale.CurrentLocale in iOS.

    For example, user could be using formatting appropriate for Germany, but speaking English.

    IMPLICATION: Just because my app lacks support for German language, so I show them English texts, would be no excuse to use the default en-US region when formatting dates for the user!

    (In Xamarin, CurrentCulture is not reflecting the device's CurrentLocale, at least on iOS simulator. This seems to be a Xamarin bug - both CurrentCulture and CurrentUICulture change when user changes language. So I examine the iOS objects directly, and construct .Net CultureInfo objects based on those.)

  • SteveShaw.5557SteveShaw.5557 ✭✭✭ USMember ✭✭✭
    edited September 2016

    Actually, it may be due to what iOS does: I just realized that CurrentLocale in this case is "en-SE". Not a standard combination for .NET.

    IMHO, Xamarin should only use the COUNTRY part of CurrentLocale, to determine CurrentCulture, as that corresponds to user's Region setting. Country="SE" would pick CurrentCulture="{sv-SE}". Language would only be used to set CurrentUICulture. In my example, Language="en" would pick CurrentUICulture="{en}".

    With this combination, it becomes possible to determine that date/number formatting should be for Sweden, but the language is English.

  • SteveShaw.5557SteveShaw.5557 ✭✭✭ USMember ✭✭✭
    edited September 2016

    Code to get an appropriate Locale; this is what CultureInfo.CurrentCulture should be, in my opinion:

        static CultureInfo _Locale;
        //
        public static CultureInfo Locale()
        {
            if (_Locale == null) {
                CultureInfo ci = null;
    
                #if __IOS__
                // Work around bug, where CultureInfo.CurrentCulture is based on user's LANGUAGE, instead of on their REGION (locale).
                //   (To see bug, set phone's language to English, locale to any non-English country.
                //    CultureInfo.CurrentCulture will NOT match the country.)
                //const string DEFAULT_LOCALE = "en";
                string language = NSLocale.CurrentLocale.LanguageCode;
                string country = NSLocale.CurrentLocale.CountryCode;
    
                try {
                    ci = new CultureInfo( string.Format( "{0}-{1}", language, country ) );
    
                } catch {
                    // Not a .NET standard combination; search for one that has the specified country.
                    try {
                        CultureInfo[] cultures = CultureInfo.GetCultures( CultureTypes.AllCultures );
                        foreach (CultureInfo culture in cultures) {
                            if (culture.Name.EndsWith( country )) {
                                ci = culture;
                                break;
                            }
                        }
                    } catch (Exception ex1) {
                    }
                }
    
    
                if (ci == null) {
                    // Still not recognized .NET culture; fallback to language (of Locale) only.
                    try {
                        ci = new CultureInfo( language );
    
                    } catch (Exception ex2) {
                        // Still not recognized.
                        // Use the buggy one that fails to match user's country (region).
                        ci = CultureInfo.CurrentCulture;
    
                        // ALTERNATIVE: Use default.
                        //ci = new CultureInfo( DEFAULT_LOCALE );
                    }
                }
                #endif
    
    
                #if __ANDROID__
                // TODO: Does same bug exist on Android?  If so, use native Android calls here.
                ci = CultureInfo.CurrentCulture;
                #endif
    
    
                _Locale = ci;
            }
    
            return _Locale;
        }
    

    And to clarify Language vs. Locale, here is Language:

        public static CultureInfo Language()
        {
            return CultureInfo.CurrentUICulture;
        }
    
Sign In or Register to comment.