# Однофайловые компоненты
# Базовое использование
В компоненте Vue или приложении Vue с использованием однофайловых компонентов, можно управлять сообщениями локализации с помощью пользовательского блока i18n
.
Код компонента из примера использования с однофайловыми компонентами (opens new window):
<i18n>
{
"en": {
"hello": "hello world!"
},
"ru": {
"hello": "Привет мир!"
}
}
</i18n>
<template>
<div id="app">
<label for="locale">Язык</label>
<select v-model="locale">
<option>en</option>
<option>ru</option>
</select>
<p>Сообщение: {{ $t('hello') }}</p>
</div>
</template>
<script>
export default {
name: 'app',
data () {
this.$i18n.locale = 'ru';
return { locale: 'ru' }
},
watch: {
locale (val) {
this.$i18n.locale = val
}
}
}
</script>
# Установка vue-i18n-loader
Требуется установить vue-loader
и vue-i18n-loader
чтобы использовать пользовательские блоки <i18n>
. Скорее всего vue-loader (opens new window) уже используется в проекте, если уже работаете с однофайловыми компонентами, но необходимо дополнительно установить vue-i18n-loader (opens new window):
npm i --save-dev @kazupon/vue-i18n-loader
# Webpack
Для Webpack требуется следующая конфигурация:
Для vue-loader v15 или более поздних версий:
module.exports = {
// ...
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
resourceQuery: /blockType=i18n/,
type: 'javascript/auto',
loader: '@kazupon/vue-i18n-loader'
}
// ...
]
}
// ...
}
Для vue-loader v14:
module.exports = {
// ...
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// необходимо указать ключ `i18n` для загрузчика `vue-i18n-loader`
// (https://github.com/kazupon/vue-i18n-loader)
i18n: '@kazupon/vue-i18n-loader'
}
}
}
// ...
]
}
// ...
}
# Vue CLI 3.0
Vue CLI 3.0 (opens new window) скрывает конфигурацию Webpack, поэтому для добавления поддержки тегов <i18n>
в однофайловых компонентах необходимо изменить существующую конфигурацию.
Для этого нужно создать файл vue.config.js
в корне проекта и добавить в него следующее:
Для vue-loader v15 или более поздних версий:
module.exports = {
chainWebpack: config => {
config.module
.rule('i18n')
.resourceQuery(/blockType=i18n/)
.type('javascript/auto')
.use('i18n')
.loader('@kazupon/vue-i18n-loader')
.end()
}
}
Для vue-loader v14:
const merge = require('deepmerge')
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options =>
merge(options, {
loaders: {
i18n: '@kazupon/vue-i18n-loader'
}
})
)
}
}
Не забудьте установить deepmerge (opens new window)! (npm i deepmerge -D
или yarn add deepmerge -D
)
Подробнее о возможностях изменения существующей конфигурации Webpack можно изучить здесь (opens new window).
# Laravel-Mix
Для Laravel-mix 4 с vue-loader v15 или более поздней версии:
// Расширяем Mix с помощью метода "i18n", который загрузит vue-i18n-loader
mix.extend( 'i18n', new class {
webpackRules() {
return [
{
resourceQuery: /blockType=i18n/,
type: 'javascript/auto',
loader: '@kazupon/vue-i18n-loader',
},
];
}
}(),
);
// Убедитесь что вызвали .i18n() (для загрузки загрузчика) перед .js(..., ...)
mix.i18n()
.js( 'resources/js/App.js', 'public/js/app.js' )
...
Для Laravel-mix 2 с vue-loader v14:
В Laravel-mix, начиная с версии V2.1 (opens new window), можно добавлять пользовательские правила с помощью mix.extend()
. Laravel-mix уже имеет собственные правила для обработки .vue
файлов. Чтобы добавить vue-i18n-loader
, нужно добавить в webpack.mix.js
следующее:
// Код ниже внедрит загрузчик i18n (@kazupon/vue-i18n-loader) в качестве загрузчика .vue файлов.
mix.extend( 'i18n', function( webpackConfig, ...args ) {
webpackConfig.module.rules.forEach( ( module ) => {
// Поиск компонента "vue-loader", который обрабатывает .vue файлы.
if( module.loader !== 'vue-loader' ) {
return;
}
// В этом модуле добавляем vue-i18n-loader для тега i18n.
module.options.loaders.i18n = '@kazupon/vue-i18n-loader';
} );
} );
// Убедитесь что вызвали .i18n() (для загрузки загрузчика) перед .js(..., ...)
mix.i18n()
.js( 'resources/assets/js/App.js', 'public/js/app.js' )
...
# Загрузка YAML
Пользовательские блоки i18n
можно указывать в формате JSON
или YAML
(используя функцию предварительного загрузчика vue-loader
).
Пользовательский блок i18n
в формате YAML
:
<i18n>
en:
hello: "hello world!"
ru:
hello: "привет мир!"
</i18n>
Конфигурация Webpack:
Для vue-loader v15 или более поздних версий:
// Vue CLI 3.0
module.exports = {
chainWebpack: config => {
config.module
.rule('i18n')
.resourceQuery(/blockType=i18n/)
.type('javascript/auto')
.use('i18n')
.loader('@kazupon/vue-i18n-loader')
.end()
.use('yaml')
.loader('yaml-loader')
.end()
}
}
Для vue-loader v14:
module.exports = {
// ...
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
preLoaders: {
i18n: 'yaml-loader'
},
loaders: {
i18n: '@kazupon/vue-i18n-loader'
}
}
}
// ...
]
}
// ...
}
# Несколько пользовательских блоков
Можно использовать сообщения локализации из нескольких пользовательских блоков i18n
.
<i18n src="./common/locales.json"></i18n>
<i18n>
{
"en": {
"hello": "hello world!"
},
"ru": {
"hello": "Привет мир!"
}
}
</i18n>
В примере выше, первый пользовательский блок загружает общие сообщения локализации с помощью атрибута src
, второй пользовательский блок загружает сообщения локализации, которые определены только в этом однофайловом компоненте. Все они будут объединены в качестве сообщений локализации компонента.
Несколько пользовательских блоков полезны, когда использовать их в качестве модулей.
# Локальные стили
При использовании vue-i18n
с локальными стилями (style scoped
) необходимо помнить и использовать глубокий селектор (opens new window) для стилизации элемента внутри строки перевода. Например:
Когда перевод содержит только текст (работает без глубокого селектора)
<i18n>
{
"en": {
"hello": "hello world!"
},
"ru": {
"hello": "Привет мир!"
}
}
</i18n>
<template>
<div class="parent">
<p>Сообщение: {{ $t('hello') }}</p>
</div>
</template>
<!-- Будет работать -->
<style scoped>
.parent p {
color: #42b883;
}
</style>
Когда перевод содержит HTML-элемент (необходимо использовать глубокий селектор)
<i18n>
{
"en": {
"hello": "hello<span>world!</span>"
},
"ru": {
"hello": "привет <span>мир!</span>"
}
}
</i18n>
<template>
<div class="parent">
<p v-html="$t('hello')"></p>
</div>
</template>
<!-- НЕ БУДЕТ РАБОТАТЬ! -->
<style scoped>
.parent p {
color: #42b883;
}
.parent p span {
color: red;
}
</style>
<!-- Будет работать >>> -->
<style scoped>
.parent p {
color: #42b883;
}
.parent p >>> span {
color: red;
}
</style>
<!-- Будет работать /deep/ -->
<style scoped>
.parent p {
color: #42b883;
}
.parent p /deep/ span {
color: red;
}
</style>
<!-- Будет работать ::v-deep -->
<style scoped>
.parent p {
color: #42b883;
}
::v-deep .parent p span {
color: red;
}
</style>
# Пользовательские блоки в функциональном компоненте
Если в шаблоне однофайловых компонентов используется функциональный компонент и определены пользовательские блоки i18n
, то обратите внимание что невозможно локализовать с помощью сообщений локализации.
Например, следующий код не может использовать сообщения локализации из блока i18n
.
<i18n>
{
"en": {
"hello": "hello world"
},
"ru": {
"hello": "привет мир"
}
}
</i18n>
<template functional>
<!-- Сообщение локализации 'hello' из родительского экземпляра -->
<p>{{ parent.$t('hello') }}</p>
</template>