最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - [Nuxt, i18n, Vuex]: How to access this.$i18n.locales from store getter - Stack Overflow

programmeradmin6浏览0评论

I'm building a web app using Nuxt v2.15 and @nuxtjs/i18n v7.2. I'm using Vuex for state management. In my global state, I want to create a getter that returns a value based on this.$i18n.locale.

What is the best way to access the current app context, which has $i18n attached to it, in my Vuex getter method?

nuxt.config.js

export default {
  modules: [
    "@nuxtjs/i18n", // /
  ],
  i18n: {
    locales: { /* configuration */ },
    defaultLocale: "en",
    detectBrowserLanguage: {
      fallbackLocale: "en",
      redirectOn: "root",
    },
    langDir: "~/locales/",
    vueI18n: {
      fallbackLocale: "en",
      messages: { /* translation data */ },
    },
  },
};

store/index.js

export const state = () => ({
  // Root module for Vuex store: /
});

export const getters = {
  loginOpts() {
    const locale = this.$i18n.locale;
    const uiLocales = [locale];
    if (locale === "zh") {
      uiLocales.push("zh-CN");
    }
    return { params: { ui_locales: uiLocales } };
  },
};

ponents/login.vue

<template>
  <div>
    <v-btn v-if="$auth.loggedIn" @click="$auth.logout()">Sign Out</v-btn>
    <v-btn v-else @click="$auth.loginWith('auth0', $store.getters.loginOpts)">Sign In</v-btn>
  </div>
</template>

<script>
import { mapGetters } from "vuex";

export default {
  name: "Login",
  data() {
    return {};
  },
  puted: {
    ...mapGetters(["loginOpts"]),
  },
};
</script>

What I expect

I expect to be able to access this.$i18n from a Vuex getter, or to have some means of doing so.

What actually happens

In the getter method, this is undefined.

TypeError: Cannot read properties of undefined (reading '$i18n')

What I've tried

I see here that a getter is passed four arguments: state, getters, rootState, and rootGetters.

I've tried:

  • RTFM for Vuex State, Getters, and Nuxt i18n
  • accessing state.$i18n
  • adding $i18n: this.$i18n to the root state

I'm building a web app using Nuxt v2.15 and @nuxtjs/i18n v7.2. I'm using Vuex for state management. In my global state, I want to create a getter that returns a value based on this.$i18n.locale.

What is the best way to access the current app context, which has $i18n attached to it, in my Vuex getter method?

nuxt.config.js

export default {
  modules: [
    "@nuxtjs/i18n", // https://i18n.nuxtjs/
  ],
  i18n: {
    locales: { /* configuration */ },
    defaultLocale: "en",
    detectBrowserLanguage: {
      fallbackLocale: "en",
      redirectOn: "root",
    },
    langDir: "~/locales/",
    vueI18n: {
      fallbackLocale: "en",
      messages: { /* translation data */ },
    },
  },
};

store/index.js

export const state = () => ({
  // Root module for Vuex store: https://nuxtjs/docs/directory-structure/store/
});

export const getters = {
  loginOpts() {
    const locale = this.$i18n.locale;
    const uiLocales = [locale];
    if (locale === "zh") {
      uiLocales.push("zh-CN");
    }
    return { params: { ui_locales: uiLocales } };
  },
};

ponents/login.vue

<template>
  <div>
    <v-btn v-if="$auth.loggedIn" @click="$auth.logout()">Sign Out</v-btn>
    <v-btn v-else @click="$auth.loginWith('auth0', $store.getters.loginOpts)">Sign In</v-btn>
  </div>
</template>

<script>
import { mapGetters } from "vuex";

export default {
  name: "Login",
  data() {
    return {};
  },
  puted: {
    ...mapGetters(["loginOpts"]),
  },
};
</script>

What I expect

I expect to be able to access this.$i18n from a Vuex getter, or to have some means of doing so.

What actually happens

In the getter method, this is undefined.

TypeError: Cannot read properties of undefined (reading '$i18n')

What I've tried

I see here that a getter is passed four arguments: state, getters, rootState, and rootGetters.

I've tried:

  • RTFM for Vuex State, Getters, and Nuxt i18n
  • accessing state.$i18n
  • adding $i18n: this.$i18n to the root state
Share Improve this question edited Jan 30, 2022 at 1:58 Shaun Scovil asked Jan 30, 2022 at 1:07 Shaun ScovilShaun Scovil 3,9875 gold badges45 silver badges59 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 3

I had a similar problem last week where I absolutely needed to use i18n inside a vuex getter.

I wouldn't remend this as its probably not the most performant thing in the world but it worked for me and solved a huge problem while I was working on a government application.

ponents/login.vue

<template>
  <div>
    <v-btn v-if="$auth.loggedIn" @click="$auth.logout()">Sign Out</v-btn>
    <v-btn v-else @click="$auth.loginWith('auth0', theLoginOpts)">Sign In</v-btn>
  </div>
</template>

<script>
import { mapGetters } from "vuex";

export default {
  name: "Login",
  data() {
    return {
        theLoginOpts: $store.getters.loginOpts(this) // The secret sauce
    };
  },
  puted: {
    ...mapGetters(["loginOpts"]),
  },
};
</script>

store/index.js

export const state = () => ({
  // Root module for Vuex store: https://nuxtjs/docs/directory-structure/store/
});

export const getters = {
  loginOpts: (state) => (app) => { // App is the secret sauce from earlier
    const locale = app.$i18n.locale;
    const uiLocales = [locale];
    if (locale === "zh") {
      uiLocales.push("zh-CN");
    }
    return { params: { ui_locales: uiLocales } };
  },
};

After digging through docs, experimenting, and discussing with the folks who were kind enough to offer answers here, it is clear that i18n is not directly accessible in a Vuex getter method, despite the fact that @nuxt/i18n registers a Vuex module called i18n and everything I've read about Vuex modules suggests this should be possible.

I did however e across the docs for @nuxt/i18n callbacks, which led me to create a small plugin that sets the value of locale and uiLocales in the global state using a mutation.

The end result looks like this:

nuxt.config.js

export default {
  modules: [
    "@nuxtjs/i18n", // https://i18n.nuxtjs/
  ],
  plugins: [
    "~/plugins/i18n.js",
  ],
  i18n: {
    locales: { /* configuration */ },
    defaultLocale: "en",
    detectBrowserLanguage: {
      fallbackLocale: "en",
      redirectOn: "root",
    },
    langDir: "~/locales/",
    vueI18n: {
      fallbackLocale: "en",
      messages: { /* translation data */ },
    },
  },
};

plugins/i18n.js

export function findLocaleConfig (i18n, locale) {
  return (
    i18n.locales.find(({ iso, code }) => [iso, code].includes(locale)) || {}
  );
}

export default function ({ app }) {
  app.store.mit("localeChange", findLocaleConfig(app.i18n, app.i18n.locale));

  app.i18n.onLanguageSwitched = (oldLocale, newLocale) => {
    app.store.mit("localeChange", findLocaleConfig(app.i18n, newLocale));
  };
}

store/index.js

export const state = () => ({
  locale: null,
  uiLocales: [],
});

export const mutations = {
  localeChange(state, locale) {
    state.locale = locale.code;
    state.uiLocales = [locale.code, locale.iso];
  },
};

ponents/login.vue

<template>
  <div>
    <v-btn v-if="$auth.loggedIn" @click="$auth.logout()">Sign Out</v-btn>
    <v-btn v-else @click="$auth.loginWith('auth0', loginOpts)">Sign In</v-btn>
  </div>
</template>

<script>
export default {
  name: "Login",
  data() {
    return {};
  },
  puted: {
    loginOpts() {
      const uiLocales = this.$store.state.uiLocales;
      return { params: { ui_locales: uiLocales } };
    },
  },
};
</script>

You can access a the locale in an Vuex action with: this.app.i18n.locale.
This cannot be accessed in a state or getter (a getter is a not a place for it anyway IMO).

PS: The above means that means that you can access this value anywhere you have access to the Nuxt context.

The simple way we did in our project is like below: In ponent puted prop

teamsForSelector() {
  return this.$store.getters['pany/teamsForSelector'](this.$i18n);
}

and in state getters

teamsForSelector: (state) => ($i18n) => {
const teamsForSelector = state.teams.map((team) => {
  return {
    id: team.teamUid,
    label: team.teamName,
  };
});
teamsForSelector.unshift({
  id: 'all-teams',
  label: $i18n.t('key'),
});

return teamsForSelector; }

In Nuxt 2 if your page renders on frontend you can try to access $i18n using window.$nuxt or simply $nuxt:

export const getters = {
  loginOpts() {
    const locale = window.$nuxt.$i18n.locale;
    ...
  },
};

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论