New:Microsoft Teams Notifications Are Now Available in Socket.Learn more
Get Started

svintl

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

svintl

Internationalization for Svelte

latest
Source
npmnpm
Version
1.17.0
Version published
Weekly downloads
128
652.94%
Maintainers
1
Weekly downloads
 
Created
Source

Internationalization for Svelte

Developer-friendly CLI tool for managing internationalization dictionaries with automatic translation via OpenAI.

  • Bulk dictionary manipulation
  • Automatic translation via OpenAI
  • Generates typed JavaScript modules

TL;DR

npm i svintl -D
npx intl hola # initialize dictionaries in default location
npx intl add example.hello "Hello world" # add a translation
npx intl create es # create a new locale dictionary
npx intl build # generate JavaScript dictionaries
<script lang="ts">
  import { dict, locale } from '$lib/intl'

  // bind $locale to a dropdown or whatever
</script>

<h1>{$dict.example.hello}</h1>

Everything below this line is written by AI.

Dictionary format

The dictionary is an object with an arbitrary structure, where strings are located at the leaves.

native: English
example:
  hello: "Hello world"
<h1>{$dict.example.hello}</h1>

Values can be specified as JavaScript functions using the following syntax:

example:
  hello: |
    !js
    () => 'Hello world'

This looks weird, suggestions are welcome.

Functions can accept arguments:

example:
  hello: |
    !js
    (count) => `${count || 'No'} item${count === 1 ? '' : 's'}`
<h1>You have {$dict.example.hello(count)}</h1>

The translation prompt provides clear guidance on using functions across locales to implement phrases with locale-specific rules.

If a phrase contains placeholders like {name} or {itemId}, store it as a !js function with matching parameters.

If a phrase contains placeholders like [names] in square brackets, treat them as array-of-strings parameters and format them with Intl.ListFormat using style: "long" and type: "conjunction". Make the phrase grammatically correct based on the number of items in the array.

Example input:

npx intl set joined "[names] have joined the {groupName}"

Example function output:

joined: |
  !js
  (names, groupName) => {
    const list = new Intl.ListFormat("en", { style: "long", type: "conjunction" }).format(names)
    return names.length === 1
      ? `${list} has joined the ${groupName}`
      : `${list} have joined the ${groupName}`
  }

Pluralization

For pluralized content, use arrays containing objects with named plural forms. This format automatically generates functions that use Intl.PluralRules for proper pluralization:

items:
  count:
    - one: item
      other: items

product:
  count:
    - one: product
      other: products

For locales with complex pluralization rules (like Russian), include all required forms:

# Russian pluralization
product:
  count:
    - one: товар      # 1, 21, 31, 41...
      few: товара     # 2-4, 22-24, 32-34...
      many: товаров   # 0, 5-20, 25-30...
      other: товаров  # fallback

The array format [{ one: '...', other: '...' }] serves as an indicator for pluralization. The system automatically:

  • Detects the array-with-object format
  • Generates optimized functions using direct property access
  • Eliminates the need for CLDR ordering complexity
  • Supports all standard plural categories: zero, one, two, few, many, other
<p>You have {$dict.items.count(itemCount)}</p>

Mounts

Mounts allow you to organize translations into separate directories anywhere in your filesystem. Each mount acts as an independent dictionary that can be imported separately.

npx intl mount foo ./any/path # creates foo mount with empty dictionaries for all locales
npx intl set foo/bar.baz "Hello mount" # set key in mount 'foo'
npx intl import bar ./vendor/bar-intl # adopt an existing dictionary dir as a mount

Mounts are created with the same languages as the root dictionary but start empty (no native key). Use import instead to adopt a populated dictionary directory and reconcile its locales to the root.

Mounts are useful for:

  • Organizing large applications by feature/module
  • Separate dictionaries for different user roles
  • Logical grouping of related translations
  • Storing dictionaries in different locations
<script lang="ts">
  import { dict as mainDict } from '$lib/intl'
  import { dict as adminDict } from '$lib/intl/admin'
</script>

<div>{$mainDict.foo}</div>
<div>{$adminDict.bar}</div>

Context

Translation contexts are automatically saved when using the set command with a comment parameter. These contexts enhance translation accuracy when creating new locale dictionaries.

npx intl set app.welcome "Welcome to our application" "greeting shown on homepage"

Contexts are stored in context.yaml alongside your locale files:

mounts:
  foo: ../../any/path # path relative to this main context file

inputs:
  app:
    welcome:
      input: "Welcome to our application"
      context: "greeting shown on homepage"

When creating new locales with npx intl create <lang>, saved per-key contexts under inputs are passed into batch translation.

The optional global product description (npx intl context "…"), stored as the top-level context field in context.yaml, is sent on every OpenAI translation: add, set, unit, create (when translating from a source locale), and sync.

CLI

Translations are powered by OpenAI. Ensure you set the OPENAI_API_KEY in your environment variables. .env and .env.local are supported (.env.local overrides .env).

On add and set, pass --debug to print the full translation request (model, system and user messages) to stdout before the OpenAI call.

npx intl

Print help.

npx intl hola
  • Create a directory src/lib/intl/ or specified with -p
  • Create en-US dictionary
  • Generate JavaScript dictionaries and TypeScript types
npx intl create es
npx intl create en-US
npx intl create pt-BR

Creates a new locale dictionary. Locale codes must be valid BCP 47 locale tags. The new dictionary will automatically include a native key with the locale name in that locale.

Dictionary names must be valid BCP 47 locale tags.

npx intl add example.hello "Hello world"   # new key (fails if key already exists)
npx intl set example.hello "Hello world"   # update existing key
npx intl set wardrobe.tops "Tops" "Clothing"
npx intl set example.hello "Hello world" --debug   # log OpenAI request before sending

add creates an entry; set updates an existing one. Optional third argument is context for the translator.

npx intl open                  # whole dictionary as a collapsible tree
npx intl open example          # a sub-tree
npx intl open example.hello    # a single entry
npx intl open foo/             # a whole mount
npx intl open foo/bar          # a sub-tree inside a mount
npx intl open -l ru-RU         # edit a specific locale
npx intl open --port 4567      # choose the server port

Starts a small local web server and opens your browser with a no-framework editor. You edit one locale (default en-US, or the first available; override with --locale/-l). Each field shows an editable translator context (pre-filled from context.yaml). Pressing Save writes the changed entries through the same translate-to-all pipeline as set (so other locales are re-translated via OpenAI) — a field is re-translated when its value or its context changed, and untouched fields are left alone. Then the server shuts down and the CLI exits. Only plain-string entries are editable; !js functions and pluralization arrays are hidden.

npx intl mount <mount> <dir>

Create a dictionary mount at the specified path with empty dictionaries for all languages in the root directory. Mounts can be addressed with mount/key key syntax. Example: npx intl set mount/key "value" "context".

npx intl import <name> <dir> [--js]

Adopt an existing dictionary directory (must contain context.yaml) as a mount and reconcile its locales to the root: drop languages the root lacks, generate languages it has but the mount lacks (translating the imported inputs with the root's context and genders), leave shared locales untouched. Errors if <name> is already a mount.

npx intl unmount <mount>

Remove a mount from context.yaml but keep the partition files on disk. The mount can be re-added later using the mount command.

npx intl unit items.count "item"

Creates pluralized translation entries for all locales using the object-based format. The system automatically generates appropriate plural forms for each locale based on their pluralization rules.

npx intl const example.hello "Hello"

Sets the same value in all dictionaries without translation.

npx intl move example.hello example.greeting.welcome

Moves a translation entry or a branch.

npx intl del example.hello

Deletes a translation entry or a branch.

npx intl destroy es

Deletes a locale dictionary.

npx intl sync en
npx intl sync en example.hello # sync specific key

Syncs (re-translates) all locales using the source locale dictionary.

npx intl context "Describe shared project background"
npx intl context --clear

Sets or clears project-wide translation guidance stored in context.yaml.

npx intl genders he she none   # enable; list the gender values (last = neutral/fallback)
npx intl genders               # print current values

Lists the grammatical genders your strings vary by — they become the Grammar union in the generated types. Disable by removing the genders key from context.yaml (there is no genders false).

Gender-dependent phrases become !js functions taking the gender as their last argument (the phrase's own arguments, if any, come first). Prefer the neutral form; otherwise a combined one (бежал(а), должен(на)), never a neuter form for a person.

run: |
  !js
  (gender) => gender === "she" ? "бежала" : gender === "he" ? "бежал" : "бежал(а)"
npx intl build

Generates JavaScript dictionaries and TypeScript types from YAML files. Creates built.js and types.ts files that can be imported in your Svelte application.

FAQs

Package last updated on 04 Aug 2026

Related posts