build lib

This commit is contained in:
Wang Kejun 2022-07-11 18:45:09 +08:00
parent 7967c99f66
commit 1ff46b6e30
23 changed files with 492 additions and 12 deletions

23
lib/initialize-prod.d.ts vendored Normal file
View File

@ -0,0 +1,23 @@
import { Aspect, AspectWrapper, Checker, StorageSchema, Context, RowStore } from 'oak-domain/lib/types';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { Feature } from './types/Feature';
import { BasicFeatures } from './features';
import { ActionDictOfEntityDict } from 'oak-domain/lib/types/Action';
import { CommonAspectDict } from 'oak-common-aspect';
/**
* @param storageSchema
* @param createFeatures
* @param contextBuilder
* @param context
* @param triggers
* @param checkers
* @param watchers
* @param aspectDict
* @param initialData
* @param actionDict
* @returns
*/
export declare function initialize<ED extends EntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>>(storageSchema: StorageSchema<ED>, createFeatures: (aspectWrapper: AspectWrapper<ED, Cxt, AD>, basicFeatures: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>, context: Cxt) => FD, contextBuilder: (cxtString?: string) => (store: RowStore<ED, Cxt>) => Cxt, serverUrl: string, checkers?: Array<Checker<ED, keyof ED, Cxt>>, actionDict?: ActionDictOfEntityDict<ED>): {
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD;
context: Cxt;
};

76
lib/initialize-prod.js Normal file
View File

@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initialize = void 0;
const Exception_1 = require("oak-domain/lib/types/Exception");
const features_1 = require("./features");
const lodash_1 = require("lodash");
const actionDef_1 = require("oak-domain/lib/store/actionDef");
const CacheStore_1 = require("./cacheStore/CacheStore");
function makeContentTypeAndBody(data) {
return {
contentType: 'application/json',
body: JSON.stringify(data),
};
}
/**
* @param storageSchema
* @param createFeatures
* @param contextBuilder
* @param context
* @param triggers
* @param checkers
* @param watchers
* @param aspectDict
* @param initialData
* @param actionDict
* @returns
*/
function initialize(storageSchema, createFeatures, contextBuilder, serverUrl, checkers, actionDict) {
const cacheStore = new CacheStore_1.CacheStore(storageSchema, contextBuilder);
if (checkers) {
checkers.forEach((checker) => cacheStore.registerChecker(checker));
}
if (actionDict) {
const { checkers: adCheckers } = (0, actionDef_1.analyzeActionDefDict)(storageSchema, actionDict);
adCheckers.forEach((checker) => cacheStore.registerChecker(checker));
}
const context = contextBuilder()(cacheStore);
const wrapper = {
exec: async (name, params) => {
const cxtStr = await context.toString();
const { contentType, body } = makeContentTypeAndBody(params);
const response = await global.fetch(serverUrl, {
method: 'POST',
headers: {
'Content-Type': contentType,
'oak-cxt': cxtStr,
'oak-aspect': name,
},
body,
});
if (response.status > 299) {
const err = new Exception_1.OakExternalException(`网络请求返回异常status是${response.status}`);
throw err;
}
// todo 处理各种异常
const { result, opRecords } = await response.json();
return {
result,
opRecords,
};
},
};
const basicFeatures = (0, features_1.initialize)(wrapper, storageSchema, context, cacheStore);
// basicFeatures.runningNode.setStorageSchema(storageSchema);
const userDefinedfeatures = createFeatures(wrapper, basicFeatures, context);
const intersect = (0, lodash_1.intersection)((0, lodash_1.keys)(basicFeatures), (0, lodash_1.keys)(userDefinedfeatures));
if (intersect.length > 0) {
throw new Error(`用户定义的feature中不能和系统feature同名${intersect.join(',')}`);
}
const features = (0, lodash_1.assign)(basicFeatures, userDefinedfeatures);
return {
features,
context,
};
}
exports.initialize = initialize;

View File

@ -1 +1,5 @@
export declare function initialize(): void;
/**
* vs code能正确定位webpack编译时应该跳过initialize.prod.mp.ts获initialize.prod.web.ts
*/
import { initialize as initMp } from './initialize.prod.mp';
export declare const initialize: typeof initMp;

View File

@ -1,6 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initialize = void 0;
function initialize() {
}
exports.initialize = initialize;
/**
* 此文件是为了vs code能正确定位在webpack编译时应该跳过直接去获取initialize.prod.mp.ts获initialize.prod.web.ts
*/
const initialize_prod_mp_1 = require("./initialize.prod.mp");
console.log('不应该跑到这里');
exports.initialize = initialize_prod_mp_1.initialize;

9
lib/initialize.prod.mp.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
import './utils/wx.polyfill';
import { Aspect, AspectWrapper, Checker, StorageSchema, Context, RowStore } from 'oak-domain/lib/types';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { Feature } from './types/Feature';
import { BasicFeatures } from './features';
import { ActionDictOfEntityDict } from 'oak-domain/lib/types/Action';
import { CommonAspectDict } from 'oak-common-aspect';
import { ExceptionRouters } from './types/ExceptionRoute';
export declare function initialize<ED extends EntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>>(storageSchema: StorageSchema<ED>, createFeatures: (aspectWrapper: AspectWrapper<ED, Cxt, AD>, basicFeatures: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>, context: Cxt) => FD, contextBuilder: (cxtString?: string) => (store: RowStore<ED, Cxt>) => Cxt, translations: Record<string, any>, exceptionRouters: ExceptionRouters | undefined, serverUrl: string, checkers?: Array<Checker<ED, keyof ED, Cxt>>, actionDict?: ActionDictOfEntityDict<ED>): void;

38
lib/initialize.prod.mp.js Normal file
View File

@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initialize = void 0;
require("./utils/wx.polyfill");
const lodash_1 = require("lodash");
const page_mp_1 = require("./page.mp");
const initialize_prod_1 = require("./initialize-prod");
const i18n_1 = require("./platforms/wechatMp/i18n");
function initialize(storageSchema, createFeatures, contextBuilder, translations, exceptionRouters = [], serverUrl, checkers, actionDict) {
const { features, context } = (0, initialize_prod_1.initialize)(storageSchema, createFeatures, contextBuilder, serverUrl, checkers, actionDict);
const exceptionRouterDict = {};
for (const router of exceptionRouters) {
(0, lodash_1.assign)(exceptionRouterDict, {
[router[0].name]: router[1],
});
}
// 初始化locales
if (translations) {
const systemInfo = wx.getSystemInfoSync();
const { language } = systemInfo; // 系统语言
let defaultLocale;
if (language === 'zh_CN') {
defaultLocale = language;
}
//初始化i18n
(0, i18n_1.initI18nWechatMp)({
locales: {
translations,
},
defaultLocale,
});
}
(0, lodash_1.assign)(global, {
OakPage: (options) => (0, page_mp_1.createPage)(options, features, exceptionRouterDict, context),
OakComponent: (options) => (0, page_mp_1.createComponent)(options, features, exceptionRouterDict, context),
});
}
exports.initialize = initialize;

9
lib/initialize.prod.web.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
import './utils/wx.polyfill';
import { Aspect, AspectWrapper, Checker, StorageSchema, Context, RowStore } from 'oak-domain/lib/types';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { Feature } from './types/Feature';
import { BasicFeatures } from './features';
import { ActionDictOfEntityDict } from 'oak-domain/lib/types/Action';
import { CommonAspectDict } from 'oak-common-aspect';
import { ExceptionRouters } from './types/ExceptionRoute';
export declare function initialize<ED extends EntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>>(storageSchema: StorageSchema<ED>, createFeatures: (aspectWrapper: AspectWrapper<ED, Cxt, AD>, basicFeatures: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>, context: Cxt) => FD, contextBuilder: (cxtString?: string) => (store: RowStore<ED, Cxt>) => Cxt, translations: Record<string, any>, exceptionRouters: ExceptionRouters | undefined, serverUrl: string, checkers?: Array<Checker<ED, keyof ED, Cxt>>, actionDict?: ActionDictOfEntityDict<ED>): void;

View File

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initialize = void 0;
require("./utils/wx.polyfill");
const lodash_1 = require("lodash");
const page_web_1 = require("./page.web");
const initialize_prod_1 = require("./initialize-prod");
function initialize(storageSchema, createFeatures, contextBuilder, translations, exceptionRouters = [], serverUrl, checkers, actionDict) {
const { features, context } = (0, initialize_prod_1.initialize)(storageSchema, createFeatures, contextBuilder, serverUrl, checkers, actionDict);
const exceptionRouterDict = {};
for (const router of exceptionRouters) {
(0, lodash_1.assign)(exceptionRouterDict, {
[router[0].name]: router[1],
});
}
(0, lodash_1.assign)(global, {
OakPage: (options) => (0, page_web_1.createPage)(options, features, exceptionRouterDict, context),
OakComponent: (options) => (0, page_web_1.createComponent)(options, features, exceptionRouterDict, context),
});
}
exports.initialize = initialize;

View File

@ -101,7 +101,7 @@ function makeCommonComponentMethods(features, exceptionRouterDict, formData) {
(0, assert_1.default)(typeof relation === 'string');
subEntity = relation;
}
let url = `pickers/${subEntity}?oakIsPicker=true&oakParentEntity=${this.state.oakEntity}&oakParent=${this.state.oakFullpath}&oakPath=${attr}`;
let url = `/pickers/${subEntity}?oakIsPicker=true&oakParentEntity=${this.state.oakEntity}&oakParent=${this.state.oakFullpath}&oakPath=${attr}`;
for (const k in params) {
url += `&${k}=${JSON.stringify(params[k])}`;
}

View File

@ -42,10 +42,25 @@ function makeCommonComponentMethods(features, exceptionRouterDict, formData) {
return this.props.t(key, params);
},
resolveInput(input, keys) {
const { currentTarget, target } = input;
const { currentTarget, target, nativeEvent } = input;
const { value, dataset } = target;
const newDataset = Object.assign({}, dataset);
if (!target.dataset || Object.keys(target.dataset).length === 0) {
const { parentNode } = nativeEvent
.target;
const getDataset = (parentNode) => {
const { dataset: dataset2, parentNode: parentNode2 } = parentNode;
if (!dataset2 || Object.keys(dataset2).length === 0) {
getDataset(parentNode2);
}
else {
Object.assign(newDataset, dataset2);
}
};
getDataset(parentNode);
}
const result = {
dataset,
dataset: newDataset,
value,
};
if (keys) {
@ -148,7 +163,6 @@ function createPage(options, features, exceptionRouterDict, context) {
context.setScene(options.path);
lifetimes?.created && lifetimes.created.call(this);
hiddenMethods.subscribe.call(this);
lifetimes?.attached && lifetimes.attached.call(this);
}
features = features;
isReachBottom = false;
@ -179,6 +193,7 @@ function createPage(options, features, exceptionRouterDict, context) {
await onLoad.call(this, this.props);
methods?.onLoad && methods.onLoad.call(this, this.props);
methods?.onReady && methods.onReady.call(this);
lifetimes?.attached && lifetimes.attached.call(this);
lifetimes?.ready && lifetimes.ready.call(this);
pageLifetimes?.show && pageLifetimes.show.call(this);
}
@ -236,7 +251,6 @@ function createComponent(options, features, exceptionRouterDict, context) {
}
lifetimes?.created && lifetimes.created.call(this);
hiddenMethods.subscribe.call(this);
lifetimes?.attached && lifetimes.attached.call(this);
}
features = features;
isReachBottom = false;
@ -252,6 +266,7 @@ function createComponent(options, features, exceptionRouterDict, context) {
});
}
hiddenMethods.subscribe.call(this);
lifetimes?.attached && lifetimes.attached.call(this);
lifetimes?.ready && lifetimes.ready.call(this);
pageLifetimes?.show && pageLifetimes.show.call(this);
}

1
lib/platforms/web/i18n/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export declare function getI18next(translations: any): import("i18next").i18n;

View File

@ -0,0 +1,116 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getI18next = void 0;
/**
* Created by Administrator on 2018/3/24.
*/
const assert_1 = __importDefault(require("assert"));
const i18next_1 = __importDefault(require("i18next"));
const i18next_chained_backend_1 = __importDefault(require("i18next-chained-backend"));
const i18next_browser_languagedetector_1 = __importDefault(require("i18next-browser-languagedetector"));
const react_i18next_1 = require("react-i18next");
// import { I18nextKeysOnDemand } from 'i18next-keys-ondemand';
const lodash_1 = require("lodash");
/**
* I18N语言包设计思路
* 1在本地缓存中查找
* 2通过xhr请求服务器上的ns文件
* 3若服务器的ns版本作了动态更新在一个key发生miss的时候再请求一次
* @type {string}
*/
const LOCAL_STORE_PREFIX = 'i18next_res_';
/**
* 当一个ns下的key发生了miss的处理
* 当用户本地缓存的ns文件和远端的ns文件不一致时才会发生此时先获得整个新的ns文件的内容储存在本地
* todo 可以做成增量获取但现在没必要 by Xc
* @param keys
* @param lng
* @param ns
* @returns {Promise}
*/
async function translationService(keys, lng, ns) {
const url = `${process.env.PUBLIC_URL}/locales/${lng}/${ns}.json`;
const response = await fetch(url);
const json = await response.json();
if (window.localStorage) {
try {
window.localStorage.setItem(`${LOCAL_STORE_PREFIX}${lng}-${ns}`, JSON.stringify(json));
}
catch (e) {
// f.log('failed to set value for key "' + key + '" to localStorage.');
}
}
const result = {};
keys.forEach((k) => {
const v = (0, lodash_1.get)(json, k);
if (process.env.NODE_ENV !== 'production') {
(0, assert_1.default)(v, `[i18n]:${ns}-${k}最新的服务器数据中无此键值`);
}
(0, lodash_1.assign)(result, { [k]: v });
});
return result;
}
const i18nextInitOptions = {
debug: process.env.NODE_ENV !== 'production',
fallbackLng: 'zh-CN',
ns: ['common', 'error'],
lng: 'zh-CN',
load: 'currentOnly',
defaultNS: 'common',
interpolation: {
escapeValue: false, // not needed for react!!
},
// react i18next special options (optional)
react: {
// wait: true,
bindI18n: 'added languageChanged',
bindI18nStore: 'added',
nsMode: 'default',
useSuspense: false,
},
// backend: {
// backends: [
// LocalStorageBackend, // primary
// HttpBackend, // fallback
// ],
// backendOptions: [
// {
// // prefix for stored languages
// prefix: LOCAL_STORE_PREFIX,
// // expiration
// expirationTime: process.env.NODE_ENV !== 'production' ? 120 * 1000 : 300 * 24 * 3600 * 1000,
// defaultVersion: '2.9.0',
// },
// {
// // for all available options read the backend's repository readme file
// loadPath: `${process.env.PUBLIC_URL}/locales/{{lng}}/{{ns}}.json`,
// },
// ],
// },
returnObjects: true,
joinArrays: true,
saveMissing: true,
};
function getI18next(translations) {
Object.assign(i18nextInitOptions, {
resources: {
'zh-CN': Object.assign(translations, {
common: {
GREETING: 'Hello {{name}}, nice to see you.',
},
}),
},
});
i18next_1.default
// .use(new I18nextKeysOnDemand({ translationGetter: translationService }))
.use(i18next_chained_backend_1.default)
.use(i18next_browser_languagedetector_1.default)
.use(react_i18next_1.initReactI18next) // if not using I18nextProvider
.init(i18nextInitOptions);
return i18next_1.default;
}
exports.getI18next = getI18next;
;

View File

@ -0,0 +1,9 @@
/// <reference types="react" />
import { Breakpoints } from './context';
export interface ResponsiveProviderProps {
children?: React.ReactNode;
breakpoints?: Breakpoints;
}
export declare function ResponsiveProvider(props: ResponsiveProviderProps): import("react").FunctionComponentElement<import("react").ProviderProps<{
breakpoints?: Breakpoints | undefined;
}>>;

View File

@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResponsiveProvider = void 0;
const react_1 = require("react");
const context_1 = require("./context");
function ResponsiveProvider(props) {
const { breakpoints, children } = props;
const value = (0, react_1.useMemo)(() => ({
breakpoints,
}), [breakpoints]);
return (0, react_1.createElement)(context_1.ResponsiveContext.Provider, {
value,
}, children);
}
exports.ResponsiveProvider = ResponsiveProvider;

View File

@ -0,0 +1,20 @@
import * as React from 'react';
export declare type Width = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | string;
export declare type Keys = Width[];
export declare type Values = {
xs: number;
sm: number;
md: number;
lg: number;
xl: number;
xxl: number;
[k: string]: number;
};
export declare type Breakpoints = {
keys: Keys;
values: Values;
};
export declare const defaultBreakpoints: Breakpoints;
export declare const ResponsiveContext: React.Context<{
breakpoints?: Breakpoints | undefined;
}>;

View File

@ -0,0 +1,43 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResponsiveContext = exports.defaultBreakpoints = void 0;
const React = __importStar(require("react"));
const keys = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
const values = {
xs: 0,
sm: 576,
md: 768,
lg: 992,
xl: 1200,
xxl: 1600,
};
exports.defaultBreakpoints = {
keys: keys,
values: values,
};
exports.ResponsiveContext = React.createContext({
breakpoints: exports.defaultBreakpoints,
});

View File

@ -0,0 +1,2 @@
export { ResponsiveProvider } from './ResponsiveProvider';
export { useWidth } from './useWidth';

View File

@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useWidth = exports.ResponsiveProvider = void 0;
var ResponsiveProvider_1 = require("./ResponsiveProvider");
Object.defineProperty(exports, "ResponsiveProvider", { enumerable: true, get: function () { return ResponsiveProvider_1.ResponsiveProvider; } });
var useWidth_1 = require("./useWidth");
Object.defineProperty(exports, "useWidth", { enumerable: true, get: function () { return useWidth_1.useWidth; } });

View File

@ -0,0 +1,4 @@
import { Breakpoints } from './context';
export declare function useWidth(props?: {
breakpoints?: Breakpoints;
}): string;

View File

@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useWidth = void 0;
const react_1 = require("react");
const react_responsive_1 = require("react-responsive");
const context_1 = require("./context");
function useWidth(props) {
const { breakpoints: breakpointsFromContext } = (0, react_1.useContext)(context_1.ResponsiveContext) || {};
const { breakpoints: breakpointsFromProps } = props || {};
const breakpoints = Object.assign(context_1.defaultBreakpoints, breakpointsFromProps, breakpointsFromContext);
let width = 'xs';
const obj = breakpoints.values;
const obj2 = {};
Object.keys(obj)
.sort((ele1, ele2) => obj[ele1] - obj[ele2])
.forEach((key, index) => {
const value = obj[key];
const nextKey = Object.keys(obj)[index + 1];
let result;
if (index === 0) {
if (value === 0) {
result = (0, react_responsive_1.useMediaQuery)({
minWidth: obj[key],
maxWidth: obj[nextKey] - 0.2,
});
}
else {
result = (0, react_responsive_1.useMediaQuery)({
maxWidth: obj[key] - 0.2,
});
}
}
else if (index === Object.keys(obj).length - 1) {
result = (0, react_responsive_1.useMediaQuery)({
minWidth: obj[key],
});
}
else {
result = (0, react_responsive_1.useMediaQuery)({
minWidth: obj[key],
maxWidth: obj[nextKey] - 0.2,
});
}
Object.assign(obj2, {
[key]: result,
});
});
for (let w in obj2) {
if (obj2[w]) {
width = w;
break;
}
}
return width;
}
exports.useWidth = useWidth;

1
lib/types/Page.d.ts vendored
View File

@ -73,6 +73,7 @@ export declare type OakComponentOption<ED extends EntityDict, T extends keyof ED
observers: Record<string, (...args: any[]) => any>;
pageLifetimes: Partial<WechatMiniprogram.Component.PageLifetimes> | undefined;
externalClasses: string[];
options: Partial<WechatMiniprogram.Component.ComponentOptions> | undefined;
}> & ThisType<{
features: FD & BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>;
state: TData & FormedData & OakComponentData<ED, T>;

View File

@ -14,9 +14,17 @@
"uuid": "^8.3.2"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.1.0",
"react-i18next": "^11.18.0",
"react-responsive": "^9.0.0-beta.10",
"react-router-dom": "^6.3.0"
"react-router-dom": "^6.3.0",
"i18next": "^20.6.1",
"i18next-browser-languagedetector": "^6.1.4",
"i18next-chained-backend": "^3.0.2",
"i18next-http-backend": "^1.4.1",
"i18next-localstorage-backend": "^3.1.3",
"i18next-resource-store-loader": "^0.1.2"
},
"devDependencies": {
"@babel/cli": "^7.12.13",

View File

@ -2,7 +2,7 @@
* Created by Administrator on 2018/3/24.
*/
import assert from 'assert';
import i18next from 'i18next';
import i18next, { InitOptions } from 'i18next';
import HttpBackend from 'i18next-http-backend';
import Backend from 'i18next-chained-backend';
import LocalStorageBackend from 'i18next-localstorage-backend'; // primary use cache
@ -112,7 +112,7 @@ export function getI18next(translations: any) {
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next) // if not using I18nextProvider
.init(i18nextInitOptions);
.init(i18nextInitOptions as InitOptions);
return i18next;
};