Reputation: 43
Based on the answer in this thread Change Language for Xamarin Android App using Resources I change the language while my app is running, using this code.
using Java.Util.Locale locale = new Java.Util.Locale(cultureInfo.TwoLetterISOLanguageName);
Java.Util.Locale.SetDefault(Java.Util.Locale.Category.Format, locale);
var config = Resources.Configuration;
config.SetLocale(locale);
BaseContext.CreateConfigurationContext(config);
It works as it should. Except when, for some reason that I have not found yet, it does not! The locale is changed back to the original while my app is running. I have not been able to reproduce it yet... Any ideas?
Thanks in advance.
Upvotes: 1
Views: 979
Reputation: 9224
If you used xamarin forms, you can use Xamarin.Forms String and Image Localization to achieve it.
For example. I add Change Button
Localization for English and Janpanese.
Then I used in the xaml.
<StackLayout>
<Label Text="{x:Static resources:AppResources.NotesLabel}"
WidthRequest="300"
HorizontalOptions="CenterAndExpand"
VerticalOptions="Start"/>
<Entry Placeholder="{x:Static resources:AppResources.NotesPlaceholder}"
WidthRequest="300"
HorizontalOptions="CenterAndExpand"
VerticalOptions="Start"/>
<Button Text="{x:Static resources:AppResources.AddButton}"
WidthRequest="300"
HorizontalOptions="CenterAndExpand"
VerticalOptions="Start"/>
<Button Text="{x:Static resources:AppResources.ChangeButton}" Clicked="Button_Clicked"></Button>
</StackLayout>
When I click the Button, I will change the language and refresh this page.
public partial class LocalizedXamlPage : ContentPage
{
public LocalizedXamlPage()
{
InitializeComponent();
}
private void Button_Clicked(object sender, System.EventArgs e)
{
CultureInfo.CurrentUICulture = new CultureInfo("ja-JP", false);
App.Current.MainPage =new NavigationPage( new LocalizedXamlPage());
}
}
Here is running GIF(I can not reproduce your issue, If you change the text at the runtime, please refresh view).
Here is my demo.
https://github.com/851265601/LocalzationDemo
================Update=======================
. I want to change the locale so the keyboard and the date picker and the time picker matches the application's locale and not the devices locale. For example my device language is English and my apps language is Greek. So I want the numeric keyboard decimal point to be comma and not dot and I want the OK and Cancel buttons in the date picker to be in Greek.
Do you want to achieve the result like following GIF?
If so, you can create a BaseActivity.cs
and LanguageManager
public class BaseActivity : FormsAppCompatActivity
{
protected override void AttachBaseContext(Context @base)
{
base.AttachBaseContext(LanguageManager.LoadLanguage(@base));
}
}
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
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;
}
}
Then use your MainActivity to extend the BaseActivity
, and add the public static MainActivity instance;
in MainActivity
.
[Activity(Label = "UsingResxLocalization", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : BaseActivity
{
public static MainActivity instance;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
instance = this;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
}
In your depdenceService, use following code to change it and restart your application.
[assembly: Dependency(typeof(ChangeLanguageService))]
namespace UsingResxLocalization.Droid
{
public class ChangeLanguageService : IChangeService
{
public void ChangeIanguage(string lang)
{
LanguageManager.ChangeLanguage(MainActivity.instance, "en");
//restart your application.
Intent intent = new Intent(MainActivity.instance, typeof(MainActivity));
intent.SetFlags(ActivityFlags.ClearTask | ActivityFlags.NewTask);
MainActivity.instance.StartActivity(intent);
}
}
}
Upvotes: 3