@i18n-micro/node 1.0.0 → 1.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/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -65
- package/dist/index.mjs +60 -112
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("node:fs/promises"),c=require("node:path"),h=require("@i18n-micro/core");async function f(o,e=!1){const a={global:{},routes:{}};try{const t=await p.readdir(o,{recursive:!0,withFileTypes:!0});for(const r of t){if(!r.isFile()||!r.name.endsWith(".json"))continue;const s=c.join(r.path,r.name),n=c.relative(o,s).split(c.sep),i=c.basename(r.name,".json");try{const u=await p.readFile(s,"utf-8"),g=JSON.parse(u);if(!e&&n[0]==="pages"&&n.length>=2){const b=n.slice(1,-1);if(b.length>0){const d=b.join("-");a.routes[d]||(a.routes[d]={}),a.routes[d][i]=g}}else a.global[i]=g}catch(u){console.error(`Failed to load translation file ${s}:`,u)}}}catch(t){t&&typeof t=="object"&&"code"in t&&t.code!=="ENOENT"&&console.error(`Failed to read directory ${o}:`,t)}return a}async function T(o,e=!1){const{global:a}=await f(o,e);return a}class m extends h.BaseI18n{constructor(e){const a={translations:new Map};super({storage:a,plural:e.plural,missingWarn:e.missingWarn,missingHandler:e.missingHandler}),this.currentRoute="general",this.locale=e.locale,this.fallbackLocale=e.fallbackLocale||e.locale,this.translationDir=e.translationDir,this.disablePageLocales=e.disablePageLocales??!1}setRoute(e){this.currentRoute=e}getLocale(){return this.locale}getFallbackLocale(){return this.fallbackLocale}getRoute(){return this.currentRoute}async loadTranslations(e){const a=e||this.translationDir;if(!a){console.warn("[i18n-node] No translation directory specified");return}const{global:t,routes:r}=await f(a,this.disablePageLocales);for(const[s,l]of Object.entries(t))this.helper.mergeGlobalTranslation(s,l,!0);for(const[s,l]of Object.entries(r))for(const[n,i]of Object.entries(l))this.helper.loadPageTranslations(n,s,i)}async reload(){this.helper.clearCache(),await this.loadTranslations(),console.log("[i18n-node] Cache cleared and translations reloaded.")}addTranslations(e,a,t=!0){super.loadTranslationsCore(e,a,t)}addRouteTranslations(e,a,t,r=!0){super.loadRouteTranslationsCore(e,a,t,r)}hasTranslation(e){return this.helper.hasTranslation(this.locale,e)}clear(){super.clearCache()}}function y(o){return new m(o)}Object.defineProperty(exports,"FormatService",{enumerable:!0,get:()=>h.FormatService});Object.defineProperty(exports,"interpolate",{enumerable:!0,get:()=>h.interpolate});exports.I18n=m;exports.createI18n=y;exports.loadGlobalTranslations=T;exports.loadTranslations=f;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BaseI18n } from '@i18n-micro/core';
|
|
1
2
|
import { CleanTranslation } from '@i18n-micro/types';
|
|
2
3
|
import { FormatService } from '@i18n-micro/core';
|
|
3
4
|
import { Getter } from '@i18n-micro/types';
|
|
@@ -11,86 +12,24 @@ import { Translations } from '@i18n-micro/types';
|
|
|
11
12
|
|
|
12
13
|
export { CleanTranslation }
|
|
13
14
|
|
|
14
|
-
/**
|
|
15
|
-
* Create a new I18n instance
|
|
16
|
-
*/
|
|
17
15
|
export declare function createI18n(options: I18nOptions): I18n;
|
|
18
16
|
|
|
19
17
|
export { FormatService }
|
|
20
18
|
|
|
21
19
|
export { Getter }
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
* Node.js I18n Adapter
|
|
25
|
-
*
|
|
26
|
-
* Provides a standalone i18n instance that uses the shared core logic from nuxt-i18n-micro.
|
|
27
|
-
* Fully compatible with the file structure and caching mechanisms of the Nuxt module.
|
|
28
|
-
*/
|
|
29
|
-
export declare class I18n {
|
|
21
|
+
export declare class I18n extends BaseI18n {
|
|
30
22
|
locale: string;
|
|
31
23
|
fallbackLocale: string;
|
|
32
24
|
translationDir?: string;
|
|
33
25
|
private disablePageLocales;
|
|
34
|
-
/**
|
|
35
|
-
* Current active route name for translations.
|
|
36
|
-
* Defaults to 'general' (global translations only).
|
|
37
|
-
* Change this using setRoute() to access page-specific translations.
|
|
38
|
-
*/
|
|
39
26
|
currentRoute: string;
|
|
40
|
-
private cache;
|
|
41
|
-
readonly helper: {
|
|
42
|
-
hasCache(locale: string, page: string): boolean;
|
|
43
|
-
getCache(locale: string, routeName: string): Map<string, unknown> | undefined;
|
|
44
|
-
setCache(locale: string, routeName: string, cache: Map<string, Translations | unknown>): void;
|
|
45
|
-
mergeTranslation(locale: string, routeName: string, newTranslations: Translations, force?: boolean): void;
|
|
46
|
-
mergeGlobalTranslation(locale: string, newTranslations: Translations, force?: boolean): void;
|
|
47
|
-
hasGeneralTranslation(locale: string): boolean;
|
|
48
|
-
hasPageTranslation(locale: string, routeName: string): boolean;
|
|
49
|
-
hasTranslation: (locale: string, key: TranslationKey) => boolean;
|
|
50
|
-
getTranslation: <T = unknown>(locale: string, routeName: string, key: TranslationKey) => T | null;
|
|
51
|
-
loadPageTranslations(locale: string, routeName: string, translations: Translations): Promise<void>;
|
|
52
|
-
loadTranslations(locale: string, translations: Translations): Promise<void>;
|
|
53
|
-
clearCache(): void;
|
|
54
|
-
};
|
|
55
|
-
private formatter;
|
|
56
|
-
private pluralFunc;
|
|
57
|
-
private missingWarn;
|
|
58
|
-
private missingHandler?;
|
|
59
27
|
constructor(options: I18nOptions);
|
|
60
|
-
/**
|
|
61
|
-
* Set the current route name context.
|
|
62
|
-
* Useful when processing a specific page request in Node.
|
|
63
|
-
*/
|
|
64
28
|
setRoute(routeName: string): void;
|
|
29
|
+
getLocale(): string;
|
|
30
|
+
getFallbackLocale(): string;
|
|
65
31
|
getRoute(): string;
|
|
66
|
-
/**
|
|
67
|
-
* Get translation for a key
|
|
68
|
-
*
|
|
69
|
-
* Search order:
|
|
70
|
-
* 1. Current Locale + Current Route (Specific)
|
|
71
|
-
* 2. Current Locale + General (Global)
|
|
72
|
-
* 3. Fallback Locale + Current Route
|
|
73
|
-
* 4. Fallback Locale + General
|
|
74
|
-
*/
|
|
75
|
-
t(key: TranslationKey, params?: Params, defaultValue?: string | null, routeName?: string): string;
|
|
76
|
-
/**
|
|
77
|
-
* Get translation as string
|
|
78
|
-
*/
|
|
79
|
-
ts(key: TranslationKey, params?: Params, defaultValue?: string, routeName?: string): string;
|
|
80
|
-
/**
|
|
81
|
-
* Plural translation
|
|
82
|
-
*/
|
|
83
|
-
tc(key: TranslationKey, count: number | Params, defaultValue?: string): string;
|
|
84
|
-
tn(value: number, options?: Intl.NumberFormatOptions): string;
|
|
85
|
-
td(value: Date | number | string, options?: Intl.DateTimeFormatOptions): string;
|
|
86
|
-
tdr(value: Date | number | string, options?: Intl.RelativeTimeFormatOptions): string;
|
|
87
|
-
/**
|
|
88
|
-
* Load translations from directory.
|
|
89
|
-
*/
|
|
90
32
|
loadTranslations(dir?: string): Promise<void>;
|
|
91
|
-
/**
|
|
92
|
-
* Clear cache and reload translations from disk
|
|
93
|
-
*/
|
|
94
33
|
reload(): Promise<void>;
|
|
95
34
|
addTranslations(locale: string, translations: Translations, merge?: boolean): void;
|
|
96
35
|
addRouteTranslations(locale: string, routeName: string, translations: Translations, merge?: boolean): void;
|
package/dist/index.mjs
CHANGED
|
@@ -1,154 +1,102 @@
|
|
|
1
|
-
import { readdir as
|
|
2
|
-
import { join as p, relative as
|
|
3
|
-
import {
|
|
4
|
-
import { FormatService as
|
|
5
|
-
async function
|
|
6
|
-
const
|
|
1
|
+
import { readdir as g, readFile as m } from "node:fs/promises";
|
|
2
|
+
import { join as p, relative as b, sep as T, basename as y } from "node:path";
|
|
3
|
+
import { BaseI18n as w } from "@i18n-micro/core";
|
|
4
|
+
import { FormatService as O, interpolate as k } from "@i18n-micro/core";
|
|
5
|
+
async function f(o, e = !1) {
|
|
6
|
+
const a = {
|
|
7
7
|
global: {},
|
|
8
8
|
routes: {}
|
|
9
9
|
};
|
|
10
10
|
try {
|
|
11
|
-
const
|
|
12
|
-
for (const
|
|
13
|
-
if (!
|
|
11
|
+
const t = await g(o, { recursive: !0, withFileTypes: !0 });
|
|
12
|
+
for (const r of t) {
|
|
13
|
+
if (!r.isFile() || !r.name.endsWith(".json"))
|
|
14
14
|
continue;
|
|
15
|
-
const s = p(
|
|
15
|
+
const s = p(r.path, r.name), l = b(o, s).split(T), i = y(r.name, ".json");
|
|
16
16
|
try {
|
|
17
|
-
const c = await
|
|
18
|
-
if (!e &&
|
|
19
|
-
const
|
|
20
|
-
if (
|
|
21
|
-
const u =
|
|
22
|
-
|
|
17
|
+
const c = await m(s, "utf-8"), h = JSON.parse(c);
|
|
18
|
+
if (!e && l[0] === "pages" && l.length >= 2) {
|
|
19
|
+
const d = l.slice(1, -1);
|
|
20
|
+
if (d.length > 0) {
|
|
21
|
+
const u = d.join("-");
|
|
22
|
+
a.routes[u] || (a.routes[u] = {}), a.routes[u][i] = h;
|
|
23
23
|
}
|
|
24
24
|
} else
|
|
25
|
-
|
|
25
|
+
a.global[i] = h;
|
|
26
26
|
} catch (c) {
|
|
27
27
|
console.error(`Failed to load translation file ${s}:`, c);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
-
} catch (
|
|
31
|
-
|
|
30
|
+
} catch (t) {
|
|
31
|
+
t && typeof t == "object" && "code" in t && t.code !== "ENOENT" && console.error(`Failed to read directory ${o}:`, t);
|
|
32
32
|
}
|
|
33
|
-
return
|
|
33
|
+
return a;
|
|
34
34
|
}
|
|
35
|
-
async function
|
|
36
|
-
const { global:
|
|
37
|
-
return
|
|
35
|
+
async function R(o, e = !1) {
|
|
36
|
+
const { global: a } = await f(o, e);
|
|
37
|
+
return a;
|
|
38
38
|
}
|
|
39
|
-
class
|
|
39
|
+
class L extends w {
|
|
40
40
|
constructor(e) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
const a = {
|
|
42
|
+
translations: /* @__PURE__ */ new Map()
|
|
43
|
+
};
|
|
44
|
+
super({
|
|
45
|
+
storage: a,
|
|
46
|
+
plural: e.plural,
|
|
47
|
+
missingWarn: e.missingWarn,
|
|
48
|
+
missingHandler: e.missingHandler
|
|
49
|
+
}), this.currentRoute = "general", this.locale = e.locale, this.fallbackLocale = e.fallbackLocale || e.locale, this.translationDir = e.translationDir, this.disablePageLocales = e.disablePageLocales ?? !1;
|
|
47
50
|
}
|
|
48
|
-
/**
|
|
49
|
-
* Set the current route name context.
|
|
50
|
-
* Useful when processing a specific page request in Node.
|
|
51
|
-
*/
|
|
52
51
|
setRoute(e) {
|
|
53
52
|
this.currentRoute = e;
|
|
54
53
|
}
|
|
55
|
-
|
|
56
|
-
return this.
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Get translation for a key
|
|
60
|
-
*
|
|
61
|
-
* Search order:
|
|
62
|
-
* 1. Current Locale + Current Route (Specific)
|
|
63
|
-
* 2. Current Locale + General (Global)
|
|
64
|
-
* 3. Fallback Locale + Current Route
|
|
65
|
-
* 4. Fallback Locale + General
|
|
66
|
-
*/
|
|
67
|
-
t(e, t, r, a) {
|
|
68
|
-
if (!e) return "";
|
|
69
|
-
const s = a || this.currentRoute;
|
|
70
|
-
let l = this.helper.getTranslation(this.locale, s, e);
|
|
71
|
-
return !l && this.locale !== this.fallbackLocale && (l = this.helper.getTranslation(this.fallbackLocale, s, e)), l || (this.missingHandler ? this.missingHandler(this.locale, e, s) : this.missingWarn && console.warn(
|
|
72
|
-
`[i18n] Translation key '${e}' not found for locale '${this.locale}' (route: '${s}').`
|
|
73
|
-
), l = r === void 0 ? e : r || e), typeof l == "string" && t ? F(l, t) : l || e;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Get translation as string
|
|
77
|
-
*/
|
|
78
|
-
ts(e, t, r, a) {
|
|
79
|
-
return this.t(e, t, r, a)?.toString() ?? r ?? e;
|
|
54
|
+
getLocale() {
|
|
55
|
+
return this.locale;
|
|
80
56
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
*/
|
|
84
|
-
tc(e, t, r) {
|
|
85
|
-
const { count: a, ...s } = typeof t == "number" ? { count: t } : t;
|
|
86
|
-
if (a === void 0)
|
|
87
|
-
return r ?? e;
|
|
88
|
-
const l = (i, c, h) => this.t(i, c, h);
|
|
89
|
-
return this.pluralFunc(
|
|
90
|
-
e,
|
|
91
|
-
Number.parseInt(a.toString()),
|
|
92
|
-
s,
|
|
93
|
-
this.locale,
|
|
94
|
-
l
|
|
95
|
-
) ?? r ?? e;
|
|
57
|
+
getFallbackLocale() {
|
|
58
|
+
return this.fallbackLocale;
|
|
96
59
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return this.formatter.formatNumber(e, this.locale, t);
|
|
100
|
-
}
|
|
101
|
-
td(e, t) {
|
|
102
|
-
return this.formatter.formatDate(e, this.locale, t);
|
|
103
|
-
}
|
|
104
|
-
tdr(e, t) {
|
|
105
|
-
return this.formatter.formatRelativeTime(e, this.locale, t);
|
|
60
|
+
getRoute() {
|
|
61
|
+
return this.currentRoute;
|
|
106
62
|
}
|
|
107
|
-
// --- Loader & Cache Management ---
|
|
108
|
-
/**
|
|
109
|
-
* Load translations from directory.
|
|
110
|
-
*/
|
|
111
63
|
async loadTranslations(e) {
|
|
112
|
-
const
|
|
113
|
-
if (!
|
|
64
|
+
const a = e || this.translationDir;
|
|
65
|
+
if (!a) {
|
|
114
66
|
console.warn("[i18n-node] No translation directory specified");
|
|
115
67
|
return;
|
|
116
68
|
}
|
|
117
|
-
const { global:
|
|
118
|
-
for (const [s,
|
|
119
|
-
this.helper.mergeGlobalTranslation(s,
|
|
120
|
-
for (const [s,
|
|
121
|
-
for (const [
|
|
122
|
-
|
|
69
|
+
const { global: t, routes: r } = await f(a, this.disablePageLocales);
|
|
70
|
+
for (const [s, n] of Object.entries(t))
|
|
71
|
+
this.helper.mergeGlobalTranslation(s, n, !0);
|
|
72
|
+
for (const [s, n] of Object.entries(r))
|
|
73
|
+
for (const [l, i] of Object.entries(n))
|
|
74
|
+
this.helper.loadPageTranslations(l, s, i);
|
|
123
75
|
}
|
|
124
|
-
/**
|
|
125
|
-
* Clear cache and reload translations from disk
|
|
126
|
-
*/
|
|
127
76
|
async reload() {
|
|
128
77
|
this.helper.clearCache(), await this.loadTranslations(), console.log("[i18n-node] Cache cleared and translations reloaded.");
|
|
129
78
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
r ? this.helper.mergeGlobalTranslation(e, t, !0) : this.helper.loadTranslations(e, t);
|
|
79
|
+
addTranslations(e, a, t = !0) {
|
|
80
|
+
super.loadTranslationsCore(e, a, t);
|
|
133
81
|
}
|
|
134
|
-
addRouteTranslations(e, t, r
|
|
135
|
-
|
|
82
|
+
addRouteTranslations(e, a, t, r = !0) {
|
|
83
|
+
super.loadRouteTranslationsCore(e, a, t, r);
|
|
136
84
|
}
|
|
137
85
|
hasTranslation(e) {
|
|
138
86
|
return this.helper.hasTranslation(this.locale, e);
|
|
139
87
|
}
|
|
140
88
|
clear() {
|
|
141
|
-
|
|
89
|
+
super.clearCache();
|
|
142
90
|
}
|
|
143
91
|
}
|
|
144
|
-
function
|
|
145
|
-
return new
|
|
92
|
+
function N(o) {
|
|
93
|
+
return new L(o);
|
|
146
94
|
}
|
|
147
95
|
export {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
96
|
+
O as FormatService,
|
|
97
|
+
L as I18n,
|
|
98
|
+
N as createI18n,
|
|
99
|
+
k as interpolate,
|
|
100
|
+
R as loadGlobalTranslations,
|
|
101
|
+
f as loadTranslations
|
|
154
102
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@i18n-micro/node",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -22,16 +22,16 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@i18n-micro/
|
|
26
|
-
"@i18n-micro/
|
|
25
|
+
"@i18n-micro/types": "1.1.0",
|
|
26
|
+
"@i18n-micro/core": "1.1.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@types/node": "^20.
|
|
30
|
-
"vite": "^
|
|
31
|
-
"vite-plugin-dts": "^4.
|
|
29
|
+
"@types/node": "^20.19.26",
|
|
30
|
+
"vite": "^7.3.1",
|
|
31
|
+
"vite-plugin-dts": "^4.5.4",
|
|
32
32
|
"jest": "^29.7.0",
|
|
33
|
-
"ts-jest": "^29.
|
|
34
|
-
"@types/jest": "^29.5.
|
|
33
|
+
"ts-jest": "^29.4.6",
|
|
34
|
+
"@types/jest": "^29.5.14"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "vite build",
|