finovision-i18n-resource 1.0.0
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/README.md +76 -0
- package/dist/i18n-resource.cjs +1 -0
- package/dist/i18n-resource.d.ts +70 -0
- package/dist/i18n-resource.esm.js +1 -0
- package/package.json +56 -0
- package/src/config.ts +77 -0
- package/src/constants.ts +4 -0
- package/src/index.ts +28 -0
- package/src/locale-data.d.ts +27 -0
- package/src/locale-meta.ts +14 -0
- package/src/locales/en.json +8 -0
- package/src/locales/zh-CN.json +8 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# finovision-i18n-resource
|
|
2
|
+
|
|
3
|
+
参照 Coze `studio-i18n-resource` 的 **资源适配包**。文案在 `src/locales/*.json`,由 `config.ts` 静态 import,**构建时打进主包**,浏览器 / Node 用法一致。
|
|
4
|
+
|
|
5
|
+
## 使用
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { buildDefaultConfig, defaultConfig, Locale } from 'finovision-i18n-resource';
|
|
9
|
+
import i18n from 'i18next';
|
|
10
|
+
|
|
11
|
+
// 按语言 ID 筛选(JSON 已在包内,无需 await、无需再 import JSON)
|
|
12
|
+
const resources = buildDefaultConfig([Locale.En, Locale.ZhCN]);
|
|
13
|
+
// 或全部语言:defaultConfig
|
|
14
|
+
|
|
15
|
+
await i18n.init({
|
|
16
|
+
resources,
|
|
17
|
+
lng: Locale.En,
|
|
18
|
+
defaultNS: 'i18n',
|
|
19
|
+
keySeparator: false,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
await i18n.changeLanguage(Locale.ZhCN);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Vue 3 + vue-i18n
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { createI18n } from 'vue-i18n';
|
|
29
|
+
import { buildDefaultConfig, Locale } from 'finovision-i18n-resource';
|
|
30
|
+
|
|
31
|
+
const resources = buildDefaultConfig([Locale.En, Locale.ZhCN]);
|
|
32
|
+
|
|
33
|
+
export const i18n = createI18n({
|
|
34
|
+
legacy: false,
|
|
35
|
+
locale: Locale.En,
|
|
36
|
+
messages: {
|
|
37
|
+
en: resources.en!.i18n,
|
|
38
|
+
'zh-CN': resources['zh-CN']!.i18n,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 手动传入 JSON(可选,覆盖部分语言)
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { assembleI18nResources } from 'finovision-i18n-resource';
|
|
47
|
+
import customEn from './my-en.json';
|
|
48
|
+
|
|
49
|
+
const resources = assembleI18nResources({ en: customEn });
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 安装
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install finovision-i18n-resource
|
|
56
|
+
# 本地联调
|
|
57
|
+
npm install file:../fv-i18n-resource
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 新增语言
|
|
61
|
+
|
|
62
|
+
1. 添加 `src/locales/ja.json`
|
|
63
|
+
2. `npm run dl-i18n`(更新 `Locale` 枚举、`config.ts` 内 import 区块)
|
|
64
|
+
3. `npm run build`
|
|
65
|
+
|
|
66
|
+
## 脚本
|
|
67
|
+
|
|
68
|
+
| 命令 | 说明 |
|
|
69
|
+
|------|------|
|
|
70
|
+
| `npm run dl-i18n` | 生成类型、`locale-meta.ts`、`config.ts` 内联 import |
|
|
71
|
+
| `npm run build` | Rollup 打包(含 JSON) |
|
|
72
|
+
| `npm test` | 构建并测试 |
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e="i18n",o={en:{"404_title":"Sorry, this page doesn't exist","404_content":"Please check your link or try again",Cancel:"Cancel",Confirm:"Confirm",AddSuccessToast:'"{name}" has been added',Coze_token_body:"{num, plural, one {Coze token} other {Coze tokens}}"},"zh-CN":{"404_title":"抱歉,页面不存在","404_content":"请检查链接后重试",Cancel:"取消",Confirm:"确认",AddSuccessToast:"已添加「{name}」",Coze_token_body:"{num, plural, other {Coze 代币}}"}};function t(o,t){const n=t??e,r={};for(const[e,t]of Object.entries(o))t&&(r[e]={[n]:t});return r}const n=t(o);var r;exports.Locale=void 0,(r=exports.Locale||(exports.Locale={})).En="en",r.ZhCN="zh-CN",exports.DEFAULT_I18N_NAMESPACE=e,exports.SUPPORTED_LOCALES=["en","zh-CN"],exports.assembleI18nResources=t,exports.buildDefaultConfig=function(e,n){const r=function(e){return"string"==typeof e?[e]:[...e]}(e),s={};for(const e of r)s[e]=o[e];return t(s,n)},exports.defaultConfig=n,exports.loadLocale=function(e){return o[e]};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** i18next 默认命名空间,与 {@link defaultConfig} 的 resources 结构一致 */
|
|
2
|
+
declare const DEFAULT_I18N_NAMESPACE = "i18n";
|
|
3
|
+
type DefaultI18nNamespace = typeof DEFAULT_I18N_NAMESPACE;
|
|
4
|
+
|
|
5
|
+
/** 支持的语言 ID 列表 */
|
|
6
|
+
declare const SUPPORTED_LOCALES: readonly ["en", "zh-CN"];
|
|
7
|
+
type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
|
|
8
|
+
/**
|
|
9
|
+
* 语言枚举,供 i18next / vue-i18n 使用:
|
|
10
|
+
* i18n.changeLanguage(Locale.ZhCN)
|
|
11
|
+
*/
|
|
12
|
+
declare enum Locale {
|
|
13
|
+
En = "en",
|
|
14
|
+
ZhCN = "zh-CN"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** 扁平 key 文案表 */
|
|
18
|
+
type FlatLocale = Record<string, string>;
|
|
19
|
+
/**
|
|
20
|
+
* 已加载的文案表(手动传入 JSON 时使用)
|
|
21
|
+
*/
|
|
22
|
+
type LocalesInput = Partial<Record<SupportedLocale, FlatLocale>>;
|
|
23
|
+
/** i18next 资源结构:{ [语言]: { [命名空间]: 文案表 } } */
|
|
24
|
+
type I18nResources<NS extends string = string> = Partial<Record<SupportedLocale, Record<NS, FlatLocale>>>;
|
|
25
|
+
/** 按语言 ID 取已打包的文案表 */
|
|
26
|
+
declare function loadLocale(lng: SupportedLocale): FlatLocale;
|
|
27
|
+
/**
|
|
28
|
+
* 将已加载的文案组装为 i18next resources
|
|
29
|
+
*/
|
|
30
|
+
declare function assembleI18nResources<NS extends string = DefaultI18nNamespace>(locales: LocalesInput, ns?: NS): I18nResources<NS>;
|
|
31
|
+
/** 全部语言对应的 i18next resources(文案 JSON 已内联进包) */
|
|
32
|
+
declare const defaultConfig: Partial<Record<"en" | "zh-CN", Record<"i18n", FlatLocale>>>;
|
|
33
|
+
/**
|
|
34
|
+
* 按语言 ID 从包内已打包文案组装 resources(浏览器与 Node 用法相同)
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const resources = buildDefaultConfig(['en', 'zh-CN']);
|
|
38
|
+
* i18n.init({ resources, defaultNS: DEFAULT_I18N_NAMESPACE, lng: Locale.En });
|
|
39
|
+
*/
|
|
40
|
+
declare function buildDefaultConfig<NS extends string = DefaultI18nNamespace>(locales: SupportedLocale | readonly SupportedLocale[], ns?: NS): I18nResources<NS>;
|
|
41
|
+
|
|
42
|
+
// 本文件由 npm run dl-i18n 自动生成,请勿手改
|
|
43
|
+
/** 插值参数类型,仅支持 string | number */
|
|
44
|
+
type InterpolationValue = string | number;
|
|
45
|
+
|
|
46
|
+
// #region 插值参数映射
|
|
47
|
+
interface I18nOptionsMap {
|
|
48
|
+
'AddSuccessToast': { name: InterpolationValue /* 字符串 */ };
|
|
49
|
+
'Coze_token_body': { num: InterpolationValue /* 数字 */ };
|
|
50
|
+
}
|
|
51
|
+
// #endregion
|
|
52
|
+
|
|
53
|
+
// #region 带插值的文案键
|
|
54
|
+
type I18nKeysHasOptionsType = keyof I18nOptionsMap;
|
|
55
|
+
// #endregion
|
|
56
|
+
|
|
57
|
+
// #region 不带插值的文案键
|
|
58
|
+
type I18nKeysNoOptionsType =
|
|
59
|
+
| '404_content'
|
|
60
|
+
| '404_title'
|
|
61
|
+
| 'Cancel'
|
|
62
|
+
| 'Confirm';
|
|
63
|
+
// #endregion
|
|
64
|
+
|
|
65
|
+
// #region 全部文案键
|
|
66
|
+
type Expand<T extends string> = T extends infer U ? U : never;
|
|
67
|
+
type LocaleData = Expand<I18nKeysHasOptionsType | I18nKeysNoOptionsType>;
|
|
68
|
+
|
|
69
|
+
export { DEFAULT_I18N_NAMESPACE, Locale, SUPPORTED_LOCALES, assembleI18nResources, buildDefaultConfig, defaultConfig, loadLocale };
|
|
70
|
+
export type { DefaultI18nNamespace, FlatLocale, I18nKeysHasOptionsType, I18nKeysNoOptionsType, I18nOptionsMap, I18nResources, InterpolationValue, LocaleData, LocalesInput, SupportedLocale };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const n="i18n",e={en:{"404_title":"Sorry, this page doesn't exist","404_content":"Please check your link or try again",Cancel:"Cancel",Confirm:"Confirm",AddSuccessToast:'"{name}" has been added',Coze_token_body:"{num, plural, one {Coze token} other {Coze tokens}}"},"zh-CN":{"404_title":"抱歉,页面不存在","404_content":"请检查链接后重试",Cancel:"取消",Confirm:"确认",AddSuccessToast:"已添加「{name}」",Coze_token_body:"{num, plural, other {Coze 代币}}"}};function o(n){return e[n]}function t(e,o){const t=o??n,r={};for(const[n,o]of Object.entries(e))o&&(r[n]={[t]:o});return r}const r=t(e);function c(n,o){const r=function(n){return"string"==typeof n?[n]:[...n]}(n),c={};for(const n of r)c[n]=e[n];return t(c,o)}const s=["en","zh-CN"];var i;!function(n){n.En="en",n.ZhCN="zh-CN"}(i||(i={}));export{n as DEFAULT_I18N_NAMESPACE,i as Locale,s as SUPPORTED_LOCALES,t as assembleI18nResources,c as buildDefaultConfig,r as defaultConfig,o as loadLocale};
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "finovision-i18n-resource",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "i18n resource adapter with Coze-style flat keys and TypeScript definitions (studio-i18n-resource)",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/i18n-resource.cjs",
|
|
10
|
+
"module": "./dist/i18n-resource.esm.js",
|
|
11
|
+
"types": "./dist/i18n-resource.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/i18n-resource.d.ts",
|
|
15
|
+
"import": "./dist/i18n-resource.esm.js",
|
|
16
|
+
"require": "./dist/i18n-resource.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"src"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"dl-i18n": "node scripts/dl-i18n.mjs",
|
|
25
|
+
"clean": "node -e \"import('node:fs').then(fs=>fs.rmSync('dist',{recursive:true,force:true}))\"",
|
|
26
|
+
"build": "npm run dl-i18n && npm run clean && cross-env NODE_ENV=production rollup -c",
|
|
27
|
+
"build:dev": "npm run dl-i18n && rollup -c",
|
|
28
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
29
|
+
"test": "npm run build:dev && tsx --test test/*.test.ts",
|
|
30
|
+
"test:unit": "tsx --test test/*.test.ts",
|
|
31
|
+
"prepublishOnly": "npm run build"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"i18n",
|
|
35
|
+
"locale",
|
|
36
|
+
"resource",
|
|
37
|
+
"flat-key",
|
|
38
|
+
"coze",
|
|
39
|
+
"typescript",
|
|
40
|
+
"finovision"
|
|
41
|
+
],
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
45
|
+
"@rollup/plugin-node-resolve": "^15.3.0",
|
|
46
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
47
|
+
"@rollup/plugin-typescript": "^12.1.0",
|
|
48
|
+
"@types/node": "^22.10.0",
|
|
49
|
+
"cross-env": "^7.0.3",
|
|
50
|
+
"rollup": "^4.27.0",
|
|
51
|
+
"rollup-plugin-dts": "^6.1.1",
|
|
52
|
+
"tslib": "^2.8.0",
|
|
53
|
+
"tsx": "^4.19.0",
|
|
54
|
+
"typescript": "^5.7.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { DEFAULT_I18N_NAMESPACE, type DefaultI18nNamespace } from './constants';
|
|
2
|
+
import type { SupportedLocale } from './locale-meta';
|
|
3
|
+
|
|
4
|
+
/** 扁平 key 文案表 */
|
|
5
|
+
export type FlatLocale = Record<string, string>;
|
|
6
|
+
|
|
7
|
+
// #region locale-bundles — 由 npm run dl-i18n 生成,请勿手改
|
|
8
|
+
import localeEn from './locales/en.json';
|
|
9
|
+
import localeZhCN from './locales/zh-CN.json';
|
|
10
|
+
|
|
11
|
+
const LOCALE_BUNDLES: Record<SupportedLocale, FlatLocale> = {
|
|
12
|
+
'en': localeEn,
|
|
13
|
+
'zh-CN': localeZhCN,
|
|
14
|
+
};
|
|
15
|
+
// #endregion
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 已加载的文案表(手动传入 JSON 时使用)
|
|
19
|
+
*/
|
|
20
|
+
export type LocalesInput = Partial<Record<SupportedLocale, FlatLocale>>;
|
|
21
|
+
|
|
22
|
+
/** i18next 资源结构:{ [语言]: { [命名空间]: 文案表 } } */
|
|
23
|
+
export type I18nResources<NS extends string = string> = Partial<
|
|
24
|
+
Record<SupportedLocale, Record<NS, FlatLocale>>
|
|
25
|
+
>;
|
|
26
|
+
|
|
27
|
+
function normalizeLocaleIds(
|
|
28
|
+
locales: SupportedLocale | readonly SupportedLocale[],
|
|
29
|
+
): SupportedLocale[] {
|
|
30
|
+
return typeof locales === 'string' ? [locales] : [...locales];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** 按语言 ID 取已打包的文案表 */
|
|
34
|
+
export function loadLocale(lng: SupportedLocale): FlatLocale {
|
|
35
|
+
return LOCALE_BUNDLES[lng];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 将已加载的文案组装为 i18next resources
|
|
40
|
+
*/
|
|
41
|
+
export function assembleI18nResources<NS extends string = DefaultI18nNamespace>(
|
|
42
|
+
locales: LocalesInput,
|
|
43
|
+
ns?: NS,
|
|
44
|
+
): I18nResources<NS> {
|
|
45
|
+
const namespace = (ns ?? DEFAULT_I18N_NAMESPACE) as NS;
|
|
46
|
+
const config = {} as I18nResources<NS>;
|
|
47
|
+
for (const [lng, messages] of Object.entries(locales) as [
|
|
48
|
+
SupportedLocale,
|
|
49
|
+
FlatLocale,
|
|
50
|
+
][]) {
|
|
51
|
+
if (!messages) continue;
|
|
52
|
+
config[lng] = { [namespace]: messages } as I18nResources<NS>[SupportedLocale];
|
|
53
|
+
}
|
|
54
|
+
return config;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** 全部语言对应的 i18next resources(文案 JSON 已内联进包) */
|
|
58
|
+
export const defaultConfig = assembleI18nResources(LOCALE_BUNDLES);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 按语言 ID 从包内已打包文案组装 resources(浏览器与 Node 用法相同)
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* const resources = buildDefaultConfig(['en', 'zh-CN']);
|
|
65
|
+
* i18n.init({ resources, defaultNS: DEFAULT_I18N_NAMESPACE, lng: Locale.En });
|
|
66
|
+
*/
|
|
67
|
+
export function buildDefaultConfig<NS extends string = DefaultI18nNamespace>(
|
|
68
|
+
locales: SupportedLocale | readonly SupportedLocale[],
|
|
69
|
+
ns?: NS,
|
|
70
|
+
): I18nResources<NS> {
|
|
71
|
+
const ids = normalizeLocaleIds(locales);
|
|
72
|
+
const loaded: LocalesInput = {};
|
|
73
|
+
for (const lng of ids) {
|
|
74
|
+
loaded[lng] = LOCALE_BUNDLES[lng];
|
|
75
|
+
}
|
|
76
|
+
return assembleI18nResources(loaded, ns);
|
|
77
|
+
}
|
package/src/constants.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export {
|
|
2
|
+
DEFAULT_I18N_NAMESPACE,
|
|
3
|
+
type DefaultI18nNamespace,
|
|
4
|
+
} from './constants';
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
buildDefaultConfig,
|
|
8
|
+
assembleI18nResources,
|
|
9
|
+
defaultConfig,
|
|
10
|
+
loadLocale,
|
|
11
|
+
type FlatLocale,
|
|
12
|
+
type LocalesInput,
|
|
13
|
+
type I18nResources,
|
|
14
|
+
} from './config';
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
SUPPORTED_LOCALES,
|
|
18
|
+
Locale,
|
|
19
|
+
type SupportedLocale,
|
|
20
|
+
} from './locale-meta';
|
|
21
|
+
|
|
22
|
+
export type {
|
|
23
|
+
InterpolationValue,
|
|
24
|
+
I18nOptionsMap,
|
|
25
|
+
I18nKeysHasOptionsType,
|
|
26
|
+
I18nKeysNoOptionsType,
|
|
27
|
+
LocaleData,
|
|
28
|
+
} from './locale-data';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// 本文件由 npm run dl-i18n 自动生成,请勿手改
|
|
2
|
+
/** 插值参数类型,仅支持 string | number */
|
|
3
|
+
export type InterpolationValue = string | number;
|
|
4
|
+
|
|
5
|
+
// #region 插值参数映射
|
|
6
|
+
export interface I18nOptionsMap {
|
|
7
|
+
'AddSuccessToast': { name: InterpolationValue /* 字符串 */ };
|
|
8
|
+
'Coze_token_body': { num: InterpolationValue /* 数字 */ };
|
|
9
|
+
}
|
|
10
|
+
// #endregion
|
|
11
|
+
|
|
12
|
+
// #region 带插值的文案键
|
|
13
|
+
export type I18nKeysHasOptionsType = keyof I18nOptionsMap;
|
|
14
|
+
// #endregion
|
|
15
|
+
|
|
16
|
+
// #region 不带插值的文案键
|
|
17
|
+
export type I18nKeysNoOptionsType =
|
|
18
|
+
| '404_content'
|
|
19
|
+
| '404_title'
|
|
20
|
+
| 'Cancel'
|
|
21
|
+
| 'Confirm';
|
|
22
|
+
// #endregion
|
|
23
|
+
|
|
24
|
+
// #region 全部文案键
|
|
25
|
+
type Expand<T extends string> = T extends infer U ? U : never;
|
|
26
|
+
export type LocaleData = Expand<I18nKeysHasOptionsType | I18nKeysNoOptionsType>;
|
|
27
|
+
// #endregion
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// 文件由 npm run dl-i18n 自动生成,请勿手改
|
|
2
|
+
/** 支持的语言 ID 列表 */
|
|
3
|
+
export const SUPPORTED_LOCALES = ["en","zh-CN"] as const;
|
|
4
|
+
|
|
5
|
+
export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 语言枚举,供 i18next / vue-i18n 使用:
|
|
9
|
+
* i18n.changeLanguage(Locale.ZhCN)
|
|
10
|
+
*/
|
|
11
|
+
export enum Locale {
|
|
12
|
+
En = 'en',
|
|
13
|
+
ZhCN = 'zh-CN',
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"404_title": "Sorry, this page doesn't exist",
|
|
3
|
+
"404_content": "Please check your link or try again",
|
|
4
|
+
"Cancel": "Cancel",
|
|
5
|
+
"Confirm": "Confirm",
|
|
6
|
+
"AddSuccessToast": "\"{name}\" has been added",
|
|
7
|
+
"Coze_token_body": "{num, plural, one {Coze token} other {Coze tokens}}"
|
|
8
|
+
}
|