반응형
14. Internationalization
- Next.js는 다국어를 지원한다.
14-1. 용어
- Locale : 언어 및 서식 설정에 대한 식별자로, 사용자의 언어와 지리적 가능성을 포함.
- en-US : 미국식 영어
- nl-NL : 네덜란드식 네덜란드어
- nl : 일반 네덜란드어
14-2. Routing
- 브라우저 상의 사용자 기본 언어 설정을 선택하는 것이 베스트. 언어 정보가 변경되면 Accept-Language header에 정보가 담긴다.
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
let headers = { 'accept-language': 'en-US,en;q=0.5' }
let languages = new Negotiator({ headers }).languages()
let locales = ['en-US', 'nl-NL', 'nl']
let defaultLocale = 'en-US'
match(languages, locales, defaultLocale) // -> 'en-US'
- 위 라이브러리들을 활용하면, 요청에 포함된 Header 정보를 보고 지원 locale과 기본 locale을 설정 가능.
import { NextResponse } from "next/server";
let locales = ['en-US', 'nl-NL', 'nl']
// Get the preferred locale, similar to the above or using a library
function getLocale(request) { ... }
export function middleware(request) {
// Check if there is any supported locale in the pathname
const { pathname } = request.nextUrl
const pathnameHasLocale = locales.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
)
if (pathnameHasLocale) return
// Redirect if there is no locale
const locale = getLocale(request)
request.nextUrl.pathname = `/${locale}${pathname}`
// e.g. incoming request is /products
// The new URL is now /en-US/products
return NextResponse.redirect(request.nextUrl)
}
export const config = {
matcher: [
// Skip all internal paths (_next)
'/((?!_next).*)',
// Optional: only run on root (/) URL
// '/'
],
}
- /fr/products, my-site.fr/products와 같이 Path name 또는 domain을 보고 Middleware에서 redirect 처리.
- app/[lang] 과 같이 동적 Routing을 활용하면, 모든 하위 페이지에 locale 정보를 전달 할 수 있다.
14-3. Localization
- 사용자 설정 언어에 따른 국제화는 Next.js에 국한되지 않고 모든 Web application에 해당하는 방식이 존재한다.
{
"products": {
"cart": "Add to Cart"
}
}
- en locale 단어 번역본
{
"products": {
"cart": "Toevoegen aan Winkelwagen"
}
}
- nl locale 단어 번역본
- 다음과 같이 각 locale에 맞는 단어 번역본을 만든다.
import 'server-only'
const dictionaries = {
en: () => import('./dictionaries/en.json').then((module) => module.default),
nl: () => import('./dictionaries/nl.json').then((module) => module.default),
}
export const getDictionary = async (locale) => dictionaries[locale]()
- Server level에서 실행 될 단어 정보를 가져오는 함수를 정의 (app/[lang]/dictionaries)
import { getDictionary } from './dictionaries'
export default async function Page({ params: { lang } }) {
const dict = await getDictionary(lang) // en
return <button>{dict.products.cart}</button> // Add to Cart
}
- 이렇게 사용하면, Server Component에서 Javascript Bundle Size에 영향을 주지 않고, 국제화가 가능하다.
14-4. 정적 생성
export async function generateStaticParams() {
return [{ lang: 'en-US' }, { lang: 'de' }]
}
export default function Root({ children, params }) {
return (
<html lang={params.lang}>
<body>{children}</body>
</html>
)
}
- generateStaticParams를 활용하면 정적으로 제공할 locale 정보를 미리 생성할 수 있다.
처음 뵙겠습니다.
Next.js 사용하면서 처음 본 개념이거나, 이해하기 어려운 부분(?)은 붉은색 볼드처리 해봤다.
Preference
Routing: Internationalization | Next.js
Add support for multiple languages with internationalized routing and localized content.
nextjs.org