Nuxt.js i18n 本地化在 SPA 模式下不起作用

Nuxt.js i18n localization doesn't work in SPA mode

我在通用模式下开发项目 Nuxt.js 并使用 i18n 本地化工作正常,但现在我想更改为 spa 模式,但 i18n 不会更改语言。 这是代码。 文件:nuxt.config.js

import colors from "vuetify/es5/util/colors";

export default {
  mode: "spa",
  /*
   ** Headers of the page
   */
  head: {
    meta: [
      { charset: "utf-8" },
      { name: "viewport", content: "width=device-width, initial-scale=1" },
      {
        hid: "description",
        name: "description",
        content: process.env.npm_package_description || ""
      }
    ],
    link: [
      { rel: "icon", type: "image/x-icon", href: "/favicon.ico" },
      {
        rel: "stylesheet",
        href:
          "https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons"
      }
    ]
  },
  /*
   ** Customize the progress-bar color
   */
  loading: { color: "#fff" },
  /*
   ** Global CSS
   */
  css: ["~/assets/main.css"],

  router: {
    middleware: "i18n"
  },
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [
    "~/plugins/mdi-font.js",
    "~/plugins/i18n.js",
    "~/plugins/axios.js",
    { src: "~/plugins/flag.js", ssr: false }
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    "@nuxtjs/vuetify",
    // Doc: https://axios.nuxtjs.org/usage
    "@nuxtjs/axios"
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {},
  /*
   ** vuetify module configuration
   ** https://github.com/nuxt-community/vuetify-module
   */
  vuetify: {
    theme: {
      primary: colors.blue.darken2,
      accent: colors.grey.darken3,
      secondary: colors.amber.darken3,
      info: colors.teal.lighten1,
      warning: colors.amber.base,
      error: colors.deepOrange.accent4,
      success: colors.green.accent3
    }
  },
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {}
  }
};

文件:middleware/i18n.js

export default function ({ isHMR, app, store, route, params, req, error, redirect }) {
    if (isHMR) { // ignore if called from hot module replacement
        return;
    }

    if (req) {
        if (route.name) {
            let locale = null;

            // check if the locale cookie is set
            if (req.headers.cookie) {
                const cookies = req.headers.cookie.split('; ').map(stringCookie => stringCookie.split('='));
                const cookie = cookies.find(cookie => cookie[0] === 'locale');

                if (cookie) {
                    locale = cookie[1];
                }
            }

            // if the locale cookie is not set, fallback to accept-language header
            if (!locale) {
                locale = req.headers['accept-language'].split(',')[0].toLocaleLowerCase().substring(0, 2);
            }

            store.commit('SET_LANG', locale);
            app.i18n.locale = store.state.locale;
        }
    }
};

store/index.js

export const state = () => ({
    locales: [
        {
            code: 'en',
            name: 'EN',
            flag: 'us'
        },
        {
            code: 'fa',
            name: 'FA',
            flag: 'af'
        },
        {
            code: 'pa',
            name: 'PA',
            flag: 'af'
        }
    ],
    locale: 'en'
});

export const mutations = {
    SET_LANG(state, locale) {
        if (state.locales.find(el => el.code === locale)) {
            state.locale = locale
        }
    }
};

和 licalize 文件在 locales/fa.json and en.json

export default function ({ isHMR, app, store, route, params, req, error, redirect })

这么粗的参数req在SAP模式下是接收不到的。如需更多信息,您可以访问此 link.

所以你必须尝试使用​​另一个参数的另一种方式,例如你可以看到下面的代码:

export default function ({
  isHMR, app, store, route, params, error, redirect
}) {
    const defaultLocale = app.i18n.fallbackLocale
  // If middleware is called from hot module replacement, ignore it
  if (isHMR) return
  // Get locale from params

                const locale = params.lang || defaultLocale
                if (store.state.locales.indexOf(locale) === -1) {
                  return error({
                    message: 'This page could not be found.',
                    statusCode: 404
                  })
                }

  // Set locale
  store.commit('SET_LANG', locale)
  app.i18n.locale = store.state.locale
  // If route is /<defaultLocale>/... -> redirect to /...

              if (locale === defaultLocale && route.fullPath.indexOf('/' + defaultLocale) ===
                0) {
                const toReplace = '^/' + defaultLocale
                const re = new RegExp(toReplace)
                return redirect(
                  route.fullPath.replace(re, '/')
                )
        } 
}

对于 SPA,您可以使用 js-cookie, 所以 middleware/i18n.js 中的代码将更改为

if (isHMR) return

const defaultLocale = app.i18n.fallbackLocale
let locale = null
const Cookie = require('js-cookie')
const cookie = Cookie.get('locale')    
if (cookie)
    locale = cookie

if (!locale){        
    const cookies = Cookie.set('locale', defaultLocale).split('; ').map(stringCookie => stringCookie.split('='))
    const cookie = cookies.find(cookie => cookie[0] === 'locale')
    if (cookie)
        locale = cookie[1]
}        
store.commit('SET_LANG', locale)
app.i18n.locale = store.state.locale

希望对您有所帮助。

就我而言,我在 Fr 中有自定义路线(在 nuxt.config.js 中设置为额外的自定义路线),但它也没有用。

我最终自己检测了区域设置,并为其余代码更新了内部 i18n 区域设置(问题 #1067):

async asyncData({$axios, $payloadURL, route, app, store}) {
  const [isFr] = route.fullPath.match(/^\/?fr_CA\/?/i) || []
  const locale = isFr ? 'fr_CA' : 'en'
  // NuxtI18n does not recognize the FR version of custom routes. :(
  // https://github.com/nuxt-community/i18n-module/issues/1067
  app.i18n.locale = locale
  ...
}