MOBILE

Windows Phone 7 Development : Internationalization - Using Resource Files to Localize Content

2/24/2011 4:20:52 PM
Assume now that we have been diligent designing our application for international markets: we have allowed enough space on the user interface for more verbose languages, and we have used only standard formatting options for date, time, and currency values. We still have to perform translation of the application interface and resources to other languages. This could be, certainly, the most labor-intensive part of internationalizing our application.

As has been mentioned already, the application should be flexible enough to function in different locales without the need for code change and recompilation. That means that all resources required for proper functioning of the application need to be located outside the source code of an application and loaded on demand in response to request for culture-specific elements. The location of those resources are the resource-only files, or *.resx files. In this section's walkthrough, we will enhance the WP7 Launch announcement application we built in the previous walkthrough with the use of .resx files.

NOTE

Large resource files may take some time to load on the Windows Phone 7 device. However, according to the Windows Phone 7 Application Certification Requirements document, a Windows Phone 7 application must render its first screen within five seconds of launch. Make sure to always include a splash screen image within the root of your package submitted to the Marketplace. This splash screen image can be any .jpg file of your choosing named SplashScreenImage.jpg. Even with the splash screen image, however, be aware that the Microsoft Certification Requirements document further states that an application must be responsive to user input within 20 seconds after its launch—make sure to use resource files diligently where they don't unnecessarily slow down your application.

One benefit of using .resx files is that Windows Phone 7 will automatically find and use the resource file appropriate for the user's locale based on the current user's culture settings. Another benefit of resource files comes from the concept of culture hierarchy mentioned previously—.NET Framework provides a default fallback mechanism (i.e., going one level up in the culture hierarchy) for those resources that have not been localized. Also, .resx files are easily parseable by external tools, since they are simply XML files. This allows easy editing of those files by third-parties (such as translation services).

NOTE

Throughout this book, you will see references to .NET Framework on Windows Phone 7. To be completely accurate, however, it is the compact version of .NET Framework (.NETCF) that powers Windows Phone 7. Compact .NET Framework is a portable version of the full .NET Framework, and it has a much smaller size and footprint to accommodate smaller devices. Windows Phone 7 runs .NETCF version 3.7. So whenever you encounter a reference to .NET Framework in this book, remember that the reference is really to the .NETCF 3.7.

  1. Unless it's already open, open the WP7LaunchParty solution.

  2. Right-click the WP7LaunchParty project and select Add => New Item => Resources File.

  3. This resource file will contain the values for English-US culture. Name the resource file AppResources.resx and click Add.

Remember our discussion of culture hierarchies earlier in this chapter? The fact that our resource file does not contain any locale information in the file name (unlike the Spanish one that we will be creating shortly) makes this an invariant culture resource file, or the file that will be shown if no locale-specific resource files are found on the device.

  1. Double-click the AppResources.resx file to bring up an empty table. Next, add four entries to that table for Event Title, Event Date, Event Time, and Cost, all in English, as shown in Figure 1.

Note that the contents of the first and second columns are extremely important: the first one contains the key that the code will use to reference the element, and it must be unique in this resource file.

The second column contains the value, or the actual content that will be displayed on the UI at runtime. The third column is useful, but not essential: you can provide descriptive comments about each value in this column.

We will now add a resource file for Spanish translation of the user interface elements.

  1. Right-click the WP7LaunchParty project and select Add => New Item => Resources File.

  2. Name the resource file AppResources.es-ES.resx and click Add.

Note the "es-ES" portion of the file name—it is extremely important to name resource files in accordance with the specific cultures they represent. In our case, we will provide Spanish (Spain) translation of the user interface only, hence the "es-ES" in the resources file name. If we wanted to add German (Germany) translation as well, our resource file would have the name AppResource.de-DE.resx.

  1. Add four entries for Event Title, Event Date, Event Time, and Cost in Spanish, as shown in Figure 2.

    Figure 1. Resource file for English -US translation of WP7LaunchParty application

    NOTE

    The translations are approximate and are used for demonstrative purposes only—please forgive the authors if we are not 100 percent accurate.

  2. We need to rename the textblocks used for captions in our application so that we can easily refer to them in code. Bring up MainPage.xaml and change textBlock1 to txtEventDateCaption, textBlock3 to txtEventTimeCaption, and textBlock4 to txtEventCostCaption. You should end up with XAML that matches the following markup:

    <Grid x:Name="ContentGrid" Grid.Row="1">
    <TextBlock Height="44" HorizontalAlignment="Left" Margin="204,48,0,0" Name="txtEventDate" Text="TextBlock" VerticalAlignment="Top" Width="276" />
    <TextBlock Height="43" HorizontalAlignment="Left" Margin="5,49,0,0" Name="txtEventDateCaption" Text="Date:" VerticalAlignment="Top" Width="193" />
    <TextBlock Height="44" HorizontalAlignment="Left" Margin="204,98,0,0" Name="txtEventTime" Text="TextBlock" VerticalAlignment="Top" Width="276" />
    <TextBlock Height="43" HorizontalAlignment="Left" Margin="5,99,0,0" Name="txtEventTimeCaption" Text="Time:" VerticalAlignment="Top" Width="193" />
    <TextBlock Height="44" HorizontalAlignment="Left" Margin="205,146,0,0" Name="txtEventCost" Text="TextBlock" VerticalAlignment="Top" Width="276" />
    <TextBlock Height="43" HorizontalAlignment="Left" Margin="6,147,0,0" Name="txtEventCostCaption" Text="Cost:" VerticalAlignment="Top" Width="193" />
    <Button Content="Español" Height="70" HorizontalAlignment="Left" Margin="6,233,0,0" Name="button1" VerticalAlignment="Top" Width="160" Click="button1_Click" />
    </Grid>


    Figure 2. Resource file for Spanish-Spain translation of WP7LaunchParty application
  3. To the top of the page, add the following two statements:

    using System.Resources;
    using System.Reflection;

  4. In MainPage.xaml.cs, change the ShowEventDetails() function to match the code chunk shown here. Notice how we commented out the setting of default (English) caption from code.

    private void ShowEventDetails()
    {
    //textBlockListTitle.Text = "WP7 Launch";
    ResourceManager rm = new ResourceManager("WP7LaunchParty.AppResources", Assembly.GetExecutingAssembly());
    textBlockListTitle.Text = rm.GetString("EventTitle");
    txtEventCostCaption.Text = rm.GetString("EventCost");
    txtEventDateCaption.Text = rm.GetString("EventDate");
    txtEventTimeCaption.Text = rm.GetString("EventTime");

    //create the date of November 6, 2010 at 9:00 PM
    DateTime dtLaunchDate = new DateTime(2010, 11, 6, 21, 0, 0);
    //make the cost equal to $5
    decimal decEventCost = 5.0M;

    txtEventDate.Text = dtLaunchDate.ToString("D");
    txtEventTime.Text = dtLaunchDate.ToString("T");

    txtEventCost.Text = decEventCost.ToString("C");
    }


  5. Press F5 to compile and run the application. Click the button to toggle between Spanish and English. Do you see all captions and the event title being properly translated? Probably not, since we have not indicated that our project must support different locales and which locales it must support.

  6. Open Windows Explorer and navigate to the folder where the WP7LaunchParty.csproj file is located. Open WP7LaunchParty.csproj in any text editor (Notepad is good) and find the <SupportedCultures> node. More than likely, that node will not contain any elements. Edit that node to look like text here:

    <SupportedCultures>es-ES;
    </SupportedCultures>

Were we supporting more than one culture, we would include all of them in this node, each culture code separated by a semicolon. For example, if we were supporting German and Russian translations as well, we would put "es-ES;de-DE;ru-RU;" in the <SuportedCultures> element.

  1. Save WP7LaunchParty.csproj in the text editor. Visual Studio should detect an external change to this file and ask you if you would like to reload the project. Click Yes.

  2. Add the following line of code to the ToggleEventLocale method, right below the statement Thread.CurrentThread.CurrentCulture = newCulture;:

    Thread.CurrentThread.CurrentUICulture = newCulture;

  3. Press F5 to run the application.

You have provided a non-locale specific (invariant) file, AppResources.resx, with English (US) captions for the invitation text in it. That's why you see an English interface upon launching the application. Once you click the button to toggle the application into Spanish, you should see the event title and captions translated into the Spanish language.

The title of the application ran off the screen in Spanish—a clear mistake on our part for making the font too large and not allowing an extra 40 percent of space inside that title for languages that are more verbose than English. Second, the caption for Cost did not translate into Spanish—it should be "Costo" in Spanish, not "Cost." What's going on here?

The reason for this is that in AppResources.es-ES.resx, there is not entry named "EventCost." There is an entry with the name "Cost," but that is not the name we are referring to from code. This mistake is a good demonstration of the application's cultural fallback: there was no entry in the Spanish version for "EventCost," so the application "fell back" to the default language (English-US) to represent a given caption—the raison d'être of the resource files!

Let's go ahead and correct this typo: double-click the AppResources.es-ES.resx file, change the name of the "Cost" entry to "EventCost," and re-run the application. You should see the proper caption, "Costo," for the Spanish version of our announcement.

NOTE

The MSDN documentation for internationalizing Windows Phone 7 applications proposes an entirely different approach than the one we've advocated in our walkthrough in this section. MSDN walkthroughs encourage you to add a separate class to return resources. In our walkthrough, however, we have simplified things a bit and used the ResourceManager class to locate resources within our resource files.

The main reason our walkthrough differs from the approach advocated by the MSDN documentation is that we are dynamically (i.e., in code) changing the culture of an application. We needed to do this for demonstration purposes, since changing local culture is a bit cumbersome. Dynamic rebinding of elements (to toggle captions between English and Spanish) would be a bit more involved. The addition of a separate class and references to that class, as illustrated in the MSDN documentation, could have also taken away from the main points illustrated during the walkthrough. But we could certainly have used an approach other than the ResourceManager class to accomplish the localization of our application.

Other  
  •  Windows Phone 7 Development : Internationalization - Storing and Retrieving Current Culture Settings
  •  Mobile Application Security : WebOS Security - Development and Security Testing
  •  Mobile Application Security : WebOS Security - Introduction to the Platform
  •  iPhone Application Development : Getting the User’s Attention - Using Alert Sounds and Vibrations
  •  iPhone Application Development : Getting the User’s Attention - Using Action Sheets
  •  jQuery 1.3 : Modifying table appearance (part 4) - Filtering
  •  jQuery 1.3 : Modifying table appearance (part 3) - Collapsing and expanding sections
  •  jQuery 1.3 : Modifying table appearance (part 2) - Tooltips
  •  jQuery 1.3 : Modifying table appearance (part 1) - Row highlighting
  •  Windows Phone 7 Development : Using Culture Settings with ToString to Display Dates, Times, and Text
  •  Mobile Application Security : SymbianOS Security - Persistent Data Storage
  •  Mobile Application Security : SymbianOS Security - Interprocess Communication
  •  Mobile Application Security : SymbianOS Security - Permissions and User Controls
  •  Windows Phone 7 Development : Building a Trial Application (part 3) - Verifying Trial and Full Mode & Adding Finishing Touches
  •  Windows Phone 7 Development : Building a Trial Application (part 2) - Connecting to a Web Service & Adding Page-to-Page Navigation
  •  Windows Phone 7 Development : Building a Trial Application (part 1) - Building the User Interface
  •  jQuery 1.3 : Table Manipulation - Sorting and paging (part 2) : Server-side pagination & JavaScript pagination
  •  jQuery 1.3 : Table Manipulation - Sorting and paging (part 1) : Server-side sorting & JavaScript sorting
  •  Windows Phone 7 Development : Understanding Trial and Full Modes (part 3) - Simulating Application Trial and Full Modes
  •  Windows Phone 7 Development : Understanding Trial and Full Modes (part 2) - Using the Marketplace APIs
  •  
    Top 10
    Magnetic Tape Storage - Data Storage For 30 Years
    NAD C546BEE – A Well-Built And Talented CD Player
    Optical Zoom: Better Than Digital?
    Retro Chic 1981 Minox 35 GT
    Through The Looking Glass (Part 2)
    Through The Looking Glass (Part 1)
    Pure Sensia 200D Connect – Internet Radio
    Samsung HW-E551 Soundbar - Convincing Cinema Sound
    Sansui CDD-201V – New Budget CD Player
    No Windows 7 Setup DVD Supplied With Your PC? No Problem!
    Most View
    Introduction to Transport-Level Security in Windows Server 2008 R2
    Store Data when Your App Has Restricted Permissions
    Back Up Your Photos Wirelessly Using Eye-Fi
    Complete Guide for Your PC & How to Buy It (Part 3) - Lenovo ThinkPad Edge E520 & Toshiba Portégé Z830-104
    Exploring Sample Virtualized SharePoint 2010 Architecture
    Corsair AX 1200I - The First Digitally-Controlled PSU
    The drive toward DSLs : Choosing between imperative and declarative DSLs
    Plot Thickens As Us Sues Apple To Protect Amazon's Monopod Y In Ebooks
    Mastering Windows PC (Part 3) - Uninstall the programs & Shut down safely
    Buying Guide: Gaming PCs For Hardcore Gamers' Dreams (Part 1) - Arbico Elite 5357 OCX
    iPhone 3D Programming : Adding Textures to ModelViewer (part 2) - Generating Texture Coordinates
    Microsoft ASP.NET 4 : How MVC Plays with ASP.NET (part 1) - Following the Request Path - Creating an MVC site
    The SQL Server 2008 Configuration Manager
    iPhone Application Development : Working with Text, Keyboards, and Buttons (part 2) - Adding Text Views
    Predict The Weather (Part 1)
    Install Windows Vista Home Premium SP2 Fail, What Should We Do?
    Samsung Galaxy Nexus: Really a star
    The Reality Of Gaming Laptops (Part 1)
    Logitech Tablet Keyboard for IPAD - Matching Combo
    Tokina AT-X 17-35mm f4 Pro FX (Part 1)