Pseudo Translation


As part of the internationalization process, you will certainly want to test how local-izable your application is. No matter how sophisticated your toolkit is, some part of the testing process must involve looking at the end result of the translation. The form in Figure 9.2 has been translated into Greek.

Figure 9.2. A Windows Form Localized into Greek


Although this scores 10 out of 10 for showing that the application is localizable, the user interface is very difficult to navigate if you can't read Greek. Which of the buttons in the screenshot enables the user to add payments? The user acceptance team will be unable to use the Greek version of the application to test that the application has been globalized, but if they use the English version of the application, they cannot accurately test globalization, either. You need a solution that enables the user acceptance team to read the application so that they can operate it properly, but the language and culture must be different from the development team's language and culture. Enter pseudo translation and pseudo culture.

Pseudo translation is translation that modifies the original text so that the original text can still be inferred from the translated result. You can pseudo translate your application in many different ways:

  • You could capitalize the text (e.g., "Exit" becomes "EXIT"). The downside is that there is no difference when the original text is already in capitals (e.g., "OK").

  • You could prefix the text with a letter (e.g., "T" for "translated""Exit" becomes "T Exit").

  • You could prefix the text with language and culture (e.g., "Exit" becomes "fr-FR Exit").

  • You could prefix the text with "xxx" and suffix with "xxx" (e.g., "Exit" becomes "xxx Exit xxx").

  • You could convert to Pig Latin (e.g., "Exit" becomes "Exit-hay").

  • You could convert each character to an accented version of the same character (e.g., "Exit" becomes "χ").

  • Lord of the Rings), and Klingon. The Middle Earth and Klingon languages are especially difficult to translate to, partly because there are no machine translators for these languages, but also because Klingon grammar is so very different from Roman grammar.

The option that I have chosen is to convert to accented characters. In this approach, each character is converted to an equivalent character that has an accent. You can find equivalent accented characters using the Character Map (Start, All Programs, Accessories, System Tools, Character Map).

Figure 9.3. Using the Character Map to Find Accented Characters


In addition, the result needs to be padded. English is not the longest language in the world, and often only after the translation has occurred will you discover that your carefully designed forms don't allow enough room for the translated language. German and Welsh are typically significantly longer than English. If you are translating your application for the European market, target German first, in order to identify form design problems in which the translated string needs to be padded. A general rule is that, for text less than 10 characters, the text needs to be padded by an additional 400 percent; for text greater than or equal to 10 characters, the text needs to be padded by an additional 30 percent. You also need to decide whether to pad on the left, on the right, or both. The benefit of padding on both sides is that you can check for screen design problems when your forms have been mirrored (for right-to-left languages).

The form in Figure 9.4 has been translated using the PseudoTranslator class.

Figure 9.4. An Example of a Pseudo Translated Form


You should be able to read all the text on the form and, therefore, know which button to press to add payments.

Choosing a Culture for Pseudo Translation

To use pseudo translation, you must identify a culture that represents the pseudo language. In Chapter 11, "Custom Cultures," I show how you can create your own cultures for various reasons, including supporting a pseudo translation. Creating a custom culture is a good approach in the following circumstances:

  1. You are using Visual Studio 2005 or

  2. You are writing an ASP.NET application or

  3. You are not using resx files for resources.

However, if you are using Visual Studio 2003 and are writing a Windows Forms application based on resx files, any custom culture that you create will not be recognized by Visual Studio 2003. See Chapter 11 for more information.

If you are unable to create a custom culture for pseudo translation, the alternative is to hijack an existing culture. In this approach, you identify a language/country that you do not expect to ever use for its real purpose and hijack it for your own purpose. This requires a certain amount of thought. First, hijacking someone else's culture could potentially offend the people of that culture (assuming that they find out). Second, you want to choose a culture that is as different from your own as possible. It should have a different date/time format, number format, currency, time zone, and as many other globalization differences as possible. So it is with great apologies to the people of Albania that I have chosen Albanian as the culture to hijack. From the Regional and Language Options page (see Figure 9.5), you can see that the Albanian culture is significantly different than that of English.

Figure 9.5. Regional and Language Options Dialog Showing Albanian Culture


The number format is different, the currency symbol is suffixed instead of prefixed, the time suffix is PD instead of AM, and the date separator is "-" instead of "/".

Regardless of whether you create a custom culture or hijack an existing culture, you need a means by which you can communicate your chosen culture to code that needs to know the pseudo culture. The following PseudoTranslation class has a static property that represents a global placeholder for your chosen pseudo translation culture ("sq" is the language code for Albanian):

 public class PseudoTranslation {     private static CultureInfo cultureInfo = new CultureInfo("sq");     public static CultureInfo CultureInfo     {         get {return cultureInfo;}         set {cultureInfo = value;}     } } 


Now a translator class can indicate that it supports translation to the pseudo culture without hard-coding what the pseudo culture is.

The PseudoTranslator Class

The PseudoTranslator class is the least technically sophisticated translator:

 public enum PseudoTranslationPadding {None, Left, Right, Both}; public class PseudoTranslator: Translator {     private static PseudoTranslationPadding padding =         PseudoTranslationPadding.Both;     public PseudoTranslator(): base("Pseudo Translator",         new string[,] {{"*", Internationalization.         Common.PseudoTranslation.CultureInfo.Name}})     {     }     public static PseudoTranslationPadding Padding     {         get {return padding;}         set {padding = value;}     }     public override string Translate(         string inputLanguage, string outputLanguage, string text)     {         if (! IsSupported(inputLanguage, outputLanguage))             throw new LanguageCombinationNotSupportedException(               "Language combination is not supported",               inputLanguage, outputLanguage);         return PseudoTranslate(text);     } } 


The constructor simply calls the translator base class constructor and supplies its name and the array of language pairs that it supports. It supports just one language pair, which translates from "*" (meaning any language) to the pseudo translation language. The PseudoTranslator class has a static Padding property, which indicates whether padding is added on the left, the right, both sides, or not at all. The translate method checks to see that the language translation is supported; if it isn't, it throws an exception. Otherwise, it performs the translation by calling the PseudoTranslate method:

 protected virtual string PseudoTranslate(string text) {     StringBuilder stringBuilder = new StringBuilder("[");     if (padding == PseudoTranslationPadding.Left ||         padding == PseudoTranslationPadding.Both)     {         // add padding on the left         for(int padCount = 0;             padCount < GetPaddingOnOneSideCount(text); padCount++)         {             stringBuilder.Append("!!! ");         }     }     bool previousCharacterIsSlash = false;     foreach(char chr in text)     {         if (previousCharacterIsSlash)             stringBuilder.Append(chr);         else             stringBuilder.Append(ConvertCharacter(chr));         previousCharacterIsSlash = (chr == @"\"[0]);     }     if (padding == PseudoTranslationPadding.Right ||         padding == PseudoTranslationPadding.Both)     {         // add padding on the right         for(int padCount = 0;             padCount < GetPaddingOnOneSideCount(text); padCount++)         {             stringBuilder.Append(" !!!");         }     }     stringBuilder.Append("]");     return stringBuilder.ToString(); } 


It builds the translated text by adding the padding prefix (if any) and converting each character using the ConvertCharacter method and then adding the padding suffix (if any). Notice the references to the previousCharacterIsSlash variable, which is an attempt to preserve control characters embedded in the string. Refer to the section entitled "Embedded Control Characters" in Chapter 8, "Best Practices," for a discussion on the pros and cons of embedding control characters in strings. The PseudoTranslator class can cope with embedded control characters because it performs a translation character by character and can put embedded control characters back into the same relative position that they occupied in the original string. Other translator classes do not have the same luxury and cope with embedded control characters less successfully. (Chapter 13 includes an FxCop rule to catch resource strings with embedded control characters.) The ConvertCharacter method is a straight lookup, replacing character for character:

 protected virtual char ConvertCharacter(char chr) {     switch (chr)     {         case 'A' : return '  ';         case 'B' : return ' ß ';         case 'C' : return '  ';         case 'D' : return '  ';         case 'E' : return '  ';         case 'F' : return ' F ';         case 'G' : return '  ';         case 'H' : return '  ';         case 'I' : return ' Ǐ ';         case 'J' : return '  ';         case 'K' : return '  ';         case 'L' : return '  '; etc. etc. 


Our first translator is complete.




.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