Created
September 29, 2020 01:02
-
-
Save kalineh/0ca4f639315cad42faef117901b2d149 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
public static class LocalizationEditorMenu | |
{ | |
[MenuItem("Custom/Localization Quick Import")] | |
public static void LocalizationQuickImport() | |
{ | |
var locPath = string.Format("Assets/Prefabs/Localization.prefab", Application.dataPath); | |
var locObj = AssetDatabase.LoadAssetAtPath<GameObject>(locPath); | |
if (locObj == null) | |
return; | |
var loc = locObj.GetComponent<Localization>(); | |
if (loc == null) | |
return; | |
var textPath = string.Format("{0}/Localization.csv", Application.dataPath); | |
var text = System.IO.File.ReadAllText(textPath); | |
var errors = loc.Validate(text); | |
if (errors > 0) | |
return; | |
loc.Reimport(text); | |
EditorUtility.SetDirty(loc); | |
AssetDatabase.SaveAssets(); | |
} | |
} | |
[CustomEditor(typeof(Localization))] | |
class LocalizationEditor | |
: Editor | |
{ | |
public override void OnInspectorGUI() | |
{ | |
base.OnInspectorGUI(); | |
var self = target as Localization; | |
if (GUILayout.Button("Clear")) | |
self.Clear(); | |
if (GUILayout.Button("Validate")) | |
{ | |
var filename = EditorUtility.OpenFilePanel("LocalizationData.csv", Application.dataPath, "csv"); | |
if (string.IsNullOrEmpty(filename)) | |
return; | |
var data = System.IO.File.ReadAllText(filename); | |
self.Clear(); | |
self.Validate(data); | |
} | |
if (GUILayout.Button("Import")) | |
{ | |
var filename = EditorUtility.OpenFilePanel("LocalizationData.csv", Application.dataPath, "csv"); | |
if (string.IsNullOrEmpty(filename)) | |
return; | |
var data = System.IO.File.ReadAllText(filename); | |
var errors = self.Validate(data); | |
if (errors <= 0) | |
{ | |
Undo.RecordObject(self, "Reimport"); | |
self.Clear(); | |
self.Reimport(data); | |
EditorUtility.SetDirty(self); | |
} | |
} | |
GUILayout.Label(string.Format("Language: {0}", self.languages[self.languageIndex].code)); | |
if (Application.isPlaying) | |
{ | |
var currLanguageIndex = EditorGUILayout.IntSlider(self.languageIndex, 0, self.languages.Count - 1); | |
if (currLanguageIndex != self.languageIndex) | |
self.ChangeLanguage(currLanguageIndex); | |
} | |
} | |
} | |
#endif | |
//LANGUAGE|Language|日本語|한국어|中文|Francais|Italian|Deutsch|Spanish|Dog | |
// 0: keys | |
// 1: en | |
// 2: ja | |
// 3: kr | |
// 4: zh | |
// 5: fr | |
// 6: it | |
// 7: de | |
// 8: es | |
// 9: pl | |
// 10: dog | |
public class Localization | |
: MonoBehaviour | |
{ | |
private static Localization _Instance; | |
public static Localization Instance | |
{ | |
get | |
{ | |
if (_Instance == null) | |
_Instance = GameObject.Find("Localization").GetComponent<Localization>(); | |
return _Instance; | |
} | |
} | |
public void Awake() | |
{ | |
if (Localization._Instance != null && Localization._Instance != this) | |
{ | |
GameObject.Destroy(this.gameObject); | |
return; | |
} | |
Localization._Instance = this; | |
transform.SetParent(null); | |
GameObject.DontDestroyOnLoad(gameObject); | |
} | |
private Dictionary<string, string> key; | |
private static char delimiter = ','; | |
private static char quote = '"'; | |
[System.Serializable] | |
public class Language | |
{ | |
public string code; | |
public List<string> data; | |
} | |
[System.NonSerialized] | |
public int languageIndex; | |
public List<Language> languages; | |
private Dictionary<string, int> lookup; | |
public void OnEnable() | |
{ | |
var language = Options.Instance.Language; | |
ChangeLanguage(language); | |
RebuildLookup(); | |
} | |
public void Clear() | |
{ | |
languages = new List<Language>(); | |
languages.Add(new Language() { code = "keys", data = new List<string>(), }); | |
languages.Add(new Language() { code = "en", data = new List<string>(), }); | |
languages.Add(new Language() { code = "ja", data = new List<string>(), }); | |
languages.Add(new Language() { code = "kr", data = new List<string>(), }); | |
languages.Add(new Language() { code = "zh", data = new List<string>(), }); | |
languages.Add(new Language() { code = "fr", data = new List<string>(), }); | |
languages.Add(new Language() { code = "it", data = new List<string>(), }); | |
languages.Add(new Language() { code = "de", data = new List<string>(), }); | |
languages.Add(new Language() { code = "es", data = new List<string>(), }); | |
languages.Add(new Language() { code = "pl", data = new List<string>(), }); | |
languages.Add(new Language() { code = "dog", data = new List<string>(), }); | |
} | |
public int Validate(string text) | |
{ | |
#if UNITY_EDITOR | |
var timeStart = EditorApplication.timeSinceStartup; | |
#else | |
var timeStart = Time.realtimeSinceStartup; | |
#endif | |
var errors = 0; | |
for (int i = 0; i < languages.Count; ++i) | |
Debug.LogFormat("Localization.Validate: language {0} = {1}", i, languages[i].code); | |
var clean = text; | |
var seperators = new char[] { delimiter, }; | |
var newlines = new char[] { '\n', }; | |
clean = text.Replace("\r\n", "\n"); | |
clean = text.Replace("\n", "\n"); | |
var lines = text.Split(newlines); | |
Debug.LogFormat("Localization.Validate: validating {0} entries...", lines.Length); | |
for (int i = 0; i < lines.Length; ++i) | |
{ | |
var line = lines[i]; | |
var data = line.SplitE(delimiter, quote); | |
var last = errors; | |
if (string.IsNullOrWhiteSpace(line)) | |
{ | |
Debug.LogFormat("{0}: empty line", i + 1); | |
errors++; | |
continue; | |
} | |
if (line.Contains("||")) | |
{ | |
Debug.LogFormat("{0}: double || found, likely error", i + 1); | |
errors++; | |
continue; | |
} | |
if (data.Length <= 0) | |
{ | |
Debug.LogFormat("{0}: empty row", i + 1); | |
errors++; | |
continue; | |
} | |
if (data.Length < languages.Count) | |
{ | |
Debug.LogFormat("{0}: missing language entry for {1} (found {2} of {3})", i + 1, data[0], data.Length, languages.Count); | |
errors++; | |
continue; | |
} | |
if (data.Length > languages.Count) | |
{ | |
Debug.LogFormat("{0}: too many language entries for {1} (found {2} of {3})", i + 1, data[0], data.Length, languages.Count); | |
errors++; | |
continue; | |
} | |
for (int j = 0; j < data.Length; ++j) | |
{ | |
if (string.IsNullOrWhiteSpace(data[j])) | |
{ | |
Debug.LogFormat("{0}: missing data in key {1} for language {2}", i + 1, data[0], j); | |
errors++; | |
} | |
} | |
for (int j = 0; j < lines.Length; ++j) | |
{ | |
if (j == i) | |
continue; | |
var lineCheck = lines[j]; | |
var lineCheckSplit = lineCheck.Split(seperators); | |
if (lineCheckSplit.Length <= 0) | |
continue; | |
var lineCheckKey = lineCheckSplit[0]; | |
if (lineCheckKey == data[0]) | |
{ | |
Debug.LogFormat("{0}: duplicate key {1}", i + 1, data[0]); | |
errors++; | |
} | |
} | |
if (last != errors) | |
continue; | |
//Debug.LogFormat("{0}: OK {1}", i + 1, data[0]); | |
} | |
#if UNITY_EDITOR | |
var timeEnd = EditorApplication.timeSinceStartup; | |
var timeTaken = (float)(timeEnd - timeStart); | |
#else | |
var timeTaken = Time.realtimeSinceStartup; | |
#endif | |
Debug.LogFormat("Localization.Validate: complete with {0} errors (took {1}ms)", errors, timeTaken * 1000.0f); | |
return errors; | |
} | |
public void Reimport(string text) | |
{ | |
#if UNITY_EDITOR | |
var timeStart = EditorApplication.timeSinceStartup; | |
#else | |
var timeStart = Time.realtimeSinceStartup; | |
#endif | |
var clean = text; | |
var seperators = new char[] { delimiter, }; | |
var newlines = new char[] { '\n', }; | |
clean = text.Replace("\r\n", "\n"); | |
clean = text.Replace("\n", "\n"); | |
var lines = text.Split(newlines, System.StringSplitOptions.RemoveEmptyEntries); | |
for (int i = 0; i < lines.Length; ++i) | |
{ | |
var line = lines[i]; | |
var data = line.SplitE(delimiter, quote); | |
var key = data[0]; | |
languages[0].data.Add(key); | |
for (int j = 1; j < data.Length; ++j) | |
languages[j].data.Add(data[j]); | |
} | |
#if UNITY_EDITOR | |
var timeEnd = EditorApplication.timeSinceStartup; | |
var timeTaken = (float)(timeEnd - timeStart); | |
#else | |
var timeTaken = Time.realtimeSinceStartup; | |
#endif | |
Debug.LogFormat("Localization.Reimport: complete (took {0}ms)", timeTaken * 1000.0f); | |
} | |
public void RebuildLookup() | |
{ | |
lookup = new Dictionary<string, int>(); | |
var keys = languages[0].data; | |
for (int i = 0; i < keys.Count; ++i) | |
lookup.Add(keys[i], i); | |
} | |
#if UNITY_EDITOR | |
public string EditorGet(string key) | |
{ | |
var keys = languages[0]; | |
var language = languages[1]; | |
for (int i = 0; i < keys.data.Count; ++i) | |
{ | |
var k = keys.data[i]; | |
if (k == key) | |
return languages[1].data[i]; | |
} | |
return string.Format("!{0}!", key); | |
} | |
#endif | |
public string Get(string key) | |
{ | |
#if UNITY_EDITOR | |
if (lookup.ContainsKey(key) == false) | |
{ | |
Debug.LogErrorFormat("Localization: missing key request: {0}", key); | |
return string.Format("!{0}!", key); | |
} | |
#endif | |
var index = lookup[key]; | |
var value = languages[languageIndex].data[index]; | |
return value; | |
} | |
public string Get1(string key, object arg0) | |
{ | |
#if UNITY_EDITOR | |
if (lookup.ContainsKey(key) == false) | |
{ | |
Debug.LogErrorFormat("Localization: missing key request: {0}", key); | |
return string.Format("!{0}!", key); | |
} | |
#endif | |
var format = Get(key); | |
var value = string.Format(format, arg0); | |
return value; | |
} | |
public string Get2(string key, object arg0, object arg1) | |
{ | |
#if UNITY_EDITOR | |
if (lookup.ContainsKey(key) == false) | |
{ | |
Debug.LogErrorFormat("Localization: missing key request: {0}", key); | |
return string.Format("!{0}!", key); | |
} | |
#endif | |
var format = Get(key); | |
var value = string.Format(format, arg0, arg1); | |
return value; | |
} | |
public string Get3(string key, object arg0, object arg1, object arg2) | |
{ | |
#if UNITY_EDITOR | |
if (lookup.ContainsKey(key) == false) | |
{ | |
Debug.LogErrorFormat("Localization: missing key request: {0}", key); | |
return string.Format("!{0}!", key); | |
} | |
#endif | |
var format = Get(key); | |
var value = string.Format(format, arg0, arg1, arg2); | |
return value; | |
} | |
public void CycleLanguage() | |
{ | |
ChangeLanguage((languageIndex + 1) % languages.Count); | |
} | |
public void ChangeLanguage(int index) | |
{ | |
languageIndex = index; | |
foreach (var dynamic in Tracked<LocalizationDynamic>.Instances) | |
dynamic.Translate(); | |
foreach (var character in Tracked<Character>.Instances) | |
character.SetupNametag(); | |
} | |
public List<string> CollectKeysByPrefix(string prefix) | |
{ | |
var results = new List<string>(); | |
var keys = languages[0].data; | |
for (int i = 0; i < keys.Count; ++i) | |
{ | |
var key = keys[i]; | |
if (key.StartsWith(prefix)) | |
results.Add(key); | |
} | |
return results; | |
} | |
#if UNITY_EDITOR | |
public static string EditorLocalizeGet(string key) | |
{ | |
var obj = GameObject.FindObjectOfType<Localization>(); | |
var value = obj.EditorGet(key); | |
return value; | |
} | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment