langsys-js-vue 0.1.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.
- package/CHANGELOG.md +23 -0
- package/LICENSE +21 -0
- package/README-SSR.md +211 -0
- package/README.md +307 -0
- package/dist/index.d.mts +338 -0
- package/dist/index.d.ts +338 -0
- package/dist/index.js +221 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +186 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +82 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var langsysJsTypescript = require('langsys-js-typescript');
|
|
4
|
+
var vue = require('vue');
|
|
5
|
+
|
|
6
|
+
// src/index.ts
|
|
7
|
+
function useSignal(signal) {
|
|
8
|
+
const value = vue.shallowRef(signal.get());
|
|
9
|
+
const unsubscribe = signal.subscribe((next) => {
|
|
10
|
+
value.value = next;
|
|
11
|
+
});
|
|
12
|
+
if (vue.getCurrentScope()) vue.onScopeDispose(unsubscribe);
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
function createLocaleStore(initial = "en-US") {
|
|
16
|
+
return langsysJsTypescript.createSignal(initial);
|
|
17
|
+
}
|
|
18
|
+
function refToLocaleSource(localeRef) {
|
|
19
|
+
return {
|
|
20
|
+
get: () => localeRef.value,
|
|
21
|
+
set: (value) => {
|
|
22
|
+
localeRef.value = value;
|
|
23
|
+
},
|
|
24
|
+
update: (fn) => {
|
|
25
|
+
localeRef.value = fn(localeRef.value);
|
|
26
|
+
},
|
|
27
|
+
subscribe: (run) => {
|
|
28
|
+
const stop = vue.watch(localeRef, (value) => run(value), { flush: "sync" });
|
|
29
|
+
run(localeRef.value);
|
|
30
|
+
return stop;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function useT() {
|
|
35
|
+
return useSignal(langsysJsTypescript.tSignal);
|
|
36
|
+
}
|
|
37
|
+
function useCurrentLocale() {
|
|
38
|
+
return useSignal(langsysJsTypescript.currentlyLoadedLocale);
|
|
39
|
+
}
|
|
40
|
+
function useTranslations() {
|
|
41
|
+
return useSignal(langsysJsTypescript.sTranslations);
|
|
42
|
+
}
|
|
43
|
+
function useLocaleStore(initial = "en-US") {
|
|
44
|
+
const store = createLocaleStore(initial);
|
|
45
|
+
const locale = useSignal(store);
|
|
46
|
+
return { locale, setLocale: store.set, store };
|
|
47
|
+
}
|
|
48
|
+
var Translate = vue.defineComponent({
|
|
49
|
+
name: "Translate",
|
|
50
|
+
props: {
|
|
51
|
+
category: { type: String, default: "" },
|
|
52
|
+
custom_id: { type: String, default: "" },
|
|
53
|
+
label: { type: String, default: "" },
|
|
54
|
+
tag: { type: String, default: "translate" },
|
|
55
|
+
params: { type: Object, default: void 0 }
|
|
56
|
+
},
|
|
57
|
+
setup(props, { slots }) {
|
|
58
|
+
const host = vue.ref(null);
|
|
59
|
+
let instance;
|
|
60
|
+
const create = () => {
|
|
61
|
+
if (!host.value) return;
|
|
62
|
+
instance?.destroy();
|
|
63
|
+
instance = new langsysJsTypescript.Translate(host.value, {
|
|
64
|
+
category: props.category,
|
|
65
|
+
custom_id: props.custom_id,
|
|
66
|
+
label: props.label,
|
|
67
|
+
params: props.params
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
vue.onMounted(create);
|
|
71
|
+
vue.watch(() => [props.category, props.custom_id, props.label], create);
|
|
72
|
+
vue.watch(
|
|
73
|
+
() => props.params,
|
|
74
|
+
(params) => instance?.setParams(params),
|
|
75
|
+
{ deep: true }
|
|
76
|
+
);
|
|
77
|
+
vue.onBeforeUnmount(() => instance?.destroy());
|
|
78
|
+
return () => vue.h(props.tag, { ref: host }, slots.default?.());
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
var Phrase = vue.defineComponent({
|
|
82
|
+
name: "Phrase",
|
|
83
|
+
props: {
|
|
84
|
+
category: { type: String, default: "" },
|
|
85
|
+
params: { type: Object, default: () => ({}) },
|
|
86
|
+
tag: { type: String, default: "span" }
|
|
87
|
+
},
|
|
88
|
+
setup(props, { slots }) {
|
|
89
|
+
const host = vue.ref(null);
|
|
90
|
+
let instance;
|
|
91
|
+
const create = () => {
|
|
92
|
+
if (!host.value) return;
|
|
93
|
+
instance?.destroy();
|
|
94
|
+
instance = new langsysJsTypescript.Phrase(host.value, { category: props.category, params: props.params });
|
|
95
|
+
};
|
|
96
|
+
vue.onMounted(create);
|
|
97
|
+
vue.watch(() => props.category, create);
|
|
98
|
+
vue.watch(
|
|
99
|
+
() => props.params,
|
|
100
|
+
(params) => instance?.setParams(params),
|
|
101
|
+
{ deep: true }
|
|
102
|
+
);
|
|
103
|
+
vue.onBeforeUnmount(() => {
|
|
104
|
+
instance?.destroy();
|
|
105
|
+
instance = void 0;
|
|
106
|
+
});
|
|
107
|
+
return () => vue.h(props.tag, { ref: host, [langsysJsTypescript.PHRASE_MARKER_ATTR]: "" }, slots.default?.());
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
var DontTranslate = vue.defineComponent({
|
|
111
|
+
name: "DontTranslate",
|
|
112
|
+
props: {
|
|
113
|
+
tag: { type: String, default: "span" }
|
|
114
|
+
},
|
|
115
|
+
setup(props, { slots }) {
|
|
116
|
+
return () => vue.h(props.tag, { translate: "no", "data-ls-dont-translate": "" }, slots.default?.());
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// src/index.ts
|
|
121
|
+
var LangsysAppVue = class {
|
|
122
|
+
/** Initialize Langsys. Pass a `Signal<string>` (from `createLocaleStore`) as `UserLocaleStore`. */
|
|
123
|
+
init(config) {
|
|
124
|
+
return langsysJsTypescript.LangsysApp.init(config);
|
|
125
|
+
}
|
|
126
|
+
get Translations() {
|
|
127
|
+
return langsysJsTypescript.LangsysApp.Translations;
|
|
128
|
+
}
|
|
129
|
+
get translationsLoadingPromise() {
|
|
130
|
+
return langsysJsTypescript.LangsysApp.translationsLoadingPromise;
|
|
131
|
+
}
|
|
132
|
+
/** Current translation function. Reads fresh state on every call (not reactive on its own — use `useT()` in components). */
|
|
133
|
+
get t() {
|
|
134
|
+
return langsysJsTypescript.LangsysApp.t;
|
|
135
|
+
}
|
|
136
|
+
get debug() {
|
|
137
|
+
return langsysJsTypescript.LangsysApp.debug;
|
|
138
|
+
}
|
|
139
|
+
refresh() {
|
|
140
|
+
return langsysJsTypescript.LangsysApp.refresh();
|
|
141
|
+
}
|
|
142
|
+
getCountries(inLocale) {
|
|
143
|
+
return langsysJsTypescript.LangsysApp.getCountries(inLocale);
|
|
144
|
+
}
|
|
145
|
+
getCountryName(forCountryCode, inLocale) {
|
|
146
|
+
return langsysJsTypescript.LangsysApp.getCountryName(forCountryCode, inLocale);
|
|
147
|
+
}
|
|
148
|
+
getCurrencies(inLocale) {
|
|
149
|
+
return langsysJsTypescript.LangsysApp.getCurrencies(inLocale);
|
|
150
|
+
}
|
|
151
|
+
getCurrencyName(forCurrencyCode, inLocale) {
|
|
152
|
+
return langsysJsTypescript.LangsysApp.getCurrencyName(forCurrencyCode, inLocale);
|
|
153
|
+
}
|
|
154
|
+
getDialCodes(inLocale) {
|
|
155
|
+
return langsysJsTypescript.LangsysApp.getDialCodes(inLocale);
|
|
156
|
+
}
|
|
157
|
+
getLocales(inLocale) {
|
|
158
|
+
return langsysJsTypescript.LangsysApp.getLocales(inLocale);
|
|
159
|
+
}
|
|
160
|
+
getLocalesFlat(inLocale) {
|
|
161
|
+
return langsysJsTypescript.LangsysApp.getLocalesFlat(inLocale);
|
|
162
|
+
}
|
|
163
|
+
getLocalesData(inLocale, forceRefresh) {
|
|
164
|
+
return langsysJsTypescript.LangsysApp.getLocalesData(inLocale, forceRefresh);
|
|
165
|
+
}
|
|
166
|
+
getLocalesFormat(format = "", inLocale) {
|
|
167
|
+
return langsysJsTypescript.LangsysApp.getLocalesFormat(format, inLocale);
|
|
168
|
+
}
|
|
169
|
+
getLocaleName(forLocale, shortName, inLocale) {
|
|
170
|
+
return langsysJsTypescript.LangsysApp.getLocaleName(forLocale, shortName, inLocale);
|
|
171
|
+
}
|
|
172
|
+
getLocaleNameWithLookup(forLocale, shortName, inLocale) {
|
|
173
|
+
return langsysJsTypescript.LangsysApp.getLocaleNameWithLookup(forLocale, shortName, inLocale);
|
|
174
|
+
}
|
|
175
|
+
/** @deprecated use `getLocaleNameWithLookup` or `getLocaleName` */
|
|
176
|
+
getLanguageName(forLocale, shortName, inLocale) {
|
|
177
|
+
return langsysJsTypescript.LangsysApp.getLanguageName(forLocale, shortName, inLocale);
|
|
178
|
+
}
|
|
179
|
+
detectPreferredLocale(acceptLanguageHeader, supportedLocales) {
|
|
180
|
+
return langsysJsTypescript.LangsysApp.detectPreferredLocale(acceptLanguageHeader, supportedLocales);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
var LangsysApp = new LangsysAppVue();
|
|
184
|
+
|
|
185
|
+
Object.defineProperty(exports, "LangsysAppAPI", {
|
|
186
|
+
enumerable: true,
|
|
187
|
+
get: function () { return langsysJsTypescript.LangsysAppAPI; }
|
|
188
|
+
});
|
|
189
|
+
Object.defineProperty(exports, "canonicalizeLocale", {
|
|
190
|
+
enumerable: true,
|
|
191
|
+
get: function () { return langsysJsTypescript.canonicalizeLocale; }
|
|
192
|
+
});
|
|
193
|
+
Object.defineProperty(exports, "createSignal", {
|
|
194
|
+
enumerable: true,
|
|
195
|
+
get: function () { return langsysJsTypescript.createSignal; }
|
|
196
|
+
});
|
|
197
|
+
Object.defineProperty(exports, "currentlyLoadedLocale", {
|
|
198
|
+
enumerable: true,
|
|
199
|
+
get: function () { return langsysJsTypescript.currentlyLoadedLocale; }
|
|
200
|
+
});
|
|
201
|
+
Object.defineProperty(exports, "sTranslations", {
|
|
202
|
+
enumerable: true,
|
|
203
|
+
get: function () { return langsysJsTypescript.sTranslations; }
|
|
204
|
+
});
|
|
205
|
+
Object.defineProperty(exports, "t", {
|
|
206
|
+
enumerable: true,
|
|
207
|
+
get: function () { return langsysJsTypescript.tSignal; }
|
|
208
|
+
});
|
|
209
|
+
exports.DontTranslate = DontTranslate;
|
|
210
|
+
exports.LangsysApp = LangsysApp;
|
|
211
|
+
exports.Phrase = Phrase;
|
|
212
|
+
exports.Translate = Translate;
|
|
213
|
+
exports.createLocaleStore = createLocaleStore;
|
|
214
|
+
exports.refToLocaleSource = refToLocaleSource;
|
|
215
|
+
exports.useCurrentLocale = useCurrentLocale;
|
|
216
|
+
exports.useLocaleStore = useLocaleStore;
|
|
217
|
+
exports.useSignal = useSignal;
|
|
218
|
+
exports.useT = useT;
|
|
219
|
+
exports.useTranslations = useTranslations;
|
|
220
|
+
//# sourceMappingURL=index.js.map
|
|
221
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters.ts","../src/composables.ts","../src/components/Translate.ts","../src/components/Phrase.ts","../src/components/DontTranslate.ts","../src/index.ts"],"names":["shallowRef","getCurrentScope","onScopeDispose","createSignal","watch","tSignal","currentlyLoadedLocale","sTranslations","defineComponent","ref","VanillaTranslate","onMounted","onBeforeUnmount","h","VanillaPhrase","PHRASE_MARKER_ATTR","_LangsysApp"],"mappings":"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","file":"index.js","sourcesContent":["import { getCurrentScope, onScopeDispose, shallowRef, watch } from 'vue';\nimport type { Ref, ShallowRef } from 'vue';\nimport { createSignal, type Signal } from 'langsys-js-typescript';\n\n/**\n * Subscribe the current effect scope to a base-SDK `Signal<T>` and return its\n * value as a read-only shallow ref, updating whenever the signal changes.\n *\n * This is the Vue mirror of Svelte's `$store` auto-subscription and React's\n * `useSignal` (`useSyncExternalStore`). The base SDK's `subscribe` fires\n * synchronously with the current value and returns an unsubscribe function, so\n * the ref is seeded immediately — server-side rendering sees the value the SDK\n * seeded from `initialTranslations` with no flash of untranslated content.\n *\n * `shallowRef` is deliberate: signal payloads (`TFunction`, the catalog) must\n * not be deeply proxied — the signal replaces the whole value on every change,\n * which is exactly what a shallow ref tracks.\n *\n * When called inside a component `setup()` or an `effectScope`, the\n * subscription is disposed with the scope. Outside any scope (module level),\n * the subscription lives for the app's lifetime — fine for the SDK's global\n * singletons, but prefer calling from `setup()`.\n */\nexport function useSignal<T>(signal: Signal<T>): Readonly<ShallowRef<T>> {\n const value = shallowRef(signal.get()) as ShallowRef<T>;\n const unsubscribe = signal.subscribe((next) => {\n value.value = next;\n });\n if (getCurrentScope()) onScopeDispose(unsubscribe);\n return value;\n}\n\n/**\n * Create a reactive `Signal<string>` to hold the user's selected locale — the\n * Vue analog of Svelte's `writable('en-US')`.\n *\n * Pass the result as `UserLocaleStore` to `LangsysApp.init`, read it reactively\n * with `useSignal(store)` (or use the all-in-one `useLocaleStore` composable),\n * and switch locale with `store.set('fr-FR')`. The base SDK only ever reads and\n * subscribes to it — it never writes.\n *\n * Locale identifiers are canonicalized to BCP 47 by the base SDK (v0.3.0+), so\n * `'en-us'` still works on input — but `currentlyLoadedLocale` always emits the\n * canonical form (`'en-US'`), so prefer canonical casing to keep comparisons\n * against it straightforward.\n */\nexport function createLocaleStore(initial = 'en-US'): Signal<string> {\n return createSignal<string>(initial);\n}\n\n/**\n * Adapt an existing Vue `Ref<string>` into the SDK's `Signal<string>` contract\n * — the Vue analog of the Svelte wrapper's `adaptStore(writable)`.\n *\n * Use this when your app already owns the locale in a ref (Pinia state, a\n * composable, Nuxt's `useState`) and you want the SDK to react to it directly:\n *\n * const locale = ref('en-US');\n * LangsysApp.init({ ..., UserLocaleStore: refToLocaleSource(locale) });\n * locale.value = 'fr-FR'; // SDK loads French\n *\n * The watcher uses `flush: 'sync'` to preserve the Signal contract the SDK\n * relies on (synchronous notification, immediate first fire). The returned\n * unsubscriber stops the watcher.\n */\nexport function refToLocaleSource(localeRef: Ref<string>): Signal<string> {\n return {\n get: () => localeRef.value,\n set: (value) => {\n localeRef.value = value;\n },\n update: (fn) => {\n localeRef.value = fn(localeRef.value);\n },\n subscribe: (run) => {\n const stop = watch(localeRef, (value) => run(value), { flush: 'sync' });\n run(localeRef.value);\n return stop;\n },\n };\n}\n","import { currentlyLoadedLocale, sTranslations, tSignal } from 'langsys-js-typescript';\nimport type { Signal, TFunction, iCategories } from 'langsys-js-typescript';\nimport type { ShallowRef } from 'vue';\nimport { createLocaleStore, useSignal } from './adapters.js';\n\n/**\n * The current translation function as a reactive ref, updating whenever\n * translations or the loaded locale change. This is the Vue analog of Svelte's\n * `$t` store read and React's `useT()`.\n *\n * const t = useT();\n * // template: <h1>{{ t('Welcome to my app', 'UI') }}</h1> (auto-unwrapped)\n * // script: t.value('Welcome to my app', 'UI')\n *\n * The phrase is both the lookup key and the base-language default. Signature:\n * `t(phrase, category?, params?)`. Placeholder names in the phrase are\n * type-checked against the params object at the call site.\n */\nexport function useT(): Readonly<ShallowRef<TFunction>> {\n return useSignal(tSignal);\n}\n\n/**\n * The locale whose translations are currently loaded. This lags the\n * user-selected locale (`UserLocaleStore`) until the fetch for the new locale\n * settles, which makes it the right value to gate \"translations are ready\" UI on.\n */\nexport function useCurrentLocale(): Readonly<ShallowRef<string>> {\n return useSignal(currentlyLoadedLocale);\n}\n\n/**\n * The raw translation catalog. Rarely needed in app code — prefer `useT()`.\n * Exposed for advanced cases (inspecting which categories/phrases are loaded).\n */\nexport function useTranslations(): Readonly<ShallowRef<iCategories>> {\n return useSignal(sTranslations);\n}\n\n/**\n * All-in-one convenience for the user-locale store. Creates one\n * `Signal<string>` (the Vue analog of Svelte's `writable`), subscribes the\n * current scope to it, and returns `{ locale, setLocale, store }`.\n *\n * const { locale, setLocale, store } = useLocaleStore('en-US');\n * onMounted(() => {\n * LangsysApp.init({ projectid, key, UserLocaleStore: store });\n * });\n *\n * // template: <select :value=\"locale\" @change=\"setLocale($event.target.value)\">…\n *\n * `setup()` runs once per component instance, so the store is stable for the\n * component's lifetime and safe to hand to `LangsysApp.init`.\n */\nexport function useLocaleStore(initial = 'en-US'): {\n locale: Readonly<ShallowRef<string>>;\n setLocale: (locale: string) => void;\n store: Signal<string>;\n} {\n const store = createLocaleStore(initial);\n const locale = useSignal(store);\n return { locale, setLocale: store.set, store };\n}\n","import { defineComponent, h, onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport type { PropType } from 'vue';\nimport { Translate as VanillaTranslate, type ParamPrimitive } from 'langsys-js-typescript';\n\n/**\n * Props for the Vue `Translate` component. Mirrors the React/Svelte components\n * 1:1 — Vue passes `class` through native attribute fallthrough, so no\n * `class`/`className` prop is declared.\n */\nexport interface TranslateProps {\n /** Optional category under which tokens are registered. Helps translators disambiguate. */\n category?: string;\n /** Optional stable id for the content block. If omitted, the SDK hashes category + tokens. */\n custom_id?: string;\n /** Optional human-readable label shown in the Translation Manager. */\n label?: string;\n /** Host element tag. Defaults to a `<translate>` custom element. */\n tag?: string;\n /**\n * Interpolation params for `{name}`-style placeholders in the content —\n * same single-brace syntax as `t()`. In markup, author the placeholders as\n * `%name%` (the base SDK normalizes `%name%` → `{name}` at capture); a bare\n * `{name}` also works in Vue templates but collides with `{{ }}` and other\n * frameworks, so `%name%` is the portable form.\n */\n params?: Record<string, ParamPrimitive>;\n}\n\n/**\n * Vue wrapper around the vanilla `Translate` DOM class from\n * `langsys-js-typescript`. It renders a host element, then on mount lets the\n * vanilla class walk and tokenize the rendered children (text nodes plus\n * translatable attributes), register the content block, and re-translate on\n * locale change. On unmount it tears the instance down.\n *\n * This is the Vue analog of the React/Svelte `<Translate>` components — pure\n * mount/destroy glue. The DOM walking, content-block registration, attribute\n * harvesting, `%name%`→`{name}` normalization, and re-translation lifecycle all\n * live in the base SDK.\n *\n * The SDK mutates the rendered DOM in place, so keep the children static:\n * prose, marketing copy, CMS-rendered HTML — the content-block use case. For\n * dynamic per-string values that Vue owns and re-renders, use `useT()` instead.\n */\nexport const Translate = defineComponent({\n name: 'Translate',\n props: {\n category: { type: String, default: '' },\n custom_id: { type: String, default: '' },\n label: { type: String, default: '' },\n tag: { type: String, default: 'translate' },\n params: { type: Object as PropType<Record<string, ParamPrimitive>>, default: undefined },\n },\n setup(props, { slots }) {\n const host = ref<HTMLElement | null>(null);\n let instance: VanillaTranslate | undefined;\n\n const create = () => {\n if (!host.value) return;\n instance?.destroy();\n instance = new VanillaTranslate(host.value, {\n category: props.category,\n custom_id: props.custom_id,\n label: props.label,\n params: props.params,\n });\n };\n\n onMounted(create);\n watch(() => [props.category, props.custom_id, props.label], create);\n // Param changes (e.g. a changed count) flow through setParams without recreating.\n watch(\n () => props.params,\n (params) => instance?.setParams(params),\n { deep: true }\n );\n onBeforeUnmount(() => instance?.destroy());\n\n return () => h(props.tag, { ref: host }, slots.default?.());\n },\n});\n\nexport default Translate;\n","import { defineComponent, h, onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport type { PropType } from 'vue';\nimport { PHRASE_MARKER_ATTR, Phrase as VanillaPhrase } from 'langsys-js-typescript';\n\n/**\n * Props for the Vue `Phrase` component. Mirrors the React/Svelte components —\n * `class` flows through native attribute fallthrough.\n */\nexport interface PhraseProps {\n /** Category the phrase registers under (disambiguation for translators). */\n category?: string;\n /** Interpolation params — `{n}` for pluralization, `{name}`, etc. */\n params?: Record<string, unknown>;\n /** Host element tag. Defaults to `<span>`. */\n tag?: string;\n}\n\n/**\n * Vue wrapper around the vanilla `Phrase` rich-text handler.\n *\n * Use it to keep a markup-bearing run as ONE translatable phrase — e.g. so a\n * count variable stays next to the noun it pluralizes:\n *\n * <Phrase category=\"ProductCard\" :params=\"{ n: reviewCount }\">\n * Based on {n} <strong>reviews</strong>\n * </Phrase>\n *\n * The inline markup never reaches the translator — it's replaced with neutral\n * tokens and the real elements are reconstituted at render (see richtext.ts in\n * the base SDK). The host carries `data-ls-phrase` so a wrapping `<Translate>`\n * skips it and lets this handler own it.\n *\n * Keep children static (literal markup): the handler takes over the rendered\n * subtree. For values Vue owns and re-renders, pass them through `params`.\n */\nexport const Phrase = defineComponent({\n name: 'Phrase',\n props: {\n category: { type: String, default: '' },\n params: { type: Object as PropType<Record<string, unknown>>, default: () => ({}) },\n tag: { type: String, default: 'span' },\n },\n setup(props, { slots }) {\n const host = ref<HTMLElement | null>(null);\n let instance: VanillaPhrase | undefined;\n\n const create = () => {\n if (!host.value) return;\n instance?.destroy();\n instance = new VanillaPhrase(host.value, { category: props.category, params: props.params });\n };\n\n onMounted(create);\n // Recreate only when the category changes; param changes flow through setParams below.\n watch(() => props.category, create);\n watch(\n () => props.params,\n (params) => instance?.setParams(params),\n { deep: true }\n );\n onBeforeUnmount(() => {\n instance?.destroy();\n instance = undefined;\n });\n\n return () => h(props.tag, { ref: host, [PHRASE_MARKER_ATTR]: '' }, slots.default?.());\n },\n});\n\nexport default Phrase;\n","import { defineComponent, h } from 'vue';\n\n/**\n * Props for the Vue `DontTranslate` component. Mirrors the React/Svelte\n * components — `class` flows through native attribute fallthrough.\n */\nexport interface DontTranslateProps {\n /** Host element tag. Defaults to `<span>`. */\n tag?: string;\n}\n\n/**\n * Marks a region as never-translated, preserved verbatim:\n *\n * Built with <DontTranslate>Kangen®</DontTranslate> on\n * <DontTranslate>langsys.dev</DontTranslate>\n *\n * The host carries the standard `translate=\"no\"` attribute, which both the\n * tokenizer and the renderer in the base SDK already honor — so its content is\n * never tokenized, registered, or replaced. Pure presentational glue; no\n * vanilla handler needed.\n */\nexport const DontTranslate = defineComponent({\n name: 'DontTranslate',\n props: {\n tag: { type: String, default: 'span' },\n },\n setup(props, { slots }) {\n return () => h(props.tag, { translate: 'no', 'data-ls-dont-translate': '' }, slots.default?.());\n },\n});\n\nexport default DontTranslate;\n","/**\n * langsys-js-vue — idiomatic Vue 3 binding over `langsys-js-typescript`.\n *\n * Public API:\n * - `LangsysApp` — `init` accepts a `Signal<string>` (make one with\n * `createLocaleStore`, or adapt a ref with `refToLocaleSource`) for the\n * user locale; every other method delegates.\n * - Composables — `useT`, `useCurrentLocale`, `useTranslations`,\n * `useLocaleStore`, and the low-level `useSignal`. These are the reactive\n * layer; in components prefer them over the raw signals.\n * - `createLocaleStore` — make the user-locale store (Vue analog of Svelte's\n * `writable`); `refToLocaleSource` — adapt an existing `Ref<string>`.\n * - `Translate` — Vue component wrapping the vanilla DOM `Translate` class.\n * - Raw signals `t` / `currentlyLoadedLocale` / `sTranslations` — re-exported\n * for advanced/direct subscription outside Vue's reactivity.\n */\n\nimport {\n LangsysApp as _LangsysApp,\n type ExtractParamKeys,\n type ParamPrimitive,\n type ParamsFor,\n type Signal,\n type TArgs,\n type TFunction,\n type TranslationParams,\n type iCategories,\n type iContentBlock,\n type iCountry,\n type iCountryDialCode,\n type iCountryList,\n type iCurrency,\n type iCurrencyList,\n type iLangsysInitConfig as iVanillaInitConfig,\n type iLangsysResponse,\n type iLanguageName,\n type iLocaleData,\n type iLocaleDefault,\n type iLocaleFlat,\n type iProject,\n type iTranslations,\n} from 'langsys-js-typescript';\n\n// Reactive primitives (raw signals) — re-exported for advanced/direct\n// subscription. `tSignal` is exposed under the friendlier name `t`. In\n// components, prefer the composables (`useT`, `useCurrentLocale`, …).\nexport { currentlyLoadedLocale, createSignal, sTranslations, tSignal as t } from 'langsys-js-typescript';\n\n// Locale canonicalization (BCP 47) — the SDK canonicalizes all locale input\n// (v0.3.0+); re-exported so consumers can normalize their own values the same\n// way before comparing against `useCurrentLocale()` / `detectPreferredLocale()`.\nexport { canonicalizeLocale } from 'langsys-js-typescript';\n\n// API client (vanilla — no Vue concerns)\nexport { LangsysAppAPI } from 'langsys-js-typescript';\n\n// Composables + adapters (the Vue-idiomatic reactive layer)\nexport { createLocaleStore, refToLocaleSource, useSignal } from './adapters.js';\nexport { useCurrentLocale, useLocaleStore, useT, useTranslations } from './composables.js';\n\n// Components\nexport { Translate, type TranslateProps } from './components/Translate.js';\nexport { Phrase, type PhraseProps } from './components/Phrase.js';\nexport { DontTranslate, type DontTranslateProps } from './components/DontTranslate.js';\n\n// Type re-exports — these are framework-agnostic, so consumers can rely on them\n// directly without reaching into `langsys-js-typescript`.\nexport type {\n ExtractParamKeys,\n ParamPrimitive,\n ParamsFor,\n Signal,\n TArgs,\n TFunction,\n TranslationParams,\n iCategories,\n iContentBlock,\n iCountry,\n iCountryDialCode,\n iCountryList,\n iCurrency,\n iCurrencyList,\n iLangsysResponse,\n iLanguageName,\n iLocaleData,\n iLocaleDefault,\n iLocaleFlat,\n iProject,\n iTranslations,\n};\n\n/**\n * Vue-flavored init config. Identical to the base SDK's config except\n * `UserLocaleStore` is typed as a `Signal<string>` — create one with\n * `createLocaleStore()` (or get one from the `useLocaleStore` composable, or\n * adapt an existing ref with `refToLocaleSource`). The base SDK only reads and\n * subscribes to it.\n */\nexport interface iLangsysInitConfig extends Omit<iVanillaInitConfig, 'UserLocaleStore'> {\n UserLocaleStore: Signal<string>;\n}\n\n/**\n * Vue SDK entry point. Delegates everything to the underlying\n * `langsys-js-typescript` singleton. Because the Vue locale store is already a\n * `Signal` (unlike Svelte's `Writable`, which needs adapting), `init` is a\n * straight passthrough — the Vue-native concerns live in the composables and\n * the `<Translate>` component, not here.\n */\nclass LangsysAppVue {\n /** Initialize Langsys. Pass a `Signal<string>` (from `createLocaleStore`) as `UserLocaleStore`. */\n public init(config: iLangsysInitConfig): Promise<iLangsysResponse> {\n return _LangsysApp.init(config);\n }\n\n public get Translations() {\n return _LangsysApp.Translations;\n }\n\n public get translationsLoadingPromise() {\n return _LangsysApp.translationsLoadingPromise;\n }\n\n /** Current translation function. Reads fresh state on every call (not reactive on its own — use `useT()` in components). */\n public get t(): TFunction {\n return _LangsysApp.t;\n }\n\n public get debug() {\n return _LangsysApp.debug;\n }\n\n public refresh() {\n return _LangsysApp.refresh();\n }\n\n public getCountries(inLocale?: string) {\n return _LangsysApp.getCountries(inLocale);\n }\n public getCountryName(forCountryCode: string, inLocale?: string) {\n return _LangsysApp.getCountryName(forCountryCode, inLocale);\n }\n public getCurrencies(inLocale?: string) {\n return _LangsysApp.getCurrencies(inLocale);\n }\n public getCurrencyName(forCurrencyCode: string, inLocale?: string) {\n return _LangsysApp.getCurrencyName(forCurrencyCode, inLocale);\n }\n public getDialCodes(inLocale?: string) {\n return _LangsysApp.getDialCodes(inLocale);\n }\n\n public getLocales(inLocale?: string) {\n return _LangsysApp.getLocales(inLocale);\n }\n public getLocalesFlat(inLocale?: string) {\n return _LangsysApp.getLocalesFlat(inLocale);\n }\n public getLocalesData(inLocale?: string, forceRefresh?: boolean) {\n return _LangsysApp.getLocalesData(inLocale, forceRefresh);\n }\n public getLocalesFormat(format: '' | 'flat' | 'data' = '', inLocale?: string) {\n return _LangsysApp.getLocalesFormat(format, inLocale);\n }\n public getLocaleName(forLocale: string, shortName?: boolean, inLocale?: string) {\n return _LangsysApp.getLocaleName(forLocale, shortName, inLocale);\n }\n public getLocaleNameWithLookup(forLocale: string, shortName?: boolean, inLocale?: string) {\n return _LangsysApp.getLocaleNameWithLookup(forLocale, shortName, inLocale);\n }\n\n /** @deprecated use `getLocaleNameWithLookup` or `getLocaleName` */\n public getLanguageName(forLocale: string, shortName?: boolean, inLocale?: string) {\n return _LangsysApp.getLanguageName(forLocale, shortName, inLocale);\n }\n\n public detectPreferredLocale(acceptLanguageHeader?: string | null, supportedLocales?: string[]) {\n return _LangsysApp.detectPreferredLocale(acceptLanguageHeader, supportedLocales);\n }\n}\n\nexport const LangsysApp = new LangsysAppVue();\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { PHRASE_MARKER_ATTR, Translate as Translate$1, Phrase as Phrase$1, createSignal, tSignal, currentlyLoadedLocale, sTranslations, LangsysApp as LangsysApp$1 } from 'langsys-js-typescript';
|
|
2
|
+
export { LangsysAppAPI, canonicalizeLocale, createSignal, currentlyLoadedLocale, sTranslations, tSignal as t } from 'langsys-js-typescript';
|
|
3
|
+
import { defineComponent, ref, onMounted, watch, onBeforeUnmount, h, shallowRef, getCurrentScope, onScopeDispose } from 'vue';
|
|
4
|
+
|
|
5
|
+
// src/index.ts
|
|
6
|
+
function useSignal(signal) {
|
|
7
|
+
const value = shallowRef(signal.get());
|
|
8
|
+
const unsubscribe = signal.subscribe((next) => {
|
|
9
|
+
value.value = next;
|
|
10
|
+
});
|
|
11
|
+
if (getCurrentScope()) onScopeDispose(unsubscribe);
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
function createLocaleStore(initial = "en-US") {
|
|
15
|
+
return createSignal(initial);
|
|
16
|
+
}
|
|
17
|
+
function refToLocaleSource(localeRef) {
|
|
18
|
+
return {
|
|
19
|
+
get: () => localeRef.value,
|
|
20
|
+
set: (value) => {
|
|
21
|
+
localeRef.value = value;
|
|
22
|
+
},
|
|
23
|
+
update: (fn) => {
|
|
24
|
+
localeRef.value = fn(localeRef.value);
|
|
25
|
+
},
|
|
26
|
+
subscribe: (run) => {
|
|
27
|
+
const stop = watch(localeRef, (value) => run(value), { flush: "sync" });
|
|
28
|
+
run(localeRef.value);
|
|
29
|
+
return stop;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function useT() {
|
|
34
|
+
return useSignal(tSignal);
|
|
35
|
+
}
|
|
36
|
+
function useCurrentLocale() {
|
|
37
|
+
return useSignal(currentlyLoadedLocale);
|
|
38
|
+
}
|
|
39
|
+
function useTranslations() {
|
|
40
|
+
return useSignal(sTranslations);
|
|
41
|
+
}
|
|
42
|
+
function useLocaleStore(initial = "en-US") {
|
|
43
|
+
const store = createLocaleStore(initial);
|
|
44
|
+
const locale = useSignal(store);
|
|
45
|
+
return { locale, setLocale: store.set, store };
|
|
46
|
+
}
|
|
47
|
+
var Translate = defineComponent({
|
|
48
|
+
name: "Translate",
|
|
49
|
+
props: {
|
|
50
|
+
category: { type: String, default: "" },
|
|
51
|
+
custom_id: { type: String, default: "" },
|
|
52
|
+
label: { type: String, default: "" },
|
|
53
|
+
tag: { type: String, default: "translate" },
|
|
54
|
+
params: { type: Object, default: void 0 }
|
|
55
|
+
},
|
|
56
|
+
setup(props, { slots }) {
|
|
57
|
+
const host = ref(null);
|
|
58
|
+
let instance;
|
|
59
|
+
const create = () => {
|
|
60
|
+
if (!host.value) return;
|
|
61
|
+
instance?.destroy();
|
|
62
|
+
instance = new Translate$1(host.value, {
|
|
63
|
+
category: props.category,
|
|
64
|
+
custom_id: props.custom_id,
|
|
65
|
+
label: props.label,
|
|
66
|
+
params: props.params
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
onMounted(create);
|
|
70
|
+
watch(() => [props.category, props.custom_id, props.label], create);
|
|
71
|
+
watch(
|
|
72
|
+
() => props.params,
|
|
73
|
+
(params) => instance?.setParams(params),
|
|
74
|
+
{ deep: true }
|
|
75
|
+
);
|
|
76
|
+
onBeforeUnmount(() => instance?.destroy());
|
|
77
|
+
return () => h(props.tag, { ref: host }, slots.default?.());
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
var Phrase = defineComponent({
|
|
81
|
+
name: "Phrase",
|
|
82
|
+
props: {
|
|
83
|
+
category: { type: String, default: "" },
|
|
84
|
+
params: { type: Object, default: () => ({}) },
|
|
85
|
+
tag: { type: String, default: "span" }
|
|
86
|
+
},
|
|
87
|
+
setup(props, { slots }) {
|
|
88
|
+
const host = ref(null);
|
|
89
|
+
let instance;
|
|
90
|
+
const create = () => {
|
|
91
|
+
if (!host.value) return;
|
|
92
|
+
instance?.destroy();
|
|
93
|
+
instance = new Phrase$1(host.value, { category: props.category, params: props.params });
|
|
94
|
+
};
|
|
95
|
+
onMounted(create);
|
|
96
|
+
watch(() => props.category, create);
|
|
97
|
+
watch(
|
|
98
|
+
() => props.params,
|
|
99
|
+
(params) => instance?.setParams(params),
|
|
100
|
+
{ deep: true }
|
|
101
|
+
);
|
|
102
|
+
onBeforeUnmount(() => {
|
|
103
|
+
instance?.destroy();
|
|
104
|
+
instance = void 0;
|
|
105
|
+
});
|
|
106
|
+
return () => h(props.tag, { ref: host, [PHRASE_MARKER_ATTR]: "" }, slots.default?.());
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
var DontTranslate = defineComponent({
|
|
110
|
+
name: "DontTranslate",
|
|
111
|
+
props: {
|
|
112
|
+
tag: { type: String, default: "span" }
|
|
113
|
+
},
|
|
114
|
+
setup(props, { slots }) {
|
|
115
|
+
return () => h(props.tag, { translate: "no", "data-ls-dont-translate": "" }, slots.default?.());
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// src/index.ts
|
|
120
|
+
var LangsysAppVue = class {
|
|
121
|
+
/** Initialize Langsys. Pass a `Signal<string>` (from `createLocaleStore`) as `UserLocaleStore`. */
|
|
122
|
+
init(config) {
|
|
123
|
+
return LangsysApp$1.init(config);
|
|
124
|
+
}
|
|
125
|
+
get Translations() {
|
|
126
|
+
return LangsysApp$1.Translations;
|
|
127
|
+
}
|
|
128
|
+
get translationsLoadingPromise() {
|
|
129
|
+
return LangsysApp$1.translationsLoadingPromise;
|
|
130
|
+
}
|
|
131
|
+
/** Current translation function. Reads fresh state on every call (not reactive on its own — use `useT()` in components). */
|
|
132
|
+
get t() {
|
|
133
|
+
return LangsysApp$1.t;
|
|
134
|
+
}
|
|
135
|
+
get debug() {
|
|
136
|
+
return LangsysApp$1.debug;
|
|
137
|
+
}
|
|
138
|
+
refresh() {
|
|
139
|
+
return LangsysApp$1.refresh();
|
|
140
|
+
}
|
|
141
|
+
getCountries(inLocale) {
|
|
142
|
+
return LangsysApp$1.getCountries(inLocale);
|
|
143
|
+
}
|
|
144
|
+
getCountryName(forCountryCode, inLocale) {
|
|
145
|
+
return LangsysApp$1.getCountryName(forCountryCode, inLocale);
|
|
146
|
+
}
|
|
147
|
+
getCurrencies(inLocale) {
|
|
148
|
+
return LangsysApp$1.getCurrencies(inLocale);
|
|
149
|
+
}
|
|
150
|
+
getCurrencyName(forCurrencyCode, inLocale) {
|
|
151
|
+
return LangsysApp$1.getCurrencyName(forCurrencyCode, inLocale);
|
|
152
|
+
}
|
|
153
|
+
getDialCodes(inLocale) {
|
|
154
|
+
return LangsysApp$1.getDialCodes(inLocale);
|
|
155
|
+
}
|
|
156
|
+
getLocales(inLocale) {
|
|
157
|
+
return LangsysApp$1.getLocales(inLocale);
|
|
158
|
+
}
|
|
159
|
+
getLocalesFlat(inLocale) {
|
|
160
|
+
return LangsysApp$1.getLocalesFlat(inLocale);
|
|
161
|
+
}
|
|
162
|
+
getLocalesData(inLocale, forceRefresh) {
|
|
163
|
+
return LangsysApp$1.getLocalesData(inLocale, forceRefresh);
|
|
164
|
+
}
|
|
165
|
+
getLocalesFormat(format = "", inLocale) {
|
|
166
|
+
return LangsysApp$1.getLocalesFormat(format, inLocale);
|
|
167
|
+
}
|
|
168
|
+
getLocaleName(forLocale, shortName, inLocale) {
|
|
169
|
+
return LangsysApp$1.getLocaleName(forLocale, shortName, inLocale);
|
|
170
|
+
}
|
|
171
|
+
getLocaleNameWithLookup(forLocale, shortName, inLocale) {
|
|
172
|
+
return LangsysApp$1.getLocaleNameWithLookup(forLocale, shortName, inLocale);
|
|
173
|
+
}
|
|
174
|
+
/** @deprecated use `getLocaleNameWithLookup` or `getLocaleName` */
|
|
175
|
+
getLanguageName(forLocale, shortName, inLocale) {
|
|
176
|
+
return LangsysApp$1.getLanguageName(forLocale, shortName, inLocale);
|
|
177
|
+
}
|
|
178
|
+
detectPreferredLocale(acceptLanguageHeader, supportedLocales) {
|
|
179
|
+
return LangsysApp$1.detectPreferredLocale(acceptLanguageHeader, supportedLocales);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
var LangsysApp = new LangsysAppVue();
|
|
183
|
+
|
|
184
|
+
export { DontTranslate, LangsysApp, Phrase, Translate, createLocaleStore, refToLocaleSource, useCurrentLocale, useLocaleStore, useSignal, useT, useTranslations };
|
|
185
|
+
//# sourceMappingURL=index.mjs.map
|
|
186
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters.ts","../src/composables.ts","../src/components/Translate.ts","../src/components/Phrase.ts","../src/components/DontTranslate.ts","../src/index.ts"],"names":["VanillaTranslate","watch","defineComponent","ref","VanillaPhrase","onMounted","onBeforeUnmount","h","_LangsysApp"],"mappings":"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","file":"index.mjs","sourcesContent":["import { getCurrentScope, onScopeDispose, shallowRef, watch } from 'vue';\nimport type { Ref, ShallowRef } from 'vue';\nimport { createSignal, type Signal } from 'langsys-js-typescript';\n\n/**\n * Subscribe the current effect scope to a base-SDK `Signal<T>` and return its\n * value as a read-only shallow ref, updating whenever the signal changes.\n *\n * This is the Vue mirror of Svelte's `$store` auto-subscription and React's\n * `useSignal` (`useSyncExternalStore`). The base SDK's `subscribe` fires\n * synchronously with the current value and returns an unsubscribe function, so\n * the ref is seeded immediately — server-side rendering sees the value the SDK\n * seeded from `initialTranslations` with no flash of untranslated content.\n *\n * `shallowRef` is deliberate: signal payloads (`TFunction`, the catalog) must\n * not be deeply proxied — the signal replaces the whole value on every change,\n * which is exactly what a shallow ref tracks.\n *\n * When called inside a component `setup()` or an `effectScope`, the\n * subscription is disposed with the scope. Outside any scope (module level),\n * the subscription lives for the app's lifetime — fine for the SDK's global\n * singletons, but prefer calling from `setup()`.\n */\nexport function useSignal<T>(signal: Signal<T>): Readonly<ShallowRef<T>> {\n const value = shallowRef(signal.get()) as ShallowRef<T>;\n const unsubscribe = signal.subscribe((next) => {\n value.value = next;\n });\n if (getCurrentScope()) onScopeDispose(unsubscribe);\n return value;\n}\n\n/**\n * Create a reactive `Signal<string>` to hold the user's selected locale — the\n * Vue analog of Svelte's `writable('en-US')`.\n *\n * Pass the result as `UserLocaleStore` to `LangsysApp.init`, read it reactively\n * with `useSignal(store)` (or use the all-in-one `useLocaleStore` composable),\n * and switch locale with `store.set('fr-FR')`. The base SDK only ever reads and\n * subscribes to it — it never writes.\n *\n * Locale identifiers are canonicalized to BCP 47 by the base SDK (v0.3.0+), so\n * `'en-us'` still works on input — but `currentlyLoadedLocale` always emits the\n * canonical form (`'en-US'`), so prefer canonical casing to keep comparisons\n * against it straightforward.\n */\nexport function createLocaleStore(initial = 'en-US'): Signal<string> {\n return createSignal<string>(initial);\n}\n\n/**\n * Adapt an existing Vue `Ref<string>` into the SDK's `Signal<string>` contract\n * — the Vue analog of the Svelte wrapper's `adaptStore(writable)`.\n *\n * Use this when your app already owns the locale in a ref (Pinia state, a\n * composable, Nuxt's `useState`) and you want the SDK to react to it directly:\n *\n * const locale = ref('en-US');\n * LangsysApp.init({ ..., UserLocaleStore: refToLocaleSource(locale) });\n * locale.value = 'fr-FR'; // SDK loads French\n *\n * The watcher uses `flush: 'sync'` to preserve the Signal contract the SDK\n * relies on (synchronous notification, immediate first fire). The returned\n * unsubscriber stops the watcher.\n */\nexport function refToLocaleSource(localeRef: Ref<string>): Signal<string> {\n return {\n get: () => localeRef.value,\n set: (value) => {\n localeRef.value = value;\n },\n update: (fn) => {\n localeRef.value = fn(localeRef.value);\n },\n subscribe: (run) => {\n const stop = watch(localeRef, (value) => run(value), { flush: 'sync' });\n run(localeRef.value);\n return stop;\n },\n };\n}\n","import { currentlyLoadedLocale, sTranslations, tSignal } from 'langsys-js-typescript';\nimport type { Signal, TFunction, iCategories } from 'langsys-js-typescript';\nimport type { ShallowRef } from 'vue';\nimport { createLocaleStore, useSignal } from './adapters.js';\n\n/**\n * The current translation function as a reactive ref, updating whenever\n * translations or the loaded locale change. This is the Vue analog of Svelte's\n * `$t` store read and React's `useT()`.\n *\n * const t = useT();\n * // template: <h1>{{ t('Welcome to my app', 'UI') }}</h1> (auto-unwrapped)\n * // script: t.value('Welcome to my app', 'UI')\n *\n * The phrase is both the lookup key and the base-language default. Signature:\n * `t(phrase, category?, params?)`. Placeholder names in the phrase are\n * type-checked against the params object at the call site.\n */\nexport function useT(): Readonly<ShallowRef<TFunction>> {\n return useSignal(tSignal);\n}\n\n/**\n * The locale whose translations are currently loaded. This lags the\n * user-selected locale (`UserLocaleStore`) until the fetch for the new locale\n * settles, which makes it the right value to gate \"translations are ready\" UI on.\n */\nexport function useCurrentLocale(): Readonly<ShallowRef<string>> {\n return useSignal(currentlyLoadedLocale);\n}\n\n/**\n * The raw translation catalog. Rarely needed in app code — prefer `useT()`.\n * Exposed for advanced cases (inspecting which categories/phrases are loaded).\n */\nexport function useTranslations(): Readonly<ShallowRef<iCategories>> {\n return useSignal(sTranslations);\n}\n\n/**\n * All-in-one convenience for the user-locale store. Creates one\n * `Signal<string>` (the Vue analog of Svelte's `writable`), subscribes the\n * current scope to it, and returns `{ locale, setLocale, store }`.\n *\n * const { locale, setLocale, store } = useLocaleStore('en-US');\n * onMounted(() => {\n * LangsysApp.init({ projectid, key, UserLocaleStore: store });\n * });\n *\n * // template: <select :value=\"locale\" @change=\"setLocale($event.target.value)\">…\n *\n * `setup()` runs once per component instance, so the store is stable for the\n * component's lifetime and safe to hand to `LangsysApp.init`.\n */\nexport function useLocaleStore(initial = 'en-US'): {\n locale: Readonly<ShallowRef<string>>;\n setLocale: (locale: string) => void;\n store: Signal<string>;\n} {\n const store = createLocaleStore(initial);\n const locale = useSignal(store);\n return { locale, setLocale: store.set, store };\n}\n","import { defineComponent, h, onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport type { PropType } from 'vue';\nimport { Translate as VanillaTranslate, type ParamPrimitive } from 'langsys-js-typescript';\n\n/**\n * Props for the Vue `Translate` component. Mirrors the React/Svelte components\n * 1:1 — Vue passes `class` through native attribute fallthrough, so no\n * `class`/`className` prop is declared.\n */\nexport interface TranslateProps {\n /** Optional category under which tokens are registered. Helps translators disambiguate. */\n category?: string;\n /** Optional stable id for the content block. If omitted, the SDK hashes category + tokens. */\n custom_id?: string;\n /** Optional human-readable label shown in the Translation Manager. */\n label?: string;\n /** Host element tag. Defaults to a `<translate>` custom element. */\n tag?: string;\n /**\n * Interpolation params for `{name}`-style placeholders in the content —\n * same single-brace syntax as `t()`. In markup, author the placeholders as\n * `%name%` (the base SDK normalizes `%name%` → `{name}` at capture); a bare\n * `{name}` also works in Vue templates but collides with `{{ }}` and other\n * frameworks, so `%name%` is the portable form.\n */\n params?: Record<string, ParamPrimitive>;\n}\n\n/**\n * Vue wrapper around the vanilla `Translate` DOM class from\n * `langsys-js-typescript`. It renders a host element, then on mount lets the\n * vanilla class walk and tokenize the rendered children (text nodes plus\n * translatable attributes), register the content block, and re-translate on\n * locale change. On unmount it tears the instance down.\n *\n * This is the Vue analog of the React/Svelte `<Translate>` components — pure\n * mount/destroy glue. The DOM walking, content-block registration, attribute\n * harvesting, `%name%`→`{name}` normalization, and re-translation lifecycle all\n * live in the base SDK.\n *\n * The SDK mutates the rendered DOM in place, so keep the children static:\n * prose, marketing copy, CMS-rendered HTML — the content-block use case. For\n * dynamic per-string values that Vue owns and re-renders, use `useT()` instead.\n */\nexport const Translate = defineComponent({\n name: 'Translate',\n props: {\n category: { type: String, default: '' },\n custom_id: { type: String, default: '' },\n label: { type: String, default: '' },\n tag: { type: String, default: 'translate' },\n params: { type: Object as PropType<Record<string, ParamPrimitive>>, default: undefined },\n },\n setup(props, { slots }) {\n const host = ref<HTMLElement | null>(null);\n let instance: VanillaTranslate | undefined;\n\n const create = () => {\n if (!host.value) return;\n instance?.destroy();\n instance = new VanillaTranslate(host.value, {\n category: props.category,\n custom_id: props.custom_id,\n label: props.label,\n params: props.params,\n });\n };\n\n onMounted(create);\n watch(() => [props.category, props.custom_id, props.label], create);\n // Param changes (e.g. a changed count) flow through setParams without recreating.\n watch(\n () => props.params,\n (params) => instance?.setParams(params),\n { deep: true }\n );\n onBeforeUnmount(() => instance?.destroy());\n\n return () => h(props.tag, { ref: host }, slots.default?.());\n },\n});\n\nexport default Translate;\n","import { defineComponent, h, onBeforeUnmount, onMounted, ref, watch } from 'vue';\nimport type { PropType } from 'vue';\nimport { PHRASE_MARKER_ATTR, Phrase as VanillaPhrase } from 'langsys-js-typescript';\n\n/**\n * Props for the Vue `Phrase` component. Mirrors the React/Svelte components —\n * `class` flows through native attribute fallthrough.\n */\nexport interface PhraseProps {\n /** Category the phrase registers under (disambiguation for translators). */\n category?: string;\n /** Interpolation params — `{n}` for pluralization, `{name}`, etc. */\n params?: Record<string, unknown>;\n /** Host element tag. Defaults to `<span>`. */\n tag?: string;\n}\n\n/**\n * Vue wrapper around the vanilla `Phrase` rich-text handler.\n *\n * Use it to keep a markup-bearing run as ONE translatable phrase — e.g. so a\n * count variable stays next to the noun it pluralizes:\n *\n * <Phrase category=\"ProductCard\" :params=\"{ n: reviewCount }\">\n * Based on {n} <strong>reviews</strong>\n * </Phrase>\n *\n * The inline markup never reaches the translator — it's replaced with neutral\n * tokens and the real elements are reconstituted at render (see richtext.ts in\n * the base SDK). The host carries `data-ls-phrase` so a wrapping `<Translate>`\n * skips it and lets this handler own it.\n *\n * Keep children static (literal markup): the handler takes over the rendered\n * subtree. For values Vue owns and re-renders, pass them through `params`.\n */\nexport const Phrase = defineComponent({\n name: 'Phrase',\n props: {\n category: { type: String, default: '' },\n params: { type: Object as PropType<Record<string, unknown>>, default: () => ({}) },\n tag: { type: String, default: 'span' },\n },\n setup(props, { slots }) {\n const host = ref<HTMLElement | null>(null);\n let instance: VanillaPhrase | undefined;\n\n const create = () => {\n if (!host.value) return;\n instance?.destroy();\n instance = new VanillaPhrase(host.value, { category: props.category, params: props.params });\n };\n\n onMounted(create);\n // Recreate only when the category changes; param changes flow through setParams below.\n watch(() => props.category, create);\n watch(\n () => props.params,\n (params) => instance?.setParams(params),\n { deep: true }\n );\n onBeforeUnmount(() => {\n instance?.destroy();\n instance = undefined;\n });\n\n return () => h(props.tag, { ref: host, [PHRASE_MARKER_ATTR]: '' }, slots.default?.());\n },\n});\n\nexport default Phrase;\n","import { defineComponent, h } from 'vue';\n\n/**\n * Props for the Vue `DontTranslate` component. Mirrors the React/Svelte\n * components — `class` flows through native attribute fallthrough.\n */\nexport interface DontTranslateProps {\n /** Host element tag. Defaults to `<span>`. */\n tag?: string;\n}\n\n/**\n * Marks a region as never-translated, preserved verbatim:\n *\n * Built with <DontTranslate>Kangen®</DontTranslate> on\n * <DontTranslate>langsys.dev</DontTranslate>\n *\n * The host carries the standard `translate=\"no\"` attribute, which both the\n * tokenizer and the renderer in the base SDK already honor — so its content is\n * never tokenized, registered, or replaced. Pure presentational glue; no\n * vanilla handler needed.\n */\nexport const DontTranslate = defineComponent({\n name: 'DontTranslate',\n props: {\n tag: { type: String, default: 'span' },\n },\n setup(props, { slots }) {\n return () => h(props.tag, { translate: 'no', 'data-ls-dont-translate': '' }, slots.default?.());\n },\n});\n\nexport default DontTranslate;\n","/**\n * langsys-js-vue — idiomatic Vue 3 binding over `langsys-js-typescript`.\n *\n * Public API:\n * - `LangsysApp` — `init` accepts a `Signal<string>` (make one with\n * `createLocaleStore`, or adapt a ref with `refToLocaleSource`) for the\n * user locale; every other method delegates.\n * - Composables — `useT`, `useCurrentLocale`, `useTranslations`,\n * `useLocaleStore`, and the low-level `useSignal`. These are the reactive\n * layer; in components prefer them over the raw signals.\n * - `createLocaleStore` — make the user-locale store (Vue analog of Svelte's\n * `writable`); `refToLocaleSource` — adapt an existing `Ref<string>`.\n * - `Translate` — Vue component wrapping the vanilla DOM `Translate` class.\n * - Raw signals `t` / `currentlyLoadedLocale` / `sTranslations` — re-exported\n * for advanced/direct subscription outside Vue's reactivity.\n */\n\nimport {\n LangsysApp as _LangsysApp,\n type ExtractParamKeys,\n type ParamPrimitive,\n type ParamsFor,\n type Signal,\n type TArgs,\n type TFunction,\n type TranslationParams,\n type iCategories,\n type iContentBlock,\n type iCountry,\n type iCountryDialCode,\n type iCountryList,\n type iCurrency,\n type iCurrencyList,\n type iLangsysInitConfig as iVanillaInitConfig,\n type iLangsysResponse,\n type iLanguageName,\n type iLocaleData,\n type iLocaleDefault,\n type iLocaleFlat,\n type iProject,\n type iTranslations,\n} from 'langsys-js-typescript';\n\n// Reactive primitives (raw signals) — re-exported for advanced/direct\n// subscription. `tSignal` is exposed under the friendlier name `t`. In\n// components, prefer the composables (`useT`, `useCurrentLocale`, …).\nexport { currentlyLoadedLocale, createSignal, sTranslations, tSignal as t } from 'langsys-js-typescript';\n\n// Locale canonicalization (BCP 47) — the SDK canonicalizes all locale input\n// (v0.3.0+); re-exported so consumers can normalize their own values the same\n// way before comparing against `useCurrentLocale()` / `detectPreferredLocale()`.\nexport { canonicalizeLocale } from 'langsys-js-typescript';\n\n// API client (vanilla — no Vue concerns)\nexport { LangsysAppAPI } from 'langsys-js-typescript';\n\n// Composables + adapters (the Vue-idiomatic reactive layer)\nexport { createLocaleStore, refToLocaleSource, useSignal } from './adapters.js';\nexport { useCurrentLocale, useLocaleStore, useT, useTranslations } from './composables.js';\n\n// Components\nexport { Translate, type TranslateProps } from './components/Translate.js';\nexport { Phrase, type PhraseProps } from './components/Phrase.js';\nexport { DontTranslate, type DontTranslateProps } from './components/DontTranslate.js';\n\n// Type re-exports — these are framework-agnostic, so consumers can rely on them\n// directly without reaching into `langsys-js-typescript`.\nexport type {\n ExtractParamKeys,\n ParamPrimitive,\n ParamsFor,\n Signal,\n TArgs,\n TFunction,\n TranslationParams,\n iCategories,\n iContentBlock,\n iCountry,\n iCountryDialCode,\n iCountryList,\n iCurrency,\n iCurrencyList,\n iLangsysResponse,\n iLanguageName,\n iLocaleData,\n iLocaleDefault,\n iLocaleFlat,\n iProject,\n iTranslations,\n};\n\n/**\n * Vue-flavored init config. Identical to the base SDK's config except\n * `UserLocaleStore` is typed as a `Signal<string>` — create one with\n * `createLocaleStore()` (or get one from the `useLocaleStore` composable, or\n * adapt an existing ref with `refToLocaleSource`). The base SDK only reads and\n * subscribes to it.\n */\nexport interface iLangsysInitConfig extends Omit<iVanillaInitConfig, 'UserLocaleStore'> {\n UserLocaleStore: Signal<string>;\n}\n\n/**\n * Vue SDK entry point. Delegates everything to the underlying\n * `langsys-js-typescript` singleton. Because the Vue locale store is already a\n * `Signal` (unlike Svelte's `Writable`, which needs adapting), `init` is a\n * straight passthrough — the Vue-native concerns live in the composables and\n * the `<Translate>` component, not here.\n */\nclass LangsysAppVue {\n /** Initialize Langsys. Pass a `Signal<string>` (from `createLocaleStore`) as `UserLocaleStore`. */\n public init(config: iLangsysInitConfig): Promise<iLangsysResponse> {\n return _LangsysApp.init(config);\n }\n\n public get Translations() {\n return _LangsysApp.Translations;\n }\n\n public get translationsLoadingPromise() {\n return _LangsysApp.translationsLoadingPromise;\n }\n\n /** Current translation function. Reads fresh state on every call (not reactive on its own — use `useT()` in components). */\n public get t(): TFunction {\n return _LangsysApp.t;\n }\n\n public get debug() {\n return _LangsysApp.debug;\n }\n\n public refresh() {\n return _LangsysApp.refresh();\n }\n\n public getCountries(inLocale?: string) {\n return _LangsysApp.getCountries(inLocale);\n }\n public getCountryName(forCountryCode: string, inLocale?: string) {\n return _LangsysApp.getCountryName(forCountryCode, inLocale);\n }\n public getCurrencies(inLocale?: string) {\n return _LangsysApp.getCurrencies(inLocale);\n }\n public getCurrencyName(forCurrencyCode: string, inLocale?: string) {\n return _LangsysApp.getCurrencyName(forCurrencyCode, inLocale);\n }\n public getDialCodes(inLocale?: string) {\n return _LangsysApp.getDialCodes(inLocale);\n }\n\n public getLocales(inLocale?: string) {\n return _LangsysApp.getLocales(inLocale);\n }\n public getLocalesFlat(inLocale?: string) {\n return _LangsysApp.getLocalesFlat(inLocale);\n }\n public getLocalesData(inLocale?: string, forceRefresh?: boolean) {\n return _LangsysApp.getLocalesData(inLocale, forceRefresh);\n }\n public getLocalesFormat(format: '' | 'flat' | 'data' = '', inLocale?: string) {\n return _LangsysApp.getLocalesFormat(format, inLocale);\n }\n public getLocaleName(forLocale: string, shortName?: boolean, inLocale?: string) {\n return _LangsysApp.getLocaleName(forLocale, shortName, inLocale);\n }\n public getLocaleNameWithLookup(forLocale: string, shortName?: boolean, inLocale?: string) {\n return _LangsysApp.getLocaleNameWithLookup(forLocale, shortName, inLocale);\n }\n\n /** @deprecated use `getLocaleNameWithLookup` or `getLocaleName` */\n public getLanguageName(forLocale: string, shortName?: boolean, inLocale?: string) {\n return _LangsysApp.getLanguageName(forLocale, shortName, inLocale);\n }\n\n public detectPreferredLocale(acceptLanguageHeader?: string | null, supportedLocales?: string[]) {\n return _LangsysApp.detectPreferredLocale(acceptLanguageHeader, supportedLocales);\n }\n}\n\nexport const LangsysApp = new LangsysAppVue();\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "langsys-js-vue",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Vue 3 binding for the Langsys translation SDK — realtime continuous translations with automatic token discovery, delivered as composables and a <Translate> component.",
|
|
5
|
+
"author": "Langsys",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/gcapra/langsys-js-vue",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/gcapra/langsys-js-vue.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/gcapra/langsys-js-vue/issues"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18"
|
|
17
|
+
},
|
|
18
|
+
"main": "dist/index.js",
|
|
19
|
+
"module": "dist/index.mjs",
|
|
20
|
+
"types": "dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.mjs",
|
|
25
|
+
"require": "./dist/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"README-SSR.md",
|
|
32
|
+
"CHANGELOG.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
35
|
+
"sideEffects": false,
|
|
36
|
+
"scripts": {
|
|
37
|
+
"dev": "vite",
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"build:watch": "tsup --watch",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"test:watch": "vitest",
|
|
43
|
+
"lint": "prettier --check . && eslint .",
|
|
44
|
+
"format": "prettier --write .",
|
|
45
|
+
"prepublishOnly": "npm run build",
|
|
46
|
+
"release": "./_dev_/publish.sh"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"i18n",
|
|
50
|
+
"l10n",
|
|
51
|
+
"vue",
|
|
52
|
+
"vue3",
|
|
53
|
+
"composables",
|
|
54
|
+
"nuxt",
|
|
55
|
+
"language",
|
|
56
|
+
"localization",
|
|
57
|
+
"internationalization",
|
|
58
|
+
"translation",
|
|
59
|
+
"langsys",
|
|
60
|
+
"sdk"
|
|
61
|
+
],
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"vue": "^3.4.0"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"langsys-js-typescript": "^0.4.1"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@eslint/js": "^9.0.0",
|
|
70
|
+
"@vitejs/plugin-vue": "^5.2.0",
|
|
71
|
+
"eslint": "^9.0.0",
|
|
72
|
+
"eslint-config-prettier": "^10.0.0",
|
|
73
|
+
"eslint-plugin-vue": "^10.0.0",
|
|
74
|
+
"prettier": "^3.3.0",
|
|
75
|
+
"tsup": "^8.4.0",
|
|
76
|
+
"typescript": "^5.8.3",
|
|
77
|
+
"typescript-eslint": "^8.0.0",
|
|
78
|
+
"vite": "^6.0.0",
|
|
79
|
+
"vitest": "^4.1.7",
|
|
80
|
+
"vue": "^3.5.0"
|
|
81
|
+
}
|
|
82
|
+
}
|