com.xmobitea.changx.mini-localization 1.4.1 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Editor/LocalizationManagerEditor.cs +61 -4
- package/Editor/Tools/GetLocalizationTools/linux-x64/GetLocalization +0 -0
- package/Editor/Tools/GetLocalizationTools/linux-x64/GetLocalization.pdb +0 -0
- package/Editor/Tools/GetLocalizationTools/osx-x64/GetLocalization +0 -0
- package/Editor/Tools/GetLocalizationTools/osx-x64/GetLocalization.pdb +0 -0
- package/Editor/Tools/GetLocalizationTools/win-x64/GetLocalization.exe +0 -0
- package/Editor/Tools/GetLocalizationTools/win-x64/GetLocalization.pdb +0 -0
- package/Runtime/LocalizationLanguageItem.cs +16 -11
- package/Runtime/LocalizationManager.cs +107 -77
- package/package.json +1 -1
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
using System.Linq;
|
|
7
7
|
using System.Xml;
|
|
8
8
|
using System.Collections.Generic;
|
|
9
|
+
using System.Text.RegularExpressions;
|
|
10
|
+
using System.Text;
|
|
9
11
|
|
|
10
12
|
[CustomEditor(typeof(LocalizationManager))]
|
|
11
13
|
public class LocalizationManagerEditor : Editor
|
|
12
14
|
{
|
|
13
|
-
private const string Version = "1.4.
|
|
15
|
+
private const string Version = "1.4.2";
|
|
14
16
|
private const string Library = @".\Library\PackageCache\com.xmobitea.changx.mini-localization@" + Version;
|
|
15
17
|
//private const string Library = @".\Assets\MiniLocalization";
|
|
16
18
|
private const string ProcessPath = @"\Editor\Tools\GetLocalizationTools";
|
|
@@ -101,6 +103,16 @@
|
|
|
101
103
|
|
|
102
104
|
for (var i = 0; i < localizationLanguageItems.Length; i++) arguments += " " + localizationLanguageItems[i].SystemLanguage;
|
|
103
105
|
|
|
106
|
+
if (platform == RuntimePlatform.WindowsEditor || platform == RuntimePlatform.WindowsPlayer || platform == RuntimePlatform.WindowsServer)
|
|
107
|
+
{
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
else
|
|
111
|
+
{
|
|
112
|
+
processPath = processPath.Replace("\\", "/");
|
|
113
|
+
arguments = arguments.Replace("\\", "/");
|
|
114
|
+
}
|
|
115
|
+
|
|
104
116
|
Debug.Log("Run CommandLine " + processPath + " " + arguments);
|
|
105
117
|
|
|
106
118
|
var process = new System.Diagnostics.Process
|
|
@@ -189,11 +201,13 @@
|
|
|
189
201
|
{
|
|
190
202
|
var key = node.Attributes.GetNamedItem("name").Value;
|
|
191
203
|
|
|
192
|
-
|
|
204
|
+
var validKey = ToValidFieldName(key);
|
|
205
|
+
|
|
206
|
+
if (!keyNameLst.Contains(validKey))
|
|
193
207
|
{
|
|
194
|
-
keyNameLst.Add(
|
|
208
|
+
keyNameLst.Add(validKey);
|
|
195
209
|
|
|
196
|
-
contentBuilder.AppendLine(" public const string " +
|
|
210
|
+
contentBuilder.AppendLine(" public const string " + validKey + " = " + "\"" + key + "\";");
|
|
197
211
|
}
|
|
198
212
|
}
|
|
199
213
|
}
|
|
@@ -202,5 +216,48 @@
|
|
|
202
216
|
contentBuilder.AppendLine("}");
|
|
203
217
|
MiniAutoGenerate.Editor.AutoGenerate.GenerateFile("LocalizationConstanceId.cs", contentBuilder, Application.dataPath + "/XmobiTea-constance/Scripts/");
|
|
204
218
|
}
|
|
219
|
+
|
|
220
|
+
private static readonly HashSet<string> CSharpKeywords = new()
|
|
221
|
+
{
|
|
222
|
+
"class","struct","int","float","string","public","private","protected",
|
|
223
|
+
"internal","void","new","return","if","else","for","while","switch",
|
|
224
|
+
"case","default","break","continue","static","this","base","null",
|
|
225
|
+
"true","false","namespace","using"
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
private static string RemoveDiacritics(string text)
|
|
229
|
+
{
|
|
230
|
+
var normalized = text.Normalize(NormalizationForm.FormD);
|
|
231
|
+
var sb = new StringBuilder();
|
|
232
|
+
|
|
233
|
+
foreach (var c in normalized)
|
|
234
|
+
{
|
|
235
|
+
if (System.Globalization.CharUnicodeInfo.GetUnicodeCategory(c)
|
|
236
|
+
!= System.Globalization.UnicodeCategory.NonSpacingMark)
|
|
237
|
+
{
|
|
238
|
+
sb.Append(c);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return sb.ToString().Normalize(NormalizationForm.FormC);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private static string ToValidFieldName(string input)
|
|
246
|
+
{
|
|
247
|
+
if (string.IsNullOrWhiteSpace(input))
|
|
248
|
+
return "_field";
|
|
249
|
+
|
|
250
|
+
input = RemoveDiacritics(input.Trim());
|
|
251
|
+
|
|
252
|
+
input = Regex.Replace(input, @"[^a-zA-Z0-9_]", "_");
|
|
253
|
+
|
|
254
|
+
if (char.IsDigit(input[0]))
|
|
255
|
+
input = "_" + input;
|
|
256
|
+
|
|
257
|
+
if (CSharpKeywords.Contains(input))
|
|
258
|
+
input = "_" + input;
|
|
259
|
+
|
|
260
|
+
return input;
|
|
261
|
+
}
|
|
205
262
|
}
|
|
206
263
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
using System;
|
|
4
4
|
using UnityEngine;
|
|
5
5
|
|
|
6
|
+
#if ADDRESSABLE
|
|
7
|
+
using UnityEngine.AddressableAssets;
|
|
8
|
+
#endif
|
|
9
|
+
|
|
6
10
|
[Serializable]
|
|
7
11
|
public class LocalizationLanguageItem
|
|
8
12
|
{
|
|
@@ -18,16 +22,17 @@
|
|
|
18
22
|
private TextAsset xml;
|
|
19
23
|
public TextAsset XML { get { return xml; } set { xml = value; } }
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
25
|
+
#if ADDRESSABLE
|
|
26
|
+
|
|
27
|
+
[SerializeField]
|
|
28
|
+
private AssetReferenceT<TextAsset> xmlRef;
|
|
29
|
+
public AssetReferenceT<TextAsset> XMLRef { get { return xmlRef; } set { xmlRef = value; } }
|
|
30
|
+
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
[SerializeField]
|
|
34
|
+
private string onlineLocalizationUrl;
|
|
35
|
+
public string OnlineLocalizationUrl { get { return onlineLocalizationUrl; } set { onlineLocalizationUrl = value; } }
|
|
36
|
+
|
|
32
37
|
}
|
|
33
38
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
using System.IO;
|
|
8
8
|
using MiniSingleton;
|
|
9
9
|
using Core;
|
|
10
|
+
using UnityEngine.Networking;
|
|
10
11
|
|
|
11
12
|
public class LocalizationManager : Singleton<LocalizationManager>
|
|
12
13
|
{
|
|
@@ -63,42 +64,22 @@
|
|
|
63
64
|
|
|
64
65
|
var thisLanguage = Instance.localizationLanguageItemDic[systemLanguage];
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
{
|
|
69
|
-
var xml = LocalizationManager.GetTextWithoutBOM(thisLanguage.XML);
|
|
70
|
-
|
|
71
|
-
var xmlDoc = new XmlDocument();
|
|
72
|
-
|
|
73
|
-
xmlDoc.LoadXml(xml);
|
|
74
|
-
|
|
75
|
-
//var xml = thisLanguage.XML;
|
|
76
|
-
|
|
77
|
-
var xSectionNode = xmlDoc.ChildNodes.Item(1);
|
|
78
|
-
|
|
79
|
-
textLocalizationDic.Clear();
|
|
67
|
+
Instance.currentLanguage = thisLanguage;
|
|
80
68
|
|
|
81
|
-
|
|
82
|
-
{
|
|
83
|
-
foreach (XmlNode node in sectionNode)
|
|
84
|
-
{
|
|
85
|
-
var key = node.Attributes.GetNamedItem("name").Value;
|
|
86
|
-
var text = node.InnerText.Replace("\\n", "\n").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace("'", "'").Replace(""", "\"");
|
|
69
|
+
var textLocalizationDic = Instance.textLocalizationDic;
|
|
87
70
|
|
|
88
|
-
|
|
89
|
-
else Instance.textLocalizationDic[key] = text;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
71
|
+
textLocalizationDic.Clear();
|
|
93
72
|
|
|
94
73
|
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (!string.IsNullOrEmpty(onlineXmlStr))
|
|
74
|
+
if (thisLanguage.XML != null)
|
|
98
75
|
{
|
|
76
|
+
var xml = LocalizationManager.GetTextWithoutBOM(thisLanguage.XML);
|
|
77
|
+
|
|
99
78
|
var xmlDoc = new XmlDocument();
|
|
100
79
|
|
|
101
|
-
xmlDoc.LoadXml(
|
|
80
|
+
xmlDoc.LoadXml(xml);
|
|
81
|
+
|
|
82
|
+
//var xml = thisLanguage.XML;
|
|
102
83
|
|
|
103
84
|
var xSectionNode = xmlDoc.ChildNodes.Item(1);
|
|
104
85
|
|
|
@@ -109,78 +90,116 @@
|
|
|
109
90
|
var key = node.Attributes.GetNamedItem("name").Value;
|
|
110
91
|
var text = node.InnerText.Replace("\\n", "\n").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace("'", "'").Replace(""", "\"");
|
|
111
92
|
|
|
112
|
-
if (textLocalizationDic.ContainsKey(key))
|
|
113
|
-
|
|
114
|
-
Debug.LogError("[Localization] " + key + " " + " had replace by online xml");
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
textLocalizationDic[key] = text;
|
|
93
|
+
if (textLocalizationDic.ContainsKey(key)) Debug.LogError("[Localization] " + key + " " + " duplicate");
|
|
94
|
+
else textLocalizationDic[key] = text;
|
|
118
95
|
}
|
|
119
96
|
}
|
|
120
97
|
}
|
|
121
|
-
}
|
|
122
98
|
|
|
123
|
-
|
|
99
|
+
#if ADDRESSABLE
|
|
100
|
+
if (thisLanguage.XMLRef != null)
|
|
101
|
+
{
|
|
102
|
+
thisLanguage.XMLRef.LoadAssetAsync().Completed += (handle) =>
|
|
103
|
+
{
|
|
104
|
+
if (handle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded)
|
|
105
|
+
{
|
|
106
|
+
Debug.Log("Load xml from addressable success");
|
|
124
107
|
|
|
125
|
-
|
|
108
|
+
if (Instance.currentLanguage == thisLanguage)
|
|
109
|
+
{
|
|
110
|
+
var xml = LocalizationManager.GetTextWithoutBOM(handle.Result);
|
|
126
111
|
|
|
127
|
-
|
|
128
|
-
}
|
|
112
|
+
var xmlDoc = new XmlDocument();
|
|
129
113
|
|
|
130
|
-
|
|
131
|
-
{
|
|
132
|
-
if (!IsExists)
|
|
133
|
-
{
|
|
134
|
-
Debug.LogError("[Localization] LocalizationManager instance is null!");
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
114
|
+
xmlDoc.LoadXml(xml);
|
|
137
115
|
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
Debug.LogError("[Localization] LocalizationManager currentLanguage is null!");
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
116
|
+
var xSectionNode = xmlDoc.ChildNodes.Item(1);
|
|
143
117
|
|
|
144
|
-
|
|
118
|
+
foreach (XmlNode sectionNode in xSectionNode)
|
|
119
|
+
{
|
|
120
|
+
foreach (XmlNode node in sectionNode)
|
|
121
|
+
{
|
|
122
|
+
var key = node.Attributes.GetNamedItem("name").Value;
|
|
123
|
+
var text = node.InnerText.Replace("\\n", "\n").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace("'", "'").Replace(""", "\"");
|
|
145
124
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
125
|
+
if (textLocalizationDic.ContainsKey(key))
|
|
126
|
+
{
|
|
127
|
+
Debug.LogError("[Localization] " + key + " " + " had replace by addressable xml");
|
|
128
|
+
}
|
|
151
129
|
|
|
152
|
-
|
|
130
|
+
textLocalizationDic[key] = text;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
153
133
|
|
|
154
|
-
|
|
134
|
+
OnUpdateText?.Invoke();
|
|
135
|
+
}
|
|
136
|
+
else
|
|
137
|
+
{
|
|
138
|
+
Debug.Log("Load xml from addressable success, but the current language does not match");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else
|
|
142
|
+
{
|
|
143
|
+
Debug.LogError("Failed to load xml from addressable");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
#endif
|
|
150
|
+
}
|
|
155
151
|
|
|
156
152
|
{
|
|
157
|
-
var
|
|
153
|
+
var onlineLocalizationUrl = thisLanguage.OnlineLocalizationUrl;
|
|
158
154
|
|
|
159
|
-
if (!string.IsNullOrEmpty(
|
|
155
|
+
if (!string.IsNullOrEmpty(onlineLocalizationUrl))
|
|
160
156
|
{
|
|
161
|
-
|
|
157
|
+
Instance.StartCoroutine(IELoadOnlineLocalization(onlineLocalizationUrl, (success, value) =>
|
|
158
|
+
{
|
|
159
|
+
if (success)
|
|
160
|
+
{
|
|
161
|
+
Debug.Log("Load xml from online url success");
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
if (Instance.currentLanguage == thisLanguage)
|
|
164
|
+
{
|
|
165
|
+
var xml = value;
|
|
164
166
|
|
|
165
|
-
|
|
167
|
+
var xmlDoc = new XmlDocument();
|
|
166
168
|
|
|
167
|
-
|
|
169
|
+
xmlDoc.LoadXml(xml);
|
|
168
170
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
var xSectionNode = xmlDoc.ChildNodes.Item(1);
|
|
172
|
+
|
|
173
|
+
textLocalizationDic.Clear();
|
|
174
|
+
|
|
175
|
+
foreach (XmlNode sectionNode in xSectionNode)
|
|
176
|
+
{
|
|
177
|
+
foreach (XmlNode node in sectionNode)
|
|
178
|
+
{
|
|
179
|
+
var key = node.Attributes.GetNamedItem("name").Value;
|
|
180
|
+
var text = node.InnerText.Replace("\\n", "\n").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace("'", "'").Replace(""", "\"");
|
|
181
|
+
|
|
182
|
+
if (textLocalizationDic.ContainsKey(key))
|
|
183
|
+
{
|
|
184
|
+
Debug.LogError("[Localization] " + key + " " + " had replace by online url");
|
|
185
|
+
}
|
|
175
186
|
|
|
176
|
-
|
|
187
|
+
textLocalizationDic[key] = text;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
OnUpdateText?.Invoke();
|
|
192
|
+
}
|
|
193
|
+
else
|
|
177
194
|
{
|
|
178
|
-
Debug.
|
|
195
|
+
Debug.Log("Load xml from online url success, but the current language does not match");
|
|
179
196
|
}
|
|
180
|
-
|
|
181
|
-
textLocalizationDic[key] = text;
|
|
182
197
|
}
|
|
183
|
-
|
|
198
|
+
else
|
|
199
|
+
{
|
|
200
|
+
Debug.LogError("Failed to load xml from online url");
|
|
201
|
+
}
|
|
202
|
+
}));
|
|
184
203
|
}
|
|
185
204
|
}
|
|
186
205
|
|
|
@@ -189,6 +208,17 @@
|
|
|
189
208
|
return true;
|
|
190
209
|
}
|
|
191
210
|
|
|
211
|
+
private static System.Collections.IEnumerator IELoadOnlineLocalization(string localizationUrl, Action<bool, string> onLoaded)
|
|
212
|
+
{
|
|
213
|
+
using var unityWebRequest = UnityWebRequest.Get(localizationUrl);
|
|
214
|
+
yield return unityWebRequest.SendWebRequest();
|
|
215
|
+
|
|
216
|
+
if (unityWebRequest.result == UnityWebRequest.Result.Success)
|
|
217
|
+
onLoaded?.Invoke(true, unityWebRequest.downloadHandler.text);
|
|
218
|
+
else
|
|
219
|
+
onLoaded?.Invoke(false, unityWebRequest.error);
|
|
220
|
+
}
|
|
221
|
+
|
|
192
222
|
public static string GetTextWithoutBOM(TextAsset textAsset)
|
|
193
223
|
{
|
|
194
224
|
var memoryStream = new MemoryStream(textAsset.bytes);
|