Fundamentals 16 min read

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.

Taobao Frontend Technology
Taobao Frontend Technology
Taobao Frontend Technology
How VS Code Implements Multi‑Language Support: Deep Dive into NLS and Module Loading

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:

<code># MacOS
~/Library/Application Support/Code

# Linux
~/.config

# Windows
%USERPROFILE%/AppData/Roaming</code>

metaDataFile

The file

nls.metadata.json

is generated only after a full VS Code build. It contains three objects:

<code>{
  "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"] }
}</code>

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.

<code>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;
  });
}
</code>

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.

<code>define(__m[34], __M([1, 36]), function (require, exports, electron_1, strings_1, os_1, product_1, nls_1, ...) {
  // module body
});</code>

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.

ElectronVSCodei18nmodule-loaderlanguage-packnls
Taobao Frontend Technology
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.