| name | svintl |
| description | svintl CLI for i18n — translations, locales, pluralization, mounts, building typed dictionaries. Triggers on `npx intl`, YAML locale files, intl directories, or any translation/i18n work in Svelte projects.
|
svintl — i18n for Svelte
CLI tool for managing internationalization dictionaries with automatic translation via OpenAI.
Core Rule
The *.yaml, built.js, and types.ts files in intl directories are generated — they're edited through the npx intl CLI, not by hand.
CLI Commands
npx intl hola
npx intl hola -p ./custom/path
npx intl add key.path "Value" "context"
npx intl set key.path "Updated value"
npx intl set "mount/key.path" "Value"
npx intl add key.path "Value" --debug
npx intl const key.path "Same everywhere"
npx intl unit items.count "item"
npx intl move old.key new.key
npx intl del key.path
npx intl create es
npx intl destroy es
npx intl mount foo ./any/path
npx intl import foo ./any/path
npx intl unmount foo
npx intl context "Project description"
npx intl context --clear
npx intl genders he she none
npx intl genders
npx intl sync en key.path
npx intl sync en
npx intl build
Dictionary Format
YAML with arbitrary nesting, strings at leaves:
native: English
example:
hello: "Hello world"
Usage: {$dict.example.hello}
Dynamic Values — Placeholders
For simple cases the CLI auto-generates !js functions from placeholder syntax — no need to write them manually:
npx intl set greeting "Hello, {name}!"
npx intl set joined "[names] joined {groupName}"
For complex logic, pass !js functions via intl set:
npx intl set greeting '!js (count) => `${count || "No"} item${count === 1 ? "" : "s"}`'
Usage in components: {$dict.greeting(user.name)}
Pluralization
Use npx intl unit — generates Intl.PluralRules-based functions:
npx intl unit items.count "item"
Produces:
items:
count:
- one: item
other: items
Usage: {$dict.items.count(count)}
Complex locales (Russian, Arabic) auto-get few, many, etc.
Genders
When enabled (npx intl genders he she none), gender-dependent phrases become functions whose last argument is the gender ('he' | 'she' | 'none') — the phrase's own arguments come first, e.g. (name, gender) => …. The listed values become the generated Grammar union.
Mounts
Organize translations into separate directories:
npx intl mount admin ./src/features/admin/intl
npx intl set "admin/dashboard.title" "Admin Dashboard"
Mount keys use {mount}/ prefix in CLI commands.
mount scaffolds an empty mount; import adopts a populated dir (with its own context.yaml) and reconciles its locales to the root — drops languages the root lacks, generates ones it lacks (translating the imported inputs), leaves shared locales untouched.
Import Pattern
Root dictionary:
<script lang="ts">
import { dict, locale } from '$lib/intl'
</script>
<h1>{$dict.example.hello}</h1>
Mount dictionary:
<script lang="ts">
import { dict } from './intl'
</script>
<h1>{$dict.dashboard.title}</h1>
Mount's intl/index.ts:
import { derived } from 'svelte/store'
import { locale } from '$lib/intl'
import { dictionaries } from './built.js'
import type { Locale, Dictionary } from './types'
const dict = derived(locale, ($locale) => dictionaries[$locale])
export { dict, dictionaries, locale }
export type { Locale, Dictionary }
Context for Translation Accuracy
npx intl set app.welcome "Welcome" "greeting shown on homepage"
npx intl context "B2B SaaS for enterprise users"
Context is stored in context.yaml and used by OpenAI when creating new locales.
Workflow
- Use
npx intl add/set/unit/const to add/update translations
- Run
npx intl build to generate JS/TS (often auto-runs)
- Import
dict store in components
- Use
$dict.key.path in templates
Avoid
- Editing YAML by hand — go through the CLI
npx intl sync for routine edits — it's only for reconciling after a manual source edit; use add/set instead
- Non-BCP47 locale codes — use valid tags like
en-US, es, pt-BR