From af4162d1c92b2cc473938ad711e1cc41d2bf7c75 Mon Sep 17 00:00:00 2001 From: Xc Date: Fri, 18 Aug 2023 12:32:30 +0800 Subject: [PATCH] =?UTF-8?q?i18n=E7=9A=84wxs=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/platforms/wechatMp/i18n/wxs.d.ts | 1 + lib/platforms/wechatMp/i18n/wxs.js | 132 ++++++++++++++++++++++++ package.json | 2 +- src/platforms/wechatMp/i18n/wxs.ts | 144 +++++++++++++++++++++++++++ test/test.ts | 38 ++----- 5 files changed, 287 insertions(+), 30 deletions(-) create mode 100644 lib/platforms/wechatMp/i18n/wxs.d.ts create mode 100644 lib/platforms/wechatMp/i18n/wxs.js create mode 100644 src/platforms/wechatMp/i18n/wxs.ts diff --git a/lib/platforms/wechatMp/i18n/wxs.d.ts b/lib/platforms/wechatMp/i18n/wxs.d.ts new file mode 100644 index 00000000..cc2792c8 --- /dev/null +++ b/lib/platforms/wechatMp/i18n/wxs.d.ts @@ -0,0 +1 @@ +export declare function t(key: string, p1: any, p2: any, p3: any, p4: any, p5: any, p6: any): string; diff --git a/lib/platforms/wechatMp/i18n/wxs.js b/lib/platforms/wechatMp/i18n/wxs.js new file mode 100644 index 00000000..79a7707c --- /dev/null +++ b/lib/platforms/wechatMp/i18n/wxs.js @@ -0,0 +1,132 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.t = void 0; +/** + * 在wxs环境下实现部分i18n-js内的逻辑 + * 参见i18n-js/src/i18n.ts中的translate逻辑 + * + * 这里为了能在小程序的wxs环境中运行,部分代码写的很奇怪 + * 还需要在编译时将正则统一编译成小程序的 getRegExp 语法 + */ +function isSet(value) { + return value !== undefined && value !== null; +} +function get(object, path) { + // 沿着路径寻找到对应的值,未找到则返回默认值 defaultValue + return (path.split('.').reduce(function (o, k) { + return (o || {})[k]; + }, object)); +} +function _getPlural(count) { + switch (count) { + case 0: { + return 'zero'; + } + case 1: { + return 'one'; + } + default: { + return 'other'; + } + } +} +var PlaceHolder = /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm; +function interpolate(message, options) { + if (typeof message === 'string') { + var matches = message.match(PlaceHolder); + if (!matches) { + return message; + } + while (matches.length) { + var value = void 0; + var placeholder = matches.shift(); + var name_1 = placeholder.replace(PlaceHolder, "$1"); + if (isSet(options[name_1])) { + value = options[name_1].toString().replace(/\$/gm, "_#$#_"); + } + else if (options.hasOwnProperty(name_1)) { + value = ''; + } + else { + value = "!missing placeholder ".concat(name_1); + } + var regex = new RegExp(placeholder.replace(/\{/gm, "\\{").replace(/\}/gm, "\\}")); + message = message.replace(regex, value); + } + return message.replace(/_#\$#_/g, "$"); + } + else if (typeof message === 'object' && isSet(options.count)) { + // 复数形式 + var pluralization = _getPlural(options.count); + var message2 = message[pluralization]; + return interpolate(message2, options); + } + else { + return "!unrecoganized locales: ".concat(JSON.stringify(message)); + } +} +function constructFullKey(key, namespace, moduleName) { + var key2 = key; + if (key.indexOf('::') > 0) { + // 公共模块 + key2 = "".concat(moduleName, "-l-").concat(key).replace('::', '.'); + } + else if (key.indexOf(':') > 0) { + // entity + key2 = key.replace(':', '.'); + } + else { + // 自身模块 + key2 = "".concat(namespace, ".").concat(key); + } + return key2; +} +function t(key, p1, p2, p3, p4, p5, p6) { + var fullKey = ''; + var hasLocale = false; + if (arguments.length === 7) { + // key, params, oakLocales, oakLng, oakDefaultLng, namespace, module + var params = p1, locales = p2, lng = p3, defaultLng = p4, namespace = p5, moduleName = p6; + if (locales && lng) { + hasLocale = true; + fullKey = constructFullKey(key, namespace, moduleName); + var _a = locales, _b = lng, lngLocales = _a[_b]; + var lngTrans = lngLocales && get(lngLocales, fullKey); + if (lngTrans) { + return interpolate(lngTrans, params); + } + if (defaultLng) { + var _c = locales, _d = defaultLng, dftLngLocales = _c[_d]; + var dftLngTrans = dftLngLocales && get(dftLngLocales, fullKey); + if (dftLngTrans) { + return interpolate(dftLngTrans, params); + } + } + } + } + else if (arguments.length === 6) { + var locales = p1, lng = p2, defaultLng = p3, namespace = p4, moduleName = p5; + if (locales && lng) { + hasLocale = true; + fullKey = constructFullKey(key, namespace, moduleName); + var _e = locales, _f = lng, lngLocales = _e[_f]; + var lngTrans = lngLocales && get(lngLocales, fullKey); + if (lngTrans) { + return lngTrans; + } + if (defaultLng) { + var _g = locales, _h = defaultLng, dftLngLocales = _g[_h]; + var dftLngTrans = dftLngLocales && get(dftLngLocales, fullKey); + if (dftLngTrans) { + return dftLngTrans; + } + } + } + } + // 到这里说明miss了,通知AppService层,并返回value + if (hasLocale) { + // todo + } + return fullKey.split('.').pop(); +} +exports.t = t; diff --git a/package.json b/package.json index 415bab6a..758d23cb 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "copy-wxs": "copyfiles -u 1 src/**/*.wxs lib/", "copy-xml": "copyfiles -u 1 src/**/*.xml lib/ & copyfiles -u 1 src/**/*.wxml lib/", "build": "tsc && npm run copy-js && npm run copy-less && npm run copy-wxs && npm run copy-svg && npm run copy-xml && npm run copy-json", - "test": "ts-node ./test/test2.ts", + "test": "ts-node ./test/test.ts", "prepare": "rimraf node_modules/react & rimraf node_modules/react-dom & rimraf node_modules/react-router & rimraf node_modules/react-router-dom", "remove-antd": "rimraf node_modules/antd & rimraf node_modules/antd-mobile & rimraf node_modules/@ant-design & rimraf node_modules/antd-mobile-icons & rimraf node_modules/antd-mobile-v5-count" }, diff --git a/src/platforms/wechatMp/i18n/wxs.ts b/src/platforms/wechatMp/i18n/wxs.ts new file mode 100644 index 00000000..ea5482cd --- /dev/null +++ b/src/platforms/wechatMp/i18n/wxs.ts @@ -0,0 +1,144 @@ +/** + * 在wxs环境下实现部分i18n-js内的逻辑 + * 参见i18n-js/src/i18n.ts中的translate逻辑 + * + * 这里为了能在小程序的wxs环境中运行,部分代码写的很奇怪 + * 还需要在编译时将正则统一编译成小程序的 getRegExp 语法 + */ +function isSet(value: unknown): boolean { + return value !== undefined && value !== null; +} + +function get(object: Record>, path: string): string | undefined { + // 沿着路径寻找到对应的值,未找到则返回默认值 defaultValue + return ( + path.split('.').reduce((o: any, k: string) => { + return (o || {})[k]; + }, object) + ); +} + + +function _getPlural(count: number) { + switch (count) { + case 0: { + return 'zero'; + } + case 1: { + return 'one'; + } + default: { + return 'other'; + } + } +} + +const PlaceHolder = /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm; +function interpolate(message: any, options: Record): string { + if (typeof message === 'string') { + const matches = message.match(PlaceHolder); + + if (!matches) { + return message; + } + + while (matches.length) { + let value: string; + const placeholder = matches.shift() as string; + const name = placeholder.replace(PlaceHolder, "$1"); + + if (isSet(options[name])) { + value = options[name].toString().replace(/\$/gm, "_#$#_"); + } else if (options.hasOwnProperty(name)) { + value = ''; + } else { + value = `!missing placeholder ${name}`; + } + + const regex = new RegExp( + placeholder.replace(/\{/gm, "\\{").replace(/\}/gm, "\\}"), + ); + + message = message.replace(regex, value); + } + + return message.replace(/_#\$#_/g, "$"); + } + else if (typeof message === 'object' && isSet(options.count)) { + // 复数形式 + const pluralization = _getPlural(options.count); + const message2 = message[pluralization]; + return interpolate(message2, options); + } + else { + return `!unrecoganized locales: ${JSON.stringify(message)}`; + } +} + +function constructFullKey(key: string, namespace: string, moduleName: string) { + let key2 = key; + if (key.indexOf('::') > 0) { + // 公共模块 + key2 = `${moduleName}-l-${key}`.replace('::', '.'); + } + else if (key.indexOf(':') > 0) { + // entity + key2 = key.replace(':', '.'); + } + else { + // 自身模块 + key2 = `${namespace}.${key}`; + } + return key2; +} + + +export function t(key: string, p1: any, p2: any, p3: any, p4: any, p5: any, p6: any): string { + let fullKey = ''; + let hasLocale = false; + if (arguments.length === 7) { + // key, params, oakLocales, oakLng, oakDefaultLng, namespace, module + const params = p1, locales = p2, lng = p3, defaultLng = p4, namespace = p5, moduleName = p6; + if (locales && lng ) { + hasLocale = true; + fullKey = constructFullKey(key, namespace, moduleName); + const { [lng]: lngLocales } = locales; + const lngTrans = lngLocales && get(lngLocales, fullKey); + if (lngTrans) { + return interpolate(lngTrans, params); + } + if (defaultLng) { + const { [defaultLng]: dftLngLocales } = locales; + const dftLngTrans = dftLngLocales && get(dftLngLocales, fullKey); + if (dftLngTrans) { + return interpolate(dftLngTrans, params); + } + } + } + } + else if (arguments.length === 6) { + const locales = p1, lng = p2, defaultLng = p3, namespace = p4, moduleName = p5; + if (locales && lng) { + hasLocale = true; + fullKey = constructFullKey(key, namespace, moduleName); + const { [lng]: lngLocales } = locales; + const lngTrans = lngLocales && get(lngLocales, fullKey); + if (lngTrans) { + return lngTrans; + } + if (defaultLng) { + const { [defaultLng]: dftLngLocales } = locales; + const dftLngTrans = dftLngLocales && get(dftLngLocales, fullKey); + if (dftLngTrans) { + return dftLngTrans; + } + } + } + } + + // 到这里说明miss了,通知AppService层,并返回value + if (hasLocale) { + // todo + } + return fullKey.split('.').pop()!; +} diff --git a/test/test.ts b/test/test.ts index 7449782d..162a0dc3 100644 --- a/test/test.ts +++ b/test/test.ts @@ -1,31 +1,11 @@ -import { CommonAspectDict } from 'oak-common-aspect'; -import commonAspectDict from 'oak-common-aspect'; -import { - Aspect, - AspectWrapper, - Checker, - Trigger, - StorageSchema, - Context, - RowStore, - OakRowInconsistencyException, - Watcher, -} from 'oak-domain/lib/types'; -import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain'; -import { EntityDict } from 'oak-domain/lib/types/Entity'; +import { t } from '../src/platforms/wechatMp/i18n/wxs'; -function tt, AD extends CommonAspectDict>(ad: AD) { - console.log(111); -} - -function init< -ED extends EntityDict & BaseEntityDict, -Cxt extends Context, -AD extends Record> -> (aspectDict: AD) { - const ad2 = Object.assign({}, aspectDict, commonAspectDict); - tt(ad2); -} - -init({}); +const r = t('test', { word: 'ddd'}, { + 'zh-CN': { + ns: { + test: '我是一个测试{{word}}', + } + }, +}, 'zh-CN', 'zh-CN', 'ns', 'ns'); +console.log(r); \ No newline at end of file