Click here to Skip to main content
15,896,201 members
Articles / General Programming / Localization

Automatically localizing applications with Google Translate

Rate me:
Please Sign up or sign in to vote.
4.86/5 (15 votes)
21 Aug 2012CPOL4 min read 54.1K   3.4K   43  
Localizing your apps with Google Translate
using System;
using System.IO;
using System.Xml;
using System.Net;
using System.Text;

namespace org.vonburg.UtilityApps.App_Localizer
{
    /// <summary>
    /// Provides mechanisms to read and translate resource files using Google Translate
    /// </summary>
    public class Localizer
    {
        #region Constants
        /// <summary>
        /// The URL to access Google Translater at.
        /// You should append sourcelang/destlanguage/phrase
        /// e.g. "http://www.google.com/translate_t?langpair=en|es&text=Hello, world!"
        /// </summary>
        private const string c_GoogleTranslateUrl = "http://www.google.com/translate_t?langpair=";

        #endregion

        #region Constructor

        /// <summary>
        /// Creates a new instance of the Localizer object
        /// </summary>
        public Localizer()
        {
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Iterates through the .resx file and tranlates all entries for text properties
        /// </summary>
        /// <param name="resourceFilePath"></param>
        /// <param name="sourceLanguageCode"></param>
        /// <param name="outputLanguageCode"></param>
        /// <param name="TextPropertiesOnly">True if only text properties (items where the name ends with .text) should be translated</param>
        private void translateRESX(string resourceFilePath, string sourceLanguageCode, string outputLanguageCode, bool TextPropertiesOnly)
        {
            //variables
            XmlDocument doc = null;

            try
            {
                //open the document
                doc = new XmlDocument();
                doc.Load(resourceFilePath);
            }
            catch (Exception err)
            {
                throw new Exception("Failed to load the resource file.\r\n" + err.Message);
            }

            //get all of the data elements
            XmlNodeList nodes = doc.SelectNodes("/root/data");
            
            //loop through each node and translate the text value
            for (int i = 0; nodes.Count > i; i++)
            {
                XmlNode node = nodes[i];
                //filter out anything that has a type (as it is not a string) 
                XmlAttribute typeAtt = node.Attributes["type"];
                if (typeAtt == null)
                {
                    //If the TextPropertiesOnly is true, filter out any nodes where the name doesn't contain .Text
                    XmlAttribute nameAtt = node.Attributes["name"];

                    if (TextPropertiesOnly)
                    {
                        //get only the nodes where the name ends with .text
                        if (nameAtt != null && nameAtt.InnerText.EndsWith(".Text"))
                        {
                            //get the value node
                            XmlNode valueNode = node.SelectSingleNode("value");
                            if (valueNode != null)
                            {
                                string text = valueNode.InnerText;
                                if (text != null && text != "")
                                {
                                    string newText = this.translatePhrase(text, sourceLanguageCode, outputLanguageCode);
                                    valueNode.InnerText = newText;
                                }
                            }
                        }
                    }
                    else //get all nodes
                    {
                        //get the value node
                        XmlNode valueNode = node.SelectSingleNode("value");
                        if (valueNode != null)
                        {
                            string text = valueNode.InnerText;
                            if (text != null && text != "")
                            {
                                string newText = this.translatePhrase(text, sourceLanguageCode, outputLanguageCode);
                                valueNode.InnerText = newText;
                            }
                        }
                    }
                }
            }

            //save the file
            doc.Save(resourceFilePath);            
        }

        /// <summary>
        /// Iterates through the supplied .propeties file and translates all entries
        /// </summary>
        /// <param name="resourceFilePath"></param>
        /// <param name="sourceLanguageCode"></param>
        /// <param name="outputLanguageCode"></param>
        private void translateProperties(string resourceFilePath, string sourceLanguageCode, string outputLanguageCode)
        {
            try
            {                
                //Read the file line by line                
                StringBuilder sb = new StringBuilder();
                using (StreamReader reader = new StreamReader(resourceFilePath))
                {
                    string line;                
                    while ((line = reader.ReadLine()) != null)
                    {
                        //if the line has an = in it, get the name and values
                        if (line.Contains("="))
                        {
                            string[] sLine = line.Split('=');
                            string name = sLine[0];
                            string value = sLine[1];

                            if (value != null && !value.Equals(""))
                            {
                                //translate the phrase
                                value = this.translatePhrase(value.Trim(), sourceLanguageCode, outputLanguageCode);

                                //write the new value
                                sb.AppendLine(name + "=" + value);

                            }
                            else
                            {
                                //write blank lines
                                sb.AppendLine(line);
                            }
                        }
                        else
                        {
                            //write non setting lines
                            sb.AppendLine(line);
                        }
                    
                    }

                    //close the file
                    reader.Close();
                    reader.Dispose();
                }

                //write the new updated file
                using (StreamWriter writer = new StreamWriter(resourceFilePath, false))
                {
                    //write the entire file
                    writer.Write(sb.ToString());

                    //flush and close the file
                    writer.Flush();
                    writer.Close();
                    writer.Dispose();                    
                }

            }
            catch (Exception err)
            {
                throw new Exception("An error occured reading or writing to the properties file.\r\n" + err.Message);
            }
        }

        /// <summary>
        /// Calls out to Google translate to translate the supplied phrase
        /// </summary>
        /// <param name="phrase"></param>
        /// <param name="sourceLangCode"></param>
        /// <param name="destLangCode"></param>
        /// <returns></returns>
        private string translatePhrase(string phrase, string sourceLangCode, string destLangCode)
        {
            string translatedText = null;

            try
            {
                //create the web client
                WebClient client = new WebClient();

                //Open the page and get the results
                string url = c_GoogleTranslateUrl + sourceLangCode + "|" + destLangCode + "&text=" + phrase;
                string sPage = client.DownloadString(url);

                // Parse as the page as a string
                //  Page can have bad HTML causing problems if you try to parse as xml
                //  Find the span with the title of the original string
                int tagStart = sPage.IndexOf("<span title=\"" + phrase + "\"");
                int tagEnd = sPage.IndexOf("</span>", tagStart);
                string resultsTag = sPage.Substring(tagStart, (tagEnd - tagStart));
                //get rid of the start tag
                resultsTag = resultsTag.Substring(resultsTag.IndexOf(">") + 1);

                //You now have the translated text
                translatedText = resultsTag.Trim();                


                //dispose of the web client
                client.Dispose();
            }
            catch(Exception err)
            {
                throw new Exception("Failed to download results from Google Translator.\r\n" + err.Message);
            }

            return translatedText;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Creates a copy of the resource file, and then translates it phrase by phrase.
        /// </summary>
        /// <param name="sourceResourceFilePath"></param>
        /// <param name="outputResourceFilePath"></param>
        /// <param name="sourceLanguageCode"></param>
        /// <param name="outputLanguageCode"></param>
        /// <param name="TextPropertiesOnly">True if only text properties (items where the name ends with .text) should be translated</param>
        public void translateFile(string sourceResourceFilePath, string outputResourceFilePath, string sourceLanguageCode, string outputLanguageCode, bool TextPropertiesOnly)
        {
            try
            {
                //create the new output file
                File.Copy(sourceResourceFilePath, outputResourceFilePath, true);
            }
            catch (Exception err)
            {
                throw new Exception("Failed to create output file.\r\n" + err.Message);
            }

            //determine the file type
            string extension = Path.GetExtension(sourceResourceFilePath);
            if (extension.ToLower().Equals(".resx"))
            {
                this.translateRESX(outputResourceFilePath, sourceLanguageCode, outputLanguageCode, TextPropertiesOnly);

                //exit
                return;
            }
            if (extension.ToLower().Equals(".properties"))
            {
                this.translateProperties(outputResourceFilePath, sourceLanguageCode, outputLanguageCode);
                
                //exit
                return;
            }

            //if we made it this far, throw an expcetion as this is not a file extension we recognize
            throw new Exception("Unable to translate the supplied source resource file. Make sure your source file has either a .resx or .properties extension");
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions