Introduction
I was involved in development of Xamarin Forms mobile app which was targeting also Chinese market. I handled Chinese localization as any other language/region (see link here: Xamarin Forms Localization ). But with some Android phones I encountered some difficulties.
Let’s look at some code
My problematic Xamarin.Forms app used exact the same code as in official documentation- you can find it here: Xamarin.Forms Localization (Android). As a general practice with Xamarin.Forms, I used platform specific LocalizationService
which was instantiated in platform specific code and injected into common code where it was widely used.
The platform specific code handling Android localization is straightforward and simple – when Localize.GetCurrentCultureInfo()
is called, the following code is executed:
- Android native
Java.Util.Locale.Default
API is called to get phone current localization code, - convert “_” to “-” to be .NET Compliant, do some small adaptations (in
AndroidToDotnetLanguage()
method), - try to convert it to
System.Globalization.CultureInfo
, - and try to return…
if problems, then
- try to return
CultureInfo
with only language name inToDotnetFallbackLanguage()
method, - and try to return,
if it fails for the second time, then
- simply return
System.Globalization.CultureInfo("en");
Everything fine here, this code work like a charm, but…
Problem: China-based Android phones didn’t work
We had three Android phones to test in the field: two in China and one in Germany: letter was working fine (even after changing language/region), but first two had problems. Even if user settings were set to specific region, Traditional Chinese was always displayed. All three devices were running Android 7+.
Identifying the problem
I prepared some builds to including some debug info. First step was to check what localization code Androids were returning. Two of China made Androids return localization tag code “zn” – apparently first try to get .NET localization info crashed, and application fallback to second options as described above. So language was always “zh”.
When I dig deeper in this rabbit hole, I noticed that problematic Androids were returning:
zh_HK_#Hant and
zh_CN_#Hans
What was going on?
After reading some documentation I found out that Android +7 handles localization in a bit different way as pre-7 versions, more info here: https://fabiohub.wordpress.com/2016/12/31/chinese-locale-in-android/.
So, It was time to fix the problem:
Fix
Because I had localization resources already organized I just need to fix handling of mapping native language code to .NET one, so I just put some extra code to handle 3rd part of returning localization code returned by Android.
Here, initial code excerpt is shown:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
.... private string AndroidToDotnetLanguage(string androidLanguage) { Debug.WriteLine("Android Language:" + androidLanguage); var netLanguage = androidLanguage; //certain languages need to be converted to CultureInfo equivalent switch (androidLanguage) { case "ms-BN": // "Malaysian (Brunei)" not supported .NET culture case "ms-MY": // "Malaysian (Malaysia)" not supported .NET culture case "ms-SG": // "Malaysian (Singapore)" not supported .NET culture .... |
After fix:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
.... private string AndroidToDotnetLanguage(string androidLanguage) { Debug.WriteLine("Android Language:" + androidLanguage); var netLanguage = androidLanguage; // fix some special china loc andoid languages, e.g. (zh_HK_#Hant, zh_CN_#Hans) var splittedLanguageCodes = netLanguage.Split('-'); if (splittedLanguageCodes.Length > 2) { netLanguage = string.Join("-", splittedLanguageCodes.Take(2)); } //certain languages need to be converted to CultureInfo equivalent switch (androidLanguage) { case "ms-BN": // "Malaysian (Brunei)" not supported .NET culture case "ms-MY": // "Malaysian (Malaysia)" not supported .NET culture case "ms-SG": // "Malaysian (Singapore)" not supported .NET culture .... |
Conclusion
Xamarin Forms is wonderful framework: it’s open source, it’s under .NET Foundation umbrella, code share between platforms is amazing, performances are near native speed, etc… For .NET/C# developer there is no better way to develop modern mobile apps for Android, iOS or UWP.