Being more involved in the engineering process of a product I had the chance to participate in the design of various features instead of just the ones that I’m responsible for delivering. One of those areas was the way we would enable developers to produce localized applications. Before this process I have to be honest and as an app developer never really paid much attention to providing localized versions of any app that I wrote. I had absolutely no good reason for coming to that decision, just never bothered. In helping to design and understand localization a bit more I can say that it is easy to do this in your app and there shouldn’t be any excuse for any app developer to create their application in a way to make it localized at any given moment. Note I didn’t say localized immediately, but rather I mean to create your app in a way that would make it easy to provide a localized version in a fairly quick turnaround.
As I do some app development for Windows 8 I wanted to share my thoughts around localization and what it really means to me to provide a ‘world-ready’ application. The three areas of focus are 1) how the platforms support a localized app, 2) what technical tools you have to automate localization 3) getting culture-correct localization and 4) testing your localized app.
Platform support for localization
The first thing you have to understand is how the platform you are targeting enables support for your app to easily be localized. This may be in how you organize your content, how you name certain things, and how you write code. For most platforms there is a pretty predictable method of doing this. I would argue not all platforms make this extremely intuitive, but also state that inferring how (and what) you want to localize your app isn’t something a platform can predict well for every app. It is important for the app developer to plan for a global market and fully understand the models before writing a line of code to understand how to make the app localized more easily later in the process.
For Windows 8, a new resource model is introduced for WinRT that is common across the entire platform regardless of the UI framework choice. The areas you should understand are Windows.ApplicationModel.Resources and Windows.ApplicationModel.Resources.Core. These two areas are where most Windows 8 developers will spend most of their time with regard to localization of UI strings (and other content). For most, the GetString() method is probably where you’ll spend your time when using code. String values are indexed during the build process of your application. Your strings will either reside in a RESJSON (for HTML/JS) or RESW (for XAML) file. Both of these are essentially name/value collections for your strings. An example of the process of naming and managing your string resources can be found here: How to manage string resources.
In XAML we created a new way to do XAML UI localization in your markup, by moving some functionality into the platform for you. Previously in platforms like Silverlight people used techniques like data binding to accomplish the mapping from the RESX-generated class to the UI. Because the indexing of the string resources changed a bit (i.e., currently no strongly-typed resource class representation), we wanted to have the platform do some more heavy lifting for you. We already load the index file (resources.pri) automatically during load of the app, so we’re aware of the resources and all the context the app may have (i.e., what locale, screen resolution, etc.). Because of this we enabled a markup mechanism in XAML for you to provide easy string localization. Let’s use a simple example of a TextBlock that you might have a static string:
1: <TextBlock x:Uid="MyTextBlock" FontSize="24.667" Text="Design Placeholder" />
Notice the x:Uid value here. This now maps back to the key in your RESW file. Anything with that starting key will have properties merged into it. So we can have a key in our RESW for “Text” using the key name MyTextBlock.Text with a value of “Hello World” and the runtime will do the replacement for you. This applies to properties other than text (i.e. width) as well as attached properties. While we think this is a great new method, it may not work for everyone’s situations and you still have control over retrieving strings using the Windows.ApplicationModel.Resources WinRT APIs. You can read more about this method with some examples here: QuickStart: Make your Metro style app world ready and an SDK Sample here: Application Resources.
Tools to help with localizing content
Once you have understood what your platform provides and you have taken the effort to prepare your app for easy localization, the next step is to actually use tools/process to perform the localization. I’ve come across a few tools that I think are helpful for XAML developers who are ‘small shops’ and don’t have an existing process for app localization.
The easiest thing for a developer to do is to use machine translation using automated services. There are a few tools out there that I think can be helpful for this method. It is important to note we are talking about machine translation here…I will get to that point later on in the post.
RESX Translator with Bing
Since the RESW format is identical with RESW (restriction is that RESW only supports string values currently), you can use a lot of existing RESX tools. There is a RESX Translator with Bing project on CodePlex that was done by Microsoft UK Consulting Services. This allows you to select a file and source language and translate to any language that Microsoft Translator supports.
Since the current project supports (and only loads) .resx files, I had submitted some patch files to quickly make it support the .resw file extension. The contributor hasn’t accepted these patches, but you can find them on the patches section for the project.
Multilingual App Toolkit
Released with the Visual Studio 11 Beta, the Multilingual App Toolkit from Microsoft provides an integrated method for generating resources for your app. One of the benefits of this app is that it produces some standards-based files that are used to send to localizers and can be used in other tools. This includes the TPX and XLIFF file formats. Once installed the tool is integrated within visual studio and your flow would be something like the following.
First you’d have your app and an initial RESW file containing your default language (in my case en-US) resources. Once I have that I can right-click on the project and choose Add translation languages and when doing so, launches:
which I can select the languages I would prefer. Notice the translator icon next to some of them indicating that these could be machine-translated. Once you select the languages you want, you’ll see a folder within your app that contains the configuration information:
Now if you open the XLF files you’ll basically see some XML that contains configuration information but initially won’t see any of your string values. You need to do a build to populate those files. After building you’ll see the XLF files regenerated with the keys to be localized:
1: <?xml version="1.0" encoding="utf-8"?>
2: <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
3: <file datatype="xml" source-language="en-US" target-language="de-DE" original="LocTesting_Multilingual.prilog.xml" tool-id="MAT" product-name="LocTesting" product-version="Version 1" build-num="188.8.131.52">
5: <tool tool-id="MAT" tool-name="Multilingual App Toolkit" tool-version="1.0" tool-company="Microsoft" />
8: <group id="Resources">
9: <trans-unit id="Resources\SomeTextBlock\Text" translate="yes" xml:space="preserve">
10: <source>Good morning! Have a nice day!</source>
11: <target state="new">Good morning! Have a nice day!</target>
13: <trans-unit id="Resources\SomeButton\Content" translate="yes" xml:space="preserve">
14: <source>Click to Save</source>
15: <target state="new">Click to Save</target>
Now you send those off for translation by right-clicking on the XLF file and choosing Send for translation which will give you a dialog to choose if you want to mail them or save to a folder and which format (TPX/XLIFF). At this point your translation process can begin. If you don’t have a translation process where you would normally send the XLIFF files, you can use the MAT Localization Editor that is installed with the toolkit. Launching this tool and opening your XLIFF file will allow you (or the person doing translations) to edit the files with the correct value. The MAT editor also has the Microsoft Translator capability as well. Here’s an example of the above German file in the editor with one value translated by the Microsoft Translator:
Once you have the edited XLIFF file you import that back into your project. Notice there are some other workflow-related properties in the XLIFF (i.e., Signed off, ready for review, etc.) that you can enforce. Right-click on the XLF file in your project and choose Import translation and the XLIFF file that was modified. Once imported, when I build next the signed-off items will be indexed within my app’s resource lookup (resources.pri) and packaged. You will not see any new RESW files generated as using this process does the indexing during the build process with the XLF file and a build task.
Another tool that I’ve come across is Amanuens, which is more of a service/tool than anything that integrates into Visual Studio or runs on your machine. This service acts as a broker to translators. You basically create a project and then upload files to be localized. After you login and create a project (specifying the type as Metro as they now support Windows 8 application file types) then you upload your “master” RESW/RESJSON file. After doing that you can assign a translation and this is the core of their service. You can assign a file for translation to a person that is a user on the system as you may have a German speaking friend who might help you out. Or you can assign to an agency and get a quote:
This way you can send it off and wait. Either way when the translation comes back you just download the file, put it in your project in the appropriate folder and rebuild your app. Amanuens is a pay service with a free option, but if you have an app and want to manage the workflow of that process, it seems like a pretty cool service. They also have automatic source control synchronization that you can opt-in for so as your translations come in, they are automatically in your app via a repo sync.
While all the above tools are awesome and fast to get you started, to build a really targeted localized app it is highly recommended you do more than machine translation, or at a minimum verify that machine translation. Many times, especially for east Asian languages, the machine translation can be grammatically incorrect or sometimes culturally insensitive as most do dictionary-based translation rather than really understanding any context.
I recall a time in high school where a classmate went to Germany for exchange. Having taken 6 semesters of German she felt pretty confident in her skills. Little did she know her hoch Deutsch would prove to be a problem. Upon arrival she went to a café with some friends and proclaimed she was hot. However, her dictionary translation was bad and she effectively said “I’m horny” which immediately caught the attention of all the men in the room. So it is key to understand context and culture when translating!
For this services like Amanuens really help out in both the flow and identifying a person to do the translation. If you don’t know anyone who speaks Swedish, but want to target that market, using a service could help you get more culturally-correct translations for your app over just machine translation. This, of course, does not come without a cost, but usually it is minimal and is a one-time translation.
One thing I’d love to see happen is somewhat of a co-op of software developers from around the world to offer translation help. Working at Microsoft I had the chance to get correct translations of my Sudoku app for German, Japanese, Korean and French. It was helpful to just send off the RESW file and get back the translation from a human who speaks the language and understands technology terms as well. A service like Amanuens can help facilitate that co-op having a bank of users that are willing to donate their translation services for your project. I think the struggle is that it is mostly English apps that need the help and hard for an English person to really reciprocate the value. But if you are willing to help out other software developers perhaps we can start this co-op idea?
Testing your localized app
[!!_Śò ẃĥâт đõ Уôú ďó įƒ ўôú đõи'ť ћãνê тŕáйşłâţêď ţę×т ýęţ áйď ẅàήт тó тęšť ÿòµѓ ãрρ?_!!!!!!!!!!!!!!!!!!!!!!!!]
Could you read that? Squint a little more. It is what we call Pseudo Language. Not a ‘real’ language but something that simulates a lot of different characteristics of localized language challenges. Using the Multilingual Toolkit you can have all your strings translated to this Pseudo Language (sometimes called “ploc” within the walls of Microsoft) to test your app before your real language translations come in. Using ploc helps you identify various artifacts that may exist in localizing an app. Let’s take a simple example from above. We had a button that said “Click to Save” in English and we translated it to German. When rendered it would look like this respectively:
Notice that the German translation didn’t fit within the Button MaxWidth we had set because the translation of the text was longer than our English version. Testing this is important for us to realize we need to change the constraint of the XAML sizes to accommodate our languages that we are targeting.
Historically testing localized versions of apps may have been challenging requiring you to install a language pack, try to navigate menus that you may not understand, or relying on others to verify for you. In Windows 8, this process has become easier using the language list preferences. The Building Windows 8 blog had a post called “Using the language you want” which talks about this concept in detail.
NOTE: If using the Pseudo Language option and you want to test, when in the Language panel search for “qps-ploc” and you’ll see it under English (qps-ploc) as an option and then you can really test the boundaries of your app with the ploc strings!
Effectively as a developer I can go into the Language panel, add German, set it as my first language and run my app. Now I’ll get my German resources first and I can visible verify things that need to be changed without installing any language pack on my machine…and I can quickly change back without any reboots.
Developing your application to be world-ready doesn’t have to be a huge undertaking and can turn out not to be difficult at all for your app. While not every app is going to be the same and how you choose to architect your code may dictate how you get your resources, the concepts are still the same and starting with the mindset that your app may be localized at some point is the right thing to do. Using RESW/RESJSON from the start and understanding the options you have for extracting those resources will make localization later very easy…in fact in some cases as easy as just putting in the updated RESW file and recompiling.
Start smart from the beginning and think global even if you aren’t ready for it just yet. You never know when your German friend might help out translating for you and then you can instantly expand to that market within a day!
Hope this helps!