240 lines
5.7 KiB
C#
240 lines
5.7 KiB
C#
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Xml;
|
||
|
using UnityEngine;
|
||
|
|
||
|
public class Localizer : MonoBehaviour
|
||
|
{
|
||
|
public class LocaleParameters
|
||
|
{
|
||
|
public string translation = string.Empty;
|
||
|
|
||
|
public float characterSizeFactor = 1f;
|
||
|
|
||
|
public float lineSpacingFactor = 1f;
|
||
|
}
|
||
|
|
||
|
private const string defaultFontName = "default";
|
||
|
|
||
|
private Dictionary<string, LocaleParameters> activeTranslations = new Dictionary<string, LocaleParameters>();
|
||
|
|
||
|
private Font languageSpecificFont;
|
||
|
|
||
|
private static Localizer instance;
|
||
|
|
||
|
private bool localizationDataInitalized;
|
||
|
|
||
|
private string currentLocale = string.Empty;
|
||
|
|
||
|
public static Localizer Instance
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return instance;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Font LanguageFont
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return languageSpecificFont;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static bool IsInstantiated()
|
||
|
{
|
||
|
return instance;
|
||
|
}
|
||
|
|
||
|
public static XmlDocument LoadLocalizationFile()
|
||
|
{
|
||
|
XmlDocument xmlDocument = new XmlDocument();
|
||
|
TextAsset textAsset = (TextAsset)Resources.Load("Localization/localization_data", typeof(TextAsset));
|
||
|
if ((bool)textAsset)
|
||
|
{
|
||
|
Debug.Log("Localization asset loaded: " + textAsset.name);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Assert.ErrorBreak("localization file failed to load");
|
||
|
}
|
||
|
xmlDocument.LoadXml(textAsset.text);
|
||
|
return xmlDocument;
|
||
|
}
|
||
|
|
||
|
private void Awake()
|
||
|
{
|
||
|
Assert.Check(instance == null, "Singleton " + base.name + " spawned twice");
|
||
|
instance = this;
|
||
|
UnityEngine.Object.DontDestroyOnLoad(this);
|
||
|
currentLocale = DetectLocale();
|
||
|
PopulateTranslations(currentLocale);
|
||
|
localizationDataInitalized = true;
|
||
|
}
|
||
|
|
||
|
private string DetectLocale()
|
||
|
{
|
||
|
string text = "en-EN";
|
||
|
switch (Application.systemLanguage)
|
||
|
{
|
||
|
case SystemLanguage.English:
|
||
|
text = "en-EN";
|
||
|
break;
|
||
|
case SystemLanguage.French:
|
||
|
text = "fr-FR";
|
||
|
break;
|
||
|
case SystemLanguage.Italian:
|
||
|
text = "it-IT";
|
||
|
break;
|
||
|
case SystemLanguage.German:
|
||
|
text = "de-DE";
|
||
|
break;
|
||
|
case SystemLanguage.Spanish:
|
||
|
text = "es-ES";
|
||
|
break;
|
||
|
case SystemLanguage.Chinese:
|
||
|
Debug.LogWarning("Chinese language dialect cannot be detected, using locale: 'zh-TW'");
|
||
|
text = "zh-TW";
|
||
|
break;
|
||
|
case SystemLanguage.Japanese:
|
||
|
text = "ja-JA";
|
||
|
break;
|
||
|
case SystemLanguage.Russian:
|
||
|
text = "ru-RU";
|
||
|
break;
|
||
|
case SystemLanguage.Arabic:
|
||
|
text = "ar-AR";
|
||
|
break;
|
||
|
case SystemLanguage.Portuguese:
|
||
|
Debug.LogWarning("Portugese language dialect cannot be detected, using locale: 'pt-PT'");
|
||
|
text = "pt-PT";
|
||
|
break;
|
||
|
case SystemLanguage.Polish:
|
||
|
text = "pl-PL";
|
||
|
break;
|
||
|
default:
|
||
|
text = "en-EN";
|
||
|
break;
|
||
|
}
|
||
|
Debug.Log(string.Concat("Unity system language: ", Application.systemLanguage, ", using game locale: ", text));
|
||
|
return text;
|
||
|
}
|
||
|
|
||
|
public LocaleParameters Resolve(string textId)
|
||
|
{
|
||
|
Assert.Check(localizationDataInitalized, "Tried to fetch translation:" + textId + " But localization data is not initialized");
|
||
|
Assert.Check(activeTranslations.Count > 0, "Could not resolve locale, localization data is empty");
|
||
|
if (!activeTranslations.ContainsKey(textId) || activeTranslations[textId].translation == string.Empty)
|
||
|
{
|
||
|
LocaleParameters localeParameters = new LocaleParameters();
|
||
|
Debug.LogWarning("LOCALIZATION KEY MISSING OR EMPTY (" + textId + ")");
|
||
|
localeParameters.translation = textId;
|
||
|
return localeParameters;
|
||
|
}
|
||
|
return activeTranslations[textId];
|
||
|
}
|
||
|
|
||
|
private void LoadFont(string fontName)
|
||
|
{
|
||
|
if (fontName != "default")
|
||
|
{
|
||
|
languageSpecificFont = (Font)Resources.Load("Localization/" + fontName, typeof(Font));
|
||
|
if ((bool)languageSpecificFont)
|
||
|
{
|
||
|
Debug.Log("language specific font loaded: " + fontName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Debug.LogWarning("Failed to load language specific font: " + fontName);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void PopulateTranslations(string localeId)
|
||
|
{
|
||
|
XmlDocument xmlDocument = LoadLocalizationFile();
|
||
|
XmlNode xmlNode = xmlDocument.SelectSingleNode("/texts/languages/" + localeId);
|
||
|
if (xmlNode != null)
|
||
|
{
|
||
|
LoadFont(xmlNode["font"].InnerText);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Debug.LogWarning("Could not find localization language settings for locale: " + localeId);
|
||
|
}
|
||
|
XmlNodeList xmlNodeList = xmlDocument.SelectNodes("/texts/text");
|
||
|
foreach (XmlNode item in xmlNodeList)
|
||
|
{
|
||
|
string innerText = item["text_id"].InnerText;
|
||
|
XmlElement xmlElement = item[localeId];
|
||
|
if (xmlElement == null)
|
||
|
{
|
||
|
xmlElement = item["en-EN"];
|
||
|
}
|
||
|
if (activeTranslations.ContainsKey(innerText))
|
||
|
{
|
||
|
if (Application.isEditor)
|
||
|
{
|
||
|
Assert.ErrorBreak("Localization data contains duplicate key: " + innerText);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
activeTranslations.Add(innerText, FormulateTranslation(xmlElement));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private LocaleParameters FormulateTranslation(XmlElement xn)
|
||
|
{
|
||
|
LocaleParameters localeParameters = new LocaleParameters();
|
||
|
localeParameters.translation = xn.InnerText;
|
||
|
string attribute = xn.GetAttribute("character_size");
|
||
|
string attribute2 = xn.GetAttribute("line_spacing");
|
||
|
if (attribute != string.Empty)
|
||
|
{
|
||
|
localeParameters.characterSizeFactor = (float)Convert.ToDouble(attribute);
|
||
|
}
|
||
|
if (attribute2 != string.Empty)
|
||
|
{
|
||
|
localeParameters.lineSpacingFactor = (float)Convert.ToDouble(attribute2);
|
||
|
}
|
||
|
return localeParameters;
|
||
|
}
|
||
|
|
||
|
private void OnApplicationFocus(bool focus)
|
||
|
{
|
||
|
if (focus)
|
||
|
{
|
||
|
string text = DetectLocale();
|
||
|
if (text != currentLocale)
|
||
|
{
|
||
|
RefreshLocalization();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnApplicationPause(bool paused)
|
||
|
{
|
||
|
if (!paused)
|
||
|
{
|
||
|
string text = DetectLocale();
|
||
|
if (text != currentLocale)
|
||
|
{
|
||
|
RefreshLocalization();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void RefreshLocalization()
|
||
|
{
|
||
|
Debug.Log("Relocalize all texts");
|
||
|
activeTranslations.Clear();
|
||
|
languageSpecificFont = null;
|
||
|
currentLocale = DetectLocale();
|
||
|
PopulateTranslations(currentLocale);
|
||
|
EventManager.Send(new LocalizationReloaded(currentLocale));
|
||
|
}
|
||
|
}
|