使用Gatsby和Cosmic JS创建多语言网站

A friend recently asked me to build a website which has a Japanese and an English version. I never wrote an internationalized website but I have strong opinions about how localization should work. So here is one way to approach internationalization in Gatsby using Cosmic JS, a headless CMS.

最近有一个朋友要我建立一个日文和英文版本的网站。 我从未写过国际化的网站,但对本地化的工作方式有强烈的意见。 因此,这是使用Cosmic JS(无头CMS)在盖茨进行国际化的一种方法。

一点背景 (A Bit of Context)

There are many ways to approach localization and as always there is no silver bullet. Each approach solves the problem in different ways. So here is my context:

有许多方法可以实现本地化,而且一如既往没有灵丹妙药。 每种方法都以不同的方式解决问题。 所以这是我的上下文:

  • I want to build a site with as little maintenance cost as possible.

    我想建立一个维护成本尽可能低的站点。
  • The content writer doesn’t have any programing experience

    内容作者没有任何编程经验
  • The site’s maintenance costs should be as low as possible.

    该站点的维护成本应尽可能低。
  • The site should not force the user on one version of the site.

    该网站不应强迫用户使用该网站的一个版本。

This last point is so important to me. When you are in a foreign country, some websites force you to use the local version of their site. When [array of multinational companies] forces me to the [long array of languages I don't understand] version of the website it drives me mad. I have the same issue with automatic translations of a page. If I want an automatic translation of my website, I can use the fantastic Google translate Chrome extension.

最后一点对我很重要。 当您在国外时,某些网站会强迫您使用其网站的本地版本。 当[array of multinational companies]迫使我进入网站的[long array of languages I don't understand]版本时,我发疯了。 我对页面的自动翻译有相同的问题。 如果我想自动翻译网站,可以使用出色的Google翻译Chrome扩展程序

This website is for both Japanese and English users. So all the pages of the site should have an English version and a Japanese version. If the user wants to change the current version of the website she can click a language menu in the navigation bar.

该网站面向日语和英语用户。 因此,该网站的所有页面均应具有英文版和日文版。 如果用户想要更改网站的当前版本,则可以单击导航栏中的语言菜单。

我的方法 (My approach)

Gatsby and React offer many tools to approach localization (l10n) and internationalization (i18n).

Gatsby和React提供了许多解决本地化(l10n)和国际化(i18n)的工具

I first used gatsby-plugin-i18n to easily generate routes.

我首先使用gatsby-plugin-i18n轻松生成路由。

For example, /page/team.ja.js will generate the following URL: /ja/team (ja is the language code for Japan).

例如,/ /page/team.ja.js /ja/team /page/team.ja.js将生成以下URL: /ja/team ( ja是日本的语言代码)。

This is a really nice plugin but the problem is that it isn’t programmatic. I have to write a new file for each language. In each file, I have to make a specific GraphQL query to fetch the data. So for example, if I introduce a new language to my CMS I have to create all the routes again with the new language extension.

这是一个非常不错的插件,但是问题在于它不是编程的。 我必须为每种语言编写一个新文件。 在每个文件中,我必须进行特定的GraphQL查询以获取数据。 因此,例如,如果我在CMS中引入一种新语言,则必须使用新语言扩展名再次创建所有路由。

So instead, I decided to build l10n without any plugin. All the code for this project is available at https://github.com/alligatorio/kodou.

因此,我决定构建没有任何插件的l10n。 该项目的所有代码都可以在https://github.com/alligatorio/kodou上找到

In this context, the content writer is fully responsible for localization. When she writes the Japanese version of the website, she should make sure that the date formats are correct. This is why we are not using react-intl which relies on the Internationalization API and will be the topic of a future post.

在这种情况下,内容编写者完全负责本地化。 在撰写日语版网站时,应确保日期格式正确。 这就是为什么我们不使用依赖于国际化API的react-intl原因,它将成为以后文章的主题。

设置Cosmic JS (Setting up Cosmic JS)

Cosmic JS, a great headless CMS option, allows you do activate localization when you create a new object type.

Cosmic JS,一个很棒的无头CMS选项,允许您在创建新的对象类型时激活本地化。

Don’t forget to select a priority locale otherwise the new object won’t save.

不要忘记选择优先级语言环境,否则新对象将不会保存。

In our new site we have a team page so we create a Team Members object. When we create a new Team Member we now can choose its’ language.

在我们的新站点中,我们有一个团队页面,因此我们创建了一个“团队成员”对象。 现在,当我们创建新的团队成员时,我们可以选择其语言。

Now to access that data from Gatsby we need to add the gatsby-source-cosmicjs source plugin:

现在,要从Gatsby访问数据,我们需要添加gatsby-source-cosmicjs源插件:

$ yarn add gatsby-source-cosmicjs

Then we need to configure gatsby-config.js to use gatsby-source-cosmicjs by adding the following code in plugins.

然后,我们需要通过在plugins添加以下代码来配置gatsby-config.js以使用gatsby-source-cosmicjs

Module: gatsby-config.js
模组:gatsby-config.js
{
  resolve: "gatsby-source-cosmicjs",
  options: {
    bucketSlug: process.env.COSMIC_BUCKET,
    // We add the 'team-members' object type to be able to fetch it later
    objectTypes: ["team-members"],
    // If you have enabled read_key to fetch data (optional).
    apiAccess: {
      read_key: process.env.COSMIC_ENV_KEY,
    }
  }
}

In the rest of our code we can access the team member data from Cosmic JS by running:

在我们的其余代码中,我们可以通过运行以下命令从Cosmic JS访问团队成员数据:

graphql(`
  {
    allCosmicjsTeamMembers  {
      edges {
      # Here we have the structure of out `team-members` object
        node {
          title
          locale
          content
          metadata {
            profile_picture {
              imgix_url
            }
          }
        }
      }
    }
  }
`)

Now the localization magic happens.

现在,本地化魔术发生了。

生成本地化页面 (Generating Localized Pages)

I wanted my friend to be able to do any changes he wanted by himself. So I completely dropped the /pages directory in favor of the /templates directory. Gatsby templates allow us to have reusable content and programmatically create pages; which is exactly what we need to do!

我希望我的朋友能够自己进行任何更改。 因此,我完全放弃了/pages目录,转而使用/templates目录。 Gatsby模板允许我们拥有可重用的内容并以编程方式创建页面; 这正是我们需要做的!

Before we look at our template file let’s see how we can fetch data from Cosmic JS to create new pages.

在查看模板文件之前,让我们看一下如何从Cosmic JS中获取数据以创建新页面。

Module: gatsby-node.js
模组:gatsby-node.js
// langs contains the languages of our blog and default langKey is the default language of the site
// To be fully programmatic we could calculate langs
// here langs = ['en', 'ja'] and 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)
  }

  // Creates a profiles object with out site's languages 
  const profiles = createLanguagesObject(langs)
  // profiles = {
  // 'en': [],
  // 'ja': []  
  // }

  // converting the raw cosmic data into a more useable data structure
  result.data.allCosmicjsTeamMembers.edges.forEach(({ node }) => {
    profiles[node.locale].push(node)
  })
  // profiles = {
  // 'en': [...all English profiles],
  // 'ja': [...all Japanese profiles]  
  // }

  // we create a new page for each language
  langs.forEach(lang =>{
     createPage({
      // the localizeUrl function creates a url which takes into consideration what the default language is
      path: localizeUrl(lang, defaultLangKey, '/team'),
      component: path.resolve(`src/templates/team.js`),
      context: {
        profiles: profiles[lang]
      }
    })
  })
}

This code will create two new pages with the paths /ja/team and /team (There is no /en since we set English as the default language).

此代码将创建两个新页面,其路径分别为/ja/team/team (因为我们将英语设置为默认语言,所以没有/en )。

As you can see the createPage takes as an argument an object with 3 fields path, component and context. Path is simply the path we want our new page to have. component is the template we want to use. context is the data we want to pass to our template. Here we pass the profiles written in our desired language.

如您所见, createPage将具有3个字段pathcomponentcontext的对象作为参数。 路径只是我们希望新页面拥有的路径。 component是我们要使用的模板。 context是我们要传递给模板的数据。 在这里,我们传递以所需语言编写的配置文件。

模板化 (Templating)

Let’s take a look at our team template.

让我们看一下我们的团队模板。

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

const TeamPage = (props) => {
  // We will see about pageContext in the next section
  const {profiles} = props.pageContext
  return (
  <Layout location={props.location}>
    <SEO title="Team" />
    <h1>Team</h1>
    // Iterating trough the array of profiles
    {profiles.map((profile,i)=>(
      <div key={i} className="columns">
        <div className="column">
          // Here are some nice profile pictures of our team members
          <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>
          // Here is some html content we get from Cosmic
          <div dangerouslySetInnerHTML={{ __html: profile.content }}/>
        </div>
      </div>
      )
    )}
  </Layout>
  )
}

export default TeamPage

To sum up, the code above takes a profiles props which is an array of profiles we get from Cosmic JS. Each profile has a profile picture object, a title and a content field. The content is actually a string of HTML so we have to set it using the dangerouslySetInnerHTML prop.

综上所述,上面的代码采用了一个profiles props,这是我们从Cosmic JS获得的profiles数组。 每个配置文件都有一个配置文件图片对象,一个title和一个content字段。 content实际上是一串HTML,因此我们必须使用dangerouslySetInnerHTML SetInnerHTML道具进行设置。

For this template to work, it’s important to prepare your CSS files in advance to get consistent results. My friend won’t be able to add class names or ids in Cosmic’s WYSIWYG.

为了使该模板正常工作,预先准备CSS文件以获得一致的结果很重要。 我的朋友无法在Cosmic的WYSIWYG中添加类名或ID。

There is much more to say and do:

还有更多要做的事情:

  • Creating a navbar and location aware Layout

    创建导航栏和位置感知布局
  • How to use the internationalization API

    如何使用国际化API
  • How to softly redirect users to their version of the site

    如何将用户轻柔地重定向到他们的网站版本

You can explore the Github repo to find out how I address these issues and see the results on kodou.me. Or use Alligator.io to see if we uploaded some new content on that topic. But I think it’s already a lot to process in one post. Above I hope this will help a little or a lot to build your own internationalized site and stay tuned for more to come! 😉

您可以浏览Github仓库以了解我如何解决这些问题,并在kodou.me上查看结果。 或使用Alligator.io查看我们是否上传了有关该主题的一些新内容。 但是我认为在一篇文章中要处理的事情已经很多了。 在上面,我希望这对建立您自己的国际化站点有所帮助或有所帮助,并请继续关注更多! 😉

翻译自: https://www.digitalocean.com/community/tutorials/gatsbyjs-create-a-multilanguage-site

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值