zmdms-utils 0.0.72 → 0.0.74
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/es/crypto.d.ts +3 -0
- package/dist/es/crypto.js +4 -0
- package/dist/es/locales/i18n.d.ts +15 -0
- package/dist/es/locales/t-in-non-react.d.ts +17 -0
- package/dist/es/locales/t-options.d.ts +7 -0
- package/dist/es/locales/use-translation.d.ts +42 -0
- package/dist/es/microAppCreator.d.ts +25 -2
- package/dist/es/microAppCreator.js +28 -6
- package/dist/es/node_modules/html-parse-stringify/dist/html-parse-stringify.module.js +5 -0
- package/dist/es/node_modules/i18next/dist/esm/i18next.js +2242 -0
- package/dist/es/node_modules/js-base64/base64.js +273 -0
- package/dist/es/node_modules/react-i18next/dist/es/Trans.js +47 -0
- package/dist/es/node_modules/react-i18next/dist/es/TransWithoutContext.js +312 -0
- package/dist/es/node_modules/react-i18next/dist/es/context.js +18 -0
- package/dist/es/node_modules/react-i18next/dist/es/defaults.js +21 -0
- package/dist/es/node_modules/react-i18next/dist/es/i18nInstance.js +7 -0
- package/dist/es/node_modules/react-i18next/dist/es/initReactI18next.js +12 -0
- package/dist/es/node_modules/react-i18next/dist/es/unescape.js +27 -0
- package/dist/es/node_modules/react-i18next/dist/es/useTranslation.js +112 -0
- package/dist/es/node_modules/react-i18next/dist/es/utils.js +63 -0
- package/dist/es/node_modules/void-elements/index.js +23 -0
- package/dist/es/request.d.ts +1 -1
- package/dist/es/request.js +4 -3
- package/dist/es/src/locales/i18n.js +16 -0
- package/dist/es/src/locales/t-in-non-react.js +54 -0
- package/dist/es/src/locales/t-options.js +20 -0
- package/dist/es/src/locales/use-translation.js +60 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/package.json +4 -1
- package/src/crypto.ts +6 -0
- package/src/index.ts +4 -1
- package/src/locales/i18n.ts +18 -0
- package/src/locales/index.ts +8 -0
- package/src/locales/t-in-non-react.ts +65 -0
- package/src/locales/t-options.ts +24 -0
- package/src/locales/use-translation.ts +76 -0
- package/src/locales//345/244/232/350/257/255/350/250/200.md +1 -0
- package/src/microAppCreator.ts +47 -8
- package/src/request.ts +5 -4
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const matchHtmlEntity = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g;
|
|
2
|
+
const htmlEntities = {
|
|
3
|
+
'&': '&',
|
|
4
|
+
'&': '&',
|
|
5
|
+
'<': '<',
|
|
6
|
+
'<': '<',
|
|
7
|
+
'>': '>',
|
|
8
|
+
'>': '>',
|
|
9
|
+
''': "'",
|
|
10
|
+
''': "'",
|
|
11
|
+
'"': '"',
|
|
12
|
+
'"': '"',
|
|
13
|
+
' ': ' ',
|
|
14
|
+
' ': ' ',
|
|
15
|
+
'©': '©',
|
|
16
|
+
'©': '©',
|
|
17
|
+
'®': '®',
|
|
18
|
+
'®': '®',
|
|
19
|
+
'…': '…',
|
|
20
|
+
'…': '…',
|
|
21
|
+
'/': '/',
|
|
22
|
+
'/': '/'
|
|
23
|
+
};
|
|
24
|
+
const unescapeHtmlEntity = m => htmlEntities[m];
|
|
25
|
+
const unescape = text => text.replace(matchHtmlEntity, unescapeHtmlEntity);
|
|
26
|
+
|
|
27
|
+
export { unescape };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { useContext, useState, useRef, useEffect, useCallback } from 'react';
|
|
2
|
+
import { I18nContext, ReportNamespaces } from './context.js';
|
|
3
|
+
import { warnOnce, hasLoadedNamespace, loadLanguages, loadNamespaces, isString, isObject } from './utils.js';
|
|
4
|
+
import { getI18n } from './i18nInstance.js';
|
|
5
|
+
import { getDefaults } from './defaults.js';
|
|
6
|
+
|
|
7
|
+
const usePrevious = (value, ignore) => {
|
|
8
|
+
const ref = useRef();
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
ref.current = ignore ? ref.current : value;
|
|
11
|
+
}, [value, ignore]);
|
|
12
|
+
return ref.current;
|
|
13
|
+
};
|
|
14
|
+
const alwaysNewT = (i18n, language, namespace, keyPrefix) => i18n.getFixedT(language, namespace, keyPrefix);
|
|
15
|
+
const useMemoizedT = (i18n, language, namespace, keyPrefix) => useCallback(alwaysNewT(i18n, language, namespace, keyPrefix), [i18n, language, namespace, keyPrefix]);
|
|
16
|
+
const useTranslation = (ns, props = {}) => {
|
|
17
|
+
const {
|
|
18
|
+
i18n: i18nFromProps
|
|
19
|
+
} = props;
|
|
20
|
+
const {
|
|
21
|
+
i18n: i18nFromContext,
|
|
22
|
+
defaultNS: defaultNSFromContext
|
|
23
|
+
} = useContext(I18nContext) || {};
|
|
24
|
+
const i18n = i18nFromProps || i18nFromContext || getI18n();
|
|
25
|
+
if (i18n && !i18n.reportNamespaces) i18n.reportNamespaces = new ReportNamespaces();
|
|
26
|
+
if (!i18n) {
|
|
27
|
+
warnOnce(i18n, 'NO_I18NEXT_INSTANCE', 'useTranslation: You will need to pass in an i18next instance by using initReactI18next');
|
|
28
|
+
const notReadyT = (k, optsOrDefaultValue) => {
|
|
29
|
+
if (isString(optsOrDefaultValue)) return optsOrDefaultValue;
|
|
30
|
+
if (isObject(optsOrDefaultValue) && isString(optsOrDefaultValue.defaultValue)) return optsOrDefaultValue.defaultValue;
|
|
31
|
+
return Array.isArray(k) ? k[k.length - 1] : k;
|
|
32
|
+
};
|
|
33
|
+
const retNotReady = [notReadyT, {}, false];
|
|
34
|
+
retNotReady.t = notReadyT;
|
|
35
|
+
retNotReady.i18n = {};
|
|
36
|
+
retNotReady.ready = false;
|
|
37
|
+
return retNotReady;
|
|
38
|
+
}
|
|
39
|
+
if (i18n.options.react?.wait) warnOnce(i18n, 'DEPRECATED_OPTION', 'useTranslation: It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.');
|
|
40
|
+
const i18nOptions = {
|
|
41
|
+
...getDefaults(),
|
|
42
|
+
...i18n.options.react,
|
|
43
|
+
...props
|
|
44
|
+
};
|
|
45
|
+
const {
|
|
46
|
+
useSuspense,
|
|
47
|
+
keyPrefix
|
|
48
|
+
} = i18nOptions;
|
|
49
|
+
let namespaces = ns || defaultNSFromContext || i18n.options?.defaultNS;
|
|
50
|
+
namespaces = isString(namespaces) ? [namespaces] : namespaces || ['translation'];
|
|
51
|
+
i18n.reportNamespaces.addUsedNamespaces?.(namespaces);
|
|
52
|
+
const ready = (i18n.isInitialized || i18n.initializedStoreOnce) && namespaces.every(n => hasLoadedNamespace(n, i18n, i18nOptions));
|
|
53
|
+
const memoGetT = useMemoizedT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
|
54
|
+
const getT = () => memoGetT;
|
|
55
|
+
const getNewT = () => alwaysNewT(i18n, props.lng || null, i18nOptions.nsMode === 'fallback' ? namespaces : namespaces[0], keyPrefix);
|
|
56
|
+
const [t, setT] = useState(getT);
|
|
57
|
+
let joinedNS = namespaces.join();
|
|
58
|
+
if (props.lng) joinedNS = `${props.lng}${joinedNS}`;
|
|
59
|
+
const previousJoinedNS = usePrevious(joinedNS);
|
|
60
|
+
const isMounted = useRef(true);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
const {
|
|
63
|
+
bindI18n,
|
|
64
|
+
bindI18nStore
|
|
65
|
+
} = i18nOptions;
|
|
66
|
+
isMounted.current = true;
|
|
67
|
+
if (!ready && !useSuspense) {
|
|
68
|
+
if (props.lng) {
|
|
69
|
+
loadLanguages(i18n, props.lng, namespaces, () => {
|
|
70
|
+
if (isMounted.current) setT(getNewT);
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
loadNamespaces(i18n, namespaces, () => {
|
|
74
|
+
if (isMounted.current) setT(getNewT);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (ready && previousJoinedNS && previousJoinedNS !== joinedNS && isMounted.current) {
|
|
79
|
+
setT(getNewT);
|
|
80
|
+
}
|
|
81
|
+
const boundReset = () => {
|
|
82
|
+
if (isMounted.current) setT(getNewT);
|
|
83
|
+
};
|
|
84
|
+
if (bindI18n) i18n?.on(bindI18n, boundReset);
|
|
85
|
+
if (bindI18nStore) i18n?.store.on(bindI18nStore, boundReset);
|
|
86
|
+
return () => {
|
|
87
|
+
isMounted.current = false;
|
|
88
|
+
if (i18n) bindI18n?.split(' ').forEach(e => i18n.off(e, boundReset));
|
|
89
|
+
if (bindI18nStore && i18n) bindI18nStore.split(' ').forEach(e => i18n.store.off(e, boundReset));
|
|
90
|
+
};
|
|
91
|
+
}, [i18n, joinedNS]);
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (isMounted.current && ready) {
|
|
94
|
+
setT(getT);
|
|
95
|
+
}
|
|
96
|
+
}, [i18n, keyPrefix, ready]);
|
|
97
|
+
const ret = [t, i18n, ready];
|
|
98
|
+
ret.t = t;
|
|
99
|
+
ret.i18n = i18n;
|
|
100
|
+
ret.ready = ready;
|
|
101
|
+
if (ready) return ret;
|
|
102
|
+
if (!ready && !useSuspense) return ret;
|
|
103
|
+
throw new Promise(resolve => {
|
|
104
|
+
if (props.lng) {
|
|
105
|
+
loadLanguages(i18n, props.lng, namespaces, () => resolve());
|
|
106
|
+
} else {
|
|
107
|
+
loadNamespaces(i18n, namespaces, () => resolve());
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export { useTranslation };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const warn = (i18n, code, msg, rest) => {
|
|
2
|
+
const args = [msg, {
|
|
3
|
+
code,
|
|
4
|
+
...(rest || {})
|
|
5
|
+
}];
|
|
6
|
+
if (i18n?.services?.logger?.forward) {
|
|
7
|
+
return i18n.services.logger.forward(args, 'warn', 'react-i18next::', true);
|
|
8
|
+
}
|
|
9
|
+
if (isString(args[0])) args[0] = `react-i18next:: ${args[0]}`;
|
|
10
|
+
if (i18n?.services?.logger?.warn) {
|
|
11
|
+
i18n.services.logger.warn(...args);
|
|
12
|
+
} else if (console?.warn) {
|
|
13
|
+
console.warn(...args);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const alreadyWarned = {};
|
|
17
|
+
const warnOnce = (i18n, code, msg, rest) => {
|
|
18
|
+
if (isString(msg) && alreadyWarned[msg]) return;
|
|
19
|
+
if (isString(msg)) alreadyWarned[msg] = new Date();
|
|
20
|
+
warn(i18n, code, msg, rest);
|
|
21
|
+
};
|
|
22
|
+
const loadedClb = (i18n, cb) => () => {
|
|
23
|
+
if (i18n.isInitialized) {
|
|
24
|
+
cb();
|
|
25
|
+
} else {
|
|
26
|
+
const initialized = () => {
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
i18n.off('initialized', initialized);
|
|
29
|
+
}, 0);
|
|
30
|
+
cb();
|
|
31
|
+
};
|
|
32
|
+
i18n.on('initialized', initialized);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const loadNamespaces = (i18n, ns, cb) => {
|
|
36
|
+
i18n.loadNamespaces(ns, loadedClb(i18n, cb));
|
|
37
|
+
};
|
|
38
|
+
const loadLanguages = (i18n, lng, ns, cb) => {
|
|
39
|
+
if (isString(ns)) ns = [ns];
|
|
40
|
+
if (i18n.options.preload && i18n.options.preload.indexOf(lng) > -1) return loadNamespaces(i18n, ns, cb);
|
|
41
|
+
ns.forEach(n => {
|
|
42
|
+
if (i18n.options.ns.indexOf(n) < 0) i18n.options.ns.push(n);
|
|
43
|
+
});
|
|
44
|
+
i18n.loadLanguages(lng, loadedClb(i18n, cb));
|
|
45
|
+
};
|
|
46
|
+
const hasLoadedNamespace = (ns, i18n, options = {}) => {
|
|
47
|
+
if (!i18n.languages || !i18n.languages.length) {
|
|
48
|
+
warnOnce(i18n, 'NO_LANGUAGES', 'i18n.languages were undefined or empty', {
|
|
49
|
+
languages: i18n.languages
|
|
50
|
+
});
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return i18n.hasLoadedNamespace(ns, {
|
|
54
|
+
lng: options.lng,
|
|
55
|
+
precheck: (i18nInstance, loadNotPending) => {
|
|
56
|
+
if (options.bindI18n?.indexOf('languageChanging') > -1 && i18nInstance.services.backendConnector.backend && i18nInstance.isLanguageChangingTo && !loadNotPending(i18nInstance.isLanguageChangingTo, ns)) return false;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const isString = obj => typeof obj === 'string';
|
|
61
|
+
const isObject = obj => typeof obj === 'object' && obj !== null;
|
|
62
|
+
|
|
63
|
+
export { hasLoadedNamespace, isObject, isString, loadLanguages, loadNamespaces, warn, warnOnce };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file automatically generated from `pre-publish.js`.
|
|
3
|
+
* Do not manually edit.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
var voidElements = {
|
|
7
|
+
"area": true,
|
|
8
|
+
"base": true,
|
|
9
|
+
"br": true,
|
|
10
|
+
"col": true,
|
|
11
|
+
"embed": true,
|
|
12
|
+
"hr": true,
|
|
13
|
+
"img": true,
|
|
14
|
+
"input": true,
|
|
15
|
+
"link": true,
|
|
16
|
+
"meta": true,
|
|
17
|
+
"param": true,
|
|
18
|
+
"source": true,
|
|
19
|
+
"track": true,
|
|
20
|
+
"wbr": true
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { voidElements as default };
|
package/dist/es/request.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ interface IOtherOptions {
|
|
|
57
57
|
/** 提示方法 外部传入 */
|
|
58
58
|
messageWarning?: (msg: string, duration: number, callback?: () => void) => void;
|
|
59
59
|
modalConfirm?: (msg: string, callback?: () => void) => void;
|
|
60
|
-
/**
|
|
60
|
+
/** @deprecated 租户ID,只有登录接口 需要 传递。 */
|
|
61
61
|
TenantId?: string;
|
|
62
62
|
/** auth值 */
|
|
63
63
|
Authorization?: string;
|
package/dist/es/request.js
CHANGED
|
@@ -4,7 +4,7 @@ import { removeToken, getToken } from './auth.js';
|
|
|
4
4
|
import { TOKEN_KEY } from './constants.js';
|
|
5
5
|
|
|
6
6
|
var defaultOptions = {
|
|
7
|
-
TenantId: "000000",
|
|
7
|
+
// TenantId: "000000", // 租户ID不需要了
|
|
8
8
|
Authorization: "Basic em1kbXM6em1kbXNfc2VjcmV0",
|
|
9
9
|
timeout: 60000,
|
|
10
10
|
};
|
|
@@ -39,8 +39,9 @@ var AxiosRequest = /** @class */ (function () {
|
|
|
39
39
|
AxiosRequest.prototype.defaultSetting = function () {
|
|
40
40
|
var _this = this;
|
|
41
41
|
// 设置默认请求头
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
// 租户ID只有登录的时候才需要传递
|
|
43
|
+
// this.instanceAxios.defaults.headers.common["Tenant-Id"] =
|
|
44
|
+
// this.otherOptions.TenantId;
|
|
44
45
|
this.instanceAxios.defaults.headers.common["Authorization"] =
|
|
45
46
|
this.otherOptions.Authorization;
|
|
46
47
|
if (this.otherOptions.commonHeaders) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import instance from '../../node_modules/i18next/dist/esm/i18next.js';
|
|
2
|
+
import { initReactI18next } from '../../node_modules/react-i18next/dist/es/initReactI18next.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 初始化逻辑
|
|
6
|
+
* - 本函数主要用于初始化 i18next 实例,同时使用 react-i18next 插件进行 react 组件的支持
|
|
7
|
+
* - 本函数的调用时机,一般是在项目的入口文件中进行调用,如 src/main.tsx 中
|
|
8
|
+
* @param options 参数 同i18next.init 第一个参数
|
|
9
|
+
* @param callback 参数 同i18next.init 第二个参数
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
function initLocale(options, callback) {
|
|
13
|
+
return instance.use(initReactI18next).init(options, callback);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { instance as i18n, initLocale };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import instance from '../../node_modules/i18next/dist/esm/i18next.js';
|
|
2
|
+
import { getTFuncArgs } from './t-options.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* t 函数封装:
|
|
6
|
+
* - 本文件的几个 t 函数,主要用于弥补一些在 React 组件之外使用的场景
|
|
7
|
+
* - 常规情况下,在 react 组件中,更加推荐的是使用 react-i18next 包中的 t 函数,即 const { t } = useTranslate(); 形式
|
|
8
|
+
*/
|
|
9
|
+
/** 包裹一层 try-catch 的 t 函数 */
|
|
10
|
+
var tryT = function (key, defaultValueOrOptions) {
|
|
11
|
+
var _a = getTFuncArgs(defaultValueOrOptions), defaultValue = _a.defaultValue, options = _a.options;
|
|
12
|
+
if (!key) {
|
|
13
|
+
// 情况1:键名为空,返回默认值或键名
|
|
14
|
+
console.error("tryT: \u8BF7\u4E0D\u8981\u4F20\u5165\u7A7A key \u503C\u8FDB\u884C i18n.t \u51FD\u6570\u6267\u884C\uFF0C\u8FD9\u5C06\u4F1A\u5BFC\u81F4\u76F4\u63A5\u8FD4\u56DE\u7A7A\u5B57\u7B26\u4E32\uFF01");
|
|
15
|
+
return defaultValue || key;
|
|
16
|
+
}
|
|
17
|
+
if (!instance.exists(key)) {
|
|
18
|
+
// 情况2:键名不存在,返回默认值或键名
|
|
19
|
+
console.error("tryT: i18n-key '".concat(key, "' \u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u5BF9\u5E94\u7684 @/locales/resources/locales/xx.json \u4E2D\u662F\u5426\u5B58\u5728\u5BF9\u5E94\u503C"));
|
|
20
|
+
return defaultValue || key;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
// 情况3:尝试执行 i18n.t 函数
|
|
24
|
+
return instance.t(key, options);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
// 情况4:执行 i18n.t 函数异常,返回默认值或键名
|
|
28
|
+
console.error("tryT: i18n.t key=".concat(key, " \u51FD\u6570\u6267\u884C\u5F02\u5E38\uFF1Aerr="), err);
|
|
29
|
+
return defaultValue || key;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* 同步版本的 i18n.t 函数(应对在 react 组件外使用的翻译函数)
|
|
34
|
+
* - 如果 i18n 未初始化,则返回默认值或键名
|
|
35
|
+
* - 如果 i18n 初始化后,键名不存在,则返回默认值或键名
|
|
36
|
+
* - 其他正常情况(已经初始化+键名存在),则返回翻译值
|
|
37
|
+
* @description 本函数为在非 react 组件中使用的翻译函数;(在react中请求使用 useTranslate() 返回的 t 函数)
|
|
38
|
+
* @param {string} key
|
|
39
|
+
* @param {TOpionsEx|string} defaultValue 必填值
|
|
40
|
+
* @returns {string}
|
|
41
|
+
* @example
|
|
42
|
+
* const txt = t('someLocaleKey', '兜底默认值');
|
|
43
|
+
*/
|
|
44
|
+
function safeT(key, defaultValueOrOptions) {
|
|
45
|
+
if (instance.isInitialized) {
|
|
46
|
+
return tryT(key, defaultValueOrOptions);
|
|
47
|
+
}
|
|
48
|
+
// 异常情况:没有初始化完成时,返回默认值
|
|
49
|
+
var defaultValue = getTFuncArgs(defaultValueOrOptions).defaultValue;
|
|
50
|
+
console.warn("safeT: i18n is not initialized. Returning defaultValue(".concat(defaultValue, ") or origin key (").concat(key, ")."));
|
|
51
|
+
return defaultValue || key;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { safeT };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 获取 t 函数的参数
|
|
3
|
+
* @param {string | TOpionsEx} defaultValueOrOptions 默认值或者选项
|
|
4
|
+
* @returns { {defaultValue: string, options: TOpionsEx} } 默认值和选项
|
|
5
|
+
*/
|
|
6
|
+
function getTFuncArgs(defaultValueOrOptions) {
|
|
7
|
+
var options = null;
|
|
8
|
+
var defaultValue = "";
|
|
9
|
+
if (typeof defaultValueOrOptions === "string") {
|
|
10
|
+
defaultValue = defaultValueOrOptions;
|
|
11
|
+
options = { defaultValue: defaultValue };
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
options = defaultValueOrOptions;
|
|
15
|
+
defaultValue = options.defaultValue;
|
|
16
|
+
}
|
|
17
|
+
return { defaultValue: defaultValue, options: options };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { getTFuncArgs };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { getTFuncArgs } from './t-options.js';
|
|
2
|
+
import { useTranslation } from '../../node_modules/react-i18next/dist/es/useTranslation.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 这里只是简单代理一下useTranslation,方便后续扩展或添加其他逻辑
|
|
6
|
+
* @param ns 命名空间 大多数情况下都不需要传入这个参数,除非你用到了命名空间。
|
|
7
|
+
* @param options 其他参数 大多数情况下,都不需要关注这个参数。
|
|
8
|
+
* options.keyPrefix 为所有翻译键添加前缀
|
|
9
|
+
* // JSON 文件:{ "greeting": { "welcome": "Welcome" } }
|
|
10
|
+
* const { t } = useTranslation('common', { keyPrefix: 'greeting' });
|
|
11
|
+
* // 使用时省略前缀
|
|
12
|
+
* t('welcome'); // 等价于 t('greeting:welcome')
|
|
13
|
+
* @returns { t, i18n, ready }
|
|
14
|
+
* t: 翻译方法
|
|
15
|
+
* i18n: i18next实例 访问 i18next 的完整 API(如切换语言、加载命名空间)
|
|
16
|
+
* i18n.changeLanguage('zh-CN'); 使用它切换语言,可以触发组件渲染。但是当前项目中是使用全局刷新的模式,来更新语言的。
|
|
17
|
+
* ready: 是否加载完成
|
|
18
|
+
*/
|
|
19
|
+
function useZtTranslation(ns, options) {
|
|
20
|
+
var _a = useTranslation(ns, options), _tOld = _a.t, i18n = _a.i18n, ready = _a.ready;
|
|
21
|
+
// 扩展t方法,用于处理嵌套的翻译键
|
|
22
|
+
var tEnhance = function (key, defaultValueOrOptions) {
|
|
23
|
+
var _a = getTFuncArgs(defaultValueOrOptions), defaultValue = _a.defaultValue, options = _a.options;
|
|
24
|
+
if (!key) {
|
|
25
|
+
// 情况1:键名为空,返回默认值或键名
|
|
26
|
+
console.error("tEnhance: \u8BF7\u4E0D\u8981\u4F20\u5165\u7A7A key \u503C\u8FDB\u884C t \u51FD\u6570\u6267\u884C\uFF0C\u8FD9\u5C06\u4F1A\u5BFC\u81F4\u76F4\u63A5\u8FD4\u56DE\u7A7A\u5B57\u7B26\u4E32\uFF01");
|
|
27
|
+
return defaultValue || key;
|
|
28
|
+
}
|
|
29
|
+
if (!i18n.exists(key)) {
|
|
30
|
+
// 情况2:键名不存在,返回默认值或键名
|
|
31
|
+
console.error("tEnhance: i18n-key '".concat(key, "' \u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u5BF9\u5E94\u7684 @/locales/resources/locales/xx.json \u4E2D\u662F\u5426\u5B58\u5728\u5BF9\u5E94\u503C"));
|
|
32
|
+
return defaultValue || key;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return _tOld(key, options);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.warn("tEnhance: t \u51FD\u6570\u6267\u884C\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5! key=".concat(key, ", err="), error);
|
|
39
|
+
return defaultValue || key || "unknown";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
/**
|
|
44
|
+
* t函数的使用方式:基本上使用1、2两种方式就可以了。
|
|
45
|
+
* 1、t('key') // 基础用法
|
|
46
|
+
* 2、t('greeting', { name: 'John' }); // 对应 JSON: "greeting": "Hello {{name}}"
|
|
47
|
+
* 3、t('auth:login'); // 显式指定命名空间
|
|
48
|
+
*
|
|
49
|
+
* 关于t函数的第二个参数的说明。
|
|
50
|
+
* 为了防止一些异常情况,翻译失败。可以传入一个默认值。这个默认值就是原本的中文就行。
|
|
51
|
+
* 1、t('key', '默认值');
|
|
52
|
+
* 2、t('key', { defaultValue: '默认值', ...otherOptions });
|
|
53
|
+
*/
|
|
54
|
+
t: tEnhance,
|
|
55
|
+
i18n: i18n,
|
|
56
|
+
ready: ready,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { useZtTranslation as useTranslation };
|
package/dist/index.d.ts
CHANGED
|
@@ -18,3 +18,9 @@ export { imgToPdf } from './es/pdf.js';
|
|
|
18
18
|
export { htmlToPdf } from './es/htmlToPdf.js';
|
|
19
19
|
export { htmlPrint, imgPrint, pdfPrint, windowPrint } from './es/print.js';
|
|
20
20
|
export { createWater, getDefaultContent, mergeWaterConfig } from './es/water.js';
|
|
21
|
+
export { initLocale } from './es/locales/i18n.js';
|
|
22
|
+
export { useTranslation } from './es/locales/use-translation.js';
|
|
23
|
+
export { safeT } from './es/locales/t-in-non-react.js';
|
|
24
|
+
export { Base64 } from 'js-base64';
|
|
25
|
+
export { default as i18n } from 'i18next';
|
|
26
|
+
export { Trans } from 'react-i18next';
|
package/dist/index.js
CHANGED
|
@@ -18,3 +18,9 @@ export { imgToPdf } from './es/pdf.js';
|
|
|
18
18
|
export { htmlToPdf } from './es/htmlToPdf.js';
|
|
19
19
|
export { htmlPrint, imgPrint, pdfPrint, windowPrint } from './es/print.js';
|
|
20
20
|
export { createWater, getDefaultContent, mergeWaterConfig } from './es/water.js';
|
|
21
|
+
export { initLocale } from './es/src/locales/i18n.js';
|
|
22
|
+
export { useTranslation } from './es/src/locales/use-translation.js';
|
|
23
|
+
export { safeT } from './es/src/locales/t-in-non-react.js';
|
|
24
|
+
export { Base64 } from './es/node_modules/js-base64/base64.js';
|
|
25
|
+
export { default as i18n } from './es/node_modules/i18next/dist/esm/i18next.js';
|
|
26
|
+
export { Trans } from './es/node_modules/react-i18next/dist/es/Trans.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zmdms-utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.74",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -36,9 +36,12 @@
|
|
|
36
36
|
"crypto-js": "^4.1.1",
|
|
37
37
|
"dayjs": "^1.11.10",
|
|
38
38
|
"html2canvas": "^1.4.1",
|
|
39
|
+
"i18next": "^25.1.2",
|
|
40
|
+
"js-base64": "^3.7.7",
|
|
39
41
|
"jspdf": "^2.5.1",
|
|
40
42
|
"print-js": "^1.6.0",
|
|
41
43
|
"qiankun": "^2.10.8",
|
|
44
|
+
"react-i18next": "^15.5.1",
|
|
42
45
|
"rimraf": "^4.4.1",
|
|
43
46
|
"rollup": "^3.20.2",
|
|
44
47
|
"rollup-plugin-dts": "^5.3.0",
|
package/src/crypto.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import CryptoJS from "crypto-js";
|
|
2
|
+
import { Base64 } from "js-base64";
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* 对称加密和hash
|
|
6
|
+
*/
|
|
3
7
|
export class Crypto {
|
|
4
8
|
// 使用AesUtil.genAesKey()生成,需和后端配置保持一致
|
|
5
9
|
private aesKey: string;
|
|
@@ -107,3 +111,5 @@ export class Crypto {
|
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
export const md5 = (str: string) => CryptoJS.MD5(str).toString().toLowerCase();
|
|
114
|
+
|
|
115
|
+
export { Base64 };
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { initMainApp, initGlobalError } from "./mainApp";
|
|
|
4
4
|
export { getToken, setToken, removeToken, parseToken } from "./auth";
|
|
5
5
|
export { AxiosRequest, type IOtherOptions, type IOptions } from "./request";
|
|
6
6
|
export { getBaseUrl } from "./baseUrl";
|
|
7
|
-
export { Crypto, md5 } from "./crypto";
|
|
7
|
+
export { Crypto, md5, Base64 } from "./crypto";
|
|
8
8
|
export {
|
|
9
9
|
delay,
|
|
10
10
|
emitter,
|
|
@@ -78,3 +78,6 @@ export { windowPrint, htmlPrint, imgPrint, pdfPrint } from "./print";
|
|
|
78
78
|
|
|
79
79
|
// 水印相关
|
|
80
80
|
export { createWater, mergeWaterConfig, getDefaultContent } from "./water";
|
|
81
|
+
|
|
82
|
+
// 多语言相关
|
|
83
|
+
export { initLocale, i18n, useTranslation, Trans, safeT } from "./locales";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import i18next from "i18next";
|
|
2
|
+
import { initReactI18next } from "react-i18next";
|
|
3
|
+
|
|
4
|
+
type InitOptions = Parameters<typeof i18next.init>;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 初始化逻辑
|
|
8
|
+
* - 本函数主要用于初始化 i18next 实例,同时使用 react-i18next 插件进行 react 组件的支持
|
|
9
|
+
* - 本函数的调用时机,一般是在项目的入口文件中进行调用,如 src/main.tsx 中
|
|
10
|
+
* @param options 参数 同i18next.init 第一个参数
|
|
11
|
+
* @param callback 参数 同i18next.init 第二个参数
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
function initLocale(options: InitOptions[0], callback?: InitOptions[1]) {
|
|
15
|
+
return i18next.use(initReactI18next).init(options, callback);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { initLocale, i18next as i18n };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* t 函数封装:
|
|
3
|
+
* - 本文件的几个 t 函数,主要用于弥补一些在 React 组件之外使用的场景
|
|
4
|
+
* - 常规情况下,在 react 组件中,更加推荐的是使用 react-i18next 包中的 t 函数,即 const { t } = useTranslate(); 形式
|
|
5
|
+
*/
|
|
6
|
+
import { i18n } from "./i18n";
|
|
7
|
+
import type { TOpionsEx } from "./t-options";
|
|
8
|
+
import { getTFuncArgs } from "./t-options";
|
|
9
|
+
|
|
10
|
+
/** 包裹一层 try-catch 的 t 函数 */
|
|
11
|
+
const tryT = (
|
|
12
|
+
key: string,
|
|
13
|
+
defaultValueOrOptions: string | TOpionsEx
|
|
14
|
+
): string => {
|
|
15
|
+
const { defaultValue, options } = getTFuncArgs(defaultValueOrOptions);
|
|
16
|
+
if (!key) {
|
|
17
|
+
// 情况1:键名为空,返回默认值或键名
|
|
18
|
+
console.error(
|
|
19
|
+
`tryT: 请不要传入空 key 值进行 i18n.t 函数执行,这将会导致直接返回空字符串!`
|
|
20
|
+
);
|
|
21
|
+
return defaultValue || key;
|
|
22
|
+
}
|
|
23
|
+
if (!i18n.exists(key)) {
|
|
24
|
+
// 情况2:键名不存在,返回默认值或键名
|
|
25
|
+
console.error(
|
|
26
|
+
`tryT: i18n-key '${key}' 不存在,请检查对应的 @/locales/resources/locales/xx.json 中是否存在对应值`
|
|
27
|
+
);
|
|
28
|
+
return defaultValue || key;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
// 情况3:尝试执行 i18n.t 函数
|
|
32
|
+
return i18n.t(key, options);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
// 情况4:执行 i18n.t 函数异常,返回默认值或键名
|
|
35
|
+
console.error(`tryT: i18n.t key=${key} 函数执行异常:err=`, err);
|
|
36
|
+
return defaultValue || key;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 同步版本的 i18n.t 函数(应对在 react 组件外使用的翻译函数)
|
|
42
|
+
* - 如果 i18n 未初始化,则返回默认值或键名
|
|
43
|
+
* - 如果 i18n 初始化后,键名不存在,则返回默认值或键名
|
|
44
|
+
* - 其他正常情况(已经初始化+键名存在),则返回翻译值
|
|
45
|
+
* @description 本函数为在非 react 组件中使用的翻译函数;(在react中请求使用 useTranslate() 返回的 t 函数)
|
|
46
|
+
* @param {string} key
|
|
47
|
+
* @param {TOpionsEx|string} defaultValue 必填值
|
|
48
|
+
* @returns {string}
|
|
49
|
+
* @example
|
|
50
|
+
* const txt = t('someLocaleKey', '兜底默认值');
|
|
51
|
+
*/
|
|
52
|
+
export function safeT(
|
|
53
|
+
key: string,
|
|
54
|
+
defaultValueOrOptions: string | TOpionsEx
|
|
55
|
+
): string {
|
|
56
|
+
if (i18n.isInitialized) {
|
|
57
|
+
return tryT(key, defaultValueOrOptions);
|
|
58
|
+
}
|
|
59
|
+
// 异常情况:没有初始化完成时,返回默认值
|
|
60
|
+
const { defaultValue } = getTFuncArgs(defaultValueOrOptions);
|
|
61
|
+
console.warn(
|
|
62
|
+
`safeT: i18n is not initialized. Returning defaultValue(${defaultValue}) or origin key (${key}).`
|
|
63
|
+
);
|
|
64
|
+
return defaultValue || key;
|
|
65
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import type { TOptions } from "i18next";
|
|
3
|
+
|
|
4
|
+
export interface TOpionsEx extends TOptions {
|
|
5
|
+
defaultValue: string; // 必须填值
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 获取 t 函数的参数
|
|
10
|
+
* @param {string | TOpionsEx} defaultValueOrOptions 默认值或者选项
|
|
11
|
+
* @returns { {defaultValue: string, options: TOpionsEx} } 默认值和选项
|
|
12
|
+
*/
|
|
13
|
+
export function getTFuncArgs(defaultValueOrOptions: string | TOpionsEx) {
|
|
14
|
+
let options: TOpionsEx | null = null;
|
|
15
|
+
let defaultValue = "";
|
|
16
|
+
if (typeof defaultValueOrOptions === "string") {
|
|
17
|
+
defaultValue = defaultValueOrOptions;
|
|
18
|
+
options = { defaultValue };
|
|
19
|
+
} else {
|
|
20
|
+
options = defaultValueOrOptions;
|
|
21
|
+
defaultValue = options.defaultValue;
|
|
22
|
+
}
|
|
23
|
+
return { defaultValue, options };
|
|
24
|
+
}
|