Views: 3176
Number of votes: 3
Average rating:

Itera.Translate a Web Control/BaseUserControl that translate key phrases

I like EPiServer a lot, but one of the areas I think need some work is the handling of translation of key strings. Or more précises how too easy add text that can be translated or changed by editors.   I have started on a module that can handle some of these issues.

The concept is simple. All text within  {{text}} will be added to a dynamic data store table, where it’s possible to specify new text. Either change the text, or make a translation. The original text is uses as the key, so different areas that use the same key will share the translations. The data store class looks like this:

Code Snippet
  1. public class TranslateStore : IDynamicData
  2. {
  3.     public EPiServer.Data.Identity Id { get; set; }
  4.     [EPiServerDataIndex]
  5.     public string Key { get; set; }
  6.     public string EN { get; set; }
  7.     public string NO { get; set; }
  8.  
  9.     public string GetText()
  10.     {
  11.         var lang = Thread.CurrentThread.CurrentUICulture.IetfLanguageTag;
  12.        
  13.         if (lang == "no" && !string.IsNullOrEmpty(NO))
  14.             return NO;
  15.         if (lang == "en" && !string.IsNullOrEmpty(EN))
  16.             return EN;
  17.         return Key;
  18.     }
  19.     
  20.     public static TranslateStore Find(string key)
  21.     {
  22.       
  23.         var q = (from item in Items where item.Key == key select item).ToList();
  24.         if (q != null && q.Count > 0)
  25.             return q[0];
  26.         var newItem = new TranslateStore();
  27.         newItem.Key = key;
  28.         Store.Save(newItem);
  29.         return newItem;
  30.     }
  31.    
  32.     public static IOrderedQueryable<TranslateStore> Items
  33.     {
  34.         get
  35.         {
  36.             return Store.Items<TranslateStore>();
  37.         }
  38.     }
  39.  
  40.     public static TranslateStore Load(EPiServer.Data.Identity id)
  41.     {
  42.         return Store.Load<TranslateStore>(id);
  43.     }
  44.     public static DynamicDataStore Store
  45.     {
  46.         get
  47.         {
  48.             return DynamicDataStoreFactory.Instance.GetStore(typeof(TranslateStore));
  49.         }
  50.     }
  51. }
The code can either be used by inherit from a user control class, or as a web Control.

Inside the Render method I do

Code Snippet
  1. protected override void Render(HtmlTextWriter writer)
  2. {
  3.     var page = this.Page as PageBase;
  4.     StringBuilder sb = new StringBuilder();
  5.     StringWriter sw = new StringWriter(sb);
  6.     HtmlTextWriter htw = new HtmlTextWriter(sw);
  7.     base.Render(htw);
  8.     try
  9.     {
  10.         writer.Write(inner.TranslateText(sb, page, this.ClientID, DisplayName));
  11.     }
  12.     catch (System.Exception error)
  13.     {
  14.         base.Render(writer);
  15.         writer.Write(error.Message);
  16.     }
  17.    
  18. }

and the replacement is done by

Code Snippet
  1.   publicStringBuilder TranslateText(StringBuilder sb, PageBase page, string id, string displayName)
  2. {
  3.     var result = new StringBuilder();
  4.     try
  5.     {
  6.  
  7.         var start = DateTime.Now;
  8.         string content = sb.ToString();
  9.         var matches = FindMatches(content);
  10.         var start2 = DateTime.Now;
  11.         TranslateStore data = null;
  12.         int startIndex = 0;
  13.         foreach (var match in matches)
  14.         {
  15.             result.Append(content.Substring(startIndex, match.Index - startIndex));
  16.             string key = match.Value.Substring(2, match.Value.Length - 4);
  17.             if (!keys.ContainsKey(key.ToLower()))
  18.             {
  19.                 data = TranslateStore.Find(key);
  20.                 keys.Add(key.ToLower(), data);
  21.             }
  22.             else
  23.                 data = keys[key.ToLower()];
  24.             result.Append(data.GetText());
  25.             startIndex = match.Index + match.Length;
  26.         }
  27.         result.Append(content.Substring(startIndex));
  28.  
  29.  
  30.         if (HttpContext.Current.Items["TranslateMenu"] != null && HttpContext.Current.Request["translate"] != null && HttpContext.Current.Request["translate"]=="true")
  31.         {
  32.             var debug = new StringBuilder();
  33.             debug.AppendLine("Found matches:" + ((TimeSpan)(start2 - start)).TotalMilliseconds + "ms<br />");
  34.  
  35.             debug.AppendLine("replaced matches:" + ((TimeSpan)(DateTime.Now - start2)).TotalMilliseconds + "ms<br />");
  36.  
  37.             result.Append(EditMode(page, debug, displayName + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tot time:" + ((TimeSpan)(DateTime.Now - start)).TotalMilliseconds + "ms", id));
  38.         }
  39.         if (HttpContext.Current.Items["TranslateMenu"] != null && HttpContext.Current.Request["translate"] != null && HttpContext.Current.Request["translate"] == "all" && first)
  40.         {
  41.             var debug = new StringBuilder();
  42.             var query = from item in TranslateStore.Items select item;
  43.  
  44.             var allKeys =new Dictionary<string, TranslateStore>();
  45.             foreach (var item in query)
  46.                 allKeys.Add(item.Key, item);
  47.             result.Append(EditMode(page, debug, "ALL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tot time:" + ((TimeSpan)(DateTime.Now - start)).TotalMilliseconds + "ms", id, allKeys,true));
  48.         }
  49.  
  50.     }
  51.     catch (System.Exception error)
  52.     {
  53.  
  54.         result.Append(error.Message + error.StackTrace);
  55.  
  56.     }
  57.     return result;
  58. }

 

I’m also adding a context menu so this html code:

image

will appear like this:

image

and if I select Translate

image

this blue dragable div will lay it self over the text.

If you select Translate – all one blue box will appear with all the elements in the dynamic data store table displayed.

Use

Web Control

just add this line in the web.config pages/controls section

Code Snippet
  1. <add tagPrefix="Itera" namespace="Itera.WebControls" assembly="Itera.Translate" />

Then you can easy translate text like this

Code Snippet
  1. <Itera:Translate ID="Translate1" runat="server" DisplayName="MasterPage" >
  2.         <a href="#nonav1" class="hiddenTxt">{{G&aring; direkte til navigasjon}}</a>
  3.         <a href="#nonav2" class="hiddenTxt">{{G&aring; direkte til hovedinnhold}}</a>
  4.         <a href="#nonav3" class="hiddenTxt">{{G&aring; direkte til kontaktinfo}}</a>
  5. </Itera:Translate>

User Control

Just inherit from TranslateUserControl instead of UserControlBase and add the following element in the page directives

Code Snippet
  1. <%@ Control Language="C#" TranslateElements="true"

then you can either change text using {{}} like this

image

or from the code behind

Code Snippet
  1. var format = TranslateText("Denne saken har {0} kommentar(er)");

Code is in the code section here it’s compiled with CMS 6 R2, but it will work if you recompile it and remove the new the Data Store attributes.

May 02, 2011

Please login to comment.