기존 개인 프로젝트에서 영어와 한국어를 섞어서 사용하고 있었고, 게다가 텍스트를 그냥 코드 중간에 삽입하는 형식으로 관리하고 있었다. 사실상 관리는 아닌 것이다.
nextjs
에서 사용하는 다국어 패키지를 찾아보았고, 그중 괜찮은 것을 사용하기로 하였다.
기본 설정
next-i18next 설치
npm install next-i18next
npm
과 yarn
등으로 쉽게 설치할 수 있다.
next-i18next 경로 예시
.
└── public
└── locales
├── ko
| └── common.json
| └── index.json
| └── footer.json
└── en
└── common.json
└── index.json
└── footer.json
json
형식으로 사용하는 텍스트를 관리할 수 있다. nextjs가 pages
를 router
형태로 관리하다보니 기본적으로 페이지 이름별로 json
파일을 만들고 공통으로 사용하는 common
이나 footer
을 따로 만들어서 관리하였다.
next-i18next.config.js
module.exports = {
debug: process.env.NODE_ENV === 'development',
i18n: {
defaultLocale: 'ko',
locales: ['ko', 'en'],
},
reloadOnPrerender: process.env.NODE_ENV === 'development',
};
next-i18next
의 설정 파일이다. 프로젝트의 root
경로에 두어 관리하였다.
자세한 설정은 docs를 참고하면 좋을 것 같다.
next.config.js
const { i18n } = require('./next-i18next.config');
const nextConfig = {
i18n,
};
module.exports = nextConfig;
위의 next-i18next.config.js
파일에서 설정을 해준 것을 적용하려면, next.config.js
파일에서 적용시켜주어야 한다.
_app.tsx
import React from 'react';
import { AppProps } from 'next/app';
import { appWithTranslation } from 'next-i18next';
function MyApp({ Component, pageProps }: AppProps) {
return (
<Component {...pageProps} />
);
}
export default appWithTranslation(MyApp);
또한 적용시켜주려면 _app.tsx
에서 appWithTranslation
로 감싸주어야 한다.
사용 방법
공통사항
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
export async function getStaticProps({ locale }) {
return {
props: {
...(await serverSideTranslations(locale, ['common', 'footer'])),
// Will be passed to the page component as props
},
};
}
nextjs
에서 서버사이드로 next-i18next
를 적용시키려면, 위와 같이 모든 페이지에 getStaticProps
에서 텍스트 정보들을 가져와 주어야 한다. 이것이 귀찮다면, 이처럼 사용하는 고도화 방법도 있다.
페이지에서 사용하기
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useTranslation, Trans } from 'next-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { Header } from '../components/Header'
import { Footer } from '../components/Footer'
const Homepage = () => {
const router = useRouter()
const { t } = useTranslation('common')
return (
<>
<main>
<Header heading={t('h1')} title={t('title')} />
<div style={{ display: 'inline-flex', width: '90%' }}>
<div style={{ width: '50%' }}>
<h3 style={{ minHeight: 70 }}>{t('blog.optimized.question')}</h3>
<p>
<Trans i18nKey='blog.optimized.answer'>
Then you may have a look at <a href={t('blog.optimized.link')}>this blog post</a>.
</Trans>
</p>
<a href={t('blog.optimized.link')}>
<img style={{ width: '50%' }} src='https://locize.com/blog/next-i18next/next-i18next.jpg' />
</a>
</div>
<div style={{ width: '50%' }}>
<h3 style={{ minHeight: 70 }}>{t('blog.ssg.question')}</h3>
<p>
<Trans i18nKey='blog.ssg.answer'>
Then you may have a look at <a href={t('blog.ssg.link')}>this blog post</a>.
</Trans>
</p>
<a href={t('blog.ssg.link')}>
<img style={{ width: '50%' }} src='https://locize.com/blog/next-i18n-static/title.jpg' />
</a>
</div>
</div>
<hr style={{ marginTop: 20, width: '90%' }} />
<div>
<Link
href='/'
locale={router.locale === 'en' ? 'de' : 'en'}
>
<button>
{t('change-locale', { changeTo: router.locale === 'en' ? 'de' : 'en' })}
</button>
</Link>
<Link href='/second-page'>
<button
type='button'
>
{t('to-second-page')}
</button>
</Link>
</div>
</main>
<Footer />
</>
)
}
export const getStaticProps = async ({ locale }) => ({
props: {
...await serverSideTranslations(locale, ['common', 'footer']),
},
})
export default Homepage
위처럼 json object
를 object[key]
처럼 사용하는 것이 아니라, t(’object.key’)
의 형식으로 접근할 수 있다.
t('object.key', { returnObjects: true })
이전의 방식은 텍스트를 불러오는 방법이고, 위처럼 사용하면, object나, array형식도 불러올 수 있다.
컴포넌트에서의 사용
혹시나 컴포넌트에서 사용하려면, props
로 전달해야 하는가 궁금하였다면, 걱정하지 않아도 된다.
page단에서 이미 getStaticProps
로 불러왔다면, 추가 방식 없이 t(’object.key’)
처럼 그냥 사용할 수 있다.
결과
할인율, 세일, 비율, 일부 값, 퍼센트 계산기 - 개발자 유도혁
개인 프로젝트에 적용해본 결과이다. opengraph
도 언어별로 설정하여서 seo
에 더 좋은 결과가 있으면 좋겠다.