0
votes

We have an app written with Pages and no pattern and I want to re-write it using MVVM. Currently we use a Picker for language selection and when the culture changes we set all label.Text controls again in order to redraw them in the new language. I re-wrote the same page using MVVM and now SelectedItem in the Picker is bound to a Language object. In the setter for SelectedItem I also change the culture of my resx (AppResources.Culture) but the UI bound to it (e.g. Text="{x:Static resources:AppResources.Title) doesn't change language.

Full code in my SelectedItem setter:

            SetProperty(ref selectedLanguage, value);
            AppResources.Culture = value.Culture;
            cultureManager.SetLocale(value.Culture);

How should I update all the Text of my UI? Is there any clean way to do something like this, it seems like a basic translation need... or it wasn't meant to be done, especially not without closing the view/app?

The approaches I found for localization using IMarkupExtension and this thread on Xamarin forums which in the end effectively re-creates the page...

My goal is to ideally reload text without having to re-create the view/close the app, using MVVM and clean code. I have about 10 views so it has to be something reusable.

1

1 Answers

2
votes

Create you RESX Resources first. I use en, nl, fr for example.

enter image description here

Create the view model to binding the LocalizedResources.

 public class ViewModelBase : INotifyPropertyChanged
{
    public LocalizedResources Resources
    {
        get;
        private set;
    }

    public ViewModelBase()
    {
        Resources = new LocalizedResources(typeof(LocalizationDemoResources), App.CurrentLanguage);
    }

    public void OnPropertyChanged([CallerMemberName]string property = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

In SettingsPage, use a picker to choose the language.

   <StackLayout>
        <Label Text="{Binding Resources[PickLng]}" />
        <Picker ItemsSource="{Binding Languages}" SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}" />
    </StackLayout>

View model of SettingsPage.

public class SettingsViewModel : ViewModelBase
{
    public List<string> Languages { get; set; } = new List<string>()
    {
        "EN",
        "NL",
        "FR"
    };

    private string _SelectedLanguage;

    public string SelectedLanguage
    {
        get { return _SelectedLanguage; }
        set
        {
            _SelectedLanguage = value;
            SetLanguage();
        }
    }

    public SettingsViewModel()
    {
        _SelectedLanguage = App.CurrentLanguage;
    }

    private void SetLanguage()
    {
        App.CurrentLanguage = SelectedLanguage;
        MessagingCenter.Send<object, CultureChangedMessage>(this,
                string.Empty, new CultureChangedMessage(SelectedLanguage));
    }
}

Do not forget to binding the context.

I have upload on GitHub, you could download from DynamicallyBindingRESXResources folder on my GitHub for reference.

https://github.com/WendyZang/Test.git

enter image description here