diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js index 22b70a953df..5b55d60e328 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.js @@ -78,7 +78,7 @@ const extractEditorSrcTask = task.define('extract-editor-src', () => { apiusages, extrausages ], - shakeLevel: 2, // 0-Files, 1-InnerFile, 2-ClassMembers + shakeLevel: 0, // 0-Files, 1-InnerFile, 2-ClassMembers importIgnorePattern: /(^vs\/css!)/, destRoot: path.join(root, 'out-editor-src'), redirects: [] @@ -88,6 +88,8 @@ const extractEditorSrcTask = task.define('extract-editor-src', () => { // Disable mangling for the editor, as it complicates debugging & quite a few users rely on private/protected fields. const compileEditorAMDTask = task.define('compile-editor-amd', compilation.compileTask('out-editor-src', 'out-editor-build', true, { disableMangle: true })); +const compileEditorESMTaskPipeline = task.define('compile-editor-esm', compilation.compileTask('out-editor-esm', 'out-monaco-editor-core/esm', true, { disableMangle: true, transformConstEnum: 1 })); + const optimizeEditorAMDTask = task.define('optimize-editor-amd', optimize.optimizeTask( { out: 'out-editor', @@ -120,8 +122,11 @@ const createESMSourcesAndResourcesTask = task.define('extract-editor-esm', () => ignores: [ 'inlineEntryPoint:0.ts', 'inlineEntryPoint:1.ts', + 'inlineEntryPoint.0.ts', + 'inlineEntryPoint.1.ts', 'vs/loader.js', 'vs/base/worker/workerMain.ts', + 'vs/nls.ts', ], renames: { 'vs/nls.mock.ts': 'vs/nls.ts' @@ -332,7 +337,7 @@ const finalEditorResourcesTask = task.define('final-editor-resources', () => { // version.txt gulp.src('build/monaco/version.txt') .pipe(es.through(function (data) { - data.contents = Buffer.from(`monaco-editor-core: https://github.com/microsoft/vscode/tree/${sha1}`); + data.contents = Buffer.from(`monaco-editor-core: https://github.com/opensumi/monaco-editor-core/tree/${sha1}`); this.emit('data', data); })) .pipe(gulp.dest('out-monaco-editor-core')), @@ -408,12 +413,13 @@ gulp.task('editor-distro', task.series( compileEditorAMDTask, optimizeEditorAMDTask, - minifyEditorAMDTask + // disable minify + // minifyEditorAMDTask ), task.series( createESMSourcesAndResourcesTask, - compileEditorESMTask, - appendJSToESMImportsTask + compileEditorESMTaskPipeline, + appendJSToESMImportsTask, ) ), finalEditorResourcesTask diff --git a/build/hygiene.js b/build/hygiene.js index 3809036dad1..5c06430c3cf 100644 --- a/build/hygiene.js +++ b/build/hygiene.js @@ -130,6 +130,10 @@ function hygiene(some, linting = true) { const original = result.src.replace(/\r\n/gm, '\n'); const formatted = result.dest.replace(/\r\n/gm, '\n'); + if (process.env.WRITE_FAIL) { + fs.writeFileSync(file.path, formatted, 'utf8'); + } + if (original !== formatted) { console.error( `File not formatted. Run the 'Format Document' command to fix it:`, @@ -173,8 +177,8 @@ function hygiene(some, linting = true) { .pipe(unicodeFilterStream.restore) .pipe(filter(indentationFilter)) .pipe(indentation) - .pipe(filter(copyrightFilter)) - .pipe(copyrights); + .pipe(filter(copyrightFilter)); + // .pipe(copyrights); const streams = [ result.pipe(filter(tsFormattingFilter)).pipe(formatting) diff --git a/build/lib/compilation.js b/build/lib/compilation.js index 35bc464d34a..31b029600c1 100644 --- a/build/lib/compilation.js +++ b/build/lib/compilation.js @@ -132,6 +132,7 @@ function compileTask(src, out, build, options = {}) { .pipe(mangleStream) .pipe(generator.stream) .pipe(compile()) + .pipe(options?.transformConstEnum ? transformConstEnum() : es.through()) .pipe(gulp.dest(out)); }; task.taskName = `compile-${path.basename(src)}`; @@ -291,4 +292,12 @@ exports.watchApiProposalNamesTask = task.define('watch-api-proposal-names', () = .pipe(util.debounce(task)) .pipe(gulp.dest('src')); }); +function transformConstEnum() { + return es.map((file, cb) => { + if (/\.ts$/.test(file.path)) { + file.contents = Buffer.from(file.contents.toString().replace(/const enum/g, 'enum')); + } + cb(null, file); + }); +} //# sourceMappingURL=compilation.js.map \ No newline at end of file diff --git a/build/lib/compilation.ts b/build/lib/compilation.ts index 94bfe6e832d..dba0004561b 100644 --- a/build/lib/compilation.ts +++ b/build/lib/compilation.ts @@ -48,6 +48,7 @@ function createCompile(src: string, build: boolean, emitError: boolean, transpil const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json'); const overrideOptions = { ...getTypeScriptCompilerOptions(src), inlineSources: Boolean(build) }; + if (!build) { overrideOptions.inlineSourceMap = true; } @@ -114,7 +115,7 @@ export function transpileTask(src: string, out: string, swc: boolean): task.Stre return task; } -export function compileTask(src: string, out: string, build: boolean, options: { disableMangle?: boolean } = {}): task.StreamTask { +export function compileTask(src: string, out: string, build: boolean, options: { disableMangle?: boolean; transformConstEnum?: boolean } = {}): task.StreamTask { const task = () => { @@ -156,6 +157,7 @@ export function compileTask(src: string, out: string, build: boolean, options: { .pipe(mangleStream) .pipe(generator.stream) .pipe(compile()) + .pipe(options?.transformConstEnum ? transformConstEnum() : es.through()) .pipe(gulp.dest(out)); }; @@ -340,3 +342,12 @@ export const watchApiProposalNamesTask = task.define('watch-api-proposal-names', .pipe(util.debounce(task)) .pipe(gulp.dest('src')); }); + +function transformConstEnum() { + return es.map((file: File, cb: any) => { + if (/\.ts$/.test(file.path)) { + file.contents = Buffer.from(file.contents.toString().replace(/const enum/g, 'enum')); + } + cb(null, file); + }); +} diff --git a/build/lib/i18n.js b/build/lib/i18n.js index 1844af139c5..64daa2b05dc 100644 --- a/build/lib/i18n.js +++ b/build/lib/i18n.js @@ -19,6 +19,9 @@ const l10n_dev_1 = require("@vscode/l10n-dev"); function log(message, ...rest) { fancyLog(ansiColors.green('[i18n]'), message, ...rest); } +function consumeUnusedVar(...args) { + void args; +} exports.defaultLanguages = [ { id: 'zh-tw', folderName: 'cht', translationId: 'zh-hant' }, { id: 'zh-cn', folderName: 'chs', translationId: 'zh-hans' }, @@ -263,9 +266,9 @@ function escapeCharacters(value) { for (let i = 0; i < value.length; i++) { const ch = value.charAt(i); switch (ch) { - case '\'': - result.push('\\\''); - break; + // case '\'': + // result.push('\\\''); + // break; case '"': result.push('\\"'); break; @@ -294,6 +297,7 @@ function escapeCharacters(value) { return result.join(''); } function processCoreBundleFormat(fileHeader, languages, json, emitter) { + consumeUnusedVar(fileHeader); const keysSection = json.keys; const messageSection = json.messages; const bundleSection = json.bundles; @@ -318,10 +322,18 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { } }); }); - const languageDirectory = path.join(__dirname, '..', '..', '..', 'vscode-loc', 'i18n'); + let languageDirectory = path.join(__dirname, '..', '..', '..', 'vscode-loc', 'i18n'); if (!fs.existsSync(languageDirectory)) { log(`No VS Code localization repository found. Looking at ${languageDirectory}`); - log(`To bundle translations please check out the vscode-loc repository as a sibling of the vscode repository.`); + languageDirectory = path.join(__dirname, '..', '..', 'vscode-loc', 'i18n'); + log(`Now looking at ${languageDirectory}`); + if (!fs.existsSync(languageDirectory)) { + log(`No VS Code localization repository found. Looking at ${languageDirectory}`); + log(`To bundle translations please check out the vscode-loc repository as a sibling of the vscode repository.`); + } + } + if (languageDirectory) { + log(`Found VS Code localization repository at ${languageDirectory}`); } const sortedLanguages = sortLanguages(languages); sortedLanguages.forEach((language) => { @@ -374,8 +386,7 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { Object.keys(bundleSection).forEach((bundle) => { const modules = bundleSection[bundle]; const contents = [ - fileHeader, - `define("${bundle}.nls.${language.id}", {` + '{', ]; modules.forEach((module, index) => { contents.push(`\t"${module}": [`); @@ -385,12 +396,12 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { return; } messages.forEach((message, index) => { - contents.push(`\t\t"${escapeCharacters(message)}${index < messages.length ? '",' : '"'}`); + contents.push(`\t\t"${escapeCharacters(message)}${index < messages.length - 1 ? '",' : '"'}`); }); contents.push(index < modules.length - 1 ? '\t],' : '\t]'); }); - contents.push('});'); - emitter.queue(new File({ path: bundle + '.nls.' + language.id + '.js', contents: Buffer.from(contents.join('\n'), 'utf-8') })); + contents.push('}'); + emitter.queue(new File({ path: bundle + '.nls.' + language.id + '.json', contents: Buffer.from(contents.join('\n'), 'utf-8') })); }); }); Object.keys(statistics).forEach(key => { @@ -404,6 +415,20 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { } }); } +const commonHeader1 = `/*---------------------------------------------------------\n`; +const commonHeader2 = `* Copyright (c) Microsoft Corporation. All rights reserved.\n`; +const commonHeader3 = `*--------------------------------------------------------*/`; +// transform nls.js to nls.json +function toJsonNlsFile(content, fileHeader) { + return content + .replace(fileHeader, '') + .replace(commonHeader1, '') + .replace(commonHeader2, '') + .replace(commonHeader3, '') + .replace(`define("vs/editor/editor.main.nls", {`, '{') + .replace('});', '}') + .trim(); +} function processNlsFiles(opts) { return (0, event_stream_1.through)(function (file) { const fileName = path.basename(file.path); @@ -420,7 +445,15 @@ function processNlsFiles(opts) { processCoreBundleFormat(opts.fileHeader, opts.languages, json, this); } } - this.queue(file); + if (file.path.includes('editor.main.nls.js')) { + this.queue(new File({ + path: file.path.replace('.js', '.json'), + contents: Buffer.from(toJsonNlsFile(file.contents.toString(), opts.fileHeader)), + })); + } + else { + this.queue(file); + } }); } exports.processNlsFiles = processNlsFiles; diff --git a/build/lib/i18n.ts b/build/lib/i18n.ts index 444e3abe59c..e465c866f4f 100644 --- a/build/lib/i18n.ts +++ b/build/lib/i18n.ts @@ -20,6 +20,10 @@ function log(message: any, ...rest: any[]): void { fancyLog(ansiColors.green('[i18n]'), message, ...rest); } +function consumeUnusedVar(...args: any[]): void { + void args; +} + export interface Language { id: string; // language id, e.g. zh-tw, de translationId?: string; // language id used in translation tools, e.g. zh-hant, de (optional, if not set, the id is used) @@ -334,9 +338,9 @@ function escapeCharacters(value: string): string { for (let i = 0; i < value.length; i++) { const ch = value.charAt(i); switch (ch) { - case '\'': - result.push('\\\''); - break; + // case '\'': + // result.push('\\\''); + // break; case '"': result.push('\\"'); break; @@ -366,6 +370,7 @@ function escapeCharacters(value: string): string { } function processCoreBundleFormat(fileHeader: string, languages: Language[], json: BundledFormat, emitter: ThroughStream) { + consumeUnusedVar(fileHeader); const keysSection = json.keys; const messageSection = json.messages; const bundleSection = json.bundles; @@ -392,11 +397,22 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json }); }); - const languageDirectory = path.join(__dirname, '..', '..', '..', 'vscode-loc', 'i18n'); + let languageDirectory = path.join(__dirname, '..', '..', '..', 'vscode-loc', 'i18n'); if (!fs.existsSync(languageDirectory)) { log(`No VS Code localization repository found. Looking at ${languageDirectory}`); - log(`To bundle translations please check out the vscode-loc repository as a sibling of the vscode repository.`); + languageDirectory = path.join(__dirname, '..', '..', 'vscode-loc', 'i18n'); + log(`Now looking at ${languageDirectory}`); + + if (!fs.existsSync(languageDirectory)) { + log(`No VS Code localization repository found. Looking at ${languageDirectory}`); + log(`To bundle translations please check out the vscode-loc repository as a sibling of the vscode repository.`); + } + } + + if (languageDirectory) { + log(`Found VS Code localization repository at ${languageDirectory}`); } + const sortedLanguages = sortLanguages(languages); sortedLanguages.forEach((language) => { if (process.env['VSCODE_BUILD_VERBOSE']) { @@ -446,10 +462,10 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json localizedModules[module] = localizedMessages; }); Object.keys(bundleSection).forEach((bundle) => { + const modules = bundleSection[bundle]; const contents: string[] = [ - fileHeader, - `define("${bundle}.nls.${language.id}", {` + '{', ]; modules.forEach((module, index) => { contents.push(`\t"${module}": [`); @@ -459,12 +475,12 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json return; } messages.forEach((message, index) => { - contents.push(`\t\t"${escapeCharacters(message)}${index < messages.length ? '",' : '"'}`); + contents.push(`\t\t"${escapeCharacters(message)}${index < messages.length - 1 ? '",' : '"'}`); }); contents.push(index < modules.length - 1 ? '\t],' : '\t]'); }); - contents.push('});'); - emitter.queue(new File({ path: bundle + '.nls.' + language.id + '.js', contents: Buffer.from(contents.join('\n'), 'utf-8') })); + contents.push('}'); + emitter.queue(new File({ path: bundle + '.nls.' + language.id + '.json', contents: Buffer.from(contents.join('\n'), 'utf-8') })); }); }); Object.keys(statistics).forEach(key => { @@ -479,6 +495,22 @@ function processCoreBundleFormat(fileHeader: string, languages: Language[], json }); } +const commonHeader1 = `/*---------------------------------------------------------\n`; +const commonHeader2 = `* Copyright (c) Microsoft Corporation. All rights reserved.\n`; +const commonHeader3 = `*--------------------------------------------------------*/`; + +// transform nls.js to nls.json +function toJsonNlsFile(content: string, fileHeader: string): string { + return content + .replace(fileHeader, '') + .replace(commonHeader1, '') + .replace(commonHeader2, '') + .replace(commonHeader3, '') + .replace(`define("vs/editor/editor.main.nls", {`, '{') + .replace('});', '}') + .trim(); +} + export function processNlsFiles(opts: { fileHeader: string; languages: Language[] }): ThroughStream { return through(function (this: ThroughStream, file: File) { const fileName = path.basename(file.path); @@ -494,7 +526,17 @@ export function processNlsFiles(opts: { fileHeader: string; languages: Language[ processCoreBundleFormat(opts.fileHeader, opts.languages, json, this); } } - this.queue(file); + + if (file.path.includes('editor.main.nls.js')) { + this.queue(new File( + { + path: file.path.replace('.js', '.json'), + contents: Buffer.from(toJsonNlsFile(file.contents.toString(), opts.fileHeader)), + } + )); + } else { + this.queue(file); + } }); } diff --git a/build/lib/nls.js b/build/lib/nls.js index 982f74bcf4d..36ebbe31f1a 100644 --- a/build/lib/nls.js +++ b/build/lib/nls.js @@ -127,7 +127,7 @@ var _nls; } return node.kind === ts.SyntaxKind.CallExpression ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse; } - function analyze(ts, contents, functionName, options = {}) { + function analyze(ts, moduleId, contents, functionName, options = {}) { const filename = 'file.ts'; const serviceHost = new SingleFileServiceHost(ts, Object.assign(clone(options), { noResolve: true }), filename, contents); const service = ts.createLanguageService(serviceHost); @@ -139,13 +139,13 @@ var _nls; .filter(n => n.kind === ts.SyntaxKind.ImportEqualsDeclaration) .map(n => n) .filter(d => d.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) - .filter(d => d.moduleReference.expression.getText() === '\'vs/nls\''); + .filter(d => d.moduleReference.expression.getText().includes('\/nls')); // import ... from 'vs/nls'; const importDeclarations = imports .filter(n => n.kind === ts.SyntaxKind.ImportDeclaration) .map(n => n) .filter(d => d.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral) - .filter(d => d.moduleSpecifier.getText() === '\'vs/nls\'') + .filter(d => d.moduleSpecifier.getText().includes('\/nls')) .filter(d => !!d.importClause && !!d.importClause.namedBindings); const nlsExpressions = importEqualsDeclarations .map(d => d.moduleReference.expression) @@ -201,7 +201,9 @@ var _nls; .filter(a => a.length > 1) .sort((a, b) => a[0].getStart() - b[0].getStart()) .map(a => ({ - keySpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getEnd()) }, + pathSpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getEnd()) }, + path: `"${moduleId}",`, + keySpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart() - 1), end: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart() - 1) }, key: a[0].getText(), valueSpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getEnd()) }, value: a[1].getText() @@ -309,8 +311,8 @@ var _nls; return JSON.parse(smg.toString()); } function patch(ts, moduleId, typescript, javascript, sourcemap) { - const { localizeCalls, nlsExpressions } = analyze(ts, typescript, 'localize'); - const { localizeCalls: localize2Calls, nlsExpressions: nls2Expressions } = analyze(ts, typescript, 'localize2'); + const { localizeCalls, nlsExpressions } = analyze(ts, moduleId, typescript, 'localize'); + const { localizeCalls: localize2Calls, nlsExpressions: nls2Expressions } = analyze(ts, moduleId, typescript, 'localize2'); if (localizeCalls.length === 0 && localize2Calls.length === 0) { return { javascript, sourcemap }; } @@ -327,13 +329,18 @@ var _nls; let i = 0; const localizePatches = lazy(localizeCalls) .map(lc => ([ + { range: lc.pathSpan, content: lc.path }, { range: lc.keySpan, content: '' + (i++) }, - { range: lc.valueSpan, content: 'null' } + { range: lc.valueSpan, content: lc.value }, ])) .flatten() .map(toPatch); const localize2Patches = lazy(localize2Calls) - .map(lc => ({ range: lc.keySpan, content: '' + (i++) })) + .map(lc => ([ + { range: lc.pathSpan, content: lc.path }, + { range: lc.keySpan, content: '' + (i++) }, + { range: lc.valueSpan, content: lc.value }, + ])).flatten() .map(toPatch); // Sort patches by their start position const patches = localizePatches.concat(localize2Patches).toArray().sort((a, b) => { @@ -364,6 +371,7 @@ var _nls; sourcemap = patchSourcemap(patches, sourcemap, smc); return { javascript, sourcemap, nlsKeys, nls }; } + _nls.patch = patch; function patchFiles(javascriptFile, typescript) { const ts = require('typescript'); // hack? diff --git a/build/lib/nls.ts b/build/lib/nls.ts index c4ee031b2eb..fa317640048 100644 --- a/build/lib/nls.ts +++ b/build/lib/nls.ts @@ -116,6 +116,8 @@ module _nls { key: string; valueSpan: ISpan; value: string; + pathSpan: ISpan; + path: string; } interface ILocalizeAnalysisResult { @@ -183,6 +185,7 @@ module _nls { function analyze( ts: typeof import('typescript'), + moduleId: string, contents: string, functionName: 'localize' | 'localize2', options: ts.CompilerOptions = {} @@ -200,14 +203,14 @@ module _nls { .filter(n => n.kind === ts.SyntaxKind.ImportEqualsDeclaration) .map(n => n) .filter(d => d.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) - .filter(d => (d.moduleReference).expression.getText() === '\'vs/nls\''); + .filter(d => (d.moduleReference).expression.getText().includes('\/nls')); // import ... from 'vs/nls'; const importDeclarations = imports .filter(n => n.kind === ts.SyntaxKind.ImportDeclaration) .map(n => n) .filter(d => d.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral) - .filter(d => d.moduleSpecifier.getText() === '\'vs/nls\'') + .filter(d => d.moduleSpecifier.getText().includes('\/nls')) .filter(d => !!d.importClause && !!d.importClause.namedBindings); const nlsExpressions = importEqualsDeclarations @@ -273,7 +276,9 @@ module _nls { .filter(a => a.length > 1) .sort((a, b) => a[0].getStart() - b[0].getStart()) .map(a => ({ - keySpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getEnd()) }, + pathSpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getEnd()) }, + path: `"${moduleId}",`, + keySpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart() - 1), end: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart() - 1) }, key: a[0].getText(), valueSpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getEnd()) }, value: a[1].getText() @@ -410,10 +415,9 @@ module _nls { return JSON.parse(smg.toString()); } - function patch(ts: typeof import('typescript'), moduleId: string, typescript: string, javascript: string, sourcemap: sm.RawSourceMap): INlsStringResult { - const { localizeCalls, nlsExpressions } = analyze(ts, typescript, 'localize'); - const { localizeCalls: localize2Calls, nlsExpressions: nls2Expressions } = analyze(ts, typescript, 'localize2'); - + export function patch(ts: typeof import('typescript'), moduleId: string, typescript: string, javascript: string, sourcemap: sm.RawSourceMap): INlsStringResult { + const { localizeCalls, nlsExpressions } = analyze(ts, moduleId, typescript, 'localize'); + const { localizeCalls: localize2Calls, nlsExpressions: nls2Expressions } = analyze(ts, moduleId, typescript, 'localize2'); if (localizeCalls.length === 0 && localize2Calls.length === 0) { return { javascript, sourcemap }; } @@ -433,16 +437,19 @@ module _nls { let i = 0; const localizePatches = lazy(localizeCalls) .map(lc => ([ + { range: lc.pathSpan, content: lc.path }, { range: lc.keySpan, content: '' + (i++) }, - { range: lc.valueSpan, content: 'null' } + { range: lc.valueSpan, content: lc.value }, ])) .flatten() .map(toPatch); const localize2Patches = lazy(localize2Calls) - .map(lc => ( - { range: lc.keySpan, content: '' + (i++) } - )) + .map(lc => ([ + { range: lc.pathSpan, content: lc.path }, + { range: lc.keySpan, content: '' + (i++) }, + { range: lc.valueSpan, content: lc.value }, + ])).flatten() .map(toPatch); // Sort patches by their start position diff --git a/build/lib/standalone.js b/build/lib/standalone.js index 4ddf88ed223..27207948f08 100644 --- a/build/lib/standalone.js +++ b/build/lib/standalone.js @@ -134,8 +134,11 @@ function createESMSourcesAndResources2(options) { } if (file === 'tsconfig.json') { const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString()); - tsConfig.compilerOptions.module = 'es6'; + tsConfig.compilerOptions.module = 'commonjs'; tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/'); + tsConfig.compilerOptions.preserveConstEnums = true; + tsConfig.compilerOptions.declaration = true; + tsConfig.compilerOptions.noEmitOnError = false; write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); continue; } @@ -153,12 +156,18 @@ function createESMSourcesAndResources2(options) { const pos = info.importedFiles[i].pos; const end = info.importedFiles[i].end; let importedFilepath; + let importedIsAFile = false; if (/^vs\/css!/.test(importedFilename)) { importedFilepath = importedFilename.substr('vs/css!'.length) + '.css'; } else { importedFilepath = importedFilename; } + // try to resolve the imported file path + const filePath = path.join(SRC_FOLDER, importedFilepath); + if (fs.existsSync(filePath + '.ts')) { + importedIsAFile = true; + } if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) { importedFilepath = path.join(path.dirname(file), importedFilepath); } @@ -170,7 +179,14 @@ function createESMSourcesAndResources2(options) { relativePath = '../../' + path.basename(path.dirname(path.dirname(file))); } else { - relativePath = path.relative(path.dirname(file), importedFilepath); + if (importedIsAFile) { + importedFilepath = importedFilepath + '.ts'; + relativePath = path.relative(path.dirname(file), importedFilepath); + relativePath = relativePath.replace(/\.ts$/, ''); + } + else { + relativePath = path.relative(path.dirname(file), importedFilepath); + } } relativePath = relativePath.replace(/\\/g, '/'); if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts index 775a1be5996..adcada78a71 100644 --- a/build/lib/standalone.ts +++ b/build/lib/standalone.ts @@ -160,8 +160,12 @@ export function createESMSourcesAndResources2(options: IOptions2): void { if (file === 'tsconfig.json') { const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString()); - tsConfig.compilerOptions.module = 'es6'; + tsConfig.compilerOptions.module = 'commonjs'; tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/'); + tsConfig.compilerOptions.preserveConstEnums = true; + tsConfig.compilerOptions.declaration = true; + tsConfig.compilerOptions.noEmitOnError = false; + write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t')); continue; } @@ -184,11 +188,19 @@ export function createESMSourcesAndResources2(options: IOptions2): void { const end = info.importedFiles[i].end; let importedFilepath: string; + let importedIsAFile = false; if (/^vs\/css!/.test(importedFilename)) { importedFilepath = importedFilename.substr('vs/css!'.length) + '.css'; } else { importedFilepath = importedFilename; } + + // try to resolve the imported file path + const filePath = path.join(SRC_FOLDER, importedFilepath); + if (fs.existsSync(filePath + '.ts')) { + importedIsAFile= true; + } + if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) { importedFilepath = path.join(path.dirname(file), importedFilepath); } @@ -199,7 +211,13 @@ export function createESMSourcesAndResources2(options: IOptions2): void { } else if (importedFilepath === path.dirname(path.dirname(file)).replace(/\\/g, '/')) { relativePath = '../../' + path.basename(path.dirname(path.dirname(file))); } else { - relativePath = path.relative(path.dirname(file), importedFilepath); + if (importedIsAFile) { + importedFilepath = importedFilepath + '.ts'; + relativePath = path.relative(path.dirname(file), importedFilepath); + relativePath = relativePath.replace(/\.ts$/, ''); + } else{ + relativePath = path.relative(path.dirname(file), importedFilepath); + } } relativePath = relativePath.replace(/\\/g, '/'); if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) { diff --git a/build/monaco/package.json b/build/monaco/package.json index 687af0852aa..484db0b92c0 100644 --- a/build/monaco/package.json +++ b/build/monaco/package.json @@ -1,17 +1,19 @@ { - "name": "monaco-editor-core", - "private": true, - "version": "0.0.0", + "name": "@opensumi/monaco-editor-core", + "version": "0.47.0-patch.15", "description": "A browser based code editor", - "author": "Microsoft Corporation", + "author": "Microsoft Corporation and open source contributors", "license": "MIT", "typings": "./esm/vs/editor/editor.api.d.ts", "module": "./esm/vs/editor/editor.main.js", "repository": { "type": "git", - "url": "https://github.com/microsoft/vscode" + "url": "https://github.com/opensumi/monaco-editor-core" }, "bugs": { - "url": "https://github.com/microsoft/vscode/issues" + "url": "https://github.com/opensumi/monaco-editor-core/issues" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/" } } diff --git a/src/vs/base/browser/dompurify/dompurify.js b/src/vs/base/browser/dompurify/dompurify.js index d43b10a85d1..2ce7f2b9219 100644 --- a/src/vs/base/browser/dompurify/dompurify.js +++ b/src/vs/base/browser/dompurify/dompurify.js @@ -1625,7 +1625,7 @@ var purify = createDOMPurify(); define(function () { return purify; }); // ESM-comment-end -// ESM-uncomment-begin +// -ESM-uncomment-begin // export default purify; // export const version = purify.version; // export const isSupported = purify.isSupported; @@ -1637,4 +1637,9 @@ define(function () { return purify; }); // export const removeHook = purify.removeHook; // export const removeHooks = purify.removeHooks; // export const removeAllHooks = purify.removeAllHooks; +// -ESM-uncomment-end + + +// ESM-uncomment-begin +// module.exports = purify; // ESM-uncomment-end diff --git a/src/vs/base/browser/settings.ts b/src/vs/base/browser/settings.ts new file mode 100644 index 00000000000..64b8d1f75f7 --- /dev/null +++ b/src/vs/base/browser/settings.ts @@ -0,0 +1,49 @@ +/* eslint-disable header/header */ + +class OverflowContentWidgetsSettings { + private _topPadding = 22; + private _bottomPadding = 22; + + private _hoverWidgetMaxHeight = 250; + private _hoverWidgetMaxWidth = 500; + + set topPadding(num: number) { + if (Number.isInteger(num)) { + this._topPadding = num; + } + } + get topPadding() { + return this._topPadding; + } + + set bottomPadding(num: number) { + if (Number.isInteger(num)) { + this._bottomPadding = num; + } + } + get bottomPadding() { + return this._bottomPadding; + } + + get hoverWidgetMaxHeight() { + return this._hoverWidgetMaxHeight; + } + + get hoverWidgetMaxWidth() { + return this._hoverWidgetMaxWidth; + } + + set hoverWidgetMaxHeight(num: number) { + if (Number.isInteger(num)) { + this._hoverWidgetMaxHeight = num; + } + } + + set hoverWidgetMaxWidth(num: number) { + if (Number.isInteger(num)) { + this._hoverWidgetMaxWidth = num; + } + } +} + +export const overflowWidgetsSettings = new OverflowContentWidgetsSettings(); diff --git a/src/vs/base/common/amd.ts b/src/vs/base/common/amd.ts index 2ee86a98646..e521ba000df 100644 --- a/src/vs/base/common/amd.ts +++ b/src/vs/base/common/amd.ts @@ -7,7 +7,7 @@ export const isESM = false; // ESM-comment-end // ESM-uncomment-begin -// export const isESM = true; +// export const isESM = false; // ESM-uncomment-end export abstract class LoaderStats { diff --git a/src/vs/base/common/marked/marked.js b/src/vs/base/common/marked/marked.js index eb8cde82ab4..7b30c4ba083 100644 --- a/src/vs/base/common/marked/marked.js +++ b/src/vs/base/common/marked/marked.js @@ -9,14 +9,14 @@ * The code in this file is generated from files in ./src/ */ -// ESM-uncomment-begin +// -ESM-uncomment-begin // let __marked_exports = {}; // (function() { // function define(deps, factory) { // factory(__marked_exports); // } // define.amd = true; -// ESM-uncomment-end +// -ESM-uncomment-end (function (global, factory) { typeof define === 'function' && define.amd ? define(['exports'], factory) : @@ -3079,7 +3079,7 @@ })); -// ESM-uncomment-begin +// -ESM-uncomment-begin // })(); // export var Lexer = (__marked_exports.Lexer || exports.Lexer); // export var Parser = (__marked_exports.Parser || exports.Parser); @@ -3097,4 +3097,4 @@ // export var setOptions = (__marked_exports.setOptions || exports.setOptions); // export var use = (__marked_exports.use || exports.use); // export var walkTokens = (__marked_exports.walkTokens || exports.walkTokens); -// ESM-uncomment-end +// -ESM-uncomment-end diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index aff4d0734de..bfacc6543c3 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -78,7 +78,7 @@ } else if (typeof process === 'object') { // node.js: use the normal polyfill but add the timeOrigin // from the node perf_hooks API as very first mark - const timeOrigin = performance?.timeOrigin ?? Math.round((require.__$__nodeRequire || require)('perf_hooks').performance.timeOrigin); + const timeOrigin = (performance ? performance.timeOrigin : undefined) || Math.round((require.__$__nodeRequire || require.nodeRequire || require)('perf_hooks').performance.timeOrigin); return _definePolyfillMarks(timeOrigin); } else { diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts index 3893fbc6fcd..e55dc47bf28 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -60,7 +60,8 @@ let nodeProcess: INodeProcess | undefined = undefined; if (typeof $globalThis.vscode !== 'undefined' && typeof $globalThis.vscode.process !== 'undefined') { // Native environment (sandboxed) nodeProcess = $globalThis.vscode.process; -} else if (typeof process !== 'undefined') { +} else if (typeof process !== 'undefined' && !(process as any).browser && typeof process.platform === 'string') { + // bundler may inject a `process`, but current environment is not node.js // Native environment (non-sandboxed) nodeProcess = process; } diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index 3112c19c324..2bf539a6b21 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -16,6 +16,7 @@ import { IDimension } from 'vs/editor/common/core/dimension'; import { PositionAffinity } from 'vs/editor/common/model'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { IViewModel } from 'vs/editor/common/viewModel'; +import { overflowWidgetsSettings } from 'vs/base/browser/settings'; export class ViewContentWidgets extends ViewPart { @@ -291,7 +292,7 @@ class Widget { this._cachedDomNodeOffsetHeight = -1; } - private _layoutBoxInViewport(anchor: AnchorCoordinate, width: number, height: number, ctx: RenderingContext): IBoxLayoutResult { + private _layoutBoxInViewport(anchor: AnchorCoordinate, width: number, _height: number, ctx: RenderingContext): IBoxLayoutResult { // Our visible box is split horizontally by the current line => 2 boxes // a) the box above the line @@ -302,6 +303,19 @@ class Widget { const underLineTop = anchor.top + anchor.height; const heightAvailableUnderLine = ctx.viewportHeight - underLineTop; + // allow-any-unicode-next-line + // 这里传入的 height 为 0 会导致下面计算 contentWidget 定位时整体向下偏移了一行 + // allow-any-unicode-next-line + // 由于获取的是缓存的 domNode 的 clientHeight 可能为 0, domNode 渲染时机暂时不好修改,所以如果高度为 0 的话,在这里重新获取一次高度 + let height = _height; + if (height === 0) { + const domNode = this.domNode.domNode; + const clientRect = domNode.getBoundingClientRect(); + this._cachedDomNodeOffsetWidth = Math.round(clientRect.width); + this._cachedDomNodeOffsetHeight = Math.round(clientRect.height); + height = this._cachedDomNodeOffsetHeight; + } + const aboveTop = aboveLineTop - height; const fitsAbove = (heightAvailableAboveLine >= height); const belowTop = underLineTop; @@ -361,8 +375,8 @@ class Widget { const [left, absoluteAboveLeft] = this._layoutHorizontalSegmentInPage(windowSize, domNodePosition, anchor.left - ctx.scrollLeft + this._contentLeft, width); // Leave some clearance to the top/bottom - const TOP_PADDING = 22; - const BOTTOM_PADDING = 22; + const TOP_PADDING = overflowWidgetsSettings.topPadding; + const BOTTOM_PADDING = overflowWidgetsSettings.bottomPadding; const fitsAbove = (absoluteAboveTop >= TOP_PADDING); const fitsBelow = (absoluteBelowTop + height <= windowSize.height - BOTTOM_PADDING); diff --git a/src/vs/editor/browser/viewParts/lines/viewLine.ts b/src/vs/editor/browser/viewParts/lines/viewLine.ts index e4174a2f286..6981ccd7778 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLine.ts @@ -395,7 +395,7 @@ class FastRenderedViewLine implements IRenderedViewLine { const horizontalOffset = this._characterMapping.getHorizontalOffset(this._characterMapping.length); return Math.round(this._charWidth * horizontalOffset); } - if (this._cachedWidth === -1) { + if (this._cachedWidth <= 0) { this._cachedWidth = this._getReadingTarget(this.domNode).offsetWidth; context?.markDidDomLayout(); } @@ -529,7 +529,7 @@ class RenderedViewLine implements IRenderedViewLine { if (!this.domNode) { return 0; } - if (this._cachedWidth === -1) { + if (this._cachedWidth <= 0) { this._cachedWidth = this._getReadingTarget(this.domNode).offsetWidth; context?.markDidDomLayout(); } diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index f03e018cac0..69faeaba4ab 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -809,7 +809,7 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { // static foreing module return Promise.resolve(getAllMethodNames(this._foreignModule)); } - // ESM-comment-begin + // -ESM-comment-begin return new Promise((resolve, reject) => { require([moduleId], (foreignModule: { create: IForeignModuleFactory }) => { this._foreignModule = foreignModule.create(ctx, createData); @@ -818,11 +818,11 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { }, reject); }); - // ESM-comment-end + // -ESM-comment-end - // ESM-uncomment-begin + // -ESM-uncomment-begin // return Promise.reject(new Error(`Unexpected usage`)); - // ESM-uncomment-end + // -ESM-uncomment-end } // foreign method request diff --git a/src/vs/editor/contrib/codeAction/browser/lightBulbWidget.ts b/src/vs/editor/contrib/codeAction/browser/lightBulbWidget.ts index 42564d79f66..fc6b7c0d124 100644 --- a/src/vs/editor/contrib/codeAction/browser/lightBulbWidget.ts +++ b/src/vs/editor/contrib/codeAction/browser/lightBulbWidget.ts @@ -20,7 +20,7 @@ import * as nls from 'vs/nls'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -namespace LightBulbState { +export namespace LightBulbState { export const enum Type { Hidden, @@ -47,22 +47,22 @@ export class LightBulbWidget extends Disposable implements IContentWidget { public static readonly ID = 'editor.contrib.lightbulbWidget'; - private static readonly _posPref = [ContentWidgetPositionPreference.EXACT]; + protected static readonly _posPref = [ContentWidgetPositionPreference.EXACT]; - private readonly _domNode: HTMLElement; + protected readonly _domNode: HTMLElement; - private readonly _onClick = this._register(new Emitter<{ readonly x: number; readonly y: number; readonly actions: CodeActionSet; readonly trigger: CodeActionTrigger }>()); + protected readonly _onClick = this._register(new Emitter<{ readonly x: number; readonly y: number; readonly actions: CodeActionSet; readonly trigger: CodeActionTrigger }>()); public readonly onClick = this._onClick.event; - private _state: LightBulbState.State = LightBulbState.Hidden; - private _iconClasses: string[] = []; + protected _state: LightBulbState.State = LightBulbState.Hidden; + protected _iconClasses: string[] = []; - private _preferredKbLabel?: string; - private _quickFixKbLabel?: string; + protected _preferredKbLabel?: string; + protected _quickFixKbLabel?: string; constructor( - private readonly _editor: ICodeEditor, - @IKeybindingService private readonly _keybindingService: IKeybindingService, + protected readonly _editor: ICodeEditor, + @IKeybindingService protected readonly _keybindingService: IKeybindingService, @ICommandService commandService: ICommandService, ) { super(); @@ -201,14 +201,14 @@ export class LightBulbWidget extends Disposable implements IContentWidget { this._editor.layoutContentWidget(this); } - private get state(): LightBulbState.State { return this._state; } + protected get state(): LightBulbState.State { return this._state; } - private set state(value) { + protected set state(value) { this._state = value; this._updateLightBulbTitleAndIcon(); } - private _updateLightBulbTitleAndIcon(): void { + protected _updateLightBulbTitleAndIcon(): void { this._domNode.classList.remove(...this._iconClasses); this._iconClasses = []; if (this.state.type !== LightBulbState.Type.Showing) { @@ -237,7 +237,7 @@ export class LightBulbWidget extends Disposable implements IContentWidget { this._domNode.classList.add(...this._iconClasses); } - private _updateLightbulbTitle(autoFix: boolean, autoRun: boolean): void { + protected _updateLightbulbTitle(autoFix: boolean, autoRun: boolean): void { if (this.state.type !== LightBulbState.Type.Showing) { return; } @@ -252,7 +252,7 @@ export class LightBulbWidget extends Disposable implements IContentWidget { } } - private set title(value: string) { + protected set title(value: string) { this._domNode.title = value; } } diff --git a/src/vs/editor/contrib/hover/browser/contentHover.ts b/src/vs/editor/contrib/hover/browser/contentHover.ts index 491ecb001dd..143be6d8f8c 100644 --- a/src/vs/editor/contrib/hover/browser/contentHover.ts +++ b/src/vs/editor/contrib/hover/browser/contentHover.ts @@ -26,6 +26,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c import { ResizableContentWidget } from 'vs/editor/contrib/hover/browser/resizableContentWidget'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; +import { overflowWidgetsSettings } from 'vs/base/browser/settings'; const $ = dom.$; @@ -782,8 +783,8 @@ export class ContentHoverWidget extends ResizableContentWidget { } private _updateMaxDimensions() { - const height = Math.max(this._editor.getLayoutInfo().height / 4, 250, ContentHoverWidget._lastDimensions.height); - const width = Math.max(this._editor.getLayoutInfo().width * 0.66, 500, ContentHoverWidget._lastDimensions.width); + const height = Math.max(this._editor.getLayoutInfo().height / 4, overflowWidgetsSettings.hoverWidgetMaxHeight, ContentHoverWidget._lastDimensions.height); + const width = Math.max(this._editor.getLayoutInfo().width * 0.66, overflowWidgetsSettings.hoverWidgetMaxWidth, ContentHoverWidget._lastDimensions.width); this._setHoverWidgetMaxDimensions(width, height); } diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts index 351f85537d8..bb448d2adf6 100644 --- a/src/vs/editor/standalone/browser/standaloneServices.ts +++ b/src/vs/editor/standalone/browser/standaloneServices.ts @@ -1142,9 +1142,10 @@ export module StandaloneServices { serviceCollection.set(IInstantiationService, instantiationService); export function get(serviceId: ServiceIdentifier): T { - if (!initialized) { - initialize({}); - } + // we will initialize the services in need on demand on OpenSumi + // if (!initialized) { + // initialize({}); + // } const r = serviceCollection.get(serviceId); if (!r) { throw new Error('Missing service ' + serviceId); diff --git a/src/vs/nls.mock.ts b/src/vs/nls.mock.ts index d9ee1ecd2c6..03e50f7fca6 100644 --- a/src/vs/nls.mock.ts +++ b/src/vs/nls.mock.ts @@ -3,12 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +// @ts-ignore +const zhCnBundle = require('../../dev/vs/editor/editor.main.nls.zh-cn.json'); + export interface ILocalizeInfo { key: string; comment: string[]; } -interface ILocalizedString { +export interface ILocalizedString { original: string; value: string; } @@ -26,12 +29,57 @@ function _format(message: string, args: any[]): string { return result; } +let defaultLocale: string | undefined; +let initialized = false; +let CURRENT_LOCALE_DATA: { [prop: string]: string[] } | null = null; +let localeFactory: () => string; + +export type LocaleType = 'zh-CN' | 'en-US'; + +export function setLocale(locale: LocaleType): void { + defaultLocale = locale; +} + +export function loadLocaleBundle(bundle: { [prop: string]: string[] }) { + CURRENT_LOCALE_DATA = bundle; +} + +export function configureLocaleFactory(factory: () => string): void { + localeFactory = factory; +} + export function localize(data: ILocalizeInfo | string, message: string, ...args: any[]): string { + // allow-any-unicode-next-line + // 第一次调用 localize 时如果没有默认语言,或语言包尚未初始化,则走初始化逻辑 + if (!defaultLocale || !initialized) { + const factory = localeFactory || defaultInitialLocaleBundle; + if (factory) { + defaultLocale = factory(); + // allow-any-unicode-next-line + // 由于目前仅支持中/英文,所以如果 locale 为 'zh-cn',则表示已经设置了中文,locale 不设置的话,直接用传入的默认值 + if (defaultLocale?.toLowerCase() === 'zh-cn') { + CURRENT_LOCALE_DATA = zhCnBundle; + } + initialized = true; + } + } + + if (typeof data === 'string') { + let template: string | undefined; + if (CURRENT_LOCALE_DATA && CURRENT_LOCALE_DATA[data]) { + template = CURRENT_LOCALE_DATA[data][message as unknown as number]; + } + + const [defaultMessage, ...otherArgs] = args; + return _format(template || defaultMessage, otherArgs); + } + return _format(message, args); } export function localize2(data: ILocalizeInfo | string, message: string, ...args: any[]): ILocalizedString { - const res = _format(message, args); + // eslint-disable-next-line local/code-no-unexternalized-strings + const res = localize(data, message, ...args); return { original: res, value: res @@ -41,3 +89,32 @@ export function localize2(data: ILocalizeInfo | string, message: string, ...args export function getConfiguredDefaultLocale(_: string) { return undefined; } + +export enum PreferenceScope { + Default, + User, +} + +const KAITIAN_LANGUAGE_KEY = 'general.language'; + + +function defaultInitialLocaleBundle() { + // @ts-ignore + if (!global.localStorage || !self.localStorage) { + return; + + } + let _locale = defaultLocale; + + if (!_locale) { + if (localStorage[`${PreferenceScope.User}:${KAITIAN_LANGUAGE_KEY}`]) { + _locale = localStorage[`${PreferenceScope.User}:${KAITIAN_LANGUAGE_KEY}`]; + } else if (localStorage[`${PreferenceScope.Default}:${KAITIAN_LANGUAGE_KEY}`]) { + _locale = localStorage[`${PreferenceScope.Default}:${KAITIAN_LANGUAGE_KEY}`]; + } else { + _locale = 'zh-CN'; + } + } + + return _locale; +}