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.
Unless it's already
open, open the WP7LaunchParty solution.
Right-click the
WP7LaunchParty project and select Add => New Item => Resources File.
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.
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.
Right-click
the WP7LaunchParty project and select Add => New Item => Resources File.
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.
Add four entries for Event
Title, Event Date, Event Time, and Cost
in Spanish, as shown in Figure 2.
NOTE
The translations
are approximate and are used for demonstrative purposes only—please
forgive the authors if we are not 100 percent accurate.
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>
To the top of the page, add the
following two statements:
using System.Resources;
using System.Reflection;
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");
}
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.
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.
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.
Add
the following line of code to the ToggleEventLocale method, right below
the statement Thread.CurrentThread.CurrentCulture = newCulture;:
Thread.CurrentThread.CurrentUICulture = newCulture;
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.