@eggjs/i18n 4.0.0-beta.35 → 4.0.0-beta.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,11 @@
1
- import { Application } from 'egg';
2
- export default class I18nApplication extends Application {
3
- _I18N_RESOURCES: Record<string, Record<string, string>>;
4
- isSupportLocale(locale: string): boolean;
5
- gettext(locale: string, key: string, value?: any, ...args: any[]): string;
6
- __(locale: string, key: string, value?: any, ...args: any[]): string;
1
+ import { Application } from "egg";
2
+
3
+ //#region src/app/extend/application.d.ts
4
+ declare class I18nApplication extends Application {
5
+ _I18N_RESOURCES: Record<string, Record<string, string>>;
6
+ isSupportLocale(locale: string): boolean;
7
+ gettext(locale: string, key: string, value?: any, ...args: any[]): string;
8
+ __(locale: string, key: string, value?: any, ...args: any[]): string;
7
9
  }
10
+ //#endregion
11
+ export { I18nApplication as default };
@@ -1,76 +1,48 @@
1
- import { debuglog, format } from 'node:util';
2
- import { Application } from 'egg';
3
1
  import { isObject } from "../../utils.js";
4
- const debug = debuglog('egg/i18n/app/extend/application');
5
- export default class I18nApplication extends Application {
6
- _I18N_RESOURCES;
7
- isSupportLocale(locale) {
8
- return !!this._I18N_RESOURCES[locale];
9
- }
10
- gettext(locale, key, value, ...args) {
11
- if (!locale || !key) {
12
- // __()
13
- // __('en')
14
- return '';
15
- }
16
- const resource = this._I18N_RESOURCES[locale] ?? {};
17
- let text = resource[key];
18
- if (text === undefined) {
19
- text = key;
20
- }
21
- debug('%s: %j => %j', locale, key, text);
22
- if (!text) {
23
- return '';
24
- }
25
- if (value === undefined) {
26
- // __(locale, key)
27
- return text;
28
- }
29
- if (args.length === 0) {
30
- if (isObject(value)) {
31
- // __(locale, key, object)
32
- // __('zh', '{a} {b} {b} {a}', {a: 'foo', b: 'bar'})
33
- // =>
34
- // foo bar bar foo
35
- return formatWithObject(text, value);
36
- }
37
- if (Array.isArray(value)) {
38
- // __(locale, key, array)
39
- // __('zh', '{0} {1} {1} {0}', ['foo', 'bar'])
40
- // =>
41
- // foo bar bar foo
42
- return formatWithArray(text, value);
43
- }
44
- // __(locale, key, value)
45
- return format(text, value);
46
- }
47
- // __(locale, key, value1, ...)
48
- return format(text, value, ...args);
49
- }
50
- __(locale, key, value, ...args) {
51
- return this.gettext(locale, key, value, ...args);
52
- }
53
- }
2
+ import { debuglog, format } from "node:util";
3
+ import { Application } from "egg";
4
+
5
+ //#region src/app/extend/application.ts
6
+ const debug = debuglog("egg/i18n/app/extend/application");
7
+ var I18nApplication = class extends Application {
8
+ _I18N_RESOURCES;
9
+ isSupportLocale(locale) {
10
+ return !!this._I18N_RESOURCES[locale];
11
+ }
12
+ gettext(locale, key, value, ...args) {
13
+ if (!locale || !key) return "";
14
+ let text = (this._I18N_RESOURCES[locale] ?? {})[key];
15
+ if (text === void 0) text = key;
16
+ debug("%s: %j => %j", locale, key, text);
17
+ if (!text) return "";
18
+ if (value === void 0) return text;
19
+ if (args.length === 0) {
20
+ if (isObject(value)) return formatWithObject(text, value);
21
+ if (Array.isArray(value)) return formatWithArray(text, value);
22
+ return format(text, value);
23
+ }
24
+ return format(text, value, ...args);
25
+ }
26
+ __(locale, key, value, ...args) {
27
+ return this.gettext(locale, key, value, ...args);
28
+ }
29
+ };
54
30
  const ARRAY_INDEX_RE = /\{(\d+)\}/g;
55
31
  function formatWithArray(text, values) {
56
- return text.replace(ARRAY_INDEX_RE, (original, matched) => {
57
- const index = parseInt(matched);
58
- if (index < values.length) {
59
- return values[index];
60
- }
61
- // not match index, return original text
62
- return original;
63
- });
32
+ return text.replace(ARRAY_INDEX_RE, (original, matched) => {
33
+ const index = parseInt(matched);
34
+ if (index < values.length) return values[index];
35
+ return original;
36
+ });
64
37
  }
65
38
  const Object_INDEX_RE = /\{(.+?)\}/g;
66
39
  function formatWithObject(text, values) {
67
- return text.replace(Object_INDEX_RE, (original, matched) => {
68
- const value = values[matched];
69
- if (value) {
70
- return value;
71
- }
72
- // not match index, return original text
73
- return original;
74
- });
40
+ return text.replace(Object_INDEX_RE, (original, matched) => {
41
+ const value = values[matched];
42
+ if (value) return value;
43
+ return original;
44
+ });
75
45
  }
76
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXBwL2V4dGVuZC9hcHBsaWNhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUU3QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRWxDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUxQyxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsaUNBQWlDLENBQUMsQ0FBQztBQUUxRCxNQUFNLENBQUMsT0FBTyxPQUFPLGVBQWdCLFNBQVEsV0FBVztJQUN0RCxlQUFlLENBQTBDO0lBRXpELGVBQWUsQ0FBQyxNQUFjO1FBQzVCLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVELE9BQU8sQ0FBQyxNQUFjLEVBQUUsR0FBVyxFQUFFLEtBQVcsRUFBRSxHQUFHLElBQVc7UUFDOUQsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ3BCLE9BQU87WUFDUCxXQUFXO1lBQ1gsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBRUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFcEQsSUFBSSxJQUFJLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3pCLElBQUksSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3ZCLElBQUksR0FBRyxHQUFHLENBQUM7UUFDYixDQUFDO1FBRUQsS0FBSyxDQUFDLGNBQWMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNWLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUVELElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3hCLGtCQUFrQjtZQUNsQixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdEIsSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDcEIsMEJBQTBCO2dCQUMxQixvREFBb0Q7Z0JBQ3BELEtBQUs7Z0JBQ0wsa0JBQWtCO2dCQUNsQixPQUFPLGdCQUFnQixDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztZQUN2QyxDQUFDO1lBRUQsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ3pCLHlCQUF5QjtnQkFDekIsOENBQThDO2dCQUM5QyxLQUFLO2dCQUNMLGtCQUFrQjtnQkFDbEIsT0FBTyxlQUFlLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3RDLENBQUM7WUFFRCx5QkFBeUI7WUFDekIsT0FBTyxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzdCLENBQUM7UUFFRCwrQkFBK0I7UUFDL0IsT0FBTyxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRCxFQUFFLENBQUMsTUFBYyxFQUFFLEdBQVcsRUFBRSxLQUFXLEVBQUUsR0FBRyxJQUFXO1FBQ3pELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ25ELENBQUM7Q0FDRjtBQUVELE1BQU0sY0FBYyxHQUFHLFlBQVksQ0FBQztBQUNwQyxTQUFTLGVBQWUsQ0FBQyxJQUFZLEVBQUUsTUFBYTtJQUNsRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxFQUFFO1FBQ3hELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNoQyxJQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDMUIsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkIsQ0FBQztRQUNELHdDQUF3QztRQUN4QyxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxNQUFNLGVBQWUsR0FBRyxZQUFZLENBQUM7QUFDckMsU0FBUyxnQkFBZ0IsQ0FBQyxJQUFZLEVBQUUsTUFBMkI7SUFDakUsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUN6RCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDOUIsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNWLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUNELHdDQUF3QztRQUN4QyxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMifQ==
46
+
47
+ //#endregion
48
+ export { I18nApplication as default };
@@ -1,72 +1,76 @@
1
- import { Context } from 'egg';
2
- export default class I18nContext extends Context {
3
- /**
4
- * get current request locale
5
- * @member Context#locale
6
- * @return {String} lower case locale string, e.g.: 'zh-cn', 'en-us'
7
- */
8
- get locale(): string;
9
- set locale(l: string);
10
- /**
11
- * `ctx.__` 的别名。
12
- * @see {@link Context#__}
13
- * @function Context#gettext
14
- */
15
- gettext(key: string, value?: any, ...args: any[]): string;
16
- /**
17
- * 如果开启了 I18n 多语言功能,那么会出现此 API,通过它可以获取到当前请求对应的本地化数据。
18
- *
19
- * 详细使用说明,请查看 {@link I18n}
20
- * - `ctx.__ = function (key, value[, value2, ...])`: 类似 `util.format` 接口
21
- * - `ctx.__ = function (key, values)`: 支持数组下标占位符方式,如
22
- * - `__` 的别名是 `gettext(key, value)`
23
- *
24
- * > NOTE: __ 是两个下划线哦!
25
- * @function Context#__
26
- * @example
27
- * ```js
28
- * ctx.__('{0} {0} {1} {1}'), ['foo', 'bar'])
29
- * ctx.gettext('{0} {0} {1} {1}'), ['foo', 'bar'])
30
- * =>
31
- * foo foo bar bar
32
- * ```
33
- * ##### Controller 下的使用示例
34
- *
35
- * ```js
36
- * module.exports = function* () {
37
- * this.body = {
38
- * message: this.__('Welcome back, %s!', this.user.name),
39
- * // 或者使用 gettext,如果觉得 __ 不好看的话
40
- * // message: this.gettext('Welcome back, %s!', this.user.name),
41
- * user: this.user,
42
- * };
43
- * };
44
- * ```
45
- *
46
- * ##### View 文件下的使用示例
47
- *
48
- * ```html
49
- * <li>{{ __('Email') }}: {{ user.email }}</li>
50
- * <li>
51
- * {{ __('Hello %s, how are you today?', user.name) }}
52
- * </li>
53
- * <li>
54
- * {{ __('{0} {0} {1} {1}'), ['foo', 'bar']) }}
55
- * </li>
56
- * ```
57
- *
58
- * ##### locale 参数获取途径
59
- *
60
- * 优先级从上到下:
61
- *
62
- * - query: `/?locale=en-US`
63
- * - cookie: `locale=zh-TW`
64
- * - header: `Accept-Language: zh-CN,zh;q=0.5`
65
- */
66
- __(key: string, value?: any, ...args: any[]): string;
67
- __locale: string;
68
- __getLocale(): string;
69
- __localeOrigin: string;
70
- __getLocaleOrigin(): string;
71
- __setLocale(locale: string): void;
1
+ import { Context } from "egg";
2
+
3
+ //#region src/app/extend/context.d.ts
4
+ declare class I18nContext extends Context {
5
+ /**
6
+ * get current request locale
7
+ * @member Context#locale
8
+ * @return {String} lower case locale string, e.g.: 'zh-cn', 'en-us'
9
+ */
10
+ get locale(): string;
11
+ set locale(l: string);
12
+ /**
13
+ * `ctx.__` 的别名。
14
+ * @see {@link Context#__}
15
+ * @function Context#gettext
16
+ */
17
+ gettext(key: string, value?: any, ...args: any[]): string;
18
+ /**
19
+ * 如果开启了 I18n 多语言功能,那么会出现此 API,通过它可以获取到当前请求对应的本地化数据。
20
+ *
21
+ * 详细使用说明,请查看 {@link I18n}
22
+ * - `ctx.__ = function (key, value[, value2, ...])`: 类似 `util.format` 接口
23
+ * - `ctx.__ = function (key, values)`: 支持数组下标占位符方式,如
24
+ * - `__` 的别名是 `gettext(key, value)`
25
+ *
26
+ * > NOTE: __ 是两个下划线哦!
27
+ * @function Context#__
28
+ * @example
29
+ * ```js
30
+ * ctx.__('{0} {0} {1} {1}'), ['foo', 'bar'])
31
+ * ctx.gettext('{0} {0} {1} {1}'), ['foo', 'bar'])
32
+ * =>
33
+ * foo foo bar bar
34
+ * ```
35
+ * ##### Controller 下的使用示例
36
+ *
37
+ * ```js
38
+ * module.exports = function* () {
39
+ * this.body = {
40
+ * message: this.__('Welcome back, %s!', this.user.name),
41
+ * // 或者使用 gettext,如果觉得 __ 不好看的话
42
+ * // message: this.gettext('Welcome back, %s!', this.user.name),
43
+ * user: this.user,
44
+ * };
45
+ * };
46
+ * ```
47
+ *
48
+ * ##### View 文件下的使用示例
49
+ *
50
+ * ```html
51
+ * <li>{{ __('Email') }}: {{ user.email }}</li>
52
+ * <li>
53
+ * {{ __('Hello %s, how are you today?', user.name) }}
54
+ * </li>
55
+ * <li>
56
+ * {{ __('{0} {0} {1} {1}'), ['foo', 'bar']) }}
57
+ * </li>
58
+ * ```
59
+ *
60
+ * ##### locale 参数获取途径
61
+ *
62
+ * 优先级从上到下:
63
+ *
64
+ * - query: `/?locale=en-US`
65
+ * - cookie: `locale=zh-TW`
66
+ * - header: `Accept-Language: zh-CN,zh;q=0.5`
67
+ */
68
+ __(key: string, value?: any, ...args: any[]): string;
69
+ __locale: string;
70
+ __getLocale(): string;
71
+ __localeOrigin: string;
72
+ __getLocaleOrigin(): string;
73
+ __setLocale(locale: string): void;
72
74
  }
75
+ //#endregion
76
+ export { I18nContext as default };
@@ -1,176 +1,152 @@
1
- import { debuglog } from 'node:util';
2
- import { Context } from 'egg';
3
1
  import { formatLocale } from "../../utils.js";
4
- const debug = debuglog('egg/i18n/app/extend/context');
5
- export default class I18nContext extends Context {
6
- /**
7
- * get current request locale
8
- * @member Context#locale
9
- * @return {String} lower case locale string, e.g.: 'zh-cn', 'en-us'
10
- */
11
- get locale() {
12
- return this.__getLocale();
13
- }
14
- set locale(l) {
15
- this.__setLocale(l);
16
- }
17
- /**
18
- * `ctx.__` 的别名。
19
- * @see {@link Context#__}
20
- * @function Context#gettext
21
- */
22
- gettext(key, value, ...args) {
23
- return this.app.gettext(this.locale, key, value, ...args);
24
- }
25
- /**
26
- * 如果开启了 I18n 多语言功能,那么会出现此 API,通过它可以获取到当前请求对应的本地化数据。
27
- *
28
- * 详细使用说明,请查看 {@link I18n}
29
- * - `ctx.__ = function (key, value[, value2, ...])`: 类似 `util.format` 接口
30
- * - `ctx.__ = function (key, values)`: 支持数组下标占位符方式,如
31
- * - `__` 的别名是 `gettext(key, value)`
32
- *
33
- * > NOTE: __ 是两个下划线哦!
34
- * @function Context#__
35
- * @example
36
- * ```js
37
- * ctx.__('{0} {0} {1} {1}'), ['foo', 'bar'])
38
- * ctx.gettext('{0} {0} {1} {1}'), ['foo', 'bar'])
39
- * =>
40
- * foo foo bar bar
41
- * ```
42
- * ##### Controller 下的使用示例
43
- *
44
- * ```js
45
- * module.exports = function* () {
46
- * this.body = {
47
- * message: this.__('Welcome back, %s!', this.user.name),
48
- * // 或者使用 gettext,如果觉得 __ 不好看的话
49
- * // message: this.gettext('Welcome back, %s!', this.user.name),
50
- * user: this.user,
51
- * };
52
- * };
53
- * ```
54
- *
55
- * ##### View 文件下的使用示例
56
- *
57
- * ```html
58
- * <li>{{ __('Email') }}: {{ user.email }}</li>
59
- * <li>
60
- * {{ __('Hello %s, how are you today?', user.name) }}
61
- * </li>
62
- * <li>
63
- * {{ __('{0} {0} {1} {1}'), ['foo', 'bar']) }}
64
- * </li>
65
- * ```
66
- *
67
- * ##### locale 参数获取途径
68
- *
69
- * 优先级从上到下:
70
- *
71
- * - query: `/?locale=en-US`
72
- * - cookie: `locale=zh-TW`
73
- * - header: `Accept-Language: zh-CN,zh;q=0.5`
74
- */
75
- __(key, value, ...args) {
76
- return this.gettext(key, value, ...args);
77
- }
78
- // 1. query: /?locale=en-US
79
- // 2. cookie: locale=zh-TW
80
- // 3. header: Accept-Language: zh-CN,zh;q=0.5
81
- __getLocale() {
82
- if (this.__locale) {
83
- return this.__locale;
84
- }
85
- const { localeAlias, defaultLocale, cookieField, queryField, writeCookie } = this.app.config.i18n;
86
- const cookieLocale = this.cookies.get(cookieField, { signed: false });
87
- // 1. Query
88
- let locale = this.query[queryField];
89
- let localeOrigin = 'query';
90
- // 2. Cookie
91
- if (!locale && cookieLocale) {
92
- locale = cookieLocale;
93
- localeOrigin = 'cookie';
94
- }
95
- // 3. Header
96
- if (!locale) {
97
- // Accept-Language: zh-CN,zh;q=0.5
98
- // Accept-Language: zh-CN
99
- let languages = this.acceptsLanguages();
100
- if (languages) {
101
- if (Array.isArray(languages)) {
102
- if (languages[0] === '*') {
103
- languages = languages.slice(1);
104
- }
105
- if (languages.length > 0) {
106
- for (const l of languages) {
107
- const lang = formatLocale(l);
108
- if (this.app.isSupportLocale(lang) || localeAlias[lang]) {
109
- locale = lang;
110
- localeOrigin = 'header';
111
- break;
112
- }
113
- }
114
- }
115
- }
116
- else {
117
- locale = languages;
118
- localeOrigin = 'header';
119
- }
120
- }
121
- // all missing, set it to defaultLocale
122
- if (!locale) {
123
- locale = defaultLocale;
124
- localeOrigin = 'default';
125
- }
126
- }
127
- // cookie alias
128
- if (locale in localeAlias) {
129
- const originalLocale = locale;
130
- locale = localeAlias[locale];
131
- debug('Used alias, received %s but using %s', originalLocale, locale);
132
- }
133
- locale = formatLocale(locale);
134
- // validate locale
135
- if (!this.app.isSupportLocale(locale)) {
136
- debug('Locale %s is not supported. Using default (%s)', locale, defaultLocale);
137
- locale = defaultLocale;
138
- }
139
- // if header not send, set the locale cookie
140
- if (writeCookie && cookieLocale !== locale && !this.headerSent) {
141
- updateCookie(this, locale);
142
- }
143
- debug('Locale: %s from %s', locale, localeOrigin);
144
- this.__locale = locale;
145
- this.__localeOrigin = localeOrigin;
146
- return locale;
147
- }
148
- __getLocaleOrigin() {
149
- if (this.__localeOrigin) {
150
- return this.__localeOrigin;
151
- }
152
- this.__getLocale();
153
- return this.__localeOrigin;
154
- }
155
- __setLocale(locale) {
156
- this.__locale = locale;
157
- this.__localeOrigin = 'set';
158
- if (this.app.config.i18n.writeCookie && !this.headerSent) {
159
- updateCookie(this, locale);
160
- }
161
- }
162
- }
2
+ import { debuglog } from "node:util";
3
+ import { Context } from "egg";
4
+
5
+ //#region src/app/extend/context.ts
6
+ const debug = debuglog("egg/i18n/app/extend/context");
7
+ var I18nContext = class extends Context {
8
+ /**
9
+ * get current request locale
10
+ * @member Context#locale
11
+ * @return {String} lower case locale string, e.g.: 'zh-cn', 'en-us'
12
+ */
13
+ get locale() {
14
+ return this.__getLocale();
15
+ }
16
+ set locale(l) {
17
+ this.__setLocale(l);
18
+ }
19
+ /**
20
+ * `ctx.__` 的别名。
21
+ * @see {@link Context#__}
22
+ * @function Context#gettext
23
+ */
24
+ gettext(key, value, ...args) {
25
+ return this.app.gettext(this.locale, key, value, ...args);
26
+ }
27
+ /**
28
+ * 如果开启了 I18n 多语言功能,那么会出现此 API,通过它可以获取到当前请求对应的本地化数据。
29
+ *
30
+ * 详细使用说明,请查看 {@link I18n}
31
+ * - `ctx.__ = function (key, value[, value2, ...])`: 类似 `util.format` 接口
32
+ * - `ctx.__ = function (key, values)`: 支持数组下标占位符方式,如
33
+ * - `__` 的别名是 `gettext(key, value)`
34
+ *
35
+ * > NOTE: __ 是两个下划线哦!
36
+ * @function Context#__
37
+ * @example
38
+ * ```js
39
+ * ctx.__('{0} {0} {1} {1}'), ['foo', 'bar'])
40
+ * ctx.gettext('{0} {0} {1} {1}'), ['foo', 'bar'])
41
+ * =>
42
+ * foo foo bar bar
43
+ * ```
44
+ * ##### Controller 下的使用示例
45
+ *
46
+ * ```js
47
+ * module.exports = function* () {
48
+ * this.body = {
49
+ * message: this.__('Welcome back, %s!', this.user.name),
50
+ * // 或者使用 gettext,如果觉得 __ 不好看的话
51
+ * // message: this.gettext('Welcome back, %s!', this.user.name),
52
+ * user: this.user,
53
+ * };
54
+ * };
55
+ * ```
56
+ *
57
+ * ##### View 文件下的使用示例
58
+ *
59
+ * ```html
60
+ * <li>{{ __('Email') }}: {{ user.email }}</li>
61
+ * <li>
62
+ * {{ __('Hello %s, how are you today?', user.name) }}
63
+ * </li>
64
+ * <li>
65
+ * {{ __('{0} {0} {1} {1}'), ['foo', 'bar']) }}
66
+ * </li>
67
+ * ```
68
+ *
69
+ * ##### locale 参数获取途径
70
+ *
71
+ * 优先级从上到下:
72
+ *
73
+ * - query: `/?locale=en-US`
74
+ * - cookie: `locale=zh-TW`
75
+ * - header: `Accept-Language: zh-CN,zh;q=0.5`
76
+ */
77
+ __(key, value, ...args) {
78
+ return this.gettext(key, value, ...args);
79
+ }
80
+ __getLocale() {
81
+ if (this.__locale) return this.__locale;
82
+ const { localeAlias, defaultLocale, cookieField, queryField, writeCookie } = this.app.config.i18n;
83
+ const cookieLocale = this.cookies.get(cookieField, { signed: false });
84
+ let locale = this.query[queryField];
85
+ let localeOrigin = "query";
86
+ if (!locale && cookieLocale) {
87
+ locale = cookieLocale;
88
+ localeOrigin = "cookie";
89
+ }
90
+ if (!locale) {
91
+ let languages = this.acceptsLanguages();
92
+ if (languages) if (Array.isArray(languages)) {
93
+ if (languages[0] === "*") languages = languages.slice(1);
94
+ if (languages.length > 0) for (const l of languages) {
95
+ const lang = formatLocale(l);
96
+ if (this.app.isSupportLocale(lang) || localeAlias[lang]) {
97
+ locale = lang;
98
+ localeOrigin = "header";
99
+ break;
100
+ }
101
+ }
102
+ } else {
103
+ locale = languages;
104
+ localeOrigin = "header";
105
+ }
106
+ if (!locale) {
107
+ locale = defaultLocale;
108
+ localeOrigin = "default";
109
+ }
110
+ }
111
+ if (locale in localeAlias) {
112
+ const originalLocale = locale;
113
+ locale = localeAlias[locale];
114
+ debug("Used alias, received %s but using %s", originalLocale, locale);
115
+ }
116
+ locale = formatLocale(locale);
117
+ if (!this.app.isSupportLocale(locale)) {
118
+ debug("Locale %s is not supported. Using default (%s)", locale, defaultLocale);
119
+ locale = defaultLocale;
120
+ }
121
+ if (writeCookie && cookieLocale !== locale && !this.headerSent) updateCookie(this, locale);
122
+ debug("Locale: %s from %s", locale, localeOrigin);
123
+ this.__locale = locale;
124
+ this.__localeOrigin = localeOrigin;
125
+ return locale;
126
+ }
127
+ __getLocaleOrigin() {
128
+ if (this.__localeOrigin) return this.__localeOrigin;
129
+ this.__getLocale();
130
+ return this.__localeOrigin;
131
+ }
132
+ __setLocale(locale) {
133
+ this.__locale = locale;
134
+ this.__localeOrigin = "set";
135
+ if (this.app.config.i18n.writeCookie && !this.headerSent) updateCookie(this, locale);
136
+ }
137
+ };
163
138
  function updateCookie(ctx, locale) {
164
- const { cookieMaxAge, cookieField, cookieDomain } = ctx.app.config.i18n;
165
- const cookieOptions = {
166
- // make sure browser javascript can read the cookie
167
- httpOnly: false,
168
- maxAge: cookieMaxAge,
169
- signed: false,
170
- domain: cookieDomain,
171
- overwrite: true,
172
- };
173
- ctx.cookies.set(cookieField, locale, cookieOptions);
174
- debug('Saved cookie with locale %s, options: %j', locale, cookieOptions);
139
+ const { cookieMaxAge, cookieField, cookieDomain } = ctx.app.config.i18n;
140
+ const cookieOptions = {
141
+ httpOnly: false,
142
+ maxAge: cookieMaxAge,
143
+ signed: false,
144
+ domain: cookieDomain,
145
+ overwrite: true
146
+ };
147
+ ctx.cookies.set(cookieField, locale, cookieOptions);
148
+ debug("Saved cookie with locale %s, options: %j", locale, cookieOptions);
175
149
  }
176
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcHAvZXh0ZW5kL2NvbnRleHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUVyQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRTlCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUU5QyxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsNkJBQTZCLENBQUMsQ0FBQztBQUV0RCxNQUFNLENBQUMsT0FBTyxPQUFPLFdBQVksU0FBUSxPQUFPO0lBQzlDOzs7O09BSUc7SUFDSCxJQUFJLE1BQU07UUFDUixPQUFPLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUM1QixDQUFDO0lBRUQsSUFBSSxNQUFNLENBQUMsQ0FBUztRQUNsQixJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLEdBQVcsRUFBRSxLQUFXLEVBQUUsR0FBRyxJQUFXO1FBQzlDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BaURHO0lBQ0gsRUFBRSxDQUFDLEdBQVcsRUFBRSxLQUFXLEVBQUUsR0FBRyxJQUFXO1FBQ3pDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUdELDJCQUEyQjtJQUMzQiwwQkFBMEI7SUFDMUIsNkNBQTZDO0lBQzdDLFdBQVc7UUFDVCxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNsQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDdkIsQ0FBQztRQUVELE1BQU0sRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQ2xHLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBRXRFLFdBQVc7UUFDWCxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBVyxDQUFDO1FBQzlDLElBQUksWUFBWSxHQUFHLE9BQU8sQ0FBQztRQUUzQixZQUFZO1FBQ1osSUFBSSxDQUFDLE1BQU0sSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUM1QixNQUFNLEdBQUcsWUFBWSxDQUFDO1lBQ3RCLFlBQVksR0FBRyxRQUFRLENBQUM7UUFDMUIsQ0FBQztRQUVELFlBQVk7UUFDWixJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixrQ0FBa0M7WUFDbEMseUJBQXlCO1lBQ3pCLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3hDLElBQUksU0FBUyxFQUFFLENBQUM7Z0JBQ2QsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7b0JBQzdCLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO3dCQUN6QixTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDakMsQ0FBQztvQkFDRCxJQUFJLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7d0JBQ3pCLEtBQUssTUFBTSxDQUFDLElBQUksU0FBUyxFQUFFLENBQUM7NEJBQzFCLE1BQU0sSUFBSSxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQzs0QkFDN0IsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQ0FDeEQsTUFBTSxHQUFHLElBQUksQ0FBQztnQ0FDZCxZQUFZLEdBQUcsUUFBUSxDQUFDO2dDQUN4QixNQUFNOzRCQUNSLENBQUM7d0JBQ0gsQ0FBQztvQkFDSCxDQUFDO2dCQUNILENBQUM7cUJBQU0sQ0FBQztvQkFDTixNQUFNLEdBQUcsU0FBUyxDQUFDO29CQUNuQixZQUFZLEdBQUcsUUFBUSxDQUFDO2dCQUMxQixDQUFDO1lBQ0gsQ0FBQztZQUVELHVDQUF1QztZQUN2QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ1osTUFBTSxHQUFHLGFBQWEsQ0FBQztnQkFDdkIsWUFBWSxHQUFHLFNBQVMsQ0FBQztZQUMzQixDQUFDO1FBQ0gsQ0FBQztRQUVELGVBQWU7UUFDZixJQUFJLE1BQU0sSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUMxQixNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUM7WUFDOUIsTUFBTSxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUM3QixLQUFLLENBQUMsc0NBQXNDLEVBQUUsY0FBYyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFFRCxNQUFNLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTlCLGtCQUFrQjtRQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUN0QyxLQUFLLENBQUMsZ0RBQWdELEVBQUUsTUFBTSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBQy9FLE1BQU0sR0FBRyxhQUFhLENBQUM7UUFDekIsQ0FBQztRQUVELDRDQUE0QztRQUM1QyxJQUFJLFdBQVcsSUFBSSxZQUFZLEtBQUssTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQy9ELFlBQVksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDN0IsQ0FBQztRQUNELEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLFFBQVEsR0FBRyxNQUFNLENBQUM7UUFDdkIsSUFBSSxDQUFDLGNBQWMsR0FBRyxZQUFZLENBQUM7UUFDbkMsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUdELGlCQUFpQjtRQUNmLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztRQUM3QixDQUFDO1FBQ0QsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ25CLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUM3QixDQUFDO0lBRUQsV0FBVyxDQUFDLE1BQWM7UUFDeEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxNQUFNLENBQUM7UUFDdkIsSUFBSSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUM7UUFDNUIsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3pELFlBQVksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDN0IsQ0FBQztJQUNILENBQUM7Q0FDRjtBQUVELFNBQVMsWUFBWSxDQUFDLEdBQVksRUFBRSxNQUFjO0lBQ2hELE1BQU0sRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztJQUN4RSxNQUFNLGFBQWEsR0FBRztRQUNwQixtREFBbUQ7UUFDbkQsUUFBUSxFQUFFLEtBQUs7UUFDZixNQUFNLEVBQUUsWUFBc0I7UUFDOUIsTUFBTSxFQUFFLEtBQUs7UUFDYixNQUFNLEVBQUUsWUFBWTtRQUNwQixTQUFTLEVBQUUsSUFBSTtLQUNoQixDQUFDO0lBQ0YsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLE1BQU0sRUFBRSxhQUFhLENBQUMsQ0FBQztJQUNwRCxLQUFLLENBQUMsMENBQTBDLEVBQUUsTUFBTSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0FBQzNFLENBQUMifQ==
150
+
151
+ //#endregion
152
+ export { I18nContext as default };