Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Change localization based on user country

User has a flag, from where he is from (1 - Slovenia, 2 - Croatia) and I want to change locale and app language based on this flag.
When I'm on login page, user can choose what language he wants by pressing on the flag (button text and labels are translated successfully when this flags are pressed).
Code for changing language on loging page (arg is si or hr (name for slovenian and croatian language)):

private void ExecuteOnLanguageSelectedCommand(string arg)
{
    if (arg == null)
        return;
    DependencyService.Get<ILocalize>().SetLocale(new CultureInfo(arg));
    ...

On app load, I check if language is set in Application settings or secure storage, if neither, then I go with phone language. This also works as expected, language is changed.

public App()
{
    InitializeComponent();

    ...

    CultureInfo ci = null;
    string localeFromSS = SecureStorage.GetAsync("locale").Result;
    if (localeFromSS != null)
        ci = new CultureInfo(localeFromSS);
    else if (ApplicationSettings.Locale != null)
        ci = new CultureInfo(ApplicationSettings.Locale);
    else 
        ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();

    DependencyService.Get<ILocalize>().SetLocale(ci);

    ...

But when user logs in and I want to change app language based on his location, language doesn't change, it stays like it was before. I tried changing language in LoginViewModel inside and outside mainUI thread:

...
string locale = await SecureStorage.GetAsync("locale").ConfigureAwait(false);
DependencyService.Get<ILocalize>().SetLocale(new CultureInfo(locale));
Device.BeginInvokeOnMainThread(async () =>
{
    // string locale = await SecureStorage.GetAsync("locale").ConfigureAwait(false);
    // DependencyService.Get<ILocalize>().SetLocale(new CultureInfo(locale));
    Application.Current.MainPage = new AppShell();
    await Shell.Current.GoToAsync("//main").ConfigureAwait(false);
});
...

Tried calling it in auth manager where I get locale info, but nothing changes it.

But when app is closed and opened, so it hits App() in App.xaml.cs constructor it changes language, the strange thing is it works in LoginPage.
Also, this is how I'm rerouting user, when he logs in, if that might help you in some way:

public App()
{
    ...
    var IsLoggedIn = SecureStorage.GetAsync("isLoggedIn").Result;
    var HasReadPrivacy = SecureStorage.GetAsync("HasReadPrivacy").Result;
    if (ApplicationSettings.HasConnectivity == false)
        MainPage = new NoConnectionPage();
    else if (IsLoggedIn == "1")
        if (HasReadPrivacy == "1")
            MainPage = new AppShell();
        else
            MainPage = new PrivacyPolicyPage();
    else
        MainPage = new LoginPage();
    ...

This is code in Android Localize class that I'm calling with dependancyService

public void SetLocale(CultureInfo ci)
{
    Thread.CurrentThread.CurrentCulture = ci;
    Thread.CurrentThread.CurrentUICulture = ci;
}
Tagged:

Best Answer

Answers

  • JarvanJarvan Member, Xamarin Team Xamurai
    edited October 2019

    Create a LanguageManager class and add the function method, pass the language string to change language.
    Check the code.

    private void LanguageSelect(string language)
    {   
       //var s = GetSharedPreferences("myPreference", FileCreationMode.Private).GetString("myLanguage", Locale.Default.Language);
    
        var s = GetSharedPreferences("myPreference", FileCreationMode.Private).GetString("myLanguage", language);
        LanguageManager.ChangeLanguage(this, s);
    }
    

    LanguageManager.cs

    internal class LanguageManager
    {
        private const string MYLANGUAGE = "myLanguage";
        private const string MYPREF = "myPreference";
    
        public static Context LoadLanguage(Context context)
        {
            var loadedLanguage = GetLanguage(context, Locale.Default.Language);
            return ChangeLanguage(context, loadedLanguage);
        }
    
        public static Context ChangeLanguage(Context context, string language)
        {
            SaveLanguage(context, language);
            if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
            {
                return ChangeForAPI24(context, language);
            }
            return ChangeForLegacy(context, language);
        }
    
        private static string GetLanguage(Context context, string Language)
        {
            var privatePreference = context.GetSharedPreferences(MYPREF, FileCreationMode.Private);
            return privatePreference.GetString(MYLANGUAGE, Language);
        }
    
        private static void SaveLanguage(Context context, string language)
        {
            var privatePreference = context.GetSharedPreferences(MYPREF, FileCreationMode.Private);
            var editor = privatePreference.Edit();
            editor.PutString(MYLANGUAGE, language);
            editor.Apply();
        }
    
        private static Context ChangeForAPI24(Context context, string language)
        {
            // for api >= 24
            var locale = new Locale(language);
            Locale.Default = locale;
            var configuration = context.Resources.Configuration;
            configuration.SetLocale(locale);
            configuration.SetLayoutDirection(locale);
    
            return context.CreateConfigurationContext(configuration);
        }
    
        private static Context ChangeForLegacy(Context context, string language)
        {
            var locale = new Locale(language);
            Locale.Default = locale;
            var resources = context.Resources;
            var configuration = resources.Configuration;
            configuration.Locale = locale;
            resources.UpdateConfiguration(configuration, resources.DisplayMetrics);
            return context;
        }
    }
    

    Refer to:
    https://stackoverflow.com/questions/55465355/is-there-way-to-change-language-while-app-running/55469439#55469439

  • rozman50rozman50 Member ✭✭

    Will this solution also work on iOS devices?

  • rozman50rozman50 Member ✭✭
    edited October 2019 Accepted Answer

    Turns out, it was just my mistake in setting locale. Instead of "sl-SI" I passed in "si" and instead of "hr-HR" I passed in "hr".

    I implemented this code, if anyone needs it in the future: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/localization/text?tabs=windows#platform-specific-code

Sign In or Register to comment.