2026-04-17 13:01:42 +08:00
using System ;
2025-09-25 11:11:19 +08:00
using System.Collections.Generic ;
2026-04-17 13:01:42 +08:00
using System.IO ;
2025-09-23 19:27:17 +08:00
using System.Text ;
2025-09-25 11:11:19 +08:00
using AlicizaX.Editor ;
2025-09-23 12:04:39 +08:00
using UnityEditor ;
using UnityEditorInternal ;
2026-04-17 13:01:42 +08:00
using UnityEngine ;
2025-09-23 12:04:39 +08:00
namespace AlicizaX.Localization.Editor
{
2026-04-17 13:01:42 +08:00
internal sealed class LocalizationSettingsProvider : EditorWindow
2025-09-23 12:04:39 +08:00
{
2026-04-17 13:01:42 +08:00
private const string WindowTitle = "Localization Settings" ;
2026-04-17 14:21:46 +08:00
private const string MenuPath = "AlicizaX/Localization/Open Localization Settings" ;
2026-04-17 13:01:42 +08:00
2025-09-23 12:04:39 +08:00
private SerializedObject _serializedObject ;
private SerializedProperty _languageTypes ;
2025-09-23 19:27:17 +08:00
private SerializedProperty _genLangaugeTypePath ;
2026-04-17 13:01:42 +08:00
private SerializedProperty _generateScriptCodeFirstConfig ;
private SerializedProperty _generateLanguageTypesNamespace ;
private SerializedProperty _generateLanguageTypesTemplate ;
private ReorderableList _languageList ;
private readonly List < string > _languagePopupOptions = new ( ) ;
private readonly List < string > _originalLanguages = new ( ) ;
private readonly List < GameLocaizationTable > _localizationTables = new ( ) ;
2025-09-23 12:04:39 +08:00
2026-04-17 13:01:42 +08:00
private Vector2 _scrollPosition ;
private bool _hasUnsavedChanges ;
2025-12-26 18:08:15 +08:00
2026-04-17 13:01:42 +08:00
[MenuItem(MenuPath)]
private static void Open ( )
2025-09-23 19:27:17 +08:00
{
2026-04-17 13:01:42 +08:00
LocalizationSettingsProvider window = GetWindow < LocalizationSettingsProvider > ( ) ;
window . titleContent = new GUIContent ( WindowTitle ) ;
window . minSize = new Vector2 ( 760f , 520f ) ;
window . Show ( ) ;
2025-09-23 19:27:17 +08:00
}
2025-09-23 12:04:39 +08:00
2026-04-17 13:01:42 +08:00
private void OnEnable ( )
2025-09-23 12:04:39 +08:00
{
InitGUI ( ) ;
2026-04-17 13:01:42 +08:00
RefreshLocalizationTables ( ) ;
}
private void OnFocus ( )
{
RefreshLocalizationTables ( ) ;
}
private void OnDisable ( )
{
_serializedObject ? . Dispose ( ) ;
_serializedObject = null ;
LocalizationConfiguration . Save ( ) ;
2025-09-23 12:04:39 +08:00
}
private void InitGUI ( )
{
2026-04-17 13:01:42 +08:00
LocalizationConfiguration setting = LocalizationConfiguration . Instance ;
2025-09-23 12:04:39 +08:00
_serializedObject ? . Dispose ( ) ;
_serializedObject = new SerializedObject ( setting ) ;
_languageTypes = _serializedObject . FindProperty ( "LanguageTypes" ) ;
2025-09-23 19:27:17 +08:00
_genLangaugeTypePath = _serializedObject . FindProperty ( "_genLangaugeTypePath" ) ;
2026-04-17 13:01:42 +08:00
_generateScriptCodeFirstConfig = _serializedObject . FindProperty ( "generateScriptCodeFirstConfig" ) ;
_generateLanguageTypesNamespace = _serializedObject . FindProperty ( "generateLanguageTypesNamespace" ) ;
_generateLanguageTypesTemplate = _serializedObject . FindProperty ( "generateLanguageTypesTemplate" ) ;
CaptureOriginalLanguages ( ) ;
BuildLanguageList ( ) ;
RefreshLanguagePopupOptions ( ) ;
}
2025-12-26 18:08:15 +08:00
2026-04-17 13:01:42 +08:00
private void CaptureOriginalLanguages ( )
{
2025-12-26 18:08:15 +08:00
_originalLanguages . Clear ( ) ;
2026-04-17 13:01:42 +08:00
if ( _languageTypes = = null )
{
return ;
}
2025-12-26 18:08:15 +08:00
for ( int i = 0 ; i < _languageTypes . arraySize ; i + + )
{
_originalLanguages . Add ( _languageTypes . GetArrayElementAtIndex ( i ) . stringValue ) ;
}
2026-04-17 13:01:42 +08:00
}
2025-12-26 18:08:15 +08:00
2026-04-17 13:01:42 +08:00
private void BuildLanguageList ( )
{
2025-09-23 12:04:39 +08:00
_languageList = new ReorderableList ( _serializedObject , _languageTypes ,
2025-09-25 11:11:19 +08:00
draggable : false ,
2025-09-23 12:04:39 +08:00
displayHeader : true ,
displayAddButton : true ,
displayRemoveButton : true ) ;
2025-09-23 19:27:17 +08:00
_languageList . drawHeaderCallback = rect = > { EditorGUI . LabelField ( rect , "Language Types" ) ; } ;
2025-09-23 12:04:39 +08:00
_languageList . drawElementCallback = ( rect , index , isActive , isFocused ) = >
{
2026-04-17 13:01:42 +08:00
SerializedProperty element = _languageTypes . GetArrayElementAtIndex ( index ) ;
rect . y + = 2f ;
2025-09-23 12:04:39 +08:00
2026-04-17 13:01:42 +08:00
bool isBuiltInLanguage = index < 2 ;
using ( new EditorGUI . DisabledGroupScope ( isBuiltInLanguage ) )
2025-09-25 11:11:19 +08:00
{
2025-12-26 18:08:15 +08:00
EditorGUI . BeginChangeCheck ( ) ;
string newValue = EditorGUI . TextField (
2025-09-25 11:11:19 +08:00
new Rect ( rect . x , rect . y , rect . width , EditorGUIUtility . singleLineHeight ) ,
element . stringValue ) ;
2025-12-26 18:08:15 +08:00
if ( EditorGUI . EndChangeCheck ( ) )
{
element . stringValue = newValue ;
_hasUnsavedChanges = true ;
}
2025-09-25 11:11:19 +08:00
}
2025-09-23 12:04:39 +08:00
} ;
2025-09-25 11:11:19 +08:00
2026-04-17 13:01:42 +08:00
_languageList . onCanRemoveCallback = list = > list . index > = 2 ;
2025-12-26 18:08:15 +08:00
_languageList . onAddCallback = list = >
{
int newIndex = _languageTypes . arraySize ;
_languageTypes . InsertArrayElementAtIndex ( newIndex ) ;
2026-04-17 13:01:42 +08:00
SerializedProperty newElement = _languageTypes . GetArrayElementAtIndex ( newIndex ) ;
2025-12-26 18:08:15 +08:00
newElement . stringValue = "NewLanguage" ;
_hasUnsavedChanges = true ;
} ;
_languageList . onRemoveCallback = list = >
{
if ( list . index < 2 )
{
EditorUtility . DisplayDialog ( "Cannot Remove" , "The first two languages (ChineseSimplified and English) cannot be removed." , "OK" ) ;
return ;
}
_languageTypes . DeleteArrayElementAtIndex ( list . index ) ;
_hasUnsavedChanges = true ;
} ;
2026-04-17 13:01:42 +08:00
}
2025-12-26 18:08:15 +08:00
2026-04-17 13:01:42 +08:00
private void RefreshLanguagePopupOptions ( )
{
_languagePopupOptions . Clear ( ) ;
IReadOnlyList < string > languageNames = LocalizationConfiguration . Instance . LanguageTypeNames ;
for ( int i = 0 ; i < languageNames . Count ; i + + )
2025-09-25 11:11:19 +08:00
{
2026-04-17 13:01:42 +08:00
string name = languageNames [ i ] . Or ( "Unknown" ) ;
_languagePopupOptions . Add ( name ) ;
}
}
private void RefreshLocalizationTables ( )
{
_localizationTables . Clear ( ) ;
string [ ] guids = AssetDatabase . FindAssets ( "t:GameLocaizationTable" ) ;
for ( int i = 0 ; i < guids . Length ; i + + )
{
string assetPath = AssetDatabase . GUIDToAssetPath ( guids [ i ] ) ;
GameLocaizationTable table = AssetDatabase . LoadAssetAtPath < GameLocaizationTable > ( assetPath ) ;
if ( table ! = null )
2025-09-25 11:11:19 +08:00
{
2026-04-17 13:01:42 +08:00
_localizationTables . Add ( table ) ;
2025-09-25 11:11:19 +08:00
}
}
2025-09-23 12:04:39 +08:00
}
2026-04-17 13:01:42 +08:00
private void OnGUI ( )
2025-09-23 12:04:39 +08:00
{
if ( _serializedObject = = null | | ! _serializedObject . targetObject )
{
InitGUI ( ) ;
}
_serializedObject . Update ( ) ;
2026-04-17 13:01:42 +08:00
RefreshLanguagePopupOptions ( ) ;
2025-09-25 11:11:19 +08:00
2026-04-17 13:01:42 +08:00
EditorGUILayout . Space ( ) ;
_scrollPosition = EditorGUILayout . BeginScrollView ( _scrollPosition ) ;
2025-09-23 12:04:39 +08:00
2026-04-17 13:01:42 +08:00
DrawLanguageTypesSection ( ) ;
EditorGUILayout . Space ( 8f ) ;
DrawLanguageTypesGenerateSection ( ) ;
EditorGUILayout . Space ( 8f ) ;
DrawLocalizationTablesSection ( ) ;
2025-09-23 12:04:39 +08:00
2026-04-17 13:01:42 +08:00
EditorGUILayout . EndScrollView ( ) ;
if ( _serializedObject . ApplyModifiedProperties ( ) )
2025-09-23 12:04:39 +08:00
{
LocalizationConfiguration . Save ( ) ;
}
2026-04-17 13:01:42 +08:00
}
private void DrawLanguageTypesSection ( )
{
using ( new EditorDrawing . BorderBoxScope ( new GUIContent ( "Language Types" ) , roundedBox : false ) )
{
_languageList . DoLayoutList ( ) ;
EditorGUILayout . Space ( 10f ) ;
EditorGUILayout . BeginHorizontal ( ) ;
GUILayout . FlexibleSpace ( ) ;
using ( new EditorGUI . DisabledGroupScope ( ! _hasUnsavedChanges ) )
{
if ( GUILayout . Button ( "Save Language Changes" , GUILayout . Width ( 200f ) , GUILayout . Height ( 30f ) ) )
{
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 DrawLanguageTypesGenerateSection ( )
{
using ( new EditorDrawing . BorderBoxScope ( new GUIContent ( "Generate LanguageTypes" ) , roundedBox : false ) )
{
EditorGUILayout . PropertyField ( _genLangaugeTypePath , new GUIContent ( "File Path" ) ) ;
EditorGUILayout . PropertyField ( _generateLanguageTypesNamespace , new GUIContent ( "Namespace" ) ) ;
EditorDrawing . DrawStringSelectPopup (
new GUIContent ( "生成多语言Key索引文件时的注释首选语言" ) ,
new GUIContent ( "None" ) ,
_languagePopupOptions . ToArray ( ) ,
_generateScriptCodeFirstConfig . stringValue ,
selected = >
{
_generateScriptCodeFirstConfig . stringValue = selected ;
_serializedObject . ApplyModifiedProperties ( ) ;
LocalizationConfiguration . Save ( ) ;
} ) ;
EditorGUILayout . LabelField ( "Template" , EditorStyles . boldLabel ) ;
EditorGUILayout . HelpBox ( "Use placeholders: {NAMESPACE_START}, {NAMESPACE_END}, {LANGUAGE_CONSTANTS}, {LANGUAGE_LIST}" , MessageType . None ) ;
2025-12-26 18:08:15 +08:00
2026-04-17 13:01:42 +08:00
EditorGUI . BeginChangeCheck ( ) ;
string template = EditorGUILayout . TextArea ( _generateLanguageTypesTemplate . stringValue , GUILayout . MinHeight ( 240f ) ) ;
if ( EditorGUI . EndChangeCheck ( ) )
{
_generateLanguageTypesTemplate . stringValue = template ;
}
EditorGUILayout . BeginHorizontal ( ) ;
GUILayout . FlexibleSpace ( ) ;
if ( GUILayout . Button ( "Reset Template" , GUILayout . Width ( 140f ) ) )
{
_generateLanguageTypesTemplate . stringValue = LocalizationConfiguration . DefaultTemplate ;
}
if ( GUILayout . Button ( "Generate Language Types" , GUILayout . Width ( 180f ) ) )
{
RegenerateLanguageTypes ( ) ;
}
EditorGUILayout . EndHorizontal ( ) ;
}
}
2025-12-26 18:08:15 +08:00
2026-04-17 13:01:42 +08:00
private void DrawLocalizationTablesSection ( )
{
using ( new EditorDrawing . BorderBoxScope ( new GUIContent ( "LocalizationTable" ) , roundedBox : false ) )
2025-12-26 18:08:15 +08:00
{
2026-04-17 13:01:42 +08:00
if ( GUILayout . Button ( "Refresh LocalizationTable List" , GUILayout . Width ( 220f ) ) )
2025-12-26 18:08:15 +08:00
{
2026-04-17 13:01:42 +08:00
RefreshLocalizationTables ( ) ;
}
EditorGUILayout . Space ( 4f ) ;
if ( _localizationTables . Count = = 0 )
{
EditorGUILayout . HelpBox ( "No LocalizationTable assets found in the project." , MessageType . Info ) ;
return ;
}
for ( int i = 0 ; i < _localizationTables . Count ; i + + )
{
DrawLocalizationTableEntry ( _localizationTables [ i ] , i ) ;
if ( i < _localizationTables . Count - 1 )
{
EditorGUILayout . Space ( 6f ) ;
}
2025-12-26 18:08:15 +08:00
}
}
2026-04-17 13:01:42 +08:00
}
2025-12-26 18:08:15 +08:00
2026-04-17 13:01:42 +08:00
private void DrawLocalizationTableEntry ( GameLocaizationTable table , int index )
{
SerializedObject tableSerializedObject = new SerializedObject ( table ) ;
SerializedProperty pathProperty = tableSerializedObject . FindProperty ( "GenerateScriptCodePath" ) ;
SerializedProperty namespaceProperty = tableSerializedObject . FindProperty ( "GenerateScriptCodeNamespace" ) ;
2025-12-26 18:08:15 +08:00
2026-04-17 13:01:42 +08:00
using ( new EditorDrawing . BorderBoxScope ( new GUIContent ( $"LocalizationTable {index + 1}" ) , roundedBox : false ) )
2025-12-26 18:08:15 +08:00
{
2026-04-17 13:01:42 +08:00
using ( new EditorGUI . DisabledGroupScope ( true ) )
{
EditorGUILayout . ObjectField ( "Table" , table , typeof ( GameLocaizationTable ) , false ) ;
}
tableSerializedObject . Update ( ) ;
EditorGUILayout . PropertyField ( pathProperty , new GUIContent ( "Gen Code Path" ) ) ;
EditorGUILayout . PropertyField ( namespaceProperty , new GUIContent ( "Namespace" ) ) ;
EditorGUILayout . BeginHorizontal ( ) ;
GUILayout . FlexibleSpace ( ) ;
if ( GUILayout . Button ( "Gen Code" , GUILayout . Width ( 120f ) ) )
{
tableSerializedObject . ApplyModifiedProperties ( ) ;
EditorUtility . SetDirty ( table ) ;
LocalizationWindowUtility . GenerateCode ( table ) ;
}
EditorGUILayout . EndHorizontal ( ) ;
if ( tableSerializedObject . ApplyModifiedProperties ( ) )
{
EditorUtility . SetDirty ( table ) ;
AssetDatabase . SaveAssets ( ) ;
}
2025-12-26 18:08:15 +08:00
}
2025-09-23 12:04:39 +08:00
}
2025-09-23 19:27:17 +08:00
private void RegenerateLanguageTypes ( )
{
2026-04-17 13:01:42 +08:00
string filePath = _genLangaugeTypePath . stringValue ;
if ( string . IsNullOrWhiteSpace ( filePath ) )
2025-10-13 20:18:01 +08:00
{
2026-04-17 13:01:42 +08:00
EditorUtility . DisplayDialog ( "Invalid Path" , "LanguageTypes output path cannot be empty." , "OK" ) ;
return ;
2025-10-13 20:18:01 +08:00
}
2026-04-17 13:01:42 +08:00
string directory = Path . GetDirectoryName ( filePath ) ;
if ( ! string . IsNullOrEmpty ( directory ) & & ! Directory . Exists ( directory ) )
2025-09-23 19:27:17 +08:00
{
2026-04-17 13:01:42 +08:00
Directory . CreateDirectory ( directory ) ;
2025-09-23 19:27:17 +08:00
}
2026-04-17 13:01:42 +08:00
string template = string . IsNullOrEmpty ( _generateLanguageTypesTemplate . stringValue )
? LocalizationConfiguration . DefaultTemplate
: _generateLanguageTypesTemplate . stringValue ;
string generatedCode = BuildLanguageTypesCode ( template , _generateLanguageTypesNamespace . stringValue , LocalizationConfiguration . Instance . LanguageTypeNames ) ;
File . WriteAllText ( filePath , generatedCode , Encoding . UTF8 ) ;
2025-09-23 19:27:17 +08:00
AssetDatabase . Refresh ( ) ;
}
2026-04-17 13:01:42 +08:00
private static string BuildLanguageTypesCode ( string template , string namespaceName , IReadOnlyList < string > languages )
2025-09-23 12:04:39 +08:00
{
2026-04-17 13:01:42 +08:00
StringBuilder constantsBuilder = new StringBuilder ( ) ;
StringBuilder listBuilder = new StringBuilder ( ) ;
for ( int i = 0 ; i < languages . Count ; i + + )
{
string languageName = languages [ i ] ;
constantsBuilder . AppendLine ( $" public const string {languageName} = \" { languageName } \ ";" ) ;
listBuilder . AppendLine ( $" \" { languageName } \ "," ) ;
}
string namespaceStart = string . IsNullOrWhiteSpace ( namespaceName )
? string . Empty
: $"namespace {namespaceName}{Environment.NewLine}{{{Environment.NewLine}" ;
string namespaceEnd = string . IsNullOrWhiteSpace ( namespaceName )
? string . Empty
: $"{Environment.NewLine}}}" ;
return template
. Replace ( "{NAMESPACE_START}" , namespaceStart )
. Replace ( "{NAMESPACE_END}" , namespaceEnd )
. Replace ( "{LANGUAGE_CONSTANTS}" , constantsBuilder . ToString ( ) . TrimEnd ( ) )
. Replace ( "{LANGUAGE_LIST}" , listBuilder . ToString ( ) . TrimEnd ( ) ) ;
2025-09-23 12:04:39 +08:00
}
2025-12-26 18:08:15 +08:00
private void ApplyLanguageChanges ( )
{
List < string > currentLanguages = new List < string > ( ) ;
for ( int i = 0 ; i < _languageTypes . arraySize ; i + + )
{
currentLanguages . Add ( _languageTypes . GetArrayElementAtIndex ( i ) . stringValue ) ;
}
List < string > addedLanguages = new List < string > ( ) ;
List < string > removedLanguages = new List < string > ( ) ;
2026-04-17 13:01:42 +08:00
Dictionary < string , string > renamedLanguages = new Dictionary < string , string > ( ) ;
2025-12-26 18:08:15 +08:00
2026-04-17 13:01:42 +08:00
foreach ( string lang in currentLanguages )
2025-12-26 18:08:15 +08:00
{
if ( ! _originalLanguages . Contains ( lang ) )
{
addedLanguages . Add ( lang ) ;
}
}
2026-04-17 13:01:42 +08:00
foreach ( string lang in _originalLanguages )
2025-12-26 18:08:15 +08:00
{
if ( ! currentLanguages . Contains ( lang ) )
{
removedLanguages . Add ( lang ) ;
}
}
for ( int i = 0 ; i < Mathf . Min ( _originalLanguages . Count , currentLanguages . Count ) ; i + + )
{
if ( _originalLanguages [ i ] ! = currentLanguages [ i ] )
{
if ( ! addedLanguages . Contains ( currentLanguages [ i ] ) & & ! removedLanguages . Contains ( _originalLanguages [ i ] ) )
{
renamedLanguages [ _originalLanguages [ i ] ] = currentLanguages [ i ] ;
}
}
}
string [ ] guids = AssetDatabase . FindAssets ( "t:GameLocaizationTable" ) ;
int tablesUpdated = 0 ;
foreach ( string guid in guids )
{
string assetPath = AssetDatabase . GUIDToAssetPath ( guid ) ;
GameLocaizationTable table = AssetDatabase . LoadAssetAtPath < GameLocaizationTable > ( assetPath ) ;
if ( table = = null )
2026-04-17 13:01:42 +08:00
{
2025-12-26 18:08:15 +08:00
continue ;
2026-04-17 13:01:42 +08:00
}
2025-12-26 18:08:15 +08:00
bool tableModified = false ;
2026-04-17 13:01:42 +08:00
foreach ( KeyValuePair < string , string > rename in renamedLanguages )
2025-12-26 18:08:15 +08:00
{
LocalizationLanguage language = table . Languages . Find ( lang = > lang . LanguageName = = rename . Key ) ;
if ( language ! = null )
{
language . LanguageName = rename . Value ;
language . name = rename . Value ;
tableModified = true ;
}
}
2026-04-17 13:01:42 +08:00
foreach ( string newLang in addedLanguages )
2025-12-26 18:08:15 +08:00
{
if ( table . Languages . Exists ( lang = > lang . LanguageName = = newLang ) )
2026-04-17 13:01:42 +08:00
{
2025-12-26 18:08:15 +08:00
continue ;
2026-04-17 13:01:42 +08:00
}
2025-12-26 18:08:15 +08:00
LocalizationLanguage newLanguage = ScriptableObject . CreateInstance < LocalizationLanguage > ( ) ;
newLanguage . name = newLang ;
newLanguage . LanguageName = newLang ;
newLanguage . Strings = new List < LocalizationLanguage . LocalizationString > ( ) ;
2026-04-17 13:01:42 +08:00
foreach ( GameLocaizationTable . TableData section in table . TableSheet )
2025-12-26 18:08:15 +08:00
{
2026-04-17 13:01:42 +08:00
foreach ( GameLocaizationTable . SheetItem item in section . SectionSheet )
2025-12-26 18:08:15 +08:00
{
2026-04-17 13:01:42 +08:00
string sectionKey = section . SectionName . Replace ( " " , string . Empty ) ;
string itemKey = item . Key . Replace ( " " , string . Empty ) ;
2025-12-26 18:08:15 +08:00
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 ;
}
2026-04-17 13:01:42 +08:00
foreach ( string removedLang in removedLanguages )
2025-12-26 18:08:15 +08:00
{
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 ( ) ;
_originalLanguages . Clear ( ) ;
_originalLanguages . AddRange ( currentLanguages ) ;
_hasUnsavedChanges = false ;
2026-04-17 13:01:42 +08:00
RefreshLocalizationTables ( ) ;
2025-12-26 18:08:15 +08:00
if ( addedLanguages . Count > 0 )
2026-04-17 13:01:42 +08:00
{
2025-12-26 18:08:15 +08:00
Debug . Log ( $"Added {addedLanguages.Count} language(s) to {tablesUpdated} table(s): {string.Join(" , ", addedLanguages)}" ) ;
2026-04-17 13:01:42 +08:00
}
2025-12-26 18:08:15 +08:00
if ( removedLanguages . Count > 0 )
2026-04-17 13:01:42 +08:00
{
2025-12-26 18:08:15 +08:00
Debug . Log ( $"Removed {removedLanguages.Count} language(s) from {tablesUpdated} table(s): {string.Join(" , ", removedLanguages)}" ) ;
2026-04-17 13:01:42 +08:00
}
2025-09-23 12:04:39 +08:00
2026-04-17 13:01:42 +08:00
if ( renamedLanguages . Count > 0 )
2025-09-23 12:04:39 +08:00
{
2026-04-17 13:01:42 +08:00
Debug . Log ( $"Renamed {renamedLanguages.Count} language(s) in {tablesUpdated} table(s)" ) ;
2025-09-23 12:04:39 +08:00
}
2025-09-23 19:27:17 +08:00
2026-04-17 13:01:42 +08:00
EditorUtility . DisplayDialog ( "Success" , $"Language changes applied to {tablesUpdated} GameLocalizationTable(s)." , "OK" ) ;
2025-09-23 12:04:39 +08:00
}
}
}