Gatsby.jsの国際化されたナビゲーションメニュー
以前の投稿Gatsbyで多言語のウェブサイトを作成し、kodou.meを作成しました。 鼓童には日本語版と英語版があります。 投稿は少し長かったので、私が使用したユーティリティのいくつかと、サイトのナビゲーションメニューを作成する方法については話しませんでした。
クイックサマリー
前回の投稿では、日本語と英語でサイトを構築しました。 サイトのデフォルト言語は英語です。 これは、2つのURLタイプがあることを意味します。
- 日本語ページ:
kodou.me/ja/team
- 英語のページ
kodou.me/team
さまざまなページバージョンがCosmicJSで記述されています。 Gatsbyに/config/languages
で使用する言語を認識させます。 gatsby-node.js
では、CosmicJSからのデータを入力したテンプレートを使用してページを作成します。
これは、CosmicJSによって返されるteam-members
配列の簡略版です。
teamMembers = [ { title: 'CEO', fullName: 'Jack Misteli', content: 'The CEO of the Company', locale: 'en' }, { title: 'CEO', fullName: 'ジャック・ミステリ', content: '会社のCEO', locale: 'ja' } ]
teamMembers
を受け取った後、2つのオブジェクトjaTeamMembers
とenTeamMembers
を作成します。 templates/team
にjaTeamMembers
を入力して/ja/team
を作成し、enTeamMembers
を入力して/team
を作成します。
サイトを言語対応にする
優れたWeb市民であり、私たちが作成するサイトにアクセスできるようにすることが重要です。 したがって、最初に行う必要があるのは、サイトのメタデータに言語を追加することです。 また、よりターゲットを絞った検索結果を得るのに役立つ場合があります。
モジュール:gatsby-config.js
module.export = { siteMetadata: { title: `Kodou`, description: `Kodou site description`, author: `Jack Misteli `, languages }, //....
Gatsbyアプリケーションでは、ページのコンテキストで現在の言語をテンプレートに渡します。
モジュール:pageGenerator.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') module.exports = async (options, createPage, graphql) => { const {query, pageName} = options let templateName = options.templateName ? options.templateName : pageName const result = await graphql(query) if (result.errors) console.error(result.errors) const cosmicJSData = createLanguagesObject(langs) Object.values(result.data)[0].edges.forEach(({ node }) => { cosmicJSData[node.locale].push(node) }) // 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], // Here we pass the current language to the page lang } }) }) }
これで、テンプレートでlang
にアクセスできます
const { lang } = props.pageContext;
国際化APIの使用
Intl API は、文字列の比較、数値の書式設定、および日付と時刻の書式設定に使用されます。 ここでは取り上げないクールな機能がたくさんあります。 ここでは、日付を適切な形式で表示するために使用します。
react-intl
パッケージをLayout
ファイルに追加します。
モジュール:layout.js
import React from "react" import { useStaticQuery, graphql } from "gatsby" import "../styles/main.scss" import Header from "./header" import { IntlProvider, FormattedDate } from "react-intl" const Layout = ({ children, location, lang }) => { // We populated the siteMetaData in `gatsby-config.js` and are extracting it here for some extra language context // The best practice here would be to directly get that data from `config` but I want to show different ways to do it const data = useStaticQuery(graphql` query SiteInfoQuery { site { siteMetadata { title languages { defaultLang langs } } } } `) // langs is an array of all the supported languages // defaultLang is the default site language // title is the website's title const {langs, defaultLang, title} = data.site.siteMetadata return ( // We use IntlProvider to set the default language of our page <IntlProvider locale={lang} defaultLocale={defaultLang} > <Header location={location} defaultLang={defaultLang} languages={langs} siteTitle={title} /> <main className="section"> <div className="container"> {children} </div> </main> <footer> <div className="footer"> <div className="content has-text-centered"> {/* FormattedDate will format our date according to the language we set in IntlProvider locale prop */} © <FormattedDate value={new Date()} year="numeric" month="long" day="numeric" weekday="long" />, Built by <a href="https://jmisteli.com"> Jack Misteli</a> </div> </div> </footer> </IntlProvider> ) } export default Layout
ページが英語で生成される場合、<FormattedDate>
はMonday, December 9, 2019
を返します。 ページが日本語で生成された場合、<FormattedDate>
は2019年12月9日月曜日
を返します。
メニューの作成
Layout
には、Header
コンポーネントがあることがわかります。 現在の言語プロパティを除くすべての言語情報をヘッダーに渡します。 ページの現在の言語への別の方法を紹介したいので、合格しません。
import { Link } from "gatsby" import PropTypes from "prop-types" import React from "react" import { getCurrentLangKey, getLangs, getUrlForLang } from 'ptz-i18n' import langmap from 'langmap' import { localizeUrl, buildMenu } from '../../utils/localization' const Header = ({ languages, location, defaultLang}) => { const url = location.pathname const currentLangKey = getCurrentLangKey(languages, defaultLang, url) // Create a home link by adding a slash before the language and if it const homeLink = localizeUrl(currentLangKey, defaultLang, '/') // Get langs return language menu information // langsMenu will allow us to build a dropdown with all the available language options const langsMenu = buildMenu(languages, defaultLang, currentLangKey, url) // On the `/team` page this will return the following array // [{selected: true, link: "/team/", langKey: "en"}, // {selected: false, link: "/ja/team/", langKey: "ja"}] // All the navigation menu item titles const allLanguageTitles = { 'en':['Concept', 'Work', 'Team', 'News', 'Contact'], 'ja': ['コンセプト', '仕事', 'チーム', 'ニュース', '連絡先'] } // Selecting the current language and default to english titles const currentLanguageTitles = allLanguageTitles[currentLangKey] || allLanguageTitles['en'] // allNavigationLinks contains all the pages name, with urls in every supported language const allNavigationLinks = currentLanguageTitles.map((page, i) => ({ name: page, url: `${homeLink.replace(defaultLang, '')}${allLanguageTitles.en[i].toLowerCase()}` })) // On the English page it will return // [{name: "Concept", url: "/concept"}, {name: "Work", url: "/work"}, {name: "Team", url: "/team"}...] // [{name: "コンセプト", url: "/ja/concept"}, {name: "仕事", url: "/ja/work"}, {name: "チーム", url: "/ja/team"} ...] return ( <nav> <Link to={homeLink} className="navbar-item"> HOME </Link> {allLinks.map((link, i) => ( <Link key={i} to={link.url} className="navbar-item"> {link.name.toUpperCase()} </Link> ))} <div className="navbar-language-menu"> <div className="current-language"> // langmap is an object with the language keys as object keys and english, original versions of the language {langmap[langKey]['englishName']} </div> <div className="all-languages-dropdown"> {langsMenu.map((lang)=>( !lang.selected && <Link key={lang.langKey} to={lang.link} className="navbar-item"> {langmap[lang.langKey]['englishName']} </Link> ))} </div> </div> </nav> )} export default Header
これで、ユーザーの現在の言語に応じてリンクを調整するさまざまな言語のナビゲーションメニューが表示されます。 私が作成したユーティリティ関数を確認したい場合は、GitHubリポジトリで入手できます。