Tanoda
Localization_SOURCE_Window.cs
Go to the documentation of this file.
1#if UNITY_EDITOR
2using System;
3using System.Collections.Generic;
4using System.IO;
5using System.Text;
6using UnityEditor;
7using UnityEngine;
8
9//---Written by Matej Vanco 20.10.2018 dd/mm/yyyy
10//---Updated by Matej Vanco 05.01.2021 dd/mm/yyyy
11//---Language Localization - Window
12
13public class Localization_SOURCE_Window : EditorWindow
14{
15 //---Input-Output Settings & Registry
16 private static string locSelectedPath;
17
18 private static readonly string locRegistryKey = "LOCATION_MANAGER_LocManagPath";
19
20 //Main heading format [will be written on top of every language file] - you can customize it
21 private static readonly string locHeadingFormat = "Localization_Manager_Source";
22
23 //---Essential Variables - Language file, Category, Localization
24 public static string locCurrentLanguage;
25
26 //Main language localization file selected
27 private static bool locManagerSelected = true;
28
29 //Category settings
30 private static int locCategorySelected;
31 public static List<string> locAvailableCategories = new List<string>();
32 private static string locSelectedCategoryName;
33
34 public class LocalizationElemenets
35 {
36 public string Key;
37 [Multiline] public string Text;
38 public int Category;
39 }
40
41 public static List<LocalizationElemenets> localizationElements = new List<LocalizationElemenets>();
42
43 public static bool loc_WindowInitialized;
44 private static bool loc_ReadySteady;
45
49 public static void Init()
50 {
51 if (loc_WindowInitialized)
52 return;
53
54 loc_WindowInitialized = true;
55
56 localizationElements.Clear();
57 Loc_GetLocalizationManagerPath();
58 }
59
60 [MenuItem("Window/Localization Manager")]
61 public static void InitWindow()
62 {
63 var win = new Localization_SOURCE_Window();
64 win.minSize = new Vector2(400, 250);
65 win.titleContent = new GUIContent("Localization Editor");
66 win.Show();
67
68 localizationElements.Clear();
69 Loc_GetLocalizationManagerPath();
70 }
71
72
73 #region DataManaging
74
78 public static void Loc_GetLocalizationManagerPath()
79 {
80 locCurrentLanguage = "";
81
82 locSelectedPath = PlayerPrefs.GetString(locRegistryKey);
83 loc_ReadySteady = !string.IsNullOrEmpty(locSelectedPath);
84
85 if (!loc_ReadySteady) return;
86
87 loc_ReadySteady = true;
88 locManagerSelected = true;
89
90 Loc_RefreshContent();
91 }
92
93 private static void Loc_SelectLanguageFile()
94 {
95 Loc_SaveDatabase(locSelectedPath, false);
96
97 var f = EditorUtility.OpenFilePanel("Select Language File Path", Application.dataPath, "xml");
98
99 if (string.IsNullOrEmpty(f)) return;
100
101 locSelectedPath = f;
102 locManagerSelected = false;
103
104 locCurrentLanguage = Path.GetFileNameWithoutExtension(locSelectedPath);
105
106 Loc_LoadDatabase(locSelectedPath, false);
107 }
108
109 private static void Loc_CreateLanguageFile()
110 {
111 Loc_SaveDatabase(locSelectedPath, false);
112
113 var f = EditorUtility.SaveFilePanel("Create Language File", Application.dataPath, "English", "xml");
114
115 if (string.IsNullOrEmpty(f)) return;
116
117 File.Create(f).Dispose();
118
119 locSelectedPath = f;
120 locManagerSelected = false;
121
122 locCurrentLanguage = Path.GetFileNameWithoutExtension(locSelectedPath);
123
124 Loc_LoadDatabase(locSelectedPath, false);
125
126 AssetDatabase.Refresh();
127 }
128
132 public static void Loc_RefreshContent()
133 {
134 locAvailableCategories.Clear();
135 locAvailableCategories.Add("Default"); //Add default category
136 localizationElements.Clear();
137
138 if (!File.Exists(locSelectedPath))
139 {
140 Loc_ErrorDebug("The selected file path '" + locSelectedPath + "' doesn't exist!");
141 PlayerPrefs.DeleteKey(locRegistryKey);
142 loc_ReadySteady = false;
143 return;
144 }
145
146 var allLines = File.ReadAllLines(locSelectedPath);
147 if (allLines.Length <= 1)
148 return;
149
150 //Getting all categories first (Categories starts with 'Category Delimiter Symbol')
151 for (var i = 1; i < allLines.Length; i++)
152 {
153 var currentLine = allLines[i];
154 if (currentLine.Length <= 1) continue;
155 if (currentLine.StartsWith(Localization_SOURCE.GENERAL_DelimiterSymbol_Category))
156 locAvailableCategories.Add(currentLine.Trim().Remove(0, 1));
157 }
158
159 //Getting all localization keys (Keys contains 'Key Delimiter Symbol')
160 var currentCategory = 0;
161 for (var i = 1; i < allLines.Length; i++)
162 {
163 var currentLine = allLines[i];
164 if (currentLine.Length <= 1) continue;
165
166 //Skip lines that starts with category delimiter
167 if (currentLine.StartsWith(Localization_SOURCE.GENERAL_DelimiterSymbol_Category))
168 {
169 currentCategory++;
170 continue;
171 }
172
173 //Key must be longer than 1 char!
174 if (!locManagerSelected &&
175 currentLine.IndexOf(Localization_SOURCE.GENERAL_DelimiterSymbol_Key) <= 1) continue;
176
177 var locElement = new LocalizationElemenets();
178 var keySrc = locManagerSelected
179 ? currentLine
180 : currentLine.Substring(0, currentLine.IndexOf(Localization_SOURCE.GENERAL_DelimiterSymbol_Key));
181 locElement.Key = keySrc;
182 if (!locManagerSelected)
183 {
184 var keyText = currentLine.Substring(keySrc.Length + 1, currentLine.Length - keySrc.Length - 1);
185 locElement.Text = keyText.Replace(Localization_SOURCE.GENERAL_NewLineSymbol, Environment.NewLine);
186 }
187
188 locElement.Category = currentCategory;
189
190 //Add proper key
191 localizationElements.Add(locElement);
192 }
193 }
194
198 public static void Loc_SaveDatabase(string ToPath, bool RefreshData = true)
199 {
200 if (!File.Exists(ToPath))
201 {
202 Loc_ErrorDebug("The file path " + ToPath + " doesn't exist!");
203 return;
204 }
205
206 File.WriteAllText(ToPath, locHeadingFormat);
207
208 var fstream = new FileStream(ToPath, FileMode.Append);
209 var fwriter = new StreamWriter(fstream);
210
211 fwriter.WriteLine("");
212
213 foreach (var category in locAvailableCategories)
214 {
215 //Write category name first
216 if (category != "Default")
217 fwriter.WriteLine(Localization_SOURCE.GENERAL_DelimiterSymbol_Category + category);
218
219 //Write category elements
220 foreach (var locElement in localizationElements)
221 {
222 //Check conditions
223 if (category != locAvailableCategories[locElement.Category]) continue;
224 if (string.IsNullOrEmpty(locElement.Key)) continue;
225
226 //Write key & text
227 if (locElement.Key.Contains(Localization_SOURCE.GENERAL_DelimiterSymbol_Category)
228 ||
229 locElement.Key.Contains(Localization_SOURCE.GENERAL_DelimiterSymbol_Key))
230 {
231 Loc_ErrorDebug("key '" + locElement.Key +
232 "' contains Category Delimiter or Key Delimiter. Please remove these characters from the key... Saving process was terminated");
233 fwriter.Dispose();
234 fstream.Close();
235 }
236
237 if (locManagerSelected)
238 {
239 fwriter.WriteLine(locElement.Key);
240 }
241 else
242 {
243 var sb = new StringBuilder(locElement.Text);
244 sb.Replace(Environment.NewLine, Localization_SOURCE.GENERAL_NewLineSymbol);
247 fwriter.WriteLine(locElement.Key + Localization_SOURCE.GENERAL_DelimiterSymbol_Key + sb);
248 }
249 }
250 }
251
252 fwriter.Dispose();
253 fstream.Close();
254
255 AssetDatabase.Refresh();
256
257 if (RefreshData) Loc_RefreshContent();
258 }
259
263 public static void Loc_LoadDatabase(string FromPath, bool RefreshData = true)
264 {
265 if (!File.Exists(FromPath))
266 {
267 Loc_ErrorDebug("The file path " + FromPath + " doesn't exist!");
268 return;
269 }
270
271 if (File.ReadAllLines(FromPath).Length > 1)
272 {
273 var storedFilelines = new List<string>();
274 for (var i = 1; i < File.ReadAllLines(FromPath).Length; i++)
275 storedFilelines.Add(File.ReadAllLines(FromPath)[i]);
276
277 foreach (var categories in locAvailableCategories)
278 foreach (var locArray in localizationElements)
279 if (Loc_GetLocalizationCategory(categories) == locArray.Category)
280 foreach (var s in storedFilelines)
281 {
282 if (string.IsNullOrEmpty(s)) continue;
283 if (s.StartsWith(Localization_SOURCE.GENERAL_DelimiterSymbol_Category)) continue;
284
286 ? s.Substring(0, s.IndexOf(Localization_SOURCE.GENERAL_DelimiterSymbol_Key))
287 : s;
288 if (string.IsNullOrEmpty(Key)) continue;
289
290 if (Key == locArray.Key)
291 {
292 if (s.Length < Key.Length + 1) continue;
293 locArray.Text = s.Substring(Key.Length + 1, s.Length - Key.Length - 1)
294 .Replace(Localization_SOURCE.GENERAL_NewLineSymbol, Environment.NewLine);
295 break;
296 }
297 }
298 }
299
300 if (RefreshData) Loc_RefreshContent();
301 }
302
303 #endregion
304
305
306 private static int Loc_GetLocalizationCategory(string entry)
307 {
308 var c = 0;
309 foreach (var categ in locAvailableCategories)
310 {
311 if (categ == entry) return c;
312 c++;
313 }
314
315 return 0;
316 }
317
318 private static Vector2 guiScrollHelper;
319
320 private void OnGUI()
321 {
322 EditorGUI.indentLevel++;
323 pDrawSpace();
324
325 pDrawLabel("Localization Manager by Matej Vanco", true);
326
327 pDrawSpace();
328
329 //If Localization Manager file not set & ready
330 if (!loc_ReadySteady)
331 {
332 GUILayout.BeginVertical("Box");
333
334 EditorGUILayout.HelpBox(
335 "There is no Localization Manager file. To set up keys structure and language system, select or create a Localization Manager file.",
336 MessageType.Info);
337 GUILayout.BeginHorizontal("Box");
338 if (GUILayout.Button("Select Localization Manager file"))
339 {
340 var f = EditorUtility.OpenFilePanel("Select Localization Manager file", Application.dataPath, "txt");
341 if (string.IsNullOrEmpty(f)) return;
342 locSelectedPath = f;
343 PlayerPrefs.SetString(locRegistryKey, locSelectedPath);
344 Loc_MessageDebug("All set! The Localization Manager is now ready.");
345 Loc_GetLocalizationManagerPath();
346 return;
347 }
348
349 if (GUILayout.Button("Create Localization Manager file"))
350 {
351 var f = EditorUtility.SaveFilePanel("Create Localization Manager file", Application.dataPath,
352 "LocalizationManager", "txt");
353 if (string.IsNullOrEmpty(f))
354 return;
355 File.Create(f).Dispose();
356 locSelectedPath = f;
357 PlayerPrefs.SetString(locRegistryKey, locSelectedPath);
358 Loc_MessageDebug("Great! The Localization Manager is now ready.");
359 Loc_SaveDatabase(locSelectedPath, false);
360 Loc_GetLocalizationManagerPath();
361 return;
362 }
363
364 GUILayout.EndHorizontal();
365 GUILayout.EndVertical();
366
367 return;
368 }
369
370 //If Localization Manager file selected & ready
371
372 #region SECTION__UPPER
373
374 GUILayout.BeginHorizontal("Box");
375 if (GUILayout.Button("Save System"))
376 Loc_SaveDatabase(locSelectedPath);
377 pDrawSpace();
378 if (locManagerSelected)
379 if (GUILayout.Button("Reset Manager Path"))
380 if (EditorUtility.DisplayDialog("Question",
381 "You are about to reset the Localization Manager path... No file o file be removed, just the current Language Localization path will be removed from the registry. Are you sure to continue?",
382 "Yes", "No"))
383 {
384 PlayerPrefs.DeleteKey(locRegistryKey);
385 Close();
386 return;
387 }
388
389 GUILayout.EndHorizontal();
390
391 pDrawSpace(5);
392
393 string lang;
394 if (!string.IsNullOrEmpty(locCurrentLanguage))
395 {
396 locManagerSelected = false;
397 lang = locCurrentLanguage;
398 }
399 else
400 {
401 locManagerSelected = true;
402 lang = "Language Manager";
403 }
404
405 GUILayout.BeginHorizontal("Box");
406 pDrawLabel("Selected: " + lang);
407 if (GUILayout.Button("Deselect Language"))
408 {
409 Loc_SaveDatabase(locSelectedPath, false);
410 Loc_GetLocalizationManagerPath();
411 }
412
413 if (GUILayout.Button("Select Language"))
414 Loc_SelectLanguageFile();
415 pDrawSpace();
416 if (GUILayout.Button("Create Language"))
417 Loc_CreateLanguageFile();
418 GUILayout.EndHorizontal();
419
420 #endregion
421
422 pDrawSpace(5);
423
424 GUILayout.BeginVertical("Box");
425
426 #region SECTION__CATEGORIES
427
428 GUILayout.BeginHorizontal("Box");
429 EditorGUIUtility.labelWidth -= 70;
430 locCategorySelected = EditorGUILayout.Popup("Category:", locCategorySelected, locAvailableCategories.ToArray(),
431 GUILayout.MaxWidth(300), GUILayout.MinWidth(150));
432 EditorGUIUtility.labelWidth += 70;
433 if (locManagerSelected)
434 {
435 pDrawSpace();
436 locSelectedCategoryName = EditorGUILayout.TextField(locSelectedCategoryName);
437 if (GUILayout.Button("Add Category"))
438 {
439 if (string.IsNullOrEmpty(locSelectedCategoryName))
440 {
441 Loc_ErrorDebug("Please fill the required field! [Category Name]");
442 return;
443 }
444
445 locAvailableCategories.Add(locSelectedCategoryName);
446 locSelectedCategoryName = "";
447 GUI.FocusControl("Set");
448 return;
449 }
450
451 if (GUILayout.Button("Remove Category") && locAvailableCategories.Count > 1)
452 if (EditorUtility.DisplayDialog("Question", "You are about to remove a category... Are you sure?",
453 "Yes", "No"))
454 {
455 if (string.IsNullOrEmpty(locSelectedCategoryName))
456 {
457 locAvailableCategories.RemoveAt(locAvailableCategories.Count - 1);
458 locCategorySelected = 0;
459 }
460 else
461 {
462 var cc = 0;
463 var notfound = true;
464 foreach (var cat in locAvailableCategories)
465 {
466 if (locSelectedCategoryName == cat)
467 {
468 locAvailableCategories.RemoveAt(cc);
469 locCategorySelected = 0;
470 notfound = false;
471 break;
472 }
473
474 cc++;
475 }
476
477 if (notfound) Loc_ErrorDebug("The category couldn't be found.");
478 locSelectedCategoryName = "";
479 }
480
481 return;
482 }
483 }
484
485 GUILayout.EndHorizontal();
486
487 #endregion
488
489 pDrawSpace();
490
491 #region SECTION__LOCALIZATION_ARRAY
492
493 GUILayout.BeginHorizontal();
494 pDrawLabel("Localization Keys & Texts");
495 if (locManagerSelected && GUILayout.Button("+"))
496 localizationElements.Add(new LocalizationElemenets {Category = locCategorySelected});
497 GUILayout.EndHorizontal();
498
499 if (localizationElements.Count == 0)
500 {
501 pDrawLabel(" - - Empty! - -");
502 }
503 else
504 {
505 guiScrollHelper = EditorGUILayout.BeginScrollView(guiScrollHelper);
506
507 var c = 0;
508 foreach (var locA in localizationElements)
509 {
510 if (locA.Category >= locAvailableCategories.Count)
511 {
512 locA.Category = 0;
513 break;
514 }
515
516 if (locAvailableCategories[locA.Category] != locAvailableCategories[locCategorySelected])
517 continue;
518
519 EditorGUIUtility.labelWidth -= 100;
520 EditorGUILayout.BeginHorizontal("Box");
521 if (!locManagerSelected)
522 {
523 EditorGUILayout.LabelField(locA.Key, GUILayout.Width(100));
524
525 EditorGUILayout.LabelField("Text:", GUILayout.Width(100));
526 locA.Text = EditorGUILayout.TextArea(locA.Text, GUILayout.MinWidth(100));
527 }
528 else
529 {
530 EditorGUILayout.LabelField("Key:", GUILayout.Width(45));
531
532 locA.Key = EditorGUILayout.TextField(locA.Key, GUILayout.MaxWidth(100), GUILayout.MinWidth(30));
533 EditorGUILayout.LabelField("Category:", GUILayout.Width(75));
534 locA.Category = EditorGUILayout.Popup(locA.Category, locAvailableCategories.ToArray());
535 if (GUILayout.Button("-", GUILayout.Width(30)))
536 {
537 localizationElements.Remove(locA);
538 return;
539 }
540 }
541
542 EditorGUILayout.EndHorizontal();
543 EditorGUIUtility.labelWidth += 100;
544 c++;
545 }
546
547 EditorGUILayout.EndScrollView();
548 }
549
550 GUILayout.EndVertical();
551
552 #endregion
553
554 EditorGUI.indentLevel--;
555 }
556
557
558 #region LayoutShortcuts
559
560 private void pDrawLabel(string text, bool bold = false)
561 {
562 if (bold)
563 {
564 var add = "<b>";
565 add += text + "</b>";
566 text = add;
567 }
568
569 var style = new GUIStyle();
570 style.richText = true;
571 style.normal.textColor = Color.white;
572 EditorGUILayout.LabelField(text, style);
573 }
574
575 private void pDrawSpace(float space = 10)
576 {
577 GUILayout.Space(space);
578 }
579
580 #endregion
581
582 private static void Loc_ErrorDebug(string msg)
583 {
584 EditorUtility.DisplayDialog("Error", msg, "OK");
585 }
586
587 private static void Loc_MessageDebug(string msg)
588 {
589 EditorUtility.DisplayDialog("Info", msg, "OK");
590 }
591}
592#endif
System.IO.FileMode FileMode
Definition: AssetLoader.cs:14
UnityEngine.Color Color
Definition: TestScript.cs:32
static string GENERAL_NewLineSymbol
static string GENERAL_DelimiterSymbol_Key
static string GENERAL_DelimiterSymbol_Category