From 461fd181910c2eea2ab8ecd2abf9ae7f56706855 Mon Sep 17 00:00:00 2001 From: Ding Yuntian <1491671119@qq.com> Date: Thu, 23 Apr 2026 19:49:00 +0800 Subject: [PATCH] =?UTF-8?q?refactor(localization):=20=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E5=8C=96=E4=B8=BA=20CSV=20=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E5=B9=B6=E6=94=AF=E6=8C=81=E5=A4=9A=E8=AF=AD=E8=A8=80=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/AssetRefs/ConstRef.cs | 2 - Assets/Scripts/Framework/Config/Character.cs | 27 ++- Assets/Scripts/Framework/Config/ConfigUtil.cs | 26 ++- Assets/Scripts/Framework/Config/Param.cs | 27 +++ Assets/Scripts/Framework/Config/Param.cs.meta | 11 ++ .../Framework/OtherKit/LocalizationKit.cs | 159 ++++++------------ Assets/StreamingAssets/Config/character.csv | 46 ++--- Assets/StreamingAssets/Config/params.csv | 9 + Assets/StreamingAssets/Config/params.csv.meta | 7 + 9 files changed, 181 insertions(+), 133 deletions(-) create mode 100644 Assets/Scripts/Framework/Config/Param.cs create mode 100644 Assets/Scripts/Framework/Config/Param.cs.meta create mode 100644 Assets/StreamingAssets/Config/params.csv create mode 100644 Assets/StreamingAssets/Config/params.csv.meta diff --git a/Assets/Scripts/AssetRefs/ConstRef.cs b/Assets/Scripts/AssetRefs/ConstRef.cs index 9042d2dcf..9980b77a9 100644 --- a/Assets/Scripts/AssetRefs/ConstRef.cs +++ b/Assets/Scripts/AssetRefs/ConstRef.cs @@ -36,8 +36,6 @@ namespace AibisDream.Utility public const string UITextTable = "UIText"; - public const string ActorNameTable = "ActorName"; - #endregion #region 资产 diff --git a/Assets/Scripts/Framework/Config/Character.cs b/Assets/Scripts/Framework/Config/Character.cs index a4dca311d..c04ccd301 100644 --- a/Assets/Scripts/Framework/Config/Character.cs +++ b/Assets/Scripts/Framework/Config/Character.cs @@ -1,4 +1,4 @@ -using AibisDream.Framework; +using AibisDream.Framework; namespace AibisDream.Kit { @@ -6,6 +6,8 @@ namespace AibisDream.Kit { public string Key { get; set; } public string Cn { get; set; } + public string En { get; set; } + public string Ja { get; set; } public string NameColor { get; set; } public string HeadPicPath { get; set; } public string VoicePath { get; set; } @@ -22,6 +24,8 @@ namespace AibisDream.Kit CharacterVo vo; vo.key = Key; vo.cn = Cn; + vo.en = En; + vo.ja = Ja; vo.nameColor = NameColor; vo.headPicPath = HeadPicPath; vo.voicePath = VoicePath; @@ -37,6 +41,8 @@ namespace AibisDream.Kit { public string key; public string cn; + public string en; + public string ja; public string nameColor; public string headPicPath; public string voicePath; @@ -58,14 +64,27 @@ namespace AibisDream.Kit } else { - // 人名能找到 - var entry = LocalizationKit.ActorTable[key]; - rawName = entry == null ? key : entry.LocalizedValue; + rawName = GetLocalizedNameByKind(LocalizationKit.CurrentLocaleKind); } return string.IsNullOrEmpty(nameColor) ? rawName : $"{rawName}"; } + private string GetLocalizedNameByKind(LocaleKind kind) + { + switch (kind) + { + case LocaleKind.En: + return string.IsNullOrWhiteSpace(en) ? key : en; + case LocaleKind.Ja: + if (!string.IsNullOrWhiteSpace(ja)) return ja; + return string.IsNullOrWhiteSpace(cn) ? key : cn; + case LocaleKind.Cn: + default: + return string.IsNullOrWhiteSpace(cn) ? key : cn; + } + } + public string VoicePath { get diff --git a/Assets/Scripts/Framework/Config/ConfigUtil.cs b/Assets/Scripts/Framework/Config/ConfigUtil.cs index b3cef2915..50372eeea 100644 --- a/Assets/Scripts/Framework/Config/ConfigUtil.cs +++ b/Assets/Scripts/Framework/Config/ConfigUtil.cs @@ -13,8 +13,10 @@ namespace AibisDream.Kit public class ConfigUtil : SingletonBase { private const string CharacterConfigPath = "/Config/character.csv"; + private const string ParamConfigPath = "/Config/params.csv"; private Dictionary _characters; + private Dictionary _params; /// /// 用于单例模式 @@ -39,12 +41,23 @@ namespace AibisDream.Kit public override void OnSingletonInit() { InitCharacterConfig(); + InitParamConfig(); } private void InitCharacterConfig() { var characterList = CsvUtil.ReadAsBean(Application.streamingAssetsPath + CharacterConfigPath); - _characters = characterList.ToDictionary(item => item.Key, item => item); + _characters = characterList + .Where(item => !string.IsNullOrWhiteSpace(item.Key)) + .ToDictionary(item => item.Key, item => item); + } + + private void InitParamConfig() + { + var paramList = CsvUtil.ReadAsBean(Application.streamingAssetsPath + ParamConfigPath); + _params = paramList + .Where(item => !string.IsNullOrWhiteSpace(item.Key)) + .ToDictionary(item => item.Key, item => item); } @@ -59,6 +72,17 @@ namespace AibisDream.Kit return _characters.TryGetValue(key, out character); } + /// + /// 按key获取参数本地化配置 + /// + /// key + /// 参数配置 + /// 是否能获取 + public bool TryGetParam(string key, out Param param) + { + return _params.TryGetValue(key, out param); + } + /// /// 按类型读取Json配置 /// diff --git a/Assets/Scripts/Framework/Config/Param.cs b/Assets/Scripts/Framework/Config/Param.cs new file mode 100644 index 000000000..021cfca82 --- /dev/null +++ b/Assets/Scripts/Framework/Config/Param.cs @@ -0,0 +1,27 @@ +using AibisDream.Framework; + +namespace AibisDream.Kit +{ + public class Param + { + public string Key { get; set; } + public string Cn { get; set; } + public string En { get; set; } + public string Ja { get; set; } + + public string LocalizeByKind(LocaleKind kind) + { + switch (kind) + { + case LocaleKind.En: + return string.IsNullOrWhiteSpace(En) ? Key : En; + case LocaleKind.Ja: + if (!string.IsNullOrWhiteSpace(Ja)) return Ja; + return string.IsNullOrWhiteSpace(Cn) ? Key : Cn; + case LocaleKind.Cn: + default: + return string.IsNullOrWhiteSpace(Cn) ? Key : Cn; + } + } + } +} diff --git a/Assets/Scripts/Framework/Config/Param.cs.meta b/Assets/Scripts/Framework/Config/Param.cs.meta new file mode 100644 index 000000000..3420c0a8f --- /dev/null +++ b/Assets/Scripts/Framework/Config/Param.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c12e0d2c486f4ea6a5d4f70878b6e7c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Framework/OtherKit/LocalizationKit.cs b/Assets/Scripts/Framework/OtherKit/LocalizationKit.cs index 81ab83f0e..0de3f1307 100644 --- a/Assets/Scripts/Framework/OtherKit/LocalizationKit.cs +++ b/Assets/Scripts/Framework/OtherKit/LocalizationKit.cs @@ -1,59 +1,83 @@ -using UnityEngine; +using AibisDream.Kit; +using UnityEngine; using UnityEngine.Localization; using UnityEngine.Localization.Settings; -using UnityEngine.Localization.Tables; #if UNITY_EDITOR using UnityEditor; #endif namespace AibisDream.Framework { + /// + /// csv 本地化列类别。集中声明"哪些 Locale 归到哪一列",csv 数据类按此枚举取字段。 + /// + public enum LocaleKind + { + Cn, + En, + Ja + } + public static class LocalizationKit { private const string LocalizationPrefix = "l10n."; - private const string ActorTableName = "ActorName"; - private const string ParamTableName = "Params"; - - private static LocalizationTable _paramTable; - - public static LocalizationTable ActorTable { get; private set; } + public static string CurrentLanguageCode { get; private set; } = "zh-Hans"; public static Locale CurrentLocale => LocalizationSettings.SelectedLocale; + /// + /// 把 LocaleCode 映射到 csv 列类别。集中在此一处,便于扩展(加新语言时修改这里 + LocaleKind 枚举 + 数据类字段)。 + /// + public static LocaleKind GetLocaleKind(string localeCode) + { + if (string.IsNullOrEmpty(localeCode)) return LocaleKind.Cn; + if (localeCode.StartsWith("en")) return LocaleKind.En; + if (localeCode.StartsWith("ja")) return LocaleKind.Ja; + return LocaleKind.Cn; + } + + public static LocaleKind CurrentLocaleKind => GetLocaleKind(CurrentLanguageCode); + static LocalizationKit() { #if UNITY_EDITOR EditorApplication.playModeStateChanged += OnPlayModeChanged; #else - _paramTable = new LocalizationTable(ParamTableName); - ActorTable = new LocalizationTable(ActorTableName); LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged; + RefreshCurrentLanguageCodeAsync(); #endif } private static void OnLocaleChanged(Locale locale) { + UpdateCurrentLanguageCode(locale); EnumEventSystem.Global.Send(SettingChangeEvent.LocaleChanged, locale); } + private static void UpdateCurrentLanguageCode(Locale locale) + { + if (locale != null) + { + CurrentLanguageCode = locale.Identifier.Code; + } + } + + private static async void RefreshCurrentLanguageCodeAsync() + { + await LocalizationSettings.InitializationOperation.Task; + UpdateCurrentLanguageCode(LocalizationSettings.SelectedLocale); + } + #if UNITY_EDITOR private static void OnPlayModeChanged(PlayModeStateChange playMode) { if (playMode == PlayModeStateChange.EnteredPlayMode) { - // 进入游戏模式的时候 - _paramTable?.Dispose(); - ActorTable?.Dispose(); - _paramTable = new LocalizationTable(ParamTableName); - ActorTable = new LocalizationTable(ActorTableName); LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged; + RefreshCurrentLanguageCodeAsync(); } else if (playMode == PlayModeStateChange.ExitingPlayMode) { - _paramTable?.Dispose(); - ActorTable?.Dispose(); - _paramTable = null; - ActorTable = null; LocalizationSettings.SelectedLocaleChanged -= OnLocaleChanged; } } @@ -81,33 +105,22 @@ namespace AibisDream.Framework /// 本地化参数 /// /// 参数名 - /// 本地化表 - /// - public static string LocalizeParam(string param, LocalizationTable table) - { - // 非本地化参数直接返回 - if (!param.StartsWith(LocalizationPrefix)) return param; - - var localizationKey = param[LocalizationPrefix.Length..]; - // 获取本地化值 - if (table.TryGetValue(localizationKey, out var value)) - { - return value.LocalizedValue; - } - - // 如果找不到,则使用原始值 - Debug.LogWarning($"Variable Key '{localizationKey}' not found in localization table."); - return localizationKey; - } - - /// - /// 本地化参数 - /// - /// /// public static string LocalizeParam(string param) { - return LocalizeParam(param, _paramTable); + // 非本地化参数直接返回 + if (string.IsNullOrEmpty(param)) return param; + if (!param.StartsWith(LocalizationPrefix)) return param; + + var localizationKey = param[LocalizationPrefix.Length..]; + if (ConfigUtil.Instance.TryGetParam(localizationKey, out var value)) + { + return value.LocalizeByKind(CurrentLocaleKind); + } + + // 如果找不到,则使用原始值 + Debug.LogWarning($"Variable Key '{localizationKey}' not found in params csv."); + return localizationKey; } public static string GetL10NParamKey(string key) @@ -125,64 +138,4 @@ namespace AibisDream.Framework await LocalizationSettings.InitializationOperation.Task; } } - - public class LocalizationTable - { - public string TableName { get; } - - private StringTable _stringTable; - private bool _isInitialized; - - public LocalizationTable(string tableName) - { - TableName = tableName; - Debug.Log($"开始初始化表格{tableName}"); - InitializeAsync(); - } - - private async void InitializeAsync() - { - // 等待本地化系统初始化完成 - await LocalizationSettings.InitializationOperation.Task; - - _stringTable = LocalizationSettings.StringDatabase.GetTable(TableName); - LocalizationSettings.SelectedLocaleChanged += OnLocaleChanged; - _isInitialized = true; - - Debug.Log($"表格{TableName}已成功加载"); - } - - public void Dispose() - { - if (_isInitialized) - { - LocalizationSettings.SelectedLocaleChanged -= OnLocaleChanged; - } - _stringTable = null; - _isInitialized = false; - } - - private void OnLocaleChanged(Locale locale) - { - if (_isInitialized) - { - _stringTable = LocalizationSettings.StringDatabase.GetTable(TableName); - } - } - - public StringTableEntry this[string key] => _isInitialized ? _stringTable?[key] : null; - - public bool TryGetValue(string key, out StringTableEntry value) - { - if (_isInitialized && _stringTable != null) - { - value = _stringTable.GetEntry(key); - return value != null; - } - value = null; - return false; - } - - public LocaleIdentifier? LocaleIdentifier => _isInitialized ? _stringTable?.LocaleIdentifier : null; - } } \ No newline at end of file diff --git a/Assets/StreamingAssets/Config/character.csv b/Assets/StreamingAssets/Config/character.csv index 47e1bd8c5..3579b2525 100644 --- a/Assets/StreamingAssets/Config/character.csv +++ b/Assets/StreamingAssets/Config/character.csv @@ -1,5 +1,5 @@ -通过key索引配置,中文名,,"显示位置,Default使用默认,Screen插线屏幕,OldBox基本对话框",人物角色(Player/MainActor/Aside),名称显示时的颜色,头像Pic路径,语音资源路径,气泡序号(默认0) -Key,Cn,,DialogViewType,Role,NameColor,HeadPicPath,VoicePath,BubbleIdx +通过key索引配置,中文名,英文名,"显示位置,Default使用默认,Screen插线屏幕,OldBox基本对话框",人物角色(Player/MainActor/Aside),名称显示时的颜色,头像Pic路径,语音资源路径,气泡序号(默认0) +Key,Cn,En,DialogViewType,Role,NameColor,HeadPicPath,VoicePath,BubbleIdx jg,警告,Warning,Default,MainActor,#7ae622,,, 门,门,Door,Default,MainActor,#7ae622,,, 矩形,黑暗,Darkness,Default,MainActor,#7ae622,,, @@ -10,45 +10,45 @@ peipei,佩佩,Peipei,Default,MainActor,#00FFFF,peipei_head,VO/voice_PP, 女孩,女孩,Girl,Default,MainActor,,,VO/voice_JJ, pp,佩佩,Peipei,Default,MainActor,#00FFFF,peipei_head,VO/voice_PP, ppm,佩佩,Peipei,Default,Aside,#00FFFF,peipei_head,VO/voice_PP, -me,路斯,Me,Default,Player,,me_head,VO/voice_ME, -bb,BB机,beeper,Default,Player,,me_head,, +me,路斯,Luth,Default,Player,,me_head,VO/voice_ME, +bb,BB机,Beeper,Default,Player,,me_head,, jj,姐姐,Sister,Default,MainActor,,me_head,VO/voice_JJ, jj?,柔和女声,???,Default,MainActor,,me_head,VO/voice_JJ, -hs,火山,Huoshan,Default,MainActor,#FFA800,peipei_head,VO/voice_HS, +hs,火山,Cal,Default,MainActor,#FFA800,peipei_head,VO/voice_HS, hs?,沙哑男声,???,Default,MainActor,#FFA800,peipei_head,VO/voice_HS, -yl,英理,Yingli,Default,MainActor,#4000FF,peipei_head,VO/voice_YL, +yl,英理,Ingrid,Default,MainActor,#4000FF,peipei_head,VO/voice_YL, ql?,02号调酒机体,Bartender,Default,MainActor,#00FFFF,peipei_head,VO/voice_YL, -ql,奇琳,Kirin,Default,MainActor,#00FFFF,peipei_head,VO/voice_YL, +ql,琪琳,Kilin,Default,MainActor,#00FFFF,peipei_head,VO/voice_YL, peipei_novoice,胆怯女声,Timid female voice,Default,Aside,#00FFFF,,VO/voice_PP,2 -yingli_novoice,英里,Stern female voice,Default,Aside,#FFCC00,,VO/voice_YL,1 -tutorial,教学,Teaching,Default,Aside,,,, +yingli_novoice,严厉女声,Stern female voice,Default,Aside,#FFCC00,,VO/voice_YL,1 +tutorial,教学,Tutorial,Default,Aside,,,, docter,儿科医生,Pediatrician,Default,Aside,#FFCC00,,, peipei_child,童年佩佩,Childhood Peipei,Default,Aside,#00FFFF,,VO/voice_PP, unknown,???,???,Default,Aside,#FFCC00,,, shitou,石头,Stone,Default,MainActor,,,VO/voice_shitou, Descent,Descent,Descent,Default,Aside,#FFCC00,,VO/voice_me, -e-assistant,电子助手,Electronic assistant,Default,Aside,#FFCC00,,VO/voice_me, +e-assistant,电子助手,Electronic Assistant,Default,Aside,#FFCC00,,VO/voice_me, Gotashi_unknow,戴纯金雕塑头的男人,Man with a pure gold sculpture head,Default,Aside,#FFCC00,,, Linking,连接中……,Connecting...,Screen,Aside,#E6A23C,,, Analysing,分析中,Analyzing...,Screen,Aside,#E6A23C,,, Error,错误警告,Error warning,Screen,Aside,#E6A23C,,, -UfModule,UnstableFusion
图像生成模块,UnstableFusion image generation module,Screen,Aside,#F56C6C,,, -EyeModule,HS9型
视觉模块,HS9 type visual module,Screen,Aside,#F56C6C,,, -EmoModule,通用型
情绪发生模块,Universal emotion generation module,Screen,Aside,#F56C6C,,, -MemModule,通用型
记忆模块,Universal memory module,Screen,Aside,#F56C6C,,, -LogicModule,MK1型
逻辑处理模块,MK1 type logic processing module,Screen,Aside,#F56C6C,,, -SpeakerModule,MK1型
表达模块,MK1 type expression module,Screen,Aside,#F56C6C,,, +UfModule,Unstable Fusion图像生成模块,Unstable Fusion Module,Screen,Aside,#F56C6C,,, +EyeModule,HS9型视觉模块,HS9 Visual Module,Screen,Aside,#F56C6C,,, +EmoModule,通用型情绪发生模块,Universal Emotion Generation Module,Screen,Aside,#F56C6C,,, +MemModule,通用型记忆模块,Universal Memory Module,Screen,Aside,#F56C6C,,, +LogicModule,MK1型逻辑处理模块,MK1 logic Processing Module,Screen,Aside,#F56C6C,,, +SpeakerModule,MK1型表达模块,MK1 Expression Module,Screen,Aside,#F56C6C,,, SaleModule,销售型
销售语言处理模块,Sales type sales language processing module,Screen,Aside,#F56C6C,,, -ChipModule,4R7型
色觉晶圆训练槽,4R7 type color perception wafer training slot,Screen,Aside,#F56C6C,,, +ChipModule,4R7型色觉晶圆训练槽,4R7 Color Perception Wafer Training Slot,Screen,Aside,#F56C6C,,, HivemindModule,未知型号
Hivemind通讯终端,Unknown type Hivemind communication terminal,Screen,Aside,#F56C6C,,, -HeartModule,C03UR型特配
涡轮增压动力模块,C03UR special turbocharged power module,Screen,Aside,#E6A23C,,, -LungModule,MK1型
气体处理模块,MK1 type gas processing module,Screen,Aside,#E6A23C,,, -LiverModule,MK1型
冷却液循环模块,MK1 type coolant circulation module,Screen,Aside,#E6A23C,,, -DigestModule,MK1型
物料处理模块,MK1 type material processing module,Screen,Aside,#E6A23C,,, +HeartModule,C03UR型特配涡轮增压动力模块,C03UR Special Turbocharged Power Module,Screen,Aside,#E6A23C,,, +LungModule,MK1型气体处理模块,MK1 Gas Processing Module,Screen,Aside,#E6A23C,,, +LiverModule,MK1型冷却液循环模块,MK1 Coolant Circulation Module,Screen,Aside,#E6A23C,,, +DigestModule,MK1型物料处理模块,MK1 Material Processing Module,Screen,Aside,#E6A23C,,, CenterText,,,CenterText,Aside,,,, CenterOption,,,CenterOption,Aside,,,, Task,,,Task,Aside,,,, TempText,,,Default,Aside,,,, -gotash?,,,Default,MainActor,,,VO/voice_GTS_broken, -classmate,,,Default,Aside,,,, +gotash?,???,???,Default,MainActor,,,VO/voice_GTS_broken, +classmate,同学,Classmate,Default,Aside,,,, jb,酒保,Bartender,Default,MainActor,,,, diff --git a/Assets/StreamingAssets/Config/params.csv b/Assets/StreamingAssets/Config/params.csv new file mode 100644 index 000000000..884ebb4dc --- /dev/null +++ b/Assets/StreamingAssets/Config/params.csv @@ -0,0 +1,9 @@ +键,中文,英文,日文 +Key,Cn,En,Ja +天空,天空,Sky, +海报,海报,Poster, +植物,植物,Plant, +朋友,朋友,Friend, +情绪,情绪,Emo, +记忆,记忆,Memory, +逻辑,逻辑,Logic, diff --git a/Assets/StreamingAssets/Config/params.csv.meta b/Assets/StreamingAssets/Config/params.csv.meta new file mode 100644 index 000000000..dd48c8466 --- /dev/null +++ b/Assets/StreamingAssets/Config/params.csv.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e721272cd05718a4d8872d0f3e3f5b8c +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: