lsr-text-catalog 0.1.2
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.
- package/LICENSE +21 -0
- package/README.md +184 -0
- package/dist/compiled/index.d.ts +12 -0
- package/dist/compiled/index.d.ts.map +1 -0
- package/dist/compiled/index.js +39 -0
- package/dist/compiled/index.js.map +1 -0
- package/dist/language.d.ts +4 -0
- package/dist/language.d.ts.map +1 -0
- package/dist/language.js +50 -0
- package/dist/language.js.map +1 -0
- package/dist/runtime/index.d.ts +17 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +68 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/vite/index.d.ts +21 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +559 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/manifest.d.ts +24 -0
- package/dist/vite/manifest.d.ts.map +1 -0
- package/dist/vite/manifest.js +110 -0
- package/dist/vite/manifest.js.map +1 -0
- package/dist/vite/transform.d.ts +5 -0
- package/dist/vite/transform.d.ts.map +1 -0
- package/dist/vite/transform.js +873 -0
- package/dist/vite/transform.js.map +1 -0
- package/dist/vite/types.d.ts +23 -0
- package/dist/vite/types.d.ts.map +1 -0
- package/dist/vite/types.js +2 -0
- package/dist/vite/types.js.map +1 -0
- package/package.json +99 -0
- package/src/compiled/index.ts +81 -0
- package/src/language.ts +62 -0
- package/src/runtime/index.ts +126 -0
- package/src/types.ts +55 -0
- package/src/vite/index.ts +642 -0
- package/src/vite/manifest.ts +158 -0
- package/src/vite/transform.ts +1228 -0
- package/src/vite/types.ts +27 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tomáš Vojík
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Text Catalog for Vue and Vite
|
|
2
|
+
|
|
3
|
+
`lsr-text-catalog` supplies typed Vue/gettext helpers and a Vite plugin for NEON source-copy catalogs compiled by the independently versioned [PHP package](https://packagist.org/packages/lsr/text-catalog).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install from [npm](https://www.npmjs.com/package/lsr-text-catalog) together with its Vue/gettext peers:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install lsr-text-catalog vue vue3-gettext
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For Vite integration, also install the host build tools:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install --save-dev vite @vitejs/plugin-vue typescript
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Use the PHP compiler to generate or update catalog artifacts:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
composer require lsr/text-catalog:^0.1.2
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
PHP compiler `0.1.2` introduces the unscoped TypeScript imports. Regenerate existing frontend artifacts when upgrading; do not hand-edit generated import paths.
|
|
26
|
+
|
|
27
|
+
Prebuilt frontend catalogs do not require PHP at runtime. Applications supply their own HTML sanitizer; no sanitizer package is installed automatically.
|
|
28
|
+
|
|
29
|
+
## Requirements and exports
|
|
30
|
+
|
|
31
|
+
Node `^20.19.0 || >=22.12.0`; ESM only. Host peers: Vue `^3.5.42` and vue3-gettext `^4.0.1`. `/vite` additionally needs Vite `^8.2.2` (an optional peer so prebuilt runtime consumers do not need Vite).
|
|
32
|
+
|
|
33
|
+
| Export | Responsibility |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| `lsr-text-catalog/runtime` | `createRuntimeCatalog`: typed dynamic source lookup, contextual/plural translation and guarded HTML rendering. |
|
|
36
|
+
| `lsr-text-catalog/compiled` | `createCompiledCatalog`: lookup-free contextual/plural/HTML adapters for transformed calls. |
|
|
37
|
+
| `lsr-text-catalog/types` | Reusable catalog, translation, interpolation and instance types. Consumer-specific key unions are generated locally. |
|
|
38
|
+
| `lsr-text-catalog/vite` | `textCatalog`: Node-only compiler orchestration, versioned artifact validation and literal transformation. |
|
|
39
|
+
|
|
40
|
+
Babel, Vue compilers, MagicString and TypeScript are direct dependencies because the shipped Node plugin executes them. Browser entry points do not import the Node plugin or its filesystem/compiler modules. PHP is needed only when the consumer's compiler callback invokes it, not to use prebuilt frontend data.
|
|
41
|
+
|
|
42
|
+
For local package development, build before linking a checkout with pnpm `link:`. Consumer applications should normally install a released npm version instead of a local link.
|
|
43
|
+
|
|
44
|
+
## Generate consumer-owned artifacts
|
|
45
|
+
|
|
46
|
+
Configure `Lsr\TextCatalog\TextCatalogCompiler` with explicit source/language directories, source-reference root, domain, locales, source locale, cache file, and frontend directory. Run it before standalone `tsc`/`vue-tsc` checks; Vite generation cannot supply types to a command that ran earlier.
|
|
47
|
+
|
|
48
|
+
The frontend directory contains `catalog.ts`, `catalog.compiled.ts`, and `catalog.build.json`. Generated files import this package's `/types` export, not application aliases. Keep these files in the consumer's normal TypeScript resolution graph.
|
|
49
|
+
|
|
50
|
+
## Runtime facade
|
|
51
|
+
|
|
52
|
+
Create a real consumer module such as `src/copy.ts`:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import * as generated from '../generated/catalog.js';
|
|
56
|
+
import { createRuntimeCatalog } from 'lsr-text-catalog/runtime';
|
|
57
|
+
import { sanitizeCopyHtml } from './sanitizeCopyHtml.js';
|
|
58
|
+
|
|
59
|
+
export const {
|
|
60
|
+
text, langText, langTextPlural, langHtmlText, createCatalog, installCatalog,
|
|
61
|
+
} = createRuntimeCatalog({ ...generated, sanitizeHtml: sanitizeCopyHtml });
|
|
62
|
+
export type { TextKey, HtmlTextKey } from '../generated/catalog.js';
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`sanitizeCopyHtml` is an application implementation, not a package export. Omit `sanitizeHtml` for plain-text-only consumers; HTML calls then throw rather than return raw markup.
|
|
66
|
+
|
|
67
|
+
Create and install a new instance for **each Vue app and SSR request**:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { createSSRApp } from 'vue';
|
|
71
|
+
import App from './App.vue';
|
|
72
|
+
import { createCatalog, installCatalog } from './copy.js';
|
|
73
|
+
|
|
74
|
+
const app = createSSRApp(App);
|
|
75
|
+
const copy = createCatalog({ locale: 'cs_CZ' });
|
|
76
|
+
installCatalog(app, copy);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Use the same initial locale and sanitizer output policy during SSR and hydration. The instance exposes `gettext`; changing `copy.gettext.current` updates that instance. Each instance owns cloned nested translation/plural data. Consumer facades have distinct Vue injection keys. Helpers select the current app at invocation time; outside an injection context they use a private, fixed source-language fallback. For ordinary non-Vue code needing a selected locale, call the explicit instance's helpers instead of relying on ambient state.
|
|
80
|
+
|
|
81
|
+
```vue
|
|
82
|
+
<script setup lang="ts">
|
|
83
|
+
import { computed, ref } from 'vue';
|
|
84
|
+
import { langText, langTextPlural, langHtmlText } from './copy.js';
|
|
85
|
+
|
|
86
|
+
const count = ref(3);
|
|
87
|
+
const label = computed(() => langText('example.title', { name: 'Ada' }));
|
|
88
|
+
</script>
|
|
89
|
+
|
|
90
|
+
<template>
|
|
91
|
+
<h1>{{ label }}</h1>
|
|
92
|
+
<p>{{ langTextPlural('example.count.one', 'example.count.plural', count, { count }) }}</p>
|
|
93
|
+
<div v-html="langHtmlText('example.rich', { name: 'Ada' })" />
|
|
94
|
+
</template>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`text(key)` returns canonical source text without translating/interpolating. Runtime mode accepts typed dynamic keys. Plural helpers require sibling `.one`/`.plural` entries and use their parent as gettext context. Plain text uses ordinary escaped Vue rendering. `langHtmlText` validates HTML membership at runtime, translates/interpolates, and then sanitizes. A generated `HtmlTextKey` union is available to type stricter application wrappers.
|
|
98
|
+
|
|
99
|
+
## Vite configuration
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import { execFileSync } from 'node:child_process';
|
|
103
|
+
import vue from '@vitejs/plugin-vue';
|
|
104
|
+
import { defineConfig } from 'vite';
|
|
105
|
+
import { textCatalog } from 'lsr-text-catalog/vite';
|
|
106
|
+
|
|
107
|
+
export default defineConfig({
|
|
108
|
+
plugins: [
|
|
109
|
+
textCatalog({
|
|
110
|
+
mode: 'runtime', // default; 'compiled' is explicit opt-in
|
|
111
|
+
sourceDirectory: 'copy',
|
|
112
|
+
languageDirectory: 'languages',
|
|
113
|
+
frontendDirectory: 'generated',
|
|
114
|
+
facade: 'src/copy.ts',
|
|
115
|
+
compiledFacade: 'src/copy.compiled.ts',
|
|
116
|
+
domain: 'example',
|
|
117
|
+
sourceLocale: 'en_US',
|
|
118
|
+
locales: ['en_US', 'cs_CZ'],
|
|
119
|
+
compile(root) {
|
|
120
|
+
execFileSync('php', ['compile.php'], { cwd: root, stdio: 'inherit' });
|
|
121
|
+
},
|
|
122
|
+
}),
|
|
123
|
+
vue(),
|
|
124
|
+
],
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Paths are relative to the configured Vite root (or explicit `root`) unless absolute. The callback may return a promise; the consumer owns its command, environment and bootstrap. Plugin and PHP identity/output configuration must agree. No application-specific command, domain, locale, alias or environment defaults are injected.
|
|
129
|
+
|
|
130
|
+
The plugin validates **artifact format 1**: identity, source/HTML/plural references, exact artifact-byte SHA-256 digests and the canonical generation digest. Missing/unknown formats, tampering and mixed generations fail before output is used. A successful compiler callback alone is not sufficient. Client, SSR and custom environments use the same validated generation, and stale in-flight generations are not published.
|
|
131
|
+
|
|
132
|
+
Development watches source and editable PO inputs, updates unchanged callers and evaluated SSR, and preserves ordinary Vue HMR. Build-watch mode handles nested input creation/deletion and recovery, including cleaned generated-output directories. Compilation failure blocks reads/builds until repaired; it does not silently serve the last good generation. Generated PO/output writes do not cause perpetual watch loops.
|
|
133
|
+
|
|
134
|
+
## Compiled mode
|
|
135
|
+
|
|
136
|
+
Add `src/copy.compiled.ts`:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import * as generated from '../generated/catalog.compiled.js';
|
|
140
|
+
import { createCompiledCatalog } from 'lsr-text-catalog/compiled';
|
|
141
|
+
import { sanitizeCopyHtml } from './sanitizeCopyHtml.js';
|
|
142
|
+
|
|
143
|
+
export const {
|
|
144
|
+
pgettext, npgettext, htmlPgettext, createCatalog, installCatalog,
|
|
145
|
+
} = createCompiledCatalog({ ...generated, sanitizeHtml: sanitizeCopyHtml });
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Keep authored imports pointed at `src/copy.ts`; set `mode: 'compiled'`. The plugin resolves the configured facade canonically through Vite, including aliases and symlinks, and redirects bootstrap/adapter imports to its compiled companion. It expands literal-key calls before Vue, without a runtime lookup-map fallback.
|
|
149
|
+
|
|
150
|
+
Compiled mode is deliberately stricter: dynamic keys, first-class helper escapes, unsupported import/SFC/macro forms, mismatched plurals and ineligible HTML calls are errors. Unrelated lexical bindings are not rewritten. Non-key argument evaluation order, source maps, contextual translation and interpolation are preserved. Generated compiled `text` is declaration-only and must not escape the transform into JavaScript execution.
|
|
151
|
+
|
|
152
|
+
Application sanitizers remain responsible for final-output safety in both modes, including SSR DOM lifetimes. This package does not import DOMPurify, jsdom or Inertia and supplies no application-specific HTML policy.
|
|
153
|
+
|
|
154
|
+
## Development
|
|
155
|
+
|
|
156
|
+
```sh
|
|
157
|
+
pnpm install
|
|
158
|
+
pnpm run build
|
|
159
|
+
pnpm run typecheck
|
|
160
|
+
pnpm test
|
|
161
|
+
pnpm run format:check
|
|
162
|
+
pnpm run format
|
|
163
|
+
npm pack --dry-run --ignore-scripts --json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The build emits ESM and declarations into `dist`; package exports point only at these files. `prepack` rebuilds them. The npm tarball also includes `src` so JavaScript and declaration source maps resolve to the original TypeScript. Tests cover runtime/request isolation, source-map and macro boundaries, manifest validation, real Vite client/SSR/custom-environment lifecycle and native build-watch behavior with synthetic inputs. Consumer verification should additionally exercise the actual PHP compiler and browser hydration in each supported mode.
|
|
167
|
+
|
|
168
|
+
During verification, Vite emitted an upstream browser-externalization warning for `fs` from `pofile 1.1.4`, a dependency of `vue3-gettext 4.0.1`. Both production modes and SSR hydration passed without browser console errors. The package's browser entries do not import its Node plugin; recheck the upstream warning when choosing release peer versions rather than suppressing it globally.
|
|
169
|
+
|
|
170
|
+
## Agent skill
|
|
171
|
+
|
|
172
|
+
Use the [lsr-text-catalog skill](https://github.com/Heroyt/lsr-skills/tree/master/skills/lsr-text-catalog) for generated artifacts, runtime/compiled mode selection, per-app/SSR catalog instances and application-owned sanitization.
|
|
173
|
+
|
|
174
|
+
```sh
|
|
175
|
+
npx skills add Heroyt/lsr-skills --skill lsr-text-catalog
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The skill is guidance, not a runtime dependency; installing it does not install or publish either package.
|
|
179
|
+
|
|
180
|
+
## License and maintenance
|
|
181
|
+
|
|
182
|
+
[MIT](LICENSE), copyright (c) 2026 Tomáš Vojík. Source and issue tracking: [Heroyt/lsr-text-catalog-js](https://github.com/Heroyt/lsr-text-catalog-js). npm releases are independent of PHP/Packagist releases and artifact format versions.
|
|
183
|
+
|
|
184
|
+
The manifest targets public publication on `https://registry.npmjs.org/`. Build and inspect the tarball with `npm pack` before a release; packing or creating a Git tag does not publish it. Publishing credentials and release authorization are maintainer prerequisites.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type App } from "vue";
|
|
2
|
+
import type { CatalogInstanceOptions, CatalogLanguageOptions, CompiledCatalog, InterpolationParameters } from "../types.js";
|
|
3
|
+
export type { CatalogInstanceOptions, CatalogLanguageOptions, CompiledCatalog, } from "../types.js";
|
|
4
|
+
/** Lookup-free companion facade for the compiled Vite mode. */
|
|
5
|
+
export declare function createCompiledCatalog(options: CatalogLanguageOptions): {
|
|
6
|
+
pgettext: (context: string, source: string, parameters?: InterpolationParameters) => string;
|
|
7
|
+
npgettext: (context: string, singular: string, plural: string, count: number, parameters?: InterpolationParameters) => string;
|
|
8
|
+
htmlPgettext: (context: string, source: string, parameters?: InterpolationParameters) => string;
|
|
9
|
+
createCatalog: (instance?: CatalogInstanceOptions) => CompiledCatalog;
|
|
10
|
+
installCatalog: (app: App, catalog: CompiledCatalog) => void;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compiled/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,GAAG,EAAqB,MAAM,KAAK,CAAC;AAE/E,OAAO,KAAK,EACV,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,EACf,uBAAuB,EACxB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,+DAA+D;AAC/D,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB;wBAmCxD,MAAM,UACP,MAAM,eACD,uBAAuB,KACnC,MAAM;yBAIE,MAAM,YACL,MAAM,UACR,MAAM,SACP,MAAM,eACA,uBAAuB,KACnC,MAAM;4BAUE,MAAM,UACP,MAAM,eACD,uBAAuB,KACnC,MAAM;+BAtDG,sBAAsB,KAC/B,eAAe;0BAsBW,GAAG,WAAW,eAAe,KAAG,IAAI;EAmClE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { hasInjectionContext, inject } from "vue";
|
|
2
|
+
import { languageFactory } from "../language.js";
|
|
3
|
+
/** Lookup-free companion facade for the compiled Vite mode. */
|
|
4
|
+
export function createCompiledCatalog(options) {
|
|
5
|
+
const createLanguage = languageFactory(options);
|
|
6
|
+
const sanitizeHtml = options.sanitizeHtml;
|
|
7
|
+
const key = Symbol("TextCatalog");
|
|
8
|
+
function createCatalog(instance = {}) {
|
|
9
|
+
const gettext = createLanguage(instance.locale);
|
|
10
|
+
const sanitize = instance.sanitizeHtml ?? sanitizeHtml;
|
|
11
|
+
function htmlPgettext(context, source, parameters) {
|
|
12
|
+
if (!sanitize)
|
|
13
|
+
throw new Error("Catalog HTML requires an injected sanitizeHtml function.");
|
|
14
|
+
return sanitize(gettext.$pgettext(context, source, parameters));
|
|
15
|
+
}
|
|
16
|
+
return { gettext, htmlPgettext };
|
|
17
|
+
}
|
|
18
|
+
// Private and never installed: every facade has its own fixed source-language fallback.
|
|
19
|
+
const source = createCatalog();
|
|
20
|
+
function current() {
|
|
21
|
+
return hasInjectionContext() ? inject(key, source) : source;
|
|
22
|
+
}
|
|
23
|
+
function installCatalog(app, catalog) {
|
|
24
|
+
app.provide(key, catalog);
|
|
25
|
+
app.config.globalProperties.$htmlPgettext = catalog.htmlPgettext;
|
|
26
|
+
app.use(catalog.gettext);
|
|
27
|
+
}
|
|
28
|
+
function pgettext(context, source, parameters) {
|
|
29
|
+
return current().gettext.$pgettext(context, source, parameters);
|
|
30
|
+
}
|
|
31
|
+
function npgettext(context, singular, plural, count, parameters) {
|
|
32
|
+
return current().gettext.$npgettext(context, singular, plural, count, parameters);
|
|
33
|
+
}
|
|
34
|
+
function htmlPgettext(context, source, parameters) {
|
|
35
|
+
return current().htmlPgettext(context, source, parameters);
|
|
36
|
+
}
|
|
37
|
+
return { pgettext, npgettext, htmlPgettext, createCatalog, installCatalog };
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/compiled/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAA+B,MAAM,KAAK,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAcjD,+DAA+D;AAC/D,MAAM,UAAU,qBAAqB,CAAC,OAA+B;IACnE,MAAM,cAAc,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC1C,MAAM,GAAG,GAAkC,MAAM,CAAC,aAAa,CAAC,CAAC;IAEjE,SAAS,aAAa,CACpB,WAAmC,EAAE;QAErC,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,IAAI,YAAY,CAAC;QACvD,SAAS,YAAY,CACnB,OAAe,EACf,MAAc,EACd,UAAoC;YAEpC,IAAI,CAAC,QAAQ;gBACX,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAC;YACJ,OAAO,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;IACnC,CAAC;IAED,wFAAwF;IACxF,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,SAAS,OAAO;QACd,OAAO,mBAAmB,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9D,CAAC;IACD,SAAS,cAAc,CAAC,GAAQ,EAAE,OAAwB;QACxD,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC1B,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;QACjE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,SAAS,QAAQ,CACf,OAAe,EACf,MAAc,EACd,UAAoC;QAEpC,OAAO,OAAO,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAClE,CAAC;IACD,SAAS,SAAS,CAChB,OAAe,EACf,QAAgB,EAChB,MAAc,EACd,KAAa,EACb,UAAoC;QAEpC,OAAO,OAAO,EAAE,CAAC,OAAO,CAAC,UAAU,CACjC,OAAO,EACP,QAAQ,EACR,MAAM,EACN,KAAK,EACL,UAAU,CACX,CAAC;IACJ,CAAC;IACD,SAAS,YAAY,CACnB,OAAe,EACf,MAAc,EACd,UAAoC;QAEpC,OAAO,OAAO,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CatalogLanguageOptions, Language } from "./types.js";
|
|
2
|
+
/** Capture facade identity once; never borrow an application's mutable locale. */
|
|
3
|
+
export declare function languageFactory(options: CatalogLanguageOptions): (locale?: string) => Language;
|
|
4
|
+
//# sourceMappingURL=language.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.d.ts","sourceRoot":"","sources":["../src/language.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EACtB,QAAQ,EAET,MAAM,YAAY,CAAC;AAwBpB,kFAAkF;AAClF,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,QAAQ,CA6B/B"}
|
package/dist/language.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createGettext } from "vue3-gettext";
|
|
2
|
+
/** Gettext normalizes only its outer catalog; clone every mutable nested plural array. */
|
|
3
|
+
function cloneTranslations(source) {
|
|
4
|
+
const translations = {};
|
|
5
|
+
for (const [locale, sourceMessages] of Object.entries(source)) {
|
|
6
|
+
const messages = { ...sourceMessages };
|
|
7
|
+
for (const [key, message] of Object.entries(messages)) {
|
|
8
|
+
if (typeof message === "string")
|
|
9
|
+
continue;
|
|
10
|
+
if (Array.isArray(message)) {
|
|
11
|
+
messages[key] = message.slice();
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const contexts = { ...message };
|
|
15
|
+
for (const [context, translation] of Object.entries(contexts)) {
|
|
16
|
+
if (Array.isArray(translation))
|
|
17
|
+
contexts[context] = translation.slice();
|
|
18
|
+
}
|
|
19
|
+
messages[key] = contexts;
|
|
20
|
+
}
|
|
21
|
+
translations[locale] = messages;
|
|
22
|
+
}
|
|
23
|
+
return translations;
|
|
24
|
+
}
|
|
25
|
+
/** Capture facade identity once; never borrow an application's mutable locale. */
|
|
26
|
+
export function languageFactory(options) {
|
|
27
|
+
const sourceLocale = options.sourceLocale;
|
|
28
|
+
const locales = [...options.locales];
|
|
29
|
+
if (!sourceLocale ||
|
|
30
|
+
!locales.includes(sourceLocale) ||
|
|
31
|
+
new Set(locales).size !== locales.length) {
|
|
32
|
+
throw new Error("Catalog locales must be unique and include the source locale.");
|
|
33
|
+
}
|
|
34
|
+
const availableLanguages = Object.fromEntries(locales.map((locale) => [
|
|
35
|
+
locale,
|
|
36
|
+
options.languageNames?.[locale] ?? locale,
|
|
37
|
+
]));
|
|
38
|
+
const translations = options.catalogTranslations;
|
|
39
|
+
return (locale = sourceLocale) => {
|
|
40
|
+
if (!locales.includes(locale))
|
|
41
|
+
throw new Error(`Unknown catalog locale "${locale}".`);
|
|
42
|
+
return createGettext({
|
|
43
|
+
availableLanguages: { ...availableLanguages },
|
|
44
|
+
defaultLanguage: locale,
|
|
45
|
+
sourceCodeLanguage: sourceLocale,
|
|
46
|
+
translations: cloneTranslations(translations),
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=language.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.js","sourceRoot":"","sources":["../src/language.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAO7C,0FAA0F;AAC1F,SAAS,iBAAiB,CAAC,MAAoB;IAC7C,MAAM,YAAY,GAAiB,EAAE,CAAC;IACtC,KAAK,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9D,MAAM,QAAQ,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtD,IAAI,OAAO,OAAO,KAAK,QAAQ;gBAAE,SAAS;YAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3B,QAAQ,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChC,SAAS;YACX,CAAC;YACD,MAAM,QAAQ,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;YAChC,KAAK,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC9D,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;oBAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC;YAC1E,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;QAC3B,CAAC;QACD,YAAY,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC;IAClC,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,eAAe,CAC7B,OAA+B;IAE/B,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAC1C,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrC,IACE,CAAC,YAAY;QACb,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC/B,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,EACxC,CAAC;QACD,MAAM,IAAI,KAAK,CACb,+DAA+D,CAChE,CAAC;IACJ,CAAC;IACD,MAAM,kBAAkB,GAAG,MAAM,CAAC,WAAW,CAC3C,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QACtB,MAAM;QACN,OAAO,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,IAAI,MAAM;KAC1C,CAAC,CACH,CAAC;IACF,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC;IACjD,OAAO,CAAC,MAAM,GAAG,YAAY,EAAE,EAAE;QAC/B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,IAAI,CAAC,CAAC;QACzD,OAAO,aAAa,CAAC;YACnB,kBAAkB,EAAE,EAAE,GAAG,kBAAkB,EAAE;YAC7C,eAAe,EAAE,MAAM;YACvB,kBAAkB,EAAE,YAAY;YAChC,YAAY,EAAE,iBAAiB,CAAC,YAAY,CAAC;SAC9C,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type App } from "vue";
|
|
2
|
+
import type { CatalogInstanceOptions, CatalogLanguageOptions, InterpolationParameters, RuntimeCatalog } from "../types.js";
|
|
3
|
+
export type { CatalogHelpers, CatalogInstanceOptions, CatalogLanguageOptions, RuntimeCatalog, } from "../types.js";
|
|
4
|
+
export interface RuntimeCatalogOptions<Key extends string> extends CatalogLanguageOptions {
|
|
5
|
+
readonly catalog: Readonly<Record<Key, string>>;
|
|
6
|
+
readonly htmlTextKeys: readonly NoInfer<Key>[];
|
|
7
|
+
}
|
|
8
|
+
/** One consumer-local authoring facade; each createCatalog call creates independent app/request state. */
|
|
9
|
+
export declare function createRuntimeCatalog<Key extends string>(options: RuntimeCatalogOptions<Key>): {
|
|
10
|
+
text: (key: Key) => string;
|
|
11
|
+
langText: (key: Key, parameters?: InterpolationParameters) => string;
|
|
12
|
+
langTextPlural: (singularKey: Extract<Key, `${string}.one`>, pluralKey: Extract<Key, `${string}.plural`>, count: number, parameters?: InterpolationParameters) => string;
|
|
13
|
+
langHtmlText: (key: Key, parameters?: InterpolationParameters) => string;
|
|
14
|
+
createCatalog: (instance?: CatalogInstanceOptions) => RuntimeCatalog<Key>;
|
|
15
|
+
installCatalog: (app: App, catalog: RuntimeCatalog<Key>) => void;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,GAAG,EAAqB,MAAM,KAAK,CAAC;AAE/E,OAAO,KAAK,EAEV,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACf,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,cAAc,GACf,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,qBAAqB,CACpC,GAAG,SAAS,MAAM,CAClB,SAAQ,sBAAsB;IAC9B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,SAAS,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;CAChD;AAED,0GAA0G;AAC1G,wBAAgB,oBAAoB,CAAC,GAAG,SAAS,MAAM,EACrD,OAAO,EAAE,qBAAqB,CAAC,GAAG,CAAC;gBAQhB,GAAG,KAAG,MAAM;;;;+BAOnB,sBAAsB,KAC/B,cAAc,CAAC,GAAG,CAAC;0BAuDO,GAAG,WAAW,cAAc,CAAC,GAAG,CAAC,KAAG,IAAI;EAyBtE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { hasInjectionContext, inject } from "vue";
|
|
2
|
+
import { languageFactory } from "../language.js";
|
|
3
|
+
/** One consumer-local authoring facade; each createCatalog call creates independent app/request state. */
|
|
4
|
+
export function createRuntimeCatalog(options) {
|
|
5
|
+
const createLanguage = languageFactory(options);
|
|
6
|
+
const sanitizeHtml = options.sanitizeHtml;
|
|
7
|
+
const catalog = options.catalog;
|
|
8
|
+
const htmlKeys = new Set(options.htmlTextKeys);
|
|
9
|
+
const key = Symbol("TextCatalog");
|
|
10
|
+
function text(key) {
|
|
11
|
+
if (!Object.hasOwn(catalog, key))
|
|
12
|
+
throw new Error(`Unknown catalog key "${key}".`);
|
|
13
|
+
return catalog[key];
|
|
14
|
+
}
|
|
15
|
+
function createCatalog(instance = {}) {
|
|
16
|
+
const gettext = createLanguage(instance.locale);
|
|
17
|
+
const sanitize = instance.sanitizeHtml ?? sanitizeHtml;
|
|
18
|
+
function langText(key, parameters) {
|
|
19
|
+
return gettext.$pgettext(key, text(key), parameters);
|
|
20
|
+
}
|
|
21
|
+
function langTextPlural(singularKey, pluralKey, count, parameters) {
|
|
22
|
+
const context = singularKey.slice(0, -".one".length);
|
|
23
|
+
if (!singularKey.endsWith(".one") || pluralKey !== `${context}.plural`) {
|
|
24
|
+
throw new Error('Catalog plural keys must be sibling ".one" and ".plural" entries.');
|
|
25
|
+
}
|
|
26
|
+
return gettext.$npgettext(context, text(singularKey), text(pluralKey), count, parameters);
|
|
27
|
+
}
|
|
28
|
+
function langHtmlText(key, parameters) {
|
|
29
|
+
if (!htmlKeys.has(key))
|
|
30
|
+
throw new Error(`Catalog key "${key}" is not declared as HTML.`);
|
|
31
|
+
if (!sanitize)
|
|
32
|
+
throw new Error("Catalog HTML requires an injected sanitizeHtml function.");
|
|
33
|
+
return sanitize(langText(key, parameters));
|
|
34
|
+
}
|
|
35
|
+
return { gettext, langText, langTextPlural, langHtmlText };
|
|
36
|
+
}
|
|
37
|
+
// Do not expose or install the source translator: its locale must remain fixed.
|
|
38
|
+
const { langText: sourceText, langTextPlural: sourcePlural, langHtmlText: sourceHtml, } = createCatalog();
|
|
39
|
+
const source = Object.freeze({
|
|
40
|
+
langText: sourceText,
|
|
41
|
+
langTextPlural: sourcePlural,
|
|
42
|
+
langHtmlText: sourceHtml,
|
|
43
|
+
});
|
|
44
|
+
function current() {
|
|
45
|
+
return hasInjectionContext() ? inject(key, source) : source;
|
|
46
|
+
}
|
|
47
|
+
function installCatalog(app, catalog) {
|
|
48
|
+
app.provide(key, catalog);
|
|
49
|
+
app.config.globalProperties.$langText = catalog.langText;
|
|
50
|
+
app.config.globalProperties.$langTextPlural = catalog.langTextPlural;
|
|
51
|
+
app.config.globalProperties.$langHtmlText = catalog.langHtmlText;
|
|
52
|
+
app.use(catalog.gettext);
|
|
53
|
+
}
|
|
54
|
+
const langText = (key, parameters) => current().langText(key, parameters);
|
|
55
|
+
const langTextPlural = (one, plural, count, parameters) => current().langTextPlural(one, plural, count, parameters);
|
|
56
|
+
const langHtmlText = (key, parameters) => current().langHtmlText(key, parameters);
|
|
57
|
+
return {
|
|
58
|
+
text,
|
|
59
|
+
langText,
|
|
60
|
+
langTextPlural,
|
|
61
|
+
langHtmlText,
|
|
62
|
+
createCatalog,
|
|
63
|
+
installCatalog,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Consumer facades can augment these with their catalog-specific key types instead.
|
|
67
|
+
// The package does not install a global catalog or globally claim one app's key union.
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Language, Translations } from "vue3-gettext";
|
|
2
|
+
export type { Language, Translations } from "vue3-gettext";
|
|
3
|
+
export type InterpolationParameters = Record<string, string | number>;
|
|
4
|
+
export type HtmlSanitizer = (html: string) => string;
|
|
5
|
+
export interface CatalogLanguageOptions {
|
|
6
|
+
readonly catalogTranslations: Translations;
|
|
7
|
+
readonly sourceLocale: string;
|
|
8
|
+
readonly locales: readonly string[];
|
|
9
|
+
/** Optional display names; locale identifiers are used by default. */
|
|
10
|
+
readonly languageNames?: Readonly<Record<string, string>>;
|
|
11
|
+
/** Required whenever HTML is rendered, including outside an installed app. */
|
|
12
|
+
readonly sanitizeHtml?: HtmlSanitizer;
|
|
13
|
+
}
|
|
14
|
+
export interface CatalogInstanceOptions {
|
|
15
|
+
readonly locale?: string;
|
|
16
|
+
/** Override the facade's sanitizer for this app/request only. */
|
|
17
|
+
readonly sanitizeHtml?: HtmlSanitizer;
|
|
18
|
+
}
|
|
19
|
+
export interface CatalogHelpers<Key extends string> {
|
|
20
|
+
langText(key: Key, parameters?: InterpolationParameters): string;
|
|
21
|
+
langTextPlural(singularKey: Extract<Key, `${string}.one`>, pluralKey: Extract<Key, `${string}.plural`>, count: number, parameters?: InterpolationParameters): string;
|
|
22
|
+
langHtmlText(key: Key, parameters?: InterpolationParameters): string;
|
|
23
|
+
}
|
|
24
|
+
/** Extend Vue's ComponentCustomProperties in the consumer facade to type its template globals. */
|
|
25
|
+
export interface CatalogComponentProperties<Key extends string> {
|
|
26
|
+
$langText: CatalogHelpers<Key>["langText"];
|
|
27
|
+
$langTextPlural: CatalogHelpers<Key>["langTextPlural"];
|
|
28
|
+
$langHtmlText: CatalogHelpers<Key>["langHtmlText"];
|
|
29
|
+
}
|
|
30
|
+
export interface RuntimeCatalog<Key extends string> extends CatalogHelpers<Key> {
|
|
31
|
+
gettext: Language;
|
|
32
|
+
}
|
|
33
|
+
export interface CompiledCatalog {
|
|
34
|
+
gettext: Language;
|
|
35
|
+
htmlPgettext(context: string, source: string, parameters?: InterpolationParameters): string;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE3D,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AACtE,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;AAErD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,mBAAmB,EAAE,YAAY,CAAC;IAC3C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC;CACvC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC;CACvC;AAED,MAAM,WAAW,cAAc,CAAC,GAAG,SAAS,MAAM;IAChD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAAC;IACjE,cAAc,CACZ,WAAW,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,EAC1C,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,MAAM,SAAS,CAAC,EAC3C,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,uBAAuB,GACnC,MAAM,CAAC;IACV,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAAC;CACtE;AAED,kGAAkG;AAClG,MAAM,WAAW,0BAA0B,CAAC,GAAG,SAAS,MAAM;IAC5D,SAAS,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IAC3C,eAAe,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,gBAAgB,CAAC,CAAC;IACvD,aAAa,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,cAAc,CAC7B,GAAG,SAAS,MAAM,CAClB,SAAQ,cAAc,CAAC,GAAG,CAAC;IAC3B,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,QAAQ,CAAC;IAClB,YAAY,CACV,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,uBAAuB,GACnC,MAAM,CAAC;CACX"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Plugin } from "vite";
|
|
2
|
+
import type { CatalogIdentity } from "./types.js";
|
|
3
|
+
export type TextCatalogMode = "runtime" | "compiled";
|
|
4
|
+
export interface TextCatalogOptions extends CatalogIdentity {
|
|
5
|
+
/** Preserve dynamic runtime lookups by default; opt into literal expansion explicitly. */
|
|
6
|
+
mode?: TextCatalogMode;
|
|
7
|
+
root?: string;
|
|
8
|
+
/** Input/output paths are relative to root, or absolute. No app-specific defaults. */
|
|
9
|
+
sourceDirectory: string;
|
|
10
|
+
languageDirectory: string;
|
|
11
|
+
frontendDirectory: string;
|
|
12
|
+
/** Real consumer-local authoring facade, also resolved by standalone TypeScript. */
|
|
13
|
+
facade: string;
|
|
14
|
+
/** Required in compiled mode; exports createCatalog/installCatalog and gettext adapters. */
|
|
15
|
+
compiledFacade?: string;
|
|
16
|
+
/** Compile and publish all format-v1 artifacts. The host owns process/env/bootstrap choices. */
|
|
17
|
+
compile: (root: string) => void | Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
/** Generate Text catalog, optionally expanding literals before Vue, with one coherent snapshot across environments. */
|
|
20
|
+
export declare function textCatalog(options: TextCatalogOptions): Plugin;
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,MAAM,EAEZ,MAAM,MAAM,CAAC;AAGd,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,UAAU,CAAC;AAErD,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,0FAA0F;IAC1F,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gGAAgG;IAChG,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAkBD,uHAAuH;AACvH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAmkB/D"}
|