Using the Windows Phone 8.0 SDK to localize Windows Phone OS 7.1 projects

This blog post was authored by Dan Zucker, a program manager on the Windows Phone team.

- Adam


Here are the quick steps you need to take to set up a Windows Phone OS 7.1 Visual Studio project to use the techniques and features described in the blog posts Tips for Localizing Windows Phone 8 XAML Apps – Part1 and Tips for localizing Windows Phone apps – Part 2 to localize apps. Note that throughout these steps, you must replace <PROJECT_NAME_SPACE> with your project name.

  1. Follow the steps in the Standard Localizing Steps section described in Tips for Localizing Windows Phone 8 XAML Apps – Part1 to make your single-language app ready for localization.
  2. Update the <Application.Resources> node in the App.xaml file with the following code, where <PROJECT_NAME_SPACE> is replaced with your project name:
    XAML
    1. <!–Application Resources–>
    2. <Application.Resources>
    3.     <local:LocalizedStrings xmlns:local=”clr-namespace:<PROJECT_NAME_SPACE>” x:Key=”LocalizedStrings”/>
    4. </Application.Resources>

    The LocalizedStrings Application Resource, along with the LocalizedStrings class added in the next step provides a globally accessible means for your app to access its project’s localized resources. Although there are simpler ways to achieve that goal, the method described here provides the benefits of strong typing, including resource visibility in IntelliSense and compilation validation during coding.

  3. Add a new class file named LocalizedStrings.cs to the project. Replace the existing code with the following, where <PROJECT_NAME_SPACE> is replaced with your project name:
    C#
    1. using <PROJECT_NAME_SPACE>.Resources;
    2. namespace <PROJECT_NAME_SPACE>
    3. {
    4.     /// <summary>
    5.     /// Provides access to string resources.
    6.     /// </summary>
    7.     public class LocalizedStrings
    8.     {
    9.         private static AppResources _localizedResources = new AppResources();
    10.         public AppResources LocalizedResources { get { return _localizedResources; } }
    11.     }
    12. }

  4. Search the entire project for localized string resources. Update the project namespace as needed by including the following code, where <PROJECT_NAME_SPACE> is replaced with your project name:
    C#
    1. using <PROJECT_NAME_SPACE>.Resources;

  5. Add a folder named Resources to the project.
  6. Add a new resources file named AppResources.resx file to the new Resources folder.
  7. Add the language initialization resource strings ResourceFlowDirection and ResourceLanguage to AppResources.resx, as described in Tips for Localizing Windows Phone 8 XAML Apps – Part1. Typically, the value of the resource strings should be set to meet the traditional flow direction and locale of the neutral language (the one that a viewer of your app will see if they have selected a phone language that is not supported by your app).

    Name

    Value

    Comment

    ResourceFlowDirection

    LeftToRight

    Controls the FlowDirection for all elements in the RootFrame. Set to the traditional direction of this resource file’s language.

    ResourceLanguage

    en-US

    Controls the Language and ensures that the font for all elements in the RootFrame aligns with the app’s language. Set to the language code of this resource file’s language.

  8. Change the access modifier of AppResources.resx to “Public” by using the Access Modifier drop-down list at the top of the resource editor.
    clip_image002
  9. Save and rebuild the solution.
  10. Add the following references to App.xaml.cs, where <PROJECT_NAME_SPACE> is replaced with your project name:
    C#
    1. using <PROJECT_NAME_SPACE>.Resources;
    2. using System.Threading;
    3. using System.Globalization;
    4. using System.Diagnostics;
    5. using System.Windows.Markup;

  11. Add the InitializeLanguage function and call to the constructor of the App.xaml.cs file. Include the following using statements to reference System.Threading and System.Globalization at the beginning of the file. Also, add the declaration for the appForceCulture global variable to enable the international testing feature described in Tips for localizing Windows Phone apps – Part 2.
    C#
    1. // . . .
    2. public partial class App : Application
    3. {
    4.         // Global variable to set app locale at launch for International testing
    5.         // An empty value causes the app to following users phone language culture
    6.     public static String appForceCulture = “qps-ploc”;
    7.        
    8.     /// <summary>
    9.     /// Provides easy access to the root frame of the phone app.
    10.     /// </summary>
    11.     /// <returns>The root frame of the phone app.</returns>
    12.     public static PhoneApplicationFrame RootFrame { get; private set; }
    13.     /// <summary>
    14.     /// Constructor for the Application object.
    15.     /// </summary>
    16.     public App()
    17.     {
    18.         // Global handler for uncaught exceptions.
    19.         UnhandledException += Application_UnhandledException;
    20.         // Standard XAML initialization
    21.         InitializeComponent();
    22.         // Phone-specific initialization
    23.         InitializePhoneApplication();
    24.         // Language display initialization
    25.         InitializeLanguage();
    26. // . . .

  12. Add the InitializeLanguage method to App.xaml.cs:
    C#
    1. // Initialize the app’s font and flow direction as defined in its localized resource strings.
    2. //
    3. // To ensure that your apps font is aligned with its supported languages and that the
    4. // FlowDirection for each of those languages follows its traditional direction, ResourceLanguage
    5. // and ResourceFlowDirection should be initialized in each .resx file to match these values with that
    6. // file’s culture. For example:
    7. //
    8. // AppResources.es-ES.resx
    9. //    ResourceLanguage’s value should be “es-ES”
    10. //    ResourceFlowDirection’s value should be “LeftToRight”
    11. //
    12. // AppResources.ar-SA.resx
    13. //     ResourceLanguage’s value should be “ar-SA”
    14. //     ResourceFlowDirection’s value should be “RightToLeft”
    15. //
    16. // For more info on localizing Windows Phone apps see http://go.microsoft.com/fwlink/?LinkId=262072.
    17. //
    18. private void InitializeLanguage()
    19. {
    20.     try
    21.     {
    22.         // Change locale to appForceCulture if it is not empty
    23.         if (String.IsNullOrWhiteSpace(appForceCulture) == false)
    24.         {
    25.         // Force app globalization to follow appForceCulture
    26.             Thread.CurrentThread.CurrentCulture = new CultureInfo(appForceCulture);
    27.                
    28. // Force app UI culture to follow appForceCulture
    29.             Thread.CurrentThread.CurrentUICulture = new CultureInfo(appForceCulture);
    30.         }
    31.         // Set the font to match the display language defined by the
    32.         // ResourceLanguage resource string for each supported language.
    33.         //
    34.         // Fall back to the font of the neutral language if the display
    35.         // language of the phone is not supported.
    36.         //
    37.         // If a compiler error occurs, ResourceLanguage is missing from
    38.         // the resource file.
    39.         RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage);
    40.         // Set the FlowDirection of all elements under the root frame based
    41.         // on the ResourceFlowDirection resource string for each
    42.         // supported language.
    43.         //
    44.         // If a compiler error occurs, ResourceFlowDirection is missing from
    45.         // the resource file.
    46.         FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection,false);
    47.         RootFrame.FlowDirection = flow;
    48.     }
    49.     catch
    50.     {
    51.         // If an exception is caught here it is most likely due to either
    52.         // ResourceLangauge not being correctly set to a supported language
    53.         // code or ResourceFlowDirection is set to a value other than LeftToRight
    54.         // or RightToLeft.
    55.         if (Debugger.IsAttached)
    56.         {
    57.             Debugger.Break();
    58.         }
    59.         throw;
    60.     }
    61. }

As the comments in the code explain, the InitializeLanguage method initializes the app’s font and flow direction as defined in the localized resource strings.

As described in the blog posts Tips for Localizing Windows Phone 8 XAML Apps – Part1 and Tips for localizing Windows Phone apps – Part 2, when you add a language to your app using the Windows Phone 8.0 SDK, a resource file for that locale is created. In that .resx file, the ResourceLanguage and ResourceFlowDirection values are initialized for the locale of the language you added. When the app is launched, InitializeLanguage() uses the values of ResourceLanguage and ResourceFlowDirection to initialize the xml:lang and FlowDirection of the app’s Rootframe.

Typically the culture used by InitializeLanguage() is the culture the system chooses to most closely match to the user’s phone language setting. The appForceCulture clause allows you to override this with the culture of your choice, so that you can deploy and review your app in the language of your choice without the time-consuming process of changing settings or restarting the device or emulator. If you use this convenient method, don’t forget to also test the app to be sure that everything works as expected when you modify the Phone Language setting and reboot.