forked from nuxt-modules/i18n
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlayers.ts
190 lines (147 loc) · 6.43 KB
/
layers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import createDebug from 'debug'
import { getLayerI18n, mergeConfigLocales, resolveVueI18nConfigInfo, formatMessage, getLocaleFiles } from './utils'
import { useLogger, useNuxt } from '@nuxt/kit'
import { isAbsolute, parse, resolve } from 'pathe'
import { isString } from '@intlify/shared'
import { NUXT_I18N_MODULE_ID } from './constants'
import type { LocaleConfig } from './utils'
import type { Nuxt, NuxtConfigLayer } from '@nuxt/schema'
import type { LocaleObject, NuxtI18nOptions, VueI18nConfigPathInfo } from './types'
const debug = createDebug('@nuxtjs/i18n:layers')
export const checkLayerOptions = (_options: NuxtI18nOptions, nuxt: Nuxt) => {
const logger = useLogger(NUXT_I18N_MODULE_ID)
const project = nuxt.options._layers[0]
const layers = nuxt.options._layers
for (const layer of layers) {
const layerI18n = getLayerI18n(layer)
if (layerI18n == null) continue
const configLocation = project.config.rootDir === layer.config.rootDir ? 'project layer' : 'extended layer'
const layerHint = `In ${configLocation} (\`${resolve(project.config.rootDir, layer.configFile)}\`) -`
try {
// check `langDir` option
if (layerI18n.langDir) {
const locales = layerI18n.locales || []
if (isString(layerI18n.langDir) && isAbsolute(layerI18n.langDir)) {
logger.warn(
`${layerHint} \`langDir\` is set to an absolute path (\`${layerI18n.langDir}\`) but should be set a path relative to \`srcDir\` (\`${layer.config.srcDir}\`). ` +
`Absolute paths will not work in production, see https://i18n.nuxtjs.org/options/lazy#langdir for more details.`
)
}
for (const locale of locales) {
if (isString(locale)) {
throw new Error('When using the `langDir` option the `locales` must be a list of objects.')
}
if (!(locale.file || locale.files)) {
throw new Error(
'All locales must have the `file` or `files` property set when using `langDir`.\n' +
`Found none in:\n${JSON.stringify(locale, null, 2)}.`
)
}
}
}
} catch (err) {
if (!(err instanceof Error)) throw err
throw new Error(formatMessage(`${layerHint} ${err.message}`))
}
}
}
/**
* Merges `locales` configured by each layer and resolves the locale `files` to absolute paths.
*
* This overwrites `options.locales`
*/
export const applyLayerOptions = (options: NuxtI18nOptions, nuxt: Nuxt) => {
const project = nuxt.options._layers[0]
const layers = nuxt.options._layers
const resolvedLayerPaths = layers.map(l => resolve(project.config.rootDir, l.config.rootDir))
debug('using layers at paths', resolvedLayerPaths)
const mergedLocales = mergeLayerLocales(options, nuxt)
debug('merged locales', mergedLocales)
options.locales = mergedLocales
}
export const mergeLayerPages = (analyzer: (pathOverride: string) => void, nuxt: Nuxt) => {
const project = nuxt.options._layers[0]
const layers = nuxt.options._layers
// No layers to merge
if (layers.length === 1) return
for (const l of layers) {
const lPath = resolve(project.config.rootDir, l.config.srcDir, l.config.dir?.pages ?? 'pages')
debug('mergeLayerPages: path ->', lPath)
analyzer(lPath)
}
}
export function resolveI18nDir(layer: NuxtConfigLayer, i18n: NuxtI18nOptions, fromRootDir: boolean = false) {
if (i18n.restructureDir !== false) {
return resolve(layer.config.rootDir, i18n.restructureDir ?? 'i18n')
}
return resolve(layer.config.rootDir, fromRootDir ? '' : layer.config.srcDir)
}
export function resolveLayerLangDir(layer: NuxtConfigLayer, i18n: NuxtI18nOptions) {
i18n.restructureDir ??= 'i18n'
i18n.langDir ??= i18n.restructureDir !== false ? 'locales' : ''
return resolve(resolveI18nDir(layer, i18n), i18n.langDir)
}
const mergeLayerLocales = (options: NuxtI18nOptions, nuxt: Nuxt) => {
debug('project layer `lazy` option', options.lazy)
options.locales ??= []
const configs: LocaleConfig[] = []
for (const layer of nuxt.options._layers) {
const i18n = getLayerI18n(layer)
if (i18n?.locales == null) continue
configs.push({ ...i18n, langDir: resolveLayerLangDir(layer, i18n) })
}
const installModuleConfigMap = new Map<string, LocaleConfig>()
/**
* Collect any locale files that are not provided by layers these are added when
* installing through `installModule` and should have absolute paths.
*/
outer: for (const locale of options.locales) {
if (typeof locale === 'string') continue
const files = getLocaleFiles(locale)
if (files.length === 0) continue
const langDir = parse(files[0].path).dir
const locales = (installModuleConfigMap.get(langDir)?.locales ?? []) as LocaleObject[]
// check if all files are absolute and not present in configs
for (const file of files) {
if (!isAbsolute(file.path)) continue outer
if (configs.find(config => config.langDir === parse(file.path).dir) != null) continue outer
}
locales.push(locale)
installModuleConfigMap.set(langDir, { langDir, locales })
}
configs.unshift(...Array.from(installModuleConfigMap.values()))
return mergeConfigLocales(configs)
}
/**
* Returns an array of absolute paths to each layers `langDir`
*/
export const getLayerLangPaths = (nuxt: Nuxt) => {
const langPaths: string[] = []
for (const layer of nuxt.options._layers) {
const i18n = getLayerI18n(layer)
if (i18n?.restructureDir === false && i18n?.langDir == null) continue
langPaths.push(resolveLayerLangDir(layer, i18n || {}))
}
return langPaths
}
export async function resolveLayerVueI18nConfigInfo(options: NuxtI18nOptions) {
const logger = useLogger(NUXT_I18N_MODULE_ID)
const nuxt = useNuxt()
const resolveArr = nuxt.options._layers.map(async layer => {
const i18n = getLayerI18n(layer)
const res = await resolveVueI18nConfigInfo(resolveI18nDir(layer, i18n || {}, true), i18n?.vueI18n)
if (res == null && i18n?.vueI18n != null) {
logger.warn(
`Ignore Vue I18n configuration file does not exist at ${i18n.vueI18n} in ${layer.config.rootDir}. Skipping...`
)
return undefined
}
return res
})
const resolved = await Promise.all(resolveArr)
// use `vueI18n` passed by `installModule`
if (options.vueI18n && isAbsolute(options.vueI18n)) {
resolved.unshift(await resolveVueI18nConfigInfo(parse(options.vueI18n).dir, options.vueI18n))
}
return resolved.filter((x): x is Required<VueI18nConfigPathInfo> => x != null)
}