How to use Multilingual App Toolkit in Universal Apps
- Posted in:
- internationalization
- .net
- windows phone
- windows rt
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:
.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:
When you do this Visual Studio automatically sets the targets for the PCL project to “Windows 8.1” and “Windows Phone 8.1”:
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:
(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:
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:
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:
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.
Comments
Good, thanks!
Bruno LemosI feel I'm close but I didn't get it to work yet.
My strings are empty (in the Design Mode and in the Simulator).
It seems that the mat toolkit is not generating the translated resources.
Bruno, do you have any warnings produced at compilation by the MAT? When MAT doesn't create any resource files it is usually due to a difference in the spelling between the default project language and the name of the folder where you put your main .resw file. Make sure both are spelled the same (in my case "en-US")
Giovanni ModicaThanks for this tutorial. I have the same problem. I did exactly what you did Giovanni but the strings are empty. MAT generated a new folder in PCL project called "MultilingualResources" and I added de-DE as language and then it generated the xlf file in it. Compilation has no warnings. But is it correct that I have only the standard (in my case "en-US") resource file in my en-US Folder in PCL project? Do I not need a folder "de-DE" with it's german resource file, too? Or the xlf file is enough?
Akan YilmazI recommend to use the share project. Because that works perfectly nice!
Akan YilmazAkan MAT takes care of generating the resource file at compilation time. If your .xlf is empty it might be because the project default language differs from the name of the folder where you stored the resource file. Please make sure that the PCL project has its default language set to en-US. Share projects work perfectly fine, but does it comply with all the requirements specified at the beginning of the tutorial? Please let me know. Thanks for your comments.
Giovanni ModicaI'm able to get the strong typing to work however the Uid isn't working. Any suggestions?
FraserI experience exactly the same issue Fraser does. Strong typing works, however you need to have at least one string in your resources.resw file under the shared project for the language you want to use.
JustinUI takes strings always from the shared project resources.resw. If the one for the default language does not contain the string resources the UI does not work at all.
Your help to make this work is highly appreciated. Thank you!
Eventually you could make available an example solution so we could try to find out where the bug hides.
Hi, Giovanni! If you are interested in tools to translate .resx or .resw files, I think a good one is https://poeditor.com/
Mona@Fraser: Yes, using Uid in the XAML doesn't work, not sure why. But in my case is ok since I don't use it that way. I rely on databinding to do the translation
Giovanni Modica@Justin: Yes, you're right, you need at least one string in the resource for things to work. I have made a sample available in the article for you to use.
Thanks all for the comments
Would love to use the PCL solution, but on Visual Studio Express. Any other options?
Dave@Dave you can use the Visual Studio 2013 Community edition, that is equivalent to the professional one!
Nicolò CarandiniHere are the rules to use it:
•Any individual developer can use Visual Studio Community to create their own free or paid apps.
Here’s how Visual Studio Community can be used in organizations:
•An unlimited number of users within an organization can use Visual Studio Community for the following scenarios: in a classroom learning environment, for academic research, or for contributing to open source projects.
•For all other usage scenarios: In non-enterprise organizations, up to 5 users can use Visual Studio Community. In enterprise organizations (meaning those with >250 PCs or > $1 Million US Dollars in annual revenue), no use is permitted beyond the open source, academic research, and classroom learning environment scenarios described above.
I tryed open the source you provided, adding a string to the resource distionary. After compiling the solution, that string still does not appear both in designer and code behind. I think there's something wrong with T4Toolbox extension, why is it there?
FilippoHello everyone! I just wanted to suggest you a website where you can read lots of interesting news about software translation, localization, apps, translation services and more fresh subjects. You can have a look here: http://l10nhub.com/ Thanks, all the best!
Thomasthx for sharing sample app.
saavi