Skip to main content

The core i18n functionality

@lingui/core package provides the main i18n object which manages message catalogs, active locale as well as translation and formatting of messages.

Installation

npm install --save @lingui/core

Overview

@lingui/core package exports the global instance of i18n object. Simply import it and use it:

import { i18n } from "@lingui/core"

/**
* Load messages for requested locale and activate it.
* This function isn't part of the LinguiJS library because there are
* many ways how to load messages — from REST API, from file, from cache, etc.
*/
async function activate(locale: string) {
const { messages } = await import(`${locale}/messages.js`)
i18n.loadAndActivate(locale, messages)
}

activate("cs")

// returns the Czech translation of "Hello World"
const translation = i18n._("Hello World")

If you don't want to use the global i18n instance and you want to setup your own, you can use setupI18n method. You also need to set runtimeConfigModule for macros to work correctly:

// If you import `i18n` object from custom module like this:
import { i18n } from "./custom-i18n-config"

// ... then add following line to your Lingui configuration:
// "runtimeConfigModule": ["./custom-i18n-config", "i18n"]

Reference

Class i18n()

i18n.load(catalogs: Catalogs)

i18n.load(locale: string, catalog: Catalog)

Load catalog for given locale or load multiple catalogs at once.

import { i18n } from "@lingui/core"

const messages = {
"Hello": "Hello",
"Good bye": "Good bye",

// Just an example how catalog looks internally.
// Formatting of string messages works in development only.
// See note below.
"My name is {name}": "My name is {name}"
}

const messagesCs = {
"Hello": "Ahoj",
"Good bye": "Nashledanou",
"My name is {name}": "Jmenuji se {name}"
}

i18n.load({
en: messagesEn,
cs: messagesCs
})

// This is the same as loading message catalogs separately per language:
// i18n.load('en', messagesEn)
// i18n.load('cs', messagesCs)
tip

Don't write catalogs manually.

Code above contains an example of message catalogs. In real applications, messages are loaded from external message catalogs generated by compile command.

Formatting of messages as strings (e.g: "My name is {name}") works in development only, when messages are parsed on the fly. In production, however, messages must be compiled using compile command.

The same example would in real application look like this:

import { i18n } from "@lingui/core"

// File generated by `lingui compile`
import { messages: messagesEn } from "./locale/en/messages.js"

i18n.load('en', messagesEn)

i18n.activate(locale[, locales])

Activate a locale and locales. _ from now on will return messages in given locale.

import { i18n } from "@lingui/core"

i18n.activate("en")
i18n._("Hello") // Return "Hello" in English

i18n.activate("cs")
i18n._("Hello") // Return "Hello" in Czech

i18n.loadAndActivate(locales: Locale | Locales, messages: Messages, notify = true)

Load catalog and activate given locale. This method is i18n.load() + i18n.activate() in one pass.

locales Could be one locale or array of locales. If array of locales is passed they would be used as fallback locales for date and number formatting.

messages compiled message catalog.

notify Should emit change event for all subscribers. This is useful for integration with frameworks as NextJS to avoid race-conditions during initialization.

import { i18n } from "@lingui/core"

const { messages } = await import(`${locale}/messages.js`)
i18n.loadAndActivate(locale, messages)

i18n._(messageId[, values[, options]])

The core method for translating and formatting messages.

messageId is a unique message ID which identifies message in catalog.

values is an object of variables used in translated message.

options.message is the default translation (optional). This is mostly used when application doesn't use message IDs in natural language (e.g.: msg.id or Component.title).

import { i18n } from "@lingui/core"

// Simple message
i18n._("Hello")

// Message with variables
i18n._("My name is {name}", { name: "Tom" })

// Message with custom messageId
i18n._("msg.id", { name: "Tom" }, { message: "My name is {name}" })

i18n.date(value: string | Date[, format: Intl.DateTimeFormatOptions])

Returns: Formatted date string Format a date using the conventional format for the active language.

date is a Date object to be formatted. When date is a string, the Date object is created by new Date(date).

format is an object passed to the options argument of the Intl.DateTimeFormat constructor (optional).

import { i18n } from "@lingui/core"

const d = new Date("2021-07-23T16:23:00")

i18n.activate("en")
i18n.date(d)
// Returns "7/23/2021"

i18n.date(d, { timeStyle: "medium"})
// Returns "4:23:00 PM"

i18n.date(d, { dateStyle: "medium", timeStyle: "medium"})
// Returns "Jul 23, 2021, 4:23:00 PM"

i18n.activate("cs")
i18n.date(d)
// Returns "23. 7. 2021"

i18n.number(value: number[, format: Intl.NumberFormatOptions])

Returns: Formatted number string

Format a number using the conventional format for the active language.

number is a number to be formatted.

format is an object passed to the options argument of the Intl.NumberFormat constructor (optional).

import { i18n } from "@lingui/core"

i18n.activate("en")
i18n.number(12345.678)
// Returns "12,345.678"

i18n.number(12345.678, { style: "currency", currency: "USD"})
// Returns "$12,345.68"

i18n.activate("cs")
i18n.number(12345.678)
// Returns "12 345,678"

i18n.number(12345.678, { style: "currency", currency: "CZK"})
// Returns "12 345,68 Kč"

setupI18n([options])

Returns: Instance of I18n

Initialize and return a new I18n instance. Usually you want to call it just once and then use returned i18n object across whole codebase.

note

You don't need to setup i18n instance

In most cases you can use the global i18n object exported from @lingui/core directly.

However, if you do need to setup your own i18n instance, remember to also set runtimeConfigModule work macros to work properly:

// If you import `i18n` object from custom module like this:
import { i18n } from "./custom-i18n-config"

// ... then add following line to your Lingui configuration:
// "runtimeConfigModule": ["./custom-i18n-config", "i18n"]
import { setupI18n } from "@lingui/core"

const i18n = setupI18n()

The factory function accepts one optional parameter, options:

options.locale

Initial active locale.

import { setupI18n } from "@lingui/core"

const i18n = setupI18n({ locale: "en" })

// This is a shortcut for:
// const i18n = setupI18n()
// i18n.activate("en")

options.locales

List of alternative locales (BCP 47 language tags) which are used for number and date formatting (some countries use more than one number/date format). If not set, active locale is used instead.

import { setupI18n } from "@lingui/core"

const i18n = setupI18n({
locale: "ar",
locales: ["en-UK", "ar-AS"]
})

// This is a shortcut for:
// const i18n = setupI18n()
// i18n.activate("en", ["en-UK", "ar-AS"])

options.messages

Initial Messages.

import { setupI18n } from "@lingui/core"

const messages: {
en: require("./locale/en/messages").messages, // your path to compiled messages here
cs: require("./locale/cs/messages").messages // your path to compiled messages here
}
const i18n = setupI18n({ messages })

// This is a shortcut for:
// const i18n = setupI18n()
// i18n.load(messages)

options.missing

Custom message to be returned when translation is missing. This is useful for debugging:

import { setupI18n } from "@lingui/core"

const i18n = setupI18n({ missing: "🚨" })
i18n._('missing translation') === "🚨"

This might be also a function which is called with active locale and message ID:

import { setupI18n } from "@lingui/core"

function missing(locale, id) {
alert(`Translation in ${locale} for ${id} is missing!`)
return id
}

const i18n = setupI18n({ missing })
i18n._('missing translation') // raises alert

Catalogs

Type of catalogs parameters in I18n.load method:

type Catalogs = {[locale: string]: Catalog}

// Example:
const catalogs: Catalogs = {
en: {
messages: {
"Hello": "Hello",
"Good bye": "Good bye"
}
},
cs: {
messages: {
"Hello": "Ahoj",
"Good bye": "Nashledanou"
}
}
}

Catalog

Message catalog contains messages and language data (plurals). This object is usually generated in CLI:

type Catalog = {
languageData: {
plurals: Function
},
messages: Messages
}

Messages

Type of messages in Catalogs. It's a mapping of a messageId to a translation in given language. This may be a function if messages are compiled.

type Messages = {[messageId: string]: string | Function}

// Example
const messagesEn: Messages = {
"Hello": "Hello",
"Good bye": "Good bye"
}

Events

change

Triggered after locale is changed or new catalog is loaded. There are no arguments.

missing

Triggered when a translation is requested with i18n._ that does not exist in the active locale's messages. Information about the locale and message are available from the event.

i18n.on('missing', (event) => {
alert(`alert(`Translation in ${event.locale} for ${event.id} is missing!`)`)
})