-
[Next.js 14] 다국어 지원 방법 / Localization / Internationalization 응용(데이터 및 태그를 포함한 변환) [i18next]웹 개발/Nextjs 14 2024. 12. 13. 21:58
아래의 예시처럼 특정 위치에 css를 다르게 적용하고 싶거나
텍스트 중간에 사용자 닉네임이나 결제 예정일 등의 데이터를 포함하여 함께 Localization, 즉 다국어 지원을 해야한다면
잘 찾아오셨습니다!
들어가기 앞서, 해당 글은 이전에 작성했던 i18next를 이용한 App router 기반 Localization 방법의 응용편입니다.
[Next.js 14] App router 기반 Localization / Internationalization [i18next]
다국어를 지원하는 웹에 들어가보면 드롭다운으로 언어를 바꾸고, 그에 맞게 텍스트가 휙휙 바뀌는 것을 본 적이 있을 것이다.이번 포스팅에서는 i18next 모듈을 이용해서 앱 라우터 기반의 Next.js
hotsunchip.tistory.com
따라서 처음 적용하려는 사람은 해당 게시물을 참고하시면 좋을 것 같아요!
이제 반말로...
앞의 포스팅을 참고하여 기본적인 변환에 대해 익숙해졌다면, 이제 앞으로 한 단계 더 나아가보자.
Settings.ts 변경
응용편에서는 이전에 사용했던 settings.ts를 아래와 같이 변경해주어야 한다.
// settings.ts import {InitOptions, Namespace} from 'i18next'; import {defaultLanguage} from '@/utils/userLocaleUtils'; export const isTestEnv = false; export const fallbackLng = defaultLanguage; export const locales = [fallbackLng, 'en', 'ja'] as const; export type LocaleTypes = (typeof locales)[number]; export const defaultNS = 'common'; export function getOptions(lang = fallbackLng, ns:Namespace = defaultNS): InitOptions { return { // debug: true, // Set to true to see console logs supportedLngs: locales, fallbackLng, lng: lang, fallbackNS: defaultNS, defaultNS, ns: ns, nsSeparator: '::', react: { defaultTransParent: '', transEmptyNodeValue: '', transSupportBasicHtmlNodes: true, transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'button', 'a', 'span', 'div', 'input', 'ul', 'li'], transWrapTextNodes: '', }, }; }
비교해보면 nsSeparator이라는 옵션이랑 react라는 옵션이 추가된 것을 확인할 수 있다.
쉽게 말하자면 nsSeparator은 많은 json 파일 중에서 어떤 파일에서 localization key를 가져올 것인지,
react 속성 중 transKeepBasicHtmlNodesFor은 localizationString 내에 어떤 태그를 허용할 것인지
를 정해주는 속성이라고 생각하면 될 것 같다.
사용 방법
이전에는 간단하게
const { t } = await createTranslation(locale, 'customns'); // 서버 컴포넌트일 때 const { t } = useTranslation(locale, 'customns'); // 클라이언트 컴포넌트일 때
를 썼다면, 이번에는 react-i18next에서 제공하는 Trans라는 컴포넌트를 사용할 것이다.
import {Trans} from 'react-i18next/TransWithoutContext';
더 자세한 사용 방법은...
이제 열심히 풀어 설명하는 것보다, 코드를 한번 보는 게 이해하기 쉬울 것 같아 예시를 가져왔다.
더보기'use client'; import "@/styles/pages/main.css"; import React from 'react'; import {useParams} from 'next/navigation'; import {useTranslation} from '@/utils/localization/client'; import type {LocaleTypes} from '@/utils/localization/settings'; import {Trans} from 'react-i18next/TransWithoutContext'; import Link from 'next/link'; import siteLinks from '@/data/links/siteLinks'; const Hero = () => { const locale = useParams()?.locale as LocaleTypes; const {t} = useTranslation(locale, ['public', 'subscribe']); return ( <div className="flex flex-col gap-4"> <div className="example first"> <p>첫 번째 예시</p> <div className="main-hero--text-area"> <h1><Trans t={t} i18nKey="main-hero-title" /></h1> </div> </div> <div className="example second"> <p>두 번째 예시</p> <Trans t={t} i18nKey="subscribe::withdrawal-complete-description" values={{expirationDate: new Date().toLocaleString()}} /> </div> <div className="example third"> <p>세 번째 예시</p> <Trans t={t} i18nKey={`main-faq-answer-6`} components={[ <Link href={siteLinks.discord} className="text-link" rel="noopener noreferrer" target="_blank" key="0" />, <Link href={siteLinks.twitter[locale]} className="text-link" rel="noopener noreferrer" target="_blank" key="0" />, <Link href={siteLinks.blog} className="text-link" rel="noopener noreferrer" target="_blank" key="0" />, ]} /> </div> </div> ); }; export default Hero;
첫 번째 예시
제일 간단한 응용 방법이다. 앞서 setting.ts를 바꿨기 때문에, localizationString 안에 기본 html tag인 li, ul, span 등의 태그를 이용할 수 있게 된다.
<div className="main-hero--text-area"> <h1><Trans t={t} i18nKey="main-hero-title" /></h1> </div>
이렇게 Trans 컴포넌트에 t랑 key를 세팅해주면 끝난다.
이제 스타일을 넣는 건 css 파일에서 해주면 된다는 말씀.
위 예시의 경우, main-hero--text-area의 span에 text-gradient를 적용시킨 것이다.
키는 아래와 같이 작성하면 된다.두 번째 예시
그런데 이제 중간에 유저의 닉네임이라던가, 현재 시간이라던가 등을 포함하여 정보를 제공해야 하는 경우가 있을 것이다.
이 경우에는 {{와 }}를 이용하여 문자열 보간(String Interpolation)하는 것처럼 사용할 수 있다.
<Trans t={t} i18nKey="subscribe::withdrawal-complete-description" values={{expirationDate: new Date().toLocaleString()}} />
지금 예시랑 아래의 키 예시랑 살짝 다른데, 뭐 감 잡으신 것처럼
키에서는 {{와 }}안에 변수명을 적어주고, 스크립트에서는 values라는 속성에 키랑 값을 매칭해주면 된다.
키는 아래와 같이 작성하면 된다.
세 번째 예시
화룡점정으로, 변수뿐만 아니라 컴포넌트도 넣을 수 있다.
<Trans t={t} i18nKey={`main-faq-answer-6`} components={[ <Link href={siteLinks.discord} className="text-link" rel="noopener noreferrer" target="_blank" key="0" />, <Link href={siteLinks.twitter[locale]} className="text-link" rel="noopener noreferrer" target="_blank" key="0" />, <Link href={siteLinks.blog} className="text-link" rel="noopener noreferrer" target="_blank" key="0" />, ]} />
이건 이제 첫 번째 예시랑 비슷한데, 인덱스를 태그로 사용해서 렌더링 시 components 안의 인덱스와 매칭하여 로드한다.
그래서 아래 키 예시 오른쪽에 보이는 것처럼 각 국가별로 컴포넌트 순서를 다르게 보여주거나,
아예 다른 컴포넌트를 보여주는 것도 가능하게 된다.
키는 아래와 같이 작성하면 된다.
이렇게 보면 복잡해보이지만 전혀 어렵지 않다!
예시도 많이 가져왔으니까, 한번 해보면 껌이네~ 할듯
이상 끗~
'웹 개발 > Nextjs 14' 카테고리의 다른 글
[Next.js 14] router.push에서 query만 변경 시 스크롤 유지하기 [Scroll Restoration] (0) 2024.11.21 [Next.js 14] 프로젝트 빌드 시 발생하는 no-console 에러 해결 [ES-Lint] (0) 2024.06.02 [Next.js 14] .env 파일 생성 및 환경변수 설정 [AWS Amplify] (0) 2024.05.08 [Next.js 14] 사용자 데이터 csv로 변환 및 파일로 다운로드 (0) 2024.05.08 [Next.js][PayPal] 페이팔 버튼(subscription) 연결 + 태그라인 없애기 (1) 2024.05.08