A. New Internationalization Features in the .NET Framework 2.0 and Visual Studio 2005

This appendix contains a list of the new features in the .NET Framework 2.0 and Visual Studio 2005 that are relevant to internationalization. The appendix is useful if you already have a good knowledge of internationalization in the .NET Framework 1.1 and Visual Studio 2003 and want to get up to speed as quickly as possible. It is also useful if you are trying to decide whether to start a new project in your familiar .NET Framework 1.1 and Visual Studio 2003 or make the leap to the more recent version. The appendix is mostly a list of pointers to sections of this book where the relevant features are covered in more detail.

If you are looking for a complete list of changes between any two versions of the .NET Framework, download LibCheck.exe from http://www.microsoft.com/downloads. This tool compares two versions of the .NET Framework and lists every difference.

Compatibility

This section covers the compatibility between the two versions of the .NET Framework and Visual Studio.

Windows Forms Compatibility

Visual Studio 2005 serializes components on a form using a model called Property Reflection (see Chapter 4, “Windows Forms Specifics”). Visual Studio 2003, however, serializes components using a model called Property Assignment. When you open a Visual Studio 2003 solution in Visual Studio 2005, it prompts you to convert the solution, giving you an opportunity to back up the old solution. The forms files (i.e., the .cs, .resx, and culture-neutral and culture-specific .resx files) are all initially unchanged and remain compatible with Visual Studio 2003. However, after a form has been changed, the source and resx files are written out using Visual Studio 2005’s Property Reflection model. The resulting code and resx files are now different. Although Visual Studio 2003 doesn’t use the Property Reflection model, the resulting code and resx files are recognizable and can be opened and compiled using Visual Studio 2003 (assuming that the form contains only components and code that both platforms recognize). Unfortunately, Visual Studio 2003 fails to understand that the form’s Localizable property should be true and sets it to false. When you set it to true again, Visual Studio 2003 naturally rewrites the source file and resx file, and the form returns to Visual Studio 2003’s Property Assignment model.

The upshot of all this is that both versions of Visual Studio can read each other’s form files (as long as you use components that are present in both versions of the framework). However, when you make any change to a form, the version of Visual Studio you are using writes out the form again using the model that it uses to write forms. Because Visual Studio 2003 doesn’t understand Visual Studio 2005’s serialization of the form’s Localizable property, you must set this to true again; this constitutes a change, which, therefore, means that the form is converted back to Visual Studio 2003’s model. You should also be aware that the scenario of opening Visual Studio 2005 forms in Visual Studio 2003 is not an officially supported model, so although this is often possible, you are on your own with regard to support.

Windows Forms Designer

The Visual Studio 2005 Windows Forms Designer adds many enhancements beyond the Visual Studio 2003 Windows Forms Designer, but it also removes one area of functionality. In the Visual Studio 2003 Windows Forms Designer, you can add new controls to any language version of a form. For example, with the French version of a form selected in the designer, you can add a new button to the form and it will be added to all forms. The Visual Studio 2005 Windows Forms Designer, however, requires that you first change back to the default language before adding new controls. Instead of viewing this as a step backward in Visual Studio 2005, you should understand that Visual Studio 2003 should not have allowed new controls to be added to forms other than the default language form, but this practice was not explicitly prevented.

CultureInfo.DisplayName and CultureInfo.EnglishName with Scripts

The format of the text returned by the CultureInfo DisplayName and English-Name properties for some cultures with scripts has changed. The format used in the .NET Framework 1.1 is to delimit the script entirely in its own parentheses. For example, the culture for the Azeri language in Azerbaijan using the Latin script (“az-AZ-Latn”) has this EnglishName:


Azeri (Latin) (Azerbaijan)

However, the .NET Framework 2.0 includes the script in the same parentheses as the country:


Azeri (Latin, Azerbaijan)

If you have logic that parses the name to extract its component information, you need to update this logic. Note that this change does not apply to new cultures with script suffixes that were introduced in the .NET Framework 2.0. For example, the “sr-BALatn” culture’s EnglishName is “Serbian (Latin) (Bosnia and Herzegovina)”.

CultureInfo.GetCultures Order

The order of the cultures returned from the CultureInfo.GetCultures method is different between the two versions of the framework. The order in both versions of the .NET Framework is unsorted and unspecified, but they are nonetheless different.

Control.DefaultFont Logic

The logic used to determine the DefaultFont property of System.Windows.Forms. Control is slightly more sophisticated in the .NET Framework 2.0. Because Control is the base class for all Windows Forms controls, this affects all controls. The difference is that on Arabic Windows, Control.DefaultFont now defaults to Tahoma, 8 point.

CultureInfo.Equals Logic

The logic used in the CultureInfo.Equals method has changed. In the .NET Framework 1.1, CultureInfo.Equals tests equality with another CultureInfo by comparing their locale IDs (LCIDs). In the .NET Framework 2.0, this comparison does not work because custom cultures all share the same LCID. Thus, a Spanish (United States) custom culture has the same LCID as a Bengali (Bangladesh) custom culture. In the .NET Framework 2.0, the CultureInfo.Equals method assumes that two cultures are equal if they have the same name and the same CompareInfo objects. (A test based simply on a name would be incorrect because alternate sort orders have the same culture name but different sort orders.) I have not found any circumstance in which this difference causes an incompatibility.

CultureInfo.OptionalCalendars Has New Calendars

The .NET Framework 2.0 introduces new calendar classes. These new calendars classes are available to the cultures for which they are relevant through the CultureInfo.OptionalCalendars array property. Consequently, the lengths of these arrays and, perhaps more important, the order of the elements of these arrays are different in some cultures (e.g., Arabic (Saudi Arabia)).

Base Data Has Changed for Some Cultures

The month and day names returned by the DateTimeFormatInfo, MonthNames, and DayNames array properties have changed for the Arabic (Morocco), Divehi (Maldives), Kannada (India), and Norwegian (Nynorsk) (Norway) cultures (i.e., ar-MA, div-MV, kn-IN, and nn-NO).

In addition, the currency symbols have been updated for several cultures, including Turkish (Turkey) (i.e., tr-TR), for which the currency symbol in the .NET Framework 1.1 is “TL” (Türk Lirasi); however, in the .NET Framework 2.0, the currency symbol is “YTL” (Yeni Türk Lirasi), regardless of the version of Windows and whether Windows Updates is turned on.

ResX Relative File References Break Code That Uses ResXResourceReader

The Visual Studio 2005 Resource Editor includes support for adding files such as bitmaps to resx resource files. The resulting entry in the resx file is of type ResXfileref. The ResXFileRef class is supported in both the .NET Framework 1.1 and 2.0. The problem (from the point of view of code that reads resources), however, is that the Visual Studio 2005 Resource Editor uses relative paths (see the “ResX File References” section in Chapter 10, “Resource Administration”). If you process resx files using the ResXResourceReader class, in most cases your code that reads resx files will fail if it tries to read a .NET Framework 2.0 resx file because it won’t know where to find the referenced files. A number of solutions exist, but the simplest is to set the ResXResourceReader.BasePath property to the path where the referenced files are located.

ResX Changes Break Code That Uses ResXResourceReader

The serialization of the Form.Localizable property to resx files has changed. In the .NET Framework 1.1, this property was represented as data in the resx file like this:


<data name="$this.Localizable" type="System.Boolean, mscorlib,
Version=1.0.5000.0, Culture=neutral,PublicKeyToken=b77a5c561934e089">
  <value>True</value>
</data>

In the .NET Framework 2.0, however, the same property is represented like this:


<metadata name="$this.Localizable" type="System.Boolean, mscorlib,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <value>True</value>
</metadata>

The difference is that the Form.Localizable property is now treated as meta-data instead of data. This has an impact on any code that reads resx files using the ResXResourceReader.GetEnumerator() method. The following code adds all the entries in a resx file to a TextBox:


ResXResourceReader reader =
    new ResXResourceReader(@"....Form1.resx");

IDictionaryEnumerator enumerator = reader.GetEnumerator();
while (enumerator.MoveNext())
{
    DictionaryEntry entry = enumerator.Entry;
    string value = String.Empty;
    if (entry.Value != null)
        value = entry.Value.ToString();

    textBox1.Text += entry.Key.ToString() + ", " + value +
        System.Environment.NewLine;
}

In the .NET Framework 1.1, this code includes the $this.Localizable entry. In the .NET Framework 2.0, it does not. To read this entry in the .NET Framework 2.0, you need to use the new ResXResourceReader.GetMetadataEnumerator method:


ResXResourceReader reader =
    new ResXResourceReader(@"....Form1.resx");

IDictionaryEnumerator enumerator = reader.GetMetadataEnumerator();
while(enumerator.MoveNext())
{

    DictionaryEntry entry = enumerator.Entry;
    textBox1.Text += entry.Key.ToString() + ", " +
        entry.Value.ToString() + System.Environment.NewLine;
}

This code results in just a single entry (i.e., $this.Localizable).

In addition, the change from data to metadata affects any FxCop rule that reads resource data looking for the Form.Localizable property. See the “Form. Localizable must be true” rule in Chapter 13, “Testing Internationalization Using FxCop,” for an example.

.NET Framework Redistributable

The deployment story for the .NET Framework has improved. In both .NET Framework 1.1 and 2.0, the .NET Framework redistributable (dotnetfx.exe) installs an English (United States) version of the framework. This has not changed. However, the packaging of the user interface used during the installation process has. In the .NET Framework 1.1, you could distribute different language versions of the .NET Framework redistributable. So if you distributed the German .NET Framework redistributable, the setup user interface would be in German, and the English version of the framework would be installed. In the .NET Framework 2.0, however, there is just a single .NET Framework redistributable that contains the localized user interface for all supported languages. The user interface used during installation is determined by the language version of the operating system. In addition to the installation languages supported by the .NET Framework 1.1, the .NET Framework 2.0 supports Arabic and Hebrew.

If you download the .NET Framework 2.0 redistributable from http://www.microsoft.com/downloads, be aware that the combo box that offers you a choice of languages simply refers to the language of the Web page from which the redistributable can be downloaded. The dotnetfx.exe on each and every page is 100 percent identical.

.NET Framework Language Packs

Arabic and Hebrew have been added to the list of .NET Framework Language Packs. The list of language versions for Visual Studio 2005 is the same as for Visual Studio 2003.

.NET Framework

This section describes enhancements to the .NET Framework classes, paying particular attention to the System.Globalization namespace.

New IdnMapping Class

The IdnMapping class provides support for international domain names. See the “International Domain Name Mapping” section of Chapter 6, “Globalization.”

String Identifiers for Alternate Sort Orders

Some cultures support more than one solution for sorting data. The .NET Framework 1.1 allows these alternate sort orders to be specified when a new CultureInfo is created by providing the locale ID (LCID), which represents the language, region, and sort order. The following code creates a CultureInfo object for Spanish in Spain using the traditional sort order:


CultureInfo cultureInfo = new CultureInfo(0x0000040A);

This is still supported in the .NET Framework 2.0, but the .NET Framework 2.0 supports an alternative solution when the language, region, and sort order can be specified as a string:


CultureInfo cultureInfo = new CultureInfo("es-ES_tradnl");

You can see from this example that the sort order (“tradnl”) is a suffix of the region (“ES”). The sort order can be specified for only alternate sort orders—in other words, you cannot specify the Spanish default International (Modern) sort order using “es-ES-Intl”. The complete list of alternate sort order identifiers is listed in the “Alternate Sort Orders” section of Chapter 6.

This enhancement is an important one because it enables developers to support a single data type (i.e., string) for storing and transmitting culture identifiers. Without this enhancement, developers must support both string and integer data types to be able to represent all cultures with all sort orders.

CultureInfo.GetCultures and CultureTypes Enumeration

The CultureTypes enumeration has four new members: FrameworkCultures, ReplacementCultures, UserCustomCulture, and WindowsOnlyCultures, which are used in CultureInfo.GetCultures. See the “CultureInfo.GetCultures and CultureTypes Enumeration” section in Chapter 6.

New CultureInfo Properties

CultureInfo has a new property, IetfLanguageTag, which gets the RFC 3066(bis) standard identification for a language.

New CultureInfo Methods

CultureInfo has a new method called GetCultureInfo, which provides caching support for CultureInfo objects. The first call to CultureInfo.GetCultureInfo creates a CultureInfo method as normal, but subsequent calls for the same CultureInfo get the cached copy. The benefit is better performance. However, all cached cultures are read-only and, more important, do not accept user overrides (accepting user overrides is a recommended practice); if you want to accept user overrides, you should not use this method. CultureInfo has a similar method called GetCultureInfoByIetfLanguageTag that performs the same operation but accepts an IETF language tag instead of a culture name.

String.Compare and StringComparison Enumeration

The String.Compare method has a new overload, String.Compare(string, string, StringComparison), which accepts a StringComparison enumeration. This provides a more convenient way of specifying how a string comparison should be performed instead of having to remember what String.Compare or String.CompareTo overload to call.

New DateTime Properties

DateTime has a new property called Kind, which is a DateTimeKind enumeration. This enables developers to specify whether the DateTime is local time, coordinated universal time (UTC), or unspecified (the default). This is used in conjunction with the new “KDateTime format specifier, and it provides developers with control over the serialization of dates that include time zones.

New DateTimeFormatInfo Properties

DateTimeFormatInfo has two new properties, AbbreviatedMonthGenitiveNames and MonthGenitiveNames, which surface the names of months when they are used in their genitive form (see the “Genitive Date Support” section in Chapter 6). The .NET Framework 1.1 supports genitive month names but does not expose the names for you to use for your own purposes.

DateTimeFormatInfo also has a new ShortestDayName property, which returns an array of the shortest day names (e.g., “Su”, “Mo”, “Tu”, “We”, “Th”, “Fr”, “Sa”).

New DateTime Methods

Two new methods, TryParse and TryParseExact, are siblings of the Parse and ParseExact methods. They enable you to attempt to parse a date without throwing an exception. Both methods return a Boolean indicating the success of the parsing operation.

New Calendars

The .NET Framework 2.0 adds eight new Calendar classes: EastAsianLunisolar-Calendar (abstract), ChineseLunisolarCalendar, JapaneseLunisolar Calendar, KoreanLunisolarCalendar, TaiwanLunisolarCalendar, Jalaali Calendar, PersianCalendar, and UmAlQuraCalendar. See the “Calendars” section in Chapter 6.

New Calendar Properties

Calendar.AlgorithmType is a read-only property that enables you to determine whether the calendar is a solar calendar, a lunar calendar, or both. Calendar.IsReadOnly is a read-only property indicating whether the calendar’s properties are read-only.

Calendar.MaxSupportedDateTime and Calendar.MinSupportedDateTime are read-only properties indicating the upper and lower bounds of the calendar.

New Calendar Methods

Calendar.GetLeapMonth returns a month number of the leap month in a given year and, optionally, an era. The month number is 0 if the year does not have a leap month. Calendar.ReadOnly is a static method that returns a read-only calendar object.

New CompareInfo Properties

CompareInfo has a new Name property, which provides a string identifier for the CompareInfo. Typically, this name is the same culture string used to identify a CultureInfo (e.g., “es-ES” for Spanish (Spain) international sort), but for alternate sort orders, this includes the sort suffix (e.g., “es-ES_tradnl” for Spanish (Spain) traditional sort).

New CompareInfo Methods

CompareInfo has a new static method, IsSortable, which returns true if a character or string is sortable. A character or string is sortable if all its characters are known to the .NET Framework’s sort tables. In this situation, String.Compare compares all characters in the string. However, if a string contains characters that are not known to the .NET Framework’s sort tables, String.Compare simply ignores those characters. In this situation, a more accurate test for equality can be achieved using String.CompareOrdinal, which compares the Unicode code points of all characters, regardless of their presence or absence in the .NET Framework’s sort tables.

New RegionInfo Properties

RegionInfo has new properties to help with internationalizing currency names: CurrencyEnglishName and CurrencyNativeName. RegionInfo.GeoId is a numeric geographical identifier for the region. It is useful for uniquely identifying a region and also for use with the Win32 GetGeoInfo function. See the “Geographical Information” section in Chapter 6. RegionInfo.NativeName returns the name of the region that is used in that region.

New TextInfo Properties

TextInfo.CultureName returns the name of the culture to which the TextInfo is attached. TextInfo.IsReadOnly indicates whether the TextInfo object is read-only. TextInfo.IsRightToLeft indicates whether the associated language is a right-to-left language (in the .NET Framework 1.1, this is achievable only by hard-coding a known list of right-to-left cultures). TextInfo.LCID is the locale ID of the associated language.

New TextInfo Methods

TextInfo.ReadOnly is a static method that returns a read-only TextInfo object.

New NumberFormatInfo Properties

NumberFormatInfo has two new properties, DigitSubstitution and Native Digits, which provide information about the digit systems used for formatting. DigitSubstitution is a DigitShapes enumeration that is either None, Context, or NativeNational. NativeDigits is an array of strings of the digits used for number formatting. Both properties are purely informational and have no effect in the .NET Framework 2.0. They exist for you to use for your own purposes and in expectation of better support in a future version of the .NET Framework. The following code shows their values for English (United States) and Arabic (Saudi Arabia):


CultureInfo cultureInfo = new CultureInfo("en-US");
textBox1.Text +=
    cultureInfo.NumberFormat.DigitSubstitution.ToString() +
    ":- " +
    ArrayToString(cultureInfo.NumberFormat.NativeDigits) +
    System.Environment.NewLine;

cultureInfo = new CultureInfo("ar-SA");
textBox1.Text +=
    cultureInfo.NumberFormat.DigitSubstitution.ToString() +
    ":- " +
    ArrayToString(cultureInfo.NumberFormat.NativeDigits) +
    System.Environment.NewLine;

(ArrayToString is a simple custom method to convert an array to a string.) The result is this:


None:- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Context: image

DigitSubstitution is None for all cultures except for Arabic, Kyrgyz, Mongolian, and Persian-specific cultures.

New ResourceReader Methods

ResourceReader has a new method called GetResourceData, which reads a resource as an array of bytes. The purpose of this method is to allow data of any type to be read from a .resources file. The problem that it solves is that it is not normally possible to read data from a .resources file if the data cannot be deserialized. Typically, data cannot be deserialized if the type is unknown to the application that is deserializing the data. So if one application stores, say, a BusinessObject type in a .resources file and the application reading the file does not have a reference to the assembly containing the BusinessObject type, the attempt to deserialize the BusinessObject will fail. However, the GetResourceData method allows the data for this resource to be retrieved as an array of bytes. The following example retrieves a resource entry called “String1” from “Form1Resources.resources”:


ResourceReader reader =
    new ResourceReader("Form1Resources.resources");

string resourceType;
byte[] resourceData;

reader.GetResourceData(
    "String1", out resourceType, out resourceData);

textBox1.Text +=
    "ResourceType: " + resourceType + System.Environment.NewLine +
    "ResourceData: " +
    System.Text.Encoding.UTF8.GetString(resourceData);

The result is this:


ResourceType: ResourceTypeCode.String
ResourceData: &This is the resource value for String1

Of course, this particular exercise is unnecessary because the string type can always be deserialized, but it shows the method’s behaviour.

New ResXResourceReader Properties

ResXResourceReader has a new property, BasePath, which specifies the path where files referenced in relative file references can be found. ResX file references exist in both the .NET Framework 1.1 and 2.0, and are described in the “ResX File Referencessection in Chapter 10. Another new property, UseResXDataNodes, is a Boolean value indicating whether the resource entries’ values are the simple values that they are in the .NET Framework 1.1 or are ResXDataNode objects. The default is false, so it is compatible with the .NET Framework 1.1. The benefit of the ResXDataNode objects is that they contain comments and file references. See the “ResXDataNodes and Comments” section in Chapter 10.

New ResXResourceReader Methods

ResXResourceReader has a new method called GetMetadataEnumerator. This method returns an enumerator for a resx’s metadata. The Form.Localizable property is treated as data in the .NET Framework 1.1 but as metadata in the .NET Framework 2.0. The GetMetaDataEnumerator method provides a means by which these metadata values can be retrieved. See the “ResX Changes Break Code That Uses ResXResourceReader” section of this appendix for more details.

New ResXResourceWriter Methods

ResXResourceWriter has a new method called AddAlias, which adds an assembly alias to the resx file. After ResXResourceWriter.Generate is called, the resx file contains a corresponding assembly element:


<assembly alias="System.Windows.Forms" name="System.Windows.Forms,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

Subsequent entries in the resx file need to refer to only the alias instead of the full assembly name:


<data name="button1.ImeMode"
type="System.Windows.Forms.ImeMode, System.Windows.Forms">
  <value>NoControl</value>
</data>

The result is a smaller resx file.

In addition, ResXResourceWriter has a new method called AddMetadata, which adds metadata entries to a resx file. Such entries are intended to be used for design-time properties such as Form.Localizable. Metadata entries are read using the new ResXResourceReader.GetMetadataEnumerator method.

New String and StringInfo Methods

String has two new methods, Normalize and IsNormalized, which are used to normalize strings. The problem that they solve comes from the fact that some Unicode characters can be represented in more than one way (by using several combined Uni-code characters). The binary representations are different, but the characters that they represent are the same. If their binary representations were compared, they would appear to be different, even though they result in the same character. Unicode supports a concept called normalization that resolves these representations to a simpler form, and the Normalize and IsNormalized methods implement this process.

The String and StringInfo classes also have a new property, LengthInText-Elements, and a method, SubstringByTextElements, which together enable you to process strings in terms of their text elements instead of their characters. Many scripts (e.g., Japanese Hiragana) combine characters to form text elements, and it is often meaningless to process individual characters in such scripts.

The String.Compare method has several new overloads that accept a new StringComparison enumeration that simplifies string comparisons. For example, calling String.Compare with the StringComparison.Ordinal value is the same as calling String.CompareOrdinal. Microsoft now recommends using ordinal comparisons for culture-insensitive comparisons. See the “Sort Orders” section of Chapter 6 for more details on ordinal comparisons.

New CharUnicodeInfo Class

The .NET Framework 2.0 introduces a new class, CharUnicodeInfo, which provides information about a Unicode character. The information is drawn from the Unicode Character Database for Unicode 4.1. It has four static methods (GetDecimalDigitValue, GetDigitValue, GetNumericValue, and GetUnicodeCate-gory) to retrieve various kinds of information about a character. Putting aside the 0 to 9 digits that we already know about, Unicode defines numerous code points for characters that have a numeric meaning. For example, the Unicode character ½ (U+00BD) is one half, so CharUnicodeInfo.GetNumericValue returns 0.5 for this character. A similar effect is true for Roman numerals (e.g.,“I” is 1), Tamil characters (e.g., U+0BF2 is 1000), and Tibetan characters (e.g., U+0F32 is half nine).

resx Files and File References

resx files in both the .NET Framework 1.1 and 2.0 support file references. This means that a file can be referred to instead of being embedded in the resx file. The resulting resource in the resource assembly is exactly the same as for a resource that is embedded, however, so this is simply a development issue. The important point here is that file references are now the default for the Visual Studio 2005 Resource Editor, so any file that you add to a resource, by default, simply has a reference to the file. A copy of the file is added to a local Resources folder (in a Windows Forms application) or the App_ GlobalResources or App_LocalResources folder (in an ASP.NET application), and the reference is to the file in this folder instead of the original file. In addition, the file reference is a relative reference instead of an absolute reference.

New ResourceManager Methods

ResourceManager has a new method called GetStream, which returns an UnmanagedMemoryStream for a resource given the name of that resource. The method is not CLS compliant.

Customizing the Fallback Process

The .NET Framework 2.0 enables you to specify that the location of the fallback resources is a satellite assembly. In the .NET Framework 1.1, the only choice was that fallback resources were in the invariant or fallback assembly. The downside to this approach is that there is no separation between resources and code. See the “NeutralResourcesLanguageAttribute and UltimateResourceFallback Location” section in Chapter 3, “An Introduction to Internationalization.”

ResView and ResExtract (Managed Resource Viewer)

The Base Class Library Samples includes two new utilities for manipulating resources, which are collectively referred to as the Managed Resource Viewer. Although they are not specific to the .NET Framework 2.0, they were released during the same time period, so I have included them in this appendix. ResView is a resource viewer, and ResExtract extracts resources from a resource assembly. See http://msdn.microsoft.com/netframework/downloads/samples/bclsamples/ for more details.

Strongly Typed Resources

The .NET Framework 2.0 and Visual Studio 2005 support a concept of strongly typed resources. So instead of writing this:


MessageBox.Show(resourceManager.GetString("InsufficientFunds"));

You can write this:


MessageBox.Show(Form1Resources.InsufficientFunds);

You gain several benefits from this. The resource entry name is checked at design time instead of runtime, so typos are eliminated. The property is strongly typed, which gives compile-time type checking. The resource class (Form1Resources, in this example) encapsulates the ResourceManager, so it is not necessary to manage it yourself. Strongly-typed resources are initially covered in Chapter 3 but are also covered again in several other chapters. If you are staying with the .NET Framework 1.1, see the “Strongly-Typed Resources in the .NET Framework 1.1” section in Chapter 3 for an equivalent solution.

Custom Cultures

The .NET Framework 2.0 supports a concept of custom cultures. This concept existed in the .NET Framework 1.1, but it was primitive and difficult to gain any real benefit from. This improved implementation is recognized by the .NET Framework 2.0, the .NET Framework 2.0 SDK, and Visual Studio 2005. A custom culture is a culture that you define. It can be a modification of an existing culture, a combination of existing cultures, or a completely new culture in its own right. This idea has huge potential, which is why this book includes a whole chapter on this subject: Chapter 11, “Custom Cultures.”

Visual Studio’s Resource Editor

Visual Studio’s Resource Editor has had an overhaul for Visual Studio 2005. Apart from its visual appearance, the main feature is that it does not handle all resources as strings. It enables you to manage bitmaps, icons, audio, and other files as resources.

Windows Forms

This section details the .NET Framework 2.0 and Visual Studio 2005 enhancements which are specific to Windows Forms applications.

Property Reflection Model

Visual Studio 2005 supports a model for serializing Windows Forms called property reflection. Instead of properties being serialized one by one as they are in Visual Studio 2003’s property assignment model, properties are loaded using reflection by searching for resources with names that match the control and its properties. The end result is no different from the end result of Visual Studio 2003 in terms of functionality. The difference lies in the performance of forms that have large numbers of controls, so property reflection is said to scale better than property assignment. See Chapter 4.

Control.AutoSize

In the .NET Framework 1.1, several controls have an AutoSize property, but many do not. In the .NET Framework 2.0, the AutoSize property has been moved to the System.Windows.Forms.Control base class, meaning that all controls now have an AutoSize property. You will find that a few controls (e.g., ListBox) hide their AutoSize property in the Form Designer, but putting these controls aside this means that significantly more controls in Windows Forms 2.0 have an AutoSize property. See the “AutoSize” section in Chapter 8, “Best Practices.”

Label.AutoSize Default

The default for Label.AutoSize remains unchanged in the .NET Framework 2.0 and is still false. However, Visual Studio 2005 treats this control differently from Visual Studio 2003: When a Label control is added to a form, its AutoSize property is automatically set to true. The effect is that it appears that the default has changed from false to true. This is helpful because it is more usual to want Label controls to be autosized on a localized form. Note that the LinkLabel control inherits from Label, so the same change applies to LinkLabel controls.

A similar effect can be seen for CheckBox and RadioButton controls. These controls do not have an AutoSize property in the .NET Framework 1.1. In the .NET Framework 2.0, the default value for AutoSize for CheckBoxes and RadioButtons is false, but Visual Studio 2005 automatically sets it to true.

AutoSizeMode Property

Some controls (Button, DataGridViewColumn, Form, GroupBox, Panel, Splitter-Panel, TabPage, ToolStripContentPanel, UserControl) have a new property called AutoSizeMode that can be set to determine whether the control should automatically grow and shrink as necessary or grow only as necessary. See the “Auto-SizeMode” section in Chapter 8.

AutoEllipsis Property

Some controls (Button, CheckBox, Label, RadioButton) have a new AutoEllipsis property, which automatically displays an ellipsis in the text when there is insufficient room to display the whole text. This is useful for controls that must be localized but whose size must not change (such as controls on a sculpted form). The full text is still available as a ToolTip. See the “AutoEllipsis” section in Chapter 8.

RightToLeftLayout Property

The Form control, together with a number of other Windows Forms controls, now has a RightToLeftLayout property. This Boolean property is used in conjunction with the RightToLeft property and takes effect only when RightToLeft is Yes. Its purpose is to relocate controls within the form so that the controls appear as if they have been laid out correctly for a right-to-left language instead of a left-to-right language. In addition, it correctly mirrors a form’s title bar so that the System Menu, Close, Maximize, and Minimize buttons are repositioned correctly. See the “Right-to-Left Languages and Mirroring in Windows Forms Applications” section of Chapter 7, “Middle East and East Asian Cultures,” for more details.

TableLayoutPanel and FlowLayoutPanel Controls

The .NET Framework 2.0 includes two new controls, TableLayoutPanel and FlowLayoutPanel, which bring the power of HTML’s table and flow layout to Windows Forms. These are significant controls and can have a considerable impact on the way you design your forms for localization and the subsequent role that a translator/localizer might take. Using these controls means that your forms can automatically adapt to controls that resize as a consequence of their text changing size. Well-designed forms, therefore, do not need to be redesigned for different cultures, and a single form can fit all cultures. This drastically reduces the localization effort. See the “TableLayoutPanel and FlowLayoutPanel” section in Chapter 8.

BackgroundWorker

Windows Forms 2.0 introduces a new component called BackgroundWorker, which simplifies moving work to a background thread. This control is relevant to internationalization because, unlike the primitive Thread class that it replaces, Back-groundWorker does not provide you with direct access to the background thread upon which it is based. You can still set the BackgroundWorker’s Thread’s CurrentCulture and CurrentUICulture, but these must be set in the DoWork event handler:


public void BeginBackgroundWorker()
{
    BackgroundWorker backgroundWorker = new BackgroundWorker();
    backgroundWorker.DoWork +=
        new DoWorkEventHandler(backgroundWorker_DoWork);
    backgroundWorker.RunWorkerAsync();
}

void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
    // do some work
}

WinRes

WinRes in the .NET Framework 1.1 SDK is difficult to use, for several reasons. WinRes in the .NET Framework 2.0 SDK is considerably improved, so if you rejected this tool previously, you should take a fresh look at it in 2.0 for small to medium-sized projects (for large projects, consider using one of the commercially available tools).

First and foremost, WinRes now understands the resx files that Visual Studio 2005 creates. It supports two file modes: Visual Studio File Mode and Single File Mode (the only mode used in WinRes 1.1). This means that you can read and write resx files in both Visual Studio 2005 and also WinRes 2.0 without having to commit to one tool.

WinRes 2.0 has significantly better error reporting. WinRes 1.1 had a handful of cryptic and unhelpful error messages, which lead to a lot of thrashing around trying to identify the real problem. WinRes 2.0 has more descriptive error messages.

WinRes 2.0 is more resilient than its predecessor. WinRes 1.1 refused to load a form if it found a single fault on the form. WinRes 2.0 loads all that it can load and reports the problems about the failed components.

WinRes 2.0 supports loading forms that inherit from other forms when the controls on those other forms have public visibility. Although this support is not absolute, it is considerably better than WinRes 1.1’s nonexistent support.

Finally, WinRes 2.0 offers many of the same design and productivity improvements that you see in Visual Studio 2005’s Forms Designer (e.g., snap lines).

See the “Windows Resource Localization Editor (WinRes)” section in Chapter 4.

ASP.NET

Visual Studio 2005 is a quantum leap beyond Visual Studio 2003 in terms of internationalization of ASP.NET applications. As with so many features in the .NET Framework 2.0 and Visual Studio 2005, this subject alone justifies the upgrade.

Localizability

Visual Studio 2005 enables you to localize forms with the same kind of productivity and efficiency that Visual Studio provides for Windows Forms applications. Select Tools, Generate Local Resources from Visual Studio 2005’s menu; all the Localizable property values are moved to an associated resx file, and a “meta:resourcekey” attribute referring to those resources is added to the control. See the “Localizability in Visual Studio 2005” section in Chapter 5, “ASP.NET Specifics.”

Web.config <globalization> culture and uiCulture Attributes

The <globalization> section of Web.config has always had culture and uiCulture attributes, which enable you to specify the CurrentCulture and CurrentUICulture of an entire Web site or folder. In ASP.NET 2.0, however, these attributes can be set to “auto” to automatically pick up the user’s preferred settings from the HTTP header. See the “Application-Wide Automatic Culture Recognition” section in Chapter 5.

New Page Culture and UICulture Attributes

The Page class now supports Culture and UICulture attributes, which work in the same way as the <globalization> element’s culture and uiCulture attributes, except that they apply to a single page. See the “Automatic Culture Recognition for Individual Pages” section in Chapter 5.

New Page.InitializeCulture Method

The Page class has a new method called InitializeCulture, which can be overridden to set the culture. This method is called before all the page’s events so that it occurs early in the pipeline. You would use this method if the “auto” settings did not provide the functionality you are looking for. See the “Manual Culture Recognition for Individual Pages” section in Chapter 5.

Web Control Properties Are Marked as Localizable

In ASP.NET 1.1, no properties of any control are marked with the Localizable attribute. This is because Visual Studio 2003 does not offer any localization support for ASP.NET applications, so the presence or absence of the Localizable(true) attribute makes no difference. In ASP.NET 2.0, you will find that many properties of Web controls are marked as Localizable(true), and this is how Visual Studio 2005 can localize pages. What is important to note here is that only a few HTML control properties are marked as Localizable(true). In general, this means that if you want to localize your ASP.NET applications, you must use Web controls instead of HTML controls.

New Localize Control

The Localize control inherits from the Literal control and adds no new properties, methods, or events. At runtime, the Localize control is identical to the Literal control. The difference between the two controls lies in Visual Studio 2005’s handling of these controls at design time. The Localize control uses the Localize Designer, whereas the Literal control uses the LiteralDesigner. The purpose of both the Localize control and the Literal control is to allow text to be placed in a control that can be localized—your choice between the two controls is determined by your preference of design-time support.

Automatic resx File Change Detection

By default, ASP.NET 2 applications monitor their associated resx files at runtime. When one of their associated resx files changes, ASP.NET unloads the application domain, rebuilds the associated resource assemblies, and reloads the application. This means that translators can modify resx files and see their changes immediately. In addition, the resources used in Web sites can be updated without needing to manually rebuild the application. Of course, this unloads the application domain, and any state in that domain will be lost. See the “ASP.NET 2.0 Translation/Localization Strategies” section in Chapter 14, “The Translator.”

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.22.136