NextUI 国际化 (Localization) 指南

NextUI 提供了一套完整的国际化解决方案,支持即时语言切换(无需页面刷新),并为组件库内置了多语言翻译。

目录


快速开始

1. 初始化本地化系统

Program.cs 中初始化:

// 推荐方式:使用扩展方法
await WorkbenchLocaleExtensions.InitializeAsync("en-US", "zh-CN");

// 或者分步骤初始化
NextUI.Blazor.BlazorLocaleExtensions.AddBlazorLocales();
await NextUILocalizer.PreloadAsync("en-US", "zh-CN");

2. 在组件中使用

@inject INextUILocalizer L

<h1>@L["Menu.Settings"]</h1>
<p>@L["Common.PageNotFound"]</p>

3. 切换语言

@inject ILocaleState Locale

<button @onclick='() => Locale.SetCulture("zh-CN")'>中文</button>
<button @onclick='() => Locale.SetCulture("en-US")'>English</button>

架构概述

NextUI 使用多层、基于优先级的本地化系统:

┌─────────────────────────────────────────┐
│     应用层 Application (Priority: 10)   │  ← 你的应用(可覆盖任何翻译)
├─────────────────────────────────────────┤
│       NextUI.App 层 (Priority: 5)       │  ← 应用级组件翻译
├─────────────────────────────────────────┤
│      NextUI.Blazor 层 (Priority: 0)     │  ← 核心库组件翻译
└─────────────────────────────────────────┘

优先级规则:高优先级提供者可以覆盖低优先级提供者的翻译。

核心组件

组件 说明
NextUILocalizer 静态 API,用于访问翻译
INextUILocalizer 可注入服务,用于组件内使用
LocaleResourceManager 多提供者加载的中央管理器
ILocaleResourceProvider 自定义资源提供者接口
EmbeddedResourceProvider 从程序集嵌入资源加载 JSON
FileSystemLocaleProvider 从文件系统加载 JSON(支持写入)

JSON 资源文件

文件位置

将 JSON 文件放在 Resources/Locales/ 目录:

MyProject/
├── Resources/
│   └── Locales/
│       ├── en-US.json
│       ├── zh-CN.json
│       ├── zh-TW.json
│       ├── ja-JP.json
│       └── ar.json
└── MyProject.csproj

文件格式

{
  "Menu.Settings": "Settings",
  "Menu.About": "About",
  "Common.Save": "Save",
  "Common.Cancel": "Cancel"
}

项目配置

.csproj 中添加嵌入资源配置:

<ItemGroup>
  <EmbeddedResource Include="Resources/Locales/*.json"
    LogicalName="MyProject.Resources.Locales.%(Filename)%(Extension)" />
</ItemGroup>

注册资源提供者

// 创建扩展方法
public static class MyAppLocaleExtensions
{
    private static bool _initialized;

    public static void AddMyAppLocales(int priority = 10)
    {
        if (_initialized) return;
        _initialized = true;

        var provider = new EmbeddedResourceProvider(
            typeof(MyAppLocaleExtensions).Assembly,
            "MyProject.Resources.Locales",
            priority);

        NextUILocalizer.AddProvider(provider);
    }
}

核心接口

INextUILocalizer

主要的本地化服务接口:

public interface INextUILocalizer
{
    // 获取本地化字符串
    string this[string key] { get; }

    // 语言变更事件
    event Action Changed;
}

使用示例:

@inject INextUILocalizer L

<span>@L["Common.Loading"]</span>
<button title="@L["Button.Save"]">@L["Button.Save"]</button>

ILocaleState

管理当前语言状态:

public interface ILocaleState
{
    // 当前语言代码 (e.g., "zh-CN")
    string CultureName { get; }

    // 切换语言
    void SetCulture(string cultureName);

    // 语言变更事件
    event Action Changed;
}

NextUILocalizer 静态 API

// 获取翻译(当 DI 不可用时)
var text = NextUILocalizer.Get("Menu.Settings");

// 带回退值
var text = NextUILocalizer.Get("Menu.Settings", "Settings");

// 添加提供者
NextUILocalizer.AddProvider(provider);

// 预加载文化
await NextUILocalizer.PreloadAsync("en-US", "zh-CN");

多层翻译架构

层级分布

层级 翻译键前缀 说明
NextUI.Blazor Menu.*, Color_Name_*, Density.*, Inspector.*, Detail.*, Error.* 核心库组件
NextUI.App Playground.* 应用级组件
你的应用 Nav.*, Common.*, App.*, Panel.*, Scenario.*, Group.* 应用特定翻译

库组件内置翻译

NextUI.Blazor 内置翻译示例:

Menu.Back              = "Back" / "返回"
Menu.Home              = "Home" / "首页"
Menu.ThemeMode         = "Theme Appearance" / "主题外观"
Menu.Light             = "Light" / "浅色"
Menu.Dark              = "Dark" / "深色"
Color_Name_Blue        = "Blue" / "蓝色"
Density.Compact        = "Compact" / "紧凑"
Error.Title            = "Oops! An error occurred" / "糟糕!发生错误"

语言提供者配置

默认语言提供者

NextUI 默认支持 2 种语言:

public class DefaultLanguageProvider : ILanguageProvider
{
    public IReadOnlyList<LanguageOption> GetSupportedLanguages() => new[]
    {
        new LanguageOption("en-US", "English", "en"),
        new LanguageOption("zh-CN", "简体中文", "zh")
    };
}

自定义语言提供者

支持更多语言:

public class MyLanguageProvider : ILanguageProvider
{
    public IReadOnlyList<LanguageOption> GetSupportedLanguages() => new[]
    {
        new LanguageOption("en-US", "English", "en"),
        new LanguageOption("zh-CN", "简体中文", "zh"),
        new LanguageOption("zh-TW", "繁體中文", "繁"),
        new LanguageOption("ja-JP", "日本語", "ja"),
        new LanguageOption("ar", "العربية", "ع", IsRtl: true)
    };
}

// 注册(必须在 AddNextDesignSystem 之前)
builder.Services.AddSingleton<ILanguageProvider, MyLanguageProvider>();
builder.Services.AddNextDesignSystem();

懒加载与预加载

预加载常用语言

启动时预加载可减少首次访问延迟:

// 预加载指定语言
await NextUILocalizer.PreloadAsync("en-US", "zh-CN");

启用懒加载

未预加载的语言会在首次使用时自动加载:

NextUILocalizer.Configure(options => {
    options.EnableLazyLoading = true;
    options.OnCultureMissing = async culture => {
        Console.WriteLine($"Culture {culture} not available");
    };
});

自定义资源提供者

文件系统提供者(支持运行时更新)

// 从用户目录加载,支持运行时更新
var userProvider = new FileSystemLocaleProvider(
    "~/.myapp/locales",
    priority: 20,   // 高于嵌入资源
    canWrite: true  // 启用保存
);
NextUILocalizer.AddProvider(userProvider);

// 运行时保存用户翻译
await NextUILocalizer.SaveUserTranslationsAsync("zh-CN", new Dictionary<string, string>
{
    ["Custom.Greeting"] = "你好,世界!"
});

自定义 API 提供者

public class ApiLocaleProvider : ILocaleResourceProvider
{
    public string Name => "API";
    public int Priority => 15;
    public bool CanWrite => false;

    public IEnumerable<string> GetAvailableCultures()
        => new[] { "en-US", "zh-CN" };

    public async Task<Dictionary<string, string>?> LoadAsync(string culture)
    {
        var response = await _httpClient.GetAsync($"/api/locales/{culture}");
        return await response.Content.ReadFromJsonAsync<Dictionary<string, string>>();
    }

    public Task SaveAsync(string culture, Dictionary<string, string> resources)
        => throw new NotSupportedException();
}

组件开发指南

方式一:手动订阅 Changed 事件

@inject INextUILocalizer L
@implements IDisposable

<div>@L["MyComponent.Title"]</div>

@code {
    protected override void OnInitialized()
    {
        L.Changed += OnLocaleChanged;
    }

    private void OnLocaleChanged()
    {
        InvokeAsync(StateHasChanged);
    }

    public void Dispose()
    {
        L.Changed -= OnLocaleChanged;
    }
}

方式二:继承 LocalizedComponentBase

@inherits LocalizedComponentBase

<div>@L["MyComponent.Title"]</div>

从旧 API 迁移

旧方式(已废弃)

// 硬编码在 C# 中
NextUILocalizer.Add("en-US", "Menu.Settings", "Settings");
NextUILocalizer.Add("zh-CN", "Menu.Settings", "设置");

新方式(推荐)

// en-US.json
{ "Menu.Settings": "Settings" }

// zh-CN.json
{ "Menu.Settings": "设置" }

向后兼容

旧的 NextUILocalizer.Add() API 仍然可用,但会输出废弃警告:

[NextUI Localization] Warning: NextUILocalizer.Add() is deprecated.
[NextUI Localization] Please migrate to JSON-based locale resources.

最佳实践

1. 使用 JSON 文件

比 C# 硬编码更易于维护和扩展。

2. 正确分层翻译

库组件翻译放在 NextUI.Blazor,应用组件放在你的应用中。

3. 预加载常用语言

减少首次访问延迟:

await NextUILocalizer.PreloadAsync("en-US", "zh-CN");

4. 使用一致的键命名

遵循 Component.Action 模式:

Nav.Overview           - 导航分类
Menu.Settings          - 菜单项
Button.Save            - 按钮文本
Error.NotFound         - 错误消息

5. 测试 RTL 语言

阿拉伯语有助于发现布局问题:

new LanguageOption("ar", "العربية", "ع", IsRtl: true)

6. 避免循环中频繁调用

<!-- 不推荐 -->
@foreach (var item in items)
{
    <span>@L["Item.Label"]: @item.Name</span>
}

<!-- 推荐:缓存翻译结果 -->
@{
    var label = L["Item.Label"];
}
@foreach (var item in items)
{
    <span>@label: @item.Name</span>
}

支持的语言

NextUI 内置以下语言翻译:

代码 语言 RTL
en-US English
zh-CN 简体中文
zh-TW 繁體中文
ja-JP 日本語
ar العربية

相关文件

  • src/NextUI.Core/Localization/ - 核心本地化基础设施
  • src/NextUI.Core/NextUILocalizer.cs - 静态 API
  • src/NextUI.Blazor/Resources/Locales/ - 库组件翻译 JSON
  • src/NextUI.Blazor/BlazorLocaleExtensions.cs - Blazor 层注册
  • src/NextUI.App/Resources/Locales/ - App 层翻译 JSON
  • workbench/NextUI.Workbench/Resources/Locales/ - Workbench 翻译 JSON

© 2026 NextUI Team