Understanding Translation
Real-time translation requires three steps:
- Find the data to be translated.
- Determine the target language.
- Translate the data.
The following sections describe the particulars of the TranslationControlAdapter implementation.
Determining Translation Data Using Reflection
A basic feature of the TranslationControlAdapter is that, if an adapted control has a Text property, the value assigned to the Text property will be translated. The way that the TranslationControlAdapter determines the adapted control is by referencing the base.Control object. base.Control is the adapted control.
The TranslationControlAdapter determines whether base.Control has a Text property by using Reflection. The TranslationControlAdapter literally inspects each property of the base.Control; if it comes across a Text property, it says, "Ah, this is the value to translate."
Listing 6 shows the code for the TranslationControlAdapter inclusive of the utilization of Reflection.
Listing 6 Using Reflection to inspect an object’s properties.
using System; using System.Text; using System.Web; using System.Web.UI.WebControls; using System.Web.UI.WebControls.Adapters; using System.Reflection; using System.Web.UI; using CogArtTech.Utilities; namespace CogArtTech.Web.ControlAdapters { public class TranslationControlAdapter : WebControlAdapter { protected override void Render(HtmlTextWriter writer) { //Use Reflection to determine if the base.Control has a Text property. PropertyInfo[] pis = base.Control.GetType().GetProperties(); for (int i = 0; i < pis.Length; i++) { PropertyInfo pi = pis[i]; //If the control that is being adapted has a Text property if (pi.Name.ToUpper() == "TEXT") { //Get the value assigned to the Text property. String str = Convert.ToString(pi.GetValue(base.Control, null)); if (str.Length > 0) { try { //Make a Translator object Translator translator = new Translator(); //Pass the Page and the Text property’s value to the Translate method of the //Translator object for translation. str = translator.Translate(base.Control.Page, str); //Reassign the return value from the Translator object to be the //new value for the control’s Text property. pi.SetValue(base.Control, str, null); break; } catch { break; } } } } base.Render(writer); } } }
Determining a Translation Language
Once the TranslationControlAdapter discovers the data to translate, it must determine the language to which the data is to be translated. Translation language is determined in one of two ways:
- If the page in which the adapted control resides has a Culture="a_locale_code" attribute in the @Page directive, the TranslationControlAdapter translates the data to the Page.Culture associated with the Culture attribute’s value (see Listing 7).
- If no Culture attribute is present, the TranslationControlAdapter will determine the translation language to be defined by the browser’s language configuration as indicated by the Page.Request.UserLanguages value, which is a .NET 2.0 encapsulation of the browser’s language setting (see Figure 9).
Listing 7 An @Page directive with the Culture set to Hong Kong Chinese.
<%@ Page Language="C#" AutoEventWireup="true" Culture="zh-HK" CodeBehind="Default.aspx.cs" Inherits="TestApp._Default" %>
Figure 9 Request.UserLanguages is a .NET encapsulation of the browser’s language setting.
In the case where the browser has multiple language settings, only the first language is respected (see Figure 10).
Figure 10 Request.UserLanguages returns a string array of browser language settings.
The TranslationControlAdapter delegates translation processing to a special class that I created for this article. The name of the class is Translator. Private to Translator is a method named GetTranslationMode(). GetTranslationMode() encapsulates the Culture and UserLanguages property inspection and returns a string that’s meaningful to the Translator.Translate() method. The code for GetTranslationMode() is shown in Listing 8.
Listing 8 GetTranslationMode() returns a string code that specifies the language to which to translate.
private string GetTranslationMode() { TranslationKey tkey = new TranslationKey(); if (_Page.Culture.ToUpper().IndexOf("FRENCH") != -1 || _Page.Request.UserLanguages[0].IndexOf("fr-") != -1) return tkey.EnglishToFrench; if (_Page.Culture.ToUpper().IndexOf("GERMAN") != -1 || _Page.Request.UserLanguages[0].IndexOf("de-") != -1) return tkey.EnglishToGerman; if (_Page.Culture.ToUpper().IndexOf("ITALIAN") != -1 || _Page.Request.UserLanguages[0].IndexOf("it-") != -1) return tkey.EnglishToItalian; if (_Page.Culture.ToUpper().IndexOf("SPANISH") != -1 || _Page.Request.UserLanguages[0].IndexOf("es-") != -1) return tkey.EnglishToSpanish; if (_Page.Culture.ToUpper().IndexOf("JAPANESE") != -1 || _Page.Request.UserLanguages[0].IndexOf("jp-") != -1) return tkey.EnglishToJapanese; if (_Page.Culture.ToUpper().IndexOf("PORTUGESE") != -1 || _Page.Request.UserLanguages[0].IndexOf("pt-") != -1) return tkey.EnglishToPortuguese; if (_Page.Culture.ToUpper().IndexOf("KOREAN") != -1 || _Page.Request.UserLanguages[0].IndexOf("ko-") != -1) return tkey.EnglishToKorean; if (_Page.Culture.ToUpper().IndexOf("CHINESE") != -1 || _Page.Request.UserLanguages[0].IndexOf("zh-") != -1) return tkey.EnglishToChineseSimple; return string.Empty; } }
Accessing a Translation Service at Runtime
The class Translator, as introduced earlier, publishes one method that does all the back-end translation work:
Translate(Page ClientPage, string SourceData)
Translator.Translate() does all the work of determining the language to translate to and making the back-end call to BabelFish to do the translation. All Translator.Translate() needs to do its work is a reference to the Page on which the controls reside and the particular data to be translated. For details on Translator.Translate(), see the sample code that accompanies this article.