Skip to main content


Localization is the process of supporting multiple languages and regions in your apps and components. Lit has first-party support for localization through the @lit/localize library, which has a number of advantages that can make it a good choice over third-party localization libraries:

  • Native support for expressions and HTML markup inside localized templates. No need for a new syntax and interpolation runtime for variable substitution — just use the templates you already have.

  • Automatic re-rendering of Lit components when the locale switches.

  • Only 1.27 KiB (minified + compressed) of extra JavaScript.

  • Optionally compile for each locale, reducing extra JavaScript to 0 KiB.

Install the @lit/localize client library and the @lit/localize-tools command-line interface.

  1. Wrap a string or template in the msg function (details).
  2. Create a lit-localize.json config file (details).
  3. Run lit-localize extract to generate an XLIFF file (details).
  4. Edit the generated XLIFF file to add a <target> translation tag (details).
  5. Run lit-localize build to output a localized version of your strings and templates (details).

To make a string or Lit template localizable, wrap it in the msg function. The msg function returns a version of the given string or template in whichever locale is currently active.

Before you have any translations available, msg simply returns the original string or template, so it's safe to use even if you're not yet ready to actually localize.

Any string or template that you would normally render with Lit can be localized, including ones with dynamic expressions and HTML markup.

Plain string:

Plain string with expression (see strings with expressions for details on str):

HTML template:

HTML template with expression:

Localized messages can also be nested inside HTML templates:

If a string contains an expression and doesn't need to be tagged with html, then it must be tagged with str in order to be localizable. An error will be raised during extraction if you forget to include the str tag.



The str tag is required in these cases because untagged template string literals are evaluated to regular strings before they are received by the msg function, which means dynamic expression values could not otherwise be captured and substituted into the localized versions of the string.

A locale code is a string that identifies a human language, and sometimes also includes a region, script, or other variation.

Lit Localize does not mandate use any particular system of locale codes, though it is strongly recommended to use the BCP 47 language tag standard. Some examples of BCP 47 language tags are:

  • en: English
  • es-419: Spanish spoken in Latin America
  • zh-Hans: Chinese written in Simplified script

Lit Localize defines a few important locale values:

Source locale

The locale that is used to write strings and templates in your source code.

Target locales

The locales that your strings and templates can be translated into.

Active locale

The global locale that is currently being displayed.

Lit Localize supports two output modes: runtime and transform, each with their own advantages.

Don't worry too much about which mode to use at first. It's easy to switch between the two because the core msg API is identical. If unsure, start with runtime mode.

In runtime mode, one JavaScript or TypeScript module is generated for each of your locales. Each module contains the localized templates for that locale. When the active locale switches, the module for that locale is imported, and all components are re-rendered.

Runtime mode makes switching locales very fast because a page reload is not required. However, there is a slight performance cost to rendering performance compared to transform mode.

Example generated output

See the runtime mode page for full details about runtime mode.

In transform mode, a separate folder is generated for each locale. Each folder contains a complete standalone build of your application in that locale, with msg wrappers and all other Lit Localize runtime code completely removed.

Transform mode requires 0 KiB of extra JavaScript and is extremely fast to render. However, switching locales requires re-loading the page so that a new JavaScript bundle can be loaded.

Example generated output

See the transform mode page for full details about transform mode.

Runtime modeTransform mode
OutputA dynamically loaded module for each target locale.A standalone app build for each locale.
Switch localesCall setLocale()Reload page
JS bytes1.27 KiB (minified + compressed)0 KiB
Make template localizablemsg()msg()
Advantages- Faster locale switching
- Fewer marginal bytes when switching locale
- Faster rendering
- Fewer bytes for a single locale

The lit-localize command-line tool looks for a config file called lit-localize.json in the current directory. Copy-paste the example below for a quick start, and see the CLI and config page for a full reference of all options.

If you're writing JavaScript, set the inputFiles property to the location of your .js source files. If you're writing TypeScript, set the tsConfig property to the location of your tsconfig.json file, and leave inputFiles blank.

Run lit-localize extract to generate an XLIFF file for each target locale. XLIFF is an XML format supported by most localization tools and services. XLIFF files will be written to the directory specified by the interchange.xliffDir config option.

For example, given the source:

Then a <xliffDir>/<locale>.xlf file will be generated for each target locale:

XLIFF files can be edited manually, but more typically they are sent to a third-party translation service, where they are edited by language experts using specialized tools.

After uploading an XLIFF file to your chosen translation service, you will eventually receive a new XLIFF file in response. The new XLIFF file will look just like the one you uploaded, but with <target> tags inserted into each <trans-unit>.

When you receive a new translation XLIFF file, save it to your xliff/ directory, overwriting your original version.

Use the lit-localize build command to incorporate translations back into your application. The behavior of this command depends on the mode you have configured.

See the runtime mode and transform mode pages for details of how building in each mode works.

Use the desc option to the msg function to provide human-readable descriptions for your strings and templates. These descriptions are shown to translators by most translation tools, and are highly recommended to help explain and contextualize the meaning of messages.

Descriptions will be represented in XLIFF files using <note> elements.

Lit Localize automatically generates an id for every msg call using a hash of the string contents, including HTML markup.

If two msg calls share the same id, then they are treated as the same message, meaning they will be translated as a single unit and the same translations will be substituted in both places.

For example, these two msg calls are in two different files, but since they have the same content they will be treated as one message:

If a string contains an expression (e.g. ${foo}), then the content of the expression does not affect the id, though the presence and position of the expression does.

For example, these two messages have the same id:

Message ids can be overridden by specifying the id option to the msg function. In some cases this may be necessary, such as when an identical string has multiple meanings, because each might be written differently in another language: