mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-26 03:48:12 +00:00
fix: 🐛 解决出码缺乏对于 i18n 数据的 params 的处理的问题
https://github.com/alibaba/lowcode-engine/issues/288 ✅ Closes: #288
This commit is contained in:
parent
57657fd76d
commit
2cf788c171
@ -6,4 +6,5 @@ module.exports = {
|
||||
collectCoverage: false,
|
||||
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!**/node_modules/**', '!**/vendor/**'],
|
||||
testMatch: ['<rootDir>/tests/**/*.test.ts'],
|
||||
setupFiles: ['./jest.setup.js'],
|
||||
};
|
||||
|
||||
12
modules/code-generator/jest.setup.js
Normal file
12
modules/code-generator/jest.setup.js
Normal file
@ -0,0 +1,12 @@
|
||||
// 对于 standalone 模式的专门 polyfills
|
||||
if (process.env.TEST_TARGET === 'standalone') {
|
||||
// 模拟浏览器环境
|
||||
global.window = global;
|
||||
global.self = global;
|
||||
|
||||
// 将所有测试用例里面的 './src' 都替换为 './dist/standalone'
|
||||
jest.mock('./src', () => require('./dist/standalone'));
|
||||
}
|
||||
|
||||
// 如果在调试模式下,则不限制超时时间
|
||||
jest.setTimeout(typeof v8debug === 'object' ? Infinity : 30 * 1000);
|
||||
@ -85,6 +85,7 @@
|
||||
"lodash-es": "^4.17.21",
|
||||
"mock-fs": "^5.1.2",
|
||||
"moment": "^2.29.1",
|
||||
"nanomatch": "^1.2.13",
|
||||
"node-fetch": "2.x",
|
||||
"path-browserify": "^1.0.1",
|
||||
"prettier": "^2.5.1",
|
||||
|
||||
55
modules/code-generator/scripts/run-demo-project
Executable file
55
modules/code-generator/scripts/run-demo-project
Executable file
@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// @ts-check
|
||||
const program = require('commander');
|
||||
const { spawnSync } = require('child_process');
|
||||
const glob = require('glob');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
|
||||
program
|
||||
.option('--npm <npm>', 'specify the npm command location or alias')
|
||||
.arguments('<project>')
|
||||
.action((project, options) => {
|
||||
try {
|
||||
if (!fs.existsSync(project)) {
|
||||
throw new Error(`Project ${project} does not exist`);
|
||||
}
|
||||
|
||||
const getProjectActualPath = [
|
||||
() => path.resolve(process.cwd(), project),
|
||||
() =>
|
||||
path.resolve(
|
||||
process.cwd(),
|
||||
path.join(
|
||||
project,
|
||||
path.dirname(glob.sync('*/package.json', { cwd: project })[0] || ''),
|
||||
),
|
||||
),
|
||||
]
|
||||
.map((x) => _.memoize(x))
|
||||
.find((x) => fs.existsSync(path.join(x(), 'package.json')));
|
||||
|
||||
if (!getProjectActualPath) {
|
||||
throw new Error(`Project ${project} is not a valid project(no package.json)`);
|
||||
}
|
||||
|
||||
const projectActualPath = getProjectActualPath();
|
||||
if (path.resolve(process.cwd(), project) !== projectActualPath) {
|
||||
console.log('Changing directory to', path.relative(process.cwd(), projectActualPath));
|
||||
}
|
||||
|
||||
process.chdir(projectActualPath);
|
||||
|
||||
const npm = options.npm || 'npm';
|
||||
const cmd = `${npm} install && ${npm} start`;
|
||||
console.log('# %s', cmd);
|
||||
spawnSync(cmd, { stdio: 'inherit', shell: true });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
@ -638,6 +638,7 @@ export default function createHelloWorldProjectBuilder() {
|
||||
CodeGen.plugins.react.reactCommonDeps(),
|
||||
CodeGen.plugins.common.esmodule({ fileType: 'jsx' }),
|
||||
CodeGen.plugins.react.containerClass(),
|
||||
CodeGen.plugins.react.containerInjectContext(),
|
||||
CodeGen.plugins.react.containerInjectUtils(),
|
||||
CodeGen.plugins.react.containerInjectDataSourceEngine(),
|
||||
CodeGen.plugins.react.containerInjectI18n(),
|
||||
@ -659,6 +660,7 @@ export default function createHelloWorldProjectBuilder() {
|
||||
CodeGen.plugins.react.reactCommonDeps(),
|
||||
CodeGen.plugins.common.esmodule({ fileType: 'jsx' }),
|
||||
CodeGen.plugins.react.containerClass(),
|
||||
CodeGen.plugins.react.containerInjectContext(),
|
||||
CodeGen.plugins.react.containerInjectUtils(),
|
||||
CodeGen.plugins.react.containerInjectDataSourceEngine(),
|
||||
CodeGen.plugins.react.containerInjectI18n(),
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
CodeGeneratorError,
|
||||
ICodeChunk,
|
||||
ICompiledModule,
|
||||
IContextData,
|
||||
IModuleBuilder,
|
||||
IParseResult,
|
||||
ISchemaParser,
|
||||
@ -23,6 +24,7 @@ export function createModuleBuilder(
|
||||
plugins: BuilderComponentPlugin[];
|
||||
postProcessors: PostProcessor[];
|
||||
mainFileName?: string;
|
||||
contextData?: IContextData;
|
||||
} = {
|
||||
plugins: [],
|
||||
postProcessors: [],
|
||||
@ -41,7 +43,13 @@ export function createModuleBuilder(
|
||||
|
||||
let files: ResultFile[] = [];
|
||||
|
||||
const { chunks } = await chunkGenerator.run(input);
|
||||
const { chunks } = await chunkGenerator.run(input, {
|
||||
ir: input,
|
||||
chunks: [],
|
||||
depNames: [],
|
||||
contextData: options.contextData || {},
|
||||
});
|
||||
|
||||
chunks.forEach((fileChunkList) => {
|
||||
const content = linker.link(fileChunkList);
|
||||
const file = createResultFile(
|
||||
|
||||
@ -14,7 +14,7 @@ import { SchemaParser } from '../parser/SchemaParser';
|
||||
import { createResultDir, addDirectory, addFile } from '../utils/resultHelper';
|
||||
|
||||
import { createModuleBuilder } from './ModuleBuilder';
|
||||
import { ProjectPreProcessor, ProjectPostProcessor } from '../types/core';
|
||||
import { ProjectPreProcessor, ProjectPostProcessor, IContextData } from '../types/core';
|
||||
import { CodeGeneratorError } from '../types/error';
|
||||
|
||||
interface IModuleInfo {
|
||||
@ -36,6 +36,10 @@ export interface ProjectBuilderInitOptions {
|
||||
projectPreProcessors?: ProjectPreProcessor[];
|
||||
/** 项目级别的后置处理器 */
|
||||
projectPostProcessors?: ProjectPostProcessor[];
|
||||
/** 是否处于严格模式 */
|
||||
inStrictMode?: boolean;
|
||||
/** 一些额外的上下文数据 */
|
||||
extraContextData?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export class ProjectBuilder implements IProjectBuilder {
|
||||
@ -57,6 +61,12 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
/** 项目级别的后置处理器 */
|
||||
private projectPostProcessors: ProjectPostProcessor[];
|
||||
|
||||
/** 是否处于严格模式 */
|
||||
public readonly inStrictMode: boolean;
|
||||
|
||||
/** 一些额外的上下文数据 */
|
||||
public readonly extraContextData: IContextData;
|
||||
|
||||
constructor({
|
||||
template,
|
||||
plugins,
|
||||
@ -64,6 +74,8 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
schemaParser = new SchemaParser(),
|
||||
projectPreProcessors = [],
|
||||
projectPostProcessors = [],
|
||||
inStrictMode = false,
|
||||
extraContextData = {},
|
||||
}: ProjectBuilderInitOptions) {
|
||||
this.template = template;
|
||||
this.plugins = plugins;
|
||||
@ -71,6 +83,8 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
this.schemaParser = schemaParser;
|
||||
this.projectPreProcessors = projectPreProcessors;
|
||||
this.projectPostProcessors = projectPostProcessors;
|
||||
this.inStrictMode = inStrictMode;
|
||||
this.extraContextData = extraContextData;
|
||||
}
|
||||
|
||||
async generateProject(originalSchema: ProjectSchema | string): Promise<ResultDir> {
|
||||
@ -264,6 +278,10 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
builders[pluginName] = createModuleBuilder({
|
||||
plugins: this.plugins[pluginName],
|
||||
postProcessors: this.postProcessors,
|
||||
contextData: {
|
||||
inStrictMode: this.inStrictMode,
|
||||
...this.extraContextData,
|
||||
},
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
@ -25,16 +25,8 @@ import i18n from './plugins/project/i18n';
|
||||
import utils from './plugins/project/utils';
|
||||
import prettier from './postprocessor/prettier';
|
||||
|
||||
// 引入常用工具
|
||||
import * as utilsCommon from './utils/common';
|
||||
import * as utilsCompositeType from './utils/compositeType';
|
||||
import * as utilsJsExpression from './utils/jsExpression';
|
||||
import * as utilsJsSlot from './utils/jsSlot';
|
||||
import * as utilsNodeToJSX from './utils/nodeToJSX';
|
||||
import * as utilsResultHelper from './utils/resultHelper';
|
||||
import * as utilsTemplateHelper from './utils/templateHelper';
|
||||
import * as utilsValidate from './utils/validate';
|
||||
import * as utilsSchema from './utils/schema';
|
||||
// 引入全局常用工具
|
||||
import * as globalUtils from './utils';
|
||||
|
||||
import * as CONSTANTS from './const';
|
||||
|
||||
@ -85,17 +77,7 @@ export default {
|
||||
postprocessor: {
|
||||
prettier,
|
||||
},
|
||||
utils: {
|
||||
common: utilsCommon,
|
||||
compositeType: utilsCompositeType,
|
||||
jsExpression: utilsJsExpression,
|
||||
jsSlot: utilsJsSlot,
|
||||
nodeToJSX: utilsNodeToJSX,
|
||||
resultHelper: utilsResultHelper,
|
||||
templateHelper: utilsTemplateHelper,
|
||||
validate: utilsValidate,
|
||||
schema: utilsSchema,
|
||||
},
|
||||
utils: globalUtils,
|
||||
chunkNames: {
|
||||
COMMON_CHUNK_NAME,
|
||||
CLASS_DEFINE_CHUNK_NAME,
|
||||
|
||||
@ -134,19 +134,6 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
|
||||
content: `
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
`,
|
||||
linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
|
||||
@ -10,6 +10,7 @@ import {
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
import { RAX_CHUNK_NAME } from './const';
|
||||
import { DEFAULT_LINK_AFTER } from '../../../const';
|
||||
|
||||
export interface PluginConfig {
|
||||
fileType: string;
|
||||
@ -46,6 +47,16 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
content: `
|
||||
__$$i18n._inject2(this);
|
||||
`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
|
||||
@ -29,6 +29,11 @@ import { RAX_CHUNK_NAME } from './const';
|
||||
|
||||
export interface PluginConfig extends RaxFrameworkOptions {
|
||||
fileType?: string;
|
||||
|
||||
/**
|
||||
* 数据源的 handlers 的映射配置
|
||||
* @deprecated 请使用 datasourceConfig.handlersPackages 来配置
|
||||
*/
|
||||
dataSourceHandlersPackageMap?: Record<string, string>;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
||||
|
||||
import { Scope } from '../../../utils/Scope';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
|
||||
export interface PluginConfig {
|
||||
fileType: string;
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
...config,
|
||||
};
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const scope = Scope.createRootScope();
|
||||
|
||||
const { inStrictMode } = next.contextData;
|
||||
if (inStrictMode) {
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
content: `
|
||||
_context = this._createContext();
|
||||
`,
|
||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||
});
|
||||
// TODO: createContext......
|
||||
} else {
|
||||
// 非严格模式下,上下文就是自己
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
content: `
|
||||
_context = this;
|
||||
`,
|
||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default pluginFactory;
|
||||
@ -31,13 +31,34 @@ import { isContainerSchema } from '../../../utils/schema';
|
||||
import { REACT_CHUNK_NAME } from './const';
|
||||
|
||||
export interface PluginConfig {
|
||||
fileType: string;
|
||||
fileType?: string;
|
||||
|
||||
/**
|
||||
* 数据源配置
|
||||
*/
|
||||
datasourceConfig?: {
|
||||
/** 数据源引擎的版本 */
|
||||
engineVersion?: string;
|
||||
|
||||
/** 数据源引擎的包名 */
|
||||
enginePackage?: string;
|
||||
|
||||
/** 数据源 handlers 的版本 */
|
||||
handlersVersion?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
/** 数据源 handlers 的包名 */
|
||||
handlersPackages?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
const cfg = {
|
||||
...config,
|
||||
fileType: config?.fileType || FileType.JSX,
|
||||
};
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
@ -65,7 +86,9 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
};
|
||||
|
||||
const handlerFactoryExportName = `create${changeCase.pascal(dsType)}Handler`;
|
||||
const handlerPkgName = `@alilc/lowcode-datasource-${changeCase.kebab(dsType)}-handler`;
|
||||
const handlerPkgName =
|
||||
cfg.datasourceConfig?.handlersPackages?.[dsType] ||
|
||||
`@alilc/lowcode-datasource-${changeCase.kebab(dsType)}-handler`;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
|
||||
@ -33,7 +33,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
// TODO: 下面这个路径有没有更好的方式来获取?而非写死
|
||||
content: `
|
||||
import { i18n as _$$i18n } from '../../i18n';
|
||||
import * as __$$i18n from '../../i18n';
|
||||
`,
|
||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
});
|
||||
@ -41,13 +41,11 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
content: `
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
}
|
||||
__$$i18n._inject2(this);
|
||||
`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]],
|
||||
});
|
||||
|
||||
return next;
|
||||
|
||||
@ -100,8 +100,8 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
fileType: cfg.fileType,
|
||||
name: REACT_CHUNK_NAME.ClassRenderJSX,
|
||||
content: `
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return ${jsxContent};
|
||||
`,
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassRenderStart, REACT_CHUNK_NAME.ClassRenderPre],
|
||||
|
||||
@ -18,7 +18,10 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
content: 'import React from \'react\';',
|
||||
content: `
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from \'react\';`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
|
||||
@ -23,11 +23,9 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||
content: `
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = ${i18nStr};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -35,23 +33,65 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = i18nConfig && i18nConfig[locale] && i18nConfig[locale][id] || defaultMessage;
|
||||
const isEmptyVariables = variables => (
|
||||
Array.isArray(variables) && variables.length === 0
|
||||
|| typeof variables === 'object' && (!variables || Object.keys(variables).length === 0)
|
||||
);
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) => (
|
||||
typeof msg === 'string'
|
||||
? msg.replace(/\\\$\\{(\\w+)\\}/g, (match, key) => variables?.[key] ?? '')
|
||||
: msg
|
||||
);
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return \`\${id}\`;
|
||||
return fallback === undefined ? \`\${id}\` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
return format(msg, variables);
|
||||
}
|
||||
|
||||
const i18n = id => {
|
||||
return i18nFormat({ id });
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')]
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
}
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale, setLocale: target.setLocale
|
||||
});
|
||||
}
|
||||
}
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
@ -72,6 +112,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
setLocale,
|
||||
i18n,
|
||||
i18nFormat,
|
||||
_inject2,
|
||||
};
|
||||
`,
|
||||
linkAfter: [
|
||||
|
||||
@ -5,6 +5,7 @@ import { createProjectBuilder } from '../generator/ProjectBuilder';
|
||||
import esmodule from '../plugins/common/esmodule';
|
||||
import containerClass from '../plugins/component/react/containerClass';
|
||||
import containerInitState from '../plugins/component/react/containerInitState';
|
||||
import containerInjectContext from '../plugins/component/react/containerInjectContext';
|
||||
import containerInjectUtils from '../plugins/component/react/containerInjectUtils';
|
||||
import containerInjectDataSourceEngine from '../plugins/component/react/containerInjectDataSourceEngine';
|
||||
import containerInjectI18n from '../plugins/component/react/containerInjectI18n';
|
||||
@ -31,6 +32,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
fileType: 'jsx',
|
||||
}),
|
||||
containerClass(),
|
||||
containerInjectContext(),
|
||||
containerInjectUtils(),
|
||||
containerInjectDataSourceEngine(),
|
||||
containerInjectI18n(),
|
||||
@ -53,6 +55,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
fileType: 'jsx',
|
||||
}),
|
||||
containerClass(),
|
||||
containerInjectContext(),
|
||||
containerInjectUtils(),
|
||||
containerInjectDataSourceEngine(),
|
||||
containerInjectI18n(),
|
||||
@ -86,6 +89,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
export const plugins = {
|
||||
containerClass,
|
||||
containerInitState,
|
||||
containerInjectContext,
|
||||
containerInjectUtils,
|
||||
containerInjectI18n,
|
||||
containerInjectDataSourceEngine,
|
||||
|
||||
@ -25,16 +25,8 @@ import i18n from './plugins/project/i18n';
|
||||
import utils from './plugins/project/utils';
|
||||
import prettier from './postprocessor/prettier';
|
||||
|
||||
// 引入常用工具
|
||||
import * as utilsCommon from './utils/common';
|
||||
import * as utilsCompositeType from './utils/compositeType';
|
||||
import * as utilsJsExpression from './utils/jsExpression';
|
||||
import * as utilsJsSlot from './utils/jsSlot';
|
||||
import * as utilsNodeToJSX from './utils/nodeToJSX';
|
||||
import * as utilsResultHelper from './utils/resultHelper';
|
||||
import * as utilsTemplateHelper from './utils/templateHelper';
|
||||
import * as utilsValidate from './utils/validate';
|
||||
import * as utilsSchema from './utils/schema';
|
||||
// 引入全局常用工具
|
||||
import * as globalUtils from './utils';
|
||||
|
||||
import * as CONSTANTS from './const';
|
||||
|
||||
@ -54,7 +46,6 @@ export default {
|
||||
rax,
|
||||
},
|
||||
publishers: {
|
||||
// TODO: 增加 web 端的 zip publisher
|
||||
zip: createZipPublisher,
|
||||
},
|
||||
plugins: {
|
||||
@ -85,17 +76,7 @@ export default {
|
||||
postprocessor: {
|
||||
prettier,
|
||||
},
|
||||
utils: {
|
||||
common: utilsCommon,
|
||||
compositeType: utilsCompositeType,
|
||||
jsExpression: utilsJsExpression,
|
||||
jsSlot: utilsJsSlot,
|
||||
nodeToJSX: utilsNodeToJSX,
|
||||
resultHelper: utilsResultHelper,
|
||||
templateHelper: utilsTemplateHelper,
|
||||
validate: utilsValidate,
|
||||
schema: utilsSchema,
|
||||
},
|
||||
utils: globalUtils,
|
||||
chunkNames: {
|
||||
COMMON_CHUNK_NAME,
|
||||
CLASS_DEFINE_CHUNK_NAME,
|
||||
|
||||
@ -59,8 +59,22 @@ export interface IBaseCodeStruct {
|
||||
|
||||
export interface ICodeStruct extends IBaseCodeStruct {
|
||||
ir: any;
|
||||
// FIXME: 这个方案不太好,想清楚场景,结构化表达,不要那么通用
|
||||
contextData: Record<string, any>;
|
||||
contextData: IContextData;
|
||||
}
|
||||
|
||||
/** 上下文数据,用来在插件之间共享一些数据 */
|
||||
export interface IContextData {
|
||||
/** 是否处于严格模式 */
|
||||
inStrictMode?: boolean;
|
||||
|
||||
/** 是否使用了 Ref 的 API (this.$/this.$$) */
|
||||
useRefApi?: boolean;
|
||||
|
||||
/**
|
||||
* 其他自定义数据
|
||||
* (三方自定义插件也可以在此放一些数据,建议起个长一点的名称,用自己的插件名做前缀,以防冲突)
|
||||
*/
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export type BuilderComponentPlugin = (initStruct: ICodeStruct) => Promise<ICodeStruct>;
|
||||
|
||||
1
modules/code-generator/src/typings.d.ts
vendored
Normal file
1
modules/code-generator/src/typings.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare module 'nanomatch';
|
||||
@ -57,7 +57,11 @@ function generateObject(
|
||||
options: CompositeValueGeneratorOptions = {},
|
||||
): string {
|
||||
if (value.type === 'i18n') {
|
||||
return `this._i18nText(${JSON.stringify(value)})`;
|
||||
// params 可能会绑定变量,这里需要处理下
|
||||
if (value.params && typeof value.params === 'object') {
|
||||
return `this._i18nText(${generateUnknownType(_.omit(value, 'type'), scope, options)})`;
|
||||
}
|
||||
return `this._i18nText(${JSON.stringify(_.omit(value, 'type'))})`; // TODO: 优化:这里可以考虑提取成个常量...
|
||||
}
|
||||
|
||||
const body = Object.keys(value)
|
||||
|
||||
28
modules/code-generator/src/utils/index.ts
Normal file
28
modules/code-generator/src/utils/index.ts
Normal file
@ -0,0 +1,28 @@
|
||||
// 本文件是要导出到外面的,注意只导出比较稳定的东西
|
||||
import * as common from './common';
|
||||
import * as compositeType from './compositeType';
|
||||
import * as jsExpression from './jsExpression';
|
||||
import * as jsSlot from './jsSlot';
|
||||
import * as nodeToJSX from './nodeToJSX';
|
||||
import * as resultHelper from './resultHelper';
|
||||
import * as templateHelper from './templateHelper';
|
||||
import * as validate from './validate';
|
||||
import * as schema from './schema';
|
||||
import * as version from './version';
|
||||
import * as scope from './Scope';
|
||||
import * as expressionParser from './expressionParser';
|
||||
|
||||
export {
|
||||
common,
|
||||
compositeType,
|
||||
jsExpression,
|
||||
jsSlot,
|
||||
nodeToJSX,
|
||||
resultHelper,
|
||||
templateHelper,
|
||||
validate,
|
||||
schema,
|
||||
version,
|
||||
scope,
|
||||
expressionParser,
|
||||
};
|
||||
@ -1,4 +1,5 @@
|
||||
import { ResultFile, ResultDir } from '@alilc/lowcode-types';
|
||||
import nm from 'nanomatch';
|
||||
|
||||
import { CodeGeneratorError } from '../types/error';
|
||||
import { FlattenFile } from '../types/file';
|
||||
@ -47,12 +48,204 @@ export function flattenResult(dir: ResultDir, cwd = ''): FlattenFile[] {
|
||||
return [
|
||||
...dir.files.map(
|
||||
(file): FlattenFile => ({
|
||||
pathName: `${cwd ? `${cwd}/` : ''}${file.name}${file.ext ? `.${file.ext}` : ''}`,
|
||||
pathName: joinPath(cwd, `${file.name}${file.ext ? `.${file.ext}` : ''}`),
|
||||
content: file.content,
|
||||
}),
|
||||
),
|
||||
].concat(
|
||||
...dir.dirs.map((subDir) =>
|
||||
flattenResult(subDir, [cwd, subDir.name].filter((x) => x !== '' && x !== '.').join('/'))),
|
||||
);
|
||||
].concat(...dir.dirs.map((subDir) => flattenResult(subDir, joinPath(cwd, subDir.name))));
|
||||
}
|
||||
|
||||
export type GlobOptions = {
|
||||
/** 是否查找 ".xxx" 文件, 默认: 否 */
|
||||
dot?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* 查找文件
|
||||
* @param result 出码结果
|
||||
* @param fileGlobExpr 文件名匹配表达式
|
||||
* @param resultDirPath 出码结果的路径(默认是 '.')
|
||||
* @returns 匹配的第一个文件或 null (找不到)
|
||||
*/
|
||||
export function findFile(
|
||||
result: ResultDir,
|
||||
fileGlobExpr: string,
|
||||
options: GlobOptions = {},
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
): ResultFile | null {
|
||||
const maxDepth = !/\/|\*\*/.test(fileGlobExpr) ? 1 : undefined; // 如果 glob 表达式里面压根不会匹配子目录,则深度限制为 1
|
||||
const files = scanFiles(result, resultDirPath, maxDepth);
|
||||
|
||||
for (let [filePath, file] of files) {
|
||||
if (nm.isMatch(filePath, fileGlobExpr, options)) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 glob 语法查找多个文件
|
||||
* @param result 出码结果
|
||||
* @param fileGlobExpr 文件名匹配表达式
|
||||
* @param resultDirPath 出码结果的路径(默认是 '.')
|
||||
* @returns 找到的文件列表的迭代器 [ [文件路径, 文件信息], ... ]
|
||||
*/
|
||||
export function* globFiles(
|
||||
result: ResultDir,
|
||||
fileGlobExpr: string,
|
||||
options: GlobOptions = {},
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
): IterableIterator<[string, ResultFile]> {
|
||||
const files = scanFiles(result, resultDirPath);
|
||||
|
||||
for (let [filePath, file] of files) {
|
||||
if (nm.isMatch(filePath, fileGlobExpr, options)) {
|
||||
yield [filePath, file];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历所有的文件
|
||||
*/
|
||||
export function* scanFiles(
|
||||
result: ResultDir,
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
maxDepth = 10000,
|
||||
): IterableIterator<[string, ResultFile]> {
|
||||
for (let file of result.files) {
|
||||
const fileName = getFileNameWithExt(file);
|
||||
yield [joinPath(resultDirPath, fileName), file];
|
||||
}
|
||||
|
||||
for (let subDir of result.dirs) {
|
||||
yield* scanFiles(subDir, joinPath(resultDirPath, subDir.name), maxDepth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
export function getFileNameWithExt(file: ResultFile) {
|
||||
return `${file.name}${file.ext ? `.${file.ext}` : ''}`;
|
||||
}
|
||||
|
||||
function getResultNameOrDefault(result: ResultDir, defaultDir = '/') {
|
||||
return result.name && result.name !== '.' ? result.name : defaultDir;
|
||||
}
|
||||
|
||||
function joinPath(...pathParts: string[]): string {
|
||||
return pathParts
|
||||
.filter((x) => x !== '' && x !== '.')
|
||||
.join('/')
|
||||
.replace(/\\+/g, '/')
|
||||
.replace(/\/+/g, '/');
|
||||
}
|
||||
|
||||
export function* scanDirs(
|
||||
result: ResultDir,
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
maxDepth = 10000,
|
||||
): IterableIterator<[string, ResultDir]> {
|
||||
yield [resultDirPath, result];
|
||||
|
||||
for (let subDir of result.dirs) {
|
||||
yield* scanDirs(subDir, joinPath(resultDirPath, subDir.name), maxDepth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
export function* globDirs(
|
||||
result: ResultDir,
|
||||
dirGlobExpr: string,
|
||||
options: GlobOptions = {},
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
): IterableIterator<[string, ResultDir]> {
|
||||
const dirs = scanDirs(result, resultDirPath);
|
||||
|
||||
for (let [dirPath, dir] of dirs) {
|
||||
if (nm.isMatch(dirPath, dirGlobExpr, options)) {
|
||||
yield [dirPath, dir];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function findDir(
|
||||
result: ResultDir,
|
||||
dirGlobExpr: string,
|
||||
options: GlobOptions = {},
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
): ResultDir | null {
|
||||
const dirs = scanDirs(result, resultDirPath);
|
||||
|
||||
for (let [dirPath, dir] of dirs) {
|
||||
if (nm.isMatch(dirPath, dirGlobExpr, options)) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从结果中移除一些文件
|
||||
* @param result 出码结果目录
|
||||
* @param filePathGlobExpr 要移除的文件路径(glob 表达式)
|
||||
* @param globOptions glob 参数
|
||||
* @returns 移除了多少文件
|
||||
*/
|
||||
export function removeFilesFromResult(
|
||||
result: ResultDir,
|
||||
filePathGlobExpr: string,
|
||||
globOptions: GlobOptions = {},
|
||||
): number {
|
||||
let removedCount = 0;
|
||||
const [dirPath, fileName] = splitPath(filePathGlobExpr);
|
||||
|
||||
const dirs = dirPath ? globDirs(result, dirPath) : [['', result] as const];
|
||||
for (let [, dir] of dirs) {
|
||||
const files = globFiles(dir, fileName, globOptions, '.');
|
||||
for (let [, file] of files) {
|
||||
dir.files.splice(dir.files.indexOf(file), 1);
|
||||
removedCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return removedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从结果中移除一些目录
|
||||
* @param result 出码结果目录
|
||||
* @param dirPathGlobExpr 要移除的目录路径(glob 表达式)
|
||||
* @param globOptions glob 参数
|
||||
* @returns 移除了多少文件
|
||||
*/
|
||||
export function removeDirsFromResult(
|
||||
result: ResultDir,
|
||||
dirPathGlobExpr: string,
|
||||
globOptions: GlobOptions = {},
|
||||
): number {
|
||||
let removedCount = 0;
|
||||
const [dirPath, fileName] = splitPath(dirPathGlobExpr);
|
||||
|
||||
const dirs = dirPath ? globDirs(result, dirPath) : [['', result] as const];
|
||||
for (let [, dir] of dirs) {
|
||||
const foundDirs = globDirs(dir, fileName, globOptions, '.');
|
||||
for (let [, foundDir] of foundDirs) {
|
||||
dir.dirs.splice(dir.dirs.indexOf(foundDir), 1);
|
||||
removedCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return removedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文件路径拆分为目录路径和文件名
|
||||
* @param filePath
|
||||
* @returns [fileDirPath, fileName]
|
||||
*/
|
||||
function splitPath(filePath: string) {
|
||||
const parts = filePath.split('/');
|
||||
const fileName = parts.pop() || '';
|
||||
return [joinPath(...parts), fileName];
|
||||
}
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -33,6 +33,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -63,11 +65,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -68,6 +68,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -166,11 +168,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -37,6 +37,8 @@ class Detail$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -72,11 +74,6 @@ class Detail$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -37,6 +37,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -72,11 +74,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -37,6 +37,8 @@ class List$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -75,11 +77,6 @@ class List$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -67,11 +69,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -33,6 +33,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -69,11 +71,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -75,11 +77,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -33,6 +33,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -69,11 +71,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -75,11 +77,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -78,11 +80,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -80,11 +82,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -40,6 +40,8 @@ class Aaaa$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -70,11 +72,6 @@ class Aaaa$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -33,6 +33,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -70,11 +72,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -36,6 +36,8 @@ class Example$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -72,11 +74,6 @@ class Example$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Form, Input, NumberPicker, Select, Button } from "@alifd/next";
|
||||
@ -10,11 +12,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -39,6 +43,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = { text: "outter" };
|
||||
}
|
||||
|
||||
@ -113,10 +119,6 @@ class Test$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
|
||||
@ -124,8 +126,8 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div ref={this._refsManager.linkRef("outterView")} autoLoading={true}>
|
||||
<Form
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Page } from "@alilc/b6-page";
|
||||
@ -10,11 +12,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Aaaa$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -36,6 +40,8 @@ class Aaaa$$Page extends React.Component {
|
||||
|
||||
this.utils = utils;
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
@ -60,17 +66,13 @@ class Aaaa$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div title="" backgroundColor="#fff" textColor="#333" style={{}}>
|
||||
<Text
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {
|
||||
"zh-CN": {
|
||||
"i18n-jwg27yo4": "你好",
|
||||
@ -11,7 +9,10 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -19,24 +20,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,14 +1,18 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Form, Input, NumberPicker, Select, Button } from "@alifd/next";
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -16,6 +20,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = { text: "outter" };
|
||||
}
|
||||
|
||||
@ -27,17 +33,13 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
console.log("componentDidMount");
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div ref={this._refsManager.linkRef("outterView")} autoLoading={true}>
|
||||
<Form
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {
|
||||
"zh-CN": {
|
||||
"i18n-jwg27yo4": "你好",
|
||||
@ -11,7 +9,10 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -19,24 +20,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import Super, {
|
||||
@ -13,7 +15,7 @@ import SuperOther from "@alifd/next";
|
||||
|
||||
import utils from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -24,23 +26,23 @@ const SelectOption = Select.Option;
|
||||
const SearchTable = SearchTableExport.default;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
this.utils = utils;
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div>
|
||||
<Super title={this.state.title} />
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -15,7 +17,7 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -24,6 +26,8 @@ const NextBlockCell = NextBlock.Cell;
|
||||
const AliSearchTable = AliSearchTableExport.default;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -45,6 +49,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = { text: "outter", isShowDialog: false };
|
||||
}
|
||||
|
||||
@ -81,10 +87,6 @@ class Test$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
console.log("will umount");
|
||||
}
|
||||
@ -133,8 +135,8 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -22,7 +24,7 @@ import { AliAutoSearchTable } from "@alife/mc-assets-1935/build/lowcode/index.js
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -31,6 +33,8 @@ const NextBlockCell = NextBlock.Cell;
|
||||
const AliAutoSearchTableDefault = AliAutoSearchTable.default;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -38,6 +42,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {
|
||||
name: "nongzhou",
|
||||
gateways: [],
|
||||
@ -55,10 +61,6 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
/* ... */
|
||||
}
|
||||
@ -90,8 +92,8 @@ class Test$$Page extends React.Component {
|
||||
componentDidMount() {}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Form, Input, NumberPicker, Select, Button } from "@alifd/next";
|
||||
@ -10,11 +12,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -39,6 +43,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = { text: "outter" };
|
||||
}
|
||||
|
||||
@ -113,10 +119,6 @@ class Test$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
|
||||
@ -124,8 +126,8 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div ref={this._refsManager.linkRef("outterView")} autoLoading={true}>
|
||||
<Form
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -21,13 +23,15 @@ import {
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
const NextBlockCell = NextBlock.Cell;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -35,6 +39,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {
|
||||
books: [],
|
||||
currentStep: 0,
|
||||
@ -97,10 +103,6 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
@ -189,8 +191,8 @@ class Test$$Page extends React.Component {
|
||||
componentDidMount() {}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Page, Table } from "@alilc/lowcode-components";
|
||||
@ -8,11 +10,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Example$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -32,6 +36,8 @@ class Example$$Page extends React.Component {
|
||||
|
||||
this.utils = utils;
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
@ -56,17 +62,13 @@ class Example$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Switch } from "@alifd/next";
|
||||
@ -8,11 +10,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Index$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -32,6 +36,8 @@ class Index$$Page extends React.Component {
|
||||
|
||||
this.utils = utils;
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
@ -59,17 +65,13 @@ class Index$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -25,7 +27,7 @@ import {
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -36,6 +38,8 @@ const AliAutoSearchTableDefault = AliAutoSearchTable.default;
|
||||
const NextBlockCell = NextBlock.Cell;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -43,6 +47,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {
|
||||
pkgs: [],
|
||||
total: 0,
|
||||
@ -71,10 +77,6 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
@ -181,8 +183,8 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, variables);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -25,7 +27,7 @@ import {
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -36,6 +38,8 @@ const AliAutoSearchTableDefault = AliAutoSearchTable.default;
|
||||
const NextBlockCell = NextBlock.Cell;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -43,6 +47,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {
|
||||
pkgs: [],
|
||||
total: 0,
|
||||
@ -79,10 +85,6 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
@ -207,8 +209,8 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"componentsMap": [
|
||||
{
|
||||
"package": "react-greetings",
|
||||
"version": "1.0.0",
|
||||
"componentName": "Greetings",
|
||||
"exportName": "Greetings",
|
||||
"destructuring": true
|
||||
}
|
||||
],
|
||||
"componentsTree": [
|
||||
{
|
||||
"componentName": "Page",
|
||||
"id": "node_ocl137q7oc1",
|
||||
"fileName": "test",
|
||||
"props": { "style": {} },
|
||||
"lifeCycles": {},
|
||||
"dataSource": { "list": [] },
|
||||
"state": {
|
||||
"name": "lowcode world"
|
||||
},
|
||||
"methods": {},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Greetings",
|
||||
"id": "node_ocl137q7oc4",
|
||||
"props": {
|
||||
"content": {
|
||||
"type": "i18n",
|
||||
"key": "greetings.hello",
|
||||
"params": {
|
||||
"name": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.state.name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"i18n": {
|
||||
"zh_CN": {
|
||||
"greetings.hello": "${name}, 你好!"
|
||||
},
|
||||
"en_US": {
|
||||
"greetings.hello": "Hello, ${name}!"
|
||||
}
|
||||
}
|
||||
}
|
||||
54
modules/code-generator/tests/bugfix/i18n-with-params.test.ts
Normal file
54
modules/code-generator/tests/bugfix/i18n-with-params.test.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { ProjectSchema } from '@alilc/lowcode-types';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
const inputSchemaJsonFile = path.join(__dirname, `${testCaseBaseName}.schema.json`);
|
||||
const outputDir = path.join(__dirname, `${testCaseBaseName}.generated`);
|
||||
|
||||
jest.setTimeout(60 * 60 * 1000);
|
||||
|
||||
describe(testCaseBaseName, () => {
|
||||
test('default import', async () => {
|
||||
await exportProject(inputSchemaJsonFile, outputDir, {});
|
||||
|
||||
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
|
||||
expect(generatedPageFileContent).toContain(
|
||||
`
|
||||
<Greetings
|
||||
content={this._i18nText({
|
||||
key: "greetings.hello",
|
||||
params: { name: this.state.name },
|
||||
})}
|
||||
/>
|
||||
`.trim(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function exportProject(
|
||||
importPath: string,
|
||||
outputPath: string,
|
||||
mergeSchema?: Partial<ProjectSchema>,
|
||||
) {
|
||||
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
|
||||
const schema = { ...JSON.parse(schemaJsonStr), ...mergeSchema };
|
||||
const builder = CodeGenerator.solutions.icejs();
|
||||
|
||||
return builder.generateProject(schema).then(async (result) => {
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
projectSlug: 'demo-project',
|
||||
createProjectFolder: true,
|
||||
});
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function readOutputTextFile(outputFilePath: string): string {
|
||||
return fs.readFileSync(path.resolve(outputDir, outputFilePath), 'utf-8');
|
||||
}
|
||||
@ -2,6 +2,7 @@ import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { ProjectSchema } from '@alilc/lowcode-types';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
const inputSchemaJsonFile = path.join(__dirname, `${testCaseBaseName}.schema.json`);
|
||||
@ -205,7 +206,7 @@ function exportProject(
|
||||
|
||||
return builder.generateProject(schema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
|
||||
@ -31,7 +32,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
|
||||
@ -31,7 +32,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
|
||||
@ -37,7 +38,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
|
||||
@ -25,7 +26,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
test('page-element1', async () => {
|
||||
const inputSchemaJsonFile = path.join(__dirname, 'page-element1.schema.json');
|
||||
@ -67,7 +68,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
test('page-element2', async () => {
|
||||
const inputSchemaJsonFile = path.join(__dirname, 'page-element2.schema.json');
|
||||
@ -67,7 +68,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,14 @@
|
||||
import { run } from '../src/cli';
|
||||
|
||||
describe('cli', () => {
|
||||
// standalone 模式下不需要测试 cli
|
||||
if (process.env.TEST_TARGET === 'standalone') {
|
||||
it('should ignore', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
it('should works for the default example-schema.json', async () => {
|
||||
const res = await run(['example-schema.json'], {
|
||||
solution: 'icejs',
|
||||
|
||||
@ -5,8 +5,8 @@ Object {
|
||||
"chunks": Array [
|
||||
Object {
|
||||
"content": "
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (this.state.otherThings).map((item, index) => ((__$$context) => (!!(__$$context.state.something) && (<Page><Text>Hello world!</Text></Page>)))(__$$createChildContext(__$$context, { item, index })));
|
||||
",
|
||||
"fileType": "jsx",
|
||||
@ -66,8 +66,8 @@ Object {
|
||||
"chunks": Array [
|
||||
Object {
|
||||
"content": "
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return !!(this.state.something) && (<Page><Text>Hello world!</Text></Page>);
|
||||
",
|
||||
"fileType": "jsx",
|
||||
@ -123,8 +123,8 @@ Object {
|
||||
"chunks": Array [
|
||||
Object {
|
||||
"content": "
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return <Page><Text>Hello world!</Text></Page>;
|
||||
",
|
||||
"fileType": "jsx",
|
||||
@ -177,8 +177,8 @@ Object {
|
||||
"chunks": Array [
|
||||
Object {
|
||||
"content": "
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return <Page><Text>Hello world!</Text></Page>;
|
||||
",
|
||||
"fileType": "jsx",
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": ".",
|
||||
"dirs": [
|
||||
{
|
||||
"name": "src",
|
||||
"dirs": [
|
||||
{
|
||||
"name": "components",
|
||||
"dirs": [
|
||||
{
|
||||
"name": "Hello",
|
||||
"dirs": [],
|
||||
"files": [
|
||||
{
|
||||
"name": "index",
|
||||
"ext": "js",
|
||||
"content": "export default () => <div>Hello</div>"
|
||||
},
|
||||
{
|
||||
"name": "index",
|
||||
"ext": "css",
|
||||
"content": ".hello {color: red}"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"name": "index",
|
||||
"ext": "js",
|
||||
"content": "export * from \"./Hello\";"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"files": [
|
||||
{ "name": "index", "ext": "js", "content": "console.log(\"Hello\")" },
|
||||
{ "name": "index", "ext": "css", "content": "html,body{ padding: 0; }" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"files": [
|
||||
{ "name": ".eslintrc", "ext": "", "content": "{}" },
|
||||
{ "name": "package", "ext": "json", "content": "{ \"name\": \"demo\", \"version\":\"1.0.0\" }" }
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
import _ from 'lodash';
|
||||
import CodeGen from '../../../src';
|
||||
|
||||
describe('CodeGen.utils.resultHelper.findFile', () => {
|
||||
it('could package.json by "package.json"', () => {
|
||||
const result = require('./example-result.json') as any;
|
||||
const found = CodeGen.utils.resultHelper.findFile(result, 'package.json');
|
||||
expect(found).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"content": "{ \\"name\\": \\"demo\\", \\"version\\":\\"1.0.0\\" }",
|
||||
"ext": "json",
|
||||
"name": "package",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('could find a internal component by src/components/*/index.js', () => {
|
||||
const result = require('./example-result.json') as any;
|
||||
const found = CodeGen.utils.resultHelper.findFile(result, 'src/components/*/index.js');
|
||||
expect(found).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"content": "export default () => <div>Hello</div>",
|
||||
"ext": "js",
|
||||
"name": "index",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('could not find non-existing file', () => {
|
||||
const result = require('./example-result.json') as any;
|
||||
const found = CodeGen.utils.resultHelper.findFile(result, 'something-not-exist.js');
|
||||
expect(found).toBeNull();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,67 @@
|
||||
import _ from 'lodash';
|
||||
import CodeGen from '../../../src';
|
||||
|
||||
describe('CodeGen.utils.resultHelper.globFiles', () => {
|
||||
it('could find all files exclude dot files by **/*', () => {
|
||||
const result = require('./example-result.json') as any;
|
||||
const files = CodeGen.utils.resultHelper.globFiles(result, '**/*');
|
||||
expect(Array.from(files).map(_.first)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"package.json",
|
||||
"src/index.js",
|
||||
"src/index.css",
|
||||
"src/components/index.js",
|
||||
"src/components/Hello/index.js",
|
||||
"src/components/Hello/index.css",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('could find all files by **/* with option.dot = true ', () => {
|
||||
const result = require('./example-result.json') as any;
|
||||
const files = CodeGen.utils.resultHelper.globFiles(result, '**/*', { dot: true });
|
||||
expect(Array.from(files).map(_.first)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
".eslintrc",
|
||||
"package.json",
|
||||
"src/index.js",
|
||||
"src/index.css",
|
||||
"src/components/index.js",
|
||||
"src/components/Hello/index.js",
|
||||
"src/components/Hello/index.css",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('could find all js files by **/*.js', () => {
|
||||
const result = require('./example-result.json') as any;
|
||||
const files = CodeGen.utils.resultHelper.globFiles(result, '**/*.js');
|
||||
expect(Array.from(files).map(_.first)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"src/index.js",
|
||||
"src/components/index.js",
|
||||
"src/components/Hello/index.js",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('could find package.json by package.json', () => {
|
||||
const result = require('./example-result.json') as any;
|
||||
const files = CodeGen.utils.resultHelper.globFiles(result, 'package.json');
|
||||
expect(Array.from(files).map(_.first)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"package.json",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('could find all index.js in components by **/components/*/index.js', () => {
|
||||
const result = require('./example-result.json') as any;
|
||||
const files = CodeGen.utils.resultHelper.globFiles(result, '**/components/*/index.js');
|
||||
expect(Array.from(files).map(_.first)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"src/components/Hello/index.js",
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,101 @@
|
||||
import type { ResultDir } from '@alilc/lowcode-types';
|
||||
import _ from 'lodash';
|
||||
import CodeGen from '../../../src';
|
||||
|
||||
const loadResult = (): ResultDir => _.cloneDeep(require('./example-result.json'));
|
||||
|
||||
describe('CodeGen.utils.resultHelper.removeDirsFromResult', () => {
|
||||
it('could remove src by "src"', () => {
|
||||
const result = loadResult();
|
||||
expect(listAllDirs(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"",
|
||||
"src",
|
||||
"src/components",
|
||||
"src/components/Hello",
|
||||
]
|
||||
`);
|
||||
|
||||
const removed = CodeGen.utils.resultHelper.removeDirsFromResult(result, 'src');
|
||||
|
||||
expect(listAllDirs(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"",
|
||||
]
|
||||
`);
|
||||
|
||||
expect(removed).toBe(1);
|
||||
});
|
||||
|
||||
it('could remove src/components/Hello by "*/components/*"', () => {
|
||||
const result = loadResult();
|
||||
expect(listAllDirs(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"",
|
||||
"src",
|
||||
"src/components",
|
||||
"src/components/Hello",
|
||||
]
|
||||
`);
|
||||
|
||||
const removed = CodeGen.utils.resultHelper.removeDirsFromResult(result, '*/components/*');
|
||||
|
||||
expect(listAllDirs(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"",
|
||||
"src",
|
||||
"src/components",
|
||||
]
|
||||
`);
|
||||
|
||||
expect(removed).toBe(1);
|
||||
});
|
||||
|
||||
it('could remove all dirs by "*"', () => {
|
||||
const result = loadResult();
|
||||
expect(listAllDirs(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"",
|
||||
"src",
|
||||
"src/components",
|
||||
"src/components/Hello",
|
||||
]
|
||||
`);
|
||||
|
||||
const removed = CodeGen.utils.resultHelper.removeDirsFromResult(result, '*');
|
||||
|
||||
expect(listAllDirs(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"",
|
||||
]
|
||||
`);
|
||||
|
||||
expect(removed).toBe(1);
|
||||
});
|
||||
|
||||
it('could remove all dirs by "**"', () => {
|
||||
const result = loadResult();
|
||||
expect(listAllDirs(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"",
|
||||
"src",
|
||||
"src/components",
|
||||
"src/components/Hello",
|
||||
]
|
||||
`);
|
||||
|
||||
const removed = CodeGen.utils.resultHelper.removeDirsFromResult(result, '**');
|
||||
|
||||
expect(listAllDirs(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"",
|
||||
]
|
||||
`);
|
||||
|
||||
expect(removed).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
function listAllDirs(result: ResultDir): string[] {
|
||||
return Array.from(CodeGen.utils.resultHelper.scanDirs(result)).map(([dirPath]) => dirPath);
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
import type { ResultDir } from '@alilc/lowcode-types';
|
||||
import _ from 'lodash';
|
||||
import CodeGen from '../../../src';
|
||||
|
||||
const loadResult = (): ResultDir => _.cloneDeep(require('./example-result.json'));
|
||||
|
||||
describe('CodeGen.utils.resultHelper.removeFilesFromResult', () => {
|
||||
it('could remove package.json by "package.json"', () => {
|
||||
const result = loadResult();
|
||||
expect(listAllFiles(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
".eslintrc",
|
||||
"package.json",
|
||||
"src/index.js",
|
||||
"src/index.css",
|
||||
"src/components/index.js",
|
||||
"src/components/Hello/index.js",
|
||||
"src/components/Hello/index.css",
|
||||
]
|
||||
`);
|
||||
|
||||
const removed = CodeGen.utils.resultHelper.removeFilesFromResult(result, 'package.json');
|
||||
|
||||
expect(listAllFiles(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
".eslintrc",
|
||||
"src/index.js",
|
||||
"src/index.css",
|
||||
"src/components/index.js",
|
||||
"src/components/Hello/index.js",
|
||||
"src/components/Hello/index.css",
|
||||
]
|
||||
`);
|
||||
|
||||
expect(removed).toBe(1);
|
||||
});
|
||||
|
||||
it('could remove .eslintrc.json by ".eslintrc" with dot=true', () => {
|
||||
const result = loadResult();
|
||||
expect(listAllFiles(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
".eslintrc",
|
||||
"package.json",
|
||||
"src/index.js",
|
||||
"src/index.css",
|
||||
"src/components/index.js",
|
||||
"src/components/Hello/index.js",
|
||||
"src/components/Hello/index.css",
|
||||
]
|
||||
`);
|
||||
|
||||
const removed = CodeGen.utils.resultHelper.removeFilesFromResult(result, '.eslintrc', {
|
||||
dot: true,
|
||||
});
|
||||
|
||||
expect(listAllFiles(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"package.json",
|
||||
"src/index.js",
|
||||
"src/index.css",
|
||||
"src/components/index.js",
|
||||
"src/components/Hello/index.js",
|
||||
"src/components/Hello/index.css",
|
||||
]
|
||||
`);
|
||||
|
||||
expect(removed).toBe(1);
|
||||
});
|
||||
|
||||
it('could remove all css files by "**/*.css"', () => {
|
||||
const result = loadResult();
|
||||
expect(listAllFiles(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
".eslintrc",
|
||||
"package.json",
|
||||
"src/index.js",
|
||||
"src/index.css",
|
||||
"src/components/index.js",
|
||||
"src/components/Hello/index.js",
|
||||
"src/components/Hello/index.css",
|
||||
]
|
||||
`);
|
||||
|
||||
const removed = CodeGen.utils.resultHelper.removeFilesFromResult(result, '**/*.css');
|
||||
|
||||
expect(listAllFiles(result)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
".eslintrc",
|
||||
"package.json",
|
||||
"src/index.js",
|
||||
"src/components/index.js",
|
||||
"src/components/Hello/index.js",
|
||||
]
|
||||
`);
|
||||
|
||||
expect(removed).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
function listAllFiles(result: ResultDir): string[] {
|
||||
return Array.from(CodeGen.utils.resultHelper.scanFiles(result)).map(([filePath]) => filePath);
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
import CodeGen from '../../../src';
|
||||
|
||||
describe('CodeGen.utils.resultHelper.scanFiles', () => {
|
||||
it('should works', () => {
|
||||
const result = require('./example-result.json') as any;
|
||||
const files = CodeGen.utils.resultHelper.scanFiles(result);
|
||||
expect(Array.from(files)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Array [
|
||||
".eslintrc",
|
||||
Object {
|
||||
"content": "{}",
|
||||
"ext": "",
|
||||
"name": ".eslintrc",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
"package.json",
|
||||
Object {
|
||||
"content": "{ \\"name\\": \\"demo\\", \\"version\\":\\"1.0.0\\" }",
|
||||
"ext": "json",
|
||||
"name": "package",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
"src/index.js",
|
||||
Object {
|
||||
"content": "console.log(\\"Hello\\")",
|
||||
"ext": "js",
|
||||
"name": "index",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
"src/index.css",
|
||||
Object {
|
||||
"content": "html,body{ padding: 0; }",
|
||||
"ext": "css",
|
||||
"name": "index",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
"src/components/index.js",
|
||||
Object {
|
||||
"content": "export * from \\"./Hello\\";",
|
||||
"ext": "js",
|
||||
"name": "index",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
"src/components/Hello/index.js",
|
||||
Object {
|
||||
"content": "export default () => <div>Hello</div>",
|
||||
"ext": "js",
|
||||
"name": "index",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
"src/components/Hello/index.css",
|
||||
Object {
|
||||
"content": ".hello {color: red}",
|
||||
"ext": "css",
|
||||
"name": "index",
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user