Skip to content

Commit b1a6da7

Browse files
authored
fix: prevent mutating runtime config in runtime code (#3630)
1 parent af812f8 commit b1a6da7

7 files changed

Lines changed: 34 additions & 27 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { defineNitroPlugin, useRuntimeConfig } from 'nitropack/runtime'
2+
3+
// This runtime config usage combined with `differentDomains` originally triggered #3400
4+
export default defineNitroPlugin(nitroApp => {
5+
const runtimeConfig = useRuntimeConfig()
6+
7+
nitroApp.hooks.hook('request', event => {
8+
event.context.nitro = event.context.nitro ?? {}
9+
event.context.nitro.runtimeConfig = runtimeConfig
10+
})
11+
})

src/runtime/context.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export type NuxtI18nContext = {
3131
/** SSG with dynamic locale resources */
3232
dynamicResourcesSSG: boolean
3333
getVueI18n: () => I18n
34+
/** Get default locale */
35+
getDefaultLocale: () => string
3436
/** Load locale messages */
3537
loadLocaleMessages: (locale: Locale) => Promise<void>
3638
/** Get current locale */
@@ -64,7 +66,7 @@ function createI18nCookie({ cookieCrossOrigin, cookieDomain, cookieSecure, cooki
6466
})
6567
}
6668

67-
export function createNuxtI18nContext(nuxt: NuxtApp, _i18n: I18n): NuxtI18nContext {
69+
export function createNuxtI18nContext(nuxt: NuxtApp, _i18n: I18n, defaultLocale: string): NuxtI18nContext {
6870
const i18n = getI18nTarget(_i18n)
6971
const serverLocaleConfigs = useLocaleConfigs()
7072
const runtimeI18n = nuxt.$config.public.i18n as I18nPublicRuntimeConfig
@@ -82,6 +84,7 @@ export function createNuxtI18nContext(nuxt: NuxtApp, _i18n: I18n): NuxtI18nConte
8284
preloaded: false,
8385
dynamicResourcesSSG,
8486
getVueI18n: () => _i18n,
87+
getDefaultLocale: () => defaultLocale,
8588
getLocale: () => unref(i18n.locale),
8689
setLocale: (locale: string) => {
8790
if (isRef(i18n.locale)) {

src/runtime/domain.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ export function setupMultiDomainLocales(defaultLocale: string, router: Router =
119119
/**
120120
* Returns default locale for the current domain, returns `defaultLocale` by default
121121
*/
122-
export function getDefaultLocaleForDomain(runtimeI18n: I18nPublicRuntimeConfig) {
123-
const { defaultLocale } = runtimeI18n
122+
export function getDefaultLocaleForDomain(defaultLocale: string) {
124123
const host = getHost()
125124
if (normalizedLocales.some(l => l.defaultForDomains != null)) {
126125
return normalizedLocales.find(l => !!l.defaultForDomains?.includes(host))?.code ?? ''

src/runtime/plugins/i18n.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,12 @@ export default defineNuxtPlugin({
2525

2626
const nuxt = useNuxtApp()
2727
const runtimeI18n = nuxt.$config.public.i18n as I18nPublicRuntimeConfig
28-
29-
let defaultLocaleDomain: string = runtimeI18n.defaultLocale || ''
28+
const defaultLocale: string = getDefaultLocaleForDomain(runtimeI18n.defaultLocale || '')
3029
if (__MULTI_DOMAIN_LOCALES__) {
31-
defaultLocaleDomain = getDefaultLocaleForDomain(runtimeI18n)
32-
setupMultiDomainLocales(defaultLocaleDomain)
30+
setupMultiDomainLocales(defaultLocale)
3331
}
3432

35-
runtimeI18n.defaultLocale = defaultLocaleDomain
36-
37-
const vueI18nOptions: I18nOptions = await setupVueI18nOptions()
38-
if (defaultLocaleDomain) {
39-
vueI18nOptions.locale = defaultLocaleDomain
40-
}
33+
const vueI18nOptions: I18nOptions = await setupVueI18nOptions(defaultLocale)
4134

4235
if (import.meta.server) {
4336
const serverLocaleConfigs = useLocaleConfigs()
@@ -53,7 +46,7 @@ export default defineNuxtPlugin({
5346
// create i18n instance
5447
const i18n = createI18n(vueI18nOptions)
5548

56-
nuxt._nuxtI18nCtx = createNuxtI18nContext(nuxt, i18n)
49+
nuxt._nuxtI18nCtx = createNuxtI18nContext(nuxt, i18n, defaultLocale)
5750
const ctx = useNuxtI18nContext(nuxt)
5851

5952
nuxt._nuxtI18n = createComposableContext(runtimeI18n)
@@ -97,7 +90,7 @@ export default defineNuxtPlugin({
9790
composer.loadLocaleMessages = ctx.loadLocaleMessages
9891

9992
composer.differentDomains = __DIFFERENT_DOMAINS__
100-
composer.defaultLocale = runtimeI18n.defaultLocale
93+
composer.defaultLocale = defaultLocale
10194

10295
composer.getBrowserLocale = ctx.getBrowserLocale
10396
composer.getLocaleCookie = ctx.getLocaleCookie

src/runtime/server/plugin.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { stringify } from 'devalue'
22
import { defineI18nMiddleware } from '@intlify/h3'
3-
import { defineNitroPlugin } from 'nitropack/runtime'
3+
import { defineNitroPlugin, useRuntimeConfig } from 'nitropack/runtime'
44
import { tryUseI18nContext, createI18nContext } from './context'
55
import { createUserLocaleDetector } from './utils/locale-detector'
66
import { pickNested } from './utils/messages-utils'
@@ -12,9 +12,13 @@ import { localeDetector } from '#internal/i18n/locale.detector.mjs'
1212

1313
import type { H3Event } from 'h3'
1414
import type { CoreOptions } from '@intlify/core'
15+
import type { I18nPublicRuntimeConfig } from '~/src/types'
1516

1617
export default defineNitroPlugin(async nitro => {
17-
const options = await setupVueI18nOptions()
18+
const runtime18n = useRuntimeConfig().public.i18n as I18nPublicRuntimeConfig
19+
const defaultLocale: string = runtime18n.defaultLocale || ''
20+
21+
const options = await setupVueI18nOptions(defaultLocale)
1822
const localeConfigs = createLocaleConfigs(options.fallbackLocale)
1923

2024
nitro.hooks.hook('request', async (event: H3Event) => {
@@ -63,7 +67,7 @@ export default defineNitroPlugin(async nitro => {
6367

6468
// enable server-side translations and user locale-detector
6569
if (localeDetector != null) {
66-
const options = await setupVueI18nOptions()
70+
const options = await setupVueI18nOptions(defaultLocale)
6771
const i18nMiddleware = defineI18nMiddleware({
6872
...(options as CoreOptions),
6973
locale: createUserLocaleDetector(options.locale, options.fallbackLocale)

src/runtime/shared/vue-i18n.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import { useRuntimeConfig } from '#app'
21
import { loadVueI18nOptions } from './messages'
32
import { vueI18nConfigs, localeCodes as _localeCodes } from '#build/i18n.options.mjs'
43

54
import type { I18nOptions } from 'vue-i18n'
6-
import type { I18nPublicRuntimeConfig } from '#internal-i18n-types'
75

86
type ResolvedI18nOptions = Omit<I18nOptions, 'messages' | 'locale' | 'fallbackLocale'> &
97
Required<Pick<I18nOptions, 'messages' | 'locale' | 'fallbackLocale'>>
108

11-
export const setupVueI18nOptions = async (): Promise<ResolvedI18nOptions> => {
12-
const runtimeI18n = useRuntimeConfig().public.i18n as unknown as I18nPublicRuntimeConfig
9+
export const setupVueI18nOptions = async (defaultLocale: string): Promise<ResolvedI18nOptions> => {
1310
const options = await loadVueI18nOptions(vueI18nConfigs)
1411

15-
options.locale = runtimeI18n.defaultLocale || options.locale || 'en-US'
12+
options.locale = defaultLocale || options.locale || 'en-US'
1613
options.fallbackLocale ??= false
1714
options.messages ??= {}
1815

src/runtime/utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ export function useComposableContext(): ComposableContext {
6666
export function createComposableContext(runtimeI18n: I18nPublicRuntimeConfig): ComposableContext {
6767
const router = useRouter()
6868
const ctx = useNuxtI18nContext()
69-
69+
const defaultLocale = ctx.getDefaultLocale()
7070
const routeByPathResolver = createLocalizedRouteByPathResolver(router)
71-
const getLocalizedRouteName = createLocaleRouteNameGetter(runtimeI18n.defaultLocale)
71+
const getLocalizedRouteName = createLocaleRouteNameGetter(defaultLocale)
7272

7373
function getRouteBaseName(route: RouteRecordNameGeneric | RouteLocationGenericPath | null) {
7474
return _getRouteBaseName(route, __ROUTE_NAME_SEPARATOR__)
@@ -95,7 +95,7 @@ export function createComposableContext(runtimeI18n: I18nPublicRuntimeConfig): C
9595
return route
9696
}
9797

98-
if (!__DIFFERENT_DOMAINS__ && prefixable(locale, runtimeI18n.defaultLocale)) {
98+
if (!__DIFFERENT_DOMAINS__ && prefixable(locale, defaultLocale)) {
9999
route.path = '/' + locale + route.path
100100
}
101101

@@ -106,7 +106,7 @@ export function createComposableContext(runtimeI18n: I18nPublicRuntimeConfig): C
106106
return {
107107
router,
108108
getRoutingOptions: () => ({
109-
defaultLocale: runtimeI18n.defaultLocale,
109+
defaultLocale: defaultLocale,
110110
strictCanonicals: runtimeI18n.experimental.alternateLinkCanonicalQueries ?? true,
111111
hreflangLinks: !(!__I18N_ROUTING__ && !__DIFFERENT_DOMAINS__)
112112
}),

0 commit comments

Comments
 (0)