Everyone is excited about the new Universal Apps. I can now have a new type of project, called a Shared project, where I can put all the common files shared between a Windows 8.1 and Windows Phone 8.1 project. This is a better way around the “Add as a Link” option we had before. But universal apps is more than just a shared project. It seems that the APIs used by both Windows and Windows Phone are converging into one. Granted there still a lot of work to do and I’m not sure if there will be a 100% compatibility between the two frameworks, but this is a great step.

I’m going to talk about how to localize a universal app. In my article Internationalization of a Cross Platform Application I explain how to use the Multilingual App Toolkit in a PCL project to localize an application targeted for multiple platforms (Windows, Windows Phone, Android and iOS). But when I tried to apply the steps in the article to a Universal App I run into some problems. I will still base my localization on resource files, the thing is where do I put these? Should I put them in the new Shared project? or should I keep using PCL projects? Let’s first review our main goals:

  • To have a single place where we can specify strings and have these strings shared by all the platform projects.
  • Strings can be used in the UI as well as programmatically
  • Use the Multilingual App Toolkit to handle all the translations


Resource files in Shared project

When I knew about the new shared project type I thought “great, now I can put my resource files in the shared project”. Well, it turns out you can, but this is not the best approach. To explain why let’s see how our goals stand when we use resource files in shared projects.

As mentioned before, universal apps are basically three projects: a project for Windows 8.1, a project for Windows Phone 8.1 and a Shared project. By putting resource files in the shared project they will be shared by both the Windows and Windows Phone projects. Our first goal is ok.

The convergence of the frameworks between Windows and Windows Phone is also applied to the use of resources. Windows apps (aka Windows Store or WinRT apps) use the .resw resource type. On the other hand, Windows Phone Silverlight apps (the “Silverlight” suffix was added to differentiate them from the new Windows Phone apps which use the WinPRT framework) use .resx resource files. Now, both Windows 8.1 and Windows Phone 8.1 use .resw files..resw files can be used in XAML by specifying the x:Uid attribute in XAML components (this was not possible with .resx files), but these resource files do not have a strong type associated to them (as in the case of .resx resource files). This means that we cannot use resource strings programmatically. You can create a strong type associated to .resw files by using ResW File Code Generator, but it turns out that this extension doesn’t work if the resource is in the shared project. So, our second goal doesn’t stand.

The Multilingual App Toolkit cannot be enabled for shared projects. You have to enable MAT in both Windows and Windows Phone projects. It turns out that the decision of the MAT team regarding universal app was that they “decided to enable MAT based on the specific project instead of the shared project” (see this blog post for details). This means that I would have to do translations twice, one for each project. When you enable MAT in both projects you’re solution will be something like this:

Universal app with MAT

.xlf files are duplicated. So, yes we can use MAT on universal app (our third goal is ok) but since we can’t use it on the shared project our first goal doesn’t stand.

Finally, our goals stand as this:

  • To have a single place where we can specify strings and have these strings shared by all the platform projects: No
  • Strings can be used in the UI as well as programmatically: No
  • Use the Multilingual App Toolkit to handle all the translations: Yes

In summary, having a resource file in the shared project means that I will not be able to use resource strings programmatically and also that I will have to deal with duplicate translations and manual steps to keep these translations up to date. So, resource files in shared projects: not the best approach.


Resource files in PCL project

Our second option is to put resource files in a PCL project. Let’s see how this options stands with our goals. You can perfectly add a PCL project to a universal app solution:

PCL for universal app

When you do this Visual Studio automatically sets the targets for the PCL project to “Windows 8.1” and “Windows Phone 8.1”:

PCL project properties

I suggest to change the “Default namespace” of the PCL project to match the default namespace of the other projects as well. In the PCL project, create a folder structure that is compatible with the project’s default language, in my case “en-US”. Add a new resource (.resw) file to the folder. You should have something like this:

PCL folder structure

(note: you can change the PCL default language by editing the PCL project file. Look for the node DefaultLanguage)

It is required for the resource file to be inside a folder with a name that matches the project default language, otherwise MAT will not find any strings and the .xlf files will not be generated.

Since the targets for the PCL are “Windows 8.1” and “Windows Phone 8.1” the resource files you can add are of type .resw. We already explained that .resw resources do not have an associated strong type and we cannot use strings programmatically. To work around this we will use ResW File Code Generator: in the .resw file properties we will specify values for the properties “Custom Tool” and “Custom Tool Namespace” to be “ReswFileCodeGenerator” and the namespace of our project, respectively:

resw file properties

This will generate a strong type associated with the resource file at compile time.

You can follow the approach explained in How to use the Multilingual App Toolkit (MAT) in a Portable Class Library (PCL) project to see how to use MAT on a PCL:

  • Enable MAT for the PCL project
  • Add translation languages to the project (in my case I’m adding “es” and “it”)

Your PCL project should now look as this:

PCL with MAT

At this point, when you compile the PCL project, all the strings in the default resource file will be copied to the .xlf files by MAT. You can now start translating using MAT.

There are some steps we need to do in order to finish this:

  • Make sure you add the PCL project as a reference to both Windows and Windows Phone projects
  • In the shared folder, create a structure such as the following:

Shared folder structure

Basically you need to create a resource file for each language you support and this resource file needs to be inside a folder with the name of the locale. The .resw files in this shared folder structure can be empty. This is a requirement of both Windows and Windows Phone projects in order to know that the application supports all those languages. At this point you can start using resource strings in the UI as well as programmatically (see more details about how to use PCL resources in cross platform apps by reading the article Internationalization of a Cross Platform Application)

Let’s review if we have accomplished our goals:

  • To have a single place where we can specify strings and have these strings shared by all the platform projects: Yes
  • Strings can be used in the UI as well as programmatically: Yes
  • Use the Multilingual App Toolkit to handle all the translations: Yes


Sample App

You can find a sample VS project here:


Conclusion

In summary, having our resources in a PCL project is still the best option. Shared projects is an excellent idea, but it still lacks support for some other features, as in this case, to be able to handle resource files using MAT and to have .resw files generate a strong type. Let’s hope that the guys in the MAT team provide a way to use MAT in shared projects in the future. In the meantime, let them know that we need this by voting on the user voice idea.

3 Comments

When I design a new application I always design it with localization in mind. For cross platform applications my strategy is based on the use of resource files in a Portable Class Library (PCL) project. See my previous article on Internationalization of a Cross Platform Application for details on details about how to do localization in a cross platform application.

For localization I use the Multilingual App Toolkit (MAT). MAT was created to easy the task of localizing Windows Store and Windows Phone applications and since version 3.0 it could also be used in desktop applications (Asp.Net MVC, WinForms and WPF). But what about PCLs? Can MAT be used in PCLs? Well, if you’re using version 3.1 then yes, you can use MAT in PCLs. If you’re using version 3.0 or lower then yes, you can enable a PCL project for translation with MAT, and no, it doesn’t work as it is supposed to. Let’s show how to have MAT work in a PCL project and how to solve the compilation problem you get if your project was enabled with MAT 3.0.

Create a PCL project and enable MAT on it

(note: I’m using Visual Studio 2013 Update 2 and Multilingual App Toolkit 3.1)

Start Visual Studio and create a new “Class Library (Portable)” project and call it “Portable” (or whatever you want).

New PCL project

In the target frameworks dialog, add the targets you need. I will add the newest ones: “Windows Phone 8.1”, “Windows 8.1” and “.Net Framework 4.5”.

Choose target frameworks

The combination of target frameworks you choose will determine the kind of resources files you can add to the PCL project. There are basically two types of resource files:

  • .resx: This type of resource has a strong type associated to it which allows to use strings in code. It is used by Windows Phone Silverlight 8/8.1 and .Net Framework 4.5 targets.
  • .resw: This type does not have a strong type associated (although you can create one by using ResW File Code Generator). It is used by Windows 8/8.1 and by Windows Phone 8.1 targets.

When any of the selected targets uses .resx files then the PCL project will use .resx files. Otherwise the PCL project will use .resw files. In my case, since I chose “.Net Framework 4.5” as one of the targets my PCL project will use .resx resources. Having a strong type associated with my resource is very important later when using resources in the UI and app logic. (See my article on How to use Multilingual App Toolkit in Universal Apps for more information)

Now, delete the file Class1.cs generated by the Visual Studio wizard. The first thing you will be tempted to do is to enable MAT on the project. Select the project (not the solution) in Solution Explorer and from the Tools menu select “Enable Multilingual App Toolkit”. You will get the following message:

matNoResource

The message is pretty clear: we need to add a resource file before we can enable MAT. Let’s put our resource files in a folder called Resources. Right click on the project in Solution Explorer and from the popup menu select “Add” and then “New Folder” and call it Resources. New let’s add a resource file, right click on the newly created folder and from the popup menu select “Add” and then “New Item…”. The Visual Studio “Add New Item” dialog appears:

New resource

Select “Resource File” from the list of templates and name it Resources.resx. Add some strings to your resource file and make sure to that the “Access Modifier” for the resource is marked “Public” (cause we want to access to the strong type generated from other projects):

resource

Compile your project. Now we are ready to enable MAT on the project. Select the project (not the solution) in Solution Explorer and from the Tools menu select “Enable Multilingual App Toolkit”. When MAT is enabled by default the Pseudo Language file is added automatically to the project. You can remove this file (Resources.qps-ploc.xlf) if you want. Let’s add a new language.

Right click on the project in solution explorer and from the popup menu select “Add translation languages…”. MAT will open the “Translation Languages” dialog where you can select the languages your app will support. In my case I will add Spanish (es) and Italian (it). Click OK to close the dialog. MAT will add .xlf files to your project for each of the languages you chose. Your solution now should look something like this:

solution

Now, compile the project.

Solving the compilation error if using Multilingual App Toolkit prior to 3.1

If you’re not using the latest version of MAT (at the time of this writing is 3.1) then you will probably get the following error:

Error

If you enabled MAT and added languages to your project with a version of MAT prior to 3.1 then you will probably get the error above. If you installed MAT 3.1 new projects will be created fine, but old projects will still present the error. To fix this you will need to edit your project file. If you take a closer look to the build output you will find the following message: “No XLIFF language files were found.  The app will not contain any localized resources.” This means that MAT is not able to find the files with extension .xlf in the project. Right click on the project in Solution Explorer and from the popup menu choose “Unload Project”, and then again right click on the (now unloaded) project and select “Edit Portable.cproj”. Visual Studio will open the project file. Locate the following lines:

    <None Include="Resources\Resources.es.xlf">
      <Generator>XliffResxGenerator</Generator>
      <LastGenOutput>Resources.es.resx</LastGenOutput>
    </None>
    <None Include="Resources\Resources.it.xlf">
      <Generator>XliffResxGenerator</Generator>
      <LastGenOutput>Resources.it.resx</LastGenOutput>
    </None>

And change the node name from None to XliffResource:

    <XliffResource Include="Resources\Resources.es.xlf">
      <Generator>XliffResxGenerator</Generator>
      <LastGenOutput>Resources.es.resx</LastGenOutput>
    </XliffResource>
    <XliffResource Include="Resources\Resources.it.xlf">
      <Generator>XliffResxGenerator</Generator>
      <LastGenOutput>Resources.it.resx</LastGenOutput>
    </XliffResource>

Now, reload the project: right click on the project in Solution Explorer and from the popup menu select “Reload Project”. Now you should be able to compile the project.

Now I have my resource files in a PCL project, and since I’m using resx files I also have a public resources type that I can use in MVVM and databinding. See more details on how to do this in these two articles: