import { T as ToolKey } from './tool-DA175Utm.js'; declare const refBrand: unique symbol; /** * The callback both markers expose: given the config's `default` locale, it * returns the sibling locale to forward to. {@link ref} ignores the default and * returns its fixed target; {@link todo} returns the default itself. Resolving a * marker means calling it — the translator passes in `config.default`. */ type RefCallback = (defaultLocale: string) => string; /** * A branded callback produced by {@link ref}. Forwards a locale entry to a * sibling locale's value within the same translation key, resolved lazily on * property access by invoking the callback. */ type Ref = RefCallback & { [refBrand]: true; target: Target; wasTodo: false; }; /** * A branded callback produced by {@link todo} — a {@link Ref} that defers its * target to the config's `default` (which it can't know up front), so it shares * the brand and every `ref` rule applies to it automatically. `wasTodo` only * sharpens the runtime guard's message and never participates in validation. */ type TodoRef = RefCallback & { [refBrand]: true; wasTodo: true; }; type AnyRef = Ref | TodoRef; /** * Forwards this locale's entry to another locale's value within the same * translation key — as if the target field were copied and pasted into place. * For deliberate, character-for-character identical translations. * * The target must be another locale key in the same key's object, and must not * itself be a `ref(...)`/`todo()` — both are enforced at compile time and * guarded at runtime. * * @example ```ts * define({ * submit: { * en: "Submit", * "en-gb": ref("en"), // identical to English * }, * }); * ``` * * @param target The sibling locale whose value to forward to */ declare function ref(target: Target): Ref; /** * Stubs an untranslated entry. A thin wrapper over {@link ref}: at resolve time * it forwards to `ref()`, deferring the target to the config's * `default`. Resolves to the default locale's value for that key, and because it * carries the same brand, every `ref` rule applies to it automatically. * * Enables gap-free incremental localization: add a locale, stub each missing * entry with `todo()` (the app compiles and ships on the default-locale * fallback), then replace each with a real template at your own pace. * `grep -rn 'todo()' src/` is your exact backlog. * * @example ```ts * define({ welcome: { en: msg`Hi`, fr: todo() } }); // fr falls back to the default * ``` */ declare function todo(): TodoRef; type TranslationValue = string | ((dict: never, locale?: string) => string) | AnyRef; type TranslationDict = Record>; /** * The function returned by `define(...)`. Give it the active locale and it * resolves every key to that locale's value. * * Use it to type a value that holds a translator: a prop, a context value, or a * `useTranslation` wrapper. Pin your locale union and infer the resolved * translations to keep the keys without a type assertion. * * @example ```ts * type Locale = "en" | "ja"; * * function useTranslation(translator: (locale: Locale) => T): T { * return translator(getUserLocale()); // your locale source * } * ``` */ type Translator = (locale: Locale) => { [K in keyof T]: ResolveValue; }; type ResolveValue = V extends TodoRef ? Default extends keyof Entry ? Entry[Default] : never : V extends Ref ? Target extends keyof Entry ? Entry[Target] : never : V; type ValidateDict = { [K in keyof T]: { [L in keyof T[K]]: ValidateValue; }; }; type ValidateValue = V extends TodoRef ? Default extends keyof Entry ? Entry[Default] extends AnyRef ? `❌ todo() used on the default locale "${Default & string}" — there's nothing to fall back to` : V : V : V extends Ref ? Target extends keyof Entry ? Entry[Target] extends AnyRef ? `❌ ref("${Target & string}") points at another ref() — point at a real value` : V : `❌ ref("${Target & string}") target does not exist` : V; /** * The resolved translations a {@link Translator} produces: every key mapped to * its value across the supported locales. * * @example ```ts * const translator = define({ submit: { en: "Submit", ja: "Submitto" } }); * * type T = Translation; // { submit: "Submit" | "Submitto" } * ``` */ type Translation = ReturnType; declare const msgBrand: unique symbol; /** * The branded template function produced by {@link msg}. You rarely name this * directly. It's what a `msg` interpolation resolves to inside a translation. */ type Msg = ((dict: never, locale?: string) => string) & { [msgBrand]: true; }; type TemplateKey = string | ToolKey; type UnionToIntersection = (U extends unknown ? (arg: U) => void : never) extends (arg: infer I) => void ? I : never; type NamedParam = { [P in Key]: string | number; }; type NoParams = Record; type FinalTemplateDict = [Keys] extends [never] ? NoParams : UnionToIntersection ? unknown extends V ? { [P in Name]?: V; } : { [P in Name]: V; } : Keys extends string ? NamedParam : NoParams>; type IsWidenedName = NoParams extends Record ? true : false; type LiteralName = Key extends ToolKey ? IsWidenedName extends true ? ToolKey<"❌ tool name must be a string literal, declare recipes as (name: Name)", V> : Key : IsWidenedName extends true ? "❌ msg parameter name must be a string literal" : Key; type ValidateKeys = { [I in keyof Keys]: LiteralName; }; type MsgReturn = (dict: { [K in keyof FinalTemplateDict]: FinalTemplateDict[K]; }) => string; /** * A tagged template for translations with named, type-inferred parameters. * * Interpolate a string literal for a plain named parameter, or a formatter key * from a recipe like {@link plural}/{@link num}/{@link tool}. The parameter names * and types are inferred from what you interpolate and become the argument to the * resolved template function. * * The argument is an exact object literal: every name must be a string literal * type (a name widened to `string` is a compile error), and a recipe that never * types its value makes its parameter optional. * * @example ```ts * const greet = msg`Hey ${"name"}`; * greet({ name: "Ada" }); // "Hey Ada", infers { name: string | number } * ``` */ declare function msg(strings: TemplateStringsArray, ...keys: Keys & ValidateKeys): MsgReturn; type LanguageOf = keyof Languages & string; type TranslationConfig, Default extends keyof Languages & string> = { languages: Languages; default: Default; }; /** * Creates a translator factory bound to your languages and their per-language * config. Keep this in a central `i18n.ts` and import `define`/`tool` from there. * * Each key of `languages` is a supported language; its value is that language's * config: arbitrary data your {@link tool} recipes can read (use `{}` when a * language needs none). `default` must be one of those languages and is the * locale {@link todo} falls back to. * * @returns `{ define, tool }`, both bound to this config. * * @example ```ts * // i18n.ts * export const { define, tool } = createTranslationConfig({ * languages: { en: {}, ja: {} }, * default: "en", * }); * ``` */ declare function createTranslationConfig, const Default extends keyof Languages & string>(config: TranslationConfig): { define: >>(translations: T & ValidateDict) => Translator, Default>; tool: (name: Name, format: (value: V, locale: LanguageOf, config: Languages[LanguageOf]) => string) => ToolKey; }; export { type Msg, type Ref, type TodoRef, ToolKey, type Translation, type Translator, createTranslationConfig, msg, ref, todo };