[JavaScript, VueJS] Nuxt.js app от UI-кита до деплоя. Часть 3: Мультиязычность
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет!
Это третья часть цикла статей о создании современного блога на Nuxt.js. Сегодня реализуем мультиязычность в приложении, которое мы написали в первой и второй частях.
Обратите внимание, что код каждой части можно найти в собственной ветке на Github, а в master доступна версия приложения из последней опубликованной статьи.
Зачем нужен мультиязычный сайт?
Преимущества будут различны и зависят от сферы вашего бизнеса, конкретного продукта или услуги. Однако приведем самые значимые, на наш взгляд, плюсы, которые может дать мультиязычный сайт:
- привлечение к продукту более широкой аудитории,
- уменьшение отказов и повышение конверсии,
- установление конкурентного преимущества,
- международная поисковая оптимизация,
- развитие бренда.
Многоязычный веб-сайт может изменить бизнес и помочь продукту стать более конкурентоспособным на мировом рынке.
@nuxtjs/i18n
Для реализации мультиязычности мы будем использовать модуль @nuxtjs/i18n, который предоставляет нам следующие возможности:
- автоматическая генерация маршрутов и создание настраиваемых путей,
- поисковая оптимизация,
- “ленивая” загрузка переводов для отдельных языков,
- автоматическое определение языка браузера пользователя и перенаправление на нужную версию сайта,
- разные доменные имена для разных языков (в данном приложении мы не будем это использовать),
- сохранение текущей локали и переводов с помощью Vuex (в данном приложении мы не будем это использовать).
Для начала установим модуль:
npm i nuxt-i18n
Теперь создадим в корне проекта директорию locales. Эта директория будет содержать файл конфигурации nuxt-i18n, а также файлы с переводами.
Создадим файл конфигурации i18n-nuxt-config.js со следующим содержимым:
export const i18n = {
locales: [
{
code: 'en',
iso: 'en-US',
name: 'EN',
file: 'en.js',
},
{
code: 'ru',
iso: 'ru-RU',
name: 'RU',
file: 'ru.js',
},
],
lazy: true,
langDir: '/locales/',
defaultLocale: 'en',
detectBrowserLanguage: {
alwaysRedirect: true,
fallbackLocale: 'en',
onlyOnRoot: true,
},
}
Здесь мы указываем ряд опций, которые должны быть переданы в явном виде или отличаться от значений по умолчанию. Полный список доступных опций можно найти по ссылке.
Давайте рассмотрим некоторые из них поподробнее:
1. locales — список языков, которые будут реализованы в нашем приложении. Как вы видите, в качестве второго языка был выбран русский (RU), но можно также указать любой другой язык или несколько языков. Обратите внимание, что в каждом элементе массива указано свойство file. Это обязательное свойство, если мы хотим использовать “ленивую” загрузку переводов.
2. lazy — признак, что мы хотим использовать “ленивую” загрузку переводов. В этом случае после открытия пользователем нашего приложения он скачает с сервера только файл с переводом для установленного у него языка, что положительно скажется на скорости загрузки сайта.
3. langDir — эта директория будет использоваться как корневая при поиске файлов с переводами.
4. defaultLocale — локаль, которая будет использоваться по умолчанию. Для этого языка в строке URL не будет использован префикс, а для других — будет.
То есть в нашем случае для английского языка адрес в браузере будет выглядеть следующим образом: https://nuxt-blog.hostman.site, а для русского так: https://nuxt-blog.hostman.site/ru.
5. detectBrowserLanguage — с помощью этих опций мы говорим приложению использовать при первом заходе пользователя в приложение язык, установленный в браузер, чтобы отобразить сайт на нужном языке, а если этот язык в приложении не реализован, то открыть английскую версию.
Отлично! Мы разобрались с опциями и готовы двигаться дальше.
Нам нужно создать файлы en.js и ru.js, которые будут содержать переводы на эти языки. Файлы имеют одинаковую структуру и отличаются только переводом, поэтому достаточно рассмотреть подробно один из них. Например, en.js:
export default {
home: {
title: 'Nuxt blog',
subtitle: 'The best blog you can find on the global internet',
postCount: 'Total posts: ',
},
post: {
linkHome: 'Home',
},
footer: {
feedback: 'Contact us',
copyright: 'All rights reserved',
},
}
Как можно заметить, здесь мы сгруппировали переводы по логическим группам, что позволит в дальнейшем удобно обращаться к нужным свойствам.
В нашем случае используем всего один файл для одного языка, но для больших приложений удобно создавать отдельную директорию для каждого языка и разделять перевод на несколько файлов по определенному принципу. Например, одна страница — один файл, объединяя затем все эти файлы в один объект с помощью стандартного механизма импортов.
Итоговая структура директории locales должна иметь следующий вид:
locales/
-- i18n-nuxt-config.js
-- en.js
-- ru.js
Директория locales на Github.
Всё, что нам остаётся сделать, — добавить информацию об этом модуле в секцию modules в файле nuxt.config.js:
{
modules: [
['nuxt-i18n', i18n],
]
}
Не забудьте добавить в начало файла импорт переменной i18n, которую мы использовали выше, с нашей конфигурации:
import { i18n } from './locales/i18n-nuxt-config'
Использование в компонентах
Мы подготовили переводы для разных языков, и теперь самое время начать использовать их в наших компонентах.
Модуль @nuxtjs/i18n добавляет к экземпляру Vue несколько функций (будут доступны из контекста this). Мы будем использовать следующие:
1. $t(<key>) — с помощью этой функции мы можем получить доступ к любому свойству перевода, указанному в наших файлах en и ru. Например, $t('home.title').
2. localePath(<path>, ...) — возвращает локализованный URL-адрес для запрашиваемой страницы. Первым параметром может быть либо путь, либо имя маршрута, либо объект для более сложных маршрутов. Узнать подробнее об этой функции и посмотреть примеры её использования можно здесь.
Поскольку использование во всех компонентах будет однотипное, то для примера рассмотрим компонент LinkToHome, а остальные можно рассмотреть самостоятельно на Github.
Шаблон компонента LinkToHome после изменений будет выглядеть следующим образом:
<template lang="pug">
section.section
.content
nuxt-link.lth__link(
class="primary"
:to="localePath('/')"
)
img.lth__link-icon(
src="~/assets/icons/home.svg"
alt="icon-home"
)
| {{ $t('post.linkHome') }}
</template>
Мы заменили прямое указание маршрута в nuxt-link на вызов функции localePath, передав в качестве параметра нужный нам маршрут. Точно так же прямое указание названия ссылки мы заменили на вызов функции $t, передав параметром нужное нам свойство.
Компонент LinkToHome на Github.
Также изменения были выполнены в компонентах DbFooter, PostCard, PostList, HomePage.
Посты на разных языках
Вы, наверное, обратили внимание, что в файлах en.js и ru.js не было никакой информации о постах, которые мы храним в отдельных файлах в директории content/posts. Настало время поговорить об этом!
До этого в файле posts.ts мы хранили и экспортировали информацию о наших постах следующим образом:
export default [
{
id: 1,
title: 'Post 1',
desc:
'A short description of the post to keep the user interested.' +
' Description can be of different lengths, blocks are aligned' +
' to the height of the block with the longest description',
file: 'content/posts/1.md',
img: 'assets/images/1.svg',
},
...
] as Post[]
Но в таком варианте мы не можем указывать разные файлы и метаинформацию для одного поста на разных языках. Исправим это и приведём наш файл к следующему виду:
const en = [
{
id: 1,
title: 'Post 1',
desc:
'A short description of the post to keep the user interested.' +
' Description can be of different lengths, blocks are aligned' +
' to the height of the block with the longest description',
file: 'content/posts/1.md',
img: 'assets/images/1.svg',
},
...
] as Post[]
const ru = [
{
id: 1,
title: 'Пост 1',
desc:
'Краткое описание поста, чтобы заинтересовать пользователя.' +
' Описание может быть разной длины, блоки выровнены' +
' по высоте блока с самым длинным описанием',
file: 'content/posts/1.md',
img: 'assets/images/1.svg',
},
...
] as Post[]
export default { en, ru }
Теперь у нас есть две переменных en и ru, каждая из которых хранит собственный список постов для своего языка.
Файл на Github.
В данном случае для обоих языков будут использованы одни и те же файлы, так как это демонстрационное приложение, и здесь мы хотим показать сам подход к реализации. В реальном приложении файлы, конечно, должны быть разные.
Давайте теперь немного изменим реализацию компонентов, где используется эта информация.
Компонент PostList
В компоненте PostList требуется заменить свойство posts объекта data на вычисляемое свойство с таким же названием, которое будет выглядеть следующим образом:
computed: {
posts(): Post[] {
const { locale } = (this as any).$i18n
return posts[locale as 'en' | 'ru']
},
},
Компонент на Github.
Отдельная страница поста post/_id
На отдельной странице поста реализовано вычисляемое свойство currentPost, давайте немного изменим его, чтобы оно выглядело следующим образом:
computed: {
currentPost(): Post | undefined {
const { locale } = (this as any).$i18n
return posts[locale as 'en' | 'ru'].find(
(post: Post) => post.id === this.currentId
)
},
},
Файл на Github.
Теперь наши посты на всех страницах будут корректно загружаться в зависимости от выбранного языка.
В данном случае мы не учитываем сценарий, когда пост с конкретным id существует только на одном языке, так как наше приложение демонстрационное и мы можем этим пренебречь. Не забудьте учесть этот сценарий, если будете реализовывать подобную логику в реальном приложении.
Переключатель языка
На этом этапе реализуем переключатель, который позволит выбирать нужный нам язык на сайте.
В прошлой части мы создали компонент AppOptions, который служит обёрткой для переключателей темы и языка.
Давайте создадим компонент SwitcherLang в директории components/AppOptions и приведём шаблон компонента AppOptions к следующему виду:
<template lang="pug">
section.section
.content
.app-options
switcher-lang
switcher-color-mode
</template>
Взглянем на шаблон компонента SwitcherLang:
<template lang="pug">
select(
v-model="selected"
class="body3 medium"
@change="changeLocale"
)
option(
v-for="locale in $i18n.locales"
:key="locale.code"
:value="locale.code"
) {{ locale.name }}
</template>
Как вы видите, мы просто реализуем стандартный select, в котором показываем доступные в приложении языки. При изменении значения в этом select мы будем вызывать метод changeLocale.
Далее посмотрим на секцию script:
<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
name: 'SwitcherLang',
data: () => ({
selected: '' as 'en' | 'ru',
}),
created() {
this.selected = (this as any).$i18n.locale
},
methods: {
changeLocale() {
const switchPath = (this as any).switchLocalePath(this.selected)
this.$router.push(switchPath)
},
},
})
</script>
В методе changeLocale мы используем ещё одну функцию, которую предоставляет нам модуль @nuxt/i18n, — switchLocalePath. Эта функция возвращает ссылку на текущую страницу на выбранном языке.
Также обратите внимание, что мы храним значение выбранного языка в локальной переменной selected и при создании экземпляра Vue в хуке created синхронизируем её значение с глобальным значением, которое хранится в $i18n.
Компонент на Github.
Заключение
Что у нас получилось:
Пишите в комментариях, если будут вопросы или непонятные моменты. До встречи в следующей части!
===========
Источник:
habr.com
===========
Похожие новости:
- [JavaScript, Angular, ReactJS, VueJS] Экосистема JavaScript: тренды в 2021 году. Всё ли так однозначно?
- [Работа с видео, Социальные сети и сообщества, IT-компании] В Яндексе заработает единая платформа для видеоблогеров
- [Ненормальное программирование, JavaScript, TypeScript] Фрактальная шизофрения. What`s up?
- [Разработка веб-сайтов, Open source, JavaScript, Node.JS] Создатель Node.js анонсирует замену — Deno (перевод)
- [Разработка веб-сайтов, JavaScript] Опыт разработки виджетов для сторонних сайтов
- [Информационная безопасность, IT-компании] Как я получил награду Facebook по баунти-программе дважды (перевод)
- [JavaScript, Git, Управление разработкой, Управление продуктом, DevOps] Введение в непрерывную поставку (CD) при помощи GitLab (перевод)
- [JavaScript, Google Chrome, HTML, Расширения для браузеров] Расширение для Google Chrome: управляем скиллами друзей в LinkedIn
- [JavaScript, Разработка под Arduino, Разработка на Raspberry Pi, DIY или Сделай сам] Умная квартира на JavaScript. От светодиода до распознавания лица в камере домофона
- [JavaScript, Серверная оптимизация, Node.JS] Профилирование Node.js. Доклад Яндекса
Теги для поиска: #_javascript, #_vuejs, #_nuxt.js, #_timeweb, #_multijazychnost (мультиязычность), #_blog (блог), #_blog_kompanii_timeweb (
Блог компании Timeweb
), #_javascript, #_vuejs
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:42
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет! Это третья часть цикла статей о создании современного блога на Nuxt.js. Сегодня реализуем мультиязычность в приложении, которое мы написали в первой и второй частях. Обратите внимание, что код каждой части можно найти в собственной ветке на Github, а в master доступна версия приложения из последней опубликованной статьи.
Зачем нужен мультиязычный сайт? Преимущества будут различны и зависят от сферы вашего бизнеса, конкретного продукта или услуги. Однако приведем самые значимые, на наш взгляд, плюсы, которые может дать мультиязычный сайт:
Многоязычный веб-сайт может изменить бизнес и помочь продукту стать более конкурентоспособным на мировом рынке. @nuxtjs/i18n Для реализации мультиязычности мы будем использовать модуль @nuxtjs/i18n, который предоставляет нам следующие возможности:
Для начала установим модуль: npm i nuxt-i18n
Теперь создадим в корне проекта директорию locales. Эта директория будет содержать файл конфигурации nuxt-i18n, а также файлы с переводами. Создадим файл конфигурации i18n-nuxt-config.js со следующим содержимым: export const i18n = {
locales: [ { code: 'en', iso: 'en-US', name: 'EN', file: 'en.js', }, { code: 'ru', iso: 'ru-RU', name: 'RU', file: 'ru.js', }, ], lazy: true, langDir: '/locales/', defaultLocale: 'en', detectBrowserLanguage: { alwaysRedirect: true, fallbackLocale: 'en', onlyOnRoot: true, }, } Здесь мы указываем ряд опций, которые должны быть переданы в явном виде или отличаться от значений по умолчанию. Полный список доступных опций можно найти по ссылке. Давайте рассмотрим некоторые из них поподробнее: 1. locales — список языков, которые будут реализованы в нашем приложении. Как вы видите, в качестве второго языка был выбран русский (RU), но можно также указать любой другой язык или несколько языков. Обратите внимание, что в каждом элементе массива указано свойство file. Это обязательное свойство, если мы хотим использовать “ленивую” загрузку переводов. 2. lazy — признак, что мы хотим использовать “ленивую” загрузку переводов. В этом случае после открытия пользователем нашего приложения он скачает с сервера только файл с переводом для установленного у него языка, что положительно скажется на скорости загрузки сайта. 3. langDir — эта директория будет использоваться как корневая при поиске файлов с переводами. 4. defaultLocale — локаль, которая будет использоваться по умолчанию. Для этого языка в строке URL не будет использован префикс, а для других — будет. То есть в нашем случае для английского языка адрес в браузере будет выглядеть следующим образом: https://nuxt-blog.hostman.site, а для русского так: https://nuxt-blog.hostman.site/ru. 5. detectBrowserLanguage — с помощью этих опций мы говорим приложению использовать при первом заходе пользователя в приложение язык, установленный в браузер, чтобы отобразить сайт на нужном языке, а если этот язык в приложении не реализован, то открыть английскую версию. Отлично! Мы разобрались с опциями и готовы двигаться дальше. Нам нужно создать файлы en.js и ru.js, которые будут содержать переводы на эти языки. Файлы имеют одинаковую структуру и отличаются только переводом, поэтому достаточно рассмотреть подробно один из них. Например, en.js: export default {
home: { title: 'Nuxt blog', subtitle: 'The best blog you can find on the global internet', postCount: 'Total posts: ', }, post: { linkHome: 'Home', }, footer: { feedback: 'Contact us', copyright: 'All rights reserved', }, } Как можно заметить, здесь мы сгруппировали переводы по логическим группам, что позволит в дальнейшем удобно обращаться к нужным свойствам. В нашем случае используем всего один файл для одного языка, но для больших приложений удобно создавать отдельную директорию для каждого языка и разделять перевод на несколько файлов по определенному принципу. Например, одна страница — один файл, объединяя затем все эти файлы в один объект с помощью стандартного механизма импортов. Итоговая структура директории locales должна иметь следующий вид: locales/
-- i18n-nuxt-config.js -- en.js -- ru.js Директория locales на Github. Всё, что нам остаётся сделать, — добавить информацию об этом модуле в секцию modules в файле nuxt.config.js: {
modules: [ ['nuxt-i18n', i18n], ] } Не забудьте добавить в начало файла импорт переменной i18n, которую мы использовали выше, с нашей конфигурации: import { i18n } from './locales/i18n-nuxt-config'
Использование в компонентах Мы подготовили переводы для разных языков, и теперь самое время начать использовать их в наших компонентах. Модуль @nuxtjs/i18n добавляет к экземпляру Vue несколько функций (будут доступны из контекста this). Мы будем использовать следующие: 1. $t(<key>) — с помощью этой функции мы можем получить доступ к любому свойству перевода, указанному в наших файлах en и ru. Например, $t('home.title'). 2. localePath(<path>, ...) — возвращает локализованный URL-адрес для запрашиваемой страницы. Первым параметром может быть либо путь, либо имя маршрута, либо объект для более сложных маршрутов. Узнать подробнее об этой функции и посмотреть примеры её использования можно здесь. Поскольку использование во всех компонентах будет однотипное, то для примера рассмотрим компонент LinkToHome, а остальные можно рассмотреть самостоятельно на Github. Шаблон компонента LinkToHome после изменений будет выглядеть следующим образом: <template lang="pug">
section.section .content nuxt-link.lth__link( class="primary" :to="localePath('/')" ) img.lth__link-icon( src="~/assets/icons/home.svg" alt="icon-home" ) | {{ $t('post.linkHome') }} </template> Мы заменили прямое указание маршрута в nuxt-link на вызов функции localePath, передав в качестве параметра нужный нам маршрут. Точно так же прямое указание названия ссылки мы заменили на вызов функции $t, передав параметром нужное нам свойство. Компонент LinkToHome на Github. Также изменения были выполнены в компонентах DbFooter, PostCard, PostList, HomePage. Посты на разных языках Вы, наверное, обратили внимание, что в файлах en.js и ru.js не было никакой информации о постах, которые мы храним в отдельных файлах в директории content/posts. Настало время поговорить об этом! До этого в файле posts.ts мы хранили и экспортировали информацию о наших постах следующим образом: export default [
{ id: 1, title: 'Post 1', desc: 'A short description of the post to keep the user interested.' + ' Description can be of different lengths, blocks are aligned' + ' to the height of the block with the longest description', file: 'content/posts/1.md', img: 'assets/images/1.svg', }, ... ] as Post[] Но в таком варианте мы не можем указывать разные файлы и метаинформацию для одного поста на разных языках. Исправим это и приведём наш файл к следующему виду: const en = [
{ id: 1, title: 'Post 1', desc: 'A short description of the post to keep the user interested.' + ' Description can be of different lengths, blocks are aligned' + ' to the height of the block with the longest description', file: 'content/posts/1.md', img: 'assets/images/1.svg', }, ... ] as Post[] const ru = [ { id: 1, title: 'Пост 1', desc: 'Краткое описание поста, чтобы заинтересовать пользователя.' + ' Описание может быть разной длины, блоки выровнены' + ' по высоте блока с самым длинным описанием', file: 'content/posts/1.md', img: 'assets/images/1.svg', }, ... ] as Post[] export default { en, ru } Теперь у нас есть две переменных en и ru, каждая из которых хранит собственный список постов для своего языка. Файл на Github. В данном случае для обоих языков будут использованы одни и те же файлы, так как это демонстрационное приложение, и здесь мы хотим показать сам подход к реализации. В реальном приложении файлы, конечно, должны быть разные. Давайте теперь немного изменим реализацию компонентов, где используется эта информация. Компонент PostList В компоненте PostList требуется заменить свойство posts объекта data на вычисляемое свойство с таким же названием, которое будет выглядеть следующим образом: computed: {
posts(): Post[] { const { locale } = (this as any).$i18n return posts[locale as 'en' | 'ru'] }, }, Компонент на Github. Отдельная страница поста post/_id На отдельной странице поста реализовано вычисляемое свойство currentPost, давайте немного изменим его, чтобы оно выглядело следующим образом: computed: {
currentPost(): Post | undefined { const { locale } = (this as any).$i18n return posts[locale as 'en' | 'ru'].find( (post: Post) => post.id === this.currentId ) }, }, Файл на Github. Теперь наши посты на всех страницах будут корректно загружаться в зависимости от выбранного языка. В данном случае мы не учитываем сценарий, когда пост с конкретным id существует только на одном языке, так как наше приложение демонстрационное и мы можем этим пренебречь. Не забудьте учесть этот сценарий, если будете реализовывать подобную логику в реальном приложении. Переключатель языка На этом этапе реализуем переключатель, который позволит выбирать нужный нам язык на сайте. В прошлой части мы создали компонент AppOptions, который служит обёрткой для переключателей темы и языка. Давайте создадим компонент SwitcherLang в директории components/AppOptions и приведём шаблон компонента AppOptions к следующему виду: <template lang="pug">
section.section .content .app-options switcher-lang switcher-color-mode </template> Взглянем на шаблон компонента SwitcherLang: <template lang="pug">
select( v-model="selected" class="body3 medium" @change="changeLocale" ) option( v-for="locale in $i18n.locales" :key="locale.code" :value="locale.code" ) {{ locale.name }} </template> Как вы видите, мы просто реализуем стандартный select, в котором показываем доступные в приложении языки. При изменении значения в этом select мы будем вызывать метод changeLocale. Далее посмотрим на секцию script: <script lang="ts">
import Vue from 'vue' export default Vue.extend({ name: 'SwitcherLang', data: () => ({ selected: '' as 'en' | 'ru', }), created() { this.selected = (this as any).$i18n.locale }, methods: { changeLocale() { const switchPath = (this as any).switchLocalePath(this.selected) this.$router.push(switchPath) }, }, }) </script> В методе changeLocale мы используем ещё одну функцию, которую предоставляет нам модуль @nuxt/i18n, — switchLocalePath. Эта функция возвращает ссылку на текущую страницу на выбранном языке. Также обратите внимание, что мы храним значение выбранного языка в локальной переменной selected и при создании экземпляра Vue в хуке created синхронизируем её значение с глобальным значением, которое хранится в $i18n. Компонент на Github. Заключение Что у нас получилось: Пишите в комментариях, если будут вопросы или непонятные моменты. До встречи в следующей части! =========== Источник: habr.com =========== Похожие новости:
Блог компании Timeweb ), #_javascript, #_vuejs |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:42
Часовой пояс: UTC + 5