/** * rpiv-voice — Pi extension. Registers the `/voice` command for local voice * dictation backed by sherpa-onnx Whisper. * * UI strings localize at render time via the i18n bridge. Strings are * registered with rpiv-i18n here, once, at module init — but only when the * SDK is actually installed. If `@juicesharp/rpiv-i18n` is missing * (standalone install of just this package), the dynamic-load shim no-ops * and the bridge's `t(key, fallback)` returns the inline English literal at * every call site. The extension stays online either way. * * Adding a locale: drop `locales/.json` next to en.json (mirroring * the key set). No edit needed here — `registerLocalesFromDir` iterates * `SUPPORTED_LOCALES` from the SDK. See `@juicesharp/rpiv-i18n` README → * "Contributing translations" for the full convention. */ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { registerVoiceCommand } from "./command/voice-command.js"; import { I18N_NAMESPACE } from "./state/i18n-bridge.js"; type I18nLoader = { registerLocalesFromDir: (namespace: string, packageUrl: string, options?: { label?: string }) => void; }; // Dynamic import keeps `@juicesharp/rpiv-i18n` a soft optional peer: when the // SDK is installed alongside this package the strings register and // `/languages` flips them live; when it isn't, the import rejects here, we // no-op, and the bridge's English-fallback shim keeps the extension online. // // The `/loader` subpath is used instead of the SDK entry so the i18n-ui + // pi-tui modules are not pulled into our load graph just to register strings. try { const sdk = (await import("@juicesharp/rpiv-i18n/loader")) as I18nLoader; sdk.registerLocalesFromDir(I18N_NAMESPACE, import.meta.url, { label: "rpiv-voice" }); } catch { // SDK absent — extension still loads with English-only UI. } export default function (pi: ExtensionAPI): void { registerVoiceCommand(pi); }