From bdb8fb6e4a54a0745eba24ff0719e8cec6a4f10f Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 3 Nov 2017 11:04:34 +0100 Subject: [PATCH] Restructure the code to fit to latest nls tooling --- i18n-sample/.gitignore | 1 + i18n-sample/.vscode/tasks.json | 53 +++-- i18n-sample/README.md | 49 ++--- i18n-sample/gulpfile.js | 191 ++++++++---------- .../i18n/jpn/out/src/command/sayBye.i18n.json | 3 - .../i18n/jpn/out/src/extension.i18n.json | 3 - i18n-sample/package.json | 100 ++++----- i18n-sample/package.nls.json | 6 +- i18n-sample/src/command/sayBye.ts | 11 +- i18n-sample/src/extension.ts | 26 ++- i18n-sample/tsconfig.json | 28 +-- 11 files changed, 215 insertions(+), 256 deletions(-) delete mode 100644 i18n-sample/i18n/jpn/out/src/command/sayBye.i18n.json delete mode 100644 i18n-sample/i18n/jpn/out/src/extension.i18n.json diff --git a/i18n-sample/.gitignore b/i18n-sample/.gitignore index 5df8049b..46c692aa 100644 --- a/i18n-sample/.gitignore +++ b/i18n-sample/.gitignore @@ -1,2 +1,3 @@ out node_modules +package.nls.*.json diff --git a/i18n-sample/.vscode/tasks.json b/i18n-sample/.vscode/tasks.json index 1e37eb7b..b684a876 100644 --- a/i18n-sample/.vscode/tasks.json +++ b/i18n-sample/.vscode/tasks.json @@ -1,30 +1,27 @@ -// Available variables which can be used inside of strings. -// ${workspaceRoot}: the root folder of the team -// ${file}: the current opened file -// ${fileBasename}: the current opened file's basename -// ${fileDirname}: the current opened file's dirname -// ${fileExtname}: the current opened file's extension -// ${cwd}: the current working directory of the spawned process - -// A task runner that calls a custom npm script that compiles the extension. { - "version": "0.1.0", - - // we want to run npm - "command": "npm", - - // the command is a shell script - "isShellCommand": true, - - // show the output window only if unrecognized errors occur. - "showOutput": "silent", - - // we run the custom script "compile" as defined in package.json - "args": ["run", "compile", "--loglevel", "silent"], - - // The tsc compiler is started in watching mode - "isBackground": true, - - // use the standard tsc in watch mode problem matcher to find compile problems in the output. - "problemMatcher": "$tsc-watch" + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "watch", + "isBackground": true, + "problemMatcher": [ + "$tsc-watch" + ] + }, + { + "type": "gulp", + "task": "clean", + "problemMatcher": [] + }, + { + "type": "gulp", + "task": "build", + "problemMatcher": [ + "$tsc" + ] + } + ] } \ No newline at end of file diff --git a/i18n-sample/README.md b/i18n-sample/README.md index 15708180..c1f70d3b 100644 --- a/i18n-sample/README.md +++ b/i18n-sample/README.md @@ -9,31 +9,20 @@ it shows two commands: Hello and Bye in English and Japanese. **Assumptions** * All localization files are under the i18n folder. -* You could have created this folder by hand, or you could have used the - `vscode-nls-dev` tool to extract it. -* Under the i18n folder, you have sub-folders that represent the language you - want to localize. These names follow the ISO 639-3 convention. -* Under the language names folder you will create json files that mirror the - structure of the source code for your extension (e.g., out/src). The json - files are key:value pairs of the text that you want to localize. The naming - convention is `.i18n.json`. -* If you have a top-level package.nls.json file in your extension, you should - have one for each language following the naming convention of - `package.i18n.json`. +* You could have created this folder by hand, or you could have used the `vscode-nls-dev` tool to extract it. +* Under the i18n folder, you have sub-folders that represent the language you want to localize. These names follow the ISO 639-3 convention. +* Under the language names folder you will create json files that mirror the structure of the source code for your extension (e.g., out/src). The json files are key:value pairs of the text that you want to localize. The naming convention is `.i18n.json`. +* If you have a top-level package.nls.json file in your extension, you should have one for each language following the naming convention of `package.i18n.json`. # How to run locally -Localization values are only applied in the VSIX package. +Localization values are only applied when running the gulp `build` task. During normally development which uses `tsc -watch` to compile no localization post processing happends. This speeds up development time. -1. Ensure that you have `gulp-cli` installed globally using `npm install - --global gulp-cli`. +1. Ensure that you have `gulp-cli` installed globally using `npm install --global gulp-cli`. 1. Run `npm install` to bring in the dependencies. -1. Follow the steps at - https://code.visualstudio.com/docs/extensions/publish-extension to ensure - that you have installed vsce and have a publisher account. +1. Follow the steps at https://code.visualstudio.com/docs/extensions/publish-extension to ensure that you have installed vsce and have a publisher account. 1. Run `vsce package` to produce a .vsix file. -1. Install the .vsix file following the instructions at - https://code.visualstudio.com/docs/editor/extension-gallery#_install-from-a-vsix +1. Install the .vsix file following the instructions at https://code.visualstudio.com/docs/editor/extension-gallery#_install-from-a-vsix 1. Change your locale to Japanese by invoking "Configure Language" from the Command Palette. See the demo.gif file in this repository for a screencast. @@ -41,18 +30,14 @@ See the demo.gif file in this repository for a screencast. # What happens behind the scenes 1. The `vscode-nls-dev` module is used to rewrite the generated JavaScript. -1. Calls of the form `localize('some_key', 'Hello')` are transformed to - `localize(0, null)` where the first parameter (0, in this example) is the - position of the key in your messages file. -1. The contents of the i18n folder are transformed from key:value pairs into - positional arrays. +1. Calls of the form `localize('some_key', 'Hello')` are transformed to `localize(0, null)` where the first parameter (0, in this example) is the position of the key in your messages file. +1. The contents of the i18n folder are transformed from key:value pairs into positional arrays. # Considerations It is possible to use your own localization pipeline. -1. Localizations in your package.json can be done by wrapping the localized text - in the form %some.key%. +1. Localizations in your package.json can be done by wrapping the localized text in the form %some.key%. ``` // [Before] package.json @@ -85,11 +70,7 @@ It is possible to use your own localization pipeline. Then, create the corresponding package.nls.{your_language}.json files for each language to localize. -2. It is also possible to use your own library for localizing text in your - source file. You would use the value of `process.env.VSCODE_NLS_CONFIG` - environment variable. At runtime, this environment variable is a JSON string - that contains the locale that VS Code is run with. For instance, this is the - value for Japanese: `"{"locale":"ja","availableLanguages":{"*":"ja"}}"` +2. It is also possible to use your own library for localizing text in your source file. You would use the value of `process.env.VSCODE_NLS_CONFIG` environment variable. At runtime, this environment variable is a JSON string that contains the locale that VS Code is run with. For instance, this is the value for Japanese: `"{"locale":"ja","availableLanguages":{"*":"ja"}}"` ```JavaScript @@ -110,10 +91,8 @@ localize(config); ## 0.0.2 -Hook up the vscode-nls-dev functions to gulp so that you can just run `vsce -package` without manual transformations. +Hook up the vscode-nls-dev functions to gulp so that you can just run `vsce package` without manual transformations. ## 0.0.1: -Manually transform the calls to localize to illustrate explicitly what is going -on. \ No newline at end of file +Manually transform the calls to localize to illustrate explicitly what is going on. \ No newline at end of file diff --git a/i18n-sample/gulpfile.js b/i18n-sample/gulpfile.js index 3be91d14..a5589452 100644 --- a/i18n-sample/gulpfile.js +++ b/i18n-sample/gulpfile.js @@ -1,116 +1,93 @@ -// This is based off https://github.com/Microsoft/vscode/blob/master/build/gulpfile.extensions.js -// but simplified for the single extension use-case - -"use strict"; -const es = require('event-stream'); -const filter = require('gulp-filter'); -const fs = require('fs'); +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ const gulp = require('gulp'); -const glob = require('glob'); -const nlsDev = require('vscode-nls-dev'); const path = require('path'); -const rimraf = require('rimraf'); -const shell = require('shelljs'); -const tsb = require('gulp-tsb'); -const srcBase = path.join(__dirname, 'src'); -const src = path.join(srcBase, '**'); -const typeDefinitions = path.join(__dirname, 'node_modules/**/*.d.ts'); -const out = path.join('./', 'out'); -const i18n = path.join('./', 'i18n'); -const allErrors = []; -let startTimer = null; -let count = 0; +const ts = require('gulp-typescript'); +const typescript = require('typescript'); +const sourcemaps = require('gulp-sourcemaps'); +const del = require('del'); +const runSequence = require('run-sequence'); +const es = require('event-stream'); +const vsce = require('vsce'); +const nls = require('vscode-nls-dev'); -// TASK: Add your supported languages here -const languages = ['jpn']; +const tsProject = ts.createProject('./tsconfig.json', { typescript }); -function stripSourceMappingURL() { - const input = es.through(); +const inlineMap = true; +const inlineSource = false; +const outDest = 'out'; - const output = input.pipe( - es.mapSync(f => { - const contents = f.contents.toString('utf8'); - f.contents = new Buffer( - contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), - 'utf8' - ); - return f; - }) - ); +// If all VS Code langaues are support you can use nls.coreLanguages +const languages = ['jpn']; - return es.duplex(input, output); -} - -function createPipeline(build) { - const tsOptions = require(path.join(__dirname, 'tsconfig.json')) - .compilerOptions; - tsOptions.verbose = false; - tsOptions.sourceMap = true; - - tsOptions.inlineSources = !!build; - const compilation = tsb.create(tsOptions); - - return function() { - const input = es.through(); - const tsFilter = filter(['**/*.ts', '!**/vscode-nls-dev/lib/**'], { - restore: true - }); - - const output = input - .pipe(tsFilter) - .pipe(compilation()) - .pipe(build ? nlsDev.rewriteLocalizeCalls() : es.through()) - .pipe(build ? stripSourceMappingURL() : es.through()) - .pipe( - build - ? nlsDev.createAdditionalLanguageFiles(languages, i18n, out) - : es.through() - ); - - return es.duplex(input, output); - }; -} - -gulp.task('clean-extension', cb => rimraf(out, cb)); - -const iso639_3_to_2 = { - chs: 'zh-cn', - cht: 'zh-tw', - csy: 'cs-cz', - deu: 'de', - enu: 'en', - esn: 'es', - fra: 'fr', - hun: 'hu', - ita: 'it', - jpn: 'ja', - kor: 'ko', - nld: 'nl', - plk: 'pl', - ptb: 'pt-br', - ptg: 'pt', - rus: 'ru', - sve: 'sv-se', - trk: 'tr' -}; - -gulp.task('prepare-package-nls-json', () => { - languages.map(language => { - const packageJson = path.join(i18n, language, 'package.i18n.json'); - console.log(packageJson); - if (fs.existsSync(packageJson)) { - shell.cp(packageJson, `package.nls.${iso639_3_to_2[language]}.json`); - } - }); +gulp.task('default', function(callback) { + runSequence('build', callback); }); -gulp.task( - 'build-extension', - ['clean-extension', 'prepare-package-nls-json'], - () => { - const pipeline = createPipeline(true); - const input = gulp.src([src, typeDefinitions]); - return input.pipe(pipeline()).pipe(gulp.dest(out)); - } -); +gulp.task('compile', function(callback) { + runSequence('clean', 'internal-compile', callback); +}); + +gulp.task('build', function(callback) { + runSequence('clean', 'internal-nls-compile', 'add-i18n', callback); +}); + +gulp.task('publish', function(callback) { + runSequence('build', 'vsce:publish', callback); +}); + +gulp.task('package', function(callback) { + runSequence('build', 'vsce:package', callback); +}); + +gulp.task('clean', function() { + return del(['out/**', 'package.nls.*.json', 'i18n-sample*.vsix']); +}) + +//---- internal + +function compile(buildNls) { + var r = tsProject.src() + .pipe(sourcemaps.init()) + .pipe(tsProject()).js + .pipe(buildNls ? nls.rewriteLocalizeCalls() : es.through()) + .pipe(buildNls ? nls.createAdditionalLanguageFiles(languages, 'i18n', 'out') : es.through()); + + if (inlineMap && inlineSource) { + r = r.pipe(sourcemaps.write()); + } else { + r = r.pipe(sourcemaps.write("../out", { + // no inlined source + includeContent: inlineSource, + // Return relative source map root directories per file. + sourceRoot: "../src" + })); + } + + return r.pipe(gulp.dest(outDest)); +} + +gulp.task('internal-compile', function() { + return compile(false); +}); + +gulp.task('internal-nls-compile', function() { + return compile(true); +}); + +gulp.task('add-i18n', function() { + return gulp.src(['package.nls.json']) + .pipe(nls.createAdditionalLanguageFiles(languages, 'i18n')) + .pipe(gulp.dest('.')); +}); + +gulp.task('vsce:publish', function() { + return vsce.publish(); +}); + +gulp.task('vsce:package', function() { + return vsce.createVSIX(); +}); \ No newline at end of file diff --git a/i18n-sample/i18n/jpn/out/src/command/sayBye.i18n.json b/i18n-sample/i18n/jpn/out/src/command/sayBye.i18n.json deleted file mode 100644 index 2be1a505..00000000 --- a/i18n-sample/i18n/jpn/out/src/command/sayBye.i18n.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "sayBye.text": "さようなら" -} diff --git a/i18n-sample/i18n/jpn/out/src/extension.i18n.json b/i18n-sample/i18n/jpn/out/src/extension.i18n.json deleted file mode 100644 index d199813d..00000000 --- a/i18n-sample/i18n/jpn/out/src/extension.i18n.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "sayHello.text": "こんにちは" -} diff --git a/i18n-sample/package.json b/i18n-sample/package.json index 3117d3e6..4036ae38 100644 --- a/i18n-sample/package.json +++ b/i18n-sample/package.json @@ -1,51 +1,51 @@ { - "name": "i18n-sample", - "displayName": "i18n-sample", - "description": "Sample that shows how to localize an extension", - "version": "0.0.2", - "publisher": "vazexqi", - "engines": { - "vscode": "^1.13.0" - }, - "categories": [ - "Other" - ], - "activationEvents": [ - "onCommand:extension.sayHello", - "onCommand:extension.sayBye" - ], - "main": "./out/src/extension", - "contributes": { - "commands": [ - { - "command": "extension.sayHello", - "title": "%extension.sayHello.title%" - }, - { - "command": "extension.sayBye", - "title": "%extension.sayBye.title%" - } - ] - }, - "scripts": { - "vscode:prepublish": "gulp build-extension", - "compile": "tsc -watch -p ./", - "clean": "gulp clean-extension", - "postinstall": "node ./node_modules/vscode/bin/install" - }, - "devDependencies": { - "@types/node": "^6.0.40", - "event-stream": "^3.3.4", - "gulp": "^3.9.1", - "gulp-filter": "^5.0.0", - "gulp-tsb": "^2.0.3", - "rimraf": "^2.6.1", - "shelljs": "^0.7.8", - "typescript": "^2.4.1", - "vscode": "^1.1.2", - "vscode-nls-dev": "^2.1.3" - }, - "dependencies": { - "vscode-nls": "^2.0.2" - } -} + "name": "i18n-sample", + "displayName": "i18n-sample", + "description": "Sample that shows how to localize an extension", + "version": "0.1.0", + "publisher": "vazexqi", + "engines": { + "vscode": "^1.13.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "onCommand:extension.sayHello", + "onCommand:extension.sayBye" + ], + "main": "./out/extension", + "contributes": { + "commands": [ + { + "command": "extension.sayHello", + "title": "%extension.sayHello.title%" + }, + { + "command": "extension.sayBye", + "title": "%extension.sayBye.title%" + } + ] + }, + "scripts": { + "watch": "tsc -watch -p ./", + "clean": "gulp clean", + "postinstall": "node ./node_modules/vscode/bin/install" + }, + "devDependencies": { + "@types/node": "^6.0.40", + "del": "^3.0.0", + "event-stream": "^3.3.4", + "gulp": "^3.9.1", + "gulp-filter": "^5.0.1", + "run-sequence": "^2.2.0", + "typescript": "2.5.3", + "gulp-typescript": "3.2.2", + "vsce": "^1.32.0", + "vscode": "^1.1.2", + "vscode-nls-dev": "^2.1.3" + }, + "dependencies": { + "vscode-nls": "^2.0.2" + } +} \ No newline at end of file diff --git a/i18n-sample/package.nls.json b/i18n-sample/package.nls.json index a4f15be4..3007d462 100644 --- a/i18n-sample/package.nls.json +++ b/i18n-sample/package.nls.json @@ -1,4 +1,4 @@ { - "extension.sayHello.title": "Hello", - "extension.sayBye.title": "Bye" -} + "extension.sayHello.title": "Hello", + "extension.sayBye.title": "Bye" +} \ No newline at end of file diff --git a/i18n-sample/src/command/sayBye.ts b/i18n-sample/src/command/sayBye.ts index a84fa254..5c9a636f 100644 --- a/i18n-sample/src/command/sayBye.ts +++ b/i18n-sample/src/command/sayBye.ts @@ -1,9 +1,14 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); export function sayByeCommand() { - const message = localize('sayBye.text', 'Bye') - vscode.window.showInformationMessage(message); -} + const message = localize('sayBye.text', 'Bye') + vscode.window.showInformationMessage(message); +} \ No newline at end of file diff --git a/i18n-sample/src/extension.ts b/i18n-sample/src/extension.ts index 76908422..8e96f1de 100644 --- a/i18n-sample/src/extension.ts +++ b/i18n-sample/src/extension.ts @@ -1,3 +1,8 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + import * as nls from 'vscode-nls'; const localize = nls.config(process.env.VSCODE_NLS_CONFIG)(); @@ -5,17 +10,18 @@ import * as vscode from 'vscode'; import { sayByeCommand } from './command/sayBye'; export function activate(context: vscode.ExtensionContext) { - const helloCmd = vscode.commands.registerCommand('extension.sayHello', () => { - const message = localize('sayHello.text', 'Hello') - vscode.window.showInformationMessage(message); - }); + const helloCmd = vscode.commands.registerCommand('extension.sayHello', () => { + const message = localize('sayHello.text', 'Hello') + vscode.window.showInformationMessage(message); + }); - const byeCmd = vscode.commands.registerCommand( - 'extension.sayBye', - sayByeCommand - ); + const byeCmd = vscode.commands.registerCommand( + 'extension.sayBye', + sayByeCommand + ); - context.subscriptions.push(helloCmd, byeCmd); + context.subscriptions.push(helloCmd, byeCmd); } -export function deactivate() {} +export function deactivate() { +} \ No newline at end of file diff --git a/i18n-sample/tsconfig.json b/i18n-sample/tsconfig.json index 11282c9a..afe5896a 100644 --- a/i18n-sample/tsconfig.json +++ b/i18n-sample/tsconfig.json @@ -1,16 +1,16 @@ { - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": [ - "es6" - ], - "sourceMap": true, - "rootDir": "." - }, - "exclude": [ - "node_modules", - ".vscode-test" - ] + "compileOnSave": false, + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "out", + "lib": [ + "es6" + ], + "sourceMap": true, + "rootDir": "src" + }, + "exclude": [ + "node_modules" + ] } \ No newline at end of file