Internationalization
Theia can be localized by installing Visual Studio Code language packs. Using the Configure Display Language command, users of Theia can change their currently used locale.
The framework provides additional features to enable extension developers to localize their own extensions.
Localizing Your Extension
Let's say you have a simple string you want to present in the frontend of your application, like a custom widget that displays a goodbye message:
render() {
return <span>Bye</span>
}To display this message using different locales, you can use the nls.localize function, imported from the @theia/core package:
render() {
return <span>{nls.localize('bye', 'Bye')}</span>
}The first argument is a key to identify the translated value. The second argument is the default value that will be used if the user didn't change their locale. When using template expressions in the frontend, keep in mind that the nls.localize function allows you to format strings using the additional args parameter. When the localize function identifies placeholders in the format {n} where n represents any number, it will try to replace the placeholder with the input parameter at the appropriate position, e.g. {0} will be replaced by the first additional parameter, {1} by the second and so forth:
nls.localize('bye-format', 'Bye {0} and {1}!', first, second);The Command namespace provides an additional utility function to help you localize your extension. The toLocalizedCommand function accepts a Command and localization keys as its arguments. The first additional key will be used to localize the label and the second for the category. If none are provided, the id of the command will be used as the label localization key:
command = Command.toLocalizedCommand({
id: 'hello-command',
label: 'Hello'
category: 'Greetings'
}, 'hello', 'greetings');After replacing the all user-facing strings with nls.localize calls, you can use the theia nls-extract command of the @theia/cli package to extract all used localization keys into a single JSON file. For the two examples above, it will result in the following JSON output:
{
"bye": "Bye",
"hello": "Hello",
"greetings": "Greetings"
}You can also group these keys by using forward-slashes. For example, a call like nls.localize('group/bye', 'Bye') will be transformed into this JSON file:
{
"group": {
"bye": "Bye"
}
}These files will have to be translated into your target languages. Afterwards, you can continue with registering these new localizations for your strings using a custom LocalizationContribution:
// creating your own localization contribution for German, Italian and simplified Chinese
export class CustomLocalizationContribution implements LocalizationContribution {
async registerLocalizations(registry: LocalizationRegistry): Promise<void> {
// Theia uses language codes, e.g. "de" for German
registry.registerLocalizationFromRequire('de', require('../data/i18n/nls.de.json'));
registry.registerLocalizationFromRequire('it', require('../data/i18n/nls.it.json'));
registry.registerLocalizationFromRequire('zh-cn', require('../data/i18n/nls.zh-cn.json'));
}
}Lastly, this LocalizationContribution will have to be bound within your backend injection module:
bind(CustomLocalizationContribution).toSelf().inSingletonScope();
bind(LocalizationContribution).toService(CustomLocalizationContribution);Be aware that the Configure Display Language command only shows a locale once its language pack has been installed. This assures that no parts of the Theia base framework remain untranslated after a user changes the display language.
Changing the Default Locale
If you want to deploy your Theia app to a specific region, you may want to change the default locale.
To do this you simply add a defaultLocale entry to the frontend configuration of your Theia app in your package.json file:
"theia": {
"frontend": {
"config": {
"defaultLocale": "zh-cn"
}
}
}The first time a user starts your Theia app, the locale will be automatically set to the selected default locale.
They are still free to change the selected locale using the Configure Display Language command.
Overriding Translatable Text Blocks
Sometimes you may want to override specific translatable text blocks in Theia without creating a full localization for your extension. For example, you might want to rebrand menu items or customize specific text to better fit your application's context. Theia provides the TextReplacementContribution API to handle these use cases.
This feature allows you to provide replacement text for any translatable string in Theia, supporting all available languages. The replacement logic executes during the frontendPreload phase of the application lifecycle, ensuring synchronization with the localization process.
Creating a Text Replacement Contribution
To override text blocks, create a class that implements the TextReplacementContribution interface:
import { TextReplacementContribution } from '@theia/core/lib/browser/preload/text-replacement-contribution';
export class MyTextReplacementContribution implements TextReplacementContribution {
getReplacement(locale: string): Record<string, string> {
switch (locale) {
case 'en': {
return {
'About': 'About Theia',
};
}
case 'de': {
return {
'About': 'Über Theia',
};
}
}
return {};
}
}The getReplacement method receives the current locale and returns a map of text replacements. Important: The keys in this map should be the English default values of the translatable text, not the localization keys used in nls.localize calls.
Binding the Text Replacement Contribution
Text replacement contributions must be bound in a frontendPreload module. First, create a preload module file (e.g., my-app-preload-module.ts):
import { ContainerModule } from '@theia/core/shared/inversify';
import { TextReplacementContribution } from '@theia/core/lib/browser/preload/text-replacement-contribution';
import { MyTextReplacementContribution } from './preload/my-text-replacement';
export default new ContainerModule(bind => {
bind(TextReplacementContribution).to(MyTextReplacementContribution).inSingletonScope();
});Then register this module in your extension's package.json under the frontendPreload section:
{
"theiaExtensions": [
{
"frontendPreload": "lib/browser/my-app-preload-module"
}
]
}Important Notes
- Use Default Values: The replacement map must use the default English text values as keys, not the localization keys. For example, if your code contains
nls.localize('about-key', 'About'), the replacement key should be'About', not'about-key'. - Multi-Language Support: You can provide different replacements for different locales by checking the
localeparameter. - Security: The implementation includes built-in protections against JavaScript prototype pollution attacks.
- Testing: After implementing text replacements, test them by using the
Configure Display Languagecommand to switch between different locales and verify that your replacements appear correctly.