I am using Strings.resx
, Strings.de.resx
, etc. to localize Xamarin.Forms
app.
I need to be able to change interface language at run time, and it (allmost) works.
Xamarin generates static class Strings
in namespace MyProject.Resources
from resource files, and I use those values to display strings on UI.
When doing it from code, it works flawlessly:
await DisplayAlert(Strings.lblConfirmDelete, Strings.lblDeleteMessage, Strings.lblOK, Strings.lblCancel));
Problem is - not all attributes defined this way from XAML are updated when I change UI culture during runtime. Buttons, Labels, Entry properties (Placeholder etc.) change as they should, but PageTitle, Toolbaritems, and some other properties remain in previous language.
I presume that some of these are populated when Page is first created, and are not updated on culture (and UI culture) change.
So, basically, I need a way to combine {DynamicResource ...}
with values from resources.
I know that DynamicResource
is ment to be used with Resource dictionary, but that is not a good way to store language translations for localization.
I tried
Text="{DynamicResource {x:Static lr:Strings.lblAddNew}}"
also not working.
Is there a way of refreshing page dynamicaly?
I also tried calling
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(MainListPage));
from Appearing event for that page, but that also does not work.
Any ideas?
Part of XAML file
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyProject.View"
xmlns:rs="clr-namespace:MMPI"
x:Class="MyProject.MainListPage"
xmlns:lr="clr-namespace:MyProject.Resources"
Title="{x:Static lr:Strings.appName}"
>
<ContentPage.ToolbarItems>
<ToolbarItem
Name="New"
Order="Primary"
Priority="0"
Text="{x:Static lr:Strings.lblAddNew}"
Clicked="New_Clicked"
>
When i encountered that challenge in a project I resolved it by using a simple class
ResourceLoader
and making use ofINotifyPropertyChanged
.You can access the
Instance
property from anywhere and change the culture. All String that are bound to the index would update.The
ResourceManager
instance injected into the constructor must be set up appropriately.To display the localized strings in your application you need to bind through the indexer like so:
Since it is now bound it should update when you call
ResourceLoader.SetCultureInfo
because theItem[]
'PropertyName' is causing bound controls to re-fetch the values to their bound keys.Update
I just tested it if i was talking bogus and for some reason the property changed didn't work. I've added a different approach below, which is close to what i'm using in production i urge you to add some kind of weak reference 'caching' instead of the simple list holding all the string resources (otherwise they will be kept forever)
I'm keeping above for reference.
StringResource:
XAML Binding
Update 2
Came across this link where they implemented it similarly to my first approach. Maybe you can give it a try.
Update 3
Fixed the first approach. Both are working now. What was needed was
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
instead ofthis.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(Item[]));