Многоязычный сайт на Gatsby и Cosmic JS

В этом мануале мы рассмотрим один из подходов к написанию многоязычных, локализированных сайтов на Gatsby и Cosmic JS.

Основные понятия

Сегодня существует множество подходов к локализации, и, конечно, среди них нет единственно верного решения. Каждый подход решает данную проблему по-своему.

Итак, в этом руководстве мы будем работать с таким контекстом:

  • Нам нужно создать сайт с минимальными затратами на обслуживание.
  • Автор контента не имеет опыта программирования.
  • Затраты на обслуживание сайта должны быть как можно меньше.
  • Сайт не должен заставлять пользователя переходить на ту или иную версию.

Особенное внимание мы обратим на последний пункт. Когда вы находитесь в чужой стране, некоторые веб-сайты заставляют вас использовать местную версию. Получается, множество глобальных компаний заставляют миллионы людей использовать языки, которые они, вероятно, даже не понимают. То же самое касается и автоматического перевода страниц.

Допустим, веб-сайт, над которым мы будем работать, предназначен пользователей, которые владеют японским или английским. Поэтому все страницы сайта должны иметь английскую и японскую версии. Если пользователь хочет изменить текущую версию веб-сайта, он может щелкнуть языковое меню на панели навигации.

Подход к локализации

Gatsby и React предлагают множество инструментов для локализации (l10n) и интернационализации (i18n).

Плагин gatsby-plugin-i18n позволяет легко создавать маршруты, потому его часто используют в работе над многоязычными сайтами.

Например, /page/team.ja.js сгенерирует следующий URL-адрес: /ja/team  (где ja – это языковой код японского).

Это действительно хороший плагин, но есть одна проблема – он не программный. То есть для каждого языка разработчику нужно написать отдельный файл, в котором он выполнит определенный запрос GraphQL для получения данных. Следовательно, если вы вводите в свою CMS новый язык, вам придется заново прописывать все маршруты с новым расширением языка.

Вместо этого можно собрать локализацию без каких-либо плагинов.

Примечание: Пример кода подобного проекта можно найти здесь.

В этом контексте полную ответственность за локализацию несет автор контента. Когда он пишет японскую версию веб-сайта, он должен убедиться, что данные хранятся в правильном формате. Вот почему можно не использовать react-intl, который полагается на Internationalization API (подробнее об это мы поговорим в будущих публикациях).

Настройка Cosmic JS

Cosmic JS, отличный вариант консольной CMS, позволяет активировать локализацию при создании нового типа объекта. Это делается через меню Localization. Обязательно выберите приоритетный языковой стандарт, иначе новый объект не сохранится.

Предположим, на нашем сайте есть страница для команды, поэтому мы создаем объект Team Members. При создании нового объекта можно выбрать его язык. В поле Object Type указываем Team Members, а в выпадающем меню Locale выбираем нужный язык (в нашем случае это японский).

Теперь, чтобы получить доступ к этим данным из Gatsby, нужно добавить плагин gatsby-source-cosmicjs:

$ yarn add gatsby-source-cosmicjs

Затем нужно настроить файл gatsby-config.js для поддержки плагина gatsby-source-cosmicjs, поместив в раздел plugins следующий код.

{
  resolve: "gatsby-source-cosmicjs",
  options: {
    bucketSlug: process.env.COSMIC_BUCKET,
    // добавляем тип объекта team-members, чтобы иметь возможность извлечь его позже
    objectTypes: ["team-members"],
    // если вы включили read_key для получения данных (это опционально)
    apiAccess: {
      read_key: process.env.COSMIC_ENV_KEY,
    }
  }
}

В остальной части кода мы можем получить доступ к данным членов команды через Cosmic JS:

graphql(`
  {
    allCosmicjsTeamMembers  {
      edges {
      # здесь идет структура объекта `team-members`
        node {
          title
          locale
          content
          metadata {
            profile_picture {
              imgix_url
            }
          }
        }
      }
    }
  }
`)

Создание локализованных страниц

Ранее мы говорили, что автор контента для сайта не имеет опыта программирования. Допустим, нам нужно, чтобы он мог сам вносить любые изменения, которые захочет. Что для этого нужно?

Рекомендуем полностью отказаться от каталога /pages в пользу каталога /templates. Шаблоны Gatsby позволяют сайту поддерживать повторно используемый контент и создавать страницы программным путем, что идеально подходит для нашего случая.

Прежде чем открыть файл шаблона, давайте посмотрим, как можно получать данные для создания новых страниц из Cosmic JS. Откройте gatsby-node.js:

// langs содержит языки сайта, а defaultLangKey является языком сайта по умолчанию
// langs можно было бы вычислить программным образом
// здесь langs = ['en', 'ja'] и defaultLangKey = 'en'
const { langs, defaultLangKey } = require('../config/languages')
const path = require(`path`)
const { localizeUrl, createLanguagesObject } = require('../utils/localization')

exports.createPages = async ({ actions, graphql }) => {
  const { createPage } = actions

  const result = await graphql(`
    {
      allCosmicjsTeamMembers  {
        edges {
          node {
            title
            locale
            content
            metadata {
              profile_picture {
                imgix_url
              }
            }
          }
        }
      }
    }
  `)

  if (result.errors) {
    console.error(result.errors)
  }

  // создает объект profiles без языков сайтa
  const profiles = createLanguagesObject(langs)
  // profiles = {
  // 'en': [],
  // 'ja': []
  // }

  // преобразование необработанных данных cosmic в более удобную структуру
  result.data.allCosmicjsTeamMembers.edges.forEach(({ node }) => {
    profiles[node.locale].push(node)
  })
  // profiles = {
  // 'en': [...all English profiles],
  // 'ja': [...all Japanese profiles]
  // }

  // создаем новую страницу для каждого языка
  langs.forEach(lang =>{
     createPage({
      // функция localizeUrl создает URL-адрес, который учитывает язык по умолчанию
      path: localizeUrl(lang, defaultLangKey, '/team'),
      component: path.resolve(`src/templates/team.js`),
      context: {
        profiles: profiles[lang]
      }
    })
  })
}

Этот код создаст две новые страницы с путями /ja/team и /team (где секция /en отсутствует, поскольку английский установлен как язык по умолчанию).

Как видите, createPage принимает в качестве аргумента объект с 3 полями: path, component и context. Здесь path – это просто путь, который должна иметь новая страница. component – это шаблон, который мы хотим использовать, а context – это данные, которые нужно передать шаблону. Здесь мы передаем профили, написанные на необходимом языке.

Шаблоны Gatsby

Давайте взглянем на шаблон нашей команды.

import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"

const TeamPage = (props) => {
  // далее идет раздел pageContext
  const {profiles} = props.pageContext
  return (
  <Layout location={props.location}>
    <SEO title="Team" />
    <h1>Team</h1>
    // итерация через массив профилей
    {profiles.map((profile,i)=>(
      <div key={i} className="columns">
        <div className="column">
          // Здесь лежат фотографии членов команды
          <div className="square-image" style={{backgroundImage: `url("${profile.metadata.profile_picture.imgix_url}")`}}/>
        </div>
        <div className="column is-two-thirds">
          <div className="team-member-title">{profile.title}</div>
          // далее идет html-контент от Cosmic
          <div dangerouslySetInnerHTML={{ __html: profile.content }}/>
        </div>
      </div>
      )
    )}
  </Layout>
  )
}

export default TeamPage

Подведем итог. Приведенный выше код принимает свойства profiles – массив профилей, которые мы получаем от Cosmic JS. Каждый профиль имеет объект изображения, а также поля title и content. На самом деле поле content представляет собой строку HTML, поэтому мы должны установить его с помощью свойства dangerouslySetInnerHTML.

Важно заранее подготовить файлы CSS, чтобы этот шаблон работал и выдавал стабильные результаты.

Заключение

Можно еще много чего сказать и сделать, например:

  • Создать панель навигации и макет, учитывающий местоположение пользователя.
  • Обсудить работу с internationalization API.
  • Научиться мягко перенаправлять пользователей на их версию сайта.

Рекомендуем изучить этот репозиторий Github, если вы хотите узнать, как можно решить эти проблемы.

Читайте также: Многоязычное меню сайта в Gatsby.js

Tags: ,

Добавить комментарий