Search code examples
nuxt.jspinianuxt-i18n

How to use i18n messages in a Nuxt3 pinia store


When trying to use an i18n message in a Nuxt3 Pinia store I get the error message: "SyntaxError: Must be called at the top of a setup function"

When using a message in a template I can do:

<template>
 <p>{{ $t('welcome') }}</p>
</template>

But how to do it in the pinia store?

Here is what I tried in the store that led to the error:

 import { defineStore } from 'pinia';
const { t } = useI18n();

export const useAppStore = defineStore('appStore', {
  state: () => {
    return {
      label: $t('welcome')
    };
  },  
});


Solution

  • Most composables in Nuxt require application context to work with. Having code inside setup() option or using <script setup> tag in components ensures the context is known. It is also automatically available when the app is parsing templates - this is why it "just works" inside your template.

    The problematic line is const { t } = useI18n(); because placed like this it is executed immideately upon loading the script and not after it is invoked from some component.

    I find out following works for referencing I18n translation function from within scripts as $i18n object is being added into Nuxt application via the module and useNuxtApp() exposes the app instance to you:

    export const useAppStore = defineStore('appStore', {
      state: () => {
        return {
          label: useNuxtApp().$i18n.t('welcome')
        };
      },  
    });
    

    Since I find the syntax a bit verbose, I usually create a composable wrapper around it to spare some characters:

    export function useT (key: string): string {
      return useNuxtApp().$i18n.t(key)
    }
    

    Then I can only call useT('welcome')

    Providing you invoke useAppStore() inside your component's setup, it should work fine, because the Pinia store shouldn't init prior to the first useAppStore() call.