I18n(多语言支持) - Natsukage/PostNamazu GitHub Wiki

PostNamazu 本地化系统迁移指南

概述

PostNamazu有一套简单的i18n系统,可以支持多语言切换。

  • 使用Attribute标记本地化字符串
  • 每个Module的本地化字符串在自己的文件中定义
  • 添加/删除Action无需修改其他文件
  • 自动发现和注册
  • 无需外部文件,全部编译进DLL

核心组件

1. LocalizationManager

主要的本地化管理器,自动处理所有标记的本地化字符串。

2. L类

提供简洁的访问方法:L.Get("key", args...)

3. LocalizedAttribute

用于标记本地化字符串的Attribute。

使用方法

对于Action/Module开发者

在您的Action类中定义本地化字符串:

namespace PostNamazu.Actions
{
    internal class YourAction : NamazuModule
    {
        // 使用内部类 + LocalizedAttribute
        [LocalizationProvider("YourAction")]
        private static class Localizations
        {
            [Localized("English text", "中文文本")]
            public static readonly string ErrorMessage;
            
            [Localized("Processing {0} items...", "正在处理 {0} 个项目...")]
            public static readonly string ProcessingMessage;
        }

        // 使用本地化字符串
        public void YourMethod()
        {
            // 不带参数
            throw new Exception(L.Get("YourAction/ErrorMessage"));
            
            // 带参数
            Log(L.Get("YourAction/ProcessingMessage", itemCount));
        }
    }
}

对于主程序开发者

核心本地化字符串已定义在 CoreLocalizations.cs 中:

// 使用核心本地化
PluginUI.Log(L.Get("PostNamazu/pluginInit"));

命名约定

  1. Provider名称:通常使用类名
  2. 字段名称:使用PascalCase(如 ErrorMessage
  3. 完整的KeyProvider/FieldName(如 Command/NoChannelError
  4. 核心本地化:使用 PostNamazu/ 前缀

最佳实践

  1. 组织结构:将相关的本地化字符串组织在一个内部类中
  2. 命名清晰:使用描述性的字段名
  3. 避免硬编码:所有用户可见的文本都应该本地化
  4. 参数化:使用 {0}, {1} 等占位符而不是字符串拼接

示例:完整的Action本地化

using PostNamazu.Attributes;
using PostNamazu.Common;
using PostNamazu.Common.Localization;

namespace PostNamazu.Actions
{
    internal class SampleAction : NamazuModule
    {
        [LocalizationProvider("SampleAction")]
        private static class Localizations
        {
            [Localized("Sample action executed successfully", "示例动作执行成功")]
            public static readonly string Success;
            
            [Localized("Invalid parameter: {0}", "无效参数:{0}")]
            public static readonly string InvalidParam;
            
            [Localized("Operation completed in {0}ms", "操作在 {0} 毫秒内完成")]
            public static readonly string CompletionTime;
        }

        [Command("sample")]
        public void ExecuteSample(string param)
        {
            CheckBeforeExecution(param);
            
            if (string.IsNullOrEmpty(param))
            {
                throw new Exception(L.Get("SampleAction/InvalidParam", "null"));
            }
            
            var startTime = DateTime.Now;
            // ... 执行操作 ...
            var elapsed = (DateTime.Now - startTime).TotalMilliseconds;
            
            PluginUI.Log(L.Get("SampleAction/Success"));
            PluginUI.Log(L.Get("SampleAction/CompletionTime", elapsed));
        }
    }
}

注意事项

  1. 本地化字符串在程序启动时自动注册,无需手动初始化
  2. 如果找不到对应的翻译,L.Get会返回 [key] 格式的字符串
  3. 语言切换会立即生效,无需重启程序
  4. 所有本地化定义都会编译进DLL,无需额外文件

总结

  • 开发者只需在自己的Action文件中定义本地化
  • 使用简洁的 L.Get() 方法访问
  • 无需修改任何其他文件