字典

如何使用传统的基于字典的翻译模式

字典是一种传统做法,通过在嵌套对象中使用键值对来组织翻译。虽然<T> 组件是推荐方案,但在从其他 i18n 库迁移,或当你更倾向于集中式管理翻译时,字典依然很有用。

建议: 新项目请使用<T> 组件。对字典的支持主要用于迁移场景,以及与现有翻译工作流的兼容性。

字典 与 组件翻译对比

字典模式

// dictionary.ts
export default {
  greetings: {
    hello: '你好,世界!',
    welcome: '欢迎,{name}!'
  }
};

// Component usage
function MyComponent() {
  const d = useTranslations();
  return <div>{d('greetings.hello')}</div>;
}

组件模式

// 直接组件使用 - 推荐
function MyComponent() {
  return <T><div>你好,世界!</div></T>;
}

权衡取舍

字典的优势

  • 集中存储 - 所有翻译统一管理于一处
  • 行业标准 - 沿用其他 i18n 库的通用模式
  • 便于迁移 - 轻松迁入现有翻译

字典的缺点

  • 复杂性 - 需要更多设置和配置
  • 可维护性 - 内容与使用分离,更新更困难
  • 可调试性 - 更难将翻译追溯到组件
  • 可读性 - 键名无法体现实际内容

快速上手

步骤 1:创建字典

在项目根目录或 src 目录中创建一个字典文件:

dictionary.ts
const dictionary = {
  greetings: {
    hello: '你好,世界!',
    welcome: '欢迎使用我们的应用!'
  },
  navigation: {
    home: '首页',
    about: '关于',
    contact: '联系我们'
  }
};

export default dictionary;

或使用 JSON 格式:

dictionary.json
{
  "greetings": {
    "hello": "你好,世界!",
    "welcome": "欢迎使用我们的应用!"
  },
  "navigation": {
    "home": "首页", 
    "about": "关于",
    "contact": "联系我们"
  }
}

然后将其传递给你的 <GTProvider> 组件:

index.js
import dictionary from "./dictionary.js";
import config from "./gt.config.json";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <GTProvider {...config} dictionary={dictionary}>
      <App />
    </GTProvider>
  </StrictMode>
);

步骤 2:在组件中使用

useTranslations 钩子可用于访问字典条目:

import { useTranslations } from 'gt-react';

function MyComponent() {
  const d = useTranslations();
  
  return (
    <div>
      <h1>{d('greetings.hello')}</h1>
      <p>{d('greetings.welcome')}</p>
    </div>
  );
}

使用变量

使用 {variable} 语法将变量添加到字典项中:

dictionary.ts
const dictionary = {
  user: {
    greeting: '你好,{name}!',
    itemCount: '您有 {count} 个商品',
    orderTotal: '总计:${amount}'
  }
};
function UserDashboard() {
  const d = useTranslations();
  
  return (
    <div>
      <h1>{d('user.greeting', { name: 'Alice' })}</h1>
      <p>{d('user.itemCount', { count: 5 })}</p>
      <p>{d('user.orderTotal', { amount: 99.99 })}</p>
    </div>
  );
}

使用前缀

通过前缀将字典的访问限定在特定部分:

dictionary.ts
const dictionary = {
  dashboard: {
    header: {
      welcome: '欢迎回来!',
      lastLogin: '上次登录:{date}'
    },
    stats: {
      totalUsers: '用户总数:{count}',
      activeUsers: '活跃用户:{count}'
    }
  }
};
function DashboardHeader() {
  // 前缀限制对 'dashboard.header' 的访问
  const d = useTranslations('dashboard.header');
  
  return (
    <header>
      <h1>{d('welcome')}</h1> {/* -> dashboard.header.welcome */}
      <p>{d('lastLogin', { date: 'Today' })}</p> {/* -> dashboard.header.lastLogin */}
    </header>
  );
}

function DashboardStats() {
  // 统计部分使用不同的前缀
  const d = useTranslations('dashboard.stats');
  
  return (
    <div>
      <p>{d('totalUsers', { count: 1000 })}</p> {/* -> dashboard.stats.totalUsers */}
      <p>{d('activeUsers', { count: 150 })}</p> {/* -> dashboard.stats.activeUsers */}
    </div>
  );
}

多语种支持

自动翻译(推荐)

多数用户应使用 loadTranslations 基于你的基础字典自动生成翻译:

dictionary.ts
const dictionary = {
  common: {
    save: '保存',
    cancel: '取消',
    delete: '删除'
  },
  forms: {
    required: '此字段为必填项',
    email: '请输入有效的邮箱地址'
  }
};

export default dictionary;

然后创建一个 loadTranslations 函数,用于加载生成的翻译文件:

src/loadTranslations.ts
export default async function loadTranslations(locale: string) {
  const translations = await import(`./_gt/${locale}.json`);
  return translations.default;
}

将其传给你的 <GTProvider>

src/index.tsx
import loadTranslations from './loadTranslations';
import dictionary from './dictionary';

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <GTProvider 
      {...config} 
      dictionary={dictionary}
      loadTranslations={loadTranslations}
    >
      <App />
    </GTProvider>
  </StrictMode>
);

GT 会根据你的基础字典自动为其他语言生成翻译。运行 npx gtx-cli translate 即可为所有已配置的语言生成翻译。

手动翻译文件(迁移)

从其他 i18n 库迁移或采用手动翻译管理时,请使用 loadDictionary

src/loadDictionary.ts
export default async function loadDictionary(locale: string) {
  const translations = await import(`../public/locales/${locale}.json`);
  return translations.default;
}

这会从你的 public/locales/ 目录加载 JSON 翻译文件:

es.json
fr.json
de.json

选择合适的方法: 对于自动生成翻译的新项目,请使用 loadTranslations;在迁移现有翻译文件时,请使用 loadDictionary

生产环境配置

构建流程

将翻译集成到你的构建管道中:

package.json
{
  "scripts": {
    "build": "npx gtx-cli translate && <...您的构建命令...>"
  }
}

开发环境与生产环境的行为差异

  • 开发环境:使用 Dev API key 按需翻译字典条目
  • 生产环境:在构建阶段预先生成所有字典翻译

结合组件使用

dictionaries 与 <T> 组件 可以配合使用:

function MixedApproach() {
  const d = useTranslations();
  
  return (
    <div>
      {/* 字典用于简单字符串 */}
      <h1>{d('page.title')}</h1>
      
      {/* T 组件用于复杂的 JSX */}
      <T>
        <p>这是一个<strong>复杂的消息</strong>,包含<a href="/link">链接</a>。</p>
      </T>
      
      {/* 字典用于表单标签 */}
      <label>{d('forms.email')}</label>
    </div>
  );
}

下一步

这份指南怎么样?

字典