@hoardodile/i18n 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +81 -0
  3. package/dist/catalogs/ui.d.ts +2 -0
  4. package/dist/catalogs/ui.js +449 -0
  5. package/dist/catalogs/ui.js.map +1 -0
  6. package/dist/catalogs/workbench.d.ts +291 -0
  7. package/dist/catalogs/workbench.js +250 -0
  8. package/dist/catalogs/workbench.js.map +1 -0
  9. package/dist/catalogs-BF4px4Mm.d.ts +12986 -0
  10. package/dist/catalogs.d.ts +2 -0
  11. package/dist/catalogs.js +10794 -0
  12. package/dist/catalogs.js.map +1 -0
  13. package/dist/core.d.ts +32 -0
  14. package/dist/core.js +14 -0
  15. package/dist/core.js.map +1 -0
  16. package/dist/create-i18n.d.ts +35 -0
  17. package/dist/create-i18n.js +30 -0
  18. package/dist/create-i18n.js.map +1 -0
  19. package/dist/index.d.ts +42 -0
  20. package/dist/index.js +11284 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/react.d.ts +1 -0
  23. package/dist/react.js +3 -0
  24. package/dist/react.js.map +1 -0
  25. package/dist/ui-CJPMCZT7.d.ts +548 -0
  26. package/package.json +81 -0
  27. package/src/catalogs/de.json +2155 -0
  28. package/src/catalogs/en.json +2155 -0
  29. package/src/catalogs/es.json +2155 -0
  30. package/src/catalogs/ja.json +2155 -0
  31. package/src/catalogs/ui.ts +30 -0
  32. package/src/catalogs/workbench.ts +29 -0
  33. package/src/catalogs/zh.json +2155 -0
  34. package/src/catalogs.ts +31 -0
  35. package/src/core.ts +40 -0
  36. package/src/create-i18n.ts +52 -0
  37. package/src/index.ts +66 -0
  38. package/src/language.test.ts +70 -0
  39. package/src/parity.test.ts +175 -0
  40. package/src/react.ts +25 -0
  41. package/src/ui/de.json +86 -0
  42. package/src/ui/en.json +86 -0
  43. package/src/ui/es.json +86 -0
  44. package/src/ui/ja.json +86 -0
  45. package/src/ui/zh.json +86 -0
  46. package/src/workbench/de.json +45 -0
  47. package/src/workbench/en.json +45 -0
  48. package/src/workbench/es.json +45 -0
  49. package/src/workbench/ja.json +45 -0
  50. package/src/workbench/zh.json +45 -0
package/dist/core.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Locale plumbing shared by the web SPA, the Electron shell and the plugin
3
+ * SDK: the supported-language set and pure helpers. **This module must
4
+ * stay free of catalog imports** — the sandboxed preload imports
5
+ * `isSupportedLanguage` from here, and the catalogs (which weigh far
6
+ * more than this file) live in `./catalogs.ts` (`CATALOGS`,
7
+ * `catalogFor`), `./catalogs/ui.ts` (`UI_CATALOGS`, `uiCatalogFor`) plus
8
+ * the per-language JSON modules.
9
+ *
10
+ * `catalogs/*.json` (the app `translation` namespace) and `ui/*.json`
11
+ * (the shared `ui` namespace consumed by `@hoardodile/ui` and the plugin
12
+ * SDK iframes) must stay in lockstep internally: identical flat key
13
+ * sets, matching interpolation placeholders, and complete `_one`/`_other`
14
+ * pairs. `src/parity.test.ts` enforces this — run it after touching any
15
+ * catalog. `CATALOGS: Record<SupportedLanguage, typeof en>` and
16
+ * `UI_CATALOGS: Record<SupportedLanguage, typeof uiEn>` additionally
17
+ * make any key drift a compile error in `tsc`.
18
+ */
19
+ declare const SUPPORTED_LANGUAGES: readonly ["en", "zh", "ja", "de", "es"];
20
+ type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number];
21
+ declare function isSupportedLanguage(value: string): value is SupportedLanguage;
22
+ /**
23
+ * Map a BCP-47 locale string (e.g. `navigator.language`,
24
+ * `app.getLocale()`, a stored pref) onto the supported set, taking the
25
+ * base code: `"ja-JP"` → `"ja"`, `"de-DE"` → `"de"`, `"es-MX"` → `"es"`,
26
+ * `"zh-CN"`/`"zh-TW"` → `"zh"` (any Chinese base maps to the `zh`
27
+ * catalog, preserving historical behavior). Unknown or missing values
28
+ * fall back to `"en"`.
29
+ */
30
+ declare function resolveSystemLanguage(raw: string | undefined): SupportedLanguage;
31
+
32
+ export { SUPPORTED_LANGUAGES, type SupportedLanguage, isSupportedLanguage, resolveSystemLanguage };
package/dist/core.js ADDED
@@ -0,0 +1,14 @@
1
+ // src/core.ts
2
+ var SUPPORTED_LANGUAGES = ["en", "zh", "ja", "de", "es"];
3
+ function isSupportedLanguage(value) {
4
+ return SUPPORTED_LANGUAGES.includes(value);
5
+ }
6
+ function resolveSystemLanguage(raw) {
7
+ const base = raw?.toLowerCase().split("-")[0];
8
+ if (base !== void 0 && isSupportedLanguage(base)) return base;
9
+ return "en";
10
+ }
11
+
12
+ export { SUPPORTED_LANGUAGES, isSupportedLanguage, resolveSystemLanguage };
13
+ //# sourceMappingURL=core.js.map
14
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core.ts"],"names":[],"mappings":";AAkBO,IAAM,sBAAsB,CAAC,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,MAAM,IAAI;AAGzD,SAAS,oBAAoB,KAAA,EAA2C;AAC9E,EAAA,OAAQ,mBAAA,CAA0C,SAAS,KAAK,CAAA;AACjE;AAUO,SAAS,sBACf,GAAA,EACoB;AACpB,EAAA,MAAM,OAAO,GAAA,EAAK,WAAA,GAAc,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA;AAC5C,EAAA,IAAI,IAAA,KAAS,MAAA,IAAa,mBAAA,CAAoB,IAAI,GAAG,OAAO,IAAA;AAC5D,EAAA,OAAO,IAAA;AACR","file":"core.js","sourcesContent":["/**\n * Locale plumbing shared by the web SPA, the Electron shell and the plugin\n * SDK: the supported-language set and pure helpers. **This module must\n * stay free of catalog imports** — the sandboxed preload imports\n * `isSupportedLanguage` from here, and the catalogs (which weigh far\n * more than this file) live in `./catalogs.ts` (`CATALOGS`,\n * `catalogFor`), `./catalogs/ui.ts` (`UI_CATALOGS`, `uiCatalogFor`) plus\n * the per-language JSON modules.\n *\n * `catalogs/*.json` (the app `translation` namespace) and `ui/*.json`\n * (the shared `ui` namespace consumed by `@hoardodile/ui` and the plugin\n * SDK iframes) must stay in lockstep internally: identical flat key\n * sets, matching interpolation placeholders, and complete `_one`/`_other`\n * pairs. `src/parity.test.ts` enforces this — run it after touching any\n * catalog. `CATALOGS: Record<SupportedLanguage, typeof en>` and\n * `UI_CATALOGS: Record<SupportedLanguage, typeof uiEn>` additionally\n * make any key drift a compile error in `tsc`.\n */\nexport const SUPPORTED_LANGUAGES = [\"en\", \"zh\", \"ja\", \"de\", \"es\"] as const\nexport type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number]\n\nexport function isSupportedLanguage(value: string): value is SupportedLanguage {\n\treturn (SUPPORTED_LANGUAGES as readonly string[]).includes(value)\n}\n\n/**\n * Map a BCP-47 locale string (e.g. `navigator.language`,\n * `app.getLocale()`, a stored pref) onto the supported set, taking the\n * base code: `\"ja-JP\"` → `\"ja\"`, `\"de-DE\"` → `\"de\"`, `\"es-MX\"` → `\"es\"`,\n * `\"zh-CN\"`/`\"zh-TW\"` → `\"zh\"` (any Chinese base maps to the `zh`\n * catalog, preserving historical behavior). Unknown or missing values\n * fall back to `\"en\"`.\n */\nexport function resolveSystemLanguage(\n\traw: string | undefined,\n): SupportedLanguage {\n\tconst base = raw?.toLowerCase().split(\"-\")[0]\n\tif (base !== undefined && isSupportedLanguage(base)) return base\n\treturn \"en\"\n}\n"]}
@@ -0,0 +1,35 @@
1
+ import { InitOptions, i18n } from 'i18next';
2
+
3
+ /**
4
+ * The i18next instance factory every React root uses: the web SPA, the
5
+ * desktop wizard/shell pages, the workbench and the plugin SDK iframes
6
+ * all boot their instance with the same options so catalog behavior
7
+ * (fallback, plurals, interpolation, type safety) never diverges between
8
+ * surfaces.
9
+ *
10
+ * This module is deliberately free of catalog imports — plugin iframe
11
+ * bundles import the factory through this subpath and ship only the
12
+ * small `ui`/`plugin` namespaces (the full app catalog would otherwise
13
+ * be pulled into every bundle). Host surfaces use `createI18n` from
14
+ * `@hoardodile/i18n`, which wraps this factory with the shared catalogs.
15
+ *
16
+ * React-free on purpose: the Electron main process and the sandboxed
17
+ * preload keep using `catalogFor` / `uiCatalogFor` directly, and each
18
+ * React root adds its own `react-i18next` binding (e.g.
19
+ * `setI18n(instance)`).
20
+ */
21
+
22
+ type CreateI18nOptions = Omit<InitOptions, "lng" | "resources"> & {
23
+ /** Initial language; undefined lets i18next resolve its default (fallback → "en"). */
24
+ readonly lng?: string;
25
+ /** Resource map — the shared catalogs (or the smaller ui/plugin set). */
26
+ readonly resources: InitOptions["resources"];
27
+ };
28
+ /**
29
+ * Create an i18next instance with the canonical option set. Callers
30
+ * supply the resources explicitly (hosts via the `@hoardodile/i18n`
31
+ * wrapper, plugins via the SDK).
32
+ */
33
+ declare function createI18n(options: CreateI18nOptions): i18n;
34
+
35
+ export { type CreateI18nOptions, createI18n };
@@ -0,0 +1,30 @@
1
+ import i18next from 'i18next';
2
+
3
+ // src/create-i18n.ts
4
+
5
+ // src/core.ts
6
+ var SUPPORTED_LANGUAGES = ["en", "zh", "ja", "de", "es"];
7
+
8
+ // src/create-i18n.ts
9
+ function createI18n(options) {
10
+ const { lng, resources, ...rest } = options;
11
+ const instance = i18next.createInstance();
12
+ void instance.init({
13
+ resources,
14
+ lng,
15
+ fallbackLng: "en",
16
+ supportedLngs: [...SUPPORTED_LANGUAGES],
17
+ nonExplicitSupportedLngs: true,
18
+ interpolation: { escapeValue: false },
19
+ returnNull: false,
20
+ returnEmptyString: false,
21
+ compatibilityJSON: "v4",
22
+ pluralSeparator: "_",
23
+ ...rest
24
+ });
25
+ return instance;
26
+ }
27
+
28
+ export { createI18n };
29
+ //# sourceMappingURL=create-i18n.js.map
30
+ //# sourceMappingURL=create-i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core.ts","../src/create-i18n.ts"],"names":[],"mappings":";;;;;AAkBO,IAAM,sBAAsB,CAAC,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,MAAM,IAAI,CAAA;;;ACgBzD,SAAS,WAAW,OAAA,EAA0C;AACpE,EAAA,MAAM,EAAE,GAAA,EAAK,SAAA,EAAW,GAAG,MAAK,GAAI,OAAA;AACpC,EAAA,MAAM,QAAA,GAAW,QAAQ,cAAA,EAAe;AACxC,EAAA,KAAK,SAAS,IAAA,CAAK;AAAA,IAClB,SAAA;AAAA,IACA,GAAA;AAAA,IACA,WAAA,EAAa,IAAA;AAAA,IACb,aAAA,EAAe,CAAC,GAAG,mBAAmB,CAAA;AAAA,IACtC,wBAAA,EAA0B,IAAA;AAAA,IAC1B,aAAA,EAAe,EAAE,WAAA,EAAa,KAAA,EAAM;AAAA,IACpC,UAAA,EAAY,KAAA;AAAA,IACZ,iBAAA,EAAmB,KAAA;AAAA,IACnB,iBAAA,EAAmB,IAAA;AAAA,IACnB,eAAA,EAAiB,GAAA;AAAA,IACjB,GAAG;AAAA,GACmB,CAAA;AACvB,EAAA,OAAO,QAAA;AACR","file":"create-i18n.js","sourcesContent":["/**\n * Locale plumbing shared by the web SPA, the Electron shell and the plugin\n * SDK: the supported-language set and pure helpers. **This module must\n * stay free of catalog imports** — the sandboxed preload imports\n * `isSupportedLanguage` from here, and the catalogs (which weigh far\n * more than this file) live in `./catalogs.ts` (`CATALOGS`,\n * `catalogFor`), `./catalogs/ui.ts` (`UI_CATALOGS`, `uiCatalogFor`) plus\n * the per-language JSON modules.\n *\n * `catalogs/*.json` (the app `translation` namespace) and `ui/*.json`\n * (the shared `ui` namespace consumed by `@hoardodile/ui` and the plugin\n * SDK iframes) must stay in lockstep internally: identical flat key\n * sets, matching interpolation placeholders, and complete `_one`/`_other`\n * pairs. `src/parity.test.ts` enforces this — run it after touching any\n * catalog. `CATALOGS: Record<SupportedLanguage, typeof en>` and\n * `UI_CATALOGS: Record<SupportedLanguage, typeof uiEn>` additionally\n * make any key drift a compile error in `tsc`.\n */\nexport const SUPPORTED_LANGUAGES = [\"en\", \"zh\", \"ja\", \"de\", \"es\"] as const\nexport type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number]\n\nexport function isSupportedLanguage(value: string): value is SupportedLanguage {\n\treturn (SUPPORTED_LANGUAGES as readonly string[]).includes(value)\n}\n\n/**\n * Map a BCP-47 locale string (e.g. `navigator.language`,\n * `app.getLocale()`, a stored pref) onto the supported set, taking the\n * base code: `\"ja-JP\"` → `\"ja\"`, `\"de-DE\"` → `\"de\"`, `\"es-MX\"` → `\"es\"`,\n * `\"zh-CN\"`/`\"zh-TW\"` → `\"zh\"` (any Chinese base maps to the `zh`\n * catalog, preserving historical behavior). Unknown or missing values\n * fall back to `\"en\"`.\n */\nexport function resolveSystemLanguage(\n\traw: string | undefined,\n): SupportedLanguage {\n\tconst base = raw?.toLowerCase().split(\"-\")[0]\n\tif (base !== undefined && isSupportedLanguage(base)) return base\n\treturn \"en\"\n}\n","/**\n * The i18next instance factory every React root uses: the web SPA, the\n * desktop wizard/shell pages, the workbench and the plugin SDK iframes\n * all boot their instance with the same options so catalog behavior\n * (fallback, plurals, interpolation, type safety) never diverges between\n * surfaces.\n *\n * This module is deliberately free of catalog imports — plugin iframe\n * bundles import the factory through this subpath and ship only the\n * small `ui`/`plugin` namespaces (the full app catalog would otherwise\n * be pulled into every bundle). Host surfaces use `createI18n` from\n * `@hoardodile/i18n`, which wraps this factory with the shared catalogs.\n *\n * React-free on purpose: the Electron main process and the sandboxed\n * preload keep using `catalogFor` / `uiCatalogFor` directly, and each\n * React root adds its own `react-i18next` binding (e.g.\n * `setI18n(instance)`).\n */\n\nimport i18next, { type i18n as I18nInstance, type InitOptions } from \"i18next\"\nimport { SUPPORTED_LANGUAGES } from \"./core.ts\"\n\nexport type CreateI18nOptions = Omit<InitOptions, \"lng\" | \"resources\"> & {\n\t/** Initial language; undefined lets i18next resolve its default (fallback → \"en\"). */\n\treadonly lng?: string\n\t/** Resource map — the shared catalogs (or the smaller ui/plugin set). */\n\treadonly resources: InitOptions[\"resources\"]\n}\n\n/**\n * Create an i18next instance with the canonical option set. Callers\n * supply the resources explicitly (hosts via the `@hoardodile/i18n`\n * wrapper, plugins via the SDK).\n */\nexport function createI18n(options: CreateI18nOptions): I18nInstance {\n\tconst { lng, resources, ...rest } = options\n\tconst instance = i18next.createInstance()\n\tvoid instance.init({\n\t\tresources,\n\t\tlng,\n\t\tfallbackLng: \"en\",\n\t\tsupportedLngs: [...SUPPORTED_LANGUAGES],\n\t\tnonExplicitSupportedLngs: true,\n\t\tinterpolation: { escapeValue: false },\n\t\treturnNull: false,\n\t\treturnEmptyString: false,\n\t\tcompatibilityJSON: \"v4\",\n\t\tpluralSeparator: \"_\",\n\t\t...rest,\n\t} satisfies InitOptions)\n\treturn instance\n}\n"]}
@@ -0,0 +1,42 @@
1
+ import { e as en } from './catalogs-BF4px4Mm.js';
2
+ export { C as CATALOGS, c as catalogFor } from './catalogs-BF4px4Mm.js';
3
+ import { u as uiEn } from './ui-CJPMCZT7.js';
4
+ export { U as UI_CATALOGS, a as uiCatalogFor } from './ui-CJPMCZT7.js';
5
+ import { i18n } from 'i18next';
6
+ import { CreateI18nOptions } from './create-i18n.js';
7
+ export { SUPPORTED_LANGUAGES, SupportedLanguage, isSupportedLanguage, resolveSystemLanguage } from './core.js';
8
+
9
+ /**
10
+ * Type the `t()` keys of every consumer against the catalogs: a wrong key
11
+ * (typo or a key added to one catalog but not the others) becomes a
12
+ * compile error instead of a silently rendered key name. Declared once
13
+ * here so the web SPA, the desktop surfaces, the workbench and the plugin
14
+ * SDK all resolve the same resources. The `plugin` namespace is typed
15
+ * loosely on purpose — its strings are authored per plugin (their
16
+ * bundles vary), and `@hoardodile/sdk-react`'s `useTranslation` wrapper
17
+ * returns that loose signature to plugin code.
18
+ */
19
+ declare module "i18next" {
20
+ interface CustomTypeOptions {
21
+ defaultNS: "translation";
22
+ resources: {
23
+ translation: typeof en;
24
+ ui: typeof uiEn;
25
+ plugin: Record<string, string>;
26
+ };
27
+ returnNull: false;
28
+ returnEmptyString: false;
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Host-surface factory: an i18next instance preloaded with the shared
34
+ * catalogs (`translation` + `ui`, all five languages). React roots boot
35
+ * it with the same options everywhere. Plugin iframes use the `createI18n`
36
+ * factory from `@hoardodile/i18n/create-i18n` instead with a resource
37
+ * subset (ui + plugin namespaces) so the full app catalog never enters
38
+ * their bundles.
39
+ */
40
+ declare function createI18n(options?: Omit<CreateI18nOptions, "resources">): i18n;
41
+
42
+ export { CreateI18nOptions, createI18n };