I18nextKeysOnDemand

This commit is contained in:
Wang Kejun 2022-07-18 12:51:33 +08:00
parent ed358d58b2
commit 3a2c4bc852
4 changed files with 132 additions and 5 deletions

View File

@ -3,6 +3,7 @@
"version": "1.0.0",
"description": "oak框架中前端与平台无关的逻辑部分",
"dependencies": {
"debounce": "^1.2.1",
"format-message-parse": "^6.2.4",
"lodash": "^4.17.21",
"oak-common-aspect": "file:../oak-common-aspect",
@ -18,7 +19,6 @@
"i18next-browser-languagedetector": "^6.1.4",
"i18next-chained-backend": "^3.0.2",
"i18next-http-backend": "^1.4.1",
"i18next-keys-ondemand": "^0.2.0",
"i18next-localstorage-backend": "^3.1.3",
"i18next-resource-store-loader": "^0.1.2",
"react": "^18.2.0",
@ -34,6 +34,7 @@
"@babel/preset-env": "^7.12.13",
"@babel/preset-typescript": "^7.12.13",
"@types/assert": "^1.5.6",
"@types/debounce": "^1.2.1",
"@types/fs-extra": "^9.0.13",
"@types/lodash": "^4.14.168",
"@types/luxon": "^2.0.9",

View File

@ -58,6 +58,7 @@ export function initialize<
});
}
// 初始化locales
let i18n;
if (translations) {
const systemInfo = wx.getSystemInfoSync();
const { language } = systemInfo; // 系统语言
@ -145,4 +146,8 @@ export function initialize<
TMethod
>(options, features, exceptionRouterDict, context),
});
return {
i18n,
};
}

View File

@ -8,8 +8,8 @@ import Backend from 'i18next-chained-backend';
import LocalStorageBackend from 'i18next-localstorage-backend'; // primary use cache
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
import { I18nextKeysOnDemand } from 'i18next-keys-ondemand';
import { get, assign } from 'lodash';
import I18nextKeysOnDemand from './keys-ondemand';
/**
* I18N语言包设计思路
@ -28,7 +28,7 @@ const LOCAL_STORE_PREFIX = 'i18next_res_';
* @param namespace
* @returns {Promise}
*/
async function translationGetter(
async function translationService(
keys: string[],
language: string,
namespace: string
@ -110,13 +110,16 @@ function getI18nextInitOptions(options?: Record<string, any>) {
export function getI18next(options?: Record<string, any>) {
const i18nextInitOptions = getI18nextInitOptions(options) as InitOptions;
i18next
.use(new I18nextKeysOnDemand({ translationGetter }) as any)
.use(
new I18nextKeysOnDemand({
translationGetter: translationService,
}) as any
)
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next) // if not using I18nextProvider
.init(i18nextInitOptions, (err) => {
// console.log(err);
});
return i18next;

View File

@ -0,0 +1,118 @@
import * as debounce from 'debounce';
import { InitOptions } from 'i18next';
export interface i18nInitOptions extends InitOptions {
on(
event: 'missingKey',
callback: (
lngs: string[],
namespace: string,
key: string,
res: string
) => void
): void;
/**
* Adds multiple key/values.
*/
addResources(lng: string, ns: string, resources: any): void;
options: InitOptions;
}
export interface TranslationMap {
[key: string]: string;
}
export type TranslationGetter = (
keys: string[],
language: string,
namespace: string
) => Promise<TranslationMap>;
interface KeyQueue {
[path: string]: KeysSet;
}
interface KeysSet {
[key: string]: boolean;
}
export interface Options {
/**
* The resource key translator
*
* @type {TranslationGetter}
* @memberof Options
*/
translationGetter: TranslationGetter;
/**
* Value to return for missing keys (default: empty string)
*
* @type {string}
* @memberof Options
*/
missingKeyValue?: string;
/**
* Delay in ms used to debounce the translation requests (default: 100ms)
*
* @type {number}
* @memberof Options
*/
debounceDelay?: number;
}
class I18nextKeysOnDemand {
type: string;
options: Options;
constructor(options: Options) {
this.type = '3rdParty';
this.options = { debounceDelay: 100, missingKeyValue: '', ...options };
}
init(instance: i18nInitOptions) {
const missingKeysQueue: KeyQueue = {};
const options = this.options;
function requestResources(lng: string, ns: string) {
const path = `${lng}.${ns}`;
options
.translationGetter(Object.keys(missingKeysQueue[path]), lng, ns)
.then((result) => {
missingKeysQueue[path] = {};
instance.addResources(lng, ns, result);
});
}
const debouncedRequestResources: { [path: string]: () => void } = {};
function requestKey(key: string, lng: string, ns: string) {
const path = `${lng}.${ns}`;
missingKeysQueue[path] = missingKeysQueue[path] || {};
missingKeysQueue[path][key] = true;
debouncedRequestResources[path] =
debouncedRequestResources[path] ||
debounce(
() => requestResources(lng, ns),
options.debounceDelay
);
debouncedRequestResources[path]();
}
instance.on(
'missingKey',
(lngs: string | string[], ns: string, key: string, res: string) => {
instance.options.parseMissingKeyHandler = () => {
return options.missingKeyValue;
};
const languages = typeof lngs === 'string' ? [lngs] : lngs;
languages.map((l) => requestKey(key, l, ns));
}
);
}
}
export default I18nextKeysOnDemand;