概述

CodeSpirit 框架现已支持完整的前后端多语言国际化功能,提供中英文双语支持,基于 .NET 资源文件和 AMIS locale,通过 Settings 组件实现全局、租户、用户三级语言配置。

版本: v1.0.0
支持语言: 简体中文(zh-CN)、英文(en)
更新日期: 2025年12月28日

image

  • Github:xin-lai/CodeSpirit
  • Gitee:magicodes/CodeSpirit

🎯 核心特性

  • ✅ 双语支持:中文(默认)+ 英文
  • ✅ 全栈覆盖:后端 API + 前端 UI
  • ✅ 多级配置:系统默认 → 租户默认 → 用户偏好
  • ✅ 类型安全:使用 .resx 资源文件,编译时强类型访问
  • ✅ 动态切换:用户可实时切换语言,无需重新登录
  • ✅ AMIS 兼容:集成 AMIS 的 locale 机制
  • ✅ DataAnnotations 支持:验证特性自动本地化
  • ✅ DTO描述多语言:支持字段描述信息的多语言
  • ✅ 零侵入:无需修改业务表结构,基于 Settings 组件

🏗️ 架构设计

语言解析优先级

Cookie(用户手动切换)
    ↓ (未设置)
User Settings(用户偏好)
    ↓ (未设置)
Tenant Settings(租户默认)
    ↓ (未设置)
Global Settings(系统默认)
    ↓ (未设置)
zh-CN(最终回退)

Settings 存储结构

// 全局默认语言
Module: "Localization"
Key: "DefaultLanguage"
Value: "zh-CN"
Scope: Global

// 租户默认语言
Module: "Localization"
Key: "DefaultLanguage"
Value: "en"
Scope: Tenant
ScopeId: "{tenantId}"

// 用户偏好语言
Module: "Localization"
Key: "PreferredLanguage"
Value: "en"
Scope: User
ScopeId: "{userId}"

🚀 快速开始

1. 配置已完成

本地化服务已在 ServiceDefaults 中自动注册,无需额外配置。

2. 后端使用

在 Controller 中使用本地化
using CodeSpirit.Localization.Resources;
using Microsoft.Extensions.Localization;

public class MyController : ApiControllerBase
{
    private readonly IStringLocalizer<SharedResources> _localizer;
    
    public MyController(IStringLocalizer<SharedResources> localizer)
    {
        _localizer = localizer;
    }
    
    [HttpPost]
    public IActionResult Create()
    {
        return Ok(new ApiResponse 
        { 
            Status = 1, 
            Msg = _localizer["Common.Save"].Value 
        });
    }
}
抛出本地化异常
// 使用资源键
throw new BusinessException("Errors.InvalidStartTime");

// 带参数
throw new ValidationException("Errors.NotFound", resourceId);

3. DTO 验证特性多语言

using CodeSpirit.Localization.Resources;

public class CreateQuestionDto
{
    [Display(Name = "Content", ResourceType = typeof(DisplayResources))]
    [Required(ErrorMessageResourceType = typeof(ValidationResources), 
             ErrorMessageResourceName = "Required")]
    [StringLength(2000, 
        ErrorMessageResourceType = typeof(ValidationResources),
        ErrorMessageResourceName = "StringLengthMax")]
    public string Content { get; set; } = string.Empty;
}

验证错误示例

中文环境:题目内容不能为空
英文环境:Content is required

image

4. DTO 描述信息多语言

DTO 字段的描述信息(Description)也支持多语言,通过 LocalizedDescriptionAttribute 实现。

4.1 创建服务资源文件

各服务应创建自己的资源文件,保持服务独立性:

资源文件结构

CodeSpirit.ExamApi/Resources/
  ├── ExamDisplayResources.cs    # 资源占位类(包含ResourceManager)
  ├── ExamDisplay.resx           # 中文资源
  └── ExamDisplay.en.resx        # 英文资源

资源键命名规范

  • DTO字段描述:Description.{EntityName}.{PropertyName}
  • 示例:Description.Question.OptionsDescription.Question.CorrectAnswer
4.2 在DTO中使用
using CodeSpirit.Core.Attributes;
using CodeSpirit.ExamApi.Resources;

public class CreateQuestionDto
{
    [LocalizedDescription(
        "根据题目内容生成合适的选项",  // 回退文本(可选)
        ResourceKey = "Description.Question.Options",
        ResourceType = typeof(ExamDisplayResources)
    )]
    public List<string> Options { get; set; }
}

使用方式

  • 方式1:仅使用资源键(推荐)
  • 方式2:带回退文本(更安全,资源不可用时显示回退文本)
  • 方式3:使用共享资源(仅适用于通用描述)
4.3 向后兼容

现有的 DescriptionAttribute 仍然可以正常使用,系统会优先检查 LocalizedDescriptionAttribute,如果不存在则回退到 DescriptionAttribute

4.4 资源文件组织原则
  • 共享资源CodeSpirit.Localization/Resources/ - 存放真正通用的、跨服务的资源
  • 服务资源ApiServices/{ServiceName}/Resources/ - 存放服务特有的业务资源

最佳实践

  • 各服务管理自己的资源文件,避免在共享资源中放置服务特定内容
  • 遵循 Description.{EntityName}.{PropertyName} 命名约定
  • 建议提供回退文本,确保资源不可用时仍能显示
4.5 技术实现

描述多语言的资源解析由 AMIS 表单生成时统一处理:

  • CultureResolver:从 HttpContext Features、Cookie 等多个来源获取当前语言
  • 统一解析GetLocalizedDescription 方法在表单生成时解析资源
  • 回退机制:英文环境下确保正确加载英文资源,避免回退到中文
  • 缓存优化:在同一请求中复用已解析的文化信息

5. 前端使用

JavaScript
// 获取翻译文本
const message = CodeSpirit.i18n.t('Common.Save');

// 带参数
const message = CodeSpirit.i18n.t('Validation.Required', { 0: '用户名' });

// 切换语言
CodeSpirit.i18n.switchLanguage('en');
Razor 页面
@using CodeSpirit.Localization.Resources
@using Microsoft.Extensions.Localization
@inject IStringLocalizer<SharedResources> Localizer

<h1>@Localizer["Common.Save"]</h1>

🎛️ 语言配置管理

通过 API 设置语言

系统已自动集成 Settings 组件,可以通过 Settings API 管理语言配置:

设置用户语言偏好
await _settingsService.SetUserSettingAsync(
    module: "Localization",
    key: "PreferredLanguage",
    value: "en",
    userId: currentUserId
);
设置租户默认语言
await _settingsService.SetTenantSettingAsync(
    module: "Localization",
    key: "DefaultLanguage",
    value: "en",
    tenantId: currentTenantId
);
设置全局默认语言
await _settingsService.SetGlobalSettingAsync(
    module: "Localization",
    key: "DefaultLanguage",
    value: "en"
);

通过 UI 切换语言

用户可以在导航栏的语言切换器中选择语言,切换后会:

  1. 设置 Cookie(.AspNetCore.Culture
  2. 刷新页面
  3. 所有界面文本、错误消息自动切换为对应语言

📚 资源文件说明

共享资源(Localization组件)

资源文件 用途 示例键
Shared.resx 通用 UI 文本 Common.SaveCommon.Cancel
Errors.resx 错误消息 Errors.NotFoundErrors.Unauthorized
Validation.resx 验证消息模板 RequiredStringLengthMax
Display.resx 字段显示名称 ContentTypeDifficulty

每个资源文件都有对应的英文版本(如 Shared.en.resx)。

服务特定资源(各API服务)

各服务应创建自己的资源文件,保持服务独立性:

命名规范

  • 占位类:{ServiceName}DisplayResources.cs
  • 资源文件:{ServiceName}Display.resx{ServiceName}Display.en.resx

示例

CodeSpirit.ExamApi/Resources/
  ├── ExamDisplayResources.cs    # 资源占位类(包含ResourceManager)
  ├── ExamDisplay.resx           # 中文资源
  └── ExamDisplay.en.resx        # 英文资源

CodeSpirit.SurveyApi/Resources/
  ├── SurveyDisplayResources.cs
  ├── SurveyDisplay.resx
  └── SurveyDisplay.en.resx

资源键命名约定

  • DTO字段描述:Description.{EntityName}.{PropertyName}
  • 示例:Description.Question.OptionsDescription.Survey.Title

🔧 常见场景

场景 1:用户切换语言

  1. 用户在导航栏选择 "English"

  2. JavaScript 调用 CodeSpirit.i18n.switchLanguage('en')

  3. 设置 Cookie 并刷新页面

  4. 所有内容显示为英文

    image

场景 2:租户设置默认语言

  1. 租户管理员在设置中选择默认语言为英文
  2. 系统通过 Settings API 保存配置
  3. 该租户下的所有用户默认使用英文
  4. 用户仍可以设置自己的语言偏好

场景 3:API 返回本地化错误

// 中文环境
throw new BusinessException("Errors.NotFound");
// API 返回: { "status": 0, "msg": "未找到资源" }

// 英文环境  
throw new BusinessException("Errors.NotFound");
// API 返回: { "status": 0, "msg": "Resource not found" }
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐