1

I have a button with a clicked event that triggers the following:

Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("da");
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("da");
CultureInfo.CurrentCulture = new CultureInfo("da-DK", false);
CultureInfo.CurrentUICulture = new CultureInfo("da-DK", false);

Below the button, I have a Label, with the text assigned as a value in an .resx-file. The solution has various labels, on various pages, that are all set with .resx-files.

When I click the button, how can I update all pages to switch to the new culture?

Edit: My main problem here was refreshing the app/triggering the new culture. See that accepted answer for how I solved this.

eengstroem
  • 143
  • 1
  • 9

3 Answers3

1

I'm not aware of what your localization process looks like, but if it's in a standard way that can be found on the internet and you have set the CultureInfo to the localization manager, then you just need to restart the app by

        (Application.Current as App).MainPage = new AppShell();

If there is still a problem, please, just elaborate on your problem and your localization process/solution a little bit more.

krapso
  • 26
  • 1
  • 2
1

Resetting AppShell is bad idea and may lead to numerous bugs. I've used this solution and it works great. Basically, you'd need a localization manager and a markup extension:

public class LocalizationManager : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private static readonly Lazy<LocalizationManager> _instance = new(()=> new LocalizationManager());
    private LocalizationManager()
    {
        Properties.Resources.Culture = CultureInfo.CurrentUICulture;
    }
    public static LocalizationManager Instance => _instance.Value;

    public object this[string resourceKey] => Properties.Resources.ResourceManager.GetObject(resourceKey, Properties.Resources.Culture) ?? string.Empty;

    public void SetCulture(CultureInfo culture)
    {
        Properties.Resources.Culture =
        CultureInfo.DefaultThreadCurrentCulture=
        CultureInfo.DefaultThreadCurrentUICulture =
        CultureInfo.CurrentCulture =
        CultureInfo.CurrentUICulture =
        culture;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty));
    }
}
[ContentProperty(nameof(Key))]
public class LocalizationExtension : IMarkupExtension<BindingBase>
{
    public string Key { get; set; } = string.Empty;

    public BindingBase ProvideValue(IServiceProvider serviceProvider) =>
        new Binding
        {
            Mode = BindingMode.OneWay,
            Path = $"[{Key}]",
            Source = LocalizationManager.Instance,
        };

    object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) => ProvideValue(serviceProvider);
}

Add public LocalizationManager Localize => LocalizationManager.Instance; to your model. You could do it other way, this is just an example.

Adjust your xaml like <Label Text="{Binding Localize[SamplePage_Loading]}" /> where SamplePage_Loading is key of resource.

To change current language just call LocalizationManager.Instance.SetCulture(newCultureOfChoice);

Serge Misnik
  • 139
  • 10
0

I've ended up doing it this way:

First, a button has the folllowing Clicked-event in the code-behind:

private void ChosenLanguageTapped(object sender, EventArgs e)
{
    App.CultureString = new CultureInfo("culture-code", false);
    SetUIMethod(App.CultureString);
    Preferences.Set("language", App.CultureString.Name);
    Reset();
}

In my "SetUIMethod", I have the following instructions:

    public void SetUIMethod(CultureInfo culture)
{
    Thread.CurrentThread.CurrentCulture = culture;
    Thread.CurrentThread.CurrentUICulture = culture;
    CultureInfo.DefaultThreadCurrentCulture = culture;
    CultureInfo.DefaultThreadCurrentUICulture = culture;
}

So the new culture is set, and lastly, I call Reset(), which does the following:

void Reset()
{
    (Application.Current as App).MainPage.Dispatcher.Dispatch(() =>
    {
        (Application.Current as App).MainPage = new AppShell();
    });
}

I will look into Serge Misnik's answer at some point, but this is fine for now.

In regards to keeping language when the app is closed and re-opened, I used Gerald Versluis' guide here

eengstroem
  • 143
  • 1
  • 9