How VS Code Implements Multi‑Language Support: Deep Dive into NLS and Module Loading
This article explains how VS Code’s complex Electron‑Node architecture handles internationalization by using a custom NLS system, language‑pack plugins, compile‑time AST analysis, and a specialized AMD loader to map source‑code calls to localized strings at runtime.
NLS Overview
VS Code’s main process starts in src/main.js. At line 63 it checks for a locale and creates a nlsConfigurationPromise using lp.getNLSConfiguration, which later sets the VSCODE_NLS_CONFIG environment variable when the Electron onReady event fires.
What is NLS?
NLS stands for Native Language Support . The promise returned by lp.getNLSConfiguration receives four arguments: product.commit – the commit hash of the current VS Code build. userDataPath – the directory where VS Code stores user data (different per OS). metaDataFile – the generated nls.metadata.json file. locale – the language selected by the user.
product.commit
The product.json file adds a commit field during the build. Language packs are released together with each VS Code version, so the commit hash links a specific language‑pack plugin (e.g., vscode‑loc) to the matching VS Code release.
userDataPath
Typical locations:
# MacOS
~/Library/Application Support/Code
# Linux
~/.config
# Windows
%USERPROFILE%/AppData/RoamingmetaDataFile
The file nls.metadata.json is generated only after a full VS Code build. It contains three objects:
{
"keys": { "vs/code/electron-browser/processExplorer/processExplorerMain": ["cpu","memory",...] },
"messages": { "vs/code/electron-browser/processExplorer/processExplorerMain": ["CPU %","Memory (MB)",...] },
"bundles": { "vs/code/electron-browser/processExplorer/processExplorerMain": ["vs/code/electron-browser/processExplorer/processExplorerMain"] }
}The keys map source‑file identifiers to the keys used in nls.localize, while messages hold the default strings. The bundles list entry modules for the build process.
vs/nls Module
The module vs/nls is implemented as a plugin for the VS Code loader. It exports a localize function that formats a message with optional arguments. During compilation, calls like nls.localize('key', 'Default Message') are transformed to nls.localize(index, args), where the index reflects the call order within the file.
this.localize = (data, message, ...args) => localize(this._env, data, message, ...args);
function localize(env, data, message, ...args) {
if (args.length === 0) {
return message;
}
return message.replace(/\{(\d+)\}/g, (match, index) => {
const arg = args[index];
if (typeof arg === 'string') return arg;
if (typeof arg === 'number' || typeof arg === 'boolean' || arg == null) return String(arg);
return match;
});
}After compilation, the generated AMD module includes a special dependency syntax vs/nls!<em>modulePath</em>. The loader parses the part after the exclamation mark as a PluginDependency, loads the NLS plugin, and injects the appropriate language bundle.
define(__m[34], __M([1, 36]), function (require, exports, electron_1, strings_1, os_1, product_1, nls_1, ...) {
// module body
});The loader’s _loadPluginDependency method registers the plugin and calls its load function, which ultimately defines a module containing the localized strings.
Extensions and vscode‑nls
Extension processes do not use vs/nls. Instead they rely on the vscode-nls package. Before any extension code runs, initializeSettings reads VSCODE_NLS_CONFIG. Extensions call nls.loadMessageBundle(__filename) (the filename is injected at compile time) and then use nls.localize(index, args) to retrieve strings from the generated nls.metadata.json for that extension.
The entire i18n system hinges on compile‑time AST analysis, custom AMD loader plugins, and runtime environment variables to map source‑code calls to the correct localized text.
Understanding this workflow helps developers navigate VS Code’s source code and adapt similar i18n strategies for their own Electron‑based applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Taobao Frontend Technology
The frontend landscape is constantly evolving, with rapid innovations across familiar languages. Like us, your understanding of the frontend is continually refreshed. Join us on Taobao, a vibrant, all‑encompassing platform, to uncover limitless potential.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
