nuxt-i18n-micro 3.30.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +2 -2
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/BVna_KKx.js +3 -0
- package/dist/client/_nuxt/Bw81RhAv.js +1 -0
- package/dist/client/_nuxt/CPz_jhsD.js +1 -0
- package/dist/client/_nuxt/CmvObVGq.js +1 -0
- package/dist/client/_nuxt/DKUOBR6F.js +5 -0
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/f0c8d4bf-40d2-4915-8b4a-ebe46bde61c8.json +1 -0
- package/dist/client/_nuxt/{entry.BM-mexAv.css → entry.PSWtHhay.css} +1 -1
- package/dist/client/_nuxt/error-404.xs3fxhVJ.css +1 -0
- package/dist/client/_nuxt/error-500.C2S-4iLg.css +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +14 -5
- package/dist/module.json +4 -1
- package/dist/module.mjs +850 -475
- package/dist/runtime/components/i18n-group.d.vue.ts +17 -9
- package/dist/runtime/components/i18n-group.vue +2 -4
- package/dist/runtime/components/i18n-group.vue.d.ts +17 -9
- package/dist/runtime/components/i18n-link.d.vue.ts +9 -6
- package/dist/runtime/components/i18n-link.vue +7 -28
- package/dist/runtime/components/i18n-link.vue.d.ts +9 -6
- package/dist/runtime/components/i18n-switcher.d.vue.ts +128 -54
- package/dist/runtime/components/i18n-switcher.vue +56 -156
- package/dist/runtime/components/i18n-switcher.vue.d.ts +128 -54
- package/dist/runtime/components/i18n-t.d.vue.ts +59 -116
- package/dist/runtime/components/i18n-t.vue +24 -71
- package/dist/runtime/components/i18n-t.vue.d.ts +59 -116
- package/dist/runtime/composables/useI18n.js +2 -38
- package/dist/runtime/composables/useI18nHead.js +21 -6
- package/dist/runtime/composables/useI18nLocale.d.ts +4 -1
- package/dist/runtime/composables/useI18nLocale.js +20 -22
- package/dist/runtime/composables/useLocaleHead.d.ts +26 -31
- package/dist/runtime/composables/useLocaleHead.js +47 -167
- package/dist/runtime/devtools/bridge.d.ts +2 -2
- package/dist/runtime/devtools/vue-devtools.d.ts +2 -2
- package/dist/runtime/devtools/vue-devtools.js +5 -5
- package/dist/runtime/middleware/i18n-redirect.global.d.ts +3 -2
- package/dist/runtime/middleware/i18n-redirect.global.js +30 -41
- package/dist/runtime/plugins/01.plugin.d.ts +156 -34
- package/dist/runtime/plugins/01.plugin.js +184 -138
- package/dist/runtime/plugins/02.meta.js +36 -43
- package/dist/runtime/plugins/04.vue-devtools.js +1 -1
- package/dist/runtime/plugins/06.redirect.d.ts +3 -3
- package/dist/runtime/plugins/06.redirect.js +65 -91
- package/dist/runtime/server/{utils → internal}/dev-live-translations.js +4 -3
- package/dist/runtime/server/internal/server-translation-cache.d.ts +9 -0
- package/dist/runtime/server/internal/server-translation-cache.js +10 -0
- package/dist/runtime/server/internal/shared-cache.d.ts +24 -0
- package/dist/runtime/server/internal/shared-cache.js +71 -0
- package/dist/runtime/server/internal/translation-watcher.d.ts +79 -0
- package/dist/runtime/server/internal/translation-watcher.js +105 -0
- package/dist/runtime/server/middleware/i18n.global.js +24 -37
- package/dist/runtime/server/payload-source.assets.d.ts +1 -0
- package/dist/runtime/server/payload-source.assets.js +3 -8
- package/dist/runtime/server/payload-source.fs.d.ts +1 -0
- package/dist/runtime/server/payload-source.fs.js +18 -7
- package/dist/runtime/server/plugins/failed-read.d.ts +7 -0
- package/dist/runtime/server/plugins/failed-read.js +23 -0
- package/dist/runtime/server/plugins/payload-cache.d.ts +6 -0
- package/dist/runtime/server/plugins/payload-cache.js +16 -0
- package/dist/runtime/server/plugins/watcher.dev.js +15 -79
- package/dist/runtime/server/routes/i18n.js +13 -14
- package/dist/runtime/server/utils/locale-detector.d.ts +32 -2
- package/dist/runtime/server/utils/locale-detector.js +48 -27
- package/dist/runtime/server/utils/locale-server-middleware.js +14 -33
- package/dist/runtime/server/utils/payload-cache.d.ts +4 -0
- package/dist/runtime/server/utils/payload-cache.js +13 -0
- package/dist/runtime/server/utils/server-loader.d.ts +17 -6
- package/dist/runtime/server/utils/server-loader.js +105 -51
- package/dist/runtime/server/utils/translation-server-middleware.js +18 -35
- package/dist/runtime/utils/cache-keys.d.ts +6 -0
- package/dist/runtime/utils/cache-keys.js +2 -0
- package/dist/runtime/utils/i18n-api.d.ts +185 -0
- package/dist/runtime/utils/i18n-api.js +196 -0
- package/dist/runtime/utils/i18n-config.d.ts +18 -0
- package/dist/runtime/utils/i18n-config.js +47 -0
- package/dist/runtime/utils/i18n-navigation.d.ts +26 -0
- package/dist/runtime/utils/i18n-navigation.js +96 -0
- package/dist/runtime/utils/nuxt-i18n-server.d.ts +26 -0
- package/dist/runtime/utils/nuxt-i18n-server.js +83 -0
- package/dist/runtime/utils/nuxt-i18n.d.ts +81 -96
- package/dist/runtime/utils/nuxt-i18n.js +180 -252
- package/dist/runtime/utils/page-head.d.ts +12 -0
- package/dist/runtime/utils/page-head.js +6 -0
- package/dist/runtime/utils/request-url.d.ts +6 -0
- package/dist/runtime/utils/request-url.js +11 -0
- package/dist/runtime/utils/storage.d.ts +31 -19
- package/dist/runtime/utils/storage.js +100 -49
- package/dist/runtime/utils/translation-entry.d.ts +6 -0
- package/dist/runtime/utils/translation-entry.js +16 -0
- package/dist/types.d.mts +4 -6
- package/internals.d.mts +9 -2
- package/package.json +78 -79
- package/dist/client/_nuxt/BOxWElQP.js +0 -21
- package/dist/client/_nuxt/CUWB4CwN.js +0 -3
- package/dist/client/_nuxt/CmUbe-uv.js +0 -1
- package/dist/client/_nuxt/DAzShkZF.js +0 -1
- package/dist/client/_nuxt/MokPP5zi.js +0 -1
- package/dist/client/_nuxt/builds/meta/f020fec8-462b-480b-82d8-6b0cb65617e8.json +0 -1
- package/dist/client/_nuxt/error-404.D9Svp6Hk.css +0 -1
- package/dist/client/_nuxt/error-500.B-mjI9_9.css +0 -1
- package/dist/runtime/plugins/03.define.d.ts +0 -7
- package/dist/runtime/plugins/03.define.js +0 -42
- package/dist/runtime/plugins/05.hooks.d.ts +0 -2
- package/dist/runtime/plugins/05.hooks.js +0 -47
- package/dist/runtime/server/utils/server-translation-cache.d.ts +0 -11
- package/dist/runtime/server/utils/server-translation-cache.js +0 -20
- /package/dist/runtime/server/{utils → internal}/dev-live-translations.d.ts +0 -0
|
@@ -3,41 +3,53 @@ export interface LoadOptions {
|
|
|
3
3
|
apiBaseUrl: string;
|
|
4
4
|
baseURL: string;
|
|
5
5
|
apiBaseClientHost?: string;
|
|
6
|
-
apiBaseServerHost?: string;
|
|
7
6
|
dateBuild?: string | number;
|
|
8
7
|
routesLocaleLinks?: Record<string, string>;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
/** A page's file needs its root, so the two start together. A delta from a host still finds its root without it. */
|
|
9
|
+
rootDelta?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Server only: the Nitro loader of this request (`event.context.i18n.load`), called directly. It reads a host too, named at
|
|
12
|
+
* build time or in the environment, so a render has one source. `null` is a host's "no such file", as a 404 is for a browser.
|
|
13
|
+
*/
|
|
14
|
+
serverLoad?: (locale: string, routeName: string) => Promise<Record<string, unknown> | null>;
|
|
13
15
|
}
|
|
14
16
|
declare class TranslationStorage {
|
|
15
17
|
private cc;
|
|
18
|
+
/** Roots on their way: every page of a first burst waits for one request. */
|
|
19
|
+
private readonly rootLoads;
|
|
20
|
+
/** The mark of each root held, to tell a delta made against another one. */
|
|
21
|
+
private readonly rootMarks;
|
|
16
22
|
constructor();
|
|
17
23
|
/**
|
|
18
|
-
* Configure cache limits
|
|
24
|
+
* Configure cache limits: the plugin's config values, on every request on the server, where this copy is process-wide.
|
|
19
25
|
*/
|
|
20
26
|
configure(options: CacheControlOptions): void;
|
|
21
27
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* no caller mutates a chunk in place.
|
|
28
|
+
* On the server the cache is shared by every request, so its root is frozen, once, in place: nested values are shared
|
|
29
|
+
* on purpose, and no caller mutates a chunk. A browser fetched this object for itself and has one reader: nothing to guard.
|
|
25
30
|
*/
|
|
26
|
-
private
|
|
27
|
-
private getCacheKey;
|
|
31
|
+
private shared;
|
|
28
32
|
private fetchTranslations;
|
|
29
|
-
/** Seed cache without fetching (e.g. `serverTranslationPreload` for index). */
|
|
30
|
-
seed(locale: string, routeName: string | undefined, data: Record<string, unknown>): void;
|
|
31
33
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
+
* A chunk, or `null` when the host has no file for it: a 404, a server loader's `null`, or a static host's SPA shell
|
|
35
|
+
* in a page's place. Anything else is a failed load, and the next try can work. A `null` body is one of those: a
|
|
36
|
+
* dictionary it is not, and read as "no file" on the root it would be kept as an empty one until a reload.
|
|
34
37
|
*/
|
|
35
|
-
|
|
38
|
+
private fetchChunk;
|
|
39
|
+
private request;
|
|
40
|
+
/** The URL the browser fetches a chunk from: what SSR preloads for the first page. */
|
|
41
|
+
clientUrl(locale: string, routeName: string | undefined, options: LoadOptions): string;
|
|
42
|
+
/** The cached chunk (not expired), or null. */
|
|
43
|
+
getFromCache(locale: string, routeName?: string): Record<string, unknown> | null;
|
|
44
|
+
/** Load a chunk, with caching. */
|
|
45
|
+
load(locale: string, routeName: string | undefined, options: LoadOptions): Promise<Record<string, unknown>>;
|
|
46
|
+
private loadRoot;
|
|
36
47
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
48
|
+
* A delta on the root it was made against. A root held since an older deploy lacks what moved into it, so a stale tab
|
|
49
|
+
* asks for the delta's: `?v=` of the mark, a URL no cache holds. One try, whatever comes: a CDN mid-deploy may have
|
|
50
|
+
* neither side new yet, and the root it gives is still the best text there is. Both arrive before anything is shown.
|
|
39
51
|
*/
|
|
40
|
-
|
|
52
|
+
private layered;
|
|
41
53
|
/**
|
|
42
54
|
* Clear cache and metadata.
|
|
43
55
|
*/
|
|
@@ -1,95 +1,146 @@
|
|
|
1
|
+
import { joinURL, withQuery } from "ufo";
|
|
1
2
|
import { translationCacheKey } from "@i18n-micro/core/helpers";
|
|
2
|
-
import { STORAGE_CC_KEY } from "
|
|
3
|
+
import { STORAGE_CC_KEY } from "./cache-keys.js";
|
|
4
|
+
import { takeRootMark } from "./translation-entry.js";
|
|
3
5
|
import { CacheControl } from "@i18n-micro/utils/cache-control";
|
|
6
|
+
import { mergeOverRoot, PREMERGED_ROOT_PAGE } from "@i18n-micro/utils/merge-source";
|
|
4
7
|
import { buildTranslationPayloadFetchRequest } from "@i18n-micro/utils/payload-url";
|
|
8
|
+
const NO_ROOT = Object.freeze({});
|
|
9
|
+
const NO_FILE = Object.freeze({});
|
|
10
|
+
class ChunkCache extends CacheControl {
|
|
11
|
+
/** A response requested before a clear may predate the edit the clear is for. */
|
|
12
|
+
clears = 0;
|
|
13
|
+
clear() {
|
|
14
|
+
this.clears++;
|
|
15
|
+
super.clear();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
5
18
|
function getStorageCacheControl() {
|
|
6
19
|
const g = globalThis;
|
|
7
20
|
if (!g[STORAGE_CC_KEY]) {
|
|
8
|
-
g[STORAGE_CC_KEY] = new
|
|
21
|
+
g[STORAGE_CC_KEY] = new ChunkCache();
|
|
9
22
|
}
|
|
10
23
|
return g[STORAGE_CC_KEY];
|
|
11
24
|
}
|
|
12
25
|
class TranslationStorage {
|
|
13
26
|
cc;
|
|
27
|
+
/** Roots on their way: every page of a first burst waits for one request. */
|
|
28
|
+
rootLoads = /* @__PURE__ */ new Map();
|
|
29
|
+
/** The mark of each root held, to tell a delta made against another one. */
|
|
30
|
+
rootMarks = /* @__PURE__ */ new Map();
|
|
14
31
|
constructor() {
|
|
15
32
|
this.cc = getStorageCacheControl();
|
|
16
33
|
}
|
|
17
34
|
/**
|
|
18
|
-
* Configure cache limits
|
|
35
|
+
* Configure cache limits: the plugin's config values, on every request on the server, where this copy is process-wide.
|
|
19
36
|
*/
|
|
20
37
|
configure(options) {
|
|
21
38
|
this.cc.configure(options);
|
|
22
39
|
}
|
|
23
|
-
// ==========================================================================
|
|
24
|
-
// HELPERS
|
|
25
|
-
// ==========================================================================
|
|
26
40
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* no caller mutates a chunk in place.
|
|
41
|
+
* On the server the cache is shared by every request, so its root is frozen, once, in place: nested values are shared
|
|
42
|
+
* on purpose, and no caller mutates a chunk. A browser fetched this object for itself and has one reader: nothing to guard.
|
|
30
43
|
*/
|
|
31
|
-
|
|
32
|
-
return Object.freeze(
|
|
33
|
-
}
|
|
34
|
-
getCacheKey(locale, routeName) {
|
|
35
|
-
return translationCacheKey(locale, routeName);
|
|
44
|
+
shared(data) {
|
|
45
|
+
return import.meta.server ? Object.freeze(data) : data;
|
|
36
46
|
}
|
|
37
|
-
// ==========================================================================
|
|
38
|
-
// FETCH LOADER
|
|
39
|
-
// ==========================================================================
|
|
40
47
|
async fetchTranslations(locale, routeName, options) {
|
|
41
|
-
|
|
48
|
+
if (import.meta.server && options.serverLoad) return await options.serverLoad(locale, routeName ?? "");
|
|
49
|
+
const request = this.request(locale, routeName, options, import.meta.server);
|
|
50
|
+
return await $fetch(request.path, {
|
|
51
|
+
baseURL: request.baseURL,
|
|
52
|
+
params: request.params,
|
|
53
|
+
// after a clear a browser's copy may be what the clear is for: `max-age` would answer with it
|
|
54
|
+
cache: import.meta.client && this.cc.clears ? "no-cache" : void 0
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A chunk, or `null` when the host has no file for it: a 404, a server loader's `null`, or a static host's SPA shell
|
|
59
|
+
* in a page's place. Anything else is a failed load, and the next try can work. A `null` body is one of those: a
|
|
60
|
+
* dictionary it is not, and read as "no file" on the root it would be kept as an empty one until a reload.
|
|
61
|
+
*/
|
|
62
|
+
async fetchChunk(locale, routeName, options) {
|
|
63
|
+
const data = await this.fetchTranslations(locale, routeName, options).catch((error) => {
|
|
64
|
+
if (error.status === 404) return NO_FILE;
|
|
65
|
+
throw error;
|
|
66
|
+
});
|
|
67
|
+
if (data === NO_FILE || data === null && import.meta.server && options.serverLoad) return null;
|
|
68
|
+
if (data !== null && typeof data === "object" && !Array.isArray(data)) return data;
|
|
69
|
+
if (routeName !== PREMERGED_ROOT_PAGE) return null;
|
|
70
|
+
throw new TypeError(`[i18n] Invalid translation payload: ${translationCacheKey(locale, routeName)}`);
|
|
71
|
+
}
|
|
72
|
+
request(locale, routeName, options, isServer) {
|
|
73
|
+
return buildTranslationPayloadFetchRequest({
|
|
42
74
|
apiBaseUrl: options.apiBaseUrl,
|
|
43
75
|
routeName,
|
|
44
76
|
locale,
|
|
45
|
-
isServer
|
|
77
|
+
isServer,
|
|
46
78
|
baseURL: options.baseURL,
|
|
47
79
|
apiBaseClientHost: options.apiBaseClientHost,
|
|
48
|
-
apiBaseServerHost: options.apiBaseServerHost ?? (import.meta.server ? process.env.NUXT_I18N_APP_BASE_SERVER_HOST : void 0),
|
|
49
80
|
dateBuild: options.dateBuild,
|
|
50
81
|
routesLocaleLinks: options.routesLocaleLinks
|
|
51
82
|
});
|
|
52
|
-
return await $fetch(request.path, {
|
|
53
|
-
baseURL: request.baseURL,
|
|
54
|
-
params: request.params
|
|
55
|
-
});
|
|
56
83
|
}
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
84
|
+
/** The URL the browser fetches a chunk from: what SSR preloads for the first page. */
|
|
85
|
+
clientUrl(locale, routeName, options) {
|
|
86
|
+
const request = this.request(locale, routeName, options, false);
|
|
87
|
+
return withQuery(joinURL(request.baseURL, request.path), request.params ?? {});
|
|
61
88
|
}
|
|
62
|
-
|
|
63
|
-
// PUBLIC API
|
|
64
|
-
// ==========================================================================
|
|
65
|
-
/**
|
|
66
|
-
* Synchronous cache check and retrieval.
|
|
67
|
-
* Returns data if cached (and not expired), otherwise null.
|
|
68
|
-
*/
|
|
89
|
+
/** The cached chunk (not expired), or null. */
|
|
69
90
|
getFromCache(locale, routeName) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
91
|
+
return this.cc.get(translationCacheKey(locale, routeName)) ?? null;
|
|
92
|
+
}
|
|
93
|
+
/** Load a chunk, with caching. */
|
|
94
|
+
async load(locale, routeName, options) {
|
|
95
|
+
const direct = import.meta.server && Boolean(options.serverLoad);
|
|
96
|
+
const cached = direct ? null : this.getFromCache(locale, routeName);
|
|
97
|
+
if (cached) return cached;
|
|
98
|
+
const clears = this.cc.clears;
|
|
99
|
+
const page = routeName !== PREMERGED_ROOT_PAGE;
|
|
100
|
+
const root = page && options.rootDelta && !direct ? this.loadRoot(locale, options) : void 0;
|
|
101
|
+
root?.catch(() => {
|
|
102
|
+
});
|
|
103
|
+
const file = await this.fetchChunk(locale, routeName, options);
|
|
104
|
+
const mark = file ? takeRootMark(file) : void 0;
|
|
105
|
+
const layers = file && mark && page ? await this.layered(locale, mark, file, root, options) : null;
|
|
106
|
+
const data = layers ? layers.data : file;
|
|
107
|
+
if (clears !== this.cc.clears) return this.load(locale, routeName, options);
|
|
108
|
+
if (!page) this.rootMarks.set(locale, mark);
|
|
109
|
+
if (data === null && routeName === PREMERGED_ROOT_PAGE) {
|
|
110
|
+
if (import.meta.server && import.meta.prerender) throw new Error("[i18n] The host has no dictionary for this page");
|
|
111
|
+
return NO_ROOT;
|
|
74
112
|
}
|
|
75
|
-
return
|
|
113
|
+
if (data === null) return this.load(locale, PREMERGED_ROOT_PAGE, options);
|
|
114
|
+
if (!direct && !layers?.partial) this.cc.set(translationCacheKey(locale, routeName), this.shared(data));
|
|
115
|
+
return data;
|
|
116
|
+
}
|
|
117
|
+
loadRoot(locale, options) {
|
|
118
|
+
const pending = this.rootLoads.get(locale);
|
|
119
|
+
if (pending) return pending;
|
|
120
|
+
const load = this.load(locale, PREMERGED_ROOT_PAGE, options).finally(() => this.rootLoads.delete(locale));
|
|
121
|
+
this.rootLoads.set(locale, load);
|
|
122
|
+
return load;
|
|
76
123
|
}
|
|
77
124
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
125
|
+
* A delta on the root it was made against. A root held since an older deploy lacks what moved into it, so a stale tab
|
|
126
|
+
* asks for the delta's: `?v=` of the mark, a URL no cache holds. One try, whatever comes: a CDN mid-deploy may have
|
|
127
|
+
* neither side new yet, and the root it gives is still the best text there is. Both arrive before anything is shown.
|
|
80
128
|
*/
|
|
81
|
-
async
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
129
|
+
async layered(locale, mark, delta, started, options) {
|
|
130
|
+
let root = await (started ?? this.loadRoot(locale, options));
|
|
131
|
+
const held = this.rootMarks.get(locale);
|
|
132
|
+
if (held && held !== mark) {
|
|
133
|
+
this.cc.delete(translationCacheKey(locale, PREMERGED_ROOT_PAGE));
|
|
134
|
+
root = await this.load(locale, PREMERGED_ROOT_PAGE, { ...options, dateBuild: mark });
|
|
135
|
+
}
|
|
136
|
+
return { data: mergeOverRoot(root, delta), partial: root === NO_ROOT };
|
|
88
137
|
}
|
|
89
138
|
/**
|
|
90
139
|
* Clear cache and metadata.
|
|
91
140
|
*/
|
|
92
141
|
clear() {
|
|
142
|
+
this.rootLoads.clear();
|
|
143
|
+
this.rootMarks.clear();
|
|
93
144
|
this.cc.clear();
|
|
94
145
|
}
|
|
95
146
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Translations } from '@i18n-micro/types';
|
|
2
|
+
import type { ServerTranslationCacheEntry } from '../server/internal/server-translation-cache.js';
|
|
3
|
+
/** `json` on demand: where the public dir answers `/_locales` the string would only hold memory (a chunk's size, per cached entry). */
|
|
4
|
+
export declare function toEntry(data: Translations): ServerTranslationCacheEntry;
|
|
5
|
+
/** The root mark of a file just read, taken off it: nothing above the loader sees one. `undefined`: a whole chunk. */
|
|
6
|
+
export declare function takeRootMark(file: Record<string, unknown>): string | undefined;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PREMERGED_ROOT_MARK } from "@i18n-micro/utils/merge-source";
|
|
2
|
+
export function toEntry(data) {
|
|
3
|
+
let json;
|
|
4
|
+
return {
|
|
5
|
+
// every request reads this tree: its root is frozen, once, in place
|
|
6
|
+
data: Object.freeze(data),
|
|
7
|
+
get json() {
|
|
8
|
+
return json ??= JSON.stringify(data).replaceAll("<", "\\u003c");
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function takeRootMark(file) {
|
|
13
|
+
const mark = file[PREMERGED_ROOT_MARK];
|
|
14
|
+
delete file[PREMERGED_ROOT_MARK];
|
|
15
|
+
return typeof mark === "string" ? mark : void 0;
|
|
16
|
+
}
|
package/dist/types.d.mts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ModuleRuntimeHooks } from './module.mjs'
|
|
2
2
|
|
|
3
|
-
declare module '
|
|
4
|
-
interface
|
|
3
|
+
declare module '#app' {
|
|
4
|
+
interface RuntimeNuxtHooks extends ModuleRuntimeHooks {}
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export { type Getter, type GlobalLocaleRoutes, type Locale, type LocaleCode, type ModuleOptions, type PluralFunc, type Strategies } from '@i18n-micro/types'
|
|
8
8
|
|
|
9
9
|
export { type PluginsInjections } from '../dist/runtime/plugins/01.plugin.js'
|
|
10
10
|
|
|
11
|
-
export { type TranslationPayloadMode, type resolveTranslationPayloadMode, type resolveTranslationPayloadOptions, type resolveTranslationPayloadPublicDir, type resolveTranslationPayloadPublicRel, type shouldCopyTranslationPayloadsToPublic, type shouldRegisterNitroServerAssets } from '@i18n-micro/utils/payload-config'
|
|
12
|
-
|
|
13
11
|
export { default } from './module.mjs'
|
|
14
12
|
|
|
15
|
-
export { type
|
|
13
|
+
export { type ModuleRuntimeHooks, type TranslationPayloadMode } from './module.mjs'
|
package/internals.d.mts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Getter, Params } from '@i18n-micro/types'
|
|
2
|
+
|
|
1
3
|
declare module '#build/i18n.plural.mjs' {
|
|
2
4
|
export function plural(key: string, count: number, params: Params, locale: string, getter: Getter): string | null
|
|
3
5
|
}
|
|
@@ -17,6 +19,8 @@ interface I18nPrivateConfig {
|
|
|
17
19
|
customRegexMatcher?: string
|
|
18
20
|
routesLocaleLinks?: Record<string, string>
|
|
19
21
|
serverTranslationPreload?: boolean
|
|
22
|
+
cacheStorage?: string
|
|
23
|
+
cacheStorageBuild?: string
|
|
20
24
|
/** Absolute buildDir payload dir for Node fs reads in dev/prerender. */
|
|
21
25
|
payloadFsDir: string
|
|
22
26
|
/** Relative dir under Nitro `public/` for prod payload files. */
|
|
@@ -63,8 +67,8 @@ export interface I18nStrategyInstance {
|
|
|
63
67
|
getRedirect(currentPath: string, targetLocale: string): string | null
|
|
64
68
|
getLocaleFromPath(path: string): string | null
|
|
65
69
|
resolveLocaleFromPath(path: string): string | null
|
|
66
|
-
localeRoute(targetLocale: string, routeOrPath: I18nStrategyResolvedRoute | string
|
|
67
|
-
switchLocaleRoute(
|
|
70
|
+
localeRoute(targetLocale: string, routeOrPath: I18nStrategyResolvedRoute | string): I18nStrategyResolvedRoute | string
|
|
71
|
+
switchLocaleRoute(toLocale: string, route: I18nStrategyResolvedRoute, options?: { i18nRouteParams?: Record<string, Record<string, unknown>>, named?: boolean }): I18nStrategyResolvedRoute | string
|
|
68
72
|
getCanonicalPath(route: I18nStrategyResolvedRoute, targetLocale: string): string | null
|
|
69
73
|
setRouter(router: I18nStrategyRouterLike): void
|
|
70
74
|
getCurrentLocale(route: I18nStrategyResolvedRoute, getDefaultLocale?: () => string | null | undefined): string
|
|
@@ -87,6 +91,7 @@ interface I18nStrategyRouterLike {
|
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
declare module '#build/i18n.strategy.mjs' {
|
|
94
|
+
export const domains: boolean
|
|
90
95
|
/** Создаёт инстанс стратегии: контекст (build-time) уже в файле, при импорте передаётся только router. */
|
|
91
96
|
export function createI18nStrategy(router: I18nStrategyRouterLike): I18nStrategyInstance
|
|
92
97
|
export function getI18nConfig(): unknown
|
|
@@ -98,10 +103,12 @@ declare module '#i18n-internal/config' {
|
|
|
98
103
|
}
|
|
99
104
|
|
|
100
105
|
declare module '#i18n-internal/strategy' {
|
|
106
|
+
export const domains: boolean
|
|
101
107
|
export function getI18nConfig(): unknown
|
|
102
108
|
export function createI18nStrategy(router: I18nStrategyRouterLike): I18nStrategyInstance
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
declare module '#i18n-internal/payload-source' {
|
|
112
|
+
export const embeddedPayloads: boolean
|
|
106
113
|
export function readPayload(relPath: string): Promise<Record<string, unknown>>
|
|
107
114
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-i18n-micro",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Fast, lightweight i18n for Nuxt with strategy-based routing and minimal overhead.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -24,13 +24,10 @@
|
|
|
24
24
|
"email": "Virus191288@gmail.com",
|
|
25
25
|
"url": "https://s00d.github.io/"
|
|
26
26
|
},
|
|
27
|
-
"repository":
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
"packages/**",
|
|
32
|
-
"test/fixtures/**/*"
|
|
33
|
-
],
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/s00d/nuxt-i18n-micro.git"
|
|
30
|
+
},
|
|
34
31
|
"files": [
|
|
35
32
|
"dist",
|
|
36
33
|
"internals.d.mts"
|
|
@@ -74,53 +71,58 @@
|
|
|
74
71
|
},
|
|
75
72
|
"dependencies": {
|
|
76
73
|
"@nuxt/devtools-kit": "^3.4.2",
|
|
77
|
-
"@nuxt/kit": "^3.18.
|
|
78
|
-
"@vue/compiler-sfc": "^3.5.
|
|
74
|
+
"@nuxt/kit": "^3.18.0 || ^4.0.0",
|
|
75
|
+
"@vue/compiler-sfc": "^3.5.44",
|
|
79
76
|
"chokidar": "^5.0.0",
|
|
80
77
|
"globby": "^16.2.4",
|
|
81
78
|
"h3": "^1.15.11",
|
|
82
79
|
"sirv": "^3.0.2",
|
|
83
80
|
"ufo": "^1.6.4",
|
|
84
|
-
"
|
|
85
|
-
"@i18n-micro/
|
|
86
|
-
"@i18n-micro/
|
|
87
|
-
"@i18n-micro/
|
|
88
|
-
"@i18n-micro/
|
|
89
|
-
"@i18n-micro/test-utils": "^1.2.19",
|
|
90
|
-
"@i18n-micro/types": "^1.2.18",
|
|
91
|
-
"@i18n-micro/utils": "^1.0.27"
|
|
81
|
+
"@i18n-micro/path-strategy": "^2.0.0",
|
|
82
|
+
"@i18n-micro/route-strategy": "^2.0.0",
|
|
83
|
+
"@i18n-micro/types": "^2.0.0",
|
|
84
|
+
"@i18n-micro/utils": "^2.0.0",
|
|
85
|
+
"@i18n-micro/core": "^2.0.0"
|
|
92
86
|
},
|
|
93
87
|
"devDependencies": {
|
|
94
88
|
"@nuxt/devtools": "^3.4.2",
|
|
95
89
|
"@nuxt/devtools-ui-kit": "^3.4.2",
|
|
96
90
|
"@nuxt/module-builder": "^1.0.3",
|
|
97
|
-
"@nuxt/schema": "^3.18.
|
|
98
|
-
"@nuxt/test-utils": "^4.3.
|
|
99
|
-
"@playwright/test": "^1.
|
|
91
|
+
"@nuxt/schema": "^3.18.0 || ^4.0.0",
|
|
92
|
+
"@nuxt/test-utils": "^4.3.4",
|
|
93
|
+
"@playwright/test": "^1.64.1",
|
|
94
|
+
"@stryker-mutator/core": "^10.1.1",
|
|
95
|
+
"@stryker-mutator/vitest-runner": "^10.1.1",
|
|
100
96
|
"@types/node": "^22.19.0",
|
|
101
|
-
"@untestutils/nuxt": "^0.
|
|
102
|
-
"@untestutils/perf": "^0.
|
|
97
|
+
"@untestutils/nuxt": "^0.8.1",
|
|
98
|
+
"@untestutils/perf": "^0.8.1",
|
|
103
99
|
"@vue/devtools-api": "^8.1.5",
|
|
104
100
|
"changelogen": "^0.6.2",
|
|
105
|
-
"
|
|
106
|
-
"
|
|
101
|
+
"fast-check": "^4.10.2",
|
|
102
|
+
"oxfmt": "^0.76.0",
|
|
103
|
+
"oxlint": "^1.90.0",
|
|
107
104
|
"typescript": "6.0.3",
|
|
108
|
-
"untestutils": "^0.
|
|
109
|
-
"vitest": "^5.0
|
|
110
|
-
"vue-tsc": "^3.3.
|
|
105
|
+
"untestutils": "^0.8.1",
|
|
106
|
+
"vitest": "^5.1.0",
|
|
107
|
+
"vue-tsc": "^3.3.14"
|
|
111
108
|
},
|
|
112
109
|
"peerDependencies": {
|
|
113
110
|
"@vue/devtools-api": "^8.1.5",
|
|
114
|
-
"vue-router": "^4.
|
|
111
|
+
"vue-router": "^4.5.1 || ^5.0.0"
|
|
115
112
|
},
|
|
116
113
|
"peerDependenciesMeta": {
|
|
117
114
|
"@vue/devtools-api": {
|
|
118
115
|
"optional": true
|
|
119
116
|
}
|
|
120
117
|
},
|
|
121
|
-
"
|
|
122
|
-
"
|
|
123
|
-
|
|
118
|
+
"engines": {
|
|
119
|
+
"node": ">=20"
|
|
120
|
+
},
|
|
121
|
+
"devEngines": {
|
|
122
|
+
"packageManager": {
|
|
123
|
+
"name": "pnpm",
|
|
124
|
+
"onFail": "warn"
|
|
125
|
+
}
|
|
124
126
|
},
|
|
125
127
|
"stackblitz": {
|
|
126
128
|
"startCommand": "pnpm install && pnpm --filter \"./packages/*\" run build && pnpm run dev:prepare && pnpm run dev",
|
|
@@ -129,70 +131,67 @@
|
|
|
129
131
|
}
|
|
130
132
|
},
|
|
131
133
|
"scripts": {
|
|
132
|
-
"preinstall": "node -e \"const{existsSync}=require('fs');if(!existsSync('pnpm-workspace.yaml'))process.exit(0);const ua=process.env.npm_config_user_agent||'';if(!ua.includes('pnpm')){console.error('This repo requires pnpm (npm/yarn corrupt the TypeScript hoist). Use: pnpm install');process.exit(1)}\"",
|
|
133
134
|
"dev": "nuxi dev playground",
|
|
134
135
|
"dev:build": "nuxi build playground",
|
|
135
|
-
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
136
136
|
"dev:generate": "nuxi generate playground",
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
"
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
"
|
|
147
|
-
"
|
|
137
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
138
|
+
"bench": "node playground/bench/matrix.mjs",
|
|
139
|
+
"client:build": "nuxi generate client",
|
|
140
|
+
"client:dev": "nuxi dev client --port 3300",
|
|
141
|
+
"build:packages": "pnpm --filter \"./packages/*\" run build",
|
|
142
|
+
"lint": "oxlint src packages test client playground scripts/src build.config.ts docs/app docs/server docs/nuxt.config.ts docs/content.config.ts docs/redirects.ts docs/preview.mjs",
|
|
143
|
+
"lint:fix": "oxlint src packages test client playground scripts/src build.config.ts docs/app docs/server docs/nuxt.config.ts docs/content.config.ts docs/redirects.ts docs/preview.mjs --fix",
|
|
144
|
+
"format": "oxfmt --write src packages test client playground scripts/src build.config.ts docs/app docs/server docs/nuxt.config.ts docs/content.config.ts docs/redirects.ts docs/preview.mjs",
|
|
145
|
+
"format:check": "oxfmt --check src packages test client playground scripts/src build.config.ts docs/app docs/server docs/nuxt.config.ts docs/content.config.ts docs/redirects.ts docs/preview.mjs",
|
|
146
|
+
"typecheck": "pnpm run typecheck:root && pnpm run typecheck:playground && pnpm run typecheck:scripts && pnpm run typecheck:packages && pnpm run typecheck:package-playgrounds",
|
|
147
|
+
"typecheck:root": "vue-tsc --noEmit -p tsconfig.nuxt.json",
|
|
148
|
+
"typecheck:playground": "vue-tsc --noEmit -p playground/tsconfig.json",
|
|
149
|
+
"typecheck:scripts": "pnpm -C scripts typecheck",
|
|
150
|
+
"typecheck:packages": "pnpm --filter \"./packages/**\" --filter \"!./packages/*/playground\" run typecheck",
|
|
151
|
+
"typecheck:package-playgrounds": "pnpm --filter \"./packages/*/playground\" run typecheck",
|
|
148
152
|
"test": "vitest run",
|
|
153
|
+
"test:watch": "vitest watch --config vitest.unit.config.ts",
|
|
149
154
|
"test:unit": "vitest run --config vitest.unit.config.ts",
|
|
155
|
+
"test:unit:types": "vitest run --config vitest.unit.config.ts --typecheck.only",
|
|
150
156
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
157
|
+
"test:strategies": "vitest run --config vitest.integration.config.ts test/strategies-",
|
|
151
158
|
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
159
|
+
"test:e2e:browsers": "rc=0; for b in chromium firefox webkit; do echo \"== $b\"; E2E_BROWSER=$b vitest run --config vitest.e2e.config.ts || rc=1; done; exit $rc",
|
|
152
160
|
"test:packages": "vitest run --config vitest.packages.config.ts",
|
|
161
|
+
"test:dist:packages": "pnpm --filter \"./packages/*\" run --if-present test:dist",
|
|
162
|
+
"test:presets": "pnpm -C scripts cli preset-smoke --preset all",
|
|
153
163
|
"test:performance": "pnpm -C scripts cli performance",
|
|
154
|
-
"test:
|
|
155
|
-
"test:
|
|
156
|
-
"test:types": "pnpm run typecheck",
|
|
157
|
-
"typecheck:root": "vue-tsc --noEmit -p tsconfig.nuxt.json",
|
|
158
|
-
"typecheck:playground": "vue-tsc --noEmit -p playground/tsconfig.json",
|
|
159
|
-
"typecheck:scripts": "pnpm -C scripts typecheck",
|
|
160
|
-
"typecheck:packages": "pnpm --filter \"./packages/**\" --filter \"!./packages/*/playground\" run typecheck",
|
|
161
|
-
"typecheck:package-playgrounds": "pnpm --filter \"./packages/*/playground\" run typecheck",
|
|
162
|
-
"typecheck": "pnpm run typecheck:root && pnpm run typecheck:playground && pnpm run typecheck:scripts && pnpm run typecheck:packages && pnpm run typecheck:package-playgrounds",
|
|
163
|
-
"build:packages": "pnpm --filter \"./packages/*\" run build",
|
|
164
|
-
"client:build": "nuxi generate client",
|
|
165
|
-
"client:prepare": "nuxi client:prepare client",
|
|
166
|
-
"client:dev": "nuxi dev client --port 3300",
|
|
167
|
-
"clean": "find . \\( -name 'node_modules' -o -name '.nuxt' -o -name '.output' -o -name 'dist' \\) -type d -prune -exec rm -rf '{}' + && find . \\( -name 'pnpm-lock.yaml' -o -name 'package-lock.json' \\) -type f -exec rm -f '{}' +",
|
|
168
|
-
"clean:test": "rm -rf test/.fixture-builds test/.untestutils && find test/fixtures -type d \\( -name '.nuxt' -o -name '.output-shared' -o -name '.nuxt-test' -o -name 'test-results' \\) -prune -exec rm -rf '{}' + 2>/dev/null || true",
|
|
169
|
-
"check:versions": "pnpm -C scripts cli check-versions",
|
|
170
|
-
"verify:packages": "pnpm -C scripts cli verify-packages",
|
|
171
|
-
"verify:packages:publint": "pnpm -C scripts cli verify-packages --publint",
|
|
172
|
-
"compare:published": "pnpm -C scripts cli compare-published",
|
|
173
|
-
"test:dist:packages": "pnpm --filter \"@i18n-micro/core\" --filter \"@i18n-micro/utils\" --filter \"@i18n-micro/hmr\" --filter \"@i18n-micro/vue\" --filter \"@i18n-micro/path-strategy\" --filter \"@i18n-micro/route-strategy\" --filter \"@i18n-micro/devtools-ui\" --filter \"@i18n-micro/astro\" run test:dist",
|
|
174
|
-
"typecheck:nuxt": "nuxt typecheck --no-emit",
|
|
164
|
+
"test:mutation": "stryker run stryker.config.mjs",
|
|
165
|
+
"test:fuzz": "pnpm -C scripts cli http-fuzz",
|
|
175
166
|
"docs:dev": "pnpm --filter @i18n-micro/docs dev",
|
|
176
|
-
"docs:build": "pnpm --filter @i18n-micro/docs build",
|
|
177
|
-
"docs:serve": "pnpm --filter @i18n-micro/docs preview",
|
|
178
167
|
"docs:clean-dev": "pnpm --filter @i18n-micro/docs clean-dev",
|
|
168
|
+
"docs:build": "pnpm --filter @i18n-micro/docs build",
|
|
179
169
|
"docs:preview": "pnpm --filter @i18n-micro/docs preview",
|
|
180
|
-
"
|
|
181
|
-
"
|
|
182
|
-
"
|
|
183
|
-
"
|
|
184
|
-
"test:presets:vercel": "pnpm -C scripts cli preset-smoke --preset vercel",
|
|
185
|
-
"test:presets:cloudflare": "pnpm -C scripts cli preset-smoke --preset cloudflare_pages",
|
|
186
|
-
"test:presets:netlify": "pnpm -C scripts cli preset-smoke --preset netlify",
|
|
170
|
+
"docs:generate": "pnpm -C scripts cli docs-generate",
|
|
171
|
+
"docs:generate:check": "pnpm -C scripts cli docs-generate --check",
|
|
172
|
+
"api:surface": "pnpm -C scripts cli api-surface",
|
|
173
|
+
"api:surface:update": "pnpm -C scripts cli api-surface --update",
|
|
187
174
|
"audit:deps": "pnpm -C scripts cli deps-audit",
|
|
188
175
|
"audit:docs": "pnpm -C scripts cli docs-audit",
|
|
189
176
|
"audit:fixtures": "pnpm -C scripts cli fixtures-audit",
|
|
190
|
-
"api:surface": "pnpm -C scripts cli api-surface",
|
|
191
|
-
"api:surface:update": "pnpm -C scripts cli api-surface --update",
|
|
192
177
|
"budget:payload": "pnpm -C scripts cli payload-budget",
|
|
193
178
|
"budget:payload:update": "pnpm -C scripts cli payload-budget --update",
|
|
179
|
+
"clean": "find . -path ./.claude -prune -o \\( -name 'node_modules' -o -name '.nuxt' -o -name '.output' -o -name 'dist' \\) -type d -prune -exec rm -rf '{}' +",
|
|
180
|
+
"clean:test": "rm -rf test/.fixture-builds test/.untestutils && find test/fixtures -type d \\( -name '.nuxt' -o -name '.output-shared' -o -name '.nuxt-test' -o -name 'test-results' \\) -prune -exec rm -rf '{}' + 2>/dev/null || true",
|
|
181
|
+
"check:versions": "pnpm -C scripts cli check-versions",
|
|
182
|
+
"verify:packages": "pnpm -C scripts cli verify-packages",
|
|
183
|
+
"verify:packages:publint": "pnpm -C scripts cli verify-packages --publint",
|
|
184
|
+
"compare:published": "pnpm -C scripts cli compare-published",
|
|
185
|
+
"check:consumer": "pnpm -C scripts cli consumer-types",
|
|
186
|
+
"check:oldest": "pnpm -C scripts cli oldest-versions",
|
|
194
187
|
"preflight": "pnpm -C scripts cli preflight",
|
|
195
|
-
"
|
|
196
|
-
"
|
|
188
|
+
"bump": "pnpm -C scripts cli bump",
|
|
189
|
+
"release:check": "pnpm -C scripts cli publish --check-only",
|
|
190
|
+
"release:auth": "pnpm -C scripts cli ensure-npm-auth",
|
|
191
|
+
"release:source": "pnpm -C scripts cli ensure-release-source",
|
|
192
|
+
"release:patch": "pnpm -C scripts cli publish --bump patch",
|
|
193
|
+
"release:minor": "pnpm -C scripts cli publish --bump minor",
|
|
194
|
+
"release:major": "pnpm -C scripts cli publish --bump major",
|
|
195
|
+
"release:packages": "pnpm -C scripts cli publish"
|
|
197
196
|
}
|
|
198
197
|
}
|