@wsxjs/wsx-i18next 0.0.18 → 0.0.20
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.
- package/dist/decorator.d.ts +23 -0
- package/dist/decorator.d.ts.map +1 -0
- package/dist/hooks.d.ts +18 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/i18n.d.ts +13 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/{index.mjs → index.cjs} +19 -22
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +10 -111
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -75
- package/dist/index.js.map +1 -0
- package/dist/mixin.d.ts +28 -0
- package/dist/mixin.d.ts.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +11 -10
- package/src/i18n.d.ts +40 -0
- package/src/i18n.ts +7 -5
- package/dist/index.d.mts +0 -114
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @i18n 装饰器 - 自动为组件注入翻译功能
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* @i18n 装饰器 - 自动为组件注入翻译功能
|
|
6
|
+
*
|
|
7
|
+
* 使用方式:
|
|
8
|
+
* ```tsx
|
|
9
|
+
* @i18n('common')
|
|
10
|
+
* export class MyComponent extends WebComponent {
|
|
11
|
+
* render() {
|
|
12
|
+
* return <div>{this.t('welcome')}</div>;
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @param namespace 命名空间,默认为 'common'
|
|
18
|
+
* @returns 类装饰器
|
|
19
|
+
*/
|
|
20
|
+
export declare function i18nDecorator(namespace?: string): <T extends {
|
|
21
|
+
new (...args: any[]): any;
|
|
22
|
+
}>(constructor: T) => T;
|
|
23
|
+
//# sourceMappingURL=decorator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorator.d.ts","sourceRoot":"","sources":["../src/decorator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,SAAS,GAAE,MAAiB,IAErC,CAAC,SAAS;IAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAA;CAAE,EAAE,aAAa,CAAC,KAkG7C,CAAC,CAE/B"}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useTranslation 函数(API 与 react-i18next 兼容)
|
|
3
|
+
*/
|
|
4
|
+
import type { UseTranslationResponse } from "./types";
|
|
5
|
+
/**
|
|
6
|
+
* useTranslation - API 与 react-i18next 兼容的翻译函数
|
|
7
|
+
*
|
|
8
|
+
* **重要说明**:
|
|
9
|
+
* - 这不是 React hook,而是 WSXJS 的普通函数
|
|
10
|
+
* - API 设计参考 react-i18next,但实现方式完全不同
|
|
11
|
+
* - 在 WSXJS 中,需要配合 @state 或 @i18n 装饰器实现响应式
|
|
12
|
+
* - 不会自动响应语言变化,需要手动订阅 languageChanged 事件
|
|
13
|
+
*
|
|
14
|
+
* @param namespace 命名空间,默认为 'common'
|
|
15
|
+
* @returns 翻译对象
|
|
16
|
+
*/
|
|
17
|
+
export declare function useTranslation(namespace?: string): UseTranslationResponse;
|
|
18
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,SAAS,GAAE,MAAiB,GAAG,sBAAsB,CAanF"}
|
package/dist/i18n.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* i18next 配置和初始化
|
|
3
|
+
*/
|
|
4
|
+
import i18next from "i18next";
|
|
5
|
+
import type { I18nConfig } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* 初始化 i18next
|
|
8
|
+
* @param config 配置选项
|
|
9
|
+
* @returns i18n 实例
|
|
10
|
+
*/
|
|
11
|
+
export declare function initI18n(config?: I18nConfig): typeof i18next;
|
|
12
|
+
export declare const i18n: typeof i18next;
|
|
13
|
+
//# sourceMappingURL=i18n.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAG9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,GAAE,UAAe,GAAG,OAAO,OAAO,CAmBhE;AAGD,eAAO,MAAM,IAAI,EAAE,OAAO,OAAiB,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const i18next = require("i18next");
|
|
4
|
+
const LanguageDetector = require("i18next-browser-languagedetector");
|
|
5
|
+
const Backend = require("i18next-http-backend");
|
|
5
6
|
function initI18n(config = {}) {
|
|
6
|
-
|
|
7
|
+
i18next.use(Backend).use(LanguageDetector).init({
|
|
7
8
|
fallbackLng: "en",
|
|
8
9
|
debug: false,
|
|
9
10
|
interpolation: {
|
|
@@ -16,10 +17,9 @@ function initI18n(config = {}) {
|
|
|
16
17
|
defaultNS: "common",
|
|
17
18
|
...config
|
|
18
19
|
});
|
|
19
|
-
return
|
|
20
|
+
return i18next;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
// src/decorator.ts
|
|
22
|
+
const i18n = i18next;
|
|
23
23
|
function i18nDecorator(namespace = "common") {
|
|
24
24
|
return function(constructor) {
|
|
25
25
|
class I18nEnhanced extends constructor {
|
|
@@ -38,7 +38,8 @@ function i18nDecorator(namespace = "common") {
|
|
|
38
38
|
}
|
|
39
39
|
// 生命周期:组件连接时订阅语言变化
|
|
40
40
|
onConnected() {
|
|
41
|
-
|
|
41
|
+
var _a;
|
|
42
|
+
(_a = super.onConnected) == null ? void 0 : _a.call(this);
|
|
42
43
|
const handler = () => {
|
|
43
44
|
if (this.rerender) {
|
|
44
45
|
this.rerender();
|
|
@@ -58,6 +59,7 @@ function i18nDecorator(namespace = "common") {
|
|
|
58
59
|
}
|
|
59
60
|
// 生命周期:组件断开时取消订阅
|
|
60
61
|
onDisconnected() {
|
|
62
|
+
var _a;
|
|
61
63
|
if (this._i18nUnsubscribe && typeof this._i18nUnsubscribe === "function") {
|
|
62
64
|
try {
|
|
63
65
|
this._i18nUnsubscribe();
|
|
@@ -77,7 +79,7 @@ function i18nDecorator(namespace = "common") {
|
|
|
77
79
|
if (this._languageChangedHandler) {
|
|
78
80
|
delete this._languageChangedHandler;
|
|
79
81
|
}
|
|
80
|
-
super.onDisconnected
|
|
82
|
+
(_a = super.onDisconnected) == null ? void 0 : _a.call(this);
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
Object.setPrototypeOf(I18nEnhanced, constructor);
|
|
@@ -88,8 +90,6 @@ function i18nDecorator(namespace = "common") {
|
|
|
88
90
|
return I18nEnhanced;
|
|
89
91
|
};
|
|
90
92
|
}
|
|
91
|
-
|
|
92
|
-
// src/hooks.ts
|
|
93
93
|
function useTranslation(namespace = "common") {
|
|
94
94
|
const t = (key, options) => {
|
|
95
95
|
return i18n.t(key, { ns: namespace, ...options });
|
|
@@ -101,8 +101,6 @@ function useTranslation(namespace = "common") {
|
|
|
101
101
|
ready: i18n.isInitialized
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
|
-
|
|
105
|
-
// src/mixin.ts
|
|
106
104
|
function withI18n(Base, defaultNamespace = "common") {
|
|
107
105
|
return class extends Base {
|
|
108
106
|
t(key, namespace, options) {
|
|
@@ -120,11 +118,10 @@ function withI18n(Base, defaultNamespace = "common") {
|
|
|
120
118
|
}
|
|
121
119
|
};
|
|
122
120
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
};
|
|
121
|
+
exports.i18n = i18nDecorator;
|
|
122
|
+
exports.i18nDecorator = i18nDecorator;
|
|
123
|
+
exports.i18nInstance = i18n;
|
|
124
|
+
exports.initI18n = initI18n;
|
|
125
|
+
exports.useTranslation = useTranslation;
|
|
126
|
+
exports.withI18n = withI18n;
|
|
127
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/i18n.ts","../src/decorator.ts","../src/hooks.ts","../src/mixin.ts"],"sourcesContent":["/**\n * i18next 配置和初始化\n */\n\nimport i18next from \"i18next\";\nimport LanguageDetector from \"i18next-browser-languagedetector\";\nimport Backend from \"i18next-http-backend\";\nimport type { I18nConfig } from \"./types\";\n\n/**\n * 初始化 i18next\n * @param config 配置选项\n * @returns i18n 实例\n */\nexport function initI18n(config: I18nConfig = {}): typeof i18next {\n i18next\n .use(Backend)\n .use(LanguageDetector)\n .init({\n fallbackLng: \"en\",\n debug: false,\n interpolation: {\n escapeValue: false,\n },\n backend: {\n loadPath: \"/locales/{{lng}}/{{ns}}.json\",\n },\n ns: [\"common\", \"home\", \"docs\", \"examples\"],\n defaultNS: \"common\",\n ...config,\n });\n\n return i18next;\n}\n\n// 导出 i18n 实例(直接导出常量)\nexport const i18n: typeof i18next = i18next;\n","/**\n * @i18n 装饰器 - 自动为组件注入翻译功能\n */\n\nimport { i18n } from \"./i18n\";\n\n/**\n * @i18n 装饰器 - 自动为组件注入翻译功能\n *\n * 使用方式:\n * ```tsx\n * @i18n('common')\n * export class MyComponent extends WebComponent {\n * render() {\n * return <div>{this.t('welcome')}</div>;\n * }\n * }\n * ```\n *\n * @param namespace 命名空间,默认为 'common'\n * @returns 类装饰器\n */\nexport function i18nDecorator(namespace: string = \"common\") {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return function <T extends { new (...args: any[]): any }>(constructor: T) {\n class I18nEnhanced extends constructor {\n // 使用 public 而不是 private,因为导出的匿名类类型限制\n public _i18nNamespace!: string;\n public _i18nUnsubscribe?: () => void;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n constructor(...args: any[]) {\n super(...args);\n // 初始化命名空间\n this._i18nNamespace = namespace;\n }\n\n // 注入 t 方法\n public t(key: string, options?: object): string {\n return i18n.t(key, { ns: this._i18nNamespace, ...options });\n }\n\n // 注入 i18n 实例\n public get i18n() {\n return i18n;\n }\n\n // 生命周期:组件连接时订阅语言变化\n public onConnected(): void {\n // 先调用父类的 onConnected(如果存在)\n super.onConnected?.();\n\n // 创建回调函数并保存引用,以便后续取消订阅\n const handler = (() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((this as any).rerender) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this as any).rerender();\n }\n }) as () => void;\n\n // 保存回调引用以便取消订阅\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this as any)._languageChangedHandler = handler;\n\n // 订阅语言变化事件\n const unsubscribe = i18n.on(\"languageChanged\", handler);\n\n // 如果返回的是函数,直接使用;否则使用 off 方法\n if (typeof unsubscribe === \"function\") {\n this._i18nUnsubscribe = unsubscribe;\n } else {\n // 如果 i18n.on 返回的不是函数,创建一个取消订阅函数\n // 使用 off 方法(如果可用)或空函数\n this._i18nUnsubscribe = () => {\n if (typeof i18n.off === \"function\") {\n i18n.off(\"languageChanged\", handler);\n }\n };\n }\n }\n\n // 生命周期:组件断开时取消订阅\n public onDisconnected(): void {\n // 取消 i18n 订阅\n if (this._i18nUnsubscribe && typeof this._i18nUnsubscribe === \"function\") {\n try {\n this._i18nUnsubscribe();\n } catch {\n // 如果 unsubscribe 调用失败,尝试使用 off 方法(如果可用)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handler = (this as any)._languageChangedHandler;\n if (handler && typeof i18n.off === \"function\") {\n i18n.off(\"languageChanged\", handler);\n }\n }\n this._i18nUnsubscribe = undefined;\n } else {\n // 如果 unsubscribe 不是函数,尝试使用 off 方法(如果可用)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handler = (this as any)._languageChangedHandler;\n if (handler && typeof i18n.off === \"function\") {\n i18n.off(\"languageChanged\", handler);\n }\n }\n // 清理回调引用\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((this as any)._languageChangedHandler) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n delete (this as any)._languageChangedHandler;\n }\n\n // 调用父类的 onDisconnected(如果存在)\n super.onDisconnected?.();\n }\n }\n // 复制静态属性和方法\n Object.setPrototypeOf(I18nEnhanced, constructor);\n Object.defineProperty(I18nEnhanced, \"name\", {\n value: constructor.name,\n writable: false,\n });\n return I18nEnhanced as T;\n };\n}\n","/**\n * useTranslation 函数(API 与 react-i18next 兼容)\n */\n\nimport { i18n } from \"./i18n\";\nimport type { UseTranslationResponse } from \"./types\";\n\n/**\n * useTranslation - API 与 react-i18next 兼容的翻译函数\n *\n * **重要说明**:\n * - 这不是 React hook,而是 WSXJS 的普通函数\n * - API 设计参考 react-i18next,但实现方式完全不同\n * - 在 WSXJS 中,需要配合 @state 或 @i18n 装饰器实现响应式\n * - 不会自动响应语言变化,需要手动订阅 languageChanged 事件\n *\n * @param namespace 命名空间,默认为 'common'\n * @returns 翻译对象\n */\nexport function useTranslation(namespace: string = \"common\"): UseTranslationResponse {\n // 创建一个包装函数,保持 API 兼容性\n const t = (key: string, options?: object): string => {\n // 每次调用 t() 时,i18n.t() 会使用当前的 i18n.language\n // 所以只要组件重渲染,就会得到新的翻译\n return i18n.t(key, { ns: namespace, ...options });\n };\n return {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n t: t as any,\n i18n,\n ready: i18n.isInitialized,\n };\n}\n","/**\n * Mixin API - 为基类添加 i18n 支持\n */\n\nimport { i18n } from \"./i18n\";\nimport type { WebComponent, LightComponent } from \"@wsxjs/wsx-core\";\n\n/**\n * 为任何继承自 WebComponent 或 LightComponent 的类添加 i18n 支持\n *\n * 使用方式:\n * ```tsx\n * export class MyComponent extends withI18n(WebComponent, 'common') {\n * render() {\n * return <div>{this.t('welcome')}</div>;\n * }\n * }\n *\n * export class MyLightComponent extends withI18n(LightComponent, 'common') {\n * render() {\n * return <div>{this.t('welcome')}</div>;\n * }\n * }\n * ```\n *\n * @param Base 基类(WebComponent 或 LightComponent)\n * @param defaultNamespace 默认命名空间\n * @returns 增强后的类\n */\nexport function withI18n<T extends typeof WebComponent | typeof LightComponent>(\n Base: T,\n defaultNamespace: string = \"common\"\n): T {\n return class extends Base {\n protected t(key: string, namespace?: string, options?: object): string {\n return i18n.t(key, { ns: namespace || defaultNamespace, ...options });\n }\n\n protected get i18n() {\n return i18n;\n }\n\n protected onConnected(): void {\n // 订阅语言变化事件,自动触发重渲染\n i18n.on(\"languageChanged\", () => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((this as any).rerender) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this as any).rerender();\n }\n });\n }\n } as T;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,114 +1,13 @@
|
|
|
1
|
-
import i18n$1, { TFunction, i18n } from 'i18next';
|
|
2
|
-
export { default as i18nInstance } from 'i18next';
|
|
3
|
-
import { WebComponent, LightComponent } from '@wsxjs/wsx-core';
|
|
4
|
-
|
|
5
1
|
/**
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* i18n 配置接口
|
|
11
|
-
*/
|
|
12
|
-
interface I18nConfig {
|
|
13
|
-
fallbackLng?: string;
|
|
14
|
-
debug?: boolean;
|
|
15
|
-
resources?: Record<string, Record<string, object>>;
|
|
16
|
-
backend?: {
|
|
17
|
-
loadPath?: string;
|
|
18
|
-
};
|
|
19
|
-
ns?: string[];
|
|
20
|
-
defaultNS?: string;
|
|
21
|
-
interpolation?: {
|
|
22
|
-
escapeValue?: boolean;
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* useTranslation 返回类型
|
|
27
|
-
*/
|
|
28
|
-
interface UseTranslationResponse {
|
|
29
|
-
t: TFunction;
|
|
30
|
-
i18n: i18n;
|
|
31
|
-
ready: boolean;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* i18next 配置和初始化
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 初始化 i18next
|
|
40
|
-
* @param config 配置选项
|
|
41
|
-
* @returns i18n 实例
|
|
42
|
-
*/
|
|
43
|
-
declare function initI18n(config?: I18nConfig): typeof i18n$1;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @i18n 装饰器 - 自动为组件注入翻译功能
|
|
47
|
-
*/
|
|
48
|
-
/**
|
|
49
|
-
* @i18n 装饰器 - 自动为组件注入翻译功能
|
|
50
|
-
*
|
|
51
|
-
* 使用方式:
|
|
52
|
-
* ```tsx
|
|
53
|
-
* @i18n('common')
|
|
54
|
-
* export class MyComponent extends WebComponent {
|
|
55
|
-
* render() {
|
|
56
|
-
* return <div>{this.t('welcome')}</div>;
|
|
57
|
-
* }
|
|
58
|
-
* }
|
|
59
|
-
* ```
|
|
60
|
-
*
|
|
61
|
-
* @param namespace 命名空间,默认为 'common'
|
|
62
|
-
* @returns 类装饰器
|
|
63
|
-
*/
|
|
64
|
-
declare function i18nDecorator(namespace?: string): <T extends {
|
|
65
|
-
new (...args: any[]): any;
|
|
66
|
-
}>(constructor: T) => T;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* useTranslation 函数(API 与 react-i18next 兼容)
|
|
70
|
-
*/
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* useTranslation - API 与 react-i18next 兼容的翻译函数
|
|
74
|
-
*
|
|
75
|
-
* **重要说明**:
|
|
76
|
-
* - 这不是 React hook,而是 WSXJS 的普通函数
|
|
77
|
-
* - API 设计参考 react-i18next,但实现方式完全不同
|
|
78
|
-
* - 在 WSXJS 中,需要配合 @state 或 @i18n 装饰器实现响应式
|
|
79
|
-
* - 不会自动响应语言变化,需要手动订阅 languageChanged 事件
|
|
80
|
-
*
|
|
81
|
-
* @param namespace 命名空间,默认为 'common'
|
|
82
|
-
* @returns 翻译对象
|
|
83
|
-
*/
|
|
84
|
-
declare function useTranslation(namespace?: string): UseTranslationResponse;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Mixin API - 为基类添加 i18n 支持
|
|
88
|
-
*/
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* 为任何继承自 WebComponent 或 LightComponent 的类添加 i18n 支持
|
|
92
|
-
*
|
|
93
|
-
* 使用方式:
|
|
94
|
-
* ```tsx
|
|
95
|
-
* export class MyComponent extends withI18n(WebComponent, 'common') {
|
|
96
|
-
* render() {
|
|
97
|
-
* return <div>{this.t('welcome')}</div>;
|
|
98
|
-
* }
|
|
99
|
-
* }
|
|
100
|
-
*
|
|
101
|
-
* export class MyLightComponent extends withI18n(LightComponent, 'common') {
|
|
102
|
-
* render() {
|
|
103
|
-
* return <div>{this.t('welcome')}</div>;
|
|
104
|
-
* }
|
|
105
|
-
* }
|
|
106
|
-
* ```
|
|
2
|
+
* @wsxjs/wsx-i18next - i18next integration for WSXJS components
|
|
107
3
|
*
|
|
108
|
-
*
|
|
109
|
-
* @param defaultNamespace 默认命名空间
|
|
110
|
-
* @returns 增强后的类
|
|
4
|
+
* 为 WSXJS 组件提供 i18next 国际化支持
|
|
111
5
|
*/
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
6
|
+
import { i18n as i18nInstance, initI18n } from "./i18n";
|
|
7
|
+
export { i18nInstance, initI18n };
|
|
8
|
+
import { i18nDecorator } from "./decorator";
|
|
9
|
+
export { i18nDecorator as i18n, i18nDecorator };
|
|
10
|
+
export { useTranslation } from "./hooks";
|
|
11
|
+
export { withI18n } from "./mixin";
|
|
12
|
+
export type { I18nConfig, UseTranslationResponse } from "./types";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,IAAI,IAAI,YAAY,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;AAGlC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,IAAI,IAAI,EAAE,aAAa,EAAE,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,50 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
i18n: () => i18nDecorator,
|
|
34
|
-
i18nDecorator: () => i18nDecorator,
|
|
35
|
-
i18nInstance: () => import_i18next.default,
|
|
36
|
-
initI18n: () => initI18n,
|
|
37
|
-
useTranslation: () => useTranslation,
|
|
38
|
-
withI18n: () => withI18n
|
|
39
|
-
});
|
|
40
|
-
module.exports = __toCommonJS(index_exports);
|
|
41
|
-
|
|
42
|
-
// src/i18n.ts
|
|
43
|
-
var import_i18next = __toESM(require("i18next"));
|
|
44
|
-
var import_i18next_browser_languagedetector = __toESM(require("i18next-browser-languagedetector"));
|
|
45
|
-
var import_i18next_http_backend = __toESM(require("i18next-http-backend"));
|
|
1
|
+
import i18next from "i18next";
|
|
2
|
+
import LanguageDetector from "i18next-browser-languagedetector";
|
|
3
|
+
import Backend from "i18next-http-backend";
|
|
46
4
|
function initI18n(config = {}) {
|
|
47
|
-
|
|
5
|
+
i18next.use(Backend).use(LanguageDetector).init({
|
|
48
6
|
fallbackLng: "en",
|
|
49
7
|
debug: false,
|
|
50
8
|
interpolation: {
|
|
@@ -57,10 +15,9 @@ function initI18n(config = {}) {
|
|
|
57
15
|
defaultNS: "common",
|
|
58
16
|
...config
|
|
59
17
|
});
|
|
60
|
-
return
|
|
18
|
+
return i18next;
|
|
61
19
|
}
|
|
62
|
-
|
|
63
|
-
// src/decorator.ts
|
|
20
|
+
const i18n = i18next;
|
|
64
21
|
function i18nDecorator(namespace = "common") {
|
|
65
22
|
return function(constructor) {
|
|
66
23
|
class I18nEnhanced extends constructor {
|
|
@@ -71,54 +28,56 @@ function i18nDecorator(namespace = "common") {
|
|
|
71
28
|
}
|
|
72
29
|
// 注入 t 方法
|
|
73
30
|
t(key, options) {
|
|
74
|
-
return
|
|
31
|
+
return i18n.t(key, { ns: this._i18nNamespace, ...options });
|
|
75
32
|
}
|
|
76
33
|
// 注入 i18n 实例
|
|
77
34
|
get i18n() {
|
|
78
|
-
return
|
|
35
|
+
return i18n;
|
|
79
36
|
}
|
|
80
37
|
// 生命周期:组件连接时订阅语言变化
|
|
81
38
|
onConnected() {
|
|
82
|
-
|
|
39
|
+
var _a;
|
|
40
|
+
(_a = super.onConnected) == null ? void 0 : _a.call(this);
|
|
83
41
|
const handler = () => {
|
|
84
42
|
if (this.rerender) {
|
|
85
43
|
this.rerender();
|
|
86
44
|
}
|
|
87
45
|
};
|
|
88
46
|
this._languageChangedHandler = handler;
|
|
89
|
-
const unsubscribe =
|
|
47
|
+
const unsubscribe = i18n.on("languageChanged", handler);
|
|
90
48
|
if (typeof unsubscribe === "function") {
|
|
91
49
|
this._i18nUnsubscribe = unsubscribe;
|
|
92
50
|
} else {
|
|
93
51
|
this._i18nUnsubscribe = () => {
|
|
94
|
-
if (typeof
|
|
95
|
-
|
|
52
|
+
if (typeof i18n.off === "function") {
|
|
53
|
+
i18n.off("languageChanged", handler);
|
|
96
54
|
}
|
|
97
55
|
};
|
|
98
56
|
}
|
|
99
57
|
}
|
|
100
58
|
// 生命周期:组件断开时取消订阅
|
|
101
59
|
onDisconnected() {
|
|
60
|
+
var _a;
|
|
102
61
|
if (this._i18nUnsubscribe && typeof this._i18nUnsubscribe === "function") {
|
|
103
62
|
try {
|
|
104
63
|
this._i18nUnsubscribe();
|
|
105
64
|
} catch {
|
|
106
65
|
const handler = this._languageChangedHandler;
|
|
107
|
-
if (handler && typeof
|
|
108
|
-
|
|
66
|
+
if (handler && typeof i18n.off === "function") {
|
|
67
|
+
i18n.off("languageChanged", handler);
|
|
109
68
|
}
|
|
110
69
|
}
|
|
111
70
|
this._i18nUnsubscribe = void 0;
|
|
112
71
|
} else {
|
|
113
72
|
const handler = this._languageChangedHandler;
|
|
114
|
-
if (handler && typeof
|
|
115
|
-
|
|
73
|
+
if (handler && typeof i18n.off === "function") {
|
|
74
|
+
i18n.off("languageChanged", handler);
|
|
116
75
|
}
|
|
117
76
|
}
|
|
118
77
|
if (this._languageChangedHandler) {
|
|
119
78
|
delete this._languageChangedHandler;
|
|
120
79
|
}
|
|
121
|
-
super.onDisconnected
|
|
80
|
+
(_a = super.onDisconnected) == null ? void 0 : _a.call(this);
|
|
122
81
|
}
|
|
123
82
|
}
|
|
124
83
|
Object.setPrototypeOf(I18nEnhanced, constructor);
|
|
@@ -129,31 +88,27 @@ function i18nDecorator(namespace = "common") {
|
|
|
129
88
|
return I18nEnhanced;
|
|
130
89
|
};
|
|
131
90
|
}
|
|
132
|
-
|
|
133
|
-
// src/hooks.ts
|
|
134
91
|
function useTranslation(namespace = "common") {
|
|
135
92
|
const t = (key, options) => {
|
|
136
|
-
return
|
|
93
|
+
return i18n.t(key, { ns: namespace, ...options });
|
|
137
94
|
};
|
|
138
95
|
return {
|
|
139
96
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
97
|
t,
|
|
141
|
-
i18n
|
|
142
|
-
ready:
|
|
98
|
+
i18n,
|
|
99
|
+
ready: i18n.isInitialized
|
|
143
100
|
};
|
|
144
101
|
}
|
|
145
|
-
|
|
146
|
-
// src/mixin.ts
|
|
147
102
|
function withI18n(Base, defaultNamespace = "common") {
|
|
148
103
|
return class extends Base {
|
|
149
104
|
t(key, namespace, options) {
|
|
150
|
-
return
|
|
105
|
+
return i18n.t(key, { ns: namespace || defaultNamespace, ...options });
|
|
151
106
|
}
|
|
152
107
|
get i18n() {
|
|
153
|
-
return
|
|
108
|
+
return i18n;
|
|
154
109
|
}
|
|
155
110
|
onConnected() {
|
|
156
|
-
|
|
111
|
+
i18n.on("languageChanged", () => {
|
|
157
112
|
if (this.rerender) {
|
|
158
113
|
this.rerender();
|
|
159
114
|
}
|
|
@@ -161,12 +116,12 @@ function withI18n(Base, defaultNamespace = "common") {
|
|
|
161
116
|
}
|
|
162
117
|
};
|
|
163
118
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
i18n,
|
|
119
|
+
export {
|
|
120
|
+
i18nDecorator as i18n,
|
|
167
121
|
i18nDecorator,
|
|
168
|
-
i18nInstance,
|
|
122
|
+
i18n as i18nInstance,
|
|
169
123
|
initI18n,
|
|
170
124
|
useTranslation,
|
|
171
125
|
withI18n
|
|
172
|
-
}
|
|
126
|
+
};
|
|
127
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/i18n.ts","../src/decorator.ts","../src/hooks.ts","../src/mixin.ts"],"sourcesContent":["/**\n * i18next 配置和初始化\n */\n\nimport i18next from \"i18next\";\nimport LanguageDetector from \"i18next-browser-languagedetector\";\nimport Backend from \"i18next-http-backend\";\nimport type { I18nConfig } from \"./types\";\n\n/**\n * 初始化 i18next\n * @param config 配置选项\n * @returns i18n 实例\n */\nexport function initI18n(config: I18nConfig = {}): typeof i18next {\n i18next\n .use(Backend)\n .use(LanguageDetector)\n .init({\n fallbackLng: \"en\",\n debug: false,\n interpolation: {\n escapeValue: false,\n },\n backend: {\n loadPath: \"/locales/{{lng}}/{{ns}}.json\",\n },\n ns: [\"common\", \"home\", \"docs\", \"examples\"],\n defaultNS: \"common\",\n ...config,\n });\n\n return i18next;\n}\n\n// 导出 i18n 实例(直接导出常量)\nexport const i18n: typeof i18next = i18next;\n","/**\n * @i18n 装饰器 - 自动为组件注入翻译功能\n */\n\nimport { i18n } from \"./i18n\";\n\n/**\n * @i18n 装饰器 - 自动为组件注入翻译功能\n *\n * 使用方式:\n * ```tsx\n * @i18n('common')\n * export class MyComponent extends WebComponent {\n * render() {\n * return <div>{this.t('welcome')}</div>;\n * }\n * }\n * ```\n *\n * @param namespace 命名空间,默认为 'common'\n * @returns 类装饰器\n */\nexport function i18nDecorator(namespace: string = \"common\") {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return function <T extends { new (...args: any[]): any }>(constructor: T) {\n class I18nEnhanced extends constructor {\n // 使用 public 而不是 private,因为导出的匿名类类型限制\n public _i18nNamespace!: string;\n public _i18nUnsubscribe?: () => void;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n constructor(...args: any[]) {\n super(...args);\n // 初始化命名空间\n this._i18nNamespace = namespace;\n }\n\n // 注入 t 方法\n public t(key: string, options?: object): string {\n return i18n.t(key, { ns: this._i18nNamespace, ...options });\n }\n\n // 注入 i18n 实例\n public get i18n() {\n return i18n;\n }\n\n // 生命周期:组件连接时订阅语言变化\n public onConnected(): void {\n // 先调用父类的 onConnected(如果存在)\n super.onConnected?.();\n\n // 创建回调函数并保存引用,以便后续取消订阅\n const handler = (() => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((this as any).rerender) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this as any).rerender();\n }\n }) as () => void;\n\n // 保存回调引用以便取消订阅\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this as any)._languageChangedHandler = handler;\n\n // 订阅语言变化事件\n const unsubscribe = i18n.on(\"languageChanged\", handler);\n\n // 如果返回的是函数,直接使用;否则使用 off 方法\n if (typeof unsubscribe === \"function\") {\n this._i18nUnsubscribe = unsubscribe;\n } else {\n // 如果 i18n.on 返回的不是函数,创建一个取消订阅函数\n // 使用 off 方法(如果可用)或空函数\n this._i18nUnsubscribe = () => {\n if (typeof i18n.off === \"function\") {\n i18n.off(\"languageChanged\", handler);\n }\n };\n }\n }\n\n // 生命周期:组件断开时取消订阅\n public onDisconnected(): void {\n // 取消 i18n 订阅\n if (this._i18nUnsubscribe && typeof this._i18nUnsubscribe === \"function\") {\n try {\n this._i18nUnsubscribe();\n } catch {\n // 如果 unsubscribe 调用失败,尝试使用 off 方法(如果可用)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handler = (this as any)._languageChangedHandler;\n if (handler && typeof i18n.off === \"function\") {\n i18n.off(\"languageChanged\", handler);\n }\n }\n this._i18nUnsubscribe = undefined;\n } else {\n // 如果 unsubscribe 不是函数,尝试使用 off 方法(如果可用)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const handler = (this as any)._languageChangedHandler;\n if (handler && typeof i18n.off === \"function\") {\n i18n.off(\"languageChanged\", handler);\n }\n }\n // 清理回调引用\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((this as any)._languageChangedHandler) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n delete (this as any)._languageChangedHandler;\n }\n\n // 调用父类的 onDisconnected(如果存在)\n super.onDisconnected?.();\n }\n }\n // 复制静态属性和方法\n Object.setPrototypeOf(I18nEnhanced, constructor);\n Object.defineProperty(I18nEnhanced, \"name\", {\n value: constructor.name,\n writable: false,\n });\n return I18nEnhanced as T;\n };\n}\n","/**\n * useTranslation 函数(API 与 react-i18next 兼容)\n */\n\nimport { i18n } from \"./i18n\";\nimport type { UseTranslationResponse } from \"./types\";\n\n/**\n * useTranslation - API 与 react-i18next 兼容的翻译函数\n *\n * **重要说明**:\n * - 这不是 React hook,而是 WSXJS 的普通函数\n * - API 设计参考 react-i18next,但实现方式完全不同\n * - 在 WSXJS 中,需要配合 @state 或 @i18n 装饰器实现响应式\n * - 不会自动响应语言变化,需要手动订阅 languageChanged 事件\n *\n * @param namespace 命名空间,默认为 'common'\n * @returns 翻译对象\n */\nexport function useTranslation(namespace: string = \"common\"): UseTranslationResponse {\n // 创建一个包装函数,保持 API 兼容性\n const t = (key: string, options?: object): string => {\n // 每次调用 t() 时,i18n.t() 会使用当前的 i18n.language\n // 所以只要组件重渲染,就会得到新的翻译\n return i18n.t(key, { ns: namespace, ...options });\n };\n return {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n t: t as any,\n i18n,\n ready: i18n.isInitialized,\n };\n}\n","/**\n * Mixin API - 为基类添加 i18n 支持\n */\n\nimport { i18n } from \"./i18n\";\nimport type { WebComponent, LightComponent } from \"@wsxjs/wsx-core\";\n\n/**\n * 为任何继承自 WebComponent 或 LightComponent 的类添加 i18n 支持\n *\n * 使用方式:\n * ```tsx\n * export class MyComponent extends withI18n(WebComponent, 'common') {\n * render() {\n * return <div>{this.t('welcome')}</div>;\n * }\n * }\n *\n * export class MyLightComponent extends withI18n(LightComponent, 'common') {\n * render() {\n * return <div>{this.t('welcome')}</div>;\n * }\n * }\n * ```\n *\n * @param Base 基类(WebComponent 或 LightComponent)\n * @param defaultNamespace 默认命名空间\n * @returns 增强后的类\n */\nexport function withI18n<T extends typeof WebComponent | typeof LightComponent>(\n Base: T,\n defaultNamespace: string = \"common\"\n): T {\n return class extends Base {\n protected t(key: string, namespace?: string, options?: object): string {\n return i18n.t(key, { ns: namespace || defaultNamespace, ...options });\n }\n\n protected get i18n() {\n return i18n;\n }\n\n protected onConnected(): void {\n // 订阅语言变化事件,自动触发重渲染\n i18n.on(\"languageChanged\", () => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((this as any).rerender) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this as any).rerender();\n }\n });\n }\n } as T;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/mixin.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mixin API - 为基类添加 i18n 支持
|
|
3
|
+
*/
|
|
4
|
+
import type { WebComponent, LightComponent } from "@wsxjs/wsx-core";
|
|
5
|
+
/**
|
|
6
|
+
* 为任何继承自 WebComponent 或 LightComponent 的类添加 i18n 支持
|
|
7
|
+
*
|
|
8
|
+
* 使用方式:
|
|
9
|
+
* ```tsx
|
|
10
|
+
* export class MyComponent extends withI18n(WebComponent, 'common') {
|
|
11
|
+
* render() {
|
|
12
|
+
* return <div>{this.t('welcome')}</div>;
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* export class MyLightComponent extends withI18n(LightComponent, 'common') {
|
|
17
|
+
* render() {
|
|
18
|
+
* return <div>{this.t('welcome')}</div>;
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @param Base 基类(WebComponent 或 LightComponent)
|
|
24
|
+
* @param defaultNamespace 默认命名空间
|
|
25
|
+
* @returns 增强后的类
|
|
26
|
+
*/
|
|
27
|
+
export declare function withI18n<T extends typeof WebComponent | typeof LightComponent>(Base: T, defaultNamespace?: string): T;
|
|
28
|
+
//# sourceMappingURL=mixin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mixin.d.ts","sourceRoot":"","sources":["../src/mixin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,YAAY,GAAG,OAAO,cAAc,EAC1E,IAAI,EAAE,CAAC,EACP,gBAAgB,GAAE,MAAiB,GACpC,CAAC,CAqBH"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript 类型定义
|
|
3
|
+
*/
|
|
4
|
+
import type { TFunction, i18n as I18nType } from "i18next";
|
|
5
|
+
/**
|
|
6
|
+
* i18n 配置接口
|
|
7
|
+
*/
|
|
8
|
+
export interface I18nConfig {
|
|
9
|
+
fallbackLng?: string;
|
|
10
|
+
debug?: boolean;
|
|
11
|
+
resources?: Record<string, Record<string, object>>;
|
|
12
|
+
backend?: {
|
|
13
|
+
loadPath?: string;
|
|
14
|
+
};
|
|
15
|
+
ns?: string[];
|
|
16
|
+
defaultNS?: string;
|
|
17
|
+
interpolation?: {
|
|
18
|
+
escapeValue?: boolean;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* useTranslation 返回类型
|
|
23
|
+
*/
|
|
24
|
+
export interface UseTranslationResponse {
|
|
25
|
+
t: TFunction;
|
|
26
|
+
i18n: I18nType;
|
|
27
|
+
ready: boolean;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,EAAE;QACN,QAAQ,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACZ,WAAW,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;CACL;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,CAAC,EAAE,SAAS,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAClB"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wsxjs/wsx-i18next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "i18next integration for WSXJS components",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
7
8
|
"types": "./dist/index.d.ts",
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
10
11
|
"types": "./dist/index.d.ts",
|
|
11
|
-
"import": "./dist/index.
|
|
12
|
-
"require": "./dist/index.
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
13
14
|
}
|
|
14
15
|
},
|
|
15
16
|
"repository": {
|
|
@@ -37,15 +38,15 @@
|
|
|
37
38
|
"i18next": "^23.0.0",
|
|
38
39
|
"i18next-browser-languagedetector": "^7.0.0",
|
|
39
40
|
"i18next-http-backend": "^2.0.0",
|
|
40
|
-
"@wsxjs/wsx-core": "0.0.
|
|
41
|
+
"@wsxjs/wsx-core": "0.0.20"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"@types/jest": "^29.0.0",
|
|
44
45
|
"@types/node": "^20.0.0",
|
|
45
46
|
"jest": "^29.0.0",
|
|
46
47
|
"ts-jest": "^29.0.0",
|
|
47
|
-
"
|
|
48
|
-
"
|
|
48
|
+
"typescript": "^5.0.0",
|
|
49
|
+
"vite": "^5.0.0"
|
|
49
50
|
},
|
|
50
51
|
"peerDependencies": {
|
|
51
52
|
"i18next": "^23.0.0"
|
|
@@ -54,8 +55,8 @@
|
|
|
54
55
|
"access": "public"
|
|
55
56
|
},
|
|
56
57
|
"scripts": {
|
|
57
|
-
"build": "
|
|
58
|
-
"dev": "
|
|
58
|
+
"build": "vite build && tsc --emitDeclarationOnly --declaration --declarationMap --outDir dist src/index.ts --moduleResolution node --esModuleInterop --downlevelIteration",
|
|
59
|
+
"dev": "vite build --watch",
|
|
59
60
|
"test": "jest",
|
|
60
61
|
"test:watch": "jest --watch",
|
|
61
62
|
"test:coverage": "jest --coverage",
|
package/src/i18n.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @wsxjs/wsx-i18next 类型声明
|
|
3
|
+
*
|
|
4
|
+
* 为使用 @i18n 装饰器的组件扩展类型定义
|
|
5
|
+
* 这个文件会被包含在包的 dist 目录中,供其他项目使用
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare module "@wsxjs/wsx-core" {
|
|
9
|
+
interface WebComponent {
|
|
10
|
+
/**
|
|
11
|
+
* 翻译函数,由 @i18n 装饰器注入
|
|
12
|
+
* @param key 翻译键
|
|
13
|
+
* @param options 翻译选项(插值变量等)
|
|
14
|
+
* @returns 翻译后的字符串
|
|
15
|
+
*/
|
|
16
|
+
t(key: string, options?: object): string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* i18n 实例,由 @i18n 装饰器注入
|
|
20
|
+
*/
|
|
21
|
+
readonly i18n: import("i18next").i18n;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface LightComponent {
|
|
25
|
+
/**
|
|
26
|
+
* 翻译函数,由 @i18n 装饰器注入
|
|
27
|
+
* @param key 翻译键
|
|
28
|
+
* @param options 翻译选项(插值变量等)
|
|
29
|
+
* @returns 翻译后的字符串
|
|
30
|
+
*/
|
|
31
|
+
t(key: string, options?: object): string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* i18n 实例,由 @i18n 装饰器注入
|
|
35
|
+
*/
|
|
36
|
+
readonly i18n: import("i18next").i18n;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {};
|
package/src/i18n.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* i18next 配置和初始化
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import i18next from "i18next";
|
|
6
6
|
import LanguageDetector from "i18next-browser-languagedetector";
|
|
7
7
|
import Backend from "i18next-http-backend";
|
|
8
8
|
import type { I18nConfig } from "./types";
|
|
@@ -12,8 +12,9 @@ import type { I18nConfig } from "./types";
|
|
|
12
12
|
* @param config 配置选项
|
|
13
13
|
* @returns i18n 实例
|
|
14
14
|
*/
|
|
15
|
-
export function initI18n(config: I18nConfig = {}): typeof
|
|
16
|
-
|
|
15
|
+
export function initI18n(config: I18nConfig = {}): typeof i18next {
|
|
16
|
+
i18next
|
|
17
|
+
.use(Backend)
|
|
17
18
|
.use(LanguageDetector)
|
|
18
19
|
.init({
|
|
19
20
|
fallbackLng: "en",
|
|
@@ -29,7 +30,8 @@ export function initI18n(config: I18nConfig = {}): typeof i18n {
|
|
|
29
30
|
...config,
|
|
30
31
|
});
|
|
31
32
|
|
|
32
|
-
return
|
|
33
|
+
return i18next;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
// 导出 i18n 实例(直接导出常量)
|
|
37
|
+
export const i18n: typeof i18next = i18next;
|
package/dist/index.d.mts
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import i18n$1, { TFunction, i18n } from 'i18next';
|
|
2
|
-
export { default as i18nInstance } from 'i18next';
|
|
3
|
-
import { WebComponent, LightComponent } from '@wsxjs/wsx-core';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* TypeScript 类型定义
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* i18n 配置接口
|
|
11
|
-
*/
|
|
12
|
-
interface I18nConfig {
|
|
13
|
-
fallbackLng?: string;
|
|
14
|
-
debug?: boolean;
|
|
15
|
-
resources?: Record<string, Record<string, object>>;
|
|
16
|
-
backend?: {
|
|
17
|
-
loadPath?: string;
|
|
18
|
-
};
|
|
19
|
-
ns?: string[];
|
|
20
|
-
defaultNS?: string;
|
|
21
|
-
interpolation?: {
|
|
22
|
-
escapeValue?: boolean;
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* useTranslation 返回类型
|
|
27
|
-
*/
|
|
28
|
-
interface UseTranslationResponse {
|
|
29
|
-
t: TFunction;
|
|
30
|
-
i18n: i18n;
|
|
31
|
-
ready: boolean;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* i18next 配置和初始化
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 初始化 i18next
|
|
40
|
-
* @param config 配置选项
|
|
41
|
-
* @returns i18n 实例
|
|
42
|
-
*/
|
|
43
|
-
declare function initI18n(config?: I18nConfig): typeof i18n$1;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @i18n 装饰器 - 自动为组件注入翻译功能
|
|
47
|
-
*/
|
|
48
|
-
/**
|
|
49
|
-
* @i18n 装饰器 - 自动为组件注入翻译功能
|
|
50
|
-
*
|
|
51
|
-
* 使用方式:
|
|
52
|
-
* ```tsx
|
|
53
|
-
* @i18n('common')
|
|
54
|
-
* export class MyComponent extends WebComponent {
|
|
55
|
-
* render() {
|
|
56
|
-
* return <div>{this.t('welcome')}</div>;
|
|
57
|
-
* }
|
|
58
|
-
* }
|
|
59
|
-
* ```
|
|
60
|
-
*
|
|
61
|
-
* @param namespace 命名空间,默认为 'common'
|
|
62
|
-
* @returns 类装饰器
|
|
63
|
-
*/
|
|
64
|
-
declare function i18nDecorator(namespace?: string): <T extends {
|
|
65
|
-
new (...args: any[]): any;
|
|
66
|
-
}>(constructor: T) => T;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* useTranslation 函数(API 与 react-i18next 兼容)
|
|
70
|
-
*/
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* useTranslation - API 与 react-i18next 兼容的翻译函数
|
|
74
|
-
*
|
|
75
|
-
* **重要说明**:
|
|
76
|
-
* - 这不是 React hook,而是 WSXJS 的普通函数
|
|
77
|
-
* - API 设计参考 react-i18next,但实现方式完全不同
|
|
78
|
-
* - 在 WSXJS 中,需要配合 @state 或 @i18n 装饰器实现响应式
|
|
79
|
-
* - 不会自动响应语言变化,需要手动订阅 languageChanged 事件
|
|
80
|
-
*
|
|
81
|
-
* @param namespace 命名空间,默认为 'common'
|
|
82
|
-
* @returns 翻译对象
|
|
83
|
-
*/
|
|
84
|
-
declare function useTranslation(namespace?: string): UseTranslationResponse;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Mixin API - 为基类添加 i18n 支持
|
|
88
|
-
*/
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* 为任何继承自 WebComponent 或 LightComponent 的类添加 i18n 支持
|
|
92
|
-
*
|
|
93
|
-
* 使用方式:
|
|
94
|
-
* ```tsx
|
|
95
|
-
* export class MyComponent extends withI18n(WebComponent, 'common') {
|
|
96
|
-
* render() {
|
|
97
|
-
* return <div>{this.t('welcome')}</div>;
|
|
98
|
-
* }
|
|
99
|
-
* }
|
|
100
|
-
*
|
|
101
|
-
* export class MyLightComponent extends withI18n(LightComponent, 'common') {
|
|
102
|
-
* render() {
|
|
103
|
-
* return <div>{this.t('welcome')}</div>;
|
|
104
|
-
* }
|
|
105
|
-
* }
|
|
106
|
-
* ```
|
|
107
|
-
*
|
|
108
|
-
* @param Base 基类(WebComponent 或 LightComponent)
|
|
109
|
-
* @param defaultNamespace 默认命名空间
|
|
110
|
-
* @returns 增强后的类
|
|
111
|
-
*/
|
|
112
|
-
declare function withI18n<T extends typeof WebComponent | typeof LightComponent>(Base: T, defaultNamespace?: string): T;
|
|
113
|
-
|
|
114
|
-
export { type I18nConfig, type UseTranslationResponse, i18nDecorator as i18n, i18nDecorator, initI18n, useTranslation, withI18n };
|