From 80d3a482b77520f2018673cc24c9b4e0bcfb0056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=80=9D=E6=B5=B7?= <1464576565@qq.com> Date: Fri, 26 Dec 2025 18:08:15 +0800 Subject: [PATCH] fix --- .../LocalizationSettingsProvider.cs | 212 +++++++++++++++++- 1 file changed, 211 insertions(+), 1 deletion(-) diff --git a/Editor/Localization/LocalizationSettingsProvider.cs b/Editor/Localization/LocalizationSettingsProvider.cs index 667d47a..a21c447 100644 --- a/Editor/Localization/LocalizationSettingsProvider.cs +++ b/Editor/Localization/LocalizationSettingsProvider.cs @@ -17,6 +17,10 @@ namespace AlicizaX.Localization.Editor private SerializedProperty generateScriptCodeFirstConfig; private List popConfig = new List(); + // Track original state for comparison + private List _originalLanguages = new List(); + private bool _hasUnsavedChanges = false; + public LocalizationSettingsProvider() : base("Project/Localization Settings", SettingsScope.Project) { } @@ -34,6 +38,14 @@ namespace AlicizaX.Localization.Editor _languageTypes = _serializedObject.FindProperty("LanguageTypes"); _genLangaugeTypePath = _serializedObject.FindProperty("_genLangaugeTypePath"); generateScriptCodeFirstConfig = _serializedObject.FindProperty("generateScriptCodeFirstConfig"); + + // Store original language list + _originalLanguages.Clear(); + for (int i = 0; i < _languageTypes.arraySize; i++) + { + _originalLanguages.Add(_languageTypes.GetArrayElementAtIndex(i).stringValue); + } + // 自定义 ReorderableList _languageList = new ReorderableList(_serializedObject, _languageTypes, draggable: false, @@ -58,9 +70,15 @@ namespace AlicizaX.Localization.Editor } else { - element.stringValue = EditorGUI.TextField( + EditorGUI.BeginChangeCheck(); + string newValue = EditorGUI.TextField( new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element.stringValue); + if (EditorGUI.EndChangeCheck()) + { + element.stringValue = newValue; + _hasUnsavedChanges = true; + } } }; @@ -69,6 +87,31 @@ namespace AlicizaX.Localization.Editor { return list.index >= 2; // 只有索引 >=2 的项才能删除 }; + + // Hook for when a language is added + _languageList.onAddCallback = list => + { + int newIndex = _languageTypes.arraySize; + _languageTypes.InsertArrayElementAtIndex(newIndex); + var newElement = _languageTypes.GetArrayElementAtIndex(newIndex); + newElement.stringValue = "NewLanguage"; + _hasUnsavedChanges = true; + }; + + // Hook for when a language is removed + _languageList.onRemoveCallback = list => + { + if (list.index < 2) + { + EditorUtility.DisplayDialog("Cannot Remove", "The first two languages (ChineseSimplified and English) cannot be removed.", "OK"); + return; + } + + // Just remove from the list, no immediate sync + _languageTypes.DeleteArrayElementAtIndex(list.index); + _hasUnsavedChanges = true; + }; + popConfig.Clear(); if (setting.LanguageTypeNames.Count > 0) { @@ -110,6 +153,27 @@ namespace AlicizaX.Localization.Editor _serializedObject.ApplyModifiedProperties(); LocalizationConfiguration.Save(); } + + // Add Save button + EditorGUILayout.Space(10); + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + + using (new EditorGUI.DisabledGroupScope(!_hasUnsavedChanges)) + { + if (GUILayout.Button("Save Language Changes", GUILayout.Width(200), GUILayout.Height(30))) + { + ApplyLanguageChanges(); + } + } + + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); + + if (_hasUnsavedChanges) + { + EditorGUILayout.HelpBox("You have unsaved language changes. Click 'Save Language Changes' to apply them to all GameLocalizationTable assets.", MessageType.Warning); + } } private void RegenerateLanguageTypes() @@ -172,6 +236,152 @@ namespace AlicizaX.Localization.Editor LocalizationConfiguration.Save(); } + private void ApplyLanguageChanges() + { + // Get current language list + List currentLanguages = new List(); + for (int i = 0; i < _languageTypes.arraySize; i++) + { + currentLanguages.Add(_languageTypes.GetArrayElementAtIndex(i).stringValue); + } + + // Detect changes + List addedLanguages = new List(); + List removedLanguages = new List(); + Dictionary renamedLanguages = new Dictionary(); // old -> new + + // Find added languages + foreach (var lang in currentLanguages) + { + if (!_originalLanguages.Contains(lang)) + { + addedLanguages.Add(lang); + } + } + + // Find removed languages + foreach (var lang in _originalLanguages) + { + if (!currentLanguages.Contains(lang)) + { + removedLanguages.Add(lang); + } + } + + // Detect renames (same index, different name) + for (int i = 0; i < Mathf.Min(_originalLanguages.Count, currentLanguages.Count); i++) + { + if (_originalLanguages[i] != currentLanguages[i]) + { + // Check if this is a rename (not an add/remove) + if (!addedLanguages.Contains(currentLanguages[i]) && !removedLanguages.Contains(_originalLanguages[i])) + { + renamedLanguages[_originalLanguages[i]] = currentLanguages[i]; + } + } + } + + // Apply changes to all tables + string[] guids = AssetDatabase.FindAssets("t:GameLocaizationTable"); + int tablesUpdated = 0; + + foreach (string guid in guids) + { + string assetPath = AssetDatabase.GUIDToAssetPath(guid); + GameLocaizationTable table = AssetDatabase.LoadAssetAtPath(assetPath); + + if (table == null) + continue; + + bool tableModified = false; + + // Handle renames first + foreach (var rename in renamedLanguages) + { + LocalizationLanguage language = table.Languages.Find(lang => lang.LanguageName == rename.Key); + if (language != null) + { + language.LanguageName = rename.Value; + language.name = rename.Value; + tableModified = true; + } + } + + // Handle additions + foreach (var newLang in addedLanguages) + { + // Skip if already exists + if (table.Languages.Exists(lang => lang.LanguageName == newLang)) + continue; + + // Create new LocalizationLanguage asset + LocalizationLanguage newLanguage = ScriptableObject.CreateInstance(); + newLanguage.name = newLang; + newLanguage.LanguageName = newLang; + newLanguage.Strings = new List(); + + // Synchronize keys from existing table structure + foreach (var section in table.TableSheet) + { + foreach (var item in section.SectionSheet) + { + string sectionKey = section.SectionName.Replace(" ", ""); + string itemKey = item.Key.Replace(" ", ""); + string fullKey = sectionKey + "." + itemKey; + + newLanguage.Strings.Add(new LocalizationLanguage.LocalizationString + { + SectionId = section.Id, + EntryId = item.Id, + Key = fullKey, + Value = string.Empty + }); + } + } + + AssetDatabase.AddObjectToAsset(newLanguage, table); + table.Languages.Add(newLanguage); + tableModified = true; + } + + // Handle removals + foreach (var removedLang in removedLanguages) + { + LocalizationLanguage languageToDelete = table.Languages.Find(lang => lang.LanguageName == removedLang); + if (languageToDelete != null) + { + table.Languages.Remove(languageToDelete); + UnityEngine.Object.DestroyImmediate(languageToDelete, true); + tableModified = true; + } + } + + if (tableModified) + { + EditorUtility.SetDirty(table); + tablesUpdated++; + } + } + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + // Update original languages list + _originalLanguages.Clear(); + _originalLanguages.AddRange(currentLanguages); + _hasUnsavedChanges = false; + + // Log results + if (addedLanguages.Count > 0) + Debug.Log($"Added {addedLanguages.Count} language(s) to {tablesUpdated} table(s): {string.Join(", ", addedLanguages)}"); + if (removedLanguages.Count > 0) + Debug.Log($"Removed {removedLanguages.Count} language(s) from {tablesUpdated} table(s): {string.Join(", ", removedLanguages)}"); + if (renamedLanguages.Count > 0) + Debug.Log($"Renamed {renamedLanguages.Count} language(s) in {tablesUpdated} table(s)"); + + EditorUtility.DisplayDialog("Success", $"Language changes applied to {tablesUpdated} GameLocalizationTable(s).", "OK"); + } + static LocalizationSettingsProvider s_provider; [SettingsProvider]