i18n: Vue-i18n-loader does not work

There is the problem in the main loader. In the documentation of vue-i18n, translations could be defined in the Single page component(<i18n></i18n>) by the following configs in the rule’s module:

module: {
   rules: [
   {
     test: /\.vue$/,
     loader: 'vue-loader',
     options: {
       loaders: {
         i18n: '@kazupon/vue-i18n-loader'
       }
     }
   },
   // ...
 ]
}

The problem is that we don’t use ‘vue-loader’, we use ‘eslint-loader’ instead in nuxt project. And adding loaders into the config changes nothing. I tried to define new ‘push()’ with ‘vue-loader’, but after that, other loaders works incorrectly. Or maybe Vue-i18n-loader is not adaptive for the SSR, so maybe we need nuxt-i18n-loader. And is there a place to be?

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 21 (1 by maintainers)

Commits related to this issue

Most upvoted comments

Hello everybody, I have an alternative solution, if you are interested.

Explanation

The problem by adding the webpack configuration like below, is that you overwrite all of vue-loader rules set by Nuxt.

// nuxt.config.js
...
build: {
    extend(config, ctx) {
      config.module.rules.push({
        test: /\.i18n$/,
        loader: `@kazupon/vue-i18n-loader?${JSON.stringify({
          includePaths: [path.resolve(__dirname), 'node_modules']
        })}`
      });
    }
},
...

A simple console.log() on the webpack configuration:

// Find the rules
console.log( config.module.rules.find( el => el.loader === 'vue-loader' ).options.loaders)
// Output
{ 
js: 
   { loader: 'babel-loader',
     options: { babelrc: false, cacheDirectory: true, presets: [Array] } },
  css: 
   [ { loader: 'vue-style-loader', options: [Object] },
     { loader: 'css-loader', options: [Object] } ],
  less: 
   [ { loader: 'vue-style-loader', options: [Object] },
     { loader: 'css-loader', options: [Object] },
     { options: [Object], loader: 'less-loader' } ],
  scss: 
   [ { loader: 'vue-style-loader', options: [Object] },
     { loader: 'css-loader', options: [Object] },
     { options: [Object], loader: 'sass-loader' } ],
  sass: 
   [ { loader: 'vue-style-loader', options: [Object] },
     { loader: 'css-loader', options: [Object] },
     { options: [Object], loader: 'sass-loader' } ],
  stylus: 
   [ { loader: 'vue-style-loader', options: [Object] },
     { loader: 'css-loader', options: [Object] },
     { options: [Object], loader: 'stylus-loader' } ],
  styl: 
   [ { loader: 'vue-style-loader', options: [Object] },
     { loader: 'css-loader', options: [Object] },
     { options: [Object], loader: 'stylus-loader' } ]
}

Solution

The simplest way it’s to add the configuration like below

// nuxt.config.js
...
build: {
    extend(config, ctx) {
      config.module.rules.find( el => el.loader === 'vue-loader' ).options.loaders.i18n = '@kazupon/vue-i18n-loader'
    }
},
...

Full Setup

Install vue-i18n and @kazupon/vue-i18n-loader (in dev).

package.json

"dependencies": {
    "@firebase/app": "^0.1.10",
    "@firebase/database": "^0.2.1",
    "@nuxtjs/axios": "^5.0.0",
    "nuxt": "^1.0.0",
    "vue-i18n": "^7.6.0",
    "vue-moment": "^3.2.0",
    "vuetify": "^0.17.3"
  },
  "devDependencies": {
    "@kazupon/vue-i18n-loader": "^0.3.0",
    "yaml-loader": "^0.4.0",
    "@std/esm": "^0.26.0",
    "cross-env": "^5.0.1",
    "esm": "^3.0.14",
    "firebase-tools": "^3.17.4",
    "stylus": "^0.54.5",
    "stylus-loader": "^3.0.1"
  }

Create i18n.js plugin.

plugins/i18n.js

import Vue from 'vue';
import VueI18n from 'vue-i18n';

Vue.use(VueI18n);

export default ({app, store}) => {
    app.i18n = new VueI18n({
        locale: 'ja',
        fallbackLocale: 'ja',
    });
};

Add plugin to Nuxt nuxt.config.js

   /*
    ** Plugins to load before mounting the App
    */
    plugins: [
        '@/plugins/i18n.js',
    ],

Add <i18n> in component/page/layout template components/MyComponent

<template>
    <div>{{ $t('hello') }}<div/>
</template>
<i18n>
{
  "en": {
    "hello": "hello world!"
  },
  "ja": {
    "hello": "こんにちは、世界!"
  }
}
</i18n>

You can see a sample on my repository: https://github.com/moifort/play-with-nuxt

ctmxo3hwf0

Solution for nuxt 2:

config.module.rules.push({
                resourceQuery: /blockType=i18n/,
                loader: '@kazupon/vue-i18n-loader'
            })

I’m using nuxt-edge after upgrading to 5.1 I’m getting the following error:

TypeError: Cannot set property 'i18n' of undefined at Builder.extendBuild.config (/Users/chanlito/Codes/experimental/x-app/node_modules/nuxt-i18n/src/module.js:105:31)

hi @adetbekov , here’s my package.json atm

"dependencies": {
    "@kazupon/vue-i18n-loader": "^0.3.0",
    "@nuxtjs/axios": "^5.0.0",
    "@nuxtjs/component-cache": "^1.1.1",
    "@nuxtjs/dotenv": "^1.1.0",
    "@nuxtjs/localforage": "^1.0.2",
    "@nuxtjs/proxy": "^1.1.4",
    "@nuxtjs/pwa": "^2.0.5",
    "@nuxtjs/sentry": "^1.0.1",
    "@nuxtjs/toast": "^3.0.0",
    "axios": "^0.18.0",
    "babel-polyfill": "^6.26.0",
    "bootstrap": "^4.0.0",
    "bootstrap-vue": "^2.0.0-rc.2",
    "file-loader": "^1.1.11",
    "fontfaceobserver": "^2.0.13",
    "full-icu": "^1.2.1",
    "intl": "^1.2.5",
    "lazysizes": "^4.0.1",
    "newrelic": "^3.1.0",
    "node-sass": "^4.8.3",
    "nuxt-custom-headers": "^2.0.0",
    "nuxt-edge": "^2.0.0",
    "nuxt-sass-resources-loader": "nuxt-community/nuxt-sass-resources-loader#feat/v2",
    "object-hash": "^1.2.0",
    "sass-loader": "^6.0.7",
    "sass-resources-loader": "^1.3.3",
    "smoothscroll-polyfill": "^0.4.3",
    "svg-sprite-loader": "^3.7.1",
    "url-loader": "^1.0.1",
    "vue-i18n": "^7.6.0",
    "vue-i18n-extensions": "^0.1.0",
    "vue-loader": "^15.0.0-beta.7",
    "vue-slider-component": "^2.5.8",
    "vue-styleguidist": "^1.4.9",
    "webpack-gcs-plugin": "^0.1.1"
  },
  "devDependencies": {
    "babel-eslint": "^8.2.1",
    "babel-jest": "^22.1.0",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "browser-env": "^3.2.4",
    "eslint": "^4.18.2",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-config-prettier": "^2.6.0",
    "eslint-config-standard": "^11.0.0-beta.0",
    "eslint-loader": "^2.0.0",
    "eslint-plugin-html": "^4.0.2",
    "eslint-plugin-import": "^2.8.0",
    "eslint-plugin-json": "^1.2.0",
    "eslint-plugin-jsx-a11y": "^6.0.2",
    "eslint-plugin-node": "^6.0.1",
    "eslint-plugin-prettier": "^2.5.0",
    "eslint-plugin-promise": "^3.5.0",
    "eslint-plugin-react": "^7.6.0",
    "eslint-plugin-standard": "^3.0.1",
    "eslint-plugin-vue": "^4.2.2",
    "jest": "^22.1.4",
    "jest-junit": "^3.4.1",
    "jest-serializer-vue": "^1.0.0",
    "postcss-html": "^0.15.0",
    "stylelint": "^9.1.2",
    "stylelint-config-recommended-scss": "^3.0.0",
    "stylelint-config-standard": "^18.2.0",
    "stylelint-order": "^0.8.0",
    "stylelint-scss": "^2.2.0",
    "vue-jest": "^2.1.1",
    "vue-test-utils": "^1.0.0-beta.11"
  }

here’s a part of my nuxt.config.js

build: {
    extend(config, ctx) {
      config.module.rules.push({
        test: /\.i18n$/,
        loader: `@kazupon/vue-i18n-loader?${JSON.stringify({
          includePaths: [path.resolve(__dirname), 'node_modules']
        })}`
      });
    }
},
plugins: [
    '~/plugins/vue-i18n.js'
],
render: {
    bundleRenderer: {
      directives: {
        t: i18nExtensions.directive
      }
    },
}

here’s my vue-i18n.js

import Vue from 'vue';
import VueI18n from 'vue-i18n';

Vue.use(VueI18n);

export default ({ app, store }) => {
  const currentApp = app;
  currentApp.i18n = new VueI18n({
    locale: store.state.i18n.currentLocale.language,
    fallbackLocale: 'fr',
  });
};

here’s a i18n part of a component :

<i18n lang="i18n">
{
  "fr": {
    "in_stock": "En stock"
  },
  "en": {
    "in_stock": "In stock"
  },
  "es": {
    "in_stock": "some traduction"
  },
  "de": {
    "in_stock": "Auf Lager"
  },
  "it": {
    "in_stock": "Disponibile"
  },
  "nl": {
    "in_stock": "Op voorraad"
  },
  "pt": {
    "in_stock": "In stock"
  }
}
</i18n>

and finally the results : https://i.imgur.com/F066MWU.png https://i.imgur.com/BYArnvq.png

In the nuxtServerInit, we have some logical to handle marketLanguage from the http request.

Let me know if you’re still having issues

@karellm I haven’t used vue-i18n-loader recently and don’t think I’ve ever tried with a lang switcher actually, the few times I used it was to make some quick prototyping before moving all translations to another file. But there are some issues with this option for sure, I still need to investigate but am lacking time lately…