@astroscope/i18n 0.3.3 → 0.4.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/README.md +17 -0
- package/dist/chunk-FYKC3DAZ.js +36 -0
- package/dist/{chunk-Z3LDPCYD.js → chunk-IJXSX5DY.js} +9 -38
- package/dist/{chunk-MSJHXRJB.js → chunk-LXW5WYBS.js} +25 -0
- package/dist/client/translate.d.ts +1 -1
- package/dist/extraction/index.js +4 -2
- package/dist/{i18n-DaLnNvss.d.ts → i18n-BmK1MjH7.d.ts} +5 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -2
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +2 -1
- package/dist/server/translate.d.ts +1 -1
- package/dist/server/translate.js +2 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -421,6 +421,23 @@ For `:currency` and `:unit`, the required option (`currency` or `unit`) can be:
|
|
|
421
421
|
- `'throw'` — Throw an error
|
|
422
422
|
- `(key, meta) => string` — Custom function
|
|
423
423
|
|
|
424
|
+
## ESLint Plugin
|
|
425
|
+
|
|
426
|
+
Use [`@astroscope/eslint-plugin-i18n`](../eslint-plugin-i18n) to enforce correct `t()` usage, catch build-time extraction issues, and ensure i18n-aware hydration directives.
|
|
427
|
+
|
|
428
|
+
```bash
|
|
429
|
+
npm install -D @astroscope/eslint-plugin-i18n
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
```js
|
|
433
|
+
// eslint.config.js
|
|
434
|
+
import i18n from '@astroscope/eslint-plugin-i18n';
|
|
435
|
+
|
|
436
|
+
export default [
|
|
437
|
+
i18n.configs.recommended,
|
|
438
|
+
];
|
|
439
|
+
```
|
|
440
|
+
|
|
424
441
|
## License
|
|
425
442
|
|
|
426
443
|
MIT
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/extraction/manifest.ts
|
|
2
|
+
import path from "path";
|
|
3
|
+
var I18N_MANIFEST_GLOBAL_KEY = "__astroscope_i18n_manifest__";
|
|
4
|
+
function getGlobalState() {
|
|
5
|
+
const g = globalThis;
|
|
6
|
+
if (!g[I18N_MANIFEST_GLOBAL_KEY]) {
|
|
7
|
+
g[I18N_MANIFEST_GLOBAL_KEY] = {
|
|
8
|
+
extractedKeys: [],
|
|
9
|
+
chunkManifest: {},
|
|
10
|
+
importsManifest: {},
|
|
11
|
+
projectRoot: "",
|
|
12
|
+
version: 0
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return g[I18N_MANIFEST_GLOBAL_KEY];
|
|
16
|
+
}
|
|
17
|
+
function getManifest() {
|
|
18
|
+
const state = getGlobalState();
|
|
19
|
+
const keys = state.extractedKeys.map((key) => ({
|
|
20
|
+
...key,
|
|
21
|
+
// make file paths relative to project root for better readability
|
|
22
|
+
// and avoiding leaking absolute paths from dev or ci environments
|
|
23
|
+
files: key.files.map((fileLocation) => {
|
|
24
|
+
const [filePath, line] = fileLocation.split(":");
|
|
25
|
+
if (!filePath) return fileLocation;
|
|
26
|
+
const relativePath = state.projectRoot ? path.relative(state.projectRoot, filePath) : filePath;
|
|
27
|
+
return line ? `${relativePath}:${line}` : relativePath;
|
|
28
|
+
})
|
|
29
|
+
}));
|
|
30
|
+
return { keys, chunks: state.chunkManifest, imports: state.importsManifest };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
getGlobalState,
|
|
35
|
+
getManifest
|
|
36
|
+
};
|
|
@@ -1,41 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getGlobalState,
|
|
3
|
+
getManifest
|
|
4
|
+
} from "./chunk-FYKC3DAZ.js";
|
|
1
5
|
import {
|
|
2
6
|
chunkIdToName
|
|
3
7
|
} from "./chunk-4A5BKHFN.js";
|
|
4
8
|
|
|
5
|
-
// src/extraction/manifest.ts
|
|
6
|
-
import path from "path";
|
|
7
|
-
var I18N_MANIFEST_GLOBAL_KEY = "__astroscope_i18n_manifest__";
|
|
8
|
-
function getGlobalState() {
|
|
9
|
-
const g = globalThis;
|
|
10
|
-
if (!g[I18N_MANIFEST_GLOBAL_KEY]) {
|
|
11
|
-
g[I18N_MANIFEST_GLOBAL_KEY] = {
|
|
12
|
-
extractedKeys: [],
|
|
13
|
-
chunkManifest: {},
|
|
14
|
-
importsManifest: {},
|
|
15
|
-
projectRoot: ""
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
return g[I18N_MANIFEST_GLOBAL_KEY];
|
|
19
|
-
}
|
|
20
|
-
function getManifest() {
|
|
21
|
-
const state = getGlobalState();
|
|
22
|
-
const keys = state.extractedKeys.map((key) => ({
|
|
23
|
-
...key,
|
|
24
|
-
// make file paths relative to project root for better readability
|
|
25
|
-
// and avoiding leaking absolute paths from dev or ci environments
|
|
26
|
-
files: key.files.map((fileLocation) => {
|
|
27
|
-
const [filePath, line] = fileLocation.split(":");
|
|
28
|
-
if (!filePath) return fileLocation;
|
|
29
|
-
const relativePath = state.projectRoot ? path.relative(state.projectRoot, filePath) : filePath;
|
|
30
|
-
return line ? `${relativePath}:${line}` : relativePath;
|
|
31
|
-
})
|
|
32
|
-
}));
|
|
33
|
-
return { keys, chunks: state.chunkManifest, imports: state.importsManifest };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
9
|
// src/extraction/vite-plugin.ts
|
|
37
10
|
import fs2 from "fs";
|
|
38
|
-
import
|
|
11
|
+
import path from "path";
|
|
39
12
|
import MagicString from "magic-string";
|
|
40
13
|
|
|
41
14
|
// src/extraction/extract.ts
|
|
@@ -337,9 +310,9 @@ function i18nVitePlugin(options) {
|
|
|
337
310
|
const syncGlobalState = () => {
|
|
338
311
|
const state = getGlobalState();
|
|
339
312
|
state.extractedKeys = store.extractedKeys;
|
|
313
|
+
state.version++;
|
|
340
314
|
};
|
|
341
315
|
let isBuild = false;
|
|
342
|
-
let isSSR = false;
|
|
343
316
|
let projectRoot = "";
|
|
344
317
|
return {
|
|
345
318
|
name: "@astroscope/i18n/extract",
|
|
@@ -348,7 +321,6 @@ function i18nVitePlugin(options) {
|
|
|
348
321
|
const state = getGlobalState();
|
|
349
322
|
state.projectRoot = config.root;
|
|
350
323
|
isBuild = config.command === "build";
|
|
351
|
-
isSSR = !!config.build.ssr;
|
|
352
324
|
projectRoot = config.root;
|
|
353
325
|
},
|
|
354
326
|
async configureServer(server) {
|
|
@@ -485,9 +457,9 @@ export function getManifest() { return _getManifest(); }
|
|
|
485
457
|
}
|
|
486
458
|
},
|
|
487
459
|
writeBundle(outputOptions) {
|
|
488
|
-
if (
|
|
489
|
-
const chunksDir =
|
|
490
|
-
const manifestPath =
|
|
460
|
+
if (this.environment.name === "client" && outputOptions.dir) {
|
|
461
|
+
const chunksDir = path.resolve(outputOptions.dir, "..", "server", "chunks");
|
|
462
|
+
const manifestPath = path.join(chunksDir, MANIFEST_FILE_NAME);
|
|
491
463
|
if (fs2.existsSync(chunksDir)) {
|
|
492
464
|
fs2.writeFileSync(manifestPath, JSON.stringify(getManifest()));
|
|
493
465
|
} else {
|
|
@@ -499,6 +471,5 @@ export function getManifest() { return _getManifest(); }
|
|
|
499
471
|
}
|
|
500
472
|
|
|
501
473
|
export {
|
|
502
|
-
getManifest,
|
|
503
474
|
i18nVitePlugin
|
|
504
475
|
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
compileTranslations
|
|
3
3
|
} from "./chunk-33JVAFGQ.js";
|
|
4
|
+
import {
|
|
5
|
+
getGlobalState
|
|
6
|
+
} from "./chunk-FYKC3DAZ.js";
|
|
4
7
|
|
|
5
8
|
// src/extraction/hash.ts
|
|
6
9
|
import { createHash } from "crypto";
|
|
@@ -57,6 +60,8 @@ var I18nSingleton = class {
|
|
|
57
60
|
chunkCache = /* @__PURE__ */ new Map();
|
|
58
61
|
// manifest getter (set by init module, provides live data in dev mode)
|
|
59
62
|
manifestGetter = null;
|
|
63
|
+
// tracks the manifest version to detect when derived caches need invalidation
|
|
64
|
+
manifestVersion = 0;
|
|
60
65
|
async configure(config) {
|
|
61
66
|
if (!config.locales?.length) {
|
|
62
67
|
throw new Error("i18n.configure(): locales array is required and must not be empty");
|
|
@@ -108,12 +113,18 @@ var I18nSingleton = class {
|
|
|
108
113
|
this.compiledCache.delete(locale);
|
|
109
114
|
this.hashCache.delete(locale);
|
|
110
115
|
this.scriptCache.delete(locale);
|
|
116
|
+
for (const key of this.chunkCache.keys()) {
|
|
117
|
+
if (key.startsWith(`${locale}:`)) {
|
|
118
|
+
this.chunkCache.delete(key);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
111
121
|
const { chunks } = this.getManifest();
|
|
112
122
|
if (Object.keys(chunks).length > 0) {
|
|
113
123
|
this.hashCache.set(locale, computeAllChunkHashes(raw, chunks));
|
|
114
124
|
}
|
|
115
125
|
}
|
|
116
126
|
getTranslations(locale) {
|
|
127
|
+
this.invalidateIfManifestChanged();
|
|
117
128
|
const cached = this.mergedCache.get(locale);
|
|
118
129
|
if (cached) {
|
|
119
130
|
return cached;
|
|
@@ -244,6 +255,20 @@ var I18nSingleton = class {
|
|
|
244
255
|
}
|
|
245
256
|
}
|
|
246
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* invalidate derived caches when the extraction manifest has changed (dev mode HMR)
|
|
260
|
+
*/
|
|
261
|
+
invalidateIfManifestChanged() {
|
|
262
|
+
const { version } = getGlobalState();
|
|
263
|
+
if (version === this.manifestVersion) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
this.manifestVersion = version;
|
|
267
|
+
this.mergedCache.clear();
|
|
268
|
+
this.compiledCache.clear();
|
|
269
|
+
this.scriptCache.clear();
|
|
270
|
+
this.chunkCache.clear();
|
|
271
|
+
}
|
|
247
272
|
resolveLocales(locales) {
|
|
248
273
|
if (!locales) {
|
|
249
274
|
return this.config?.locales ?? [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { R as RichComponents } from '../rich-CQUhdwBc.js';
|
|
2
|
-
import {
|
|
2
|
+
import { T as TranslationMeta, a as TranslateFunction } from '../types-DNRFj1XA.js';
|
|
3
3
|
import '../types-BeDFfFIL.js';
|
|
4
4
|
|
|
5
5
|
declare function getLocale(): string;
|
package/dist/extraction/index.js
CHANGED
|
@@ -34,6 +34,7 @@ declare class I18nSingleton {
|
|
|
34
34
|
private scriptCache;
|
|
35
35
|
private chunkCache;
|
|
36
36
|
private manifestGetter;
|
|
37
|
+
private manifestVersion;
|
|
37
38
|
configure(config: I18nConfig): Promise<void>;
|
|
38
39
|
isConfigured(): boolean;
|
|
39
40
|
getConfig(): NormalizedConfig;
|
|
@@ -64,6 +65,10 @@ declare class I18nSingleton {
|
|
|
64
65
|
* @param locales - Locale(s) to clear, or all if not specified
|
|
65
66
|
*/
|
|
66
67
|
clear(locales?: string | string[] | undefined): void;
|
|
68
|
+
/**
|
|
69
|
+
* invalidate derived caches when the extraction manifest has changed (dev mode HMR)
|
|
70
|
+
*/
|
|
71
|
+
private invalidateIfManifestChanged;
|
|
67
72
|
private resolveLocales;
|
|
68
73
|
}
|
|
69
74
|
declare const i18n: I18nSingleton;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AstroIntegration,
|
|
1
|
+
import { AstroIntegration, APIContext, MiddlewareHandler } from 'astro';
|
|
2
2
|
import { I as I18nOptions } from './types-B_8vAmvv.js';
|
|
3
|
-
export { F as FallbackBehavior, I as I18nConfig, i as i18n } from './i18n-
|
|
3
|
+
export { F as FallbackBehavior, I as I18nConfig, i as i18n } from './i18n-BmK1MjH7.js';
|
|
4
4
|
import { ExcludePattern } from '@astroscope/excludes';
|
|
5
5
|
export { R as RawTranslations, T as TranslationMeta } from './types-DNRFj1XA.js';
|
|
6
6
|
export { E as ExtractedKey, a as ExtractionManifest } from './types-moTgocy7.js';
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
i18nVitePlugin
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IJXSX5DY.js";
|
|
4
4
|
import {
|
|
5
5
|
i18n,
|
|
6
6
|
runWithContext
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LXW5WYBS.js";
|
|
8
8
|
import "./chunk-33JVAFGQ.js";
|
|
9
|
+
import "./chunk-FYKC3DAZ.js";
|
|
9
10
|
import "./chunk-4A5BKHFN.js";
|
|
10
11
|
|
|
11
12
|
// src/integration/integration.ts
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as I18nContext } from './i18n-
|
|
2
|
-
export { i as i18n } from './i18n-
|
|
1
|
+
import { a as I18nContext } from './i18n-BmK1MjH7.js';
|
|
2
|
+
export { i as i18n } from './i18n-BmK1MjH7.js';
|
|
3
3
|
export { I as I18nClientState } from './types-DNRFj1XA.js';
|
|
4
4
|
import './types-moTgocy7.js';
|
|
5
5
|
|
package/dist/internal.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { R as RichComponents } from '../rich-CQUhdwBc.js';
|
|
2
|
-
import {
|
|
2
|
+
import { T as TranslationMeta, a as TranslateFunction } from '../types-DNRFj1XA.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Get the current locale from request context.
|
package/dist/server/translate.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getContext,
|
|
3
3
|
i18n
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-LXW5WYBS.js";
|
|
5
5
|
import {
|
|
6
6
|
normalizeMeta,
|
|
7
7
|
partsToNodes
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
compileMessage,
|
|
11
11
|
formatMessageToParts
|
|
12
12
|
} from "../chunk-33JVAFGQ.js";
|
|
13
|
+
import "../chunk-FYKC3DAZ.js";
|
|
13
14
|
|
|
14
15
|
// src/server/translate.ts
|
|
15
16
|
var fallbackCache = /* @__PURE__ */ new Map();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astroscope/i18n",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "i18n for Astro + React islands — MessageFormat 2, automatic tree-shaking, parallel loading, any translation source",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -84,27 +84,27 @@
|
|
|
84
84
|
"scripts": {
|
|
85
85
|
"build": "tsup src/index.ts src/internal.ts src/extraction/index.ts src/server/translate.ts src/client/translate.ts src/client/directives/load.ts src/client/directives/idle.ts src/client/directives/visible.ts src/client/directives/media.ts src/client/directives/only.ts src/client/directives/utils.ts --format esm --dts --external astro --external astro/client/load.js --external astro/client/idle.js --external astro/client/visible.js --external astro/client/media.js --external astro/client/only.js --external virtual:@astroscope/i18n/manifest --external @babel/core",
|
|
86
86
|
"typecheck": "tsc --noEmit",
|
|
87
|
-
"lint": "eslint
|
|
88
|
-
"lint:fix": "eslint
|
|
87
|
+
"lint": "eslint src",
|
|
88
|
+
"lint:fix": "eslint src --fix"
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
-
"@astrojs/compiler": "^
|
|
91
|
+
"@astrojs/compiler": "^3.0.0",
|
|
92
92
|
"@babel/core": "^7.29.0",
|
|
93
93
|
"@babel/preset-typescript": "^7.28.5",
|
|
94
94
|
"messageformat": "^4.0.0",
|
|
95
|
-
"glob": "^13.0.
|
|
95
|
+
"glob": "^13.0.6",
|
|
96
96
|
"magic-string": "^0.30.21"
|
|
97
97
|
},
|
|
98
98
|
"devDependencies": {
|
|
99
99
|
"@babel/types": "^7.29.0",
|
|
100
100
|
"@types/babel__core": "^7.20.5",
|
|
101
|
-
"astro": "^
|
|
101
|
+
"astro": "^6.0.2",
|
|
102
102
|
"tsup": "^8.5.1",
|
|
103
103
|
"typescript": "^5.9.3",
|
|
104
|
-
"vite": "^
|
|
104
|
+
"vite": "^7.3.1"
|
|
105
105
|
},
|
|
106
106
|
"peerDependencies": {
|
|
107
|
-
"@astroscope/excludes": "^0.
|
|
108
|
-
"astro": "^
|
|
107
|
+
"@astroscope/excludes": "^0.3.0",
|
|
108
|
+
"astro": "^6.0.0"
|
|
109
109
|
}
|
|
110
110
|
}
|