March 26, 2020
Gatsby, Contentful, Netlifyで多言語ブログを作る方法 #2 - 多言語化
静的サイトジェネレーターGatsbyで作ったブログを多言語化する方法を解説。Part 2では言語切替ボタンを設置し、サイトを多言語化していきます。
Updated at November 06, 2020
Part2では、言語切替ボタンを設置し、Gatsbyで作ったサイトを多言語化していきます😀
React-intlをセットアップ
多言語化するために、今回は react-intl というライブラリを使用します。
このライブラリは、多言語化のためのComponentやAPIを提供しているんですが、テキストだけでなく日時や数字、通貨などにも幅広く対応していて非常に便利。
プラグインをインストール
react-intlを使うため、Gatsby用のプラグインgatsby-plugin-intlをインストールします。
npm install --save gatsby-plugin-intl
gatsby-config.jsに追記
追加したプラグインをgatsby-config.jsに追記します。今回はデフォルトを en
にしました。
{
resolve: `gatsby-plugin-intl`,
options: {
// language JSON resource path
path: `${__dirname}/src/intl`,
// supported language
languages: [`en`, `ja`],
// language file path
defaultLanguage: `en`,
// option to redirect to `/en` when connecting `/`
redirect: true,
},
},
これでURLが言語によって切り替わるようになります。
言語によってちゃんと別のURLにすることは、Googleが推奨しているので従った方がいいかと👍
トップページの文言を多言語に
トップページの下記2箇所の文言を、言語によって切り替わるようにしていきます。
各言語用のファイルを作成
まずは、src
フォルダ直下に intl
フォルダを作り、その中に en.json
と ja.json
ファイルを作ります。
{
"hello": "Hi people!",
"posts": "Posts"
}
{
"hello": "こんにちは!",
"posts": "ブログ記事"
}
formatMessageで置き換える
gatsby-plugin-intl
から useIntl
hookを読み込み、
import { useIntl } from "gatsby-plugin-intl"
テキスト部分を書き換えます。
<h1>{intl.formatMessage({ id: "hello" })}</h1>
<h2>{intl.formatMessage({ id: "posts" })}</h2>
最終的なコードはこんな感じ。
import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { useIntl } from "gatsby-plugin-intl"
const IndexPage = ({ data }) => {
const intl = useIntl()
return(
<Layout>
<SEO title="Home" />
<h1>{intl.formatMessage({ id: "hello" })}</h1>
<h2>{intl.formatMessage({ id: "posts" })}</h2>
<ul>
{data.allContentfulBlog.nodes.map(post => {
return (
<li key={post.contentful_id}>{post.title}</li>
)
})}
</ul>
</Layout>
)}
export const query = graphql`
query ContentFulBlog {
allContentfulBlog {
nodes {
contentful_id
node_locale
title
}
}
}
`
export default IndexPage
ここまで終わったら、
- http://localhost:8000/en/
- http://localhost:8000/ja/
それぞれの言語にアクセスすると、テキストが切り替わるのが確認できます😀
言語切替リンクを設置
Language.jsコンポーネントを作成
切替ボタン部分のコンポーネントを作るため、 src/components/Language.js
ファイルを追加します。
import React from "react"
import { IntlContextConsumer, changeLocale } from "gatsby-plugin-intl"
const languageName = {
en: "English",
ja: "日本語",
}
const Language = () => {
return (
<div>
<IntlContextConsumer>
{({ languages, language: currentLocale }) =>
languages.map(language => (
<a
key={language}
onClick={() => changeLocale(language)}
style={{
color: currentLocale === language ? `yellow` : `white`,
margin: 10,
textDecoration: `underline`,
cursor: `pointer`,
}}
>
{languageName[language]}
</a>
))
}
</IntlContextConsumer>
</div>
)
}
export default Language
header.jsへ追加
先ほど作った <Language />
コンポーネントをヘッダーコンポーネントへ追加。
import React from "react"
import { Link } from "gatsby"
import PropTypes from "prop-types"
import Language from "./Language"
const Header = ({ siteTitle }) => (
<header
style={{
background: `rebeccapurple`,
marginBottom: `1.45rem`,
}}
>
<div
style={{
margin: `0 auto`,
maxWidth: 960,
padding: `1.45rem 1.0875rem`,
display:`flex`,
alignItems:`center`,
justifyContent:`space-between`
}}
>
<h1 style={{ margin: 0 }}>
<Link
to="/"
style={{
color: `white`,
textDecoration: `none`,
}}
>
{siteTitle}
</Link>
</h1>
<Language />
</div>
</header>
)
Header.propTypes = {
siteTitle: PropTypes.string,
}
Header.defaultProps = {
siteTitle: ``,
}
export default Header
これで、言語切替ボタンを押すと、メッセージが切り替わるのが確認できます。
記事タイトルを各言語のみに
GraphQLを確認
まずはGraphQL上で、試しに言語でフィルターをかけてみます。
日英どちらの記事も取得してる状態
英語だけ
en
でフィルターをかけます。
日本語だけ
ja
でフィルターをかけます。
OK👍
では、上のフィルターをかけた状態のクエリをindex.jsに追加しましょう。
pageContextを確認
ブラウザのデベロッパーツールから、IndexPage
コンポーネントの PageContext
を見ると、language: "en"
になっているのが確認できますね。日本語ページを見ている時は language: "ja"
になっています。
では、この language
を使って、トップページのクエリにフィルターをかけていきましょう。
トップページを調整
export const query = graphql`
query ContentFulBlog($language: String) {
allContentfulBlog(filter: { node_locale: { eq: $language } }) {
nodes {
contentful_id
node_locale
title
}
}
}
`
これで、日英どちらか一方の記事タイトルだけが表示されるようになりました🙌
Part2はここまで!Part3では、ブログ記事ページを作っていきます。
👋ちなみに、ここまでのコードはGitHubでも確認できます。パートごとにブランチを分けているので、よかったら参考にしてみてください😉