Xamarin.Forms localization when using a shared project
namespace Langham | |
{ | |
public class AndroidLocale : Locale | |
{ | |
public AndroidLocale() : base() | |
{ | |
} | |
public override void ApplyLocale() | |
{ | |
Thread.CurrentThread.CurrentCulture = CI; | |
Thread.CurrentThread.CurrentUICulture = CI; | |
} | |
protected override string GetNetLanguage() | |
{ | |
var androidLocale = Java.Util.Locale.Default; | |
var androidLanguage = androidLocale.ToString().Replace("_", "-"); | |
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 | |
netLanguage = "ms"; // closest supported | |
break; | |
case "in-ID": // "Indonesian (Indonesia)" has different code in .NET | |
netLanguage = "id-ID"; // correct code for .NET | |
break; | |
case "gsw-CH": // "Schwiizertüütsch (Swiss German)" not supported .NET culture | |
netLanguage = "de-CH"; // closest supported | |
break; | |
// add more application-specific cases here (if required) | |
// ONLY use cultures that have been tested and known to work | |
} | |
Debug.WriteLine($".NET Language/Locale: {netLanguage}"); | |
return netLanguage; | |
} | |
protected override string GetNetFallbackLanguage(string languageCode) | |
{ | |
var netLanguage = languageCode; // use the first part of the identifier (two chars, usually); | |
switch (languageCode) | |
{ | |
case "gsw": | |
netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app | |
break; | |
// add more application-specific cases here (if required) | |
// ONLY use cultures that have been tested and known to work | |
} | |
return netLanguage; | |
} | |
} | |
} |
namespace Langham.Model | |
{ | |
public interface ILocale | |
{ | |
string Native(string key); | |
string NativeOrKey(string key); | |
} | |
} |
namespace Langham | |
{ | |
public class iOSLocale : Locale | |
{ | |
public iOSLocale() : base() | |
{ | |
} | |
public override void ApplyLocale() | |
{ | |
Thread.CurrentThread.CurrentCulture = CI; | |
Thread.CurrentThread.CurrentUICulture = CI; | |
} | |
protected override string GetNetLanguage() | |
{ | |
var netLanguage = DEFAULT_LANGUAGE; | |
if (NSLocale.PreferredLanguages.Length == 0) | |
return netLanguage; | |
var iOSLanguage = NSLocale.PreferredLanguages[0]; | |
Debug.WriteLine($"iOS Language: {iOSLanguage}"); | |
netLanguage = iOSLanguage; | |
//certain languages need to be converted to CultureInfo equivalent | |
switch (iOSLanguage) | |
{ | |
case "ms-MY": // "Malaysian (Malaysia)" not supported .NET culture | |
case "ms-SG": // "Malaysian (Singapore)" not supported .NET culture | |
netLanguage = "ms"; // closest supported | |
break; | |
case "gsw-CH": // "Schwiizertüütsch (Swiss German)" not supported .NET culture | |
netLanguage = "de-CH"; // closest supported | |
break; | |
// add more application-specific cases here (if required) | |
// ONLY use cultures that have been tested and known to work | |
} | |
Debug.WriteLine($".NET Language/Locale: {netLanguage}"); | |
return netLanguage; | |
} | |
protected override string GetNetFallbackLanguage(string languageCode) | |
{ | |
var netLanguage = languageCode; // use the first part of the identifier (two chars, usually); | |
switch (languageCode) | |
{ | |
case "pt": | |
netLanguage = "pt-PT"; // fallback to Portuguese (Portugal) | |
break; | |
case "gsw": | |
netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app | |
break; | |
// add more application-specific cases here (if required) | |
// ONLY use cultures that have been tested and known to work | |
} | |
return netLanguage; | |
} | |
} | |
} |
namespace Langham | |
{ | |
public abstract class Locale : Langham.Model.ILocale | |
{ | |
protected const string DEFAULT_LANGUAGE = "en"; | |
public CultureInfo CI { get; } | |
public Locale() | |
{ | |
CI = GetCurrentCultureInfo(); | |
} | |
public string NativeOrKey(string key) | |
{ | |
string translated = Fetch(key); | |
if (translated == null) | |
return key; | |
return translated; | |
} | |
public string Native(string key) | |
{ | |
string translated = Fetch(key); | |
if (translated == null) | |
throw new ArgumentException($"Key {key} was not found in resources", key); | |
return translated; | |
} | |
string Fetch(string key) | |
{ | |
var manager = new ResourceManager("Langham.Resx.AppResources", typeof(Locale).GetTypeInfo().Assembly); | |
return manager.GetString(key, CI); | |
} | |
public abstract void ApplyLocale(); | |
protected abstract string GetNetLanguage(); | |
protected abstract string GetNetFallbackLanguage(string languageCode); | |
protected CultureInfo GetCurrentCultureInfo() | |
{ | |
var netLanguage = GetNetLanguage(); | |
CultureInfo ci = null; | |
try | |
{ | |
ci = new CultureInfo(netLanguage); | |
} | |
catch (CultureNotFoundException) | |
{ | |
// platform locale not valid .NET culture (eg. "en-ES" : English in Spain on iOS) | |
// fallback to first characters, in this case "en" | |
try | |
{ | |
var fallback = GetNetFallbackLanguage(LanguageCode(netLanguage)); | |
Debug.WriteLine($"{netLanguage} failed, trying {fallback}"); | |
ci = new CultureInfo(fallback); | |
} | |
catch (CultureNotFoundException) | |
{ | |
// fallback not valid, falling back to default language | |
Debug.WriteLine($"{netLanguage} couldn't be set, using '{DEFAULT_LANGUAGE}'"); | |
ci = new CultureInfo(DEFAULT_LANGUAGE); | |
} | |
} | |
return ci; | |
} | |
private string LanguageCode(string platformCultureString) | |
{ | |
var platformString = platformCultureString.Replace("_", "-"); // .NET expects dash, not underscore | |
var dashIndex = platformString.IndexOf("-", StringComparison.Ordinal); | |
if (dashIndex == -1) return platformString; | |
var parts = platformString.Split('-'); | |
return parts[0]; | |
} | |
} | |
} |
namespace Langham | |
{ | |
// You exclude the 'Extension' suffix when using in Xaml markup | |
[ContentProperty("Text")] | |
public class TranslateExtension : IMarkupExtension | |
{ | |
Locale locale; | |
public TranslateExtension() | |
{ | |
locale = Container.Current.Resolve<Locale>(); | |
} | |
public string Text { get; set; } | |
public object ProvideValue(IServiceProvider serviceProvider) | |
{ | |
if (Text == null) | |
return ""; | |
return locale.Native(Text); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment