Skip to content

Commit

Permalink
feat: add loadLocaleMessages to manually load locale messages (#2799)
Browse files Browse the repository at this point in the history
* feat: extend Vue i18n with `loadLocaleMessages` function

* docs: add `loadLocaleMessages` to lazy-load en vue-i18n sections

* test: add test for `loadLocaleMessages`
  • Loading branch information
BobbieGoede authored Feb 16, 2024
1 parent de07830 commit bd8a2dd
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 13 deletions.
20 changes: 20 additions & 0 deletions docs/content/docs/2.guide/7.lazy-load-translations.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,23 @@ export default defineNuxtConfig({
}
})
```


## Using translations of non-loaded locale

As only the current locale translations are loaded you have to manually load a locale to be able to use its translations.

Nuxt i18n extends Vue i18n to provide the `loadLocaleMessages` function to manually load locale messages, the example below demonstrates its usage.

```ts
const { loadLocaleMessages, t } = useI18n()

await loadLocaleMessages('nl')

const welcome = computed(() => t('welcome')) // Welcome!
const welcomeDutch = computed(() => t('welcome', 1, { locale: 'nl' })) // Welkom!
```

::callout{type="info"}
As messages could be loaded from a remote API invoking the `loadLocaleMessages` function will always load messages, unnecessary loading can impact performance.
::
8 changes: 8 additions & 0 deletions docs/content/docs/4.api/4.vue-i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ Updates stored locale cookie with specified locale code. Consider using `setLoca

Switches locale of the app to specified locale code. If `useCookie` option is enabled, locale cookie will be updated with new value. If prefixes are enabled (`strategy` other than `no_prefix`), will navigate to new locale's route.

### loadLocaleMessages()

- **Arguments**:
- locale (type: `string`)
- **Returns**: `Promise<void>`

Loads the translation messages of the specified locale code. This is only relevant for projects using lazy-loaded translations when using translations from a non-loaded locale.

### getBrowserLocale()

- **Arguments**:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default defineI18nLocale(locale => ({
moduleLayerText: 'This is a merged module layer locale key in Dutch',
welcome: 'Welkom!',
dynamicTime: new Date().toISOString()
}))
3 changes: 2 additions & 1 deletion specs/fixtures/lazy/lang/lazy-locale-en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"posts": "Posts",
"dynamic": "Dynamic",
"html": "<span>This is the danger</span>",
"dynamicTime": "Not dynamic"
"dynamicTime": "Not dynamic",
"welcome": "Welcome!"
}
18 changes: 18 additions & 0 deletions specs/fixtures/lazy/pages/manual-load.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script lang="ts" setup>
import { useI18n } from '#i18n'
import { computed } from 'vue'
const { loadLocaleMessages, t } = useI18n()
await loadLocaleMessages('nl')
const welcome = computed(() => t('welcome'))
const welcomeDutch = computed(() => t('welcome', 1, { locale: 'nl' }))
</script>

<template>
<div>
<span id="welcome-english">{{ welcome }}</span>
<span id="welcome-dutch">{{ welcomeDutch }}</span>
</div>
</template>
17 changes: 7 additions & 10 deletions specs/lazy_load/basic_lazy_load.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,7 @@ describe('basic lazy loading', async () => {
})

test('files with cache disabled bypass caching', async () => {
// const home = url('/')
// const page = await createPage()
// await page.goto(home)
const { page, consoleLogs } = await renderPage('/')
// const messages: string[] = []
// page.on('console', msg => {
// const content = msg.text()
// if (content.includes('lazy-locale-')) {
// messages.push(content)
// }
// })

await page.click('#lang-switcher-with-nuxt-link-en-GB')
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-en-GB.js bypassing cache!'))).toHaveLength(1)
Expand All @@ -143,4 +133,11 @@ describe('basic lazy loading', async () => {
await page.click('#lang-switcher-with-nuxt-link-fr')
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-fr.json5 bypassing cache!'))).toHaveLength(2)
})

test('manually loaded messages can be used in translations', async () => {
const { page } = await renderPage('/manual-load')

expect(await getText(page, '#welcome-english')).toEqual('Welcome!')
expect(await getText(page, '#welcome-dutch')).toEqual('Welkom!')
})
})
15 changes: 13 additions & 2 deletions src/runtime/plugins/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ import {
parallelPlugin,
normalizedLocales
} from '#build/i18n.options.mjs'
import { loadVueI18nOptions, loadInitialMessages } from '../messages'
import { loadVueI18nOptions, loadInitialMessages, loadLocale } from '../messages'
import {
loadAndSetLocale,
detectLocale,
detectRedirect,
navigate,
injectNuxtHelpers,
extendBaseUrl,
_setLocale
_setLocale,
mergeLocaleMessage
} from '../utils'
import {
getBrowserLocale as _getBrowserLocale,
Expand Down Expand Up @@ -188,6 +189,11 @@ export default defineNuxtPlugin({
)
)
}
composer.loadLocaleMessages = async (locale: string) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const setter = (locale: Locale, message: Record<string, any>) => mergeLocaleMessage(i18n, locale, message)
await loadLocale(locale, localeLoaders, setter)
}
composer.differentDomains = nuxtI18nOptions.differentDomains
composer.defaultLocale = nuxtI18nOptions.defaultLocale
composer.getBrowserLocale = () => _getBrowserLocale()
Expand Down Expand Up @@ -299,6 +305,11 @@ export default defineNuxtPlugin({
return async (locale: string) => Reflect.apply(composer.setLocale, composer, [locale])
}
},
loadLocaleMessages: {
get() {
return async (locale: string) => Reflect.apply(composer.loadLocaleMessages, composer, [locale])
}
},
differentDomains: {
get() {
return composer.differentDomains
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ export interface ComposerCustomProperties<
* @param locale - A {@link Locale}
*/
setLocale: (locale: string) => Promise<void>
/**
* Loads locale messages of the specified locale code.
*
* @param locale - A {@link Locale}
*/
loadLocaleMessages: (locale: string) => Promise<void>
/**
* Returns browser locale code filtered against the ones defined in options.
*
Expand Down

0 comments on commit bd8a2dd

Please sign in to comment.