A .NET standard helper for xamarin localization in shared projects
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
DewXamarinLocalization
.gitignore
LICENSE
README.md

README.md

DewXamarinLocalization

A .NET standard helper for xamarin forms localization in shared projects

How to use

My first though was about that this localization system must be easy, and (maybe it can be still better, who knows?) I think I've done it!

Install package

Your first step is to install the DewXamarinLocalization in your projects (all, you can use solution nuget package manager)

Files

The files are simple json dictionary, like this:

{
  "AppTitle": "DewLocalization!",
  "AboutTitle": "Dew is great!"
}

IMPORTANT! --------------------------

These steps are important!

Tree example

-Shared project
 |
 |-Localized
     |- it-it.json
     |- en-us.json
 |- Views
 |- etc.

Every file content must be at least "{}".

Naming

This is really important, you must be carefull about the file names. Every filename MUST correspond to the CultureInfo Name property in lower case (en-us,it-it,it-ch,en-gb,fr-fr,etc.) and must be json. Obviously if your app support 3 languages, you should have 3 different culture and you must support all of them.

Path

The file MUST be placed in a folder called Localized in the shared project.

Embedded

When you create the file, you MUST set in the properties "Embedded resource" like Build Action

NOTE

If a file for a culture isn't present you'll get an exception when the app is opening only with that culture.

IMPORTANT! --------------------------

XAML Code

This page is from the xamarin.forms base template for a new app.

<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            xmlns:views="clr-namespace:ExampleApp.Views"
            xmlns:loc="clr-namespace:DewCore.Xamarin.Localization;assembly=DewXamarinLocalization"
            x:Class="ExampleApp.Views.MainPage">
    <TabbedPage.Children>
        <NavigationPage Title="{loc:_ S=AppTitle}">
            
            <NavigationPage.Icon>
                <OnPlatform x:TypeArguments="FileImageSource">
                    <On Platform="iOS" Value="tab_feed.png"/>
                </OnPlatform>
            </NavigationPage.Icon>
            <x:Arguments>
                <views:ItemsPage />
            </x:Arguments>
        </NavigationPage>
        
        <NavigationPage Title="{loc:_ S=AboutTitle}">
            <NavigationPage.Icon>
                <OnPlatform x:TypeArguments="FileImageSource">
                    <On Platform="iOS" Value="tab_about.png"/>
                </OnPlatform>
            </NavigationPage.Icon>
            <x:Arguments>
                <views:AboutPage />
            </x:Arguments>
        </NavigationPage>
    </TabbedPage.Children>
</TabbedPage>

How you can see, your first step is to import the namespace:

xmlns:loc="clr-namespace:DewCore.Xamarin.Localization;assembly=DewXamarinLocalization"

After this you can use it thanks the Markup extension

<NavigationPage Title="{loc:_ S=AppTitle}">

Another approach

You can also set the strings in this way

<NavigationPage >
    <NavigationPage.Title>
        <loc:_ S="AppTitle"/>
    </NavigationPage.Title>
    <NavigationPage.Icon>
        <OnPlatform x:TypeArguments="FileImageSource">
            <On Platform="iOS" Value="tab_feed.png"/>
        </OnPlatform>
    </NavigationPage.Icon>
    <x:Arguments>
        <views:ItemsPage />
    </x:Arguments>
</NavigationPage>

In code

If you need to acces to the dictionary in code behind you can this way:

public void Test()
{
    System.Diagnostics.Debug.Write(_.GetString("AppTitle"))
}

If string doesn't exists?

The localization system is based on aspnet core middleware DewLocalizationMiddleaware and works in the same way.

Files must be present otherwise you'll get an exception, but strings doesn't need this.

If a string doesn't exists, the Localization class just return the key value.

This way if you want you can use the default word like key, so if in the translation it doesn't exists it will return the key self.

An example

<NavigationPage Title="{loc:_ S='My App\'s name'}">

or

<NavigationPage.Title>
    <loc:_ S="My App's name"/>
</NavigationPage.Title>

If the it-it.json file contains a voice for "My App's name", it will be translated, otherwise the app will print "My App's name" (that is the key).

Change dictionary in runtime

If you want change the dictionary in runtime, you shouuld just do:

public async Task Test()
{
    var newCulture = new System.Globalization.CultureInfo("it-IT");
    await _.ChangeCulture(newCulture);
    System.Diagnostics.Debug.Write(_.GetString("AppTitle"));
    newCulture = new System.Globalization.CultureInfo("en-US");
    await _.ChangeCulture(newCulture);
    System.Diagnostics.Debug.Write(_.GetString("AppTitle"));
}

Scenario where you want change your language at app's start

If you want to change the language in app start, your first approach is to place the ChangeCulture call into OnStart event but it won't work. This because the ChangeCulture method is asyncronous, and the App will initialize via Xaml and this will create a conflict (with crashes sometimes).

Another approach is to change the culture in the OnAppaering event of the main page, and it works, but only for the next pages, because the mainpage will be loaded with the currentculture language.

If you try to call ChangeCulture method into App constructor you'll get a NullReferenceException because DewXamarinLocalization class depends from Application class.

A solution for this particular problem is done with the static property CultureStringOverride.

This property is mono-use (after set it, you should call LoadDictionary method, that will read it and will delete it) didn't has dependencies, so you can call into App constructor without problem.

Like I've said, you SHOULD call LoadDictionary after set this property, but, in this particular case, will be XAML the creator of the DewXamarinLocalization class.

NOTE: If you set property and after call LoadDictionary you'll get the same result of a call of ChangeCulture, so you should use this property only for this scenario.

Example:

public App ()
{
    InitializeComponent();
    var cul = LoadMyCultureFromSettings(); // this must be the culture name, like "it-it","en-us", etc. in lower case, see Naming paragraph for more.
    DewCore.Xamarin.Localization._.CultureStringOverride = cul;
    MainPage = new MainPage();
}

Default culture

There is now a DefaultCulture property.

You can add a default culture to prevent crashes when a culture resource doesn't extist.

For example if you set as Default Culture "en-us" and you try to load the culture "it-it", if the resource doesn't exists the system will try to load the "en-us" culture resource.

If also the en-us culture resource doesn't exists, the system will try to load the current culture's resource but, if also this will be missed, the system will launch an exception.

You should set the DefaultCulture property into the app constructor.

Note

Added DefaultCulture property (Must correspond to Name Property in lower case)

NuGet

You can find it on nuget with the name DewXamarinLocalization

About

Andrea Vincenzo Abbondanza

Donate

Help me to grow up, if you want