Migrate localization from vscode-nls to vscode.l10n#14550
Draft
sean-mcmanus wants to merge 5 commits into
Draft
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request migrates the extension’s localization pipeline from vscode-nls / vscode-nls-dev to VS Code’s built-in vscode.l10n runtime API plus @vscode/l10n-dev for extraction/build, to remove synchronous bundle loading from the activation path.
Changes:
- Replaced
localize(...)usage and per-filevscode-nlssetup withvscode.l10n.t(...)across the extension. - Switched localization build/export/import tooling from
vscode-nls-devto@vscode/l10n-dev, and updated webpack/package configuration accordingly. - Updated contributor documentation and prep checks to reflect the new
l10n/bundle flow.
Reviewed changes
Copilot reviewed 21 out of 60 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| Extension/yarn.lock | Adds @vscode/l10n-dev and its dependency graph; removes vscode-nls(-dev) entries. |
| Extension/webpack.config.js | Removes vscode-nls-dev webpack loader and env-gated rewriting. |
| Extension/src/SSH/TargetsView/targetNodes.ts | Migrates SSH targets view strings to vscode.l10n.t. |
| Extension/src/SSH/TargetsView/sshTargetsProvider.ts | Migrates SSH targets provider UI/errors to vscode.l10n.t. |
| Extension/src/SSH/sshHosts.ts | Migrates SSH host/config logging strings to vscode.l10n.t. |
| Extension/src/SSH/sshCommandRunner.ts | Migrates SSH command runner prompts/logging strings to vscode.l10n.t. |
| Extension/src/SSH/commands.ts | Migrates SSH validation errors to vscode.l10n.t. |
| Extension/src/SSH/commandInteractors.ts | Migrates SSH interactor error messages to vscode.l10n.t. |
| Extension/src/platform.ts | Migrates platform detection errors to vscode.l10n.t. |
| Extension/src/main.ts | Migrates activation-time UI/log strings to vscode.l10n.t. |
| Extension/src/logger.ts | Migrates output channel titles and crash guidance text to vscode.l10n.t. |
| Extension/src/LanguageServer/ui.ts | Migrates status bar/language status strings to vscode.l10n.t. |
| Extension/src/LanguageServer/settingsPanel.ts | Migrates settings panel title to vscode.l10n.t. |
| Extension/src/LanguageServer/settings.ts | Migrates user-facing settings notices to vscode.l10n.t. |
| Extension/src/LanguageServer/referencesTreeDataProvider.ts | Migrates “Go to reference” command title to vscode.l10n.t. |
| Extension/src/LanguageServer/references.ts | Migrates references UI/progress/channel strings to vscode.l10n.t. |
| Extension/src/LanguageServer/Providers/renameProvider.ts | Migrates rename validation/error messages to vscode.l10n.t. |
| Extension/src/LanguageServer/Providers/CopilotHoverProvider.ts | Migrates Copilot hover link/disclaimer strings to vscode.l10n.t. |
| Extension/src/LanguageServer/Providers/codeActionProvider.ts | Migrates inline macro strings/disabled reasons to vscode.l10n.t. |
| Extension/src/LanguageServer/localization.ts | Migrates symbol-scope formatting localization to vscode.l10n.t. |
| Extension/src/LanguageServer/lmTool.ts | Migrates LM tool error logging strings to vscode.l10n.t. |
| Extension/src/LanguageServer/languageConfig.ts | Migrates duplicate-pattern warning to vscode.l10n.t. |
| Extension/src/LanguageServer/extension.ts | Migrates command/UI strings and warnings to vscode.l10n.t. |
| Extension/src/LanguageServer/devcmd.ts | Migrates dev environment command prompts/errors to vscode.l10n.t. |
| Extension/src/LanguageServer/cppBuildTaskProvider.ts | Migrates build task strings to vscode.l10n.t. |
| Extension/src/LanguageServer/copilotProviders.ts | Migrates related-files provider error logging to vscode.l10n.t. |
| Extension/src/LanguageServer/configurations.ts | Migrates configuration diagnostics/messages to vscode.l10n.t. |
| Extension/src/LanguageServer/codeAnalysis.ts | Migrates code analysis code action titles to vscode.l10n.t. |
| Extension/src/LanguageServer/client.ts | Migrates client UI prompts/errors/progress strings to vscode.l10n.t. |
| Extension/src/expand.ts | Migrates expansion warnings/errors to vscode.l10n.t. |
| Extension/src/Debugger/runWithoutDebuggingAdapter.ts | Migrates “no terminal emulator” error to vscode.l10n.t. |
| Extension/src/Debugger/ParsedEnvironmentFile.ts | Migrates envfile parse warning to vscode.l10n.t. |
| Extension/src/Debugger/nativeAttach.ts | Migrates native attach errors/timeouts to vscode.l10n.t. |
| Extension/src/Debugger/extension.ts | Migrates debugger command strings/prompts to vscode.l10n.t. |
| Extension/src/Debugger/debugAdapterDescriptorFactory.ts | Migrates debugger support warnings to vscode.l10n.t. |
| Extension/src/Debugger/configurations.ts | Migrates snippet/template strings to vscode.l10n.t. |
| Extension/src/Debugger/configurationProvider.ts | Migrates debug config picker/errors/deploy-step messages to vscode.l10n.t. |
| Extension/src/Debugger/attachToProcess.ts | Migrates remote attach picker errors to vscode.l10n.t. |
| Extension/src/Debugger/attachQuickPick.ts | Migrates attach quick pick UI strings to vscode.l10n.t. |
| Extension/src/cppTools.ts | Migrates provider registration logging to vscode.l10n.t. |
| Extension/src/common.ts | Migrates common prompts/log messages to vscode.l10n.t. |
| Extension/package.json | Adds l10n bundle location; removes vscode-nls(-dev); updates webpack script. |
| Extension/gulpfile.js | Rewrites translation export/import and bundle generation to @vscode/l10n-dev. |
| Extension/.scripts/generateNativeStrings.ts | Updates generator output to use vscode.l10n.t. |
| Extension/.scripts/common.ts | Updates prep check to validate l10n/bundle.l10n.json exists. |
| Extension/.gitignore | Ignores generated l10n/bundle.l10n*.json artifacts. |
| CONTRIBUTING.md | Updates contributor guidance for vscode.l10n and @vscode/l10n-dev. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
bobbrow
reviewed
Jun 26, 2026
This comment was marked as resolved.
This comment was marked as resolved.
Contributor
Author
|
I didn't want to check this in until after we get our pending 1.33.x updated loc strings, in case there are any issues...maybe 1.33.4. |
…ze CRLF blobs to LF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix by Copilot with Claude Opus 4.8 in VS Code (with review fixes from GPT-5.5).
Fixes #13145 and #14549 .
Why
Profiling an unresponsive extension-host session showed a single synchronous call —
loadNlsBundle(vscode-nls reading the standalone NLS bundle from disk during modulerequire) — blocking the extension host for ~897 ms at activation, about 90% of the captured CPU profile. VS Code's built-invscode.l10nAPI loads the localization bundle itself (declared via thel10nfield in package.json), so strings are no longer read synchronously on the activation path.What changed
localize(...)call sites across 38 source files withl10n.t(...)(viaconst l10n = vscode.l10n;, or a namedl10nimport in files that already import named symbols fromvscode), dropping the explicit string keys (the English message is now the key). The{ key, comment }form becomes{ message, args, comment }.nls.config(...)+loadMessageBundle()); ensuredimport * as vscode from 'vscode'.generateNativeStrings.ts) to emitl10n.t, and regeneratednativeStrings.ts/localized_string_ids.h."l10n": "./l10n", swappedvscode-nls-dev→@vscode/l10n-dev, removed the runtimevscode-nlsdependency.vscode-nls-devwebpack loader (VS Code loads bundles at runtime now).translations-export/-import/-generateonto@vscode/l10n-dev(English bundle →l10n/bundle.l10n.json, per-language →l10n/bundle.l10n.<lang>.json), preserving the custom HTML / JSON-schema / walkthrough / package.nls flows.i18n/*/src/**.i18n.jsonintoi18n/<lang>/bundle.l10n.json(743 strings each), keyed by the English message — or bymessage/commentfor the 81 strings that carry a translator comment, matching how@vscode/l10n-devkeys the bundle so those strings resolve in every locale..gitignorenow ignores the generatedl10n/bundle.l10n*.json.Verification
tsc --noEmitclean;eslint src .scriptsclean;node --checkon gulpfile + webpack.String(...)coercion becausel10n.ttypes args asstring | number | boolean(stricter than nls'sany); this preserves nls's formatting behavior.Localization call sites must be a literal
l10n.t/vscode.l10n.t@vscode/l10n-devextracts strings at build time by statically scanning source forl10n.t(...)/vscode.l10n.t(...)calls — it does not execute code or follow aliases. An alias likeconst localize = vscode.l10n.tcompiles and works at runtime, but the extractor never seeslocalize(...), so those strings are silently dropped frombundle.l10n.jsonand render in English in every locale. That is why each file callsl10n.tdirectly viaconst l10n = vscode.l10n;rather than a custom-named alias.Notes
i18n/*/src/**.i18n.jsonfiles are superseded for source strings and are safe to delete once a loc cycle validates the new bundles.Migration approach
located every
localize(...)call and spliced in the equivalent l10n call, preservingsurrounding formatting, argument expressions, and message/escape sequences:
localize('key', 'Message {0}', a)→l10n.t('Message {0}', a)localize({ key, comment: [...] }, 'Message {0}', a)→l10n.t({ message: 'Message {0}', args: [a], comment: [...] }){0}-style, so message text is unchanged across the migration.Call-site form (l10n.t)
Every call is a literal
l10n.t(...):vscodemergel10ninto that named import(e.g.
targetNodes.ts,cppBuildTaskProvider.ts).import * as vscode from 'vscode'and addconst l10n = vscode.l10n;.@vscode/l10n-devextracts strings by a static AST scan ofl10n.t(...)/vscode.l10n.t(...)calls; it does not follow aliases, so a custom-named alias (
const localize = vscode.l10n.t)would compile and run but silently drop those strings from the bundle — hence the literal
l10n.t.Translation recovery
The existing translations were keyed by the old vscode-nls string IDs and would otherwise be
orphaned (the new model keys by the English string). A one-time remap joined the pre-migration
key → Englishmap (from git HEAD, plusnativeStrings.jsonfor the generated file) with thelegacy
key → translationfiles, producing English-keyedi18n/<lang>/bundle.l10n.json:debugger.noDebug.*.not.supported) were dropped — verified absent from source,so never looked up at runtime.
@vscode/l10n-dev's scheme: plain stringsstay keyed by the English message, while the 81 strings that carry a translator comment are
keyed
message/comment. The initial remap had keyed everything by message only, which wouldhave made commented strings fall back to English in every locale; all 13 bundles were rebuilt so
every key matches the generated English bundle.
At build time
generateSrcLocBundlecopiesi18n/<folder>/bundle.l10n.jsontol10n/bundle.l10n.<lang>.json(e.g.chs→zh-cn).Type-coercion fixes
vscode.l10n.ttypes args asstring | number | boolean, stricter than vscode-nls'sany.Two args were
undefined-typed under the new signature and one file had a pre-existing duplicatevscodeimport surfaced by the change:common.ts:String(exitCode)LanguageServer/configurations.ts:String(dotConfigPath)Debugger/debugAdapterDescriptorFactory.ts: removed a duplicateimport * as vscodeString(...)reproduces vscode-nls's internal formatting exactly.Other fixes surfaced in review
ProduceVersion→ProductVersion(the literalSystemVersion.plistfield name) inplatform.tsand in both the key and value of all 13recovered bundles.
.scripts/common.tsprepwarnings.
Follow-ups / validation
yarn prep(invokestranslations-generate) and confirml10n/bundle.l10n.*.jsonareproduced; verify a non-English VS Code display language shows the recovered strings.
translations-export/-import) now targets@vscode/l10n-dev; validateit against the MLCP loc pipeline on the next cycle.
i18n/*/src/**.i18n.jsonfiles can be deleted.