如何在 Vue 3 + i18n 中导入多个语言环境 json 文件?

How to import multiple locale json files in Vue 3 + i18n?

这是我的代码,可以正常运行:

import { createI18n } from 'vue-i18n'
import messages from './components/json/foo/foo_messages.json'

const app = createApp(App)
installI18n(app)

const i18n = createI18n({
  locale: 'ru',
  messages
})

app
  .use(i18n)
  .use(vuetify)
  .mount('#app')

现在我还需要加载来自 ./components/json/bar/bar_messages.json 的消息。我试过这样做:

import { createI18n } from 'vue-i18n'
import foo_msg from './components/json/foo/foo_messages.json'
import bar_msg from './components/json/bar/bar_messages.json'

const app = createApp(App)
installI18n(app)

const i18n = createI18n({
  locale: 'ru',
  messages: {foo_msg, bar_msg}
})

app
  .use(i18n)
  .use(vuetify)
  .mount('#app')

但是没有用。谁能说说怎么做?

编辑:这是我的 foo json 文件

{
  "ru": {
    "header": {
      "hello": "Привет"
    }
  },
  "en": {
    "header": {
      "hello": "Hello"
    }
  }
}

这是酒吧 json 文件

{
  "ru": {
    "footer": {
      "bye": "Пока"
    }
  },
  "en": {
    "footer": {
      "bye": "Goodbye"
    }
  }
}

您尝试做的事情不是很可扩展。鉴于 i18n JSON 消息的格式,您需要将输入文件合并为如下格式:

{
  "ru": {
    "header": {
      "hello": "Привет"
    },
    "footer": {
      "bye": "Пока"
    }
  },
  "en": {
    "header": {
      "hello": "Hello"
    },
    "footer": {
      "bye": "Goodbye"
    }
  }
}

...这在 JS 中绝对可行,但您仍然必须为 main.js 中的每个组件导入 JSON 文件,这既乏味又容易出错

您是否考虑过在您的组件中使用 vue-i18n custom blocks?您甚至可以将翻译保留在外部 JSON 文件中,并使用像 <i18n src="./myLang.json"></i18n>

这样的自定义块

这是更好的方法,但如果您仍然想使用自己的方法,这里有一段简单的代码,说明如何将所有翻译文件(从 JSON 导入的对象)合并到 vue-i18n 可用的单个对象中:

// import foo_msg from './components/json/foo/foo_messages.json'
const foo_msg = {
  "ru": {
    "header": {
      "hello": "Привет"
    }
  },
  "en": {
    "header": {
      "hello": "Hello"
    }
  }
}

// import bar_msg from './components/json/bar/bar_messages.json'
const bar_msg = {
  "ru": {
    "footer": {
      "bye": "Пока"
    }
  },
  "en": {
    "footer": {
      "bye": "Goodbye"
    }
  }
}

const sources = [foo_msg, bar_msg]
const messages = sources.reduce((acc, source) => {
  for(key in source) {
    acc[key] = { ...(acc[key] || {}), ...source[key] }
  }
  return acc
},{})

console.log(messages)

接受的解决方案已经是很好的解决方案,但如果您协助使用.json文件来翻译文本。这是我的解决方案。

使用vue-cli添加i18n依赖,它会生成我们需要的所有需求文件。

vue add vue-i18n

它将在 src 中生成 locales 文件夹,其中存储所有翻译 json 文件。 然后它会在 .env 文件和一个 i18n.js 文件

上生成几个环境变量

这是它生成的i18n.js

import { createI18n } from 'vue-i18n'

/**
 * Load locale messages
 *
 * The loaded `JSON` locale messages is pre-compiled by `@intlify/vue-i18n-loader`, which is integrated into `vue-cli-plugin-i18n`.
 * See: https://github.com/intlify/vue-i18n-loader#rocket-i18n-resource-pre-compilation
 */
function loadLocaleMessages() {
  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).default
    }
  })
  return messages
}

export default createI18n({
  locale: process.env.VUE_APP_I18N_LOCALE || 'en',
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
  messages: loadLocaleMessages()
})

在我们的main.js中,我看到vue已经帮我添加了组件

import i18n from './i18n'

const app = createApp(App).use(i18n)

*编辑 我正在使用 vite 构建 vue 项目,loadLocaleMessages 在我的情况下不起作用。 我做了一些修改。它需要手动导入所有 json 文件,但我没有找到任何替代解决方案。

我还更改了带有 'VITE' 前缀的 env 变量,并将 process.env 更改为 import.meta.env。

// import all the json files
import en from './locales/en.json'
import zh from './locales/zh.json'

/**
 * Load locale messages
 *
 * The loaded `JSON` locale messages is pre-compiled by `@intlify/vue-i18n-loader`, which is integrated into `vue-cli-plugin-i18n`.
 * See: https://github.com/intlify/vue-i18n-loader#rocket-i18n-resource-pre-compilation
 */
function loadLocaleMessages() {
  const locales = [{ en: en }, { zh: zh }]
  const messages = {}
  locales.forEach(lang => {
    const key = Object.keys(lang)
    messages[key] = lang[key] 
  })
  return messages
}
export default createI18n({
  locale: import.meta.env.VITE_APP_I18N_LOCALE || 'en',
  fallbackLocale: import.meta.env.VITE_APP_I18N_FALLBACK_LOCALE || 'en',
  messages: loadLocaleMessages()
})