Introduction
This article describes, how you can write multilingual web pages in an easy way, without using resources or localizations.
This article doesn't describe how you can translate a word or sentence from any language to another!
Background
I am developing a big web application in the company I work for and the application should be multilingual.
In the complete project, we have a COM-component that translates words or sentences from any language to another. The basic mechanism of this component is a big text file and a hashlist.
I my example project, there exists an instance of a translation class with example translations. In real life, this is the instance of the translation-COM-component! Here you should write your own solution!
The base and default language in my example project is German. I use a session-variable to store the actual language over the session, and global for the complete web application. The switch-language-dropdownlist can be placed in a menuframe. Server side code should only refresh all frames to switch language on the fly.
Using the code
First step is to take the class CMLPageControl
into your project. Copy the file CMLPageControl.vb in the project directory, and add the following lines to the vbproj-file.
<File
RelPath = "CMLPageControl.vb"
SubType = "ASPXCodeBehind"
BuildAction = "Compile"
/>
Second:
All your WebForms must be derived from this class:
Public Class WebForm1
Inherits CMLPageControl
End Class
Third and last:
To translate texts, you should put between the translation tags <ML_TAG>
and </ML_TAG>
.
<asp:Label id="Label1" runat="server">
<ML_TAG>Hallo, hier wird demonstriert</ML_TAG>
</asp:Label>
<asp:Label id="Label2" font-bold="True" runat="server">
<ML_TAG>wie man on the fly die Sprache wechselt!</ML_TAG>
</asp:Label>
<asp:Button id="Button1" runat="server" Text="<ML_TAG>Dr�ck mich</ML_TAG>">
</asp:Button>
<asp:CheckBox id="CheckBox1" runat="server"
Text="<ML_TAG>Klick mich</ML_TAG>">
</asp:CheckBox>
The translation-tag is defined as a constant in the base class.
Imports System.ComponentModel
Imports System.Web.UI
<DefaultProperty("Text"), ToolboxData("<{0}:CMLPageControl _
runat="server"></{0}:CMLPageControl>")> _
Public Class CMLPageControl _
Inherits System.Web.UI.Page
Public Const MLPAGE_TRANSLATION_TAG As String = "ML_TAG"
End Class
The solution
The base class is a custom control to overload the Render
method.
One problem is to agree the ready rendered HTML-code of the page including all sub user controls and placeholders and so on. I solved this problem while I creating my own HtmlTextWriter
-Object and let the base class System.Web.UI.Page
render the page in my writer. Now, I can get the HTML as string to translate all texts between the translation tags.
Protected Overrides Sub Render(ByVal output As System.Web.UI.HtmlTextWriter)
Dim oStringBuilder As New System.Text.StringBuilder
Dim oWriter As New System.Web.UI.HtmlTextWriter(New _
System.IO.StringWriter(oStringBuilder))
RenderChildren(oWriter)
Second problem was that the Render
-methods of all .NET controls replace the brakes <
and >
from the translation-tags by <
and >
, if the text is set in code behind instead of the static presentation tier (aspx- or ascx-file). Example:
List1.Items.Add(New ListItem("<ML_TAG>Deutsch</ML_TAG>", _
Convert.ToString(CTranslation.MLPAGE_LANGUAGE_GERMAN)))
List1.Items.Add(New ListItem("<ML_TAG>Englisch</ML_TAG>", _
Convert.ToString(CTranslation.MLPAGE_LANGUAGE_ENGLISH)))
To solve this, the translation routine is called twice. First to find all "normal" translation tags <ML_TAG>
, second to find all modified translation tags <ML_TAG>
.
output.Write(TranslatePage(TranslatePage(oStringBuilder.ToString(), _
MLPAGE_TRANSLATION_TAG, True), MLPAGE_TRANSLATION_TAG, False))
The translation itself is a very simple search and replace. I think here is a great tuning potential. But in my real customer application, the translation of page with 200-300KB rendered HTML-code needs a duration of < 0.1 seconds. Most of the time is needed to find the text in the translation-component. The data behind this a 2MB text file.
Points of Interest
If you make mistakes while using the translation-tags (i.e., forget closing-tag or syntax error), the translation parser shows you the point of the mistake.
In the next screenshot, a start tag has a writing error:
<asp:Label id="Label1" runat="server">
<ML_xTAG>Hallo, hier wird demonstriert</ML_TAG>
</asp:Label><br>
History
Initial version.