1- import {
2- existsSync ,
3- mkdirSync ,
4- readFileSync ,
5- readdirSync ,
6- statSync ,
7- writeFileSync ,
8- } from 'fs' ;
9- import {
10- dirname ,
11- join ,
12- } from 'path' ;
1+ import { existsSync , mkdirSync , readdirSync , readFileSync , statSync , writeFileSync } from 'fs' ;
2+ import { dirname , join } from 'path' ;
133import { fileURLToPath } from 'url' ;
144
155const __dirname = dirname ( fileURLToPath ( import . meta. url ) ) ;
166const packageRoot = dirname ( __dirname ) ;
177
188/**
19- * Convert CommonJS locale module to ESM format
20- * From: module.exports={messages:JSON.parse("{...}")};
21- * To: export default {messages:JSON.parse("{...}")};
9+ * Copy Lingui-compiled locale catalogs from `src/**\/locales/` into `dist/`.
10+ *
11+ * Lingui is configured with `compileNamespace: 'es'`, so it emits ESM modules
12+ * as `*.mjs` with a named export:
13+ *
14+ * /\*eslint-disable*\/export const messages=JSON.parse("{...}");
15+ *
16+ * For `dist/` we need:
17+ * - `*.js` — ESM consumers (identical contents to the `.mjs`, just renamed
18+ * so rslib's `.mjs → .js` import rewriting in compiled output
19+ * resolves correctly).
20+ * - `*.cjs` — CommonJS consumers, synthesized by wrapping the RHS of the
21+ * single `export const messages=…;` statement in
22+ * `module.exports = { messages: … };`.
23+ * - `*.json` — copied verbatim for runtime catalog loaders.
24+ *
25+ * The CJS synthesis is intentionally tied to the exact shape Lingui emits.
26+ * If Lingui ever changes its ESM output format, we fail loudly (throw) so
27+ * the breakage surfaces here rather than as a silent link-time error in a
28+ * downstream package (see `locale-registry.ts`, which imports
29+ * `{ messages }` as a named export).
2230 */
23- function convertToESM ( content : string ) : string {
24- return content . replace ( / m o d u l e \. e x p o r t s \s * = \s * / , 'export default ' ) ;
31+ const ESM_PREFIX = '/*eslint-disable*/export const messages=' ;
32+
33+ function esmToCjs ( esmContent : string , srcFile : string ) : string {
34+ const trimmed = esmContent . trimEnd ( ) ;
35+ if ( ! trimmed . startsWith ( ESM_PREFIX ) || ! trimmed . endsWith ( ';' ) ) {
36+ throw new Error (
37+ `plugin-copy-locales: unexpected Lingui ESM output in ${ srcFile } .\n` +
38+ `Expected a file starting with '${ ESM_PREFIX } ' and ending with ';'.\n` +
39+ `Got:\n${ trimmed . slice ( 0 , 200 ) } ...`
40+ ) ;
41+ }
42+ const rhs = trimmed . slice ( ESM_PREFIX . length , - 1 ) ; // strip prefix + trailing `;`
43+ return `/*eslint-disable*/module.exports={messages:${ rhs } };` ;
2544}
2645
2746export function pluginCopyLocales ( ) {
@@ -42,30 +61,26 @@ export function pluginCopyLocales() {
4261 const distLocales = join ( distDir , relativePath ) ;
4362
4463 if ( existsSync ( srcLocales ) ) {
45- // Ensure dist directory exists
4664 mkdirSync ( distLocales , { recursive : true } ) ;
4765
48- // Process each locale file
49- const files = readdirSync ( srcLocales ) ;
50- for ( const file of files ) {
51- if ( file . endsWith ( '.js' ) ) {
52- const srcFile = join ( srcLocales , file ) ;
66+ for ( const file of readdirSync ( srcLocales ) ) {
67+ const srcFile = join ( srcLocales , file ) ;
68+
69+ if ( file . endsWith ( '.mjs' ) ) {
5370 const content = readFileSync ( srcFile , 'utf-8' ) ;
71+ const baseName = file . replace ( / \. m j s $ / , '' ) ;
5472
55- // Write .cjs (CommonJS format)
56- const cjsFile = join ( distLocales , file . replace ( '.js' , '.cjs' ) ) ;
57- writeFileSync ( cjsFile , content , 'utf-8' ) ;
73+ // ESM: same contents, .js extension for rslib import rewriting.
74+ writeFileSync ( join ( distLocales , `${ baseName } .js` ) , content , 'utf-8' ) ;
5875
59- // Write .js (ESM format)
60- const esmFile = join ( distLocales , file ) ;
61- const esmContent = convertToESM ( content ) ;
62- writeFileSync ( esmFile , esmContent , 'utf-8' ) ;
76+ // CJS: synthesize from the known ESM shape.
77+ writeFileSync (
78+ join ( distLocales , `${ baseName } .cjs` ) ,
79+ esmToCjs ( content , srcFile ) ,
80+ 'utf-8'
81+ ) ;
6382 } else if ( file . endsWith ( '.json' ) ) {
64- // Copy JSON files as-is
65- const srcFile = join ( srcLocales , file ) ;
66- const destFile = join ( distLocales , file ) ;
67- const content = readFileSync ( srcFile , 'utf-8' ) ;
68- writeFileSync ( destFile , content , 'utf-8' ) ;
83+ writeFileSync ( join ( distLocales , file ) , readFileSync ( srcFile , 'utf-8' ) , 'utf-8' ) ;
6984 }
7085 }
7186
0 commit comments