Цель
Проект должен поддерживать несколько языков.Нам нужно извлечь статический текст, используемый в проекте, и управлять им с помощью языковых пакетов. При переключении настройки языка может автоматически переключаться текстовое отображение всего проекта.
Найдите соответствующий компонент в проекте Vue.vue-i18n
, а код проекта сильно не модифицируется, поэтому этот компонент используется для модификации кода в проекте.
Установить
// script 引入
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-i18n/dist/vue-i18n.js"></script>
// npm 安装
npm install vue-i18n
// yarn 安装
yarn add vue-i18n
Как правило, использование в проекте запускается путем установки пакета.script
Вводить меньше.
использовать
Настроить i18n в проекте
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
const i18n = new VueI18n({
local: 'cn', // 设置语言
messages // 语言包
})
new Vue({
el: '#app',
...
i18n
})
// messages 大概的使用格式
{
cn: {
name: '名字'
},
us: {
name: 'Name'
}
}
использовать i18n
Простой в использовании
// html 需要使用 {{}} 将 name包装起来
{{$t('name')}}
// js
$t('name')
переменная, которую можно передать
// 命名传入参数
// messages:
{
cn: {
name: '名字:{name}'
},
us: {
name: 'Name: {name}'
}
}
$t('name', {name: 'Jack'}) // Name:Jack
// 列表传入参数
// messages:
{
cn: {
name: '名字:{0}{1}'
},
us: {
name: 'Name: {0}{1}'
}
}
// array
$t('name', ['Jack', 'Job'])
// object
$t('name', {'0':'Jack', '1': 'Job'])
формат множественного числа
использовать разделитель|
// messages:
{
us: {
car: 'car | cars | {count} cars'
}
}
$tc('car', x) // 选用不同的car类型
Формат времени
const dateTimeFormats = {
'us': {
short: {
year: 'numeric', month: 'short', day: 'numeric'
},
long: {
year: 'numeric', month: 'short', day: 'numeric',
weekday: 'short', hour: 'numeric', minute: 'numeric'
}
},
cn: {
xxx
}
}
// 需要放入配置项中
const i18n = new VueI18n({
locale: '',
messages,
dateTimeFormats
})
// 使用
$d(new Date(), 'short')
$d(new Date(), 'long')
$d(new Date(), 'short', 'cn')
Символ суммы
const numberFormats = {
'en-US': {
currency: {
style: 'currency', currency: 'USD'
}
},
'ja-JP': {
currency: {
style: 'currency', currency: 'JPY', currencyDisplay: 'symbol'
}
}
}
// 同样也要加入配置项中
const i18n = new VueI18n({
numberFormats
})
// 使用
$n(100, 'currency') // $100.00
$n(100, 'currency', 'ja-JP') // ¥100
Укажите настройку языка по умолчаниюfallbackLocale
Если язык не существует, укажите полный язык по умолчанию для обработки
const messages = {
cn: {
name: 'Name:'
}
us: {
}
}
// us 的语言包中不存在 name , 我们默认cn,当us不存在时,使用cn的值
const i18n = new VueI18n({
locale: 'us',
fallbackLocale: 'cn',
messages
})
v-t
может использоваться для ссылок на переменные, подобно$t
v-t
инструкция
// 官网的列子
new Vue({
i18n: new VueI18n({
locale: 'en',
messages: {
en: { hello: 'hi {name}!' },
ja: { hello: 'こんにちは、{name}!' }
}
}),
computed: {
nickName () { return 'kazupon' }
},
data: { path: 'hello' }
}).$mount('#object-syntax')
<div id="object-syntax">
<!-- literal -->
<p v-t="{ path: 'hello', locale: 'ja', args: { name: 'kazupon' } }"></p>
<!-- data biniding via data -->
<p v-t="{ path: path, args: { name: nickName } }"></p>
</div>
<div id="object-syntax">
<p>こんにちは、kazupon!</p>
<p>hi kazupon!</p>
</div>
$t
а такжеv-t
В сравнении
-
$t
это вызов метода,v-t
это инструкция -
v-t
коэффициент производительности$t
Еще лучше, есть кеши для пользовательских директив -
$t
Более гибкий и простой в использовании
Есть и другие способы использования, пожалуйста, обратитесь к конкретномуофициальная документация. .
Для переключения языков можно использовать встроенные переменные:
// 通过设置 locale 来切换语言
this.$i18n.locale = cn | us
Вставить компоненты
Если вы столкнулись с таким сценарием, как с ним бороться?
<p>I accept xxx <a href="/term">Terms of Service Agreement</a></p>
Моей первой реакцией было разделитьдва поля, тег a не относится к переведенному контенту, просто напишите:
<p>{{ $t('xx1') }}<a href="/term">{{ $t('xx2') }}</a></p>
Прочитав введение на официальном сайте, говорят, что такая обработка слишком топорная.компонентыспособ справиться с
// 这里使用了i81n 组件
<i18n path="term" tag="label" for="tos">
<a :href="url" target="_blank">{{ $t('tos') }}</a>
</i18n>
const messages = {
en: {
tos: 'Term of Service',
term: 'I accept xxx {0}.'
}
}
new Vue({
el: '#app',
i18n,
data: {
url: '/term'
}
})
Как видите, две переменные по-прежнему используются для хранения информации, ноtag
производить этикетки,path
формулировать содержание этикетки.
Таким образом, использование более сложное, чем использование двух ** $ T ('') ** способа для меня, вероятно, не надо, потому что не видел фактическую реализацию, не существует сравнения за производительность, заключение может Не учитывайте прямые, подробные последующие наблюдения, то также нужно осторожно сравнивать.
Более расширенное использование, вы можете контролировать элемент htmlВставить позицию,пройти черезplace
чтобы указать, где он появляется в html.
<i18n path="info" tag="p">
<span place="limit">{{ changeLimit }}</span>
<a place="action" :href="changeUrl">{{ $t('change') }}</a>
</i18n>
const messages = {
en: {
info: 'You can {action} until {limit} minutes from departure.',
change: 'change your flight',
refund: 'refund the ticket'
}
}
const i18n = new VueI18n({
locale: 'en',
messages
})
new Vue({
i18n,
data: {
changeUrl: '/change',
refundUrl: '/refund',
changeLimit: 15,
refundLimit: 30
}
}).$mount('#app')
// result
<p>
You can <a href="/change">change your flight</a> until <span>15</span> minutes from departure.
</p>
Целостность предложения сохраняется, но его нельзя использовать, если для существительных выполняется только многоязычный перевод и грамматика не требуется.
Динамически загружать языковые пакеты
Не обязательно загружать все языковые пакеты сразу, особенно если языковые пакеты были пройдены, я тоже раньше поднимал этот вопрос, и нашел, что официальный сайт дал решение.
//i18n-setup.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import messages from '@/lang' // 语言包的地址,随项目本身设置修改
import axios from 'axios' // 根据项目中使用api请求模块去设置,不一定是axios
Vue.use(VueI18n)
export const i18n = new VueI18n({
locale: 'en', // set locale
fallbackLocale: 'en', // 默认语言设置,当其他语言没有的情况下,使用en作为默认语言
messages // set locale messages
})
const loadedLanguages = ['en'] // our default language that is prelaoded
function setI18nLanguage (lang) {
i18n.locale = lang
axios.defaults.headers.common['Accept-Language'] = lang // 设置请求头部
document.querySelector('html').setAttribute('lang', lang) // 根元素增加lang属性
return lang
}
export function loadLanguageAsync (lang) {
if (i18n.locale !== lang) {
if (!loadedLanguages.includes(lang)) {
return import(/* webpackChunkName: "lang-[request]" */ `@/lang/${lang}`).then(msgs => {
i18n.setLocaleMessage(lang, msgs.default)
loadedLanguages.push(lang)
return setI18nLanguage(lang)
})
}
return Promise.resolve(setI18nLanguage(lang))
}
return Promise.resolve(lang)
}
// 在vue-router的beforeEach的全局钩子了处理
router.beforeEach((to, from, next) => {
const lang = to.params.lang
loadLanguageAsync(lang).then(() => next())
})
Генерация языковых пакетов и замена существующих статических текстов в проектах
Этот шаг самый важный,
- Извлечь все вхождения китайских иероглифов
- заменить
$t('xxx')
,$n
,$d
,v-t
Подождите, выберите в зависимости от ситуации - Поддерживать несколько версий языковых файлов
Вот как здесь обрабатывается языковой пакет.Новый каталог, languages, добавляется в проект.
--languages
--lib
-- cn.js // 中文语言包
-- us.js // 英文语言包
-- .. // 其他语言,暂未实践
-- index.js // 导出语言包
cn.js
export default {
common: {
message: '消息'
},
xxx: {
}
}
us.js
export default {
common: {
message: 'Messages'
},
xxx: {
}
}
index.js
import cn from './lib/cn.js'
export default {
cn,
us
}
заменить текст
<template>
...
<div>{{$t('message')}}</div>
...
</template>
вопрос
- Разные языки, разные форматы, разная длина, вам может потребоваться изменить стиль проекта, чтобы он оставался нормальным.
- Для проекта, который уже используется, этап создания языковых пакетов требует много работы и пустой траты времени.