---
title: "i18n Интернационализация"
description: "Интернационализация плагина NocoBase: структура каталога locale, формат файлов перевода, использование this.t / useT / tExpr в разных сценариях."
keywords: "i18n,интернационализация,locale,перевод,this.t,useT,tExpr,NocoBase"
---

# i18n Интернационализация

Плагины NocoBase управляют файлами многоязычной локализации через каталог `src/locale/`. После создания файлов перевода используйте `this.t()` в Plugin, хук `useT()` в компонентах, `tExpr()` в определениях FlowModel — и Вы получите переведённый текст.

## Файлы перевода

Создайте JSON-файлы по языкам в `src/locale/` плагина: ключ — это английский оригинал, значение — перевод на соответствующий язык:

```bash
my-plugin/
└── src/
    └── locale/
        ├── zh-CN.json
        └── en-US.json
```

```json
// src/locale/zh-CN.json
{
  "Hello": "你好",
  "Save": "保存",
  "Your name is {{name}}": "你的名字是 {{name}}",
  "{{count}} February items": "{{count}} 条记录"
}
```

```json
// src/locale/en-US.json
{
  "Hello": "Hello",
  "Save": "Save",
  "Your name is {{name}}": "Your name is {{name}}",
  "{{count}} February items": "{{count}} items"
}
```

Несколько важных замечаний:

- **В качестве ключа используется английский оригинал**, чтобы при отсутствии перевода был fallback на английский
- **Переменные оборачиваются двойными фигурными скобками** `{{name}}`, синтаксис совпадает с [i18next](https://www.i18next.com/translation-function/interpolation)
- **При первом добавлении файла языка нужно перезапустить приложение**, чтобы он вступил в силу; последующие изменения содержимого подхватываются через горячую перезагрузку
- NocoBase автоматически использует **имя пакета** плагина в качестве пространства имён (namespace) перевода, переводы разных плагинов не конфликтуют

## Использование в Plugin: this.t()

В классе Plugin метод `this.t()` **автоматически подставляет имя пакета текущего плагина в качестве namespace**, передавать `ns` вручную не нужно:

```ts
// src/client-v2/plugin.tsx
import { Plugin, Application } from '@nocobase/client-v2';

export class MyPlugin extends Plugin<any, Application> {
  async load() {
    // 自动使用当前插件的包名作为 ns
    console.log(this.t('Hello')); // -> "你好"

    // 注册设置页时用 this.t() 翻译标题
    this.pluginSettingsManager.addMenuItem({
      key: 'my-settings',
      title: this.t('My Settings'),
      icon: 'SettingOutlined',
    });
    this.pluginSettingsManager.addPageTabItem({
      menuKey: 'my-settings',
      key: 'index',
      title: this.t('My Settings'),
      componentLoader: () => import('./pages/MySettingsPage'),
    });
  }
}
```

## Использование в компонентах: useT()

В React-компонентах нельзя напрямую использовать `this.t()`. Каркас плагина автоматически генерирует файл `locale.ts`, который предоставляет хук `useT()`:

```ts
// src/client-v2/locale.ts（脚手架自动生成）
import { tExpr as _tExpr, useFlowEngine } from '@nocobase/flow-engine';
// @ts-ignore
import pkg from './../../package.json';

export function useT() {
  const engine = useFlowEngine();
  return (str: string) => engine.context.t(str, { ns: [pkg.name, 'client'] });
}

export function tExpr(key: string) {
  return _tExpr(key, { ns: [pkg.name, 'client'] });
}
```

В компоненте используется так:

```tsx
// src/client-v2/pages/MySettingsPage.tsx
import React from 'react';
import { Button } from 'antd';
import { useT } from '../locale';

export default function MySettingsPage() {
  const t = useT();

  return (
    <div>
      <h2>{t('Hello')}</h2>
      <p>{t('Your name is {{name}}', { name: 'NocoBase' })}</p>
      <Button>{t('Save')}</Button>
    </div>
  );
}
```

Возвращаемая `useT()` функция `t` уже привязана к namespace плагина — достаточно передать ключ.

## Использование в FlowModel: tExpr()

`FlowModel.define()` и `registerFlow()` выполняются на этапе загрузки модуля — в этот момент i18n ещё не инициализирован, и нельзя напрямую вызывать `t()`. В таких сценариях используется `tExpr()` — он генерирует строку отложенного перевода, которая разрешается во время выполнения:

```tsx
// src/client-v2/models/MyBlockModel.tsx
import { BlockModel } from '@nocobase/client-v2';
import { tExpr } from '../locale';

export class MyBlockModel extends BlockModel {
  renderComponent() {
    return <div>My custom block</div>;
  }
}

// tExpr 生成类似 '{{t("My block")}}' 的字符串，运行时翻译
MyBlockModel.define({
  label: tExpr('My block'),
});

MyBlockModel.registerFlow({
  key: 'flow1',
  title: tExpr('My Block Settings'),
  on: 'beforeRender',
  steps: {
    editTitle: {
      title: tExpr('Edit Title'),
      uiSchema: {
        title: {
          type: 'string',
          title: tExpr('Title'),
          'x-decorator': 'FormItem',
          'x-component': 'Input',
        },
      },
      handler(ctx, params) {
        ctx.model.props.title = params.title;
      },
    },
  },
});
```

Проще говоря: `this.t()` и `useT()` используются для перевода во время выполнения, а `tExpr()` — для отложенного перевода при статическом определении.

:::tip Подсказка

`tExpr` имеет два источника: автоматически сгенерированный плагином `locale.ts` и `@nocobase/flow-engine`. Разница в том, что `tExpr` из `locale.ts` уже привязан к namespace по имени пакета плагина, а `tExpr`, импортированный напрямую из `@nocobase/flow-engine`, не имеет привязки к namespace. **В коде плагина всегда используйте `tExpr`, экспортированный из `locale.ts`** — только так перевод будет корректно сопоставляться с языковыми файлами самого плагина.

:::

## Краткая таблица трёх вариантов использования

| Сценарий | Использование | Источник |
| --- | --- | --- |
| В `load()` плагина | `this.t('key')` | Встроено в базовый класс Plugin |
| В React-компоненте | `const t = useT(); t('key')` | `locale.ts` |
| Статическое определение FlowModel | `tExpr('key')` | `locale.ts` |

## Связанные ссылки

- [Context → Распространённые возможности → Интернационализация](../ctx/common-capabilities#интернационализация-ctxt--ctxi18n) — полный API-справочник по ctx.t, ctx.i18n
- [Список языков](../../languages) — полный список кодов языков, поддерживаемых NocoBase
- [Разработка Component-компонентов](./index.md) — использование useFlowContext в компонентах
- [Обзор FlowEngine](../flow-engine/index.md) — использование tExpr в FlowModel
