предисловие
В настоящее время автор находится вShopeeНа работе основным видом деятельности нашей компании является трансграничная электронная коммерция, и в бизнесе участвуют несколько стран, поэтому наши системы будут включать международный перевод. насVueПроект технически принятVue-i18nэта библиотека.
Сегодня поговорим о функции этой библиотеки, использующей переменные при интернационализации. Использование переменных в переводе — очень распространенный сценарий. Самый простой пример, такой как следующий текст, необходимо интернационализировать.
I am Gopal.I am from China
но среди нихGopalа такжеChinaПеременные должны быть переданы, что нам делать в это время?
простой пропуск
Сначала мы определяем символы для перевода следующим образом
"introTips": "I am {name}.I am from {region}"
затем в шаблоне используйте
$t('introTips', { name: 'Gopal一号', region: 'China' })
может сделатьЯ Гопал №1. Я из Китая
Нужно добавить цвет в переменную
Предположим, мыGopalБольше, чем просто копия, должен быть красный? что нам делать? Мы можем визуализировать html напрямую, используя v-html. В настоящее время нам нужно изменить переведенные символы следующим образом.
introTipsTwo: "I am <span class='name'>{name}</span>.I am from {region}"
Прямой рендеринг с v-html
<div
class="text"
v-html="$t('introTipsTwo', { name: 'Gopal一号', region: 'China' })"
></div>
Результат рендеринга следующий
<div data-v-763db97b="" class="text">
I am <span class="name">Gopal一号</span>.I am from China
</div>
Примечание. Этот метод может вызвать XSS-атаки, поэтому не рекомендуется использовать этот метод.
Используйте атрибут места
Первая переведенная копия заменяется на исходную версию переменной.
introTips: "I am {name}.I am from {region}"
Непосредственно используйте компонент i18n и атрибут места, где путь относится к указанному выше ключу, а место определяет переменную.
<i18n path="introTips" tag="div">
<span class="name" place="name">Gopal 二号</span>
<span place="region">China</span>
</i18n>
Результат рендеринга следующий:
<div data-v-763db97b="">
I am <span data-v-763db97b="" place="name" class="name">Gopal 二号</span>.I am from <span data-v-763db97b="" place="region">China</span>
</div>
Мы реализовали нашу схему, ноЭтот метод будет устаревшим в следующей версии, посмотрите внимательно, это не слот во Vue? Да, окончательное официально рекомендуемое решение — это Slot, очень похожее на приведенное выше.
Окончательное решение — слот
Перейдите непосредственно к коду:
<i18n path="introTips" tag="div">
<template v-slot:name>
<span class="name">Gopal 三号</span>
</template>
<template v-slot:region>
<span>China</span>
</template>
</i18n>
Отрендеренный результат аналогичен приведенному выше
<div data-v-763db97b="">
I am <span data-v-763db97b="" class="name">Gopal 三号</span>.I am from <span data-v-763db97b="">China</span></div>
вопрос
При использовании его в проекте он сообщил об ошибке...
Мой подход точно такой же, как и выше...
сообщить об ошибке
<i18n path="introTips" tag="div">
<template v-slot:name>
<span class="name">Gopal 三号</span>
</template>
<template v-slot:region>
<span>China</span>
</template>
</i18n>
vue.esm.js:628 [Vue warn]: Error in nextTick: "TypeError: Cannot create property 'isRootInsert' on string 'You submit '"
Я чувствую, что снова потеряю волосы....
Представление точки останова
GoogleПосле прочтения этой ошибки и просмотра информации об ошибке в стеке это похоже на проблему рендеринга vNode, а затем я наткнулся на точку останова, где было сообщено об ошибке.Вы можете видеть, что элементы в массиве дочерних элементов ниже не все vnode .Первым пунктом является строка, которая должна быть виновником ошибки
Читать исходный код
Я посмотрел в node_modulesvue-i18nИсходный код, обратите внимание, что версия, которую я сейчас использую,8.15.0
Обнаружено, что в исходном коде функционального компонента i18n есть два очень странных кода, см. исходный код этого функционального компонента.Связь
export default {
name: 'i18n',
functional: true,
props: {
// 留意这里
tag: {
type: String
},
// ...
},
render (h: Function, { data, parent, props, slots }: Object) {
const { $i18n } = parent
// ...
const { path, locale, places } = props
const params = slots()
const children = $i18n.i(
path,
locale,
onlyHasDefaultPlace(params) || places
? useLegacyPlaces(params.default, places)
: params
)
const tag = props.tag || 'span'
return tag ? h(tag, data, children) : children
}
}
Обратите внимание на две последние строки кода
const tag = props.tag || 'span'
return tag ? h(tag, data, children) : children
Ах, это. . .childrenНеужели нет возможности казнить?
Я пытаюсь вернуться напрямуюchildren. ну успех...
попробуй обновить версию
Я думал об этом, попробовать обновиться до более новой версии?
Конечно, этот компонент был изменен..., код упрощен, исходный код виденСвязь
export default {
name: 'i18n',
functional: true,
props: {
// 留意这里
tag: {
type: [String, Boolean, Object],
default: 'span'
}
// ...
},
render (h: Function, { data, parent, props, slots }: Object) {
// ....
// 留意这里
const tag = (!!props.tag && props.tag !== true) || props.tag === false ? props.tag : 'span'
return tag ? h(tag, data, children) : children
}
}
Тег здесь может передавать String, Boolean и Object
Взгляните на официальную документацию
You can choose the root container's node type by specifying a
tagprop. If omitted, it defaults to'span'. You can also set it to the boolean valuefalseto insert the child nodes directly without creating a root element.
Проще говоряТег может быть передан как false, поэтому нет необходимости добавлять еще один узел во внешний слой перевода.
Я снова искал, чтобы исправить этоPRи соответствующийIssue
Решать проблему
Хотя кажется, что это решает проблему отсутствия необходимости настраивать корневой узел, я чувствую, что это также может решить мою проблему.После приведенной ниже версии обновления я изменил свой код.
<div class="test-container">
<i18n path="introTips" :tag="false">
<template v-slot:name>
<span class="name">Gopal 三号</span>
</template>
<template v-slot:region>
<span>China</span>
</template>
</i18n>
</div>
На этот раз действительно успешно, очень счастлив, в конечном итоге это следует
<div data-v-0b89d11d="" class="test-container">
<!-- 这里外层没有节点了 -->
I am <span data-v-0b89d11d="" class="name">Gopal 三号</span>.I am from <span data-v-0b89d11d="">China</span></div>
Вы можете видеть, что при рендеринге в это время нет самого внешнего тега.
Суммировать
В этой статье рассказывается об использовании переменных vue-i18n, несколько методов относительно просты и понятны. Это в основном для записи ямы, на которую я наступил, и это можно рассматривать как приобретение некоторого опыта.
- Когда нет идей, можно посмотреть исходный код. Вы можете просмотреть его непосредственно в node_modules или даже найти соответствующий код в файле dist, отладка точек останова
- Отладка исходного кода не только полезна для обнаружения проблем, но и расширяет горизонты. Например, реализация упомянутого выше функционального компонента i18n. Когда я смотрел на это, если бы меня попросили написать это, смог бы я написать это?
- Обратите внимание на официальный ISSUE, но в этот раз я посмотрел раньше, а не у меня эта ошибка...
- Сравните все официальные документы на английском языке, китайский и английский языки совсем разные (должны переводиться лаги)
наконец
Как упоминалось ранее, автор работает в Shopee, и студенты, которым нужно сменить работу, могут попросить меня подтолкнуть его~
На специальной сессии в мае есть много возможностей, вы можете проверить деталиСвязь. Первоклассная заводская заработная плата, меньше сверхурочных (компания способствует эффективной работе), хорошая атмосфера в коллективе, больше возможностей для карьерного роста, заинтересованные студенты, пожалуйста, спешите отправить свое резюме на мой почтовый ящик15521091584@163.com