Nextjs+next-intl 다국어 국제화 모범 사례(APP 라우터)
Nextjs에는 APP 라우터와 페이지 라우터라는 두 개의 라우터가 있습니다.
얼마 전 페이지 라우터에서 nextjs가 국제화되고 요약되었습니다.
그러나 페이지 라우터는 Nextjs에 의해 점차적으로 폐지될 라우터가 될 것입니다. 이에 최근 Nextjs는 APP 라우터를 기반으로 국제화되었습니다.
1. Nextjs 국제화 솔루션 선택
1. i18next + 반응-i18next + i18next-리소스-백엔드 + next-i18n-라우터
대부분의 사람들이 사용하고 있는 것 같은데, 시도해 봤는데 꽤 복잡하고, 아직 성공하지 못해서 포기했습니다.
2. next-i18n-라우터 반응-intl
꽤 복잡해 보였지만 1의 그림자 때문에 포기했습니다.
3. 다음 국제
next-intl은 nextjs를 위한 완벽한 국제화 솔루션이며 다른 소프트웨어 패키지가 필요하지 않습니다. 그리고 구성도 비교적 간단합니다. 더 중요한 것은 성공적으로 구성했고 설명할 수 없는 문제가 발생하지 않았다는 것입니다.
그래서 이것이다.
2. 디렉토리 구조
|app ..[로케일] ...layout.js ...page.js |컴포넌트 ..LangSwitcher.js |공개 ..locales ...en ....common.json ...es .... common.json |i18n.js |navigation.js |middleware.js |next.config.js
3. 국제 라우팅
1. 네비게이션.js
이것은 구성 파일이며 이 파일에 구성된 항목은 다른 파일에서 호출됩니다.
import { createSharedPathnamesNavigation } from 'next-intl/navigation'; 내보내기 const 로케일 = ['en', 'de', 'es', 'ja','ko','it','pt']; 내보내기 const localePrefix = '필요에 따라'; 내보내기 const defaultLocale= "en"; 내보내기 const localeItems= [ { 이름: "English", 코드: "en", iso: "en-US", dir: "ltr" }, { 이름 : "español", 코드: "es", iso: "es-ES", dir: "ltr" }, { 이름: "中文", 코드: "zh_cn", iso: "zh-CN", dir: " ltr" }, { 이름: "Deutsch", 코드: "de", iso: "de-DE", dir: "ltr" }, { 이름: "Italiano", 코드: "it", iso: "it- IT", dir: "ltr" }, { name: "日本语",code: "ja", iso: "ja-JP", dir: "ltr" }, { name: "한국인",code: "ko ", iso: "ko-KR", dir: "ltr" }, { name: "Português",code: "pt", iso: "pt-PT", dir: "ltr" }, ] 내보내기 const { 링크 , 리디렉션, usePathname, useRouter } = createSharedPathnamesNavigation({ locales, localePrefix });
2. [로캘] 디렉터리
앱 디렉토리의 모든 페이지 파일은 [locale] 디렉토리에 배치됩니다.
3. 미들웨어: middleware.js
설명하다:
다음 스타일의 URL을 구현하십시오.
기본 언어 URL:
홈페이지는 www.xxx.com 입니다.
내부 페이지는 www.xxx.com/about입니다.
다른 언어로 된 URL: (스페인어를 예로 들겠습니다)
홈페이지는 www.xxx.com/es 입니다.
내부 페이지는 www.xxx.com/es/about입니다.
또한 URL에 기본 언어가 입력되어 있는 경우(예: 기본 언어가 영어인 경우) 사용자는 URL: www.xxx.com/en을 입력합니다.
그러면 자동으로 www.xxx.com으로 이동됩니다.
암호:
"next-intl/middleware"에서 createMiddleware 가져오기; '@/navigation'에서 { defaultLocale, localePrefix, locales } 가져오기; 기본 createMiddleware 내보내기({ locales, localePrefix , defaultLocale, localeDetection: false, }); const config 내보내기 = { / / 국제화해서는 안 되는 모든 경로를 건너뜁니다. // "api", "_next" 폴더와 // 확장자(예: favicon.ico)가 있는 모든 파일을 건너뜁니다. 일치자: ["/((?!api|_next| .*\\..*).*)"], };
4. 번역 파일 로드
1. 파일 번역
설명하다
내 번역 파일은 "public" 디렉터리에 있지만 실제로 해당 경로가 i18n.js 파일에 구성되어 있는 한 번역 파일은 다른 디렉터리에 있을 수도 있습니다.
번역 파일은 json 파일이며 json 파일은 중첩 형식일 수도 있고 그렇지 않을 수도 있습니다. 궁극적으로 둘은 약간 다르게 참조됩니다.
코드(중첩되지 않음)
{ "아아아": "안녕하세요", }
코드(중첩)
{ "bbb":{ "aaa":"안녕하세요", } }
2. i18n.js 파일
설명하다:
이 파일은 번역 파일을 가져오는 데 사용됩니다. 중요한 것은 번역 파일이 있는 경로와 일치해야 하는 번역 파일의 경로를 구성하는 것입니다.
경로의 ${locale}은 언어를 나타냅니다.
암호
import { getRequestConfig } from "next-intl/server"; // 요청당 한 번 이 구성을 생성하고 // 모든 서버 구성 요소에서 사용할 수 있도록 합니다. 내보내기 기본값 getRequestConfig(async ({ locale }) => ({ // 번역 로드 활성 로캘의 경우 메시지: (await import(`./public/locales/${locale}/common.json`)).default, }));
3. next.config.js 구성
/** @type {import('next').NextConfig} */ const nextConfig = {} const withNextIntl = require("next-intl/plugin")("./i18n.js"); module.exports =withNextIntl(nextConfig)
5. 번역 구현
레이아웃.js의 코드:
"./globals.css" 가져오기; 'next-intl'에서 { NextIntlClientProvider, useMessages } 가져오기; '@/navigation'에서 { 로케일 } 가져오기; '@/comComponents/Header'에서 헤더 가져오기 '@/comComponents에서 바닥글 가져오기 /Footer' 기본 함수 내보내기 RootLayout({ children, params: { locale } }) { if (!locales.includes(locale)) { notFound(); } const message = useMessages(); return (
<html lang="{locale}">
<nextintlclientprovider locale="{locale}" messages="{messages}">
<body><header />{어린이들}<footer /></body>
</nextintlclientprovider>
</html>
);
}
page.js의 코드:
매개변수 locale은 현재 언어를 나타냅니다.
번역 파일이 중첩되지 않은 경우 const t = useTranslations();
번역 파일이 중첩된 경우 파일 구조와 실제 요구 사항에 따라 const t = useTranslations("bbb");와 같은 것을 사용합니다.
import { useTranslations } from 'next-intl'; import { Link } from '@/navigation'; 기본 함수 내보내기 Home({ params: { locale } }) { const t = useTranslations(); return (<>
<link href="{"/"}"><h1>{t("아아아")}</h1></Link>
</>)
6. 언어 전환기
1. 효과
아래로 당겨 언어를 선택하면 현재 페이지가 선택한 언어의 페이지로 전환됩니다.
2. 코드
"use client";
import { useLocale } from "next-intl";
import { localeItems, useRouter, usePathname, defaultLocale } from '@/navigation';
export default function LangSwitcher() {
const locale = useLocale();
const router = useRouter();
const pathname = usePathname();
console.log(locale)
const handleChange = (e) => {
router.push(pathname, { locale: e.target.value });
};
return (
<div>
<select
value={locale}
onChange={handleChange}
className="h-8 m-2 p-1 rounded border-current"
>
<option value={locale} > {GetLangData(locale).name}</option>
{localeItems.map((item) => {
if (item.code === locale) return null
return (<option key={item.code} value={item.code}>
{item.name}
</option>)
})}
</select>
</div>
);
}
export function GetLangData(defaultLocale) {
var res = {}
{
localeItems.map(locale => {
if (locale.code === defaultLocale) {
console.log(locale)
res = locale
}
})
}
return res
}
7. SEO 및 검색 엔진 친화적
1. 메타데이터
Nextjs APP 라우터는 페이지의 제목과 메타데이터를 생성합니다. 저는 세 가지 방법을 시도했습니다.
첫 번째 방법:layout.js에서 직접 사용: expert const 메타데이터={}
두 번째 방법: page.js에서 동적으로 생성된 메타 데이터를 사용합니다.
참고로:최적화: 메타데이터 | Next.js(nextjs.org)
이 두 가지 방법으로 다국어 타이틀과 메타데이터에 실패했습니다. 마지막으로 가장 간단하고 직접적인 방법인 세 번째 방법을 사용하였다.
세 번째 방법: page.js에 제목 태그와 메타 태그를 직접 작성합니다.
따라서 page.js의 코드는 다음과 같이 변경되었습니다.
import { useTranslations } from 'next-intl'; import { Link } from '@/navigation'; 기본 함수 내보내기 Home({ params: { locale } }) { const t = useTranslations(); return (<>
<title>{t("사이트 이름")}</title>
<meta name="keyword" content="{t("site-name")}"></meta>
<meta name="description" content="{t("사이트 설명")}"></meta>
<meta property="og:type" content="website"></meta>
<meta property="og:title" content="{t("사이트 이름")}"></meta>
<meta property="og:description" content="{t("사이트 설명")}"></meta>
<meta property="og:site_name" content="{t("사이트 이름")}"></meta>
<meta property="og:image" content="/이미지/xxx.png"></meta>
<meta property="og:image:width" content="512"></meta>
<meta property="og:image:height" content="512"></meta>
<meta property="og:image:alt" content=""></meta>
<link href="{"/"}"><h1>{t("아아아")}</h1></Link>
</>)
2. 다국어 탐색: 검색 엔진이 다국어 URL을 더 쉽게 찾을 수 있도록 합니다.
설명하다
언어 전환기는 프런트엔드 렌더링되므로 페이지 하단에 Footer.js 구성 요소인 백엔드 렌더링된 다중 언어 탐색을 추가했습니다. 해당 언어를 클릭하시면 해당 언어 홈페이지로 이동됩니다.
Footer.js 코드는 다음과 같습니다.
import Link from 'next/link'
import { localeItems,defaultLocale } from '@/navigation';
export default function Footer(){
return (<>
<div className="divider"></div>
<footer className="footer footer-center p-10 bg-base-200 text-base-content rounded">
<nav className="flex flex-wrap gap-4">
{localeItems.map(locale => {
if (locale.code === defaultLocale) return(<Link className="link link-hover" href="/" key={locale.code}>{locale.name}</Link>)
const thehref="/"+locale.code
return (<Link className="link link-hover" href={thehref} key={locale.code}> {locale.name}</Link>)
})}
</nav>
<aside className='p-6 text-center'>
<p>Copyright © 2024 - All right reserved by xxx.com</p>
</aside>
</footer>
</>
)
}
8. 요약
국제 라우팅, 번역 파일의 구조 및 도입, 번역 구현. 어떤 종류의 국제화 계획이든지 이 세 가지 측면이 관련됩니다. 번거롭지는 않지만 일반적으로 next-intl은 비교적 간단합니다.