Created
May 2, 2017 06:58
-
-
Save JannieT/8d789ca837679cbd59244564160ebe32 to your computer and use it in GitHub Desktop.
Xamarin.Forms localization when using a shared project
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Langham.Model | |
{ | |
public interface ILocale | |
{ | |
string Native(string key); | |
string NativeOrKey(string key); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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