1- import { readdirSync , readFileSync , writeFileSync } from 'node:fs' ;
1+ import { lstatSync , readdirSync , readFileSync , writeFileSync } from 'node:fs' ;
22import { resolve } from 'node:path' ;
33import type { Options } from 'prettier' ;
44import { format } from 'prettier' ;
@@ -44,20 +44,16 @@ function removeTsSuffix(files: string[]): string[] {
4444}
4545
4646function escapeImport ( module : string ) : string {
47- if ( module === 'name' ) {
48- return 'name_' ;
49- } else if ( module === 'type' ) {
50- return 'type_' ;
47+ if ( [ 'name' , 'type' , 'switch' ] . includes ( module ) ) {
48+ return `${ module } _` ;
5149 } else {
5250 return module ;
5351 }
5452}
5553
5654function escapeField ( module : string ) : string {
57- if ( module === 'name' ) {
58- return 'name: name_' ;
59- } else if ( module === 'type' ) {
60- return 'type: type_' ;
55+ if ( [ 'name' , 'type' , 'switch' ] . includes ( module ) ) {
56+ return `${ module } : ${ module } _` ;
6157 } else {
6258 return module ;
6359 }
@@ -70,7 +66,7 @@ function containsAll(checked?: string[], expected?: string[]): boolean {
7066 return expected . every ( ( c ) => checked . includes ( c ) ) ;
7167}
7268
73- function generateLocaleFile ( locale : string ) {
69+ function generateLocaleFile ( locale : string ) : void {
7470 let content = `
7571 ${ autoGeneratedCommentHeader }
7672
@@ -129,7 +125,7 @@ function generateLocalesIndexFile(
129125 depth : number ,
130126 extra : string = '' ,
131127 expected ?: string [ ]
132- ) {
128+ ) : void {
133129 let modules = readdirSync ( path ) ;
134130 modules = removeIndexTs ( modules ) ;
135131 modules = removeTsSuffix ( modules ) ;
@@ -141,14 +137,19 @@ function generateLocalesIndexFile(
141137 let asType = '' ;
142138 if ( ! containsAll ( expected , modules ) ) {
143139 asType = ` as ${ type } ` ;
144- } else {
140+ } else if ( type !== 'any' ) {
145141 fieldType = `: ${ type } ` ;
146142 }
147- let content = `${ autoGeneratedCommentHeader }
148- import type { ${ importType } } from '..${ '/..' . repeat ( depth ) } ';
149- ${ modules
150- . map ( ( module ) => `import ${ escapeImport ( module ) } from './${ module } ';` )
151- . join ( '\n' ) }
143+ let content = `${ autoGeneratedCommentHeader } \n` ;
144+ if ( type !== 'any' ) {
145+ content += ` import type { ${ importType . replace (
146+ / \[ .* / ,
147+ ''
148+ ) } } from '..${ '/..' . repeat ( depth ) } ';\n`;
149+ }
150+ content += ` ${ modules
151+ . map ( ( module ) => `import ${ escapeImport ( module ) } from './${ module } ';` )
152+ . join ( '\n' ) }
152153
153154 const ${ name } ${ fieldType } = {
154155 ${ extra }
@@ -161,6 +162,51 @@ function generateLocalesIndexFile(
161162 writeFileSync ( resolve ( path , 'index.ts' ) , content ) ;
162163}
163164
165+ function generateRecursiveModuleIndexes (
166+ path : string ,
167+ name : string ,
168+ definition : string ,
169+ depth : number ,
170+ extra ?: string ,
171+ moduleFiles ?: string [ ]
172+ ) : void {
173+ generateLocalesIndexFile ( path , name , definition , depth , extra , moduleFiles ) ;
174+
175+ let submodules = readdirSync ( path ) ;
176+ submodules = removeIndexTs ( submodules ) ;
177+ for ( const submodule of submodules ) {
178+ const pathModule = resolve ( path , submodule ) ;
179+ // Only process sub folders recursively
180+ if ( lstatSync ( pathModule ) . isDirectory ( ) ) {
181+ let moduleDefinition =
182+ definition === 'any' ? 'any' : `${ definition } ['${ submodule } ']` ;
183+ let moduleFiles : string [ ] ;
184+
185+ // Overwrite types of src/locales/<locale>/<module>/index.ts for known DEFINITIONS
186+ if ( depth === 1 ) {
187+ moduleFiles = DEFINITIONS [ submodule ] ;
188+ if ( typeof moduleFiles === 'undefined' ) {
189+ moduleDefinition = 'any' ;
190+ } else {
191+ moduleDefinition = `${ submodule . replace ( / ( ^ | _ ) ( [ a - z ] ) / g, ( s ) =>
192+ s . replace ( '_' , '' ) . toUpperCase ( )
193+ ) } Definitions`;
194+ }
195+ }
196+
197+ // Recursive
198+ generateRecursiveModuleIndexes (
199+ pathModule ,
200+ submodule ,
201+ moduleDefinition ,
202+ depth + 1 ,
203+ undefined ,
204+ moduleFiles
205+ ) ;
206+ }
207+ }
208+ }
209+
164210// Start of actual logic
165211
166212const locales = readdirSync ( pathLocales ) ;
@@ -188,38 +234,15 @@ for (const locale of locales) {
188234 // src/locale/<locale>.ts
189235 generateLocaleFile ( locale ) ;
190236
191- // src/locales/<locale> /index.ts
192- generateLocalesIndexFile (
237+ // src/locales/** /index.ts
238+ generateRecursiveModuleIndexes (
193239 pathModules ,
194240 locale ,
195241 'LocaleDefinition' ,
196242 1 ,
197243 `title: '${ localeTitle } ',` +
198- ( localeSeparator ? `\nseparator: '${ localeSeparator } ',` : '' ) ,
199- undefined
244+ ( localeSeparator ? `\nseparator: '${ localeSeparator } ',` : '' )
200245 ) ;
201-
202- let modules = readdirSync ( pathModules ) ;
203- modules = removeIndexTs ( modules ) ;
204- modules = removeTsSuffix ( modules ) ;
205- for ( const module of modules ) {
206- // src/locales/<locale>/<module>/index.ts
207- const pathModule = resolve ( pathModules , module ) ;
208- const moduleFiles : string [ ] = DEFINITIONS [ module ] ;
209- if ( typeof moduleFiles === 'undefined' ) {
210- continue ;
211- }
212- generateLocalesIndexFile (
213- pathModule ,
214- module ,
215- `${ module . replace ( / ( ^ | _ ) ( [ a - z ] ) / g, ( s ) =>
216- s . replace ( '_' , '' ) . toUpperCase ( )
217- ) } Definitions`,
218- 2 ,
219- '' ,
220- moduleFiles
221- ) ;
222- }
223246}
224247
225248// src/locales/index.ts
0 commit comments