Gatsby 사이트에 i18n 구현
This article was originally published on Obytes blog.
이 문서에서는 react-intl 및 Gatsby을 사용하여 React context API 사이트에 i18n(국제화)을 구현할 것입니다. 이 문서에서는 영어와 아랍어만 다루지만 시작하기 전에 원하는 경우 더 많은 언어를 추가할 수 있습니다. , 먼저 구현 방법을 계획해 보겠습니다.
1- 사용자의 기본 언어 감지
2- 사용자의 기본 언어에 따라 언어, 콘텐츠 방향 및 글꼴 모음을 자동으로 전환합니다.
3- 사용자는 여전히 선호하는 언어를 선택할 수 있습니다.
CLI 도구를 사용하여 새 Gatsby 사이트를 생성하여 시작하겠습니다.
gatsby new gatsby-i18n-example && cd gatsby-i18n-example/
그런 다음 필요한 라이브러리를 설치합니다(저는
yarn
를 사용하고 있지만 자유롭게 사용할 수 있습니다npm
).I'm installing recompose too to separate logic from the component and keep the code clean (Feel free not to use it but We highly recommend it), as well as styled-components beta v4 to handle css in js (Feel free not use it too but We highly recommend it) and a simple google fonts gatsby plugin
gatsby-plugin-google-fonts
yarn add react-intl recompose styled-components@next babel-plugin-styled-components gatsby-plugin-styled-components gatsby-plugin-google-fonts
시작하기 전에 먼저 아래와 같이 더 나은 방식으로 파일을 구조화하겠습니다.
.
+-- src
+-- components
| |
| +-- common
| | +-- Head
| | | |
| | | +-- index.jsx
| | +-- Container
| | | |
| | | +-- index.jsx
| | +-- Context
| | | |
| | | +-- index.jsx
| | +-- Layout
| | | |
| | | +-- index.jsx
| | | +-- Provider.jsx
| | | +-- layout.css
| | +-- Trigger
| | | |
| | | +-- index.jsx
| | +-- index.js
| +-- theme
| | +-- Header
| | | |
| | | +-- index.jsx
+-- messages
| |
| +-- ar.json
| +-- en.json
+-- pages
|
+-- index.js
+-- 404.js
+-- about.js
Context 구성 요소 내에서 컨텍스트를 생성하고 기본값으로
en
를 갖는 것으로 시작하겠습니다.import React from 'react'
export const Context = React.createContext('en')
이제 전역 상태를 하위 항목인 소비자에게 전달하는 공급자 구성 요소를 살펴보겠습니다.
Provider is a React component that allows Consumers to subscribe to context changes.
import React from 'react'
import { compose, withState, withHandlers, lifecycle } from 'recompose'
import { Context } from '../Context'
const Provider = ({ children, lang, toggleLanguage }) => (
<Context.Provider value={
{ lang, toggleLanguage: () => toggleLanguage() }
}>
{children}
</Context.Provider>
)
const enhance = compose(
withState('lang', 'handleLanguage', 'en'),
withHandlers({
toggleLanguage: ({ lang, handleLanguage }) => () => {
if (lang === 'ar') {
handleLanguage('en')
localStorage.setItem('lang', 'en')
} else {
handleLanguage('ar')
localStorage.setItem('lang', 'ar')
}
}
}),
lifecycle({
componentDidMount() {
const localLang = localStorage.getItem('lang')
if (localLang) {
this.props.handleLanguage(localLang)
} else {
this.props.handleLanguage(navigator.language.split('-')[0])
}
}
})
)
export default enhance(Provider)
이렇게 하면
lang
가 포함된 값과 toggleLanguage
라는 언어를 토글하는 함수에 액세스할 수 있도록 모든 구성 요소가 래핑되며 구성 요소 아래에는 논리가 있습니다.lang
의 기본값으로 en
를 초기화했지만 구성 요소가 마운트될 때 변경될 수 있습니다. localStorage가 사용 가능한지 확인합니다. true인 경우 해당 값을 lang
상태에 할당합니다. 그렇지 않은 경우 사용자의 브라우저를 감지합니다. 기본 언어를 선택하고 값을 분할하여 해당 언어가 포함된 첫 번째 항목을 가져옵니다.이제
Layout
구성 요소로 이동합니다.IntlProvider
와 함께 우리가 사용할 콘텐츠를 래핑합니다. react-intl
내장 구성 요소Context
및 컨슈머로 콘텐츠를 래핑하여 전역 상태Provider
로 모든 것을 래핑합니다.import React from 'react'
import styled from 'styled-components'
import ar from 'react-intl/locale-data/ar'
import en from 'react-intl/locale-data/en'
import { addLocaleData, IntlProvider } from 'react-intl'
import localEng from '../../../messages/en.json'
import localAr from '../../../messages/ar.json'
import { Context } from '../Context'
import Provider from './Provider'
import Header from '../../theme/Header'
import './layout.css'
addLocaleData(ar, en)
const Layout = ({ children }) => (
<Provider>
<Context.Consumer>
{({ lang }) => (
<IntlProvider locale={lang} messages={lang === 'en' ? localEng : localAr}>
<Global lang={lang}>
<Header />
{children}
</Global>
</IntlProvider>
)}
</Context.Consumer>
</Provider>
)
const Global = styled.div`
font-family: 'Roboto', sans-serif;
${({ lang }) => lang === 'ar' && `
font-family: 'Cairo', sans-serif;
`}
`
export { Layout }
우리는 글꼴 변경을 처리하기 위해
Global
구성 요소를 사용했다는 것을 언급하는 것을 잊었습니다. 따라서 언어가 영어로 설정되면 Roboto
가 되고 아랍어로 설정되면 Cairo
가 됩니다.작동하도록 만드는 모든 것이 준비되었으므로 헤더에 버튼을 추가하여 언어를 전환해 보겠습니다.
import React from 'react'
import styled from 'styled-components'
import { Link } from 'gatsby'
import { FormattedMessage } from 'react-intl'
import { Trigger, Container } from '../../common'
const Header = () => (
<StyledHeader>
<Navbar as={Container}>
<Link to="/">
<FormattedMessage id="logo_text" />
</Link>
<Links>
<Link to="/">
<FormattedMessage id="home" />
</Link>
<Link to="/about">
<FormattedMessage id="about" />
</Link>
<Trigger />
</Links>
</Navbar>
</StyledHeader>
)
// Feel free to move these to a separated styles.js file and import them above
const StyledHeader = styled.div`
padding: 1rem 0;
background: #00BCD4;
`
const Navbar = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
a {
color: #fff;
text-decoration: none;
}
`
const Links = styled.div`
display: flex;
align-items: center;
a {
margin: 0 1rem;
}
`
export default Header
우리가 잘 이해할 수 있도록 언어를 변경하는 버튼을 분리했습니다.
import React from 'react'
import styled from 'styled-components'
import { FormattedMessage } from 'react-intl'
import { Context } from '../Context'
const Trigger = () => (
<Context.Consumer>
{({ toggleLanguage }) => (
<Button type="button" onClick={toggleLanguage}>
<FormattedMessage id="language" />
</Button>
)}
</Context.Consumer>
)
// We recommend moving the style down below to a separate file
const Button = styled.button`
color: #fff;
padding: .3rem 1rem;
box-shadow: 0 4px 6px rgba(50,50,93,.11), 0 1px 3px rgba(0,0,0,.08);
background: #3F51B5;
border-radius: 4px;
font-size: 15px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: .025em;
text-decoration: none;
cursor: pointer;
&:focus {
outline: none;
}
`
export { Trigger }
이 파일에서
Context
를 다시 한 번 가져와서 Consumer
를 사용할 수 있으므로 전역 상태를 얻을 수 있습니다. 이제 버튼을 클릭하면 toggleLanguage
함수가 lang
값을 변경합니다.Gatsby 구성 파일을 가져오기 전에 컨텍스트 소비자의
lang
값에 액세스하고 아랍어인지 조건부로 확인하여 콘텐츠의 방향도 관리해 보겠습니다. true인 경우 방향은 rtl
가 되고 그렇지 않으면 lrt
가 됩니다. ) .import React from 'react'
import { Helmet } from 'react-helmet'
import { injectIntl } from 'react-intl'
import { Context } from '../Context'
const Head = ({ title, intl: { formatMessage } }) => (
<Context.Consumer>
{({ lang }) => (
<Helmet>
<html lang={lang} dir={lang === 'ar' ? 'rtl' : 'ltr'} />
<title>
${formatMessage({ id: title })}
</title>
</Helmet>
)}
</Context.Consumer>
)
export default injectIntl(Head)
You could include all the meta tags, opengraph, structured data and Twitter tags in this
Head
component like I did in the gatsby-i18n-starter
마지막으로 사용 중인 플러그인을
gatsby-config.js
파일에 포함하고 i18n을 지원하는 일부 메시지가 포함된 더미 페이지를 준비하겠습니다.module.exports = {
siteMetadata: {
title: 'Gatsby i18n Example',
},
plugins: [
'gatsby-plugin-react-helmet',
'gatsby-plugin-styled-components',
{
resolve: 'gatsby-plugin-google-fonts',
options: {
fonts: [
'Cairo',
'Roboto'
]
}
},
{
resolve: 'gatsby-plugin-manifest',
options: {
name: 'gatsby-starter-default',
short_name: 'starter',
start_url: '/',
background_color: '#663399',
theme_color: '#663399',
display: 'minimal-ui',
icon: 'src/images/gatsby-icon.png',
},
},
'gatsby-plugin-offline',
],
}
import React from 'react'
import { FormattedMessage } from 'react-intl'
import { Layout, Container } from '../components/common'
import Head from '../components/common/Head'
const IndexPage = () => (
<Layout>
<>
<Head title="welcome" />
<Container>
<h2>
<FormattedMessage id="welcome" />
</h2>
</Container>
</>
</Layout>
)
export default IndexPage
import React from 'react'
import { FormattedMessage } from 'react-intl'
import { Layout, Container } from '../components/common'
import Head from '../components/common/Head'
const AboutPage = () => (
<Layout>
<>
<Head title="about" />
<Container>
<h2>
<FormattedMessage id="about" />
</h2>
</Container>
</>
</Layout>
)
export default AboutPage
다음은 이 예제에서 사용하는 메시지가 포함된 두 json 파일입니다.
{
"language": "عربي",
"welcome": "Welcome",
"Logo_text": "Logo",
"Home": "Home",
"About": "About",
"not_found": "404 - Page Not Found"
}
{
"language": "English",
"welcome": "أهلا بك",
"Logo_text": "شعار",
"Home": "الرئيسية",
"About": "معلومات عنا",
"not_found": "الصفحة غير موجودة - 404"
}
다음을 실행하여 테스트해 보겠습니다.
yarn develop
작동하는 것 같습니다 🎉, check the demo , 여기 the link to the repository가 있습니다. 후속 조치를 할 수 없는 경우 질문이 있으십니까? 댓글로 남겨주시면 최대한 빨리 답변드리겠습니다.
Feel free to use my own gatsby-i18n-starter to easily get started with some other great features.
Reference
이 문제에 관하여(Gatsby 사이트에 i18n 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/smakosh/implement-i18n-to-a-gatsby-site-5ala텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)