Skip to content

Commit b6b656b

Browse files
Add localization (#18954)
* Enable localization using nls * Add i18n files * Add current translations * Add export and import scripts * Fix import translation function * Clean code * Update package-lock.json * Delete i18n files * Update package-lock.json * Add news * Fix package files * Addd sourcemaps * Add missing translations * Remove localize test * Add paths in pre-release
1 parent c2fad5f commit b6b656b

File tree

106 files changed

+2228
-970
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+2228
-970
lines changed

build/azure-pipeline.pre-release.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,28 @@ resources:
2121
extends:
2222
template: azure-pipelines/extension/pre-release.yml@templates
2323
parameters:
24+
locPushSteps:
25+
- script: echo '$(SetTranslationsPath.EnglishStrings)'
26+
- displayName: Install NPM dependencies
27+
script: 'cd $(EXTENSION_DIR) && npm ci'
28+
- script: npm run translations-export
29+
displayName: Run translations-export
30+
- publish: $(VSCODE_TRANSLATIONS_EXPORT_DIR)
31+
artifact: translations-export
32+
displayName: Publish translations-export
33+
- pwsh: |
34+
$Destination = "$(SetTranslationsPath.EnglishStrings)"
35+
New-Item -ItemType Directory -Force "$(SetTranslationsPath.EnglishStrings)"
36+
Move-Item "$(Pipeline.Workspace)/ms-python.python" $Destination
37+
displayName: Move vscode-python-translations-export to translations path
38+
39+
locPullSteps:
40+
- script: echo '$(SetTranslationsPath.TranslatedStrings)'
41+
- script: 'gulp translations-import --option "${SetTranslationsPath.TranslatedStrings}"'
42+
- pwsh: ls
43+
displayName: test if there is stuff
44+
workingDirectory: '$(SetTranslationsPath.TranslatedStrings)'
45+
2446
buildSteps:
2547
- task: NodeTool@0
2648
inputs:

build/loc/ExportTranslations.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Starter pipeline
2+
# Start with a minimal pipeline that you can customize to build and deploy your code.
3+
# Add steps that build, run tests, deploy, and more:
4+
# https://aka.ms/yaml
5+
6+
pr: none
7+
trigger:
8+
branches:
9+
include:
10+
- main
11+
schedules:
12+
- cron: "0 0 * * *"
13+
displayName: Daily midnight build
14+
branches:
15+
include:
16+
- main
17+
18+
stages:
19+
- stage: Localization
20+
pool:
21+
vmImage: windows-latest
22+
variables:
23+
skipComponentGovernanceDetection: true
24+
VSCODE_EXTENSIONS_LOC_DIR: $(Pipeline.Workspace)/vscode-extensions-loc
25+
EXTENSION_DIR: $(Build.SourcesDirectory)
26+
VSCODE_TRANSLATIONS_EXPORT_DIR: $(Pipeline.Workspace)/ms-python.python
27+
jobs:
28+
- job: Localization
29+
timeoutInMinutes: 180
30+
steps:
31+
32+
# Clone extension Repository and run translations-export to get xlf file
33+
- script: git clone https://github.com/microsoft/vscode-extensions-loc/ ${VSCODE_EXTENSIONS_LOC_DIR}
34+
displayName: Clone Microsoft/vscode-extensions-loc
35+
36+
37+
- task: NodeTool@0
38+
inputs:
39+
versionSpec: '14.18.2'
40+
displayName: Select Node version
41+
- task: UsePythonVersion@0
42+
inputs:
43+
versionSpec: '3.7'
44+
addToPath: true
45+
architecture: 'x64'
46+
displayName: Select Python version
47+
- displayName: Install NPM dependencies
48+
script: 'cd $(EXTENSION_DIR) && npm ci'
49+
- script: npm run translations-export
50+
displayName: Run translations-export
51+
- publish: $(VSCODE_TRANSLATIONS_EXPORT_DIR)
52+
artifact: translations-export
53+
displayName: Publish translations-export
54+
55+
- pwsh: |
56+
$Destination = "$(VSCODE_EXTENSIONS_LOC_DIR)/src/en"
57+
New-Item -ItemType Directory -Force "$(VSCODE_EXTENSIONS_LOC_DIR)/src/en"
58+
Move-Item "$(VSCODE_TRANSLATIONS_EXPORT_DIR)" $Destination
59+
displayName: Move vscode-python-translations-export to expected path
60+
61+
- name: Create Pull Request on vscode-extensions-loc
62+
id: cpr
63+
uses: peter-evans/create-pull-request@v3
64+
with:
65+
token: ${{ secrets.REPO_PAT }}
66+
path: ${{ github.workspace }}/vscode-extensions-loc
67+
title: Update Localization xlf files
68+
body: Automated changes based on Microsoft/vscode-python@${{ github.sha }}
69+
branch: update-localization-files-microsoft-vscode-python-${{ github.sha }}
70+
commit-message: update localization xlf files Microsoft/vscode-python@${{ github.sha }}
71+
assignees: PaulaCamargo25
72+
delete-branch: true

build/loc/ImportTranslations.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# ==================================================================================
2+
# Pipeline for VsCodeExtension-Localization build definition
3+
# Runs OneLocBuild task to localize xlf file
4+
# ==================================================================================
5+
6+
resources:
7+
repositories:
8+
- repository: self
9+
clean: true
10+
11+
trigger: none
12+
pr: none
13+
schedules:
14+
- cron: "0 7 * * *"
15+
displayName: Daily 7 AM
16+
branches:
17+
include:
18+
- main
19+
always: true
20+
21+
pool:
22+
name: 'AzurePipelines-EO'
23+
demands:
24+
- ImageOverride -equals AzurePipelinesWindows2022compliant
25+
variables:
26+
VSCODE_EXTENSIONS_LOC_DIR: $(Pipeline.Workspace)/vscode-extensions-loc
27+
EXTENSION_DIR: $(Build.SourcesDirectory)
28+
29+
steps:
30+
# Clone extension Repository and run translations-export to get xlf file
31+
- script: git clone https://github.com/microsoft/vscode-extensions-loc/ ${VSCODE_EXTENSIONS_LOC_DIR}
32+
displayName: Clone Microsoft/vscode-extensions-loc
33+
- task: CmdLine@2
34+
inputs:
35+
script: 'node ./translations_auto_pr.js microsoft vscode-python csigs csigs [email protected] "${Build.VSCODE_EXTENSIONS_LOC_DIR}/loc"'
36+
37+
- task: PublishBuildArtifacts@1
38+
inputs:
39+
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
40+
ArtifactName: 'drop'
41+
publishLocation: 'Container'

gulpfile.js

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,19 @@ const flat = require('flat');
2121
const { argv } = require('yargs');
2222
const os = require('os');
2323
const rmrf = require('rimraf');
24+
const nls = require('vscode-nls-dev');
25+
const sourcemaps = require('gulp-sourcemaps');
26+
const typescript = require('typescript');
27+
const es = require('event-stream');
28+
const minimist = require('minimist');
29+
30+
const tsProject = ts.createProject('./tsconfig.json', { typescript });
31+
const filter = require('gulp-filter');
2432

2533
const isCI = process.env.TRAVIS === 'true' || process.env.TF_BUILD !== undefined;
2634

2735
gulp.task('compile', (done) => {
2836
let failed = false;
29-
const tsProject = ts.createProject('tsconfig.json');
3037
tsProject
3138
.src()
3239
.pipe(tsProject())
@@ -353,3 +360,120 @@ function hasNativeDependencies() {
353360
}
354361
return false;
355362
}
363+
364+
const translationProjectName = 'ms-python.python';
365+
const translationExtensionName = 'vscode-python';
366+
367+
const defaultLanguages = [
368+
{ id: 'de', folderName: 'de' },
369+
{ id: 'fr', folderName: 'fr' },
370+
{ id: 'es', folderName: 'es' },
371+
{ id: 'cs', folderName: 'cs' },
372+
{ id: 'it', folderName: 'it' },
373+
{ id: 'ja', folderName: 'ja' },
374+
{ id: 'ko', folderName: 'ko' },
375+
{ id: 'pl', folderName: 'pl' },
376+
{ id: 'pt-BR', folderName: 'pt-BR' },
377+
{ id: 'ru', folderName: 'ru' },
378+
{ id: 'tr', folderName: 'tr' },
379+
{ id: 'zh-Hans', folderName: 'zh-Hans' },
380+
{ id: 'zh-Hant', folderName: 'zh-Hant' },
381+
{ id: 'qps-ploc', folderName: 'qps-ploc' },
382+
];
383+
// ****************************
384+
// Command: translations-generate
385+
// The following is used to import an i18n directory structure and generate files used at runtime.
386+
// ****************************
387+
388+
// Generate package.nls.*.json files from: ./i18n/*/package.i18n.json
389+
// Outputs to root path, as these nls files need to be along side package.json
390+
391+
const generateAdditionalLocFiles = () =>
392+
gulp
393+
.src(['package.nls.json'])
394+
.pipe(nls.createAdditionalLanguageFiles(defaultLanguages, 'i18n', 'out'))
395+
.pipe(gulp.dest('out'));
396+
397+
// Generates ./dist/nls.bundle.<language_id>.json from files in ./i18n/** *//<src_path>/<filename>.i18n.json
398+
// Localized strings are read from these files at runtime.
399+
const generateSrcLocBundle = () =>
400+
// Transpile the TS to JS, and let vscode-nls-dev scan the files for calls to localize.
401+
tsProject
402+
.src()
403+
.pipe(sourcemaps.init())
404+
.pipe(tsProject())
405+
.js.pipe(nls.createMetaDataFiles())
406+
.pipe(nls.createAdditionalLanguageFiles(defaultLanguages, 'i18n', 'out'))
407+
.pipe(nls.bundleMetaDataFiles('ms-vscode.python', 'out'))
408+
.pipe(nls.bundleLanguageFiles())
409+
.pipe(filter(['**/nls.bundle.*.json', '**/nls.metadata.header.json', '**/nls.metadata.json']))
410+
.pipe(gulp.dest('out'));
411+
412+
gulp.task('translations-generate', generateSrcLocBundle, generateAdditionalLocFiles);
413+
414+
// ****************************
415+
// Command: translations-export
416+
// The following is used to export and XLF file containing english strings for translations.
417+
// The result will be written to: ../vscode-extensions-localization-export/ms-vscode/
418+
// ****************************
419+
const exportTranslations = (done) => {
420+
const jsStream = tsProject.src().pipe(sourcemaps.init()).pipe(tsProject()).js.pipe(nls.createMetaDataFiles());
421+
422+
// Merge files from all source streams
423+
jsStream
424+
425+
// Filter down to only the files we need
426+
.pipe(filter(['**/*.nls.json', '**/*.nls.metadata.json']))
427+
428+
// Consoldate them into nls.metadata.json, which the xlf is built from.
429+
.pipe(nls.bundleMetaDataFiles('ms-vscode.python', '.'))
430+
431+
// filter down to just the resulting metadata files
432+
.pipe(filter(['**/nls.metadata.header.json', '**/nls.metadata.json']))
433+
434+
// Add package.nls.json, used to localized package.json
435+
.pipe(gulp.src(['package.nls.json']))
436+
437+
// package.nls.json and nls.metadata.json are used to generate the xlf file
438+
// Does not re-queue any files to the stream. Outputs only the XLF file
439+
.pipe(nls.createXlfFiles(translationProjectName, translationExtensionName))
440+
.pipe(gulp.dest('../'))
441+
.pipe(
442+
es.wait(() => {
443+
done();
444+
}),
445+
);
446+
};
447+
448+
gulp.task('translations-export', exportTranslations);
449+
450+
// ****************************
451+
// Command: translations-import
452+
// The following is used to import an XLF file containing all language strings.
453+
// This results in a i18n directory, which should be checked in.
454+
// ****************************
455+
456+
// Imports translations from raw localized MLCP strings to VS Code .i18n.json files
457+
gulp.task('translations-import', (done) => {
458+
const options = minimist(process.argv.slice(2), {
459+
string: 'location',
460+
default: {
461+
location: '../vscode-translations-import',
462+
},
463+
});
464+
es.merge(
465+
defaultLanguages.map((language) => {
466+
const id = language.transifexId || language.id;
467+
return gulp
468+
.src(path.join(options.location, id, `${translationExtensionName}.xlf`))
469+
.pipe(nls.prepareJsonFiles())
470+
.pipe(gulp.dest(path.join('./i18n', language.folderName)));
471+
}),
472+
).pipe(
473+
es.wait(() => {
474+
done();
475+
}),
476+
);
477+
});
478+
479+
gulp.task('create-i18n', gulp.series(generateSrcLocBundle, exportTranslations));

news/1 Enhancements/18286.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enable localization using vscode-nlsß

0 commit comments

Comments
 (0)