Skip to content

Commit 130692a

Browse files
authored
fix: pass app context to message loading logic (#3360)
1 parent b239535 commit 130692a

File tree

9 files changed

+78
-23
lines changed

9 files changed

+78
-23
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default defineI18nLocale(function () {
2+
const config = useRuntimeConfig()
3+
return {
4+
runtimeConfigKey: config.public.myKey
5+
}
6+
})

specs/fixtures/lazy/nuxt.config.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ export default defineNuxtConfig({
2020
}
2121
}
2222
},
23+
24+
runtimeConfig: {
25+
public: {
26+
myKey: 'runtime-config-value'
27+
}
28+
},
2329
modules: [i18nModule, '@nuxtjs/i18n'],
2430
i18n: {
2531
restructureDir: false,
@@ -43,7 +49,7 @@ export default defineNuxtConfig({
4349
{
4450
code: 'en-GB',
4551
language: 'en-GB',
46-
files: ['lazy-locale-en.json', 'lazy-locale-en-GB.js', 'lazy-locale-en-GB.ts'],
52+
files: ['lazy-locale-en.json', 'lazy-locale-en-GB.js', 'lazy-locale-en-GB.ts', 'runtime-config-translation.js'],
4753
name: 'English (UK)'
4854
},
4955
{

specs/fixtures/lazy/pages/index.vue

+1
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,6 @@ useHead(() => ({
4747
<p id="profile-ts">{{ $t('settings_nest_foo_bar_profile') }}</p>
4848
<p id="html-message" v-html="$t('html')"></p>
4949
<p id="dynamic-time">{{ $t('dynamicTime') }}</p>
50+
<p id="runtime-config-key">{{ $t('runtimeConfigKey') }}</p>
5051
</div>
5152
</template>

specs/lazy_load/basic_lazy_load.spec.ts

+30
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,34 @@ describe('basic lazy loading', async () => {
136136
expect(await getText(page, '#welcome-english')).toEqual('Welcome!')
137137
expect(await getText(page, '#welcome-dutch')).toEqual('Welkom!')
138138
})
139+
140+
test('(#3359) runtime config accessible in locale function', async () => {
141+
const { page, pageErrors, consoleLogs } = await renderPage('/')
142+
143+
// wait for request after navigation
144+
const localeRequestNl = page.waitForRequest(/runtime-config-translation/)
145+
await page.click('#lang-switcher-with-nuxt-link-en-GB')
146+
await localeRequestNl
147+
// await updated text
148+
await page.waitForFunction(
149+
() => document.querySelector('#runtime-config-key')?.textContent === 'runtime-config-value',
150+
{},
151+
{ timeout: 2000 }
152+
)
153+
expect(await getText(page, '#runtime-config-key')).toEqual('runtime-config-value')
154+
155+
// trigger server-side locale loading
156+
await page.reload()
157+
// @ts-ignore
158+
await page.waitForFunction(() => !window.useNuxtApp?.().isHydrating)
159+
// await updated text
160+
await page.waitForFunction(
161+
() => document.querySelector('#runtime-config-key')?.textContent === 'runtime-config-value',
162+
{},
163+
{ timeout: 2000 }
164+
)
165+
166+
expect(consoleLogs.filter(x => x.type === 'error').length).toEqual(0)
167+
expect(await getText(page, '#runtime-config-key')).toEqual('runtime-config-value')
168+
})
139169
})

src/runtime/messages.ts

+16-9
Original file line numberDiff line numberDiff line change
@@ -62,32 +62,37 @@ export async function loadInitialMessages<Context extends NuxtApp = NuxtApp>(
6262
initialLocale: Locale
6363
fallbackLocale: FallbackLocale
6464
localeCodes: string[]
65-
}
65+
},
66+
nuxt: { runWithContext: NuxtApp['runWithContext'] }
6667
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6768
): Promise<Record<string, any>> {
6869
const { defaultLocale, initialLocale, localeCodes, fallbackLocale, lazy } = options
6970

7071
// load fallback messages
7172
if (lazy && fallbackLocale) {
7273
const fallbackLocales = makeFallbackLocaleCodes(fallbackLocale, [defaultLocale, initialLocale])
73-
await Promise.all(fallbackLocales.map(locale => loadAndSetLocaleMessages(locale, localeLoaders, messages)))
74+
await Promise.all(fallbackLocales.map(locale => loadAndSetLocaleMessages(locale, localeLoaders, messages, nuxt)))
7475
}
7576

7677
// load initial messages
7778
const locales = lazy ? [...new Set<Locale>().add(defaultLocale).add(initialLocale)] : localeCodes
78-
await Promise.all(locales.map((locale: Locale) => loadAndSetLocaleMessages(locale, localeLoaders, messages)))
79+
await Promise.all(locales.map((locale: Locale) => loadAndSetLocaleMessages(locale, localeLoaders, messages, nuxt)))
7980

8081
return messages
8182
}
8283

83-
async function loadMessage(locale: Locale, { key, load }: LocaleLoader) {
84+
async function loadMessage(
85+
locale: Locale,
86+
{ key, load }: LocaleLoader,
87+
nuxt: { runWithContext: NuxtApp['runWithContext'] }
88+
) {
8489
const logger = /*#__PURE__*/ createLogger('loadMessage')
8590
let message: LocaleMessages<DefineLocaleMessage> | null = null
8691
try {
8792
__DEBUG__ && logger.log({ locale })
8893
const getter = await load().then(r => ('default' in r ? r.default : r))
8994
if (isFunction(getter)) {
90-
message = await getter(locale)
95+
message = await nuxt.runWithContext(() => getter(locale))
9196
__DEBUG__ && logger.log('dynamic load', logger.level >= 999 ? message : '')
9297
} else {
9398
message = getter
@@ -105,7 +110,8 @@ async function loadMessage(locale: Locale, { key, load }: LocaleLoader) {
105110
export async function loadLocale(
106111
locale: Locale,
107112
localeLoaders: Record<Locale, LocaleLoader[]>,
108-
setter: (locale: Locale, message: LocaleMessages<DefineLocaleMessage>) => void
113+
setter: (locale: Locale, message: LocaleMessages<DefineLocaleMessage>) => void,
114+
nuxt: { runWithContext: NuxtApp['runWithContext'] }
109115
) {
110116
const logger = /*#__PURE__*/ createLogger('loadLocale')
111117
const loaders = localeLoaders[locale]
@@ -125,7 +131,7 @@ export async function loadLocale(
125131
} else {
126132
__DEBUG__ && !loader.cache && logger.log(loader.key + ' bypassing cache!')
127133
__DEBUG__ && logger.log(loader.key + ' is loading ...')
128-
message = await loadMessage(locale, loader)
134+
message = await nuxt.runWithContext(() => loadMessage(locale, loader, nuxt))
129135
}
130136

131137
if (message != null) {
@@ -142,13 +148,14 @@ type LocaleLoaderMessages =
142148
export async function loadAndSetLocaleMessages(
143149
locale: Locale,
144150
localeLoaders: Record<Locale, LocaleLoader[]>,
145-
messages: LocaleLoaderMessages
151+
messages: LocaleLoaderMessages,
152+
nuxt: { runWithContext: NuxtApp['runWithContext'] }
146153
) {
147154
const setter = (locale: Locale, message: LocaleMessages<DefineLocaleMessage, Locale>) => {
148155
const base = messages[locale] || {}
149156
deepCopy(message, base)
150157
messages[locale] = base
151158
}
152159

153-
await loadLocale(locale, localeLoaders, setter)
160+
await loadLocale(locale, localeLoaders, setter, nuxt)
154161
}

src/runtime/plugins/i18n.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export default defineNuxtPlugin({
143143
)
144144
}
145145
composer.loadLocaleMessages = async (locale: string) =>
146-
await loadLocale(locale, localeLoaders, composer.mergeLocaleMessage.bind(composer))
146+
await loadLocale(locale, localeLoaders, composer.mergeLocaleMessage.bind(composer), nuxtApp)
147147
composer.differentDomains = runtimeI18n.differentDomains
148148
composer.defaultLocale = runtimeI18n.defaultLocale
149149
composer.getBrowserLocale = () => getBrowserLocale()

src/runtime/server/api/merged-options.get.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default defineEventHandler(async () => {
4040
deepCopy(message, messages)
4141
}
4242

43-
await loadLocale(locale, localeLoaders, setter)
43+
await loadLocale(locale, localeLoaders, setter, nuxtMock)
4444
}
4545

4646
// @ts-ignore

src/runtime/server/plugin.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@ export default defineNitroPlugin(async nitro => {
2121
const initialLocale = runtimeI18n.defaultLocale || options.locale || 'en-US'
2222

2323
// load initial locale messages for intlify/h3
24-
options.messages = await loadInitialMessages(options.messages, localeLoaders, {
25-
localeCodes,
26-
initialLocale,
27-
lazy: runtimeI18n.lazy,
28-
defaultLocale: runtimeI18n.defaultLocale,
29-
fallbackLocale: options.fallbackLocale
30-
})
24+
options.messages = await loadInitialMessages(
25+
options.messages,
26+
localeLoaders,
27+
{
28+
localeCodes,
29+
initialLocale,
30+
lazy: runtimeI18n.lazy,
31+
defaultLocale: runtimeI18n.defaultLocale,
32+
fallbackLocale: options.fallbackLocale
33+
},
34+
nuxtMock
35+
)
3136

3237
const localeDetector = async (
3338
event: H3Event,
@@ -41,10 +46,10 @@ export default defineNitroPlugin(async nitro => {
4146
if (fallbackLocale) {
4247
const fallbackLocales = makeFallbackLocaleCodes(fallbackLocale, [locale])
4348
await Promise.all(
44-
fallbackLocales.map(locale => loadAndSetLocaleMessages(locale, localeLoaders, i18nContext.messages))
49+
fallbackLocales.map(locale => loadAndSetLocaleMessages(locale, localeLoaders, i18nContext.messages, nuxtMock))
4550
)
4651
}
47-
await loadAndSetLocaleMessages(locale, localeLoaders, i18nContext.messages)
52+
await loadAndSetLocaleMessages(locale, localeLoaders, i18nContext.messages, nuxtMock)
4853
}
4954
return locale
5055
}

src/runtime/utils.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ export async function loadAndSetLocale(newLocale: Locale, initial: boolean = fal
108108
const setter = nuxtApp.$i18n.mergeLocaleMessage.bind(nuxtApp.$i18n)
109109
if (i18nFallbackLocales) {
110110
const fallbackLocales = makeFallbackLocaleCodes(i18nFallbackLocales, [newLocale])
111-
await Promise.all(fallbackLocales.map(locale => loadLocale(locale, localeLoaders, setter)))
111+
await Promise.all(fallbackLocales.map(locale => loadLocale(locale, localeLoaders, setter, nuxtApp)))
112112
}
113-
await loadLocale(newLocale, localeLoaders, setter)
113+
await loadLocale(newLocale, localeLoaders, setter, nuxtApp)
114114
// }
115115

116116
if (skipSettingLocaleOnNavigate) {

0 commit comments

Comments
 (0)