forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1import type { LocaleObject } from '@nuxtjs/i18n'
2import * as path from 'node:path'
3import * as fs from 'node:fs/promises'
4import { currentLocales, lunariaJSONFiles } from '../config/i18n.ts'
5import { deepCopy } from '@intlify/shared'
6
7const destFolder = path.resolve('lunaria/files')
8const localesFolder = path.resolve('i18n/locales')
9
10const defaultLocale = currentLocales.find(l => l.code === 'en-US')
11if (!defaultLocale?.name) {
12 throw new Error('Default locale en-US not found or has no name')
13}
14export { lunariaJSONFiles }
15export const sourceLocale = {
16 label: defaultLocale.name,
17 lang: defaultLocale.code,
18}
19const filteredLocales = currentLocales.filter(
20 (l): l is typeof l & { name: string } => l.code !== 'en-US' && typeof l.name === 'string',
21)
22const firstLocale = filteredLocales[0]
23if (!firstLocale) {
24 throw new Error('No locales found besides en-US')
25}
26export const locales: [{ label: string; lang: string }, ...{ label: string; lang: string }[]] = [
27 { label: firstLocale.name, lang: firstLocale.code },
28 ...filteredLocales.slice(1).map(l => ({
29 label: l.name,
30 lang: l.code,
31 })),
32]
33
34export async function prepareJsonFiles(): Promise<void> {
35 await fs.rm(destFolder, { recursive: true, force: true })
36 await fs.mkdir(destFolder)
37 await Promise.all(currentLocales.map(l => mergeLocale(l)))
38}
39
40type NestedObject = Record<string, unknown>
41
42export async function mergeLocaleObject(locale: LocaleObject): Promise<NestedObject | undefined> {
43 const files = locale.files ?? []
44 if (locale.file || files.length === 1) {
45 const json =
46 (locale.file ? getFileName(locale.file) : undefined) ??
47 (files[0] ? getFileName(files[0]) : undefined)
48 if (!json) return undefined
49
50 return await loadLocaleSourceJson<NestedObject>(json)
51 }
52
53 const firstFile = files[0]
54 if (!firstFile) return undefined
55 const source = await loadLocaleSourceJson<NestedObject>(getFileName(firstFile))
56 let currentSource: unknown
57 for (let i = 1; i < files.length; i++) {
58 const file = files[i]
59 if (!file) continue
60 currentSource = await loadLocaleSourceJson(getFileName(file))
61 deepCopy(currentSource, source)
62 }
63
64 return source
65}
66
67async function loadLocaleSourceJson<T = unknown>(name: string): Promise<T> {
68 const rawJson = JSON.parse(await fs.readFile(path.resolve(`${localesFolder}/${name}`), 'utf8'))
69 // Exclude $schema since it isn't useful in generated files and the relative
70
71 // TODO: removing vacations entry key for temporal recharging page
72 // would be wrong anyway
73 const { $schema: _, vacations: __, ...rest } = rawJson
74 return rest
75}
76
77function getFileName(file: string | { path: string }): string {
78 return typeof file === 'string' ? file : file.path
79}
80
81async function mergeLocale(locale: LocaleObject): Promise<void> {
82 const source = await mergeLocaleObject(locale)
83 if (!source) {
84 return
85 }
86
87 await fs.writeFile(
88 path.resolve(`${destFolder}/${locale.code}.json`),
89 `${JSON.stringify(source, null, 2)}\n`,
90 'utf-8',
91 )
92}