Intlayer 및 Vite, React로 국제화(i18n) 시작하기
Intlayer란 무엇입니까?
Intlayer는 현대 웹 애플리케이션에서 다국어 지원을 단순화하도록 설계된 혁신적인 오픈 소스 국제화(i18n) 라이브러리입니다.
Intlayer를 사용하면:
- 구성 요소 수준에서 선언적 사전을 사용하여 번역을 쉽게 관리할 수 있습니다.
- 메타데이터, 경로 및 콘텐츠를 동적으로 지역화할 수 있습니다.
- 자동 생성된 유형을 통해 TypeScript 지원을 보장하여 자동 완성 및 오류 감지를 개선할 수 있습니다.
- 동적 로케일 감지 및 전환과 같은 고급 기능을 누릴 수 있습니다.
Vite 및 React 애플리케이션에서 Intlayer 설정을 위한 단계별 가이드
1단계: 종속성 설치
npm을 사용하여 필요한 패키지를 설치합니다:
1npm install intlayer react-intlayer
1yarn add intlayer react-intlayer
1pnpm add intlayer react-intlayer
2단계: 프로젝트 구성
애플리케이션의 언어를 구성하기 위한 구성 파일을 만듭니다:
1// intlayer.config.ts
2
3import { Locales, type IntlayerConfig } from "intlayer";
4
5const config: IntlayerConfig = {
6 internationalization: {
7 locales: [
8 Locales.ENGLISH,
9 Locales.FRENCH,
10 Locales.SPANISH,
11 // 다른 로케일
12 ],
13 defaultLocale: Locales.ENGLISH,
14 },
15};
16
17export default config;
사용 가능한 모든 매개변수는 구성 문서에서 참조하십시오.
3단계: Vite 구성에 Intlayer 통합
구성에 intlayer 플러그인을 추가합니다.
1import { defineConfig } from "vite";
2import react from "@vitejs/plugin-react-swc";
3import { intLayerPlugin } from "react-intlayer/vite";
4
5// https://vitejs.dev/config/
6export default defineConfig({
7 plugins: [react(), intLayerPlugin()],
8});
4단계: 콘텐츠 선언
콘텐츠 사전을 생성하고 관리합니다:
1// src/app.content.tsx
2import { t, type DeclarationContent } from "intlayer";
3import { type ReactNode } from "react";
4
5const appContent = {
6 key: "app",
7 content: {
8 viteLogo: t({
9 en: "Vite logo",
10 fr: "Logo Vite",
11 es: "Logo Vite",
12 }),
13 reactLogo: t({
14 en: "React logo",
15 fr: "Logo React",
16 es: "Logo React",
17 }),
18
19 title: "Vite + React",
20
21 count: t({
22 en: "count is ",
23 fr: "le compte est ",
24 es: "el recuento es ",
25 }),
26
27 edit: t<ReactNode>({
28 // 콘텐츠에서 React 노드를 사용하는 경우 React를 가져오는 것을 잊지 마세요.
29 en: (
30 <>
31 Edit <code>src/App.tsx</code> and save to test HMR
32 </>
33 ),
34 fr: (
35 <>
36 Éditez <code>src/App.tsx</code> et enregistrez pour tester HMR
37 </>
38 ),
39 es: (
40 <>
41 Edita <code>src/App.tsx</code> y guarda para probar HMR
42 </>
43 ),
44 }),
45
46 readTheDocs: t({
47 en: "Click on the Vite and React logos to learn more",
48 fr: "Cliquez sur les logos Vite et React pour en savoir plus",
49 es: "Haga clic en los logotipos de Vite y React para obtener más información",
50 }),
51 },
52} satisfies DeclarationContent;
53
54export default appContent;
주의: 콘텐츠 파일에 TSX 코드가 포함된 경우, 콘텐츠 파일에 import React from "react";를 가져오는 것을 고려해야 합니다.
Intlayer 선언 파일을 선언하는 방법을 참조하세요.
5단계: 코드에서 Intlayer 활용하기
애플리케이션 전반에 걸쳐 콘텐츠 사전에 접근하세요:
1import { useState } from "react";
2import reactLogo from "./assets/react.svg";
3import viteLogo from "/vite.svg";
4import "./App.css";
5import { LocaleSwitcher } from "./components/LangSwitcherDropDown";
6import { IntlayerProvider, useIntlayer } from "react-intlayer";
7
8function AppContent() {
9 const [count, setCount] = useState(0);
10 const content = useIntlayer("app");
11
12 return (
13 <>
14 <div>
15 <a href="https://vitejs.dev" target="_blank">
16 <img src={viteLogo} className="logo" alt={content.viteLogo.value} />
17 </a>
18 <a href="https://react.dev" target="_blank">
19 <img
20 src={reactLogo}
21 className="logo react"
22 alt={content.reactLogo.value}
23 />
24 </a>
25 </div>
26 <h1>{content.title}</h1>
27 <div className="card">
28 <button onClick={() => setCount((count) => count + 1)}>
29 {content.count}
30 {count}
31 </button>
32 <p>{content.edit}</p>
33 </div>
34 <p className="read-the-docs">{content.readTheDocs}</p>
35 <div className="absolute bottom-5 right-5 z-50">
36 <LocaleSwitcher />
37 </div>
38 </>
39 );
40}
41
42function App() {
43 return (
44 <IntlayerProvider>
45 <AppContent />
46 </IntlayerProvider>
47 );
48}
49
50export default App;
주의: alt, title, href, aria-label 등과 같은 string 속성에서 콘텐츠를 사용하려면 함수의 값을 호출해야 합니다:
tsx1<img src={content.image.src.value} alt={content.image.value} />
(선택 사항) 6단계: 콘텐츠 언어 변경하기
콘텐츠의 언어를 변경하려면 useLocale 훅에서 제공하는 setLocale 함수를 사용할 수 있습니다. 이 함수는 애플리케이션의 로케일을 설정하고 콘텐츠를 해당에 따라 업데이트할 수 있습니다.
1import { Locales } from "intlayer";
2import { useLocale } from "react-intlayer";
3
4const LocaleSwitcher = () => {
5 const { setLocale } = useLocale();
6
7 return (
8 <button onClick={() => setLocale(Locales.English)}>
9 Change Language to English
10 </button>
11 );
12};
(선택 사항) 7단계: 애플리케이션에 지역화된 라우팅 추가하기
이 단계의 목적은 각 언어에 대한 고유한 경로를 만드는 것입니다. 이는 SEO 및 SEO 친화적인 URL에 유용합니다. 예시:
1// /dashboard
2// /es/dashboard
3// /fr/dashboard
기본적으로 기본 로케일의 경로는 접두어가 붙지 않습니다. 기본 로케일의 접두어를 붙이고 싶다면, 구성에서 middleware.prefixDefault 옵션을 true로 설정하면 됩니다. 자세한 내용은 구성 문서를 참조하세요.
애플리케이션에 지역화된 라우팅을 추가하려면 애플리케이션의 경로를 감싸고 로케일 기반 라우팅을 처리하는 LocaleRouter 구성 요소를 만들 수 있습니다. 다음은 React Router를 사용하는 예시입니다:
1// 필요한 종속성과 함수 가져오기
2import { Locales, getConfiguration, getPathWithoutLocale } from "intlayer"; // 'intlayer'의 유틸리티 함수 및 유형
3import { FC, PropsWithChildren } from "react"; // 함수형 구성 요소 및 props에 대한 React 유형
4import { IntlayerProvider } from "react-intlayer"; // 국제화 컨텍스트를 위한 제공자
5import {
6 BrowserRouter,
7 Routes,
8 Route,
9 useParams,
10 Navigate,
11 useLocation,
12} from "react-router-dom"; // 탐색 관리를 위한 라우터 구성 요소
13
14// Intlayer에서 구성 구 destructuring하기
15const { internationalization, middleware } = getConfiguration();
16const { locales, defaultLocale } = internationalization;
17
18/**
19 * 지역화 및 적절한 로케일 컨텍스트로 자식을 감싸는 구성 요소입니다.
20 * URL 기반 로케일 감지 및 유효성 검사를 관리합니다.
21 */
22const AppLocalized: FC<PropsWithChildren> = ({ children }) => {
23 const path = useLocation().pathname; // 현재 URL 경로 가져오기
24 const { locale } = useParams<{ locale: Locales }>(); // URL에서 로케일 매개변수 추출
25
26 // 현재 로케일 결정, 제공된 경우 기본값으로 대체
27 const currentLocale = locale ?? defaultLocale;
28
29 // 경로에서 로케일 접두어를 제거하여 기본 경로 만들기
30 const pathWithoutLocale = getPathWithoutLocale(
31 path // 현재 URL 경로
32 );
33
34 /**
35 * middleware.prefixDefault가 true이면 기본 로케일은 항상 접두어가 붙어야 합니다.
36 */
37 if (middleware.prefixDefault) {
38 // 로케일 유효성 검사
39 if (!locale || !locales.includes(locale)) {
40 // 기본 로케일로 경로 업데이트하여 리디렉션
41 return (
42 <Navigate
43 to={`/${defaultLocale}/${pathWithoutLocale}`}
44 replace // 새 항목으로 현재 히스토리 항목 바꾸기
45 />
46 );
47 }
48
49 // IntlayerProvider로 자식 감싸고 현재 로케일 설정
50 return (
51 <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
52 );
53 } else {
54 /**
55 * middleware.prefixDefault가 false이면 기본 로케일은 접두어가 붙지 않습니다.
56 * 현재 로케일이 유효하고 기본 로케일이 아니도록 합니다.
57 */
58 if (
59 currentLocale.toString() !== defaultLocale.toString() &&
60 !locales
61 .filter(
62 (locale) => locale.toString() !== defaultLocale.toString() // 기본 로케일 제외
63 )
64 .includes(currentLocale) // 현재 로케일이 유효한 로케일 목록에 있는지 확인
65 ) {
66 // 로케일 접두어가 없는 경로로 리디렉션
67 return <Navigate to={pathWithoutLocale} replace />;
68 }
69
70 // IntlayerProvider로 자식 감싸고 현재 로케일 설정
71 return (
72 <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>
73 );
74 }
75};
76
77/**
78 * 로케일별 경로를 설정하는 라우터 구성 요소입니다.
79 * React Router를 사용하여 탐색 관리 및 지역화된 구성 요소 렌더링합니다.
80 */
81export const LocaleRouter: FC<PropsWithChildren> = ({ children }) => (
82 <BrowserRouter>
83 <Routes>
84 <Route
85 // 로케일을 캡처하고 모든 후속 경로와 일치하는 경로 패턴
86 path="/:locale/*"
87 element={<AppLocalized>{children}</AppLocalized>} // 지역 관리를 위한 자식 감싸기
88 />
89
90 {
91 // 기본 로케일의 접두어가 비활성화된 경우 루트 경로에서 자식을 직접 렌더링
92 !middleware.prefixDefault && (
93 <Route
94 path="*"
95 element={<AppLocalized>{children}</AppLocalized>} // 지역 관리를 위한 자식 감싸기
96 />
97 )
98 }
99 </Routes>
100 </BrowserRouter>
101);
동시에, intLayerMiddlewarePlugin을 사용하여 애플리케이션에 서버 측 라우팅을 추가할 수도 있습니다. 이 플러그인은 URL을 기반으로 현재 로케일을 자동으로 감지하고 적절한 로케일 쿠키를 설정합니다. 로케일이 지정되지 않으면 플러그인은 사용자의 브라우저 언어 기본 설정을 기반으로 가장 적절한 로케일을 결정합니다. 로케일이 감지되지 않으면 기본 로케일로 리디렉션됩니다.
1import { defineConfig } from "vite";
2import react from "@vitejs/plugin-react-swc";
3import { intLayerPlugin, intLayerMiddlewarePlugin } from "react-intlayer/vite";
4
5// https://vitejs.dev/config/
6export default defineConfig({
7 plugins: [react(), intLayerPlugin(), intLayerMiddlewarePlugin()],
8});
(선택 사항) 8단계: 로케일 변경 시 URL 변경하기
로케일이 변경될 때 URL을 변경하려면, useLocale 훅에서 제공하는 onLocaleChange prop을 사용할 수 있습니다. 동시에, react-router-dom의 useLocation 및 useNavigate 훅을 사용하여 URL 경로를 업데이트할 수 있습니다.
1import { Locales, getLocalizedUrl } from "intlayer";
2import { useLocale } from "react-intlayer";
3import { useLocation, useNavigate } from "react-router-dom";
4
5const LocaleSwitcher = () => {
6 const location = useLocation(); // 현재 URL 경로 가져오기. 예: /fr/about
7 const navigate = useNavigate();
8
9 const changeUrl = (locale: Locales) => {
10 // 업데이트된 로케일로 URL 구성
11 // 예: 스페인어 설정 시 /es/about
12 const pathWithLocale = getLocalizedUrl(location.pathname, locale);
13
14 // URL 경로 업데이트
15 navigate(pathWithLocale);
16 };
17
18 const { setLocale } = useLocale({
19 onLocaleChange: changeUrl,
20 });
21
22 return (
23 <button onClick={() => setLocale(Locales.English)}>
24 Change Language to English
25 </button>
26 );
27};
TypeScript 구성
Intlayer는 모듈 증강을 사용하여 TypeScript의 이점을 누리고 코드베이스를 강화합니다.
TypeScript 구성에 자동 생성된 유형이 포함되었는지 확인하십시오.
1// tsconfig.json
2
3{
4 // 사용자 정의 구성
5 include: [
6 "src",
7 "types", // <- 자동 생성된 유형 포함
8 ],
9}
Git 구성
Intlayer에 의해 생성된 파일을 무시하는 것이 좋습니다. 이렇게 하면 Git 리포지토리에 이 파일이 커밋되는 것을 피할 수 있습니다.
이를 위해 .gitignore 파일에 다음 지침을 추가할 수 있습니다:
1# Intlayer에 의해 생성된 파일 무시
2.intlayer
이 문서를 개선할 아이디어가 있으시면 GitHub에 풀 리퀘스트를 제출하여 자유롭게 기여해 주세요.
문서에 대한 GitHub 링크