Menu điều hướng được quốc tế hóa trong Gatsby.js
Trong một bài trước, Tạo trang web đa ngôn ngữ với Gatsby , tôi đã xây dựng kodou.me . Kodou có version tiếng Nhật và tiếng Anh. Bài viết hơi dài nên tôi không nói về một số tiện ích tôi đã sử dụng và cách xây dựng menu chuyển của trang web.
Tóm tắt nhanh
Trong bài trước của ta , ta đã xây dựng một trang bằng tiếng Nhật và tiếng Anh. Ngôn ngữ mặc định của trang là tiếng Anh. Điều này nghĩa là ta có hai loại URL:
- Các trang tiếng Nhật:
kodou.me/ja/team
- Các trang tiếng Anh
kodou.me/team
Các version trang khác nhau được viết bằng Cosmic JS . Ta làm cho Gatsby biết về các ngôn ngữ mà ta sử dụng trong /config/languages
. Trong gatsby-node.js
, ta tạo các trang của bạn bằng cách sử dụng các mẫu mà ta đưa vào dữ liệu từ Cosmic JS.
Đây là version đơn giản của mảng team-members
do Cosmic JS trả về có thể trông như thế nào.
teamMembers = [
{
title: 'CEO',
fullName: 'Jack Misteli',
content: 'The CEO of the Company',
locale: 'en'
},
{
title: 'CEO',
fullName: 'ジャック・ミステリ',
content: '会社のCEO',
locale: 'ja'
}
]
Sau khi nhận được teamMembers
ta tạo hai đối tượng jaTeamMembers
và enTeamMembers
. Ta điền các templates/team
với jaTeamMembers
để tạo /ja/team
và enTeamMembers
để tạo /team
.
Nhận thức về ngôn ngữ trang web
Điều quan trọng là trở thành một công dân web tốt và làm cho các trang web ta tạo ra có thể truy cập được. Vì vậy, điều đầu tiên ta cần làm là thêm ngôn ngữ của ta vào metadata trang web của ta . Nó cũng có thể giúp bạn nhận được nhiều kết quả tìm kiếm được nhắm đến hơn.
module.export = {
siteMetadata: {
title: `Kodou`,
description: `Kodou site description`,
author: `Jack Misteli `,
languages
},
//....
Trong ứng dụng Gatsby của ta , ta cũng truyền cho mẫu của bạn ngôn ngữ hiện tại trong ngữ cảnh của trang.
// 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
}
})
})
}
Bây giờ ta có thể truy cập lang
trong các mẫu của ta
const { lang } = props.pageContext;
Sử dụng API quốc tế hóa
Intl API được sử dụng để so sánh chuỗi, định dạng số và định dạng ngày giờ. Nó có rất nhiều tính năng thú vị mà ta sẽ không khám phá ở đây. Ta sẽ chỉ sử dụng nó ở đây để hiển thị ngày ở định dạng thích hợp.
Ta đang thêm gói react-intl
trong file Layout
của ta .
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
Khi trang được tạo bằng tiếng Anh, <FormattedDate>
sẽ trả về Monday, December 9, 2019
. Khi trang được tạo bằng tiếng Nhật <FormattedDate>
sẽ trả về 2019年12月9日月曜日
.
Tạo menu
Bạn có thể thấy rằng trong Layout
ta có thành phần Header
. Ta chuyển tất cả thông tin ngôn ngữ vào tiêu đề ngoại trừ ngôn ngữ hỗ trợ hiện tại. Ta không vượt qua nó vì tôi muốn chỉ cho bạn một cách khác đối với ngôn ngữ hiện tại của trang.
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
Và thế là xong, bạn có một menu chuyển bằng các ngôn ngữ khác nhau điều chỉnh các liên kết của nó theo ngôn ngữ hiện tại của user . Nếu bạn muốn kiểm tra các chức năng tiện ích mà tôi đã xây dựng, chúng có sẵn trong repo GitHub .
Các tin liên quan