Aller au contenu principal
Version: 3.0.0

I18n

Midway provides a multi-language component that allows the business to quickly specify different languages and display different texts. It can also be used in HTTP scenarios with request parameters and request first-class methods.

Related information:

Description
Can be used for standard projects
Can be used for Serverless
Can be used for integration
Contains independent main framework
Contains independent logs

Installation Components

$ npm i @midwayjs/i18n@3 --save

Or reinstall the following dependencies in package.json.

{
"dependencies": {
"@midwayjs/i18n": "^3.0.0",
// ...
},
}

Use components

Configure the i18n component into the code.

import { Configuration } from '@midwayjs/core';
import * as i18n from '@midwayjs/i18n';

@Configuration({
imports: [
// ...
i18n
]
})
export class MainConfiguration {
//...
}

Use

The component provides MidwayI18nService services for translating multilingual text.

Using translate method, pass in different text keywords and parameters to return text content in different languages.

@Controller('/')
export class UserController {

@Inject()
i18nService: MidwayI18nService;

@Get('/')
async index(@Query('username') username: string) {
return this.i18nService.translate('HELLO_MESSAGE', {
args: {
username
},
});
}
}

Configure i18n messages

You can configure it directly in the configuration file, but in most cases, there will be a lot of copy, and sometimes it may even be on remote services. Direct configuration is not realistic at this time.

Generally speaking, we will put the copy into a copy configuration directory, such as src/locales.

Take the src/locale directory as an example, let's take an example, the structure is as follows:

.
├── src
│ ├── locales
| │ ├── en_US.json
| │ └── zh_CN.json
│ └── controller
│ └── home.controller.ts
├── package.json
└── tsconfig.json

Here we have created two multilingual files, en_US.json and zh_CN.json, representing English and Chinese respectively.

The contents of the documents are as follows:

// src/locales/en_US.json
{
"hello": "Hello {username} ",
"email": "email id ",
"login": "login account ",
"createdAt": "register date"
}
// src/locales/zh_CN.json
{
"hello": "你好 {username}",
"email": "邮箱",
"login": "帐号",
"createdAt": "注册时间"
}

Each line has a string pair, which is a standard JSON format. You can also use js/ts files. The curly brackets are filled with replaceable parameters.

At the same time, you need to add these two JSON to the configuration, and default property is a default group name.

// src/config/config.default.ts
export default {
// ...
i18n: {
// Put your translated text here
localeTable: {
en_US: {
default: require('../locale/en_US'),
},
zh_CN: {
default: require('../locale/zh_CN'),
}
},
}
}

In this way, it can be used. The output is as follows.

this.i18nService.translate('hello', {
args: {
username: 'harry',
},
locale: 'en_US',
});

// output: Hello harry.

this.i18nService.translate('hello', {
args: {
username: 'harry',
},
locale: 'zh_CN',
});

// output: 你好 harry.

I18n message group

In the following configuration, the multi-language message configured by the user is in the default group.

// src/config/config.default.ts
export default {
// ...
i18n: {
// Put your translated text here
localeTable: {
en_US: {
default: require('../locale/en_US'),
},
zh_CN: {
default: require('../locale/zh_CN'),
}
},
}
}

The advantage of this is that in other components or business codes, we can also use different group names to add other multilingual texts.

For example:

// src/config/config.default.ts
export default {
// ...
i18n: {
// Put your translated text here
localeTable: {
en_US: {
default: require('../locale/en_US'),
user: require('../locale/user_en_US'),
},
zh_CN: {
default: require('../locale/zh_CN'),
user: require('../locale/user_zh_CN'),
}
},
}
}

In the code, if you call a different group, you need to specify the group parameters.

this.i18nService.translate('user.hello', {
args: {
username: 'harry',
},
group: 'user', // Specify other groups
locale: 'en_US',
});

I18n message format

Parameters can be added to multilingual text, and parameters can have two forms: object and array.

The object form is as follows, using curly braces as placeholders.

Hello {username}

When used, passed by configuration, overriding variables by object key.

async index(@Query('username') username: string) {
return this.i18nService.translate('hello', {
args: {
username
},
});
}

The array form is as follows, using numbers as placeholders.

Hello {0}

When used, it is passed through configuration, and the format is in the form of an array, overwriting the numeric variables in the order of the array.

async index(@Query('username') username: string) {
return this.i18nService.translate('hello', {
args: [username]
});
}

Dynamically add i18n message

Sometimes, i18n message may be placed remotely, such as databases, etc., and we can add them dynamically through addLocale methods.

For example, after the configuration is loaded, before the code is used.

// configuration.ts

// ...
@Configuration({
imports: [
koa
i18n
]
})
export class MainConfiguration {

@Inject()
i18nService: MidwayI18nService;

async onReady() {
this.i18nService.addLocale('zh_TW', {
hello: '你好,{username} 美麗的世界'
});
}


// ...
}

It can be used in code.

async index(@Query('username') username: string) {
return this.i18nService.translate('hello', {
args: [username]
locale: 'zh_TW'
});
}

Specify the current language through parameters

In general, the default language is en_US. If you need to manually specify the locale parameter for each call, it is not reasonable. In the HTTP scenario, we provide the ability to specify the current language through parameters.

By default, you can specify URL Query,Cookie, and Header.

Priority from top to bottom:

  • query: /?locale=en-US
  • cookie: locale=zh-TW
  • header: Accept-Language: zh-CN,zh;q=0.5

After these parameters are passed, the multilingual data will be automatically saved to the current user's Cookie, and the next request will directly use the set language.

Set language manually

The current language can be set by calling the saveRequestLocale.

async index() {
// ...
this.i18nService.saveRequestLocale('zh_CN');
}

If the writeCookie configuration is turned on, the settings will be saved to the current user's Cookie and will be used in the next request.

Language selection priority

These multiple ways of setting up languages have different priorities, from high to low:

    1. The language explicitly specified by the i18nService.translate method
    1. Languages set by other decorators, such as @Validate the parameters of the decorator (essentially calling the i18nService.translate method)
    1. The current language directly set through the saveRequestLocale API
    1. Language set by browser Query,Cookie and Header (essentially, saveRequestLocale is called)
    1. default language in i18n component configuration

About Language Case

Inside the code, we will replace all multilingual, fallback rules, written text strings, and returned locale results with the following rules

    1. Use the middle dash instead of the underscore
    1. Use lowercase instead of uppercase

All en_US changes to en-us and zh_CN changes to zh-cn.

This will safely adapt URL and Cookie.

Used in View

In the Web type framework, we add locals variable support by default, which can be used in the template engine.

Assuming that the template engine we use is Nunjucks, it can be directly referenced to the i18n method.

The multilingual copy is as follows:

{
"hello": "Hello {username} ",
}

The template is as follows:

<span>{{ i18n('hello', user) }}</span>

Examples are as follows:

// ...

@Controller('/')
export class UserController {

@Inject()
ctx: Context;

@Get('/')
async index() {
await this.ctx.render('index', {
// Note that this is the entire object passed to the template
user: {
username: 'harry',
}
});
}
}

The i18n method is defined as follows:

function i18n(templateName: string, args: Record<string, any>) {
// ...
}

The method name can be modified by configuration.

// src/config/config.default.ts
export default {
// ...
i18n: {
localsField: 'i18n',
}
}

Configuration

Default configuration

In most cases, you only need to add your own multilingual translation localeTable the configuration.

The following is the complete configuration, which you can find in the configuration definition.

// src/config/config.default.ts
export default {
// ...
i18n: {
// Default language "en_US"
defaultLocale: 'en_US',

// Put your translated text here
localeTable: {
en_US: {
// group name
default: {
// hello: 'hello'
}
},
zh_CN: {
// group name
default: {
// hello: '你好'
}
},
},

// Language mapping, you can use * to match
fallbacks: {
// 'en_* ': ' en_US',
// pt: 'pt-BR',
},
// Whether to write the request parameter to the cookie
writeCookie: true
resolver: {
// url query parameter, default is "locale"
queryField: 'locale',
cookieField: {
// The key in Cookie is "locale" by default"
fieldName: 'locale',
// Cookie domain name, which is empty by default, indicates that the current domain name is valid.
cookieDomain: '',
// The default expiration time of the cookie. Default is one year.
cookieMaxAge: FORMAT.MS.ONE_YEAR
},
},
localsField: 'i18n',
}
}

By default, the multilingual component will write back the current user's language to the Cookie to avoid searching for the next request to improve performance. We can turn off this behavior by configuration.

// src/config/config.default.ts
export default {
// ...
i18n: {
writeCookie: false
}
}

Request resolution configuration

In the HTTP scenario, we provide the ability to specify the current language through parameters.

By default, components are found through the fields below.

  • locale field of query
  • locale field of cookie
  • Accept-Language of header

We can modify the fields of the query by configuration.

For example, modify the fields of Query.

// src/config/config.default.ts
export default {
// ...
i18n: {
resolver: {
queryField: 'abc'
},
}
}

You can use /?abc = en-US to request language changes.

If you do not want to set the language by request, you can turn off the entire resolver parsing and write-back to Cookie will stop at the same time.

// src/config/config.default.ts
export default {
// ...
I18n: {
resolver: false,
}
}

Common language

LanguageLanguage package name
Arabiaar_EG
Armeniahy_AM
Bulgarianbg_BG
Catalanca_ES
Czechcs_CZ
Danishda_DK
Germande_DE
Greekel_GR
Englishen_GB
English (American)en_US
Spanishes_ES
Estonianet_EE
PersianFa_IR
Finnishfi_FI
French (Belgium)fr_BE
Frenchfr_FR
HebrewHe_IL
HindiHi_IN
Croatianhr_HR
HungaryHu_HU
Icelandicis_IS
Indonesianid_ID
Italianit_IT
Japaneseja_JP
GeorgianKa_GE
KannadaKn_IN
Korean/Koreanko_KR
Kurdishku_IQ
Latvianlv_LV
MalayMs_MY
Mongolianmn_MN
Norwaynb_NO
Nepaline_NP
Dutch (Belgium)nl_BE
Dutchnl_NL
Polishpl_PL
Portuguese (Brazil)pt_BR
Portuguesept_PT
Slovaksk_SK
Serbiasr_RS
Sloveniasl_SI
Swedishsv_SE
TamilTA_IN
Thaith_TH
Turkishtr_TR
RomanianRO_RO
Russianru_RU
Ukrainianuk_UA
Vietnamesevi_VN
Simplified Chinesezh_CN
Traditional Chinesezh_TW

Common problem

1. The test configuration global language does not take effect

In general scenarios, you don't need to configure the global language, because browser access will automatically bring language information. For example, a Chinese browser will automatically return Chinese, and an English browser will automatically return English.

If you specifically wish to test the effects of global settings, be sure to do the following:

    1. If you are using a browser, please clear the page cookie before visiting again, because the cookie will record the last user's language information.
    1. If you are using tools such as Postman, please do not bring cookies and language-related Header, Query and other fields.

2. The language returned by the test is unexpected

Please use a browser to test, not Postman.

Since the Postman request does not carry a header related to the browser language, the server cannot automatically determine the language.

If you must use Postman, please refer to the browser request and add the Accept-Language Header.