Quasar Vitest: How to set up i18n boot file for both the dev/prod and the test

typescript
Ethan JacksonThe recommendation for i18n in Quasar is to add it to a boot file like this:
import { defineBoot } from '#q-app/wrappers'
import { createI18n } from 'vue-i18n'
import messages from 'src/i18n'
export default defineBoot(({ app }) => {
const i18n = createI18n({
locale: 'en-US',
globalInjection: true,
messages
})
// Set i18n instance on app
app.use(i18n)
})
From: https://quasar.dev/options/app-internationalization#setup-manually
However, when you run tests under Vitest as per https://testing.quasar.dev/packages/unit-vitest/ the boot files are not executed meaning your i18n will remain uninitialised.
In my app I use the i18n in both the Vue components and in some of the plain JS classes. I specifically want to test the JS classes and the tests are failing because the i18n is uninitialised.
I attempted to use one of the suggestions about installQuasarPlugin
but still no success - i18n remained initialised.
Answer
So, what I did instead was:
- Created a composable for the i18n like this:
/**
* Composable to provide GLOBAL i18n functionality
* for both Vue and Business Logic.
*
* Note: This is used to get the i18n instance into the boot file for Vue components.
* It is also used directly for the BL classes.
*/
import { createI18n } from 'vue-i18n'
// ie uses @/yourapp/i18n/index.js which loads all the language files into one object
import messages from '@/yourapp/i18n'
// Run once, and export i18n so it can be used in the boot file
// so it gets injected into the Vue components.
export const i18n = createI18n({
legacy: false, // Use false so it is the same as what the app uses. ie the Composition API mode.
locale: 'en-AU',
fallbackLocale: 'en-AU',
globalInjection: true,
warnHtmlMessage: false,
silentTranslationWarn: true,
silentFallbackWarn: true,
messages // The complete set for all locales
})
// Export the methods for use in your BL classes.
export function usei18n () {
const setGlobalLocale = async (locale) => {
i18n.global.locale.value = locale
}
const getGlobalLocale = () => {
return i18n.global.locale.value
}
const getGlobalMessages = () => {
return i18n.global.messages.value
}
const getTranslate = () => {
return i18n.global.t
}
return {
i18n,
setGlobalLocale,
getGlobalLocale,
getGlobalMessages,
getTranslate
}
}
- In my JS classes I use it in the normal way for composables:
import { usei18n } from '@/platform/use/usei18n.js'
const { setGlobalLocale, getGlobalLocale } = usei18n()
- In the boot file I use the composable:
// Use our composable which is also used for the BL classes
import { i18n } from '@/platform/use/usei18n'
export default ({ app }) => {
// Just plug it into the app.
app.use(i18n)
}
Works well. :-)