Simple and cross platform internationalization/translations for Xamarin and .NET This is a fork from the original project that contains an addidional ReverseTranslate method. In this method, you supply a text string value in English and you get back the keyword for which you can plug into the translator to then get the corresponding translated text in the currently set language.
- Cross platform
- Simple to use:
"key".Translate()
. or("Text".ReverseTranslate()).Translate()
. - Simple and fluent initialization setup.
- Readable locale files (.txt with key/value pairs).
- Support for custom file formats (json, xml, etc)
- Light weight
- No dependencies.
- Well tested
Install it on your PCL and platform projects. From nuget package manager console:
PM> Install-Package I18NPortablewithReverseLookup
- In your PCL/Core project, create a directory called "Locales".
- Create a
{languageCode}.txt
file for each language you want to support.languageCode
can be a two letter ISO code or a culture name like "en-US". See full list here. - Set "Build Action" to "Embedded Resource" on the properties of each file
Locale content sample
# key = value (the key will be the same across locales)
one = uno
two = dos
three = tres
four = cuatro
five = cinco
# Enums are supported
Animals.Dog = Perro
Animals.Cat = Gato
Animals.Rat = Rata
Animals.Tiger = Tigre
Animals.Monkey = Mono
# Support for string.Format()
stars.count = Tienes {0} estrellas
TextWithLineBreakCharacters = Line One\nLine Two\r\nLine Three
Multiline = Line One
Line Two
Line Three
Other file formats (including custom) supported
I18N.Current
.SetNotFoundSymbol("$") // Optional: when a key is not found, it will appear as $key$ (defaults to "$")
.SetFallbackLocale("en") // Optional but recommended: locale to load in case the system locale is not supported
.SetThrowWhenKeyNotFound(true) // Optional: Throw an exception when keys are not found (recommended only for debugging)
.SetLogger(text => Debug.WriteLine(text)) // action to output traces
.SetResourcesFolder("OtherLocales") // Optional: The directory containing the resource files (defaults to "Locales")
.Init(GetType().GetTypeInfo().Assembly); // assembly where locales live
string one = "one".Translate();
string notification = "Mailbox.Notification".Translate("Diego", 3); // same as string.Format(params). Output: Hello Diego, you´ve got 3 emails
string missingKey = "missing".Translate(); // if the key is not found the output will be $key$. Output: $missing$
string giveMeNull = "missing".TranslateOrNull(); // Output: null
string dog = Animals.Dog.Translate(); // translate enum value (Animals is an Enum backed up in the locale file with "Animals.Dog = Perro")
List<string> animals = I18N.Current.TranslateEnumToList<Animals>();
List<Tuple<Animals, string>> animals = I18N.Current.TranslateEnumToTupleList<Animals>();
string dog = animals[0].Item2; // Perro
Dictionary<Animals, string> animals = I18N.Current.TranslateEnumToDictionary<Animals>();
string dog = animals[Animals.Dog]; // Perro
//Reverse lookup to get the key for a string (in English). This Key can then be used to get the translation in any specified language.
public II18N TransStrings => I18N.Current;
var mesageText = string.IsNullOrEmpty(loginResponse.ErrorMessage) ? loginResponse.Message : loginResponse.ErrorMessage;
lookupKey = string.IsNullOrEmpty (mesageText)? "ServerProblem":mesageText.ReverseTranslate();
Mvx.IoCProvider.Resolve<IUserDialogs>().Alert(TransStrings[lookupKey]);
// List of supported languages (present in the "Locales" folder) in case you need to show a picker list
List<PortableLanguage> languages = I18N.Current.Languages; // Each `PortableLanguage` has 2 strings: Locale and DisplayName
// change language on runtime
I18N.Current.Language = language; // instance of PortableLanguage
// change language on runtime (option 2)
I18N.Current.Locale = "fr";
I18N
implements INotifyPropertyChanged
and it has an indexer to translate keys. For instance, you could translate a key like:
string three = I18N.Current["three"];
With that said, the easiest way to bind your views to I18N
translations is to use the built-in indexer
by creating a proxy object in your ViewModel:
public abstract class BaseViewModel
{
public II18N Strings => I18N.Current;
}
Xaml sample
<Button Content="{Binding Strings[key]}" />
Xamarin.Forms sample
<Button Text="{Binding Strings[key]}" />`
Android/MvvmCross sample
<TextView local:MvxBind="Text Strings[key]" />
iOS/MvvmCross sample
var set = this.CreateBindingSet<YourView, YourViewModel>();
set.Bind(anyUIText).To("Strings[key]");
The library ships with a single format reader/parser that is TextKvpReader. Any other reader will be isolated in a different nuget/plugin to keep the library as simple as possible.
Reader | Format | Source |
---|---|---|
TextKvpReader | See sample | I18NPortable |
JsonKvpReader | See sample | I18NPortable.JsonReader |
JsonListReader | See sample | I18NPortablewithReverseLookup.JsonReader |
To use any non-default format, it needs to be added on initialization:
I18N.Current
.AddLocaleReader(new JsonKvpReader(), ".json") // ILocaleReader, file extension
// add more readers here if you need to
.Init(GetType().Assembly);
It´s very easy to create custom readers/parsers for any file format you wish.
For instance, lets take a loot at the above mentioned JsonKvpReader
:
Given this en.json file
{
"one": "uno",
"two": "dos",
"three": "tres"
}
Creating a custom reader is as simple as implementing ILocaleReader
:
public interface ILocaleReader
{
Dictionary<string, string> Read(Stream stream);
}
public class JsonKvpReader : ILocaleReader
{
public Dictionary<string, string> Read(Stream stream)
{
using (var streamReader = new StreamReader(stream))
{
var json = streamReader.ReadToEnd();
return JsonConvert
.DeserializeObject<Dictionary<string, string>>(json)
.ToDictionary(x => x.Key.Trim(), x => x.Value.Trim().UnescapeLineBreaks());
}
}
}
If you implemented a new reader for another file format and you want to contribute, feel free to make a pull request. Any new reader will live in their own project in the solution and will produce a different nuget as a plugin to I18NPortable.