Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Add Multiple Language Support to Your Unity Projects

Discussion in 'Scripting' started by Tryder, Oct 21, 2013.

  1. Tryder

    Tryder

    Joined:
    Mar 26, 2012
    Posts:
    89
    After writing a couple of Android applications I thought it would be nice if one could implement support for multiple languages in their Unity projects as easily as in an Android project. I had this idea a few months ago and finally got around to writing it.

    With Unity Multiple Language Support you can easily include multi-lingual support in your Unity projects through XML. Simply create one or more XML files with the strings that have multiple translations and then reference those strings in your scripts with a common identifier. XML format is as follows:

    Code (csharp):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <languages>
    3.     <English>
    4.          <string name="app_name">Some Game</string>
    5.          <string name="score_text">Score: </string>
    6.     </English>
    7.  
    8.     <French>
    9.         <string name="app_name">Certains Jeux</string>
    10.         <string name="score_text">Score: </string>
    11.     </French>
    12.  
    13.     <German>
    14.         <string name="app_name">Einige Spiele</string>
    15.         <string name="score_text">Ergebnis: </string>
    16.     </German>
    17. </languages>
    Once the Lang Class has been initialized to a particular language you can reference the strings stored in your XML file as follows:

    Code (csharp):
    1. var scoreText : String = langClass.getString("score_text") + newScore.ToString();
    Furthermore you can reset the language on the fly with the following line:

    Code (csharp):
    1. langClass.setLanguage(Path.Combine(Application.dataPath, "lang.xml"), "French");
    The text stored in your XML resource is read as a string so any rich text formatting will remain intact, but you'll need to read up on how to format the XML file for special characters. For the most part characters such as quotes and carats need an escape character.

    The main difference between this implementation and Android's is that Android requires each language to have it's own separate XML file while UMLS leaves it up to the developer to decide whether to throw it all into one XML file or split it up into multiple files. For smaller games a single XML file should do just fine, but since all strings from the selected language are stored in RAM larger games might find it useful to use multiple XML resources such as LVL_01.xml, LVL_02.xml, etcetera. RPGs could even split their resources per conversation such as Adam_01.xml and Jenny_07.xml.

    Feel free to grab Unity Multiple Language Support off of my Google Drive for free:
    https://docs.google.com/file/d/0B6BscJ4Cq-K7WjhTM1B1N1FWSDA/edit?usp=sharing

    P.S. Google Drive opens the zip file so you can download individual items. To download the whole zip file just select File --> Download.

    P.P.S. UMLS provides support for XML resources stored on the local system and resources stored over the web, however; I have not tested UMLS with web based resources so feel free to contact me if you're having trouble.
     
    Last edited: Oct 22, 2013
  2. rattlesnake

    rattlesnake

    Joined:
    Jul 18, 2013
    Posts:
    138
    Thank youuuuu so muuuch ! it's awesome :D
     
  3. rattlesnake

    rattlesnake

    Joined:
    Jul 18, 2013
    Posts:
    138
    Ammmm I have an error :/

    Could you please help me ?

    Lang.js(55,27): BCE0018: The name 'XmlDocument' does not denote a valid type ('not found').

    Edit : By the way I'm in API compatibility Level .net 2.0 (with no subset) into the player settings.
    Maybe this cause the problem ?
     
    Last edited: Nov 25, 2013
  4. Tryder

    Tryder

    Joined:
    Mar 26, 2012
    Posts:
    89
    Hmm. I'm taking a look at msdn.microsoft.com and it indicates that the XmlDocument class is supported as far back as .net 1.0. Check out http://msdn.microsoft.com/en-us/library/system.xml.xmldocument%28v=vs.110%29.aspx for more information about the XmlDocument class.

    I'm noticing in the error that you're receiving it states that it doesn't recognize the XmlDocument type and then references line 55, I've pulled up my script and UniSciTE indicates that the first reference to the XmlDocument type is on line 42 and no reference is made on line 55. Did you modify the script at all? If so make sure you still have the following line at the top:

    Code (csharp):
    1. import System.Xml;
     
  5. shivansps

    shivansps

    Joined:
    Feb 26, 2014
    Posts:
    60
    This is to load it from resources folder directly, there seems to be no other way of using local storage outside of the editor.

    Code (JavaScript):
    1.     var xmlLang : TextAsset  = Resources.Load("lang") as TextAsset;
    2.     langClass = new Lang(xmlLang.text, currentLang, true);
    And to change it
    Code (JavaScript):
    1.         var xmlLang: TextAsset  = Resources.Load("lang") as TextAsset;
    2.         langClass.setLanguageWeb(xmlLang.text, currentLang);
     
  6. rodv27

    rodv27

    Joined:
    Nov 17, 2013
    Posts:
    9
    Is there a Csharp version of this?
     
  7. NareshKhandla

    NareshKhandla

    Joined:
    Aug 6, 2013
    Posts:
    28
    I want to write Gujarati language , please tell me how to do this. Thank you!.
     
  8. sGlorz

    sGlorz

    Joined:
    Dec 4, 2013
    Posts:
    20
    Hi, here is the C# version:

    Lang.cs

    Code (CSharp):
    1. /*
    2. The Lang Class adds easy to use multiple language support to any Unity project by parsing an XML file
    3. containing numerous strings translated into any languages of your choice.  Refer to UMLS_Help.html and lang.xml
    4. for more information.
    5.  
    6. Created by Adam T. Ryder
    7. C# version by O. Glorieux
    8.  
    9. */
    10.  
    11. using System;
    12. using System.Collections;
    13. using System.IO;
    14. using System.Xml;
    15.  
    16. using UnityEngine;
    17.  
    18. public class Lang
    19. {
    20.     private Hashtable Strings;
    21.  
    22.     /*
    23.     Initialize Lang class
    24.     path = path to XML resource example:  Path.Combine(Application.dataPath, "lang.xml")
    25.     language = language to use example:  "English"
    26.     web = boolean indicating if resource is local or on-line example:  true if on-line, false if local
    27.  
    28.     NOTE:
    29.     If XML resource is on-line rather than local do not supply the path to the path variable as stated above
    30.     instead use the WWW class to download the resource and then supply the resource.text to this initializer
    31.  
    32.     Web Example:
    33.     var wwwXML : WWW = new WWW("http://www.exampleURL.com/lang.xml");
    34.     yield wwwXML;
    35.      
    36.     var LangClass : Lang = new Lang(wwwXML.text, currentLang, true)
    37.     */
    38.     public Lang ( string path, string language, bool web) {
    39.         if (!web) {
    40.             setLanguage(path, language);
    41.         } else {
    42.             setLanguageWeb(path, language);
    43.         }
    44.     }
    45.  
    46.     /*
    47.     Use the setLanguage function to swap languages after the Lang class has been initialized.
    48.     This function is called automatically when the Lang class is initialized.
    49.     path = path to XML resource example:  Path.Combine(Application.dataPath, "lang.xml")
    50.     language = language to use example:  "English"
    51.  
    52.     NOTE:
    53.     If the XML resource is stored on the web rather than on the local system use the
    54.     setLanguageWeb function
    55.     */
    56.     public void setLanguage ( string path, string language) {
    57.         var xml = new XmlDocument();
    58.         xml.Load(path);
    59.      
    60.         Strings = new Hashtable();
    61.         var element = xml.DocumentElement[language];
    62.         if (element != null) {
    63.             var elemEnum = element.GetEnumerator();
    64.             while (elemEnum.MoveNext()) {
    65.                 var xmlItem = (XmlElement)elemEnum.Current;
    66.                 Strings.Add(xmlItem.GetAttribute("name"), xmlItem.InnerText);
    67.             }
    68.         } else {
    69.             Debug.LogError("The specified language does not exist: " + language);
    70.         }
    71.     }
    72.  
    73.     /*
    74.     Use the setLanguageWeb function to swap languages after the Lang class has been initialized
    75.     and the XML resource is stored on the web rather than locally.  This function is called automatically
    76.     when the Lang class is initialized.
    77.     xmlText = String containing all XML nodes
    78.     language = language to use example:  "English"
    79.  
    80.     Example:
    81.     var wwwXML : WWW = new WWW("http://www.exampleURL.com/lang.xml");
    82.     yield wwwXML;
    83.      
    84.     var LangClass : Lang = new Lang(wwwXML.text, currentLang)
    85.     */
    86.     public void setLanguageWeb ( string xmlText, string language) {
    87.         var xml = new XmlDocument();
    88.         xml.Load(new StringReader(xmlText));
    89.      
    90.         Strings = new Hashtable();
    91.         var element = xml.DocumentElement[language];
    92.         if (element != null) {
    93.             var elemEnum = element.GetEnumerator();
    94.             while (elemEnum.MoveNext()) {
    95.                 var xmlItem = (XmlElement)elemEnum.Current;
    96.                 Strings.Add(xmlItem.GetAttribute("name"), xmlItem.InnerText);
    97.             }
    98.         } else {
    99.             Debug.LogError("The specified language does not exist: " + language);
    100.         }
    101.     }
    102.  
    103.     /*
    104.     Access strings in the currently selected language by supplying this getString function with
    105.     the name identifier for the string used in the XML resource.
    106.  
    107.     Example:
    108.     XML file:
    109.     <languages>
    110.         <English>
    111.             <string name="app_name">Unity Multiple Language Support</string>
    112.             <string name="description">This script provides convenient multiple language support.</string>
    113.         </English>
    114.         <French>
    115.             <string name="app_name">Unité Langue Soutien Multiple</string>
    116.             <string name="description">Ce script fournit un soutien multilingue pratique.</string>
    117.         </French>
    118.     </languages>
    119.  
    120.     JavaScript:
    121.     var appName : String = langClass.getString("app_name");
    122.     */
    123.     public string getString (string name) {
    124.         if (!Strings.ContainsKey(name)) {
    125.             Debug.LogError("The specified string does not exist: " + name);
    126.          
    127.             return "";
    128.         }
    129.  
    130.         return (string)Strings[name];
    131.     }
    132.  
    133. }
    TestGui.cs

    Code (CSharp):
    1. /*
    2. This example script demonstrates how to use the Unity Multiple Language Support Lang class in a simple GUI.
    3. The accompanying lang.xml file should be placed into your project's Assests folder.
    4.  
    5. -Adam T. Ryder
    6. C# version by O. Glorieux
    7. */
    8.  
    9. using System.IO;
    10. using UnityEditor;
    11.  
    12. using UnityEngine;
    13.  
    14. public class NewMonoBehaviour : Editor
    15. {
    16.  
    17.     private Lang LMan;
    18.     private string currentLang = "English";
    19.  
    20.     public void OnEnable()
    21.     {
    22.         /*
    23.     Initialize the Lang class by providing a path to the desired language XML file, a default language
    24.     and a boolean to indicate if we are operating on an XML file located from a downloaded resource or local.
    25.     True if XML resource is on the web, false if local
    26.  
    27.     If initializing from a web based XML resource you'll need to supply the text of the downloaded resource in placed
    28.     of the path.
    29.  
    30.     web example:
    31.     var wwwXML : WWW = new WWW("http://www.exampleURL.com/lang.xml");
    32.     yield wwwXML;
    33.      
    34.     LMan = new Lang(wwwXML.text, currentLang, true);
    35.     */
    36.         LMan = new Lang(Path.Combine(Application.dataPath, "lang.xml"), currentLang, false);
    37.     }
    38.  
    39.     public void OnGUI()
    40.     {
    41.         /*
    42.     To access a string in the currently set language use the Lang class' getString function with the string name identifier supplied to it.
    43.     */
    44.         GUI.Label(new Rect(0, 0, 800, 450), LMan.getString("app_name") + "\n" + LMan.getString("description"));
    45.  
    46.         if (GUI.Button(new Rect(0, 450 - 24, 800, 24), "Language:  " + currentLang))
    47.         {
    48.             if (currentLang == "English")
    49.             {
    50.                 currentLang = "French";
    51.             }
    52.             else if (currentLang == "French")
    53.             {
    54.                 currentLang = "German";
    55.             }
    56.             else
    57.             {
    58.                 currentLang = "English";
    59.             }
    60.  
    61.             /*
    62.         To switch languages after the Lang class has been initialized call the setLanguage function
    63.         and provide a path to the desired XML resource and the desired language.
    64.      
    65.         If the XML resource is located on the web you'll need to use the WWW class to download the resource
    66.         and then supply the text of the downloaded resource in place of the path to the Lang class' setLanguageWeb function.
    67.      
    68.         web example:
    69.         var wwwXML : WWW = new WWW("http://www.exampleURL.com/lang.xml");
    70.         yield wwwXML;
    71.      
    72.         LMan.setLanguageWeb(wwwXML.text, currentLang);
    73.         */
    74.             LMan.setLanguage(Path.Combine(Application.dataPath, "lang.xml"), currentLang);
    75.         }
    76.     }
    77. }
    78.  
     
  9. shivansps

    shivansps

    Joined:
    Feb 26, 2014
    Posts:
    60
    I just wanted to share the script im using with the new UI system in order to handle static text elements.

    Code (JavaScript):
    1. #pragma strict
    2. private var Stats : GameStatics;
    3. private var Init = false;
    4. private var code : String;
    5. private var text : UI.Text;
    6.  
    7. function Start ()
    8. {
    9.     var cam=GameObject.Find("MainCamera");
    10.     Stats=cam.GetComponent(GameStatics); //The script where the langclass is
    11.  
    12.     text=this.transform.GetComponent(UI.Text);
    13.     code=text.text;
    14.  
    15.     Init=true;
    16. }
    17.  
    18. function Update ()
    19. {
    20.     if(Init) UpdateLang();
    21. }
    22.  
    23. public function UpdateLang ()
    24. {
    25.     text.text=Stats.langClass.getString(code);
    26.     Init=false;
    27. }
    just attach it to the text element.
    BTW, there is not really a need to store the component in a variable, that just better for in-game lang changes, but
    Code (JavaScript):
    1. public function UpdateLang ()
    2. {
    3.     text.text=GameObject.Find("MainCamera").GetComponent(GameStatics).langClass.getString(code);
    4.   Init=false;
    5. }
    should work just fine as well
     
    Last edited: Jan 21, 2015
  10. shivansps

    shivansps

    Joined:
    Feb 26, 2014
    Posts:
    60
    Does not work on WebGL, ive not really when into finding out why.

    Code (JavaScript):
    1. Strings.Add(elemEnum.Current.GetAttribute("name"), elemEnum.Current.InnerText);
    looks like "GetAttribute" and "InnerText" are not implemented.
     
  11. shivansps

    shivansps

    Joined:
    Feb 26, 2014
    Posts:
    60
    Thanks to jonas echterhoff that helped me, i was able to fix this in order to work in WebGL platform.

    Code (JavaScript):
    1. #pragma strict
    2. /*
    3. The Lang Class adds easy to use multiple language support to any Unity project by parsing an XML file
    4. containing numerous strings translated into any languages of your choice.  Refer to UMLS_Help.html and lang.xml
    5. for more information.
    6.  
    7. Created by Adam T. Ryder
    8.  
    9. 10/3/2015 (unofficial by shivansps)
    10. Fixed for WebGL
    11. */
    12.  
    13. import System.Xml;
    14.  
    15. public class Lang
    16. {
    17.     private var Strings : Hashtable;
    18.    
    19.     /*
    20.     Initialize Lang class
    21.     path = path to XML resource example:  Path.Combine(Application.dataPath, "lang.xml")
    22.     language = language to use example:  "English"
    23.     web = boolean indicating if resource is local or on-line example:  true if on-line, false if local
    24.    
    25.     NOTE:
    26.     If XML resource is on-line rather than local do not supply the path to the path variable as stated above
    27.     instead use the WWW class to download the resource and then supply the resource.text to this initializer
    28.    
    29.     Web Example:
    30.     var wwwXML : WWW = new WWW("http://www.exampleURL.com/lang.xml");
    31.     yield wwwXML;
    32.        
    33.     var LangClass : Lang = new Lang(wwwXML.text, currentLang, true)
    34.     */
    35.     function Lang ( path : String, language : String, web : boolean ) {
    36.         if (!web) {
    37.             setLanguage(path, language);
    38.         } else {
    39.             setLanguageWeb(path, language);
    40.         }
    41.     }
    42.    
    43.     /*
    44.     Use the setLanguage function to swap languages after the Lang class has been initialized.
    45.     This function is called automatically when the Lang class is initialized.
    46.     path = path to XML resource example:  Path.Combine(Application.dataPath, "lang.xml")
    47.     language = language to use example:  "English"
    48.    
    49.     NOTE:
    50.     If the XML resource is stored on the web rather than on the local system use the
    51.     setLanguageWeb function
    52.     */
    53.     public function setLanguage ( path : String, language : String) {
    54.         var xml : XmlDocument = new XmlDocument();
    55.         xml.Load(path);
    56.        
    57.         Strings = new Hashtable();
    58.         var element : XmlElement = xml.DocumentElement.Item[language];
    59.         if (element) {
    60.             var elemEnum : IEnumerator = element.GetEnumerator();
    61.             while (elemEnum.MoveNext()) {
    62.                 Strings.Add((elemEnum.Current as XmlElement).GetAttribute("name"), (elemEnum.Current as XmlElement).InnerText);
    63.             }
    64.         } else {
    65.             Debug.LogError("The specified language does not exist: " + language);
    66.         }
    67.     }
    68.    
    69.     /*
    70.     Use the setLanguageWeb function to swap languages after the Lang class has been initialized
    71.     and the XML resource is stored on the web rather than locally.  This function is called automatically
    72.     when the Lang class is initialized.
    73.     xmlText = String containing all XML nodes
    74.     language = language to use example:  "English"
    75.    
    76.     Example:
    77.     var wwwXML : WWW = new WWW("http://www.exampleURL.com/lang.xml");
    78.     yield wwwXML;
    79.        
    80.     var LangClass : Lang = new Lang(wwwXML.text, currentLang)
    81.    
    82.     ADDED: 10/3/2015 (unofficial by shivansps)
    83.     setLanguageWeb can also be used to load the xml file directly from the resources folder
    84.    
    85.     Example:
    86.     var xmlLang: TextAsset  = Resources.Load("lang") as TextAsset;
    87.     langClass.setLanguageWeb(xmlLang.text, currentLang);
    88.     */
    89.     public function setLanguageWeb ( xmlText : String, language : String) {
    90.         var xml : XmlDocument = new XmlDocument();
    91.         xml.Load(new StringReader(xmlText));
    92.        
    93.         Strings = new Hashtable();
    94.         var element : XmlElement = xml.DocumentElement.Item[language];
    95.         if (element) {
    96.             var elemEnum : IEnumerator = element.GetEnumerator();
    97.             while (elemEnum.MoveNext()) {
    98.                 Strings.Add((elemEnum.Current as XmlElement).GetAttribute("name"), (elemEnum.Current as XmlElement).InnerText);
    99.             }
    100.         } else {
    101.             Debug.LogError("The specified language does not exist: " + language);
    102.         }
    103.     }
    104.    
    105.     /*
    106.     Access strings in the currently selected language by supplying this getString function with
    107.     the name identifier for the string used in the XML resource.
    108.    
    109.     Example:
    110.     XML file:
    111.     <languages>
    112.         <English>
    113.             <string name="app_name">Unity Multiple Language Support</string>
    114.             <string name="description">This script provides convenient multiple language support.</string>
    115.         </English>
    116.         <French>
    117.             <string name="app_name">Unité Langue Soutien Multiple</string>
    118.             <string name="description">Ce script fournit un soutien multilingue pratique.</string>
    119.         </French>
    120.     </languages>
    121.    
    122.     JavaScript:
    123.     var appName : String = langClass.getString("app_name");
    124.     */
    125.     public function getString (name : String) : String
    126.     {
    127.         if (!Strings.ContainsKey(name))
    128.         {
    129.             Debug.Log("The specified string does not exist: " + name);
    130.            
    131.             return "Er:"+name;
    132.         }
    133.             return Strings[name];
    134.     }
    135.  
    136. }
     
  12. Neoshiftr

    Neoshiftr

    Joined:
    Dec 5, 2012
    Posts:
    67
    Hello,
    I tried using the C# Version of this code on Android, but it does not seem to work, I always get this error:

    InvalidCastException: Cannot cast from source type to destination type.
    Lang.setLanguageWeb (System.String xmlText, System.String language) (at Lang.cs:97)

    var xmlItem = (XmlElement)elemEnum.Current;
     
  13. thrmotta

    thrmotta

    Joined:
    May 27, 2014
    Posts:
    32
    Im trying to write a xml according to your specifications, but I cant find a method to write a string like this:
    Code (CSharp):
    1. <string name="app_name">
    Both WriteElementString and WriteString gives me the exact same result. What should I be using to write a string as you provided on your lang.xml example?

    Thanks!
     
  14. thrmotta

    thrmotta

    Joined:
    May 27, 2014
    Posts:
    32
    Nevermind, figured it out. In case anyone need this in the future:

    Code (CSharp):
    1. writer.WriteStartElement("string");
    2. writer.WriteAttributeString("name", "app_name");
    3. writer.WriteString("Unity Multiple Language Support");
    4. writer.WriteEndElement();
     
  15. PaolaFalcon

    PaolaFalcon

    Joined:
    Aug 12, 2013
    Posts:
    1
    Is it possible to add multi-line translations? "\n" doesn't seem to work.
     
  16. Jakhongir

    Jakhongir

    Joined:
    May 12, 2015
    Posts:
    37
    Hello, I made localization via xml. On some devices some languages is not recognized, I see question marks instead of
    text.
     
  17. Ratboy601

    Ratboy601

    Joined:
    Jun 22, 2014
    Posts:
    29
    Ever figure out that error? I'm getting it on a plain old PC, Linux, Standalone build, only its on line 65. Its the same corresponding line of code for the SetLanguage function rather than SetLanguageWeb function.

    ======EDIT======== AND GOOD NEWS!

    I was able to solve this error by deleting the line in quesiton, and for the line immediately after, replace:

    Strings.Add(xmlItem.GetAttribute("name"), xmlItem.InnerText);

    with:

    Strings.Add((elemEnum.Current as XmlElement).GetAttribute("name"),(elemEnum.Current as XmlElement).InnerText);

    This was part of another solution to another problem further up in the thread, but it works here too. Oh and for future noobs reference, DO NOT put any empty lines, or commented out lines in your .xml files, or this script will not work.
     
    Last edited: Jan 2, 2016
  18. Great-Peter

    Great-Peter

    Joined:
    Oct 9, 2015
    Posts:
    14
    Not work...
    there are no errorson code and well done on computer. but in android, it doesn't work!


    using System.IO;
    using UnityEngine;
    using UnityEngine.UI;

    public class TestGui : MonoBehaviour

    {

    private Lang LMan;
    private string currentLang = "English";

    public static TestGui S;
    public string start;
    public string restart;
    public string stats;
    public string copyright;
    public string exit;

    public void OnEnable()
    {
    LMan = new Lang(Path.Combine(Application.dataPath, "lang.xml"), currentLang, false);
    }


    void Start()
    {

    S = this;
    currentLang = Application.systemLanguage.ToString ();
    print (Application.systemLanguage.ToString ());

    LMan.setLanguage (Path.Combine (Application.dataPath, "lang.xml"), currentLang);

    start = LMan.getString ("Start");
    restart = LMan.getString ("ReStart");
    stats = LMan.getString ("Stats");
    copyright = LMan.getString ("Copyright");
    exit = LMan.getString ("Exit");
    LMan.setLanguage (Path.Combine (Application.dataPath, "lang.xml"), currentLang);
    }

    }
     
  19. Great-Peter

    Great-Peter

    Joined:
    Oct 9, 2015
    Posts:
    14
    using System;
    using System.Collections;
    using System.IO;
    using System.Xml;
    using UnityEngine;


    public class Lang
    {
    private Hashtable Strings;


    public Lang ( string path, string language, bool web) {


    if (!web) {


    setLanguage(path, language);


    } else {


    setLanguageWeb(path, language);


    }


    }


    public void setLanguage ( string path, string language) {

    var xml = new XmlDocument();


    xml.Load(path);





    Strings = new Hashtable();


    var element = xml.DocumentElement[language];


    if (element != null) {


    var elemEnum = element.GetEnumerator();


    while (elemEnum.MoveNext()) {




    Strings.Add((elemEnum.Current as XmlElement).GetAttribute("name"),(elemEnum.Current as XmlElement).InnerText);



    }


    } else {


    Debug.LogError("The specified language does not exist: " + language);


    }


    }



    public void setLanguageWeb ( string xmlText, string language) {


    var xml = new XmlDocument();


    xml.Load(new StringReader(xmlText));





    Strings = new Hashtable();


    var element = xml.DocumentElement[language];


    if (element != null) {


    var elemEnum = element.GetEnumerator();


    while (elemEnum.MoveNext()) {




    Strings.Add((elemEnum.Current as XmlElement).GetAttribute("name"),(elemEnum.Current as XmlElement).InnerText);



    }


    } else {


    Debug.LogError("The specified language does not exist: " + language);


    }


    }



    public string getString (string name) {


    if (!Strings.ContainsKey(name)) {


    Debug.LogError("The specified string does not exist: " + name);





    return "";


    }





    return (string)Strings[name];


    }





    }
     
  20. Kiel369

    Kiel369

    Joined:
    Apr 10, 2012
    Posts:
    20
    Hi!
    I once needed good localization support for my Unity game. I wrote a simple system and thought I'd share it with you to solve multi language support problem for good now. It's crossplatform, designed for the new ui and uses xml just like Android's strings.xml. Check it out on AssetStore:

    https://www.assetstore.unity3d.com/#!/content/48673
     
  21. maruudn

    maruudn

    Joined:
    Mar 3, 2016
    Posts:
    1
    Hi! This helps a lot! I need to implement the XML being hosted on the web, and I've encountered some troubles with it. Wuld you post a script where it's implemented correctly?
     
  22. santiandrade

    santiandrade

    Joined:
    Sep 2, 2013
    Posts:
    13
    Someone have been able to run the C# version on Android? I have tried playing on Unity editor and it works perfectly, but when I build the game in my android device, it doesn't work! Why?? Please, help!

    Thanks!!
     
  23. santiandrade

    santiandrade

    Joined:
    Sep 2, 2013
    Posts:
    13
  24. nonaxanon

    nonaxanon

    Joined:
    Jan 20, 2012
    Posts:
    44
    just to add to the above , the code referenced in the post above , must be placed in the Lang.js or Lang.CS file,
    replace
    Code (CSharp):
    1.         var xml = new XmlDocument();
    2.         xml.Load(path);
    with
    Code (CSharp):
    1.         TextAsset textAsset = (TextAsset)Resources.Load("YOURXMLFILENAMEWITHNOEXTENSION", typeof(TextAsset));
    2.         XmlDocument xml = new XmlDocument ();
    3.         xml.LoadXml ( textAsset.text );
    that will work on Android, had a little bad time figuring that out , hope that helps someone else as me :)
     
    sekendiz likes this.
  25. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    Is this still viable in the current versions of Unity (5.x)?

    Does this take into account Google's automated ASO algorithms?
     
  26. Konarski

    Konarski

    Joined:
    Mar 24, 2016
    Posts:
    1
    Thank you very very much! Previously I was trying to write it myself but it failed...
     
  27. v01pe_

    v01pe_

    Joined:
    Mar 25, 2015
    Posts:
    71
    Hi, does this also set the supported languages in the apk somehow? I currently have the problem that in the store it only displays english, although I support more languages internally…
     
  28. Darth_Biomech

    Darth_Biomech

    Joined:
    Nov 28, 2019
    Posts:
    5
    Wasn't working in my version of Unity (2019.3.4) - throwed an "InvalidCastException: Specified cast is not valid. Lang.SetLanguage (System.String language) (at Assets/Scripts/Core/Lang.cs:65)", so after a few swears and lots of googling I managed to make it work (although didn't tested it for android or anything, just Windows). Truncated the functionality I didn't need, but it can be restored by analogy.
    Code (CSharp):
    1. /*
    2. The Lang Class adds easy to use multiple language support to any Unity project by parsing an XML file
    3. containing numerous strings translated into any languages of your choice.  Refer to UMLS_Help.html and lang.xml
    4. for more information.
    5.  
    6. Created by Adam T. Ryder
    7. C# version by O. Glorieux
    8.  
    9. */
    10.  
    11. using System;
    12. using System.Collections;
    13. using System.Collections.Generic;
    14. using System.IO;
    15. using System.Xml;
    16. using System.Text;
    17.  
    18. using UnityEngine;
    19. using RotaryHeart.Lib.SerializableDictionary;
    20.  
    21. /// <summary>
    22. /// This is the main class used to implement language control.
    23. /// </summary>
    24. public class Lang
    25. {
    26.     private Dictionary<string,string> Strings;
    27.  
    28.     /*
    29.     Initialize Lang class
    30.     path = path to XML resource example:  Path.Combine(Application.dataPath, "lang.xml")
    31.     language = language to use example:  "English"
    32.     web = boolean indicating if resource is local or on-line example:  true if on-line, false if local
    33.  
    34.     NOTE:
    35.     If XML resource is on-line rather than local do not supply the path to the path variable as stated above
    36.     instead use the WWW class to download the resource and then supply the resource.text to this initializer
    37.  
    38.     Web Example:
    39.     var wwwXML : WWW = new WWW("http://www.exampleURL.com/lang.xml");
    40.     yield wwwXML;
    41.  
    42.     var LangClass : Lang = new Lang(wwwXML.text, currentLang, true)
    43.     */
    44.     public Lang(string language)
    45.     {
    46.         SetLanguage(language);
    47.     }
    48.  
    49.     /*
    50.     Use the setLanguage function to swap languages after the Lang class has been initialized.
    51.     This function is called automatically when the Lang class is initialized.
    52.     path = path to XML resource example:  Path.Combine(Application.dataPath, "lang.xml")
    53.     language = language to use example:  "English"
    54.  
    55.     NOTE:
    56.     If the XML resource is stored on the web rather than on the local system use the
    57.     setLanguageWeb function
    58.     */
    59.     public void SetLanguage(string language)
    60.     {
    61.         // This path is directing to the StreamingAssets/Languages folder, since I wanted the xml file to remain acessible even after the game buid, and every language there have it's own xml file for the ease of editing them.
    62.  
    63.         string path = Path.Combine(Application.streamingAssetsPath, "Languages", language + ".xml");
    64.         XmlDocument xml = new XmlDocument();
    65.         xml.Load(path);
    66.         var languagesWrap = xml.LastChild;
    67.         XmlNode languagenodes = languagesWrap.ChildNodes[0];
    68.         var nodes = languagesWrap.SelectSingleNode(language);
    69.         if (nodes != null)
    70.         {
    71.                 Strings = new Dictionary<string,string>();
    72.  
    73.             int nodescount = languagesWrap.SelectSingleNode(language).SelectNodes("string").Count;
    74.  
    75.             for (var i = 0; i < nodescount; i++)
    76.             {
    77.                 string entryLabel = nodes.SelectNodes("string")[i].Attributes.GetNamedItem("name").Value.ToLower();
    78.                 string entryContent = nodes.SelectNodes("string")[i].InnerText;
    79.                 if (!Strings.ContainsKey(entryLabel))
    80.                     Strings.Add(entryLabel, entryContent);
    81.                 else
    82.                     Debug.LogWarning("Detected conflicting entries " + entryLabel + ", entry " + (i + 1) +" weren't added.");
    83.             }
    84.         }
    85.         else
    86.             Debug.LogError("The specified language does not exist: " + language + ", in:" + path);
    87.     }
    88.     public string GetEntry(string name)
    89.     {
    90.         if (!Strings.ContainsKey(name.ToLower()))
    91.         {
    92.             Debug.LogWarning("The specified string does not exist: " + name);
    93.  
    94.             //if not found, return standard string, so you could instantly notice that something's wrong.
    95.             return Strings["default"];
    96.         }
    97.  
    98.         return Strings[name.ToLower()];
    99.     }
    100.  
    101. }
    102.  
     
    Last edited: Mar 21, 2020
    shadoath likes this.
  29. shadoath

    shadoath

    Joined:
    Apr 4, 2020
    Posts:
    2
    After running through this thread a few times and I was able to get the code to work. Then came the issue of updating all the string values in my game. So I did some more Googling and found that Unity has a Localization package (preview) that is in the works. You can check out the refrence here.
    To install you MUST go to your /Packages/manifest.json file and add a line into the 'dependancies' block
    Code (CSharp):
    1.  "com.unity.localization": "0.6.1-preview"
    After this it will show up in the Package manager (for updating).
    Cheers!