Font Selection


One of the many decisions you will have to make in the internationalization of your application is what font to use for your controls. Your choice will be dependent upon the languages you want to support and the functionality of the operating system your application will be running on. In this section, we look at the various font technologies that will affect your decision, to help you arrive at a conclusion.

Font Terminology and the Font Class

All developers have used fonts to a greater or lesser degree. The terminology used to describe fonts, however, is often not what developers have come to use in their everyday use of Windows; it is for this reason that a brief overview of font terminology is advisable. If you open the Fonts control panel applet, you will see the fonts that have been installed on your computer (see Figure 8.1).

Figure 8.1. The Fonts Control Panel Applet in Details View


You can see from this figure that there is not one, but four Times New Roman font files on this computer. Times New Roman is a typeface; it describes the way characters are drawn. Each of the font files contains the characters drawn in a different style (regular, bold, bold and italic, italic). The collection of font files for a given typeface is referred to as a font family. So Times New Roman, Times New Roman Bold, Times New Roman Bold Italic, and Times New Roman Italic are all members of the same font family. The font family is given the same name as the typeface (e.g., Times New Roman), so the terms are often used interchangeably. In the .NET Framework documentation, the term typeface is often replaced with the term family name. A font is simply a typeface plus a font size, so 8 point Times New Roman Bold is a font.

You may notice that some font families do not include bold or italic font files (e.g., Century). It is still possible to use bold and italic styles even when no font file specifically exists for that style. In these cases, the fonts are thickened or slanted to give a bold or italic impression.


The .NET Framework Font class is a wrapper around a specific font and can be created like this:

 Font font1 = new Font("Times New Roman", 8); Font font2 = new Font("Times New Roman", 8, FontStyle.Bold); Font font3 = new Font("Times New Roman", 8, FontStyle.Bold |     FontStyle.Italic); Font font4 = new Font(font1, FontStyle.Bold); 


The fonts that are installed on a machine are called physical fonts. You can request any font name with any style, and the operating system will give you the closest match to that font. The process of relating a logical font to a physical font that most closely matches the logical font is called font mapping. The font-mapping process cannot fail (unless you specify an unreasonable font size, such as infinity), so the following code does not throw an exception on any version of Windows:

 Font font = new Font("FontDoesNotExist", 8); 


On English Windows XP Professional SP2, this results in the Microsoft Sans Serif font. The font-mapping mechanism allocates a score to each font based upon nearly 30 criteria, and the font with the best score wins. The only useful criteria that the font mapper has to go on in this example is the font size. This will almost certainly match many TrueType or OpenType fonts, and several will have equal weights. In this scenario, as far as the application is concerned, the choice is arbitrary, as it is based upon issues such as the order of fonts during initialization.

Font Properties Extension

The Font Properties Extension is a free tool from Microsoft (http://www.microsoft.com/typography/FreeToolsOverview.mspx) that adds new tabs to the Font Properties dialog for OpenType and TrueType fonts. In the Fonts control panel applet, right-click a font file and select Properties. Normally, this dialog just has General and Summary tabs (and, on some versions, of Windows a Security tab). The new tabs contain a wide variety of information about a font. In particular, the CharSet/Uni-code tab enables you to explore the "Supported Unicode Ranges" (see Figure 8.2).

Figure 8.2. Charset/Unicode Tab of Font Properties Extension for Microsoft Sans Serif


You can get more information about Unicode code point ranges (detailing which ranges include which scripts) at http://www.unicode.org/charts/.


Using this tab, you can determine whether a font will be suitable for the languages you need to support. In terms of code point range coverage, Arial Unicode MS (installed with some Microsoft Office applications) has one of the largest. One of the limitations of the Font Properties Extension is that it cannot show additional tabs for Font Collections. A Font Collection (.TTC) is a file that is a collection of fonts. You can overcome this limitation by breaking down collections into individual font files using BREAKTTC.EXE (from the Microsoft TrueType Font SDK). The Font Properties Extension simply works with font files anywhere, so you don't have to extract the files to the system's font directory.

Getting Font Information Programmatically

You can obtain some information about a font programmatically. The Font class has a property called GdiCharSet that indicates the character set that the font supports. Unfortunately, it is mostly useless, as it can only ever be set to a value other than 1 using the following Font constructor:

 public Font(string familyName, float emSize, FontStyle style,     GraphicsUnit unit, byte gdiCharSet, bool gdiVerticalFont) 


In all other cases, GdiCharSet is 1. Even when the previous constructor is used, GdiCharSet is relatively meaningless because the caller must decide what the character set is and then must tell the Font object what the font's character set is. Instead, you should use the Font.ToLogFont method to gain this and other information:

 Font font = new Font("Simplified Arabic", 12); LOGFONT logFont = new LOGFONT(); font.ToLogFont(logFont); int gdiCharSet = logFont.lfCharSet; 


The Font.ToLogFont accepts a new LOGFONT object and initializes its properties. The LOGFONT class doesn't exist in the .NET Framework, so you have to define it yourself:

 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] class LOGFONT {     public int lfHeight;     public int lfWidth;     public int lfEscapement;     public int lfOrientation;     public int lfWeight;     public byte lfItalic;     public byte lfUnderline;     public byte lfStrikeOut;     public byte lfCharSet;     public byte lfOutPrecision;     public byte lfClipPrecision;     public byte lfQuality;     public byte lfPitchAndFamily;     [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]     public string lfFaceName; } 


The lfCharSet field contains a number for the character set that the font supports. The numbers are defined in WINGDI.H (in %ProgramFiles%\Microsoft Visual Studio 8\Vc\PlatformSDK\Include or %ProgramFiles%\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include, depending on your version of Visual Studio). Search for ANSI_CHARSET. In the previous example, the Simplified Arabic font returns a value of 178, which is the value defined by the ARABIC_CHARSET in WINGDI.H.

Windows Forms Controls

All Windows Forms controls inherit from System.Windows.Forms.Control, where the Font property is implemented. If the control's Font property is not explicitly set, it inherits its value from its parent control's Font property. This continues up to the ultimate parent, which gets its value from the static read-only Control.DefaultFont property. The implementation of the Control.Default-Font property differs slightly between the .NET Framework 1.1 and 2.0. In the .NET Framework 2.0, Control.DefaultFont simply uses the SystemFonts.Default-Font font. The SystemFonts.DefaultFont pseudo code is:

 if the operating system is Japanese Windows NT4     font = MS UI Gothic, 9 point else if the language version of the operating system is Arabic     font = Tahoma, 8 point else     font = GetStockObject(DEFAULT_GUI_FONT)     if GetStockObject does not return an OpenType or TrueType font         font = Tahoma, 8 point 


The Control.DefaultFont value is cached, so you can refer to it continuously without a performance overhead. The .NET Framework 1.1 doesn't have the SystemFonts class, but similar logic is built directly into the Control.Default-Font property. Here's the pseudo code:

 if the operating system is Japanese Windows NT4     font = MS UI Gothic, 9 point else     font = GetStockObject(DEFAULT_GUI_FONT)     if GetStockObject does not return an OpenType or TrueType font         font = Tahoma, 8 point 


The difference in functionality is that the .NET Framework 2.0 has additional logic for handling Arabic Windows as a special case, whereas the .NET Framework 1.1 does not. So on Arabic Windows, Control.DefaultFont is 8 point Tahoma using the .NET Framework 2.0, and Microsoft Sans Serif 8.25 using the .NET Framework 1.1. Some example values of GetStockObject and Control.DefaultFont for different operating systems and different languages can be seen in Table 8.1.

Table 8.1. GetStockObject and Control.DefaultFont Examples

Windows Version

Language Version

GetStockObject

Control.DefaultFont (.NET 2.0)

Control.DefaultFont (.NET 1.1)

Windows XP Pro SP2

English

Microsoft Sans Serif

Microsoft Sans Serif

Microsoft Sans Serif

Windows XP Pro SP2

Arabic

Microsoft Sans Serif

Tahoma

Microsoft Sans Serif

Windows XP Pro SP2

French

Microsoft Sans Serif

Microsoft Sans Serif

Microsoft Sans Serif

Windows XP Pro SP2

German

Microsoft Sans Serif

Microsoft Sans Serif

Microsoft Sans Serif

Windows XP Pro SP2

Japanese

MS UI Gothic

MS UI Gothic

MS UI Gothic

Windows 2000 Professional

English

Microsoft Sans Serif

Microsoft Sans Serif

Microsoft Sans Serif

Windows 98 SE

English

Not OpenType/TrueType font

Tahoma

Tahoma

Windows 98 SE

Japanese

MS UI Gothic

MS UI Gothic

MS UI Gothic


In both versions of the framework, the Font property is serialized on localized forms only if the Font property has been changed from the default on the development machine. So if the Font property is not changed, the Control.DefaultFont will be calculated at runtime and this will be on the user's machine. The moral of the story is that if you want the functionality provided by Control.DefaultFont, leave the font default alone at design time.

ASP.NET Controls

All ASP.NET Web controls inherit from System.Web.UI.WebControls.WebControl, where the Font property is implemented. Unlike System.Windows.Forms. Control.Font, WebControl.Font is a FontInfo object. The FontInfo object simply sets HTML attributes of a control. Figure 8.3 shows the expanded Font property of a Label control. The resulting HTML is:

 <asp:Label  runat="server" Font-Names="Tahoma,Arial" Font-Size="Larger" Font-Bold="True">Label</asp:Label> 


Figure 8.3. Properties Window Showing Expanded Label.Font Property


If the control's Font property is not explicitly set, it does not inherit its value from its parent or any other control; instead, the property remains blank and it is left to the browser to select a font. Setting an explicit font name on a control is bad practice unless there is something specific about the individual control that demands it. If a font must be set, it can be set in a Cascading Style Sheet (CSS). To create a CSS file, open Solution Explorer; right-click the project; select Add, New Item...; click the Style Sheet icon; and click Open. Add a definition for the body element either by typing or by using the Style Builder (in CSS Outline, expand elements, select body, right-click, and select Build Style...):

 body {     FONT-FAMILY: Tahoma,Arial; } 


To use the CSS file, add a LINK element to the aspx's HEAD element:

 <LINK href="StyleSheet1.css" type="text/css" rel="stylesheet"> 


This assumes that the style sheet is called StyleSheet1.css.

However, the simplest and most effective solution is to leave the problem of font selection to the browser. Obviously, this support is dependent upon the browser on the client, but in Internet Explorer, it can be configured by selecting Tools, Internet Options... and clicking on the Fonts... button (see Figure 8.4).

Figure 8.4. Internet Explorer Font Configuration


This dialog allows the user to specify which fonts are used for which languages. The "Language script" combo box allows the user to select a language, and the two list boxes below allow the user to specify which fonts are used for Web pages and plain text, respectively. If the user is running on Windows, all of the same issues covered in the next few sections (font substitution, font linking, font fallback) apply equally to an ASP.NET application as they do to a Windows Forms application.

The SystemFonts Class

The SystemFonts class, introduced in the .NET Framework 2.0, is a collection of read-only static properties and one method that represent intelligent wrappers around the system's font properties set by the user in the Display control panel applet. Table 8.2 shows the properties of the SystemFonts class and some example values.

Table 8.2. SystemFonts Properties and Example Values

Name

Description

Example on English Windows XP Pro SP2

CaptionFont

The font that an application can use to display text in the title bars of windows

Trebuchet MS

DefaultFont

The default font that an application can use for dialogs and forms

Microsoft Sans Serif

DialogFont

The font that an application can use for dialogs and forms

Tahoma

IconTitleFont

The font that is used for icon titles

Tahoma

MenuFont

The font that an application can use for menus

Tahoma

MessageBoxFont

The font that is used for message boxes

Tahoma

SmallCaptionFont

The font that is used to display text in the title bars of small windows, such as tool windows

Tahoma

StatusFont

The font that an application can use to display text in the status bar

Tahoma


The properties include the kind of intelligence seen in the Control.Default-Font discussion earlier in this chapter, so you can expect different results on Windows 98 and Me, for example. You can change the system fonts from the Display control panel applet by selecting the Appearance tab and clicking on the Advanced button to get the Advanced Appearance dialog (see Figure 8.5).

Figure 8.5. Use the Advanced Appearance Dialog to Set Properties of SystemFonts


You can use the SystemFonts class as part of the localization process by setting a form's Font to SystemFonts.DialogFont. This is best done in the form's constructor:

 public Form1() {     Font = SystemFonts.DialogFont;     InitializeComponent(); } 


To apply this behavior across your application, create a Form base class, set the Font in the base class, and ensure that all forms inherit from the base class. In this way, you can abstract the problem of choosing a font, and your application can use a font that is appropriate for the machine that it is running on.

Font Substitution

One of the older font technologies is font substitution (introduced in Windows 3.1). Font vendors often copyright their font names and, consequently, the names become unique. Font substitution allows one font name to be replaced with another. So, for example, you could map a font face name of Helvetica to the physical font Arial. Whenever the Helvetica font is requested, an Arial font would be returned. Font substitutions are set in the Registry in Windows NT and above at HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes (see Figure 8.6).

Figure 8.6. Font Substitution Registry Entries


In Windows 98 and Me, they are set in the FontSubstitutes section of WIN.INI:

 [FontSubstitutes] Helv=MS Sans Serif Tms Rmn=MS Serif Times=Times New Roman Helvetica=Arial MS Shell Dlg=MS Sans Serif MS Shell Dlg 2=MS Sans Serif Monotype.com=Andale Mono 


So in the following code snippet, where a Helvetica font is not installed and Helvetica has been mapped to Arial:

 new Font("Helvetica", 12).Name; 


the Name property is "Arial".

MS Shell Dlg and MS Shell Dlg 2

Font substitution is of interest in the localization process because of two font face names: MS Shell Dlg and MS Shell Dlg 2. These font face names are set to different fonts for different versions of Windows and different language versions of Windows (see Table 8.3).

Table 8.3. MS Shell Dlg and MS Shell Dlg 2 Font Face Name Values

Windows Version

Language Version

MS Shell Dlg

MS Shell Dlg 2

Windows XP Pro SP2

English

Microsoft Sans Serif

Tahoma

Windows XP Pro SP2

Arabic

Microsoft Sans Serif

Tahoma

Windows XP Pro SP2

French

Microsoft Sans Serif

Tahoma

Windows XP Pro SP2

German

Microsoft Sans Serif

Tahoma

Windows XP Pro SP2

Japanese

MS UI Gothic

Tahoma

Windows 2000 Professional

English

Microsoft Sans Serif

Tahoma

Windows NT 4 WorkStation

Japanese

(MS ) Japanese for MS PGothic

Not present

Windows 98 SE

English

Arial

Arial

Windows 98 SE

Japanese

Arial

Arial


The MS Shell Dlg font face name is intended to be used for compatibility with versions of Windows prior to Windows 2000. The MS Shell Dlg 2 font face name is intended to be used with Windows 2000 and above. However, you are free to use either font face name (where MS Shell Dlg 2 is preferred), as both names, thanks to font substitution and font mapping, work on all languages and all versions of Windows. The benefit of using one of these font face names in your application is that your application is abstracted from the problem of choosing a font directly, and this choice can be delayed until runtime. The disadvantage of using a font face name instead of a physical font name is that substituted fonts are not visible in the Properties Windows in Visual Studio and cannot be set in the Properties Window. Instead, they must be set in code:

 public Form1() {     Font = new Font("MS Shell Dlg 2", 12);     InitializeComponent(); } 


The same comments as before about using a form base class apply equally here. An alternative to this approach is to use the StandardPropertiesResourceMan-ager in Chapter 12, "Custom Resource Managers," which can assign the same value to every property (e.g., Font) that is loaded as a resource.

Font Linking

Font linking is a great feature introduced in Windows 2000. The basic idea is that it is unrealistic in design and performance terms for a single font to support all code points for which Unicode has a definition, but it would be useful if a single font could act as if it did. If a single font could appear to support all glyphs, an application would not have to switch fonts to display other glyphs. By default, on Windows XP Professional SP2, there are no font links, but there is nothing to stop you from adding your own. In the Registry, add new keys to HKEY_LOCAL_MACHINE\SOFT WARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink, where the key name is the name of the font and the value is the names of the fonts that it is linked to. If you install East Asian support (in the Regional and Language Options dialog, select the Languages tab, check the "Install files for East Asian languages" check box, and click OK), several entries are created (see Figure 8.7).

Figure 8.7. Font Linking Registry Entries on Windows XP Pro SP2 with East Asian Support Installed


Double-click the Microsoft Sans Serif key, and you will see what fonts it is linked to (see Figure 8.8). The value is exactly the same as for Tahoma. Recall that Microsoft Sans Serif and Tahoma are typically used as the values for the MS Shell Dlg and MS Shell Dlg 2 font face names, respectively.

Figure 8.8. Microsoft Sans Serif Font Linking Registry Entry


You can see from this that by installing East Asian support, the Microsoft Sans Serif font has been font-linked to the MSGOTHIC, gulim, SimSun, and mingliu True-Type Collections. Table 8.4 shows a cut-down list of the Unicode code ranges that these fonts support.

Table 8.4. The Unicode Code Ranges Supported by Microsoft Sans Serif and Its Font-Linked Fonts

TrueType Font Collection

TypeType Fonts

Latin, Greek, Cyrillic

Arabic, Thai, Hebrew

CJK

Hangul

Bopomofo

N/A

Microsoft Sans Serif

Yes

Yes

No

No

No

MSGOTHIC.TTC

MS Gothic, MS PGothic, MS UI Gothic

Yes

No

Most

No

No

gulim.ttc

Dotum, DotumChe, Gulim, GulimChe

Yes

No

Some

Yes

No

SimSun.TTC

SimSum, NSimSum

Basic Latin

No

Some

No

Yes

mingliu.ttc

MingLiU, PMingLiU

Basic Latin

No

Some

No

Yes


You can see from this list that Microsoft Sans Serif has been "enhanced" to support glyphs that are outside of its base ranges. The combination of the four TrueType Collections adds support for CJK (Chinese, Japanese, Korean), Hangul, and Bopomofo glyphs. If this is such a great feature, you might wonder if Microsoft Sans Serif either should be linked with these fonts by default or should include the glyphs from these other fonts without having to link to them. The answers are flexibility and performance. By default, these additional fonts are not installed in English Windows XP Professional SP2. The Microsoft Sans Serif font is 450K, whereas the additional four TrueType Collections are more than 120Mb. Apart from the performance hit that this incurs, the method of font linking means that more than one font, can be linked to the same font. As developers, we should all appreciate this form of reuse.

In localization terms, this means that we can use a single font, such as Microsoft Sans Serif or Tahoma, and rely upon it being extended to include the glyphs that we need for other Unicode code ranges. Figure 8.9 shows a Windows Forms form that uses the Microsoft Sans Serif font to display Japanese characters on an English Windows XP Professional SP2 machine that has East Asian support installed.

Figure 8.9. Form Using Microsoft Sans Serif on Windows XP Pro SP2 with East Asian Support


Figure 8.10 shows the same form running on English Windows XP Professional SP2 where East Asian support has not been installed.

Figure 8.10. Form Using Microsoft Sans Serif on Windows XP Pro SP2 without East Asian Support


When a font does not have a glyph for a requested code point, the "not defined" glyph (a box) is displayed instead. This provides a small piece of information on the nature of the display problem (i.e., the font that is being used does not have a glyph for the code point that it is trying to display). Figure 8.11 shows the same form displayed on English Windows 98 SE.

Figure 8.11. Form Using Microsoft Sans Serif on Windows 98 SE


Clearly, there is also a problem displaying some of the glyphs on Windows 98 SE, but the cause of problem is slightly different. The question marks indicate that the conversion from Unicode to the code page failed (because the code page doesn't have encodings for those Unicode code points). This will happen only on 16-bit ("code page") versions of Windows.

The moral of this story is that you can use a single font throughout your application for many different languages if it either supports all of those languages or is linked to other fonts to support those languages.

Font Fallback

Like font linking, font fallback was new in Windows 2000 and offers a similar service: When a font needs to display a Unicode code point for which it has no glyph, it can fall back to a predefined system font to provide the glyph. There are, however, several differences between font fallback and font linking. First, and most important, font fallback is implemented by Uniscribe (a layer beneath GDI+). This is important because when characters are combined in a complex script, their form can change. This is not something you see in English, for example. In English, the letter a is always formed the same way, regardless of what letters come before it or after it. In a complex script, the rendering of a character can be altered by many factors. Uniscribe takes care of these details without any intervention on the developer's behalf. So if the Courier New font needs to display the Devanagari letter Aa (U+0906) Uniscribe falls back to the Mangal font to display the letter. Figure 8.12 shows a Windows Forms application with a TextBox using the Courier New font running on Windows XP Professional SP2 with East Asian support installed.

Figure 8.12. Courier New on Windows XP Pro SP2 with East Asian Support


Figure 8.13 shows the same application running on Windows XP Pro SP2 with no additional support installed. The square character indicates that the Courier New font does not have a glyph for Unicode code point U+0906 and that the fallback fonts that Courier New could fall back to are not installed.

Figure 8.13. Courier New on Windows XP Pro SP2 without East Asian Support


The second difference between font fallback and font linking is that the font fall-back default fonts are hard-wired and cannot be interrogated. You can change the fallback fonts in the Registry by adding new entries to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Language Pack\SurrogateFallback. Each entry has a key of "Plane" with a number suffix (e.g., "Plane1", "Plane2", etc.) and refers to a different "plane" of Unicode code points. A plane is a range of 64K code points. Each key has a string value for the font family name to use for rendering code points within that plane.

Font Names Are Sometimes Translated

The Times New Roman font can be referred to as "Times New Roman" in every language version of Windows in the world. The same is true for the majority of fonts, and this makes our lives very easy. Unfortunately, the same is not true for all fonts, especially Chinese, Japanese, and Korean fonts. For many of these fonts, the names have been localized, and this represents an additional level of consideration for your applications. Take, for example, the Japanese MS Mincho font. The following code on English Windows XP Professional SP2 sets fontName to "MS Mincho" (assuming that the MS Mincho font is installed):

 Font font = new Font("MS Mincho", 12); string fontName = font.Name; 


However, the same code running on Japanese Windows XP Professional SP2 sets fontName to "MS ". The code executes fine, but if you need to compare the font name for any reason, then your code needs to be modified. Fortunately, the FontFamily.GetName method has the solution. GetName accepts an LCID of the locale for which the font name should be returned. For the vast majority of fonts, the return value will be exactly equal to the name of the font. However, for MS Mincho, the results will differ.

 Font font = new Font("MS Mincho", 12); string englishFontName = font.FontFamily.GetName(1033); string japaneseFontName = font.FontFamily.GetName(1041); 


The LCID for English (United States) is 1033 and for Japanese (Japan) is 1041, so englishFontName is set to "MS Mincho" and japaneseFontName is set to "MS ", regardless of the language version of the operating system.

It should be noted that it is also possible to specify the font name in the localized language:

 Font font = new Font("MS ", 12); 


This font name will be recognized on both English and Japanese Windows XP Professional SP2, Windows 2000, Windows Server 2003, and also, in this case, Windows 98 SE. But this support for both the English and localized font names is limited. In Windows Server 2003, Windows XP Professional SP2, and Windows 2000, both font names should be available, but support is less complete in earlier versions. This could lead you to the conclusion that, for some fonts, you are forced to use the English name on all locales, except the locale for which the font is really needed, where the font name must be localized. Of course, if the font is required for only a single locale and all other locales use a different font anyway, the problem becomes moot because you would only ever use the translated name on the locale where the font is required.

Font Strategy

So, what does all of this mean then? It means that if your clients are using Windows 2000 or later, you can afford to use a single font throughout the application for all languages. Thanks to font linking and font fallback, a single font can supply all of the characters for all the Unicode code point ranges that you need to support. It also means that if you do nothing, then the default font chosen for you will most likely be appropriate for the machine's culture. An alternative means of delaying the choice of font until runtime is to use the MS Shell Dlg or MS Shell Dlg 2 font face names. If your clients are using a version of Windows prior to Windows 2000, they will not be able to use font linking and font fallback, and you may be forced to use a different font for each culture. In most cases, however, you should still be able to get away with a single font used throughout the application.

In ASP.NET applications, you are at the mercy of the browser and the operating system the browser is running on. The advice, however, is mostly the same: Either leave the font name alone or use a font face name (assuming that the clients are running on Windows) to delay the font choice until runtime.




.NET Internationalization(c) The Developer's Guide to Building Global Windows and Web Applications
.NET Internationalization: The Developers Guide to Building Global Windows and Web Applications
ISBN: 0321341384
EAN: 2147483647
Year: 2006
Pages: 213

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net