# Internationalization

Client-side internationalization for multiple languages is implemented based on the npm package [react-i18next](https://npmjs.com/package/react-i18next), which provides a wrapper for the `<I18nextProvider>` component at the top level of the application, allowing the relevant methods to be used directly at any location.

Adding language packages:

```tsx | pure
import { i18n } from '@nocobase/client';

i18n.addResources('zh-CN', 'test', {
  Hello: '你好',
  World: '世界',
});
```

Note: Here the second parameter filled in `'test'` is the language namespace, usually the plugin itself defines the language resources should create a specific namespace according to their own plugin package name, in order to avoid conflicts with other language resources. The default namespace in NocoBase is `'client'` and most common and basic language translations are placed in this namespace. When the required language is not provided, it can be defined by extension in the plugin's own namespace.

To call the translation function in the component:

```tsx | pure
import React from 'react';
import { useTranslation } from 'react-i18next';

export default function MyComponent() {
  // Use the previously defined namespace
  const { t } = useTranslation('test');

  return (
    <div>
      <p>{t('World')}</p>
    </div>
  );
}
```

The template method `'{{t(<languageKey>)}}'` can be used directly in the SchemaComponent component, and the translation functions in the template will automatically be executed.

```tsx | pure
import React from 'react';
import { SchemaComponent } from '@nocobase/client';

export default function MySchemaComponent() {
  return (
    <SchemaComponent
      schema={{
        type: 'string',
        'x-component': 'Input',
        'x-component-props': {
          value: '{{t("Hello", { ns: "test" })}}'
        },
      }}
    />
  );
}
```

In some special cases where it is also necessary to define multilingualism as a template, the NocoBase built-in `compile()` method can be used to compile to multilingual results.

```tsx | pure
import React from 'react';
import { useCompile } from '@nocobase/client';

const title = '{{t("Hello", { ns: "test" })}}';

export default function MyComponent() {
  const { compile } = useCompile();

  return (
    <div>{compile(title)}</div>
  );
}
```

## Suggested configuration

With English text as the key and translation as the value, the benefit of this, even if multiple languages are missing, it will be displayed in English and will not cause reading barriers, e.g.

```ts
i18n.addResources('zh-CN', 'my-plugin', {
  'Show dialog': '显示对话框',
  'Hide dialog': '隐藏对话框'
});
```

To make it easier to manage multilingual files, it is recommended to create a `locale` folder in the plugin and place all the corresponding language files in it for easy management.

```bash
|- /my-plugin
  |- /src
    |- /client
      |- locale     # Multilingual folder
        |- zh-CN.ts
        |- en-US.ts
```

## Example

### Client-side components with multiple languages

For example, the order status component, with different text displays depending on the value.

```tsx | pure
import React from 'react';
import { Select } from 'antd';
import { i18n } from '@nocobase/client';
import { useTranslation } from 'react-i18next';

i18n.addResources('zh-CN', 'sample-shop-i18n', {
  Pending: '已下单',
  Paid: '已支付',
  Delivered: '已发货',
  Received: '已签收'
});

const ORDER_STATUS_LIST = [
  { value: -1, label: 'Canceled (untranslated)' },
  { value: 0, label: 'Pending' },
  { value: 1, label: 'Paid' },
  { value: 2, label: 'Delivered' },
  { value: 3, label: 'Received' },
]

function OrderStatusSelect() {
  const { t } = useTranslation('sample-shop-i18n');

  return (
    <Select style={{ minWidth: '8em' }}>
      {ORDER_STATUS_LIST.map(item => (
        <Select.Option value={item.value}>{t(item.label)}</Select.Option>
      ))}
    </Select>
  );
}

export default function () {
  return (
    <OrderStatusSelect />
  );
}
```