{"_id":"@argon-sdk/locales","_rev":"2-bedcefac5a06dc8375f92a49119ea745","name":"@argon-sdk/locales","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@argon-sdk/locales","version":"1.0.0","keywords":["argon","bot","sdk","plugin","typescript","locales","localization","i18n","fluent","translations"],"author":{"name":"omnifaced"},"license":"MIT","_id":"@argon-sdk/locales@1.0.0","maintainers":[{"name":"omnifaced","email":"omnifaced@proton.me"}],"homepage":"https://github.com/argon-sdk/locales#readme","bugs":{"url":"https://github.com/argon-sdk/locales/issues"},"bin":{"argon-locales":"dist/cli.js"},"dist":{"shasum":"9369c264929694da3cc38c08cab83c826956e363","tarball":"https://registry.npmjs.org/@argon-sdk/locales/-/locales-1.0.0.tgz","fileCount":7,"integrity":"sha512-58GraKax4tW1BD2DuF/mrvg4YKNQ79+MZSxXcDYeurG5WcQnZbhxliSk52i6dgkNyu219UN/h80rS9GWzb3WcA==","signatures":[{"sig":"MEYCIQCWBbiH+GWpF3S+WOwPgIFxlx5fz7EspsdsRNTv2b4yPgIhAKpBt/CnfLRPafmf7xfpfPA6M/2NOgX2rLnciBJWuarb","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":180125},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"bun":">=1","deno":">=2","node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsup","check":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"omnifaced","email":"omnifaced@proton.me"},"repository":{"url":"git+https://github.com/argon-sdk/locales.git","type":"git"},"_npmVersion":"11.12.1","description":"Localization plugin for Argon SDK","directories":{},"sideEffects":false,"_nodeVersion":"25.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","cleye":"^2.6.0","@types/bun":"latest","@fluent/bundle":"^0.19.1"},"peerDependencies":{"typescript":"^5","@argon-sdk/core":"1.0.2"},"_npmOperationalInternal":{"tmp":"tmp/locales_1.0.0_1776569480777_0.47637486572787324","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@argon-sdk/locales","version":"1.1.0","description":"Localization plugin for Argon SDK","type":"module","license":"MIT","author":{"name":"omnifaced"},"keywords":["argon","bot","sdk","plugin","typescript","locales","localization","i18n","fluent","translations"],"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"main":"./dist/index.js","types":"./dist/index.d.ts","sideEffects":false,"bin":{"argon-locales":"dist/cli.js"},"engines":{"node":">=18","bun":">=1","deno":">=2"},"scripts":{"build":"tsup","check":"tsc --noEmit","prepublishOnly":"npm run build"},"peerDependencies":{"@argon-sdk/core":"^1.2.0","typescript":"^5"},"devDependencies":{"@fluent/bundle":"^0.19.1","@types/bun":"^1.3.13","cleye":"^2.6.0","tsup":"^8.5.1"},"repository":{"type":"git","url":"git+https://github.com/argon-sdk/locales.git"},"publishConfig":{"access":"public"},"gitHead":"b9d771a7dc9c38f50891bc431b1a480d51ce21f9","_id":"@argon-sdk/locales@1.1.0","bugs":{"url":"https://github.com/argon-sdk/locales/issues"},"homepage":"https://github.com/argon-sdk/locales#readme","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-DcbMx/JjZw7hA9EgzHNZfAPxCQ6tpWVs2IDPHNPZlZKJe5RwhtZf7UGyD23ml7iDuvtzlxVKX2fwBp34hg6DkQ==","shasum":"4633f257df557708a2f8ac8a245ef6ea1aef282b","tarball":"https://registry.npmjs.org/@argon-sdk/locales/-/locales-1.1.0.tgz","fileCount":7,"unpackedSize":179451,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCcZjb1QMRsblY2N/k1m4UacER8w3zL+VbBOAVWeezKBAIgQcBFWbOnk+3JHCZzsv/HWtyqFfSkVA/lsJ70Vet3DHU="}]},"_npmUser":{"name":"omnifaced","email":"omnifaced@proton.me"},"directories":{},"maintainers":[{"name":"omnifaced","email":"omnifaced@proton.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/locales_1.1.0_1777154770833_0.6535007552057361"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-19T03:31:20.625Z","modified":"2026-04-25T22:06:11.122Z","1.0.0":"2026-04-19T03:31:20.943Z","1.1.0":"2026-04-25T22:06:11.001Z"},"bugs":{"url":"https://github.com/argon-sdk/locales/issues"},"author":{"name":"omnifaced"},"license":"MIT","homepage":"https://github.com/argon-sdk/locales#readme","keywords":["argon","bot","sdk","plugin","typescript","locales","localization","i18n","fluent","translations"],"repository":{"type":"git","url":"git+https://github.com/argon-sdk/locales.git"},"description":"Localization plugin for Argon SDK","maintainers":[{"name":"omnifaced","email":"omnifaced@proton.me"}],"readme":"# @argon-sdk/locales\n\nLocalization plugin for [Argon SDK](https://github.com/argon-sdk/core). Brings [Project Fluent](https://projectfluent.org/) translations into your bot with full type safety — key autocompletion, typed arguments, and missing-key validation at startup.\n\n## Features\n\n- **Project Fluent** — full `.ftl` syntax: placeables, selectors, multiline values, term references\n- **Type-safe keys** — IDE autocompletion for every translation key via generated `.d.ts`\n- **Typed arguments** — variables (`{ $name }`) inferred per-key, wrong args are a compile error\n- **Plugin integration** — `context.t` available in every handler after a one-line setup\n- **CLI** — `gen` to generate types, `check` to validate completeness, `--watch` to do it live\n- **Zero runtime dependencies** — `@fluent/bundle` is bundled in `dist/`, nothing to install at runtime\n\n## Installation\n\n```sh\nnpm install @argon-sdk/locales\n# or\nbun add @argon-sdk/locales\n```\n\n## Quick Start\n\n### 1. Write your `.ftl` files\n\n```fluent\n# locales/en.ftl\nping-description = Check if the bot is alive\nwelcome = Welcome, { $username }!\n```\n\n```fluent\n# locales/ru.ftl\nping-name = пинг\nping-description = Проверить работу бота\nwelcome = Добро пожаловать, { $username }!\n```\n\n### 2. Generate types\n\n```sh\nnpx argon-locales gen --dir ./locales\n```\n\nThis creates `locales/locale-keys.d.ts` — import it anywhere in your project (e.g. via `tsconfig.json` `include`) and your IDE will autocomplete every key.\n\n### 3. Set up the `t` function\n\n```ts\nimport * as path from 'node:path'\nimport { fluent } from '@argon-sdk/locales'\n\nconst t = fluent({\n  directory: path.join(import.meta.dirname, 'locales'),\n  defaultLocale: 'en',\n})\n```\n\n### 4. Define commands\n\nPass `t('key')` directly into SDK tokens — no wrappers, no magic:\n\n```ts\nimport { command, name, describe, option, user } from '@argon-sdk/core'\n\nconst ping = command(\n  name('ping'),\n  describe(t('ping-description')),\n).run(async (context) => {\n  await context.reply('Pong!')\n})\n\nconst greet = command(\n  name('greet'),\n  describe(t('greet-description')),\n  option(user(), name('target'), describe(t('greet-target-description'))),\n).run(async (context, opts) => {\n  await context.reply(`Hello, ${opts.target.displayName}!`)\n})\n```\n\n### 5. Register the plugin\n\n`context.t` is typed automatically via the bot's accumulated decorators — no `types.d.ts` boilerplate, no `tsconfig.json` `include` tweaks.\n\n```ts\nimport { Bot, Intent } from '@argon-sdk/core'\nimport { locales } from '@argon-sdk/locales'\n\nconst bot = new Bot(process.env.BOT_TOKEN!, {\n  intents: Intent.Messages | Intent.Commands,\n  hooks: {\n    onStart: () => {\n      for (const { locale, missing } of t.validate()) {\n        if (missing.length > 0) {\n          console.warn(`[locales] ${locale}: missing — ${missing.join(', ')}`)\n        }\n      }\n    },\n  },\n})\n\nbot\n  .plugin(locales(t))\n  .commands(ping, greet)\n  .on(message.create, async (context) => {\n    // context.t is identical to the standalone t — same function, injected by the plugin\n    await context.reply(context.t('welcome', { username: context.user.displayName }))\n  })\n```\n\n## CLI\n\n```\nargon-locales <command> [flags]\n\nCommands:\n  gen    Generate TypeScript type definitions from .ftl files\n  check  Check locale files for missing or extra keys\n\nShared flags:\n  --dir            Directory containing .ftl files\n  --defaultLocale  Default locale code (default: en)\n  -w, --watch      Re-run on file changes\n\ngen flags:\n  --out     Output path for the generated .d.ts (default: <dir>/locale-keys.d.ts)\n  --module  Module name for augmentation (default: @argon-sdk/locales)\n```\n\n```sh\n# Generate types\nargon-locales gen --dir ./locales\n\n# Check for missing / extra keys\nargon-locales check --dir ./locales\n\n# Watch mode\nargon-locales gen --dir ./locales --watch\n```\n\n## Type Safety\n\nAfter running `gen`, your IDE autocompletes every key:\n\n```ts\nt('')  // → IDE shows: 'ping-description' | 'welcome' | ...\n```\n\nKeys with Fluent variables require typed arguments — missing or wrong args are a compile error:\n\n```ts\nt('welcome', { username: 'Alice' })  // ✓\nt('welcome')                         // ✗ — args required\nt('welcome', { name: 'Alice' })      // ✗ — 'name' is not 'username'\nt('ping-description', { foo: 1 })    // ✗ — this key takes no args\n```\n\n## Fluent Syntax\n\nAny valid `.ftl` syntax works — the full `@fluent/bundle` runtime is bundled:\n\n```fluent\n# Simple placeable\ngreeting = Hello, { $name }!\n\n# Plural selector\ninbox = { $count ->\n    [one]   You have one message.\n   *[other] You have { $count } messages.\n}\n\n# Gender selector\nshared = { $actor } shared { $photoCount ->\n    [one]   a photo\n   *[other] { $photoCount } photos\n} to { $gender ->\n    [male]   his stream.\n    [female] her stream.\n   *[other]  their stream.\n}\n\n# Multiline\nterms =\n    By continuing you agree to our\n    Terms of Service and Privacy Policy.\n```\n\n## API Reference\n\n| Export | Kind | Description |\n|---|---|---|\n| `fluent(opts)` | function | Creates a `FluentHelper` (`t`) from a directory of `.ftl` files |\n| `locales(t)` | function | Argon SDK plugin — injects `t` as `context.t` |\n| `compareLocaleKeys(a, b)` | function | Compares two key sets, returns `{ missing, extra }` |\n| `FluentHelper` | interface | The callable `t` function type |\n| `FluentOptions` | interface | Options for `fluent()` |\n| `LocaleKeyRegistry` | interface | Augmentable registry — populated by the CLI |\n| `LocaleValidationResult` | type | Return type of `t.validate()` |\n| `LocaleKeyDiff` | interface | Return type of `compareLocaleKeys()` |\n| `Locale` | const + type | Built-in locale codes (`'en'`, `'ru'`, `'hy'`) |\n\n## License\n\nMIT\n","readmeFilename":"README.md"}