Skip to content

国际化

MdrFrontEngine 内置国际化(i18n)支持,让你的应用轻松支持多语言。本文档介绍如何配置和使用国际化功能。

概述

MdrFrontEngine 使用 i18next 作为国际化解决方案,提供:

  • 多语言文本管理
  • 动态语言切换
  • 插值和格式化
  • 复数处理
  • 日期/数字本地化

内置语言支持

MdrFrontEngine 编辑器默认支持:

语言代码状态
简体中文zh-CN✅ 完整支持
Englishen✅ 完整支持

项目配置

启用国际化

project.json 中配置:

json
{
  "i18n": {
    "enabled": true,
    "defaultLocale": "zh-CN",
    "locales": ["zh-CN", "en", "ja"],
    "fallbackLocale": "en"
  }
}

语言资源文件

创建语言资源文件:

project/
├── locales/
│   ├── zh-CN.json
│   ├── en.json
│   └── ja.json

zh-CN.json:

json
{
  "common": {
    "welcome": "欢迎",
    "login": "登录",
    "logout": "退出登录",
    "submit": "提交",
    "cancel": "取消"
  },
  "home": {
    "title": "首页",
    "greeting": "你好,{{name}}!",
    "items_count": "共 {{count}} 项"
  },
  "errors": {
    "required": "此字段为必填项",
    "invalid_email": "请输入有效的邮箱地址"
  }
}

en.json:

json
{
  "common": {
    "welcome": "Welcome",
    "login": "Login",
    "logout": "Logout",
    "submit": "Submit",
    "cancel": "Cancel"
  },
  "home": {
    "title": "Home",
    "greeting": "Hello, {{name}}!",
    "items_count": "{{count}} item",
    "items_count_plural": "{{count}} items"
  },
  "errors": {
    "required": "This field is required",
    "invalid_email": "Please enter a valid email address"
  }
}

在 MIR 中使用

文本翻译

使用 $t() 函数引用翻译文本:

json
{
  "type": "MdrText",
  "props": {
    "content": { "$t": "common.welcome" }
  }
}

带参数的翻译

json
{
  "type": "MdrText",
  "props": {
    "content": {
      "$t": "home.greeting",
      "params": { "name": "${user.name}" }
    }
  }
}

复数处理

json
{
  "type": "MdrText",
  "props": {
    "content": {
      "$t": "home.items_count",
      "count": "${items.length}"
    }
  }
}

语言切换

语言切换组件

json
{
  "type": "MdrSelect",
  "props": {
    "options": [
      { "label": "简体中文", "value": "zh-CN" },
      { "label": "English", "value": "en" },
      { "label": "日本語", "value": "ja" }
    ],
    "value": "$currentLocale"
  },
  "events": {
    "onChange": {
      "type": "action",
      "action": "setLocale",
      "params": { "locale": "$event.value" }
    }
  }
}

节点图中切换

┌─────────────┐     ┌─────────────┐
│ onChange    │────▶│ setLocale   │
│ Select      │     │ locale: val │
└─────────────┘     └─────────────┘

日期和数字格式化

日期格式化

json
{
  "type": "MdrText",
  "props": {
    "content": {
      "$format": "date",
      "value": "${user.createdAt}",
      "options": {
        "dateStyle": "long"
      }
    }
  }
}

不同语言的输出:

  • 中文:2024年1月15日
  • English: January 15, 2024
  • 日本語:2024年1月15日

数字格式化

json
{
  "type": "MdrText",
  "props": {
    "content": {
      "$format": "number",
      "value": "${product.price}",
      "options": {
        "style": "currency",
        "currency": "CNY"
      }
    }
  }
}

不同语言的输出:

  • 中文:¥1,234.56
  • English: CN¥1,234.56
  • 日本語:¥1,234.56

相对时间

json
{
  "type": "MdrText",
  "props": {
    "content": {
      "$format": "relativeTime",
      "value": "${post.createdAt}"
    }
  }
}

输出示例:

  • 中文:3 分钟前
  • English: 3 minutes ago
  • 日本語:3分前

代码导出

导出代码时,国际化配置会被保留:

React 导出

tsx
// i18n/index.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import zhCN from './locales/zh-CN.json';
import en from './locales/en.json';

i18n.use(initReactI18next).init({
  resources: {
    'zh-CN': { translation: zhCN },
    en: { translation: en },
  },
  lng: 'zh-CN',
  fallbackLng: 'en',
  interpolation: {
    escapeValue: false,
  },
});

export default i18n;
tsx
// components/Greeting.tsx
import { useTranslation } from 'react-i18next';

export function Greeting({ name }) {
  const { t } = useTranslation();
  return <h1>{t('home.greeting', { name })}</h1>;
}

Vue 导出

typescript
// i18n/index.ts
import { createI18n } from 'vue-i18n';
import zhCN from './locales/zh-CN.json';
import en from './locales/en.json';

export const i18n = createI18n({
  locale: 'zh-CN',
  fallbackLocale: 'en',
  messages: {
    'zh-CN': zhCN,
    en: en,
  },
});
vue
<template>
  <h1>{{ $t('home.greeting', { name }) }}</h1>
</template>

路由国际化

URL 路径策略

json
{
  "i18n": {
    "routing": {
      "strategy": "prefix", // prefix | subdomain | query
      "excludeRoutes": ["/api", "/admin"]
    }
  }
}

prefix 策略:

  • /zh-CN/about - 中文
  • /en/about - 英文
  • /about - 默认语言

subdomain 策略:

  • zh.example.com/about
  • en.example.com/about

自动语言检测

json
{
  "i18n": {
    "detection": {
      "order": ["path", "cookie", "navigator"],
      "caches": ["cookie"]
    }
  }
}

SEO 优化

多语言 SEO 标签

自动生成 hreflang 标签:

html
<link rel="alternate" hreflang="zh-CN" href="https://example.com/zh-CN/page" />
<link rel="alternate" hreflang="en" href="https://example.com/en/page" />
<link rel="alternate" hreflang="x-default" href="https://example.com/page" />

页面元信息

json
{
  "meta": {
    "title": { "$t": "home.meta.title" },
    "description": { "$t": "home.meta.description" }
  }
}

编辑器本地化

切换编辑器语言

在设置中切换 MdrFrontEngine 编辑器的界面语言:

  1. 点击右上角设置图标
  2. 选择 "语言" 选项
  3. 选择目标语言
  4. 界面自动刷新

添加编辑器翻译

如果需要贡献新语言支持:

  1. 复制 apps/web/src/i18n/resources/en.json
  2. 翻译为目标语言
  3. 提交 Pull Request

最佳实践

1. 使用命名空间

组织翻译键以便管理:

json
{
  "common": { ... },      // 通用文本
  "auth": { ... },        // 认证相关
  "dashboard": { ... },   // 仪表盘
  "errors": { ... }       // 错误信息
}

2. 避免硬编码文本

json
// ✅ 推荐
{ "content": { "$t": "button.submit" } }

// ❌ 避免
{ "content": "提交" }

3. 处理复数

json
{
  "items": "{{count}} item",
  "items_plural": "{{count}} items",
  "items_zero": "No items"
}

4. 保持上下文

为翻译提供上下文:

json
{
  "button": {
    "submit": "提交", // 表单提交按钮
    "submit_order": "提交订单" // 订单页面按钮
  }
}

5. 测试所有语言

确保所有语言都有完整的翻译,避免回退到其他语言。

下一步

基于 MIT 许可证发布