nuxt-merged-i18n
Version:
Fusionne automatiquement les fichiers i18n Nuxt par domaine.
80 lines (68 loc) • 2.31 kB
text/typescript
import { defineNuxtModule, addTemplate, createResolver } from 'nuxt/kit'
import fg from 'fast-glob'
import { readFile, writeFile, mkdir } from 'fs/promises'
import { join, dirname } from 'pathe'
import { createConsola } from 'consola'
const consola = createConsola({ fancy: true })
export interface ModuleOptions {
dirs?: string[]
flatten?: boolean
cleanOutputDir?: boolean
fallbackFile?: string
verbose?: boolean
}
export default defineNuxtModule<ModuleOptions>({
meta: {
name: 'nuxt-merged-i18n',
configKey: 'mergedI18n'
},
defaults: {
dirs: ['domains/**/i18n/*.json', 'shared/i18n/*.json'],
flatten: false,
cleanOutputDir: true,
fallbackFile: 'global',
verbose: false
},
async setup(options, nuxt) {
const resolver = createResolver(import.meta.url)
const files = await fg(options.dirs!, {
cwd: nuxt.options.rootDir,
absolute: true
})
const locales: Record<string, Record<string, any>> = {}
for (const file of files) {
const content = await readFile(file, 'utf-8')
const json = JSON.parse(content)
const relative = file.replace(nuxt.options.rootDir + '/', '')
const domainMatch = relative.match(/domains\/(.*?)\/i18n\/(.*).json$/)
const sharedMatch = relative.match(/shared\/i18n\/(.*).json$/)
let domain: string
let lang: string
if (domainMatch) {
domain = domainMatch[1]
lang = domainMatch[2]
} else if (sharedMatch) {
domain = options.fallbackFile!
lang = sharedMatch[1]
} else {
continue
}
const key = `${lang}.json`
locales[key] ??= {}
locales[key][domain] = json
nuxt.options.watch.push(file)
}
const outputDir = join(nuxt.options.rootDir, 'i18n/locales')
for (const [langFile, domains] of Object.entries(locales)) {
const outputPath = join(outputDir, langFile)
await mkdir(dirname(outputPath), { recursive: true })
await writeFile(outputPath, JSON.stringify(domains, null, 2), 'utf-8')
if (options.verbose) {
consola.success(`✅ ${langFile} généré avec ${Object.keys(domains).length} domaines.`)
}
}
nuxt.hook('merged-i18n:done', () => {
if (options.verbose) consola.info('✅ Fusion terminée')
})
}
})