Localization of text in MvvmCross ViewModels

I would like to get all my localized text from ViewModels (as is often the case dynamically) and I was wondering how to use a converter to get text from json files used for localization. For example, in the below code, I would like LocalizedString to use the converter that I am currently using in my views in bindings for static text -

public string MyText // used in the binding in the View
{
    get
    {
        string exclamation;

        if (MyValue <= 3.3)
        {
            exclamation = LocalisedString("Rubbish!");
        }
        else if (OverallScore > 3.3 && OverallScore <= 6.6)
        {
            exclamation = LocalisedString("Good!");
        }
        else
        {
            exclamation = LocalisedString("Excellent!");
        }

        return exclamation;
    }
}

      

Version 1 of MvvmCross is currently in use.

Any help is greatly appreciated.

+3


source to share


2 answers


Note: this answer is about vNext - it should be fairly easy to pass back to the master ... The differences in scope are not that big.


MvvmCross has a built-in text localization mechanism.

The only public sample that uses it is the conference sample.


This example provides generic and ViewModel specific Json files - see

These Json files contain simple key-value pairs such as:

{
"Title":"SQLBits X",
"Welcome":"Welcome",
"Sessions":"Sessions",
"Sponsors":"Sponsors",
"Tweets":"Tweets",
"Favorites":"Favorites"
}

      

They are linked to Droid, Touch and WP as content or assets ... all accessible by the platform using the ResourceLoader plugin.


To use these JSON files at runtime, the main project loads them into the TextProviderBuilder :

    protected override IDictionary<string, string> ResourceFiles
    {
        get
        {
            var dictionary = this.GetType()
                .Assembly
                .GetTypes()
                .Where(t => t.Name.EndsWith("ViewModel"))
                .Where(t => !t.Name.StartsWith("Base"))
                .ToDictionary(t => t.Name, t => t.Name);

            dictionary[Constants.Shared] = Constants.Shared;
            return dictionary;
        }
    }

      

You could easily download other JSON files here if you like. For some of my applications, this is not uncommon:

  • file for errors
  • file for common common statements
  • file for specific components
  • file for ViewModel

While others have:

  • only one big file!

Internationalization - when done - is done by loading a different set of JSON files. Usually the first set is loaded by default, then you load incremental overrides, so you can load English as default, Cat as override and Cat-Lol as additional work.

For some discussions about this see:




Assuming you have one common file and one file per ViewModel, then to provide runtime for text values ​​from JSON, the BaseViewModel presents 2 properties:

    public IMvxLanguageBinder TextSource
    {
        get { return new MvxLanguageBinder(Constants.GeneralNamespace, GetType().Name); }
    }

    public IMvxLanguageBinder SharedTextSource
    {
        get { return new MvxLanguageBinder(Constants.GeneralNamespace, Constants.Shared); }
    }

      

These properties are used in data binding using:

  • Path indicating whether to use SharedTextSource or TextSource
  • MvxLanguageBinderConverter as Converter
  • text key as ConverterParameter

For example, in Droid, these are:

<TextView
  style="@style/AboutPageBodyText"
  local:MvxBind="{'Text':{'Path':'TextSource','Converter':'Language','ConverterParameter':'Title'}}"
  />

      

Although in the modern "Swiss" binding it will be written as:

<TextView
  style="@style/AboutPageBodyText"
  local:MvxBind="Text TextSource, Converter=Language, ConverterParameter='Title'"
  />

      

Any code that wants to use text can do that as well - see for example how TimeAgo text is generated from resource strings in TimeAgoConverter.cs , which uses resource strings such as:

{
"TimeAgo.JustNow":"just now",
"TimeAgo.SecondsAgo":"{0}s ago",
"TimeAgo.MinutesAgo":"{0}m ago",
"TimeAgo.HoursAgo":"{0}h ago",
"TimeAgo.DaysAgo":"{0}d ago",
"TimeAgo.Never":"never"
}

      

The code for this is efficient:

 var valueToFormat = 42;
 var whichFormat = "TimeAgo.DaysAgo";

 var textProvider = this.GetService<IMvxTextProvider>();
 var format = textProvider.GetText(Constants.GeneralNamespace, Constants.Shared, whichFormat);

 return string.Format(format, valueToFormat)

      


Binder and ValueConverter language is really very simple code

So feel free to create something more complex for your application if you need it.


There are other methods for cross-platform text localization - I would especially like to try it once a day - https://github.com/rdio/vernacular

+9


source


Perhaps you need to return enums instead of strings and handle localization in views.



0


source







All Articles