---
title: JavaScript Internationalization (i18n)
description: Learn how to use Lingui's internationalization features in your vanilla JavaScript application
---

# JavaScript Apps Internationalization

This tutorial will walk you through using Lingui's internationalization (i18n) features in a vanilla JavaScript application. We'll cover the essentials of the `@lingui/core` package, which handles all translation and message catalog management.

:::tip Example
If you're looking for a working solution, check out the [Vanilla JS example](https://github.com/lingui/js-lingui/tree/main/examples/js). This example application shows a complete setup using Lingui and vanilla JavaScript.
:::

## Installing Lingui

1. Follow the [Installation and Setup](/installation) page for initial setup.
2. Install the [`@lingui/core`](/ref/core) package, which is responsible for translation and message catalog handling.

## Setting up i18n

First, we need to set up the i18n singleton, which is pretty simple:

```js
import { i18n } from "@lingui/core";
import { messages } from "path-to-locale/en/messages.js";

i18n.load("en", messages);
i18n.activate("en");
```

The `messages.js` is generated by the Lingui CLI and contains compiled message catalogs.

:::tip
Alternatively, you can load catalogs dynamically using the [`@lingui/loader`](/ref/loader) or [`@lingui/vite-plugin`](/ref/vite-plugin) without the need to import compiled messages manually.
:::

## Localizing Your App

To localize your application, you need to wrap your localizable texts in [Macros](/ref/macro). Lingui provides a set of Core Macros that transform tagged template literals and can be used in any JavaScript context.

Let's wrap our text in the [`t`](/ref/macro#t) macro:

```js
import { t } from "@lingui/core/macro";

t`Hello World!`;
// becomes "Salut le monde!"

const name = "Fred";
t`My name is ${name}`;
// becomes "Je m'appelle Fred"
```

Plurals and selections are possible using [`plural`](/ref/macro#plural) and [`select`](/ref/macro#select) macros:

```js
import { plural } from "@lingui/core/macro";

const count = 42;

plural(count, {
  one: "# book",
  other: "# books",
});
// becomes "42 livres"
```

It's also possible to nest message formats. Each message format method in `i18n` has a standalone companion, which only returns message without performing the translation:

```js
import { t, select, plural } from "@lingui/core/macro";

select(gender, {
  offset: 1,
  female: plural(numOfGuests, {
    offset: 1,
    0: t`${host} does not give a party.`,
    1: t`${host} invites ${guest} to her party.`,
    2: t`${host} invites ${guest} and one other person to her party.`,
    other: t`${host} invites ${guest} and # other people to her party.`
  }),
  male: plural(value, {...}),
  other: plural(value, {...}),
});
```

:::caution
All Core Macros cannot be used at the module level. They must be used within a component or function. See the [Macros](/ref/macro#using-macros) documentation for more information.
:::

## See Also

- [Message Extraction Guide](/guides/message-extraction)
- [Pluralization Guide](/guides/plurals)
- [Dynamic Loading of Message Catalogs](/guides/dynamic-loading-catalogs)
- [Lingui CLI Reference](/ref/cli)
