如何在Vue 3 + i18n中导入多个本地化JSON文件?

6

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

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"
    }
  }
}

这是 bar 的 JSON 文件。

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

JSON文件长什么样? - Boussadjra Brahim
@BoussadjraBrahim 请查看修改。 - Pavel_K
@PeterKrebs 这样做是行不通的,因为所有顶级属性(语言标识符)都会覆盖来自不同来源的其他顶级属性... - Michal Levý
@PeterKrebs 好的,我明白了,我没有阅读所有的解决方案。无论如何,将所有翻译导入您的主文件(并合并)对于他的用例来说不是一个好的解决方案。 - Michal Levý
@MichalLevý 是的,我同意。只是将其标记为重复项让我选择问题,但我不认为可以选择特定的答案。无论如何,使用“i18n”标签是个好主意 - 我得自己试试。 - Peter Krebs
显示剩余2条评论
2个回答

4
你尝试的做法不够可扩展。鉴于i18n JSON消息的格式,你需要将输入文件合并成类似以下的内容:
{
  "ru": {
    "header": {
      "hello": "Привет"
    },
    "footer": {
      "bye": "Пока"
    }
  },
  "en": {
    "header": {
      "hello": "Hello"
    },
    "footer": {
      "bye": "Goodbye"
    }
  }
}

使用JavaScript确实可以做到这一点,但仍需在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)


0
已经被接受的解决方案是一个好的解决方案,但如果您希望使用 .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”前缀的环境变量,并使用import.meta.env代替process.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()
})


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接