@i18n-micro/astro 1.2.0 → 1.2.1
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/dist/client/core.d.ts +1 -1
- package/dist/client/index.d.ts +3 -3
- package/dist/client/index.js +9 -9
- package/dist/client/preact.d.ts +1 -1
- package/dist/client/preact.js +36 -21
- package/dist/client/react.d.ts +1 -1
- package/dist/client/react.js +35 -20
- package/dist/client/svelte.d.ts +1 -1
- package/dist/client/svelte.js +8 -14
- package/dist/client/vue.d.ts +1 -1
- package/dist/client/vue.js +6 -12
- package/dist/composer.d.ts +1 -1
- package/dist/env.d.ts +0 -2
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +11 -11
- package/dist/index.mjs +140 -149
- package/dist/integration.d.ts +1 -1
- package/dist/middleware.d.ts +2 -2
- package/dist/router/adapter.d.ts +1 -1
- package/dist/utils.d.ts +2 -2
- package/package.json +4 -4
- package/src/client/core.ts +5 -11
- package/src/client/index.ts +6 -8
- package/src/client/preact.tsx +74 -61
- package/src/client/react.tsx +73 -61
- package/src/client/svelte.ts +9 -25
- package/src/client/vue.ts +7 -23
- package/src/components/i18n-link.astro +3 -3
- package/src/components/i18n-switcher.astro +3 -3
- package/src/components/i18n-t.astro +3 -13
- package/src/composer.ts +2 -7
- package/src/env.d.ts +0 -2
- package/src/index.ts +35 -42
- package/src/integration.ts +5 -10
- package/src/load-translations.ts +11 -13
- package/src/middleware.ts +12 -22
- package/src/router/adapter.ts +7 -25
- package/src/routing.ts +3 -17
- package/src/utils.ts +10 -19
package/dist/index.mjs
CHANGED
|
@@ -87,18 +87,13 @@ function v() {
|
|
|
87
87
|
return j;
|
|
88
88
|
}
|
|
89
89
|
function U(n) {
|
|
90
|
-
const {
|
|
91
|
-
locale: e,
|
|
92
|
-
fallbackLocale: s,
|
|
93
|
-
translationDir: o,
|
|
94
|
-
routingStrategy: i
|
|
95
|
-
} = n;
|
|
90
|
+
const { locale: e, fallbackLocale: s, translationDir: o, routingStrategy: i } = n;
|
|
96
91
|
return j = i || null, {
|
|
97
92
|
name: "@i18n-micro/astro",
|
|
98
93
|
hooks: {
|
|
99
94
|
// 1. Настройка Vite (Виртуальный модуль) происходит здесь
|
|
100
95
|
"astro:config:setup": (c) => {
|
|
101
|
-
const { updateConfig: f } = c, t = "virtual:i18n-micro/config", l =
|
|
96
|
+
const { updateConfig: f } = c, t = "virtual:i18n-micro/config", l = `\0${t}`, r = {
|
|
102
97
|
defaultLocale: e,
|
|
103
98
|
fallbackLocale: s || e,
|
|
104
99
|
locales: n.locales || [],
|
|
@@ -157,7 +152,39 @@ function U(n) {
|
|
|
157
152
|
function E(n) {
|
|
158
153
|
return new S(n);
|
|
159
154
|
}
|
|
160
|
-
function
|
|
155
|
+
function M(n) {
|
|
156
|
+
const { translationDir: e, rootDir: s = process.cwd(), disablePageLocales: o = !1 } = n, i = O(s, e);
|
|
157
|
+
if (!R(i))
|
|
158
|
+
return console.warn(`[i18n] Translation directory not found: ${i}`), { general: {}, routes: {} };
|
|
159
|
+
const c = {}, f = {}, t = (l, r = "") => {
|
|
160
|
+
if (!R(l)) return;
|
|
161
|
+
const a = _(l);
|
|
162
|
+
for (const u of a) {
|
|
163
|
+
const h = q(l, u);
|
|
164
|
+
if (C(h).isDirectory())
|
|
165
|
+
u === "pages" && !o ? t(h, "") : r || o ? t(h, r) : t(h, u);
|
|
166
|
+
else if (u.endsWith(".json")) {
|
|
167
|
+
const m = u.replace(".json", "");
|
|
168
|
+
try {
|
|
169
|
+
const g = N(h, "utf-8"), p = JSON.parse(g);
|
|
170
|
+
r && !o ? (f[r] || (f[r] = {}), f[r][m] = p) : c[m] = p;
|
|
171
|
+
} catch (g) {
|
|
172
|
+
console.error(`[i18n] Failed to load translation file: ${h}`, g);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
return t(i), { general: c, routes: f };
|
|
178
|
+
}
|
|
179
|
+
function J(n, e) {
|
|
180
|
+
const { general: s, routes: o } = M(e);
|
|
181
|
+
for (const [i, c] of Object.entries(s))
|
|
182
|
+
n.addTranslations(i, c, !1);
|
|
183
|
+
for (const [i, c] of Object.entries(o))
|
|
184
|
+
for (const [f, t] of Object.entries(c))
|
|
185
|
+
n.addRouteTranslations(f, i, t, !1);
|
|
186
|
+
}
|
|
187
|
+
function V(n) {
|
|
161
188
|
const {
|
|
162
189
|
i18n: e,
|
|
163
190
|
// Это глобальный синглтон с кэшем
|
|
@@ -190,7 +217,7 @@ function J(n) {
|
|
|
190
217
|
return L.setRoute(b), r.locals.i18n = L, r.locals.locale = P, r.locals.defaultLocale = s, r.locals.locales = i || o.map((y) => ({ code: y })), r.locals.currentUrl = u, r.locals.routingStrategy = d, a();
|
|
191
218
|
};
|
|
192
219
|
}
|
|
193
|
-
function
|
|
220
|
+
function W(n) {
|
|
194
221
|
const e = [], s = n.split(",");
|
|
195
222
|
for (const o of s) {
|
|
196
223
|
const [i, c = "1.0"] = o.trim().split(";q=");
|
|
@@ -201,7 +228,7 @@ function M(n) {
|
|
|
201
228
|
}
|
|
202
229
|
return e;
|
|
203
230
|
}
|
|
204
|
-
function
|
|
231
|
+
function K(n, e, s, o, i, c = "i18n-locale") {
|
|
205
232
|
const f = v();
|
|
206
233
|
let t = o;
|
|
207
234
|
if (f?.getLocaleFromPath)
|
|
@@ -218,7 +245,7 @@ function V(n, e, s, o, i, c = "i18n-locale") {
|
|
|
218
245
|
try {
|
|
219
246
|
const l = s.get("accept-language");
|
|
220
247
|
if (l) {
|
|
221
|
-
const r =
|
|
248
|
+
const r = W(l);
|
|
222
249
|
for (const a of r)
|
|
223
250
|
if (i.includes(a)) {
|
|
224
251
|
t = a;
|
|
@@ -229,6 +256,89 @@ function V(n, e, s, o, i, c = "i18n-locale") {
|
|
|
229
256
|
}
|
|
230
257
|
return t;
|
|
231
258
|
}
|
|
259
|
+
function Q(n, e, s) {
|
|
260
|
+
const o = n.map((a) => a.code), i = (a, u = []) => {
|
|
261
|
+
const h = a.replace(/^\//, "").replace(/\/$/, "");
|
|
262
|
+
if (!h)
|
|
263
|
+
return "index";
|
|
264
|
+
const d = h.split("/").filter(Boolean), m = d[0];
|
|
265
|
+
return m && u.includes(m) && d.shift(), d.length === 0 ? "index" : d.join("-");
|
|
266
|
+
}, c = (a, u = "en", h = []) => {
|
|
267
|
+
const m = a.split("/").filter(Boolean)[0];
|
|
268
|
+
return m && h.includes(m) ? m : u;
|
|
269
|
+
}, f = (a, u, h = [], d) => {
|
|
270
|
+
const m = a.split("/").filter(Boolean), g = m[0];
|
|
271
|
+
return g && h.includes(g) && m.shift(), (u !== d || d === void 0) && m.unshift(u), `/${m.join("/")}`;
|
|
272
|
+
}, t = (a, u, h = [], d) => {
|
|
273
|
+
const g = (a.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), p = g[0];
|
|
274
|
+
return p && h.includes(p) && g.shift(), (u !== d || d === void 0) && g.unshift(u), `/${g.join("/")}`;
|
|
275
|
+
};
|
|
276
|
+
return {
|
|
277
|
+
getCurrentPath: () => s ? s().pathname : typeof window < "u" ? window.location.pathname : "/",
|
|
278
|
+
getRouteName: i,
|
|
279
|
+
getLocaleFromPath: c,
|
|
280
|
+
switchLocalePath: f,
|
|
281
|
+
localizePath: t,
|
|
282
|
+
removeLocaleFromPath: (a, u = []) => {
|
|
283
|
+
const h = a.split("/").filter(Boolean), d = h[0];
|
|
284
|
+
return d && u.includes(d) && h.shift(), `/${h.join("/")}`;
|
|
285
|
+
},
|
|
286
|
+
resolvePath: (a, u) => {
|
|
287
|
+
const h = typeof a == "string" ? a : a.path || "/";
|
|
288
|
+
return t(h, u, o, e);
|
|
289
|
+
},
|
|
290
|
+
getRoute: () => {
|
|
291
|
+
if (s) {
|
|
292
|
+
const a = s();
|
|
293
|
+
return {
|
|
294
|
+
fullPath: a.pathname + a.search,
|
|
295
|
+
query: Object.fromEntries(a.searchParams)
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
if (typeof window < "u") {
|
|
299
|
+
const a = new URL(window.location.href);
|
|
300
|
+
return {
|
|
301
|
+
fullPath: a.pathname + a.search,
|
|
302
|
+
query: Object.fromEntries(a.searchParams)
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
fullPath: "/",
|
|
307
|
+
query: {}
|
|
308
|
+
};
|
|
309
|
+
},
|
|
310
|
+
// Optional: client-side navigation for islands
|
|
311
|
+
push: (a) => {
|
|
312
|
+
typeof window < "u" && (window.location.href = a.path);
|
|
313
|
+
},
|
|
314
|
+
replace: (a) => {
|
|
315
|
+
typeof window < "u" && window.location.replace(a.path);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
function X(n, e = []) {
|
|
320
|
+
const s = n.replace(/^\//, "").replace(/\/$/, "");
|
|
321
|
+
if (!s)
|
|
322
|
+
return "index";
|
|
323
|
+
const o = s.split("/").filter(Boolean), i = o[0];
|
|
324
|
+
return i && e.includes(i) && o.shift(), o.length === 0 ? "index" : o.join("-");
|
|
325
|
+
}
|
|
326
|
+
function Y(n, e = "en", s = []) {
|
|
327
|
+
const i = n.split("/").filter(Boolean)[0];
|
|
328
|
+
return i && s.includes(i) ? i : e;
|
|
329
|
+
}
|
|
330
|
+
function Z(n, e, s = [], o) {
|
|
331
|
+
const i = n.split("/").filter(Boolean), c = i[0];
|
|
332
|
+
return c && s.includes(c) && i.shift(), (e !== o || o === void 0) && i.unshift(e), `/${i.join("/")}`;
|
|
333
|
+
}
|
|
334
|
+
function x(n, e, s = [], o) {
|
|
335
|
+
const c = (n.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), f = c[0];
|
|
336
|
+
return f && s.includes(f) && c.shift(), (e !== o || o === void 0) && c.unshift(e), `/${c.join("/")}`;
|
|
337
|
+
}
|
|
338
|
+
function ee(n, e = []) {
|
|
339
|
+
const s = n.split("/").filter(Boolean), o = s[0];
|
|
340
|
+
return o && e.includes(o) && s.shift(), `/${s.join("/")}`;
|
|
341
|
+
}
|
|
232
342
|
function k(n) {
|
|
233
343
|
const e = n.locals.i18n;
|
|
234
344
|
if (!e)
|
|
@@ -247,7 +357,7 @@ function $(n) {
|
|
|
247
357
|
function D(n) {
|
|
248
358
|
return n.locals.routingStrategy || null;
|
|
249
359
|
}
|
|
250
|
-
function
|
|
360
|
+
function te(n) {
|
|
251
361
|
const e = k(n), s = T(n), o = w(n), i = $(n), c = i.map((t) => t.code), f = D(n);
|
|
252
362
|
return {
|
|
253
363
|
// Current locale
|
|
@@ -318,12 +428,8 @@ function K(n) {
|
|
|
318
428
|
}
|
|
319
429
|
};
|
|
320
430
|
}
|
|
321
|
-
function
|
|
322
|
-
const {
|
|
323
|
-
baseUrl: s = "/",
|
|
324
|
-
addDirAttribute: o = !0,
|
|
325
|
-
addSeoAttributes: i = !0
|
|
326
|
-
} = e, c = T(n), f = w(n), t = $(n), l = t.find((g) => g.code === c);
|
|
431
|
+
function ne(n, e = {}) {
|
|
432
|
+
const { baseUrl: s = "/", addDirAttribute: o = !0, addSeoAttributes: i = !0 } = e, c = T(n), f = w(n), t = $(n), l = t.find((g) => g.code === c);
|
|
327
433
|
if (!l)
|
|
328
434
|
return { htmlAttrs: {}, link: [], meta: [] };
|
|
329
435
|
const r = l.iso || c, a = l.dir || "auto", u = {
|
|
@@ -376,7 +482,7 @@ function Q(n, e = {}) {
|
|
|
376
482
|
});
|
|
377
483
|
return u;
|
|
378
484
|
}
|
|
379
|
-
function
|
|
485
|
+
function A(n, e, s) {
|
|
380
486
|
const o = e.split(".");
|
|
381
487
|
let i = n;
|
|
382
488
|
for (let f = 0; f < o.length - 1; f++) {
|
|
@@ -386,13 +492,13 @@ function W(n, e, s) {
|
|
|
386
492
|
const c = o[o.length - 1];
|
|
387
493
|
c !== void 0 && (i[c] = s);
|
|
388
494
|
}
|
|
389
|
-
function
|
|
495
|
+
function oe(n, e) {
|
|
390
496
|
const s = k(n), o = T(n), i = w(n), c = s.getRoute(), f = {};
|
|
391
497
|
if (e && e.length > 0) {
|
|
392
498
|
const t = {};
|
|
393
499
|
for (const l of e) {
|
|
394
500
|
const r = s.t(l, void 0, void 0, c);
|
|
395
|
-
r != null && r !== l &&
|
|
501
|
+
r != null && r !== l && A(t, l, r);
|
|
396
502
|
}
|
|
397
503
|
Object.keys(t).length > 0 && (f[c] = t);
|
|
398
504
|
} else {
|
|
@@ -406,143 +512,28 @@ function X(n, e) {
|
|
|
406
512
|
translations: f
|
|
407
513
|
};
|
|
408
514
|
}
|
|
409
|
-
function Y(n, e, s) {
|
|
410
|
-
const o = n.map((a) => a.code), i = (a, u = []) => {
|
|
411
|
-
const h = a.replace(/^\//, "").replace(/\/$/, "");
|
|
412
|
-
if (!h)
|
|
413
|
-
return "index";
|
|
414
|
-
const d = h.split("/").filter(Boolean), m = d[0];
|
|
415
|
-
return m && u.includes(m) && d.shift(), d.length === 0 ? "index" : d.join("-");
|
|
416
|
-
}, c = (a, u = "en", h = []) => {
|
|
417
|
-
const m = a.split("/").filter(Boolean)[0];
|
|
418
|
-
return m && h.includes(m) ? m : u;
|
|
419
|
-
}, f = (a, u, h = [], d) => {
|
|
420
|
-
const m = a.split("/").filter(Boolean), g = m[0];
|
|
421
|
-
return g && h.includes(g) && m.shift(), (u !== d || d === void 0) && m.unshift(u), `/${m.join("/")}`;
|
|
422
|
-
}, t = (a, u, h = [], d) => {
|
|
423
|
-
const g = (a.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), p = g[0];
|
|
424
|
-
return p && h.includes(p) && g.shift(), (u !== d || d === void 0) && g.unshift(u), `/${g.join("/")}`;
|
|
425
|
-
};
|
|
426
|
-
return {
|
|
427
|
-
getCurrentPath: () => s ? s().pathname : typeof window < "u" ? window.location.pathname : "/",
|
|
428
|
-
getRouteName: i,
|
|
429
|
-
getLocaleFromPath: c,
|
|
430
|
-
switchLocalePath: f,
|
|
431
|
-
localizePath: t,
|
|
432
|
-
removeLocaleFromPath: (a, u = []) => {
|
|
433
|
-
const h = a.split("/").filter(Boolean), d = h[0];
|
|
434
|
-
return d && u.includes(d) && h.shift(), `/${h.join("/")}`;
|
|
435
|
-
},
|
|
436
|
-
resolvePath: (a, u) => {
|
|
437
|
-
const h = typeof a == "string" ? a : a.path || "/";
|
|
438
|
-
return t(h, u, o, e);
|
|
439
|
-
},
|
|
440
|
-
getRoute: () => {
|
|
441
|
-
if (s) {
|
|
442
|
-
const a = s();
|
|
443
|
-
return {
|
|
444
|
-
fullPath: a.pathname + a.search,
|
|
445
|
-
query: Object.fromEntries(a.searchParams)
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
if (typeof window < "u") {
|
|
449
|
-
const a = new URL(window.location.href);
|
|
450
|
-
return {
|
|
451
|
-
fullPath: a.pathname + a.search,
|
|
452
|
-
query: Object.fromEntries(a.searchParams)
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
return {
|
|
456
|
-
fullPath: "/",
|
|
457
|
-
query: {}
|
|
458
|
-
};
|
|
459
|
-
},
|
|
460
|
-
// Optional: client-side navigation for islands
|
|
461
|
-
push: (a) => {
|
|
462
|
-
typeof window < "u" && (window.location.href = a.path);
|
|
463
|
-
},
|
|
464
|
-
replace: (a) => {
|
|
465
|
-
typeof window < "u" && window.location.replace(a.path);
|
|
466
|
-
}
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
function Z(n, e = []) {
|
|
470
|
-
const s = n.replace(/^\//, "").replace(/\/$/, "");
|
|
471
|
-
if (!s)
|
|
472
|
-
return "index";
|
|
473
|
-
const o = s.split("/").filter(Boolean), i = o[0];
|
|
474
|
-
return i && e.includes(i) && o.shift(), o.length === 0 ? "index" : o.join("-");
|
|
475
|
-
}
|
|
476
|
-
function x(n, e = "en", s = []) {
|
|
477
|
-
const i = n.split("/").filter(Boolean)[0];
|
|
478
|
-
return i && s.includes(i) ? i : e;
|
|
479
|
-
}
|
|
480
|
-
function ee(n, e, s = [], o) {
|
|
481
|
-
const i = n.split("/").filter(Boolean), c = i[0];
|
|
482
|
-
return c && s.includes(c) && i.shift(), (e !== o || o === void 0) && i.unshift(e), `/${i.join("/")}`;
|
|
483
|
-
}
|
|
484
|
-
function te(n, e, s = [], o) {
|
|
485
|
-
const c = (n.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), f = c[0];
|
|
486
|
-
return f && s.includes(f) && c.shift(), (e !== o || o === void 0) && c.unshift(e), `/${c.join("/")}`;
|
|
487
|
-
}
|
|
488
|
-
function ne(n, e = []) {
|
|
489
|
-
const s = n.split("/").filter(Boolean), o = s[0];
|
|
490
|
-
return o && e.includes(o) && s.shift(), `/${s.join("/")}`;
|
|
491
|
-
}
|
|
492
|
-
function A(n) {
|
|
493
|
-
const { translationDir: e, rootDir: s = process.cwd(), disablePageLocales: o = !1 } = n, i = O(s, e);
|
|
494
|
-
if (!R(i))
|
|
495
|
-
return console.warn(`[i18n] Translation directory not found: ${i}`), { general: {}, routes: {} };
|
|
496
|
-
const c = {}, f = {}, t = (l, r = "") => {
|
|
497
|
-
if (!R(l)) return;
|
|
498
|
-
const a = _(l);
|
|
499
|
-
for (const u of a) {
|
|
500
|
-
const h = q(l, u);
|
|
501
|
-
if (C(h).isDirectory())
|
|
502
|
-
u === "pages" && !o ? t(h, "") : r || o ? t(h, r) : t(h, u);
|
|
503
|
-
else if (u.endsWith(".json")) {
|
|
504
|
-
const m = u.replace(".json", "");
|
|
505
|
-
try {
|
|
506
|
-
const g = N(h, "utf-8"), p = JSON.parse(g);
|
|
507
|
-
r && !o ? (f[r] || (f[r] = {}), f[r][m] = p) : c[m] = p;
|
|
508
|
-
} catch (g) {
|
|
509
|
-
console.error(`[i18n] Failed to load translation file: ${h}`, g);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
};
|
|
514
|
-
return t(i), { general: c, routes: f };
|
|
515
|
-
}
|
|
516
|
-
function oe(n, e) {
|
|
517
|
-
const { general: s, routes: o } = A(e);
|
|
518
|
-
for (const [i, c] of Object.entries(s))
|
|
519
|
-
n.addTranslations(i, c, !1);
|
|
520
|
-
for (const [i, c] of Object.entries(o))
|
|
521
|
-
for (const [f, t] of Object.entries(c))
|
|
522
|
-
n.addRouteTranslations(f, i, t, !1);
|
|
523
|
-
}
|
|
524
515
|
export {
|
|
525
516
|
S as AstroI18n,
|
|
526
517
|
le as FormatService,
|
|
527
|
-
|
|
518
|
+
Q as createAstroRouterAdapter,
|
|
528
519
|
E as createI18n,
|
|
529
|
-
|
|
520
|
+
V as createI18nMiddleware,
|
|
530
521
|
re as defaultPlural,
|
|
531
|
-
|
|
522
|
+
K as detectLocale,
|
|
532
523
|
w as getDefaultLocale,
|
|
533
524
|
k as getI18n,
|
|
534
|
-
|
|
525
|
+
oe as getI18nProps,
|
|
535
526
|
T as getLocale,
|
|
536
|
-
|
|
527
|
+
Y as getLocaleFromPath,
|
|
537
528
|
$ as getLocales,
|
|
538
|
-
|
|
529
|
+
X as getRouteName,
|
|
539
530
|
U as i18nIntegration,
|
|
540
531
|
ie as interpolate,
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
532
|
+
M as loadTranslationsFromDir,
|
|
533
|
+
J as loadTranslationsIntoI18n,
|
|
534
|
+
x as localizePath,
|
|
535
|
+
ee as removeLocaleFromPath,
|
|
536
|
+
Z as switchLocalePath,
|
|
537
|
+
te as useI18n,
|
|
538
|
+
ne as useLocaleHead
|
|
548
539
|
};
|
package/dist/integration.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { Locale, ModuleOptions, PluralFunc } from '@i18n-micro/types';
|
|
1
2
|
import { AstroIntegration } from 'astro';
|
|
2
3
|
import { AstroI18n, AstroI18nOptions } from './composer';
|
|
3
|
-
import { Locale, ModuleOptions, PluralFunc } from '@i18n-micro/types';
|
|
4
4
|
import { I18nRoutingStrategy } from './router/types';
|
|
5
5
|
export interface I18nIntegrationOptions extends Omit<ModuleOptions, 'plural'> {
|
|
6
6
|
locale: string;
|
package/dist/middleware.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AstroI18n } from './composer';
|
|
2
|
-
import { MiddlewareHandler } from 'astro';
|
|
3
1
|
import { Locale } from '@i18n-micro/types';
|
|
2
|
+
import { MiddlewareHandler } from 'astro';
|
|
3
|
+
import { AstroI18n } from './composer';
|
|
4
4
|
import { I18nRoutingStrategy } from './router/types';
|
|
5
5
|
export interface I18nMiddlewareOptions {
|
|
6
6
|
i18n: AstroI18n;
|
package/dist/router/adapter.d.ts
CHANGED
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Params, Locale, CleanTranslation, TranslationKey, Translations } from '@i18n-micro/types';
|
|
1
|
+
import { CleanTranslation, Locale, Params, TranslationKey, Translations } from '@i18n-micro/types';
|
|
3
2
|
import { AstroGlobal } from 'astro';
|
|
3
|
+
import { AstroI18n } from './composer';
|
|
4
4
|
/**
|
|
5
5
|
* Get i18n instance from Astro context
|
|
6
6
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@i18n-micro/astro",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@i18n-micro/core": "1.1.
|
|
55
|
-
"@i18n-micro/
|
|
56
|
-
"@i18n-micro/
|
|
54
|
+
"@i18n-micro/core": "1.1.2",
|
|
55
|
+
"@i18n-micro/types": "1.1.1",
|
|
56
|
+
"@i18n-micro/node": "1.1.1"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"astro": "^5.16.5",
|
package/src/client/core.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Translations, Params } from '@i18n-micro/types'
|
|
2
1
|
import { interpolate } from '@i18n-micro/core'
|
|
2
|
+
import type { Params, Translations } from '@i18n-micro/types'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Состояние i18n для клиентских островов
|
|
@@ -23,15 +23,13 @@ function findTranslation<T = unknown>(translations: Translations | null, key: st
|
|
|
23
23
|
// Прямой доступ к ключу
|
|
24
24
|
if (translations[key]) {
|
|
25
25
|
value = translations[key]
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
26
|
+
} else {
|
|
28
27
|
// Поиск по вложенным ключам (например, "nested.message")
|
|
29
28
|
const parts = key.toString().split('.')
|
|
30
29
|
for (const part of parts) {
|
|
31
30
|
if (value && typeof value === 'object' && value !== null && part in value) {
|
|
32
31
|
value = (value as Translations)[part]
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
32
|
+
} else {
|
|
35
33
|
return null
|
|
36
34
|
}
|
|
37
35
|
}
|
|
@@ -76,7 +74,7 @@ export function translate(
|
|
|
76
74
|
|
|
77
75
|
// 3. Если не найдено, используем defaultValue или key
|
|
78
76
|
if (!value) {
|
|
79
|
-
value = defaultValue === undefined ? key :
|
|
77
|
+
value = defaultValue === undefined ? key : defaultValue || key
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
// 4. Интерполяция параметров (только для строк)
|
|
@@ -92,11 +90,7 @@ export function translate(
|
|
|
92
90
|
/**
|
|
93
91
|
* Проверяет наличие перевода в состоянии
|
|
94
92
|
*/
|
|
95
|
-
export function hasTranslation(
|
|
96
|
-
state: I18nState,
|
|
97
|
-
key: string,
|
|
98
|
-
routeName?: string,
|
|
99
|
-
): boolean {
|
|
93
|
+
export function hasTranslation(state: I18nState, key: string, routeName?: string): boolean {
|
|
100
94
|
const route = routeName || state.currentRoute
|
|
101
95
|
const routeTranslations = state.translations[route]
|
|
102
96
|
const generalTranslations = state.translations.general
|
package/src/client/index.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
// Core utilities (чистые функции)
|
|
2
|
-
export { translate, hasTranslation } from './core'
|
|
3
|
-
export type { I18nState } from './core'
|
|
4
|
-
|
|
5
|
-
// Vue adapter
|
|
6
|
-
export { provideI18n, useAstroI18n as useAstroI18nVue } from './vue'
|
|
7
|
-
|
|
8
|
-
// React adapter
|
|
9
|
-
export { I18nProvider, useAstroI18n as useAstroI18nReact } from './react'
|
|
10
2
|
|
|
3
|
+
export type { I18nState } from './core'
|
|
4
|
+
export { hasTranslation, translate } from './core'
|
|
11
5
|
// Preact adapter
|
|
12
6
|
export { I18nProvider as I18nProviderPreact, useAstroI18n as useAstroI18nPreact } from './preact'
|
|
13
7
|
|
|
8
|
+
// React adapter
|
|
9
|
+
export { I18nProvider, useAstroI18n as useAstroI18nReact } from './react'
|
|
14
10
|
// Svelte adapter
|
|
15
11
|
export { createI18nStore, useAstroI18n as useAstroI18nSvelte } from './svelte'
|
|
12
|
+
// Vue adapter
|
|
13
|
+
export { provideI18n, useAstroI18n as useAstroI18nVue } from './vue'
|
package/src/client/preact.tsx
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// Preact может использовать React Context API, так как Preact совместим с React
|
|
2
|
+
|
|
3
|
+
import { defaultPlural, FormatService } from '@i18n-micro/core'
|
|
4
|
+
import type { CleanTranslation, Params, TranslationKey } from '@i18n-micro/types'
|
|
2
5
|
import type { ComponentChildren } from 'preact'
|
|
3
6
|
import { createContext, createElement } from 'preact'
|
|
4
|
-
import { useContext,
|
|
7
|
+
import { useContext, useMemo, useState } from 'preact/hooks'
|
|
5
8
|
import type { I18nClientProps } from '../utils'
|
|
6
|
-
import {
|
|
7
|
-
import { defaultPlural, FormatService } from '@i18n-micro/core'
|
|
8
|
-
import type { Params, TranslationKey, CleanTranslation } from '@i18n-micro/types'
|
|
9
|
+
import { hasTranslation, type I18nState, translate } from './core'
|
|
9
10
|
|
|
10
11
|
const formatter = new FormatService()
|
|
11
12
|
|
|
@@ -14,7 +15,7 @@ const I18nContext = createContext<I18nState | null>(null)
|
|
|
14
15
|
/**
|
|
15
16
|
* Провайдер для i18n в Preact островах
|
|
16
17
|
*/
|
|
17
|
-
export const I18nProvider = ({ children, value }: { children: ComponentChildren
|
|
18
|
+
export const I18nProvider = ({ children, value }: { children: ComponentChildren; value: I18nClientProps }) => {
|
|
18
19
|
const [state] = useState<I18nState>(() => ({
|
|
19
20
|
locale: value.locale,
|
|
20
21
|
fallbackLocale: value.fallbackLocale,
|
|
@@ -34,62 +35,74 @@ export function useAstroI18n() {
|
|
|
34
35
|
throw new Error('useAstroI18n must be used within an I18nProvider')
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
const t = useMemo(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const td = useMemo(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
38
|
+
const t = useMemo(
|
|
39
|
+
() =>
|
|
40
|
+
(key: TranslationKey, params?: Params, defaultValue?: string | null, routeName?: string): CleanTranslation => {
|
|
41
|
+
return translate(state, key as string, params, defaultValue, routeName)
|
|
42
|
+
},
|
|
43
|
+
[state],
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
const ts = useMemo(
|
|
47
|
+
() =>
|
|
48
|
+
(key: TranslationKey, params?: Params, defaultValue?: string, routeName?: string): string => {
|
|
49
|
+
const value = t(key, params, defaultValue, routeName)
|
|
50
|
+
return value?.toString() ?? defaultValue ?? (key as string)
|
|
51
|
+
},
|
|
52
|
+
[t],
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
const tc = useMemo(
|
|
56
|
+
() =>
|
|
57
|
+
(key: TranslationKey, count: number | Params, defaultValue?: string): string => {
|
|
58
|
+
const { count: countValue, ...params } = typeof count === 'number' ? { count } : count
|
|
59
|
+
|
|
60
|
+
if (countValue === undefined) {
|
|
61
|
+
return defaultValue ?? (key as string)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const getter = (k: TranslationKey, p?: Params, dv?: string) => {
|
|
65
|
+
return t(k, p, dv)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const result = defaultPlural(key, Number.parseInt(countValue.toString(), 10), params, state.locale, getter)
|
|
69
|
+
|
|
70
|
+
return result ?? defaultValue ?? (key as string)
|
|
71
|
+
},
|
|
72
|
+
[t, state],
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
const tn = useMemo(
|
|
76
|
+
() =>
|
|
77
|
+
(value: number, options?: Intl.NumberFormatOptions): string => {
|
|
78
|
+
return formatter.formatNumber(value, state.locale, options)
|
|
79
|
+
},
|
|
80
|
+
[state.locale],
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
const td = useMemo(
|
|
84
|
+
() =>
|
|
85
|
+
(value: Date | number | string, options?: Intl.DateTimeFormatOptions): string => {
|
|
86
|
+
return formatter.formatDate(value, state.locale, options)
|
|
87
|
+
},
|
|
88
|
+
[state.locale],
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
const tdr = useMemo(
|
|
92
|
+
() =>
|
|
93
|
+
(value: Date | number | string, options?: Intl.RelativeTimeFormatOptions): string => {
|
|
94
|
+
return formatter.formatRelativeTime(value, state.locale, options)
|
|
95
|
+
},
|
|
96
|
+
[state.locale],
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
const has = useMemo(
|
|
100
|
+
() =>
|
|
101
|
+
(key: TranslationKey, routeName?: string): boolean => {
|
|
102
|
+
return hasTranslation(state, key as string, routeName)
|
|
103
|
+
},
|
|
104
|
+
[state],
|
|
105
|
+
)
|
|
93
106
|
|
|
94
107
|
return {
|
|
95
108
|
// Translation methods
|