Localization in Xamarin Forms UWP

This article describes the localizing Xamarin.Forms apps with resource files and get the device culture from windows devices. The resource .RESX files containing translated strings which are embedded in Xamarin.Forms assembly.

Globalizing Xamarin.Forms code
• Adding and using string resources in Xamarin.Forms PCL app
• Enabling language (culture) detection

Localizing XAML

• Localizing XAML using IMarkupExtension
• Enabling the markup extension in the native apps, it is Windows (UWP & WP8.1) in this article

Let’s create simple login page as below and bind all the strings from resource file.
Create a Xamarin.Forms project and add the resource .RESX file to PCL. This resource file contains the default text, then add additional RESX files for each language we wish to support.

When you create RESX file, the class and properties are internal by default for the assembly. To make them Public, you must manually change the resource file property CustomTool to PublicResXFileCodeGenerator.

Since globalization relies on device culture, create a dependency service to get the culture (language) of user device as below.
Create an interface in PCL and declare a function as below.

public interface IPlatformService
    {
        CultureInfo GetCurrentCultureInfo();
    }

A Class implementation in native app and register with Xamarin.forms dependency as below.

[assembly: Xamarin.Forms.Dependency(typeof(PlatformService))]
namespace PageCustomRenderer.UWP.DependencyServices
{
    public class PlatformService : IPlatformService
    {
         public CultureInfo GetCurrentCultureInfo()
         {
             return CultureInfo.CurrentUICulture;
        }
    }
}

If you want to localize or bind the resource strings in XAML, create a class to inherit from iMarkupExtension. This class is being used to get the resource string value by key from resource file based on user device culture.

[ContentProperty("Key")]
public class ResourceExtension : IMarkupExtension
    {
         private const string ResourceId = "PageCustomRenderer.Resources.Resource1";

        private readonly CultureInfo cultureInfo;

         private readonly ResourceManager resmgr;

         public ResourceExtension()
        {
            this.cultureInfo = DependencyService.Get<IPlatformService>().GetCurrentCultureInfo();
            this.resmgr = typeof(Resource1)
               .GetRuntimeFields()
               .First(m => m.Name == "resourceMan")
               .GetValue(typeof(Resource1)) as ResourceManager;
        }

        public string Key { get; set; }

         public object ProvideValue(IServiceProvider serviceProvider)
         {
             if (this.Key == null)
            {
                 return string.Empty;
            }

            var translation = this.resmgr.GetString(this.Key, this.cultureInfo);

             if (translation == null)
            {
#if DEBUG
                throw new ArgumentException(
                     string.Format("Key '{0}' was not found in resources '{1}'.", this.Key, ResourceId),
                     "Text");
#else
translation = Key; // HACK: returns the key, which GETS DISPLAYED TO THE USER
#endif
            }

            return translation;
        }
    }

From above, ResourceExtension class has been added with attribute ContentProperty of type Key, so pass the Key from XAML to get respective string value from resource manager, hence Implemented the ProvideValue function.

ResourceId
, is being used to identify the resource fileEach resource file contains ResourceManager which will be used to retrieve the resource strings. Just open the resource designer file, you can find the resource id and resource manager with all resource keys.

Now, open the MainPage.Xaml and add the xmlns namespace of the ResourceExtension class as below.
xmlns:res="clr-namespace:PageCustomRenderer.Resources"

XAML design with resource keys binding as below.

<StackLayout Margin="10">
    <Label Text="{res:Resource SignIn}" Margin="10" FontSize="25"></Label>
    <Label Text="{res:Resource UserName}" Margin="5" FontSize="21"></Label>
    <Entry Margin="5" Placeholder="User Name"></Entry>
    <Label Text="{res:Resource Password}" Margin="5" FontSize="21"></Label>
    <Entry Margin="5" Placeholder="Password" IsPassword="True"></Entry>
    <Button Text="{res:Resource Login}" Margin="10"></Button>
  </StackLayout>

From above, res is xmlns namespace and Resource is considered from ResourceExtension classs name.
If you want to use the resource file in code, you can directly use the resource file as below.
var text = Resource1.Password;

Since windows (UWP and WP8.1) apps has the limitation of loading the resource files from Xamarin.Forms PCL project, create a ResourceManager class in windows project and ensure to load the resource file from Xamarin.Forms PCL project as below.

  public class WinRtResourceManager : ResourceManager
    {
         
         private ResourceLoader resourceLoader;
         private WinRtResourceManager(string baseName, Assembly assembly) : base(baseName, assembly)
        {
            this.resourceLoader = ResourceLoader.GetForViewIndependentUse(baseName);
         }

         public static void InjectIntoResxGeneratedApplicationResourcesClass(Type resxGeneratedApplicationResourcesClass)
         {
             resxGeneratedApplicationResourcesClass
                 .GetRuntimeFields()
                 .First(m => m.Name == "resourceMan")
                 .SetValue(
                      null,
                     new WinRtResourceManager(
                          resxGeneratedApplicationResourcesClass.FullName,
                          resxGeneratedApplicationResourcesClass.GetTypeInfo().Assembly));
        }
         
        public override string GetString(string name, CultureInfo culture)
         {
             return this.resourceLoader.GetString(name);
        }
    }

Finally, use this ResourceManager class in app.xaml.cs OnLaunched event as below.
WinRtResourceManager.InjectIntoResxGeneratedApplicationResourcesClass(typeof(Resources.Resource1));

Please read through the link for more documentation on Localization.

Download the working sample.
      

By Siva Jagan Dhulipalla   Popularity  (4114 Views)