Best practice to internationalize(I18n) a unity project?

Hi,
I already read many threads about this subject, but all of them was written 2 or 3 years ago.
Does unity integrate a tool to handle internationalization properly?

All the solutions I read suggest loading files manually, parsing txt files, or hardcoding static strings, this looks a bit old fashion.

Hi @jeromeboe

About one year ago I was working on my first Unity Game Ducklings which we translated into 12 langauges. I am currently in the process of building a new game and so I will reuse the method.

I used MoonGateLab’s solution, which worked very well! It uses JSON files that are loaded at the start of your game.

It depends a little on how you built your scenes. I added a I18nManager.cs to my scene which worked like that:

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Mgl;
using ArabicSupport;

public class I18nManager : MonoBehaviour {

	private I18n i18n = I18n.Instance;

	[SerializeField] private Text title;
	[SerializeField] private Text settingsText;

	private void Start () {
		Messenger.AddListener<string>("Language:Change", SetLanguage); // event when langauge change
		InitLanguage();
		arabButtonText.text = ArabicFixer.Fix(arabButtonText.text);
	}

	private void SetLanguage (string locale) {
		PlayerPrefs.SetString("Language", locale);
		I18n.SetLocale(locale);
		DoTranslations();
	}

	private void DoTranslations () {
		title.text = i18n.__("Ducklings");
		settingsText.text = i18n.__("Settings");
	}

	private void InitLanguage () {

		if (PlayerPrefs.HasKey("Language")) {
			SetLanguage (PlayerPrefs.GetString("Language"));
			return;
		}

		// Use system language:
		//Debug.Log("Current System Language: "+Application.systemLanguage);

		switch (Application.systemLanguage) {
			// case SystemLanguage.Afrikaans: SetLanguage(""); break;
			case SystemLanguage.Arabic: SetLanguage("ar"); break;
			// case SystemLanguage.Basque: SetLanguage(""); break;
			// case SystemLanguage.Belarusian: SetLanguage(""); break;
			// case SystemLanguage.Bulgarian: SetLanguage(""); break;
			case SystemLanguage.Catalan: SetLanguage("es"); break;
			case SystemLanguage.Chinese: SetLanguage("zh"); break;
			// case SystemLanguage.Czech: SetLanguage(""); break;
			// case SystemLanguage.Danish: SetLanguage(""); break;
			// case SystemLanguage.Dutch: SetLanguage(""); break;
			case SystemLanguage.English: SetLanguage("en"); break;
			// case SystemLanguage.Estonian: SetLanguage(""); break;
			// case SystemLanguage.Faroese: SetLanguage(""); break;
			// case SystemLanguage.Finnish: SetLanguage(""); break;
			case SystemLanguage.French: SetLanguage("fr"); break;
			case SystemLanguage.German: SetLanguage("de"); break;
			// case SystemLanguage.Greek: SetLanguage(""); break;
			// case SystemLanguage.Hebrew: SetLanguage(""); break;
			// case SystemLanguage.Hungarian: SetLanguage(""); break;
			// case SystemLanguage.Icelandic: SetLanguage(""); break;
			// case SystemLanguage.Indonesian: SetLanguage(""); break;
			case SystemLanguage.Italian: SetLanguage("it"); break;
			case SystemLanguage.Japanese: SetLanguage("jp"); break;
			case SystemLanguage.Korean: SetLanguage("ko"); break;
			// case SystemLanguage.Latvian: SetLanguage(""); break;
			// case SystemLanguage.Lithuanian: SetLanguage(""); break;
			// case SystemLanguage.Norwegian: SetLanguage(""); break;
			// case SystemLanguage.Polish: SetLanguage(""); break;
			case SystemLanguage.Portuguese: SetLanguage("pr"); break;
			// case SystemLanguage.Romanian: SetLanguage(""); break;
			case SystemLanguage.Russian: SetLanguage("ru"); break;
			// case SystemLanguage.SerboCroatian: SetLanguage(""); break;
			// case SystemLanguage.Slovak: SetLanguage(""); break;
			// case SystemLanguage.Slovenian: SetLanguage(""); break;
			case SystemLanguage.Spanish: SetLanguage("es"); break;
			// case SystemLanguage.Swedish: SetLanguage(""); break;
			case SystemLanguage.Thai: SetLanguage("th"); break;
			case SystemLanguage.Turkish: SetLanguage("tr"); break;
			case SystemLanguage.Ukrainian: SetLanguage("ru"); break;
			// case SystemLanguage.Vietnamese: SetLanguage(""); break;
			case SystemLanguage.ChineseSimplified: SetLanguage("zh-si"); break;
			case SystemLanguage.ChineseTraditional: SetLanguage("zh-tr"); break;
			case SystemLanguage.Unknown: SetLanguage("en"); break;
			
		}

		// Sanity check:
		if (!PlayerPrefs.HasKey("Language")) {
			SetLanguage ("en");
		}

	}
}

For arab support I found this extension which I integrated with MoonGateLab’s code like so:

public string __(string key, params object[] args)
{
    //...

    if (config[key] != null)
    {

        //....

        if (_currentLocale == "ar") {
            translation = ArabicFixer.Fix(translation);
        }

Then I used a service like https://phraseapp.com/ which uses native speakers to translate your english JSON file to any language you want. (Spent about 12 dollars per language). The nice thing is that it provided the JSON files in the right format. So all I had to do is click the download button and save it in my assets folder. Very robust solution I think.

Took a day to implement. Three days for the translations. Cost about 150 Dollars.

Hi,

I use this class for all my projects:
I18n.cs