Search code examples
laravelvue.jsvue-i18n

vue-i18n not translating locale json files


Building an laravel spa with Vue and wanted to add some i18n to use it in different languages but when trying to use locale json files the translation does not work, when adding it inside the file it will work. I do get an warning back saying [intlify] Not found 'dashboard' key in 'en' locale messages.

package.json

{
    "private": true,
    "scripts": {
        "dev": "npm run development",
        "development": "mix",
        "watch": "mix watch",
        "watch-poll": "mix watch -- --watch-options-poll=1000",
        "hot": "mix watch --hot",
        "production": "mix --production"
    },
    "devDependencies": {
        "@intlify/eslint-plugin-vue-i18n": "^0.11.1",
        "@vue/compiler-sfc": "^3.0.11",
        "autoprefixer": "^10.2.5",
        "axios": "^0.19.2",
        "bootstrap": "^4.6.0",
        "eslint": "^7.27.0",
        "jquery": "^3.6",
        "laravel-mix": "^6.0.18",
        "lodash": "^4.17.19",
        "node-sass": "^6.0.0",
        "popper.js": "^1.16.1",
        "postcss": "^8.2.15",
        "resolve-url-loader": "^3.1.2",
        "sass": "^1.32.11",
        "sass-loader": "^10.0.0",
        "tailwindcss": "^2.1.2",
        "vue": "^3.0.5",
        "vue-loader": "^16.1.2",
        "vue-template-compiler": "^2.6.12",
        "webpack-cli": "^4.7.0"
    },
    "dependencies": {
        "@vue/cli": "^4.5.13",
        "browser-sync": "^2.26.14",
        "browser-sync-webpack-plugin": "^2.3.0",
        "npm-watch": "^0.9.0",
        "postcss-import": "^14.0.2",
        "vue-i18n": "^9.1.6",
        "vue-router": "^4.0.8",
        "vuex": "^4.0.0"
    }
}

plugins/i18n.js

import { createI18n } from 'vue-i18n'

// these will work
const workingMessages = {
    "en":{
        "dashboard":"Welcome"
    },
    "nl":{
        "dashboard":"Welkom"
    }
}

export async function loadLocalMessages () {
    const locales = require.context('../locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
    const messages = {}
    locales.keys().forEach(key => {
      const matched = key.match(/([A-Za-z0-9-_]+)\./i)
      if (matched && matched.length > 1) {
        const locale = matched[1]
        messages[locale] = locales(key)
      }
    })
    return messages
}

const i18n = createI18n({
    locale: process.env.VUE_APP_I18N_LOCALE || 'en',
    fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
    messages: loadLocalMessages()
});
  
export default i18n

Component.vue

<template>
   <div>{{$t("dashboard")}}</div>
</template>

Solution

  • The problem is loadLocalMessages is async, so it automatically returns a Promise:

    export async function loadLocalMessages() {...}
           ^^^^^
    

    createI18n expects messages to be an object, not a Promise. It doesn't look like loadLocalMessages() does anything async, so just remove async.