Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How mock i18n with vitest #3291

Open
fchancel opened this issue Jan 2, 2025 · 4 comments
Open

How mock i18n with vitest #3291

fchancel opened this issue Jan 2, 2025 · 4 comments

Comments

@fchancel
Copy link

fchancel commented Jan 2, 2025

Hello,

I've been fighting for a day about the i18n mock with vitest.
Before updating to v9, I make a global mock as follows in vitest.setup.ts

vi.mock("vue-i18n", () => ({
  useI18n: () => ({
    t: (key: string) => key,
    locale: ref("en"),
  }),

  createI18n: () => ({
    install: () => {},
  }),
}));

But since the update, I've tried a number of solutions to make an i18n mock, but I've never succeeded.
I keep getting the following error:

SyntaxError: Need to install with `app.use` function
 ❯ Module.createCompileError ../node_modules/@intlify/message-compiler/dist/message-compiler.mjs:78:19
     76|         : code;
     77|     const error = new SyntaxError(String(msg));
     78|     error.code = code;
       |                   ^
     79|     if (loc) {
     80|         error.location = loc;
 ❯ createI18nError ../node_modules/vue-i18n/dist/vue-i18n.mjs:81:34
 ❯ Module.useI18n ../node_modules/vue-i18n/dist/vue-i18n.mjs:2187:15
 ❯ setup modules/test/pages/test/test.vue:28:19
 ❯ wrappedSetup ../node_modules/@nuxt/test-utils/dist/runtime-utils/index.mjs:244:28
 ❯ clonedComponent.setup ../node_modules/@nuxt/test-utils/dist/runtime-utils/index.mjs:328:50
 ❯ callWithErrorHandling ../node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:200:19
 ❯ setupStatefulComponent ../node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7848:25
 ❯ setupComponent ../node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:7809:36
 ❯ mountComponent ../node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5159:7

knowing that in my component view. I use the following format:

const { t } = useI18n()

and that my nuxt.config.ts is

is as follows:

  i18n: {
    strategy: "no_prefix",
    locales: [
      {
        code: "en",
        name: "English",
        files: ["en.json"],
      },
      {
        code: "fr",
        name: "Français",
        files: ["fr.json"],
      },
    ],
    defaultLocale: "en",
    detectBrowserLanguage: {
      useCookie: true,
      cookieKey: "i18n_test",
      fallbackLocale: "en",
    },
  },

Do you have any solutions ?

@th1nkgr33n
Copy link

th1nkgr33n commented Jan 22, 2025

Although I got another issues with the new Update :D

In the past we have configured a global i18n mock/instance in the setup.ts file of vitest.
Currently this throws a duplicated init warning for the t function, but if I remove this, I got your error, so this might help?

// https://github.com/nuxt/test-utils/issues/566#issuecomment-2200984889
import { config } from '@vue/test-utils'
import { createI18n } from 'vue-i18n'

const i18n = createI18n({
  legacy: false,
  globalInjection: true,
  locale: 'de',
  missing: (_, key) => key,
})

config.global.plugins.push(i18n)

vue-i18n made the use of the useI18n composable much stricter, not to use it outside of a "< setup >" inside a SFC.
So if you need it inside a composable or other purposes you need to use useNuxtApp().$i18n

@FruityLeo
Copy link

FruityLeo commented Jan 25, 2025

Hello,
I am also getting the same error with "app.use" all over my tests now after migrating to the new composition API of vue-i18n.

Your solution, @th1nkgr33n, helped me for the moment – thanks ❤️. My tests are running again, i18n usage in my components is migrated, but I am getting these annoying warnings:
[Vue warn]: Directive "t" has already been registered in target app.

I want to use real translations for my tests (or have a config for i18n that is close to the real world), so I need the following config – ideally I want the same config as my real world app is using:

const i18n = createI18n({
	legacy: false,
	globalInjection: true,
	locale: "en",
	messages: {
		en: {
			...english,
		},
		de: {},
	},
});
config.global.plugins.push(i18n);

vue-i18n made the use of the useI18n composable much stricter, not to use it outside of a
For other purposes you need to use useNuxtApp().$i18n

Can you explain this statement in more detail?

@th1nkgr33n
Copy link

@FruityLeo... The MarkdownEditor removed some stuff.
What I experienced was that, the usage of the usei18n() composable inside composables is not the ideal way. This really should only be used in SFC. For other purposes you should use the useNuxtApp().$i18n

We are in on-going work to remove that warning and if we found a solution for our project, I could post that here.

@FruityLeo
Copy link

Ah ok, got it, thanks.
Yes, inside a composable I was already using useNuxtApp().$i18n.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants