Milad
Milad

Reputation: 473

Xamarin Android Locale doesn't change

I wanna change the locale in my APP... I read a lot of articles and now I have this code, it doesn't work and doesn't give me an error:

  1. My LanguageActivity:

    public class LanguageActivity : BaseActivity {

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.Language);
    
        LanguageManager.ChangeLanguage(this, "fa");
    
        Intent intent = new Intent(this, typeof(MainActivity));
        intent.SetFlags(ActivityFlags.ClearTask | ActivityFlags.NewTask);
        StartActivity(intent);
    }
    

    }

  2. My BaseActivity:

    public class BaseActivity : Activity {

    protected override void AttachBaseContext(Context @base)
    {
        base.AttachBaseContext(LanguageManager.LoadLanguage(@base));
    }
    

    }

  3. My LanguageManager:

    public 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
        Locale 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;
    }
    

    }

Why doesn't it work? I read this and this. They're using the same method!

PS1: I have values-fa folder and Strings.xml there. When I change the language in the phone's setting, I see the changes. So it works when I change the locale on the phone!

PS2: I simplified the code, that's why I removed the SharedPreference part in LanguageActivity!

PS3: Download the project: Download

Upvotes: 0

Views: 823

Answers (3)

Leo Zhu
Leo Zhu

Reputation: 15001

sorry for reply so later,i'm off duty at weekends,i test your project.the issue is you didn't let your LoginActivity extends BaseActivity.you should let all activities extends BaseActivity.

change

public class LoginActivity : Activity

to

public class LoginActivity : BaseActivity

Upvotes: 1

FreakyAli
FreakyAli

Reputation: 16547

For Xamarin.Android you can do it like this :

  • Create your own context wrapper like this :

     public class MyContextWrapper : ContextWrapper
    {
       public MyContextWrapper(Context context) : base(context)          
       {
    
       }
    public static Locale getSystemLocaleLegacy(Configuration config)
    {
        return config.Locale;
    }
    public static Locale getSystemLocale(Configuration config)
    {
        return config.Locales.Get(0);
    }
    public static void setSystemLocaleLegacy(Configuration config, Locale locale)
    {
        config.SetLocale(locale);
        config.SetLayoutDirection(locale);
    }
    public static void setSystemLocale(Configuration config, Locale locale)
    {
        config.SetLocale(locale);
        config.SetLayoutDirection(locale);
    }
    
    public static ContextWrapper wrap(Context context, string language)
    {
        Configuration config = context.Resources.Configuration;
        Locale sysLocale = null;
        if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
        {
            sysLocale = getSystemLocale(config);
        }
        else
        {
            sysLocale = getSystemLocaleLegacy(config);
        }
    
        Locale locale;
    
        if (language == "en")
        {
            locale = new Locale(language, "US");
        }
        else if (language == "zh")
        {
            locale = new Locale(language, "CN");
        }
        else
        {
            locale = new Locale("en", "US");
        }
    
        Locale.Default = (locale);
    
        if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
        {
            setSystemLocale(config, locale);
        }
        else
        {
            setSystemLocaleLegacy(config, locale);
        }
    
        if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr1)
        {
            context = context.CreateConfigurationContext(config);
        }
        else
        {
            context.Resources.UpdateConfiguration(config, context.Resources.DisplayMetrics);
        }
    
        return new MyContextWrapper(context);
    }
    

    }

  • Add the following code to your activities:

     protected override void AttachBaseContext(Context @base)
     {
        try
        {              
            base.AttachBaseContext(MyContextWrapper.wrap(@base,"Your_language"));
        }
        catch{}
     }
    

Make sure to restart the current activity every time your language changes.

Also, try updating my code as per your language requirements

Goodluck,

Feel free to get back if you have queries

Upvotes: 0

Joachim Haglund
Joachim Haglund

Reputation: 820

for the record, i have done this in the past and changing language in the app is a bad idea. it never really works well, and usually brings alot of bugs. Its much better to just let the app language be determined by the phones language setting.

if you really have to change language via the app though you need to set the locale in the configuration:

Configuration config = BaseContext.Resources.Configuration;
config.Locale = myLocale;
BaseContext.Resources.UpdateConfiguration(config, BaseContext.Resources.DisplayMetrics);

where MyLocale is the language to set, for example

var myLocale = new Locale("en");

edit: updated to xamarin code

Upvotes: 0

Related Questions