Skip to content

Simple and cross platform internationalization/translations for Xamarin and .NET

License

Notifications You must be signed in to change notification settings

danielPollackGitHub/I18N-Portable

 
 

Repository files navigation

I18NPortablewithReverseLookup for xamarin forms.

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.

NuGet NuGet AppVeyor Codecov

  • 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

https://cloud.githubusercontent.com/assets/145087/24824462/c5a0ecce-1c0b-11e7-84d3-4f0fa815c9da.png

Install

Install it on your PCL and platform projects. From nuget package manager console:

PM> Install-Package I18NPortablewithReverseLookup

Setup locales

  • 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

Fluent initialization

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

Usage

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";

Data binding

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]");

Supported formats

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 I18NPortable.JsonReader
JsonListReader See sample I18NPortablewithReverseLookup.JsonReader I18NPortable.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);

Creating a custom reader for another file format:

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());
        }
    }
}

Contributing new readers

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.

About

Simple and cross platform internationalization/translations for Xamarin and .NET

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 100.0%