Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions UoFiddler/Forms/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using UoFiddler.Controls.Classes;
using UoFiddler.Properties;
using UoFiddler.Controls.Plugin;
using UoFiddler.Localization;

namespace UoFiddler.Forms
{
Expand Down Expand Up @@ -52,6 +53,12 @@ public MainForm(ILogger<MainForm> logger)
_log = logger;
InitializeComponent();

// 调试: 打印Form名称
Console.WriteLine($"[DEBUG] MainForm.Name = '{this.Name}'");

// 应用本地化
LocalizationService.LocalizeForm(this);

darkModeMenuItem.Checked = AppSettings.DarkMode;

if (AppSettings.DarkMode)
Expand Down
48 changes: 48 additions & 0 deletions UoFiddler/Localization/Dictionaries/zh-CN.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"version": "4.24.0",
"language": "zh-CN",
"description": "UOFiddler 简体中文汉化包",
"Forms": {
"MainForm": {
"Title": "UOFiddler",
"Tabs": {
"StartTab": "开始",
"MultisTab": "多重组件",
"AnimationTab": "动画",
"ItemsTab": "物品",
"LandTilesTab": "地形图块",
"TextureTab": "纹理",
"GumpsTab": "Gump界面",
"SoundsTab": "音效",
"HuesTab": "色调",
"FontsTab": "字体",
"ClilocTab": "本地化字符串",
"MapTab": "地图",
"LightTab": "光照",
"SpeechTab": "语音",
"SkillsTab": "技能",
"AnimDataTab": "动画数据",
"MultiMapTab": "多重地图/位面",
"DressTab": "装扮",
"TileDataTab": "图块数据",
"RadarColTab": "雷达颜色",
"SkillGrpTab": "技能组",
"VerdataTab": "Verdata 补丁"
},
"Menus": {
"SettingsMenu": "设置",
"AlwaysOnTopMenuitem": "始终置顶",
"darkModeMenuItem": "暗黑模式",
"OptionsMenuItem": "选项...",
"PathSettingsMenuItem": "路径设置...",
"reloadFilesMenuItem": "重新加载文件",
"toolStripDropDownButtonView": "视图",
"ExternToolsDropDown": "外部工具",
"toolStripMenuItemManageTools": "管理...",
"toolStripDropDownButtonPlugins": "插件",
"ToolStripMenuItemHelp": "帮助",
"ToolStripMenuItemAbout": "关于"
}
}
}
}
26 changes: 26 additions & 0 deletions UoFiddler/Localization/LocalizationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Windows.Forms;

namespace UoFiddler.Localization
{
/// <summary>
/// 本地化扩展方法
/// </summary>
public static class LocalizationExtensions
{
/// <summary>
/// 为Form启用本地化
/// </summary>
public static void ApplyLocalization(this Form form)
{
LocalizationService.LocalizeForm(form);
}

/// <summary>
/// 获取本地化字符串
/// </summary>
public static string GetLocalized(this string key)
{
return LocalizationService.GetString(key) ?? key;
}
}
}
204 changes: 204 additions & 0 deletions UoFiddler/Localization/LocalizationService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace UoFiddler.Localization
{
/// <summary>
/// 本地化服务 - 管理UI控件的多语言翻译
/// </summary>
public static class LocalizationService
{
private static StringDictionary? _currentDictionary;
private static string _dictionariesPath = "";
private static string _currentLanguage = "en-US";

/// <summary>
/// 初始化本地化服务
/// </summary>
public static void Initialize(string dictionariesPath)
{
_dictionariesPath = dictionariesPath;
Console.WriteLine($"[LocalizationService] ========================================");
Console.WriteLine($"[LocalizationService] 初始化本地化服务");
Console.WriteLine($"[LocalizationService] 字典路径: {_dictionariesPath}");
Console.WriteLine($"[LocalizationService] 路径是否存在: {Directory.Exists(_dictionariesPath)}");
Console.WriteLine($"[LocalizationService] ========================================");
}

/// <summary>
/// 设置当前语言并加载对应字典
/// </summary>
public static void SetLanguage(string languageCode)
{
_currentLanguage = languageCode;
_currentDictionary = new StringDictionary(languageCode);

string dictionaryFile = Path.Combine(_dictionariesPath, $"{languageCode}.json");
Console.WriteLine($"[LocalizationService] 设置语言: {languageCode}");
Console.WriteLine($"[LocalizationService] 字典文件: {dictionaryFile}");
Console.WriteLine($"[LocalizationService] 文件是否存在: {File.Exists(dictionaryFile)}");

_currentDictionary.LoadFromFile(dictionaryFile);

Console.WriteLine($"[LocalizationService] 字典加载完成");
}

/// <summary>
/// 获取翻译字符串
/// </summary>
public static string? GetString(string key)
{
return _currentDictionary?.GetString(key);
}

/// <summary>
/// 对整个Form进行本地化处理
/// </summary>
public static void LocalizeForm(Form form)
{
if (_currentDictionary == null)
{
Console.WriteLine("[LocalizationService] 字典未初始化");
return;
}

try
{
Console.WriteLine($"[LocalizationService] 开始本地化Form: {form.Name}");

// 本地化Form标题
string? formTitle = GetString($"Forms.{form.Name}.Title");
if (!string.IsNullOrEmpty(formTitle))
{
form.Text = formTitle;
Console.WriteLine($"[LocalizationService] Form标题已本地化: {formTitle}");
}

// 递归本地化所有控件
LocalizeControls(form.Controls, form.Name);

// 本地化菜单栏
if (form.MainMenuStrip != null)
{
Console.WriteLine($"[LocalizationService] 检测到MainMenuStrip,开始本地化菜单");
LocalizeMenuStrip(form.MainMenuStrip, form.Name);
}
else
{
Console.WriteLine($"[LocalizationService] 警告: Form没有MainMenuStrip");
}
}
catch (Exception ex)
{
Console.WriteLine($"[LocalizationService] 本地化Form失败: {ex.Message}\n{ex.StackTrace}");
}
}

/// <summary>
/// 本地化菜单条
/// </summary>
private static void LocalizeMenuStrip(MenuStrip menuStrip, string formName)
{
foreach (ToolStripMenuItem item in menuStrip.Items.OfType<ToolStripMenuItem>())
{
LocalizeMenuStripItem(item, formName);
}
}

/// <summary>
/// 递归本地化菜单项
/// </summary>
private static void LocalizeMenuStripItem(ToolStripMenuItem menuItem, string formName)
{
if (!string.IsNullOrEmpty(menuItem.Name))
{
string? localizedText = GetString($"Forms.{formName}.Menus.{menuItem.Name}");
if (!string.IsNullOrEmpty(localizedText))
{
menuItem.Text = localizedText;
}
}

// 递归处理子菜单
foreach (ToolStripMenuItem subItem in menuItem.DropDownItems.OfType<ToolStripMenuItem>())
{
LocalizeMenuStripItem(subItem, formName);
}
}

/// <summary>
/// 递归本地化控件集合
/// </summary>
private static void LocalizeControls(Control.ControlCollection controls, string formName)
{
foreach (Control control in controls)
{
LocalizeControl(control, formName);

// 递归处理子控件
if (control.HasChildren)
{
LocalizeControls(control.Controls, formName);
}
}
}

/// <summary>
/// 本地化单个控件
/// </summary>
private static void LocalizeControl(Control control, string formName)
{
if (string.IsNullOrEmpty(control.Name) || control.Name.StartsWith("_"))
return;

// 按类型处理不同的控件
if (control is TabControl tabControl)
{
LocalizeTabPages(tabControl, formName);
}
else if (control is Button || control is CheckBox || control is Label ||
control is GroupBox || control is RadioButton)
{
// 普通文本控件
string? localizedText = GetString($"Forms.{formName}.{control.Name}.Text");
if (!string.IsNullOrEmpty(localizedText))
{
control.Text = localizedText;
}
}
}

/// <summary>
/// 本地化TabControl的标签页
/// </summary>
private static void LocalizeTabPages(TabControl tabControl, string formName)
{
Console.WriteLine($"[LocalizationService] 本地化TabControl,共{tabControl.TabPages.Count}个标签页");

foreach (TabPage tabPage in tabControl.TabPages)
{
if (!string.IsNullOrEmpty(tabPage.Name))
{
string key = $"Forms.{formName}.Tabs.{tabPage.Name}";
string? localizedText = GetString(key);
if (!string.IsNullOrEmpty(localizedText))
{
Console.WriteLine($"[LocalizationService] 标签页 {tabPage.Name} → {localizedText}");
tabPage.Text = localizedText;
}
}

// 本地化标签页内的控件
LocalizeControls(tabPage.Controls, formName);
}
}

/// <summary>
/// 获取当前语言代码
/// </summary>
public static string GetCurrentLanguage() => _currentLanguage;
}
}
79 changes: 79 additions & 0 deletions UoFiddler/Localization/StringDictionary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;

namespace UoFiddler.Localization
{
/// <summary>
/// 字符串字典 - 从JSON文件加载多语言字符串
/// </summary>
public class StringDictionary
{
private readonly Dictionary<string, string> _strings = new();
private readonly string _languageCode;

public StringDictionary(string languageCode)
{
_languageCode = languageCode;
}

/// <summary>
/// 从JSON文件加载字符串字典
/// </summary>
public void LoadFromFile(string filePath)
{
if (!File.Exists(filePath))
{
Console.WriteLine($"[LocalizationService] 字典文件不存在: {filePath}");
return;
}

try
{
string jsonContent = File.ReadAllText(filePath);
using (JsonDocument doc = JsonDocument.Parse(jsonContent))
{
FlattenJsonElement(doc.RootElement, "");
}
Console.WriteLine($"[LocalizationService] 已加载 {_languageCode} 字典,共 {_strings.Count} 个条目");
}
catch (Exception ex)
{
Console.WriteLine($"[LocalizationService] 加载字典失败: {ex.Message}");
}
}

/// <summary>
/// 递归展开JSON对象,生成点号路径的键值对
/// </summary>
private void FlattenJsonElement(JsonElement element, string prefix)
{
if (element.ValueKind == JsonValueKind.Object)
{
foreach (var property in element.EnumerateObject())
{
string key = string.IsNullOrEmpty(prefix) ? property.Name : $"{prefix}.{property.Name}";
FlattenJsonElement(property.Value, key);
}
}
else if (element.ValueKind == JsonValueKind.String)
{
_strings[prefix] = element.GetString() ?? "";
}
}

/// <summary>
/// 获取翻译字符串,如果不存在则返回null
/// </summary>
public string? GetString(string key)
{
return _strings.TryGetValue(key, out var value) ? value : null;
}

/// <summary>
/// 获取所有字符串条目数
/// </summary>
public int Count => _strings.Count;
}
}
Loading