Skip to content

Getting Started

@nano_kit/intl is a lightweight internationalization library for @nano_kit/store. It keeps translations reactive, lets message types flow from translation data, and composes small formatters instead of introducing a separate message syntax runtime.

  • Reactive. Locale changes update messages through @nano_kit/store signals.
  • Type-safe. Message schemas are checked against translation namespace data.
  • Composable. Build messages from formats like text, params, plural, match, number, and datetime.
  • Tree-shakeable. Import only the formats your app uses.
  • SSR-ready. Use @nano_kit/query for cached translation loading and dehydration.

Install the package with @nano_kit/store:

pnpm add @nano_kit/store @nano_kit/intl

For SPA-style apps or small demos, resolved is the simplest loader. It can return static data, a signal-derived value, or a promise.

import {
resolved,
signal
} from '@nano_kit/store'
import {
intl,
params,
plural,
text
} from '@nano_kit/intl'
const $locale = signal<'en' | 'de'>('en')
const translations = {
en: {
common: {
title: 'Event Board',
greeting: 'Hello, {name}!',
unread: {
one: '{count} unread message',
other: '{count} unread messages'
}
}
},
de: {
common: {
title: 'Event Board',
greeting: 'Hallo, {name}!',
unread: {
one: '{count} ungelesene Nachricht',
other: '{count} ungelesene Nachrichten'
}
}
}
}
const { messages } = intl(
$locale,
resolved(() => translations[$locale()])
)
const [$t] = messages('common', {
greeting: params({
name: text()
}),
unread: plural('count')
})
$t().title
// "Event Board"
$t().greeting({
name: 'Ada'
})
// "Hello, Ada!"
$t().unread({
count: 5
})
// "5 unread messages"
$locale('de')