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: