Easy and cross-platform localization (Xamarin & .NET)

I embarked on my software journey back in 2000, and today, I passionately craft high-quality mobile apps, delivering to thousands of users.
Search for a command to run...

I embarked on my software journey back in 2000, and today, I passionately craft high-quality mobile apps, delivering to thousands of users.
No comments yet. Be the first to comment.
I started writing Flutter and Dart code a few weeks ago for a real production project that we are migrating from another tech stack (Xamarin). Soon I started using the power of code generation libraries like freezed, json_serializable, slang_build_ru...

Capturing network traffic between your application and your server is a handy way of checking and debugging the data you are sending and what comes back from the server. Charles Proxy shows network calls in a sequence or as a tree structure, includin...

Upgrading your target SDK to 26+ (Android 8) can break your push notifications all of a sudden. Fortunately it's very easy to fix.

Once we change the target Android version to 26 or higher, the app icon suddenly gets messed up, from a full-size icon to a tiny, hard to notice thing inside a white shape (a circle on the default Google launcher). I delayed upgrading to 26+ because ...

When Apple realised a LinearLayout could be useful for developers...

Sooner or later we all need to localize an app in multiple languages. Each platform provides its way of localizing strings and you may wonder how to share locale files between them.
If you are a .NET dev, Resx is probably the first thing crossing your mind, and that´s fine for Visual Studio. It can be implemented on Xamarin as well but you´ll find yourself (and potentially your client) editing XML files with the following format:
<data name="Key" xml:space="preserve">
<value>KeyValue</value>
<comment>Some comments</comment>
</data>
At least at the time of this writing Xamarin does not provide a Resx editor. Besides, you need to write code for manually loading the correct language, based normally on the current system culture. Xamarin has a nice tutorial on how to do it. You´ll find even iOS, Android and Win phone concrete implementations and a bunch of useful details. They also explain how to automatically bind translations in XAML creating a IMarkupExtension class.
The problem is:
I don´t want to repeat all that process in every project, or even copy-paste across projects and platforms.
I just want a library to do it for me
I don´t like/want Resx files and I don´t want to have a client editing them
I love simplicity and that´s why I created a lightweight utility for this matter. My idea was based on two concepts:
Simpler locale files (similar to java .properties format)
Straightforward setup and initialization
I18N-Portable is a Nuget package
A locale is just a [locale].txt file with key=value pairs. You place these files on a PCL project once, under a directory called “Locales”. They will be shared across platforms:
# this is a comment
key1 = one
key2 = two
key3 = translation with \nmultiple \nlines
I18N.Current
.SetFallbackLocale("en")
.Init(GetType().GetTypeInfo().Assembly);
That´s all you need. Simple enough?
You put this line at your PCL code, normally in any method executed during app initialization.
What just happen?
The Init() method tells I18N-Portable which assembly is hosting the locales. Now the library figures out the current system culture and tries to load a matching locale. If you didn´t provide a locale for the current culture, it will fall back to English (“en.txt”).
From now on you can get any translation with a string method extension from anywhere in your app PCL and/or platform projects:
var translation = "key1".Translate(); // one
Sure. You can bind any text view to a particular key, from XAML (Xamarin.Forms, UWP, etc) and classic Android/iOS if your Mvvm framework implements bindings:
XAML:
<Button Content="{Binding [key]}" />
Xamarin.Forms XAML:
<Button Text="{Binding [key]}" />
Android with MvvmCross:
<TextView local:MvxBind="Text [key]" />
iOS with MvvmCross:
bindingSet.Bind(view).To("[key]");
To make this work, a simple indexer is needed in your ViewModel (I usually do this in a BaseViewModel once):
public string this[string key] => key.Translate();
More handy stuff and details are available at the GitHub repo
Cheers!