Skip to content
stdlib
Esc
↑↓navigate↵open⌘Jpreview
On this page

Usage

Installation

npm install -D @monstermann/stdlib-i18n
pnpm add -D @monstermann/stdlib-i18n
yarn add -D @monstermann/stdlib-i18n
bun add -D @monstermann/stdlib-i18n
nub add -D @monstermann/stdlib-i18n
aube add -D @monstermann/stdlib-i18n

Set up stdlib-transform for your bundler, without it every message ends up in every bundle.

Messages

One key per message, with one translation per language:

auth.signIn:
  en: Sign in
  de: Anmelden

auth.codeSent:
  en: We sent a code to {email}
  de: Wir haben einen Code an {email} gesendet

Files and their names don’t matter, they are only used for organization - they all get bundled together.

Translations are written in the ICU message format:

Syntax Props
Hello {name} { name: number | string }
{count, number} new { count: number }
Due {when, date, short}, {when, time} { when: Date | number }
{count, plural, one {# task} other {# tasks}} { count: number }
{place, selectordinal, one {#st} other {#th}} { place: number }
{role, select, admin {Admin} other {Member}} { role: string }

Compiling

{
    "scripts": {
        "i18n": "stdlib-i18n --messages 'i18n/*.yaml' --output src/i18n"
    }
}
  • --messages can take several globs
  • The output folder gets an index.ts and a _messages.ts
  • Git ignored files are skipped

Translating

Every message takes the language first, then its props:

import { m } from "./i18n"

m.auth.signIn({ lang: "de" })
m.auth.codeSent({ lang: "de" }, { email: "ada@example.com" })

As shown in the introduction, you can build your own wrappers to automate MessageContext, for example building a useMessage hook for react, or building an abstraction that pulls user preferences from a database for servers.

Auto-imports

Depending on your setup, the TypeScript LSP may autocomplete from _messages.ts in your editor, which you can prevent by telling it to skip files starting with _:

{ "autoImportSpecifierExcludeRegexes": ["(^|/)_[^/]*$"] }