이 페이지의 콘텐츠는 AI를 사용하여 번역되었습니다.

    영어 원본 내용의 최신 버전을 보기

    Intlayer와 React Create App으로 국제화(i18n) 시작하기

    Intlayer란 무엇인가요?

    Intlayer는 현대 웹 애플리케이션에서 다국어 지원을 간소화하기 위해 설계된 혁신적이고 오픈 소스인 국제화(i18n) 라이브러리입니다.

    Intlayer를 사용하면:

    • 컴포넌트 수준에서 선언적 사전을 사용하여 번역을 쉽게 관리할 수 있습니다.
    • 메타데이터, 라우트 및 콘텐츠를 동적으로 로컬라이즈할 수 있습니다.
    • TypeScript 지원을 통해 자동 완성 및 오류 감지를 개선할 수 있습니다.
    • 동적 로케일 감지 및 전환과 같은 고급 기능을 활용할 수 있습니다.

    React 애플리케이션에서 Intlayer 설정 단계별 가이드

    1단계: 종속성 설치

    npm을 사용하여 필요한 패키지를 설치합니다:

    bash
    npm install intlayer react-intlayer react-scripts-intlayer
    • intlayer

      구성 관리, 번역, 콘텐츠 선언, 트랜스파일링 및 CLI 명령을 위한 국제화 도구를 제공하는 핵심 패키지입니다.

    • react-intlayer

      Intlayer를 React 애플리케이션과 통합하는 패키지입니다. React 국제화를 위한 컨텍스트 제공자와 훅을 제공합니다.

    • react-scripts-intlayer

      Create React App 기반 애플리케이션과 Intlayer를 통합하기 위한 react-scripts-intlayer 명령 및 플러그인을 포함합니다. 이 플러그인은 craco를 기반으로 하며 Webpack 번들러에 대한 추가 구성을 포함합니다.

    2단계: 프로젝트 구성

    애플리케이션의 언어를 구성하기 위한 설정 파일을 생성합니다:

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [      Locales.ENGLISH,      Locales.FRENCH,      Locales.SPANISH,      // 다른 로케일 추가    ],    defaultLocale: Locales.ENGLISH,  },};export default config;

    이 구성 파일을 통해 로컬라이즈된 URL, 미들웨어 리디렉션, 쿠키 이름, 콘텐츠 선언의 위치 및 확장자, 콘솔에서 Intlayer 로그 비활성화 등을 설정할 수 있습니다. 사용 가능한 매개변수의 전체 목록은 구성 문서를 참조하세요.

    3단계: CRA 구성에 Intlayer 통합

    스크립트를 react-intlayer로 변경합니다:

    package.json
      "scripts": {    "build": "react-scripts-intlayer build",    "start": "react-scripts-intlayer start",    "transpile": "intlayer build"  },

    react-scripts-intlayer 스크립트는 CRACO를 기반으로 합니다. Intlayer craco 플러그인을 기반으로 자체 설정을 구현할 수도 있습니다. 예제 보기.

    4단계: 콘텐츠 선언

    번역을 저장하기 위해 콘텐츠 선언을 생성하고 관리합니다:

    src/app.content.tsx
    import { t, type Dictionary } from "intlayer";import React, { type ReactNode } from "react";const appContent = {  key: "app",  content: {    getStarted: t<ReactNode>({      en: (        <>          Edit <code>src/App.tsx</code> and save to reload        </>      ),      fr: (        <>          Éditez <code>src/App.tsx</code> et enregistrez pour recharger        </>      ),      es: (        <>          Edita <code>src/App.tsx</code> y guarda para recargar        </>      ),    }),    reactLink: {      href: "https://reactjs.org",      content: t({        en: "Learn React",        fr: "Apprendre React",        es: "Aprender React",      }),    },  },} satisfies Dictionary;export default appContent;

    콘텐츠 선언은 애플리케이션 어디에서나 정의할 수 있으며, contentDir 디렉토리(기본값: ./src)에 포함되고 콘텐츠 선언 파일 확장자(기본값: .content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx})와 일치해야 합니다. 자세한 내용은 콘텐츠 선언 문서를 참조하세요. 콘텐츠 파일에 TSX 코드가 포함된 경우, import React from "react";를 콘텐츠 파일에 가져오는 것을 고려해야 합니다.

    5단계: 코드에서 Intlayer 사용

    애플리케이션 전반에서 콘텐츠 사전을 액세스합니다:

    src/App.tsx
    import logo from "./logo.svg";import "./App.css";import type { FC } from "react";import { IntlayerProvider, useIntlayer } from "react-intlayer";const AppContent: FC = () => {  const content = useIntlayer("app");  return (    <div className="App">      <img src={logo} className="App-logo" alt="logo" />      {content.getStarted}      <a        className="App-link"        href={content.reactLink.href.value}        target="_blank"        rel="noopener noreferrer"      >        {content.reactLink.content}      </a>    </div>  );};const App: FC = () => (  <IntlayerProvider>    <AppContent />  </IntlayerProvider>);export default App;

    참고: alt, title, href, aria-label 등과 같은 string 속성에서 콘텐츠를 사용하려면, 함수의 값을 호출해야 합니다. 예를 들어:

    jsx
    <img src={content.image.src.value} alt={content.image.value} />

    useIntlayer 훅에 대해 더 알아보려면 문서를 참조하세요.

    (선택 사항) 단계 6: 콘텐츠 언어 변경

    콘텐츠의 언어를 변경하려면 useLocale 훅에서 제공하는 setLocale 함수를 사용할 수 있습니다. 이 함수는 애플리케이션의 로케일을 설정하고 콘텐츠를 업데이트합니다.

    src/components/LocaleSwitcher.tsx
    import { Locales } from "intlayer";import { useLocale } from "react-intlayer";const LocaleSwitcher = () => {  const { setLocale } = useLocale();  return (    <button onClick={() => setLocale(Locales.English)}>      언어를 영어로 변경    </button>  );};

    useLocale 훅에 대해 더 알아보려면 문서를 참조하세요.

    (선택 사항) 단계 7: 애플리케이션에 로컬화된 라우팅 추가

    이 단계의 목적은 각 언어에 대해 고유한 경로를 만드는 것입니다. 이는 SEO 및 SEO 친화적인 URL에 유용합니다. 예시:

    plaintext
    - https://example.com/about- https://example.com/es/about- https://example.com/fr/about

    기본적으로, 기본 로케일에 대해서는 경로가 접두어로 설정되지 않습니다. 기본 로케일에 접두어를 설정하려면, 구성에서 middleware.prefixDefault 옵션을 true로 설정할 수 있습니다. 자세한 내용은 구성 문서를 참조하세요.

    애플리케이션에 로컬화된 라우팅을 추가하려면, 애플리케이션의 경로를 감싸고 로케일 기반 라우팅을 처리하는 LocaleRouter 컴포넌트를 생성할 수 있습니다. 다음은 React Router를 사용하는 예제입니다:

    src/components/LocaleRouter.tsx
    // 필요한 종속성과 함수 가져오기import { type Locales, configuration, getPathWithoutLocale } from "intlayer"; // 'intlayer'에서 유틸리티 함수 및 타입 가져오기import type { FC, PropsWithChildren } from "react"; // React의 함수형 컴포넌트 및 props 타입import { IntlayerProvider } from "react-intlayer"; // 국제화 컨텍스트를 위한 제공자import {  BrowserRouter,  Routes,  Route,  Navigate,  useLocation,} from "react-router-dom"; // 탐색 관리를 위한 라우터 컴포넌트// Intlayer에서 구성 해체const { internationalization, middleware } = configuration;const { locales, defaultLocale } = internationalization;/** * 로컬화를 처리하고 적절한 로케일 컨텍스트로 자식을 감싸는 컴포넌트. * URL 기반 로케일 감지 및 유효성을 관리합니다. */const AppLocalized: FC<PropsWithChildren<{ locale: Locales }>> = ({  children,  locale,}) => {  const { pathname, search } = useLocation(); // 현재 URL 경로 가져오기  // 현재 로케일 결정, 제공되지 않은 경우 기본값으로 대체  const currentLocale = locale ?? defaultLocale;  // 경로에서 로케일 접두사를 제거하여 기본 경로 생성  const pathWithoutLocale = getPathWithoutLocale(    pathname // 현재 URL 경로  );  /**   * middleware.prefixDefault가 true인 경우, 기본 로케일은 항상 접두어로 설정되어야 합니다.   */  if (middleware.prefixDefault) {    // 로케일 유효성 검사    if (!locale || !locales.includes(locale)) {      // 기본 로케일과 업데이트된 경로로 리디렉션      return (        <Navigate          to={`/${defaultLocale}/${pathWithoutLocale}${search}`}          replace // 현재 히스토리 항목을 새 항목으로 대체        />      );    }    // IntlayerProvider로 자식을 감싸고 현재 로케일 설정    return (      <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>    );  } else {    /**     * middleware.prefixDefault가 false인 경우, 기본 로케일은 접두어로 설정되지 않습니다.     * 현재 로케일이 유효하고 기본 로케일이 아닌지 확인합니다.     */    if (      currentLocale.toString() !== defaultLocale.toString() &&      !locales        .filter(          (locale) => locale.toString() !== defaultLocale.toString() // 기본 로케일 제외        )        .includes(currentLocale) // 현재 로케일이 유효한 로케일 목록에 있는지 확인    ) {      // 로케일 접두사가 없는 경로로 리디렉션      return <Navigate to={`${pathWithoutLocale}${search}`} replace />;    }    // IntlayerProvider로 자식을 감싸고 현재 로케일 설정    return (      <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>    );  }};/** * 로케일별 경로를 설정하는 라우터 컴포넌트. * React Router를 사용하여 탐색을 관리하고 로컬화된 컴포넌트를 렌더링합니다. */export const LocaleRouter: FC<PropsWithChildren> = ({ children }) => (  <BrowserRouter>    <Routes>      {locales        .filter(          (locale) => middleware.prefixDefault || locale !== defaultLocale        )        .map((locale) => (          <Route            // 로케일을 캡처하는 경로 패턴(e.g., /en/, /fr/) 및 모든 후속 경로와 일치            path={`/${locale}/*`}            key={locale}            element={<AppLocalized locale={locale}>{children}</AppLocalized>} // 로케일 관리로 자식을 감쌈          />        ))}      {        // 기본 로케일 접두어가 비활성화된 경우, 루트 경로에서 자식을 직접 렌더링        !middleware.prefixDefault && (          <Route            path="*"            element={              <AppLocalized locale={defaultLocale}>{children}</AppLocalized>            } // 로케일 관리로 자식을 감쌈          />        )      }    </Routes>  </BrowserRouter>);

    그런 다음, 애플리케이션에서 LocaleRouter 컴포넌트를 사용할 수 있습니다:

    src/App.tsx
    import { LocaleRouter } from "./components/LocaleRouter";import type { FC } from "react";// ... AppContent 컴포넌트const App: FC = () => (  <LocaleRouter>    <AppContent />  </LocaleRouter>);

    (선택 사항) 단계 8: 로케일 변경 시 URL 변경

    src/components/LocaleSwitcher.tsx
    import { useLocation, useNavigate } from "react-router-dom";import {  Locales,  getHTMLTextDir,  getLocaleName,  getLocalizedUrl,} from "intlayer";import { useLocale } from "react-intlayer";import { type FC } from "react";const LocaleSwitcher: FC = () => {  const { pathname, search } = useLocation(); // 현재 URL 경로를 가져옵니다. 예: /fr/about?foo=bar  const navigate = useNavigate();  const { availableLocales, setLocale } = useLocale({    onLocaleChange: (locale) => {      // 업데이트된 로케일로 URL을 구성합니다.      // 예: /es/about?foo=bar      const pathWithLocale = getLocalizedUrl(`${pathname}${search}`, locale);      // URL 경로를 업데이트합니다.      navigate(pathWithLocale);    },  });  return (    <div>      <button popoverTarget="localePopover">{getLocaleName(locale)}</button>      <div id="localePopover" popover="auto">        {availableLocales.map((localeItem) => (          <a            href={getLocalizedUrl(location.pathname, localeItem)}            hrefLang={localeItem}            aria-current={locale === localeItem ? "page" : undefined}            onClick={(e) => {              e.preventDefault();              setLocale(localeItem);            }}            key={localeItem}          >            <span>              {/* 로케일 - 예: FR */}              {localeItem}            </span>            <span>              {/* 해당 로케일의 언어 - 예: Français */}              {getLocaleName(localeItem, locale)}            </span>            <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>              {/* 현재 로케일의 언어 - 예: Francés (현재 로케일이 Locales.SPANISH로 설정된 경우) */}              {getLocaleName(localeItem)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* 영어로 된 언어 - 예: French */}              {getLocaleName(localeItem, Locales.ENGLISH)}            </span>          </a>        ))}      </div>    </div>  );};

    문서 참조:

    (선택 사항) 단계 9: HTML 언어 및 방향 속성 전환

    애플리케이션이 여러 언어를 지원할 때, <html> 태그의 langdir 속성을 현재 로케일에 맞게 업데이트하는 것이 중요합니다. 이를 통해 다음을 보장할 수 있습니다:

    • 접근성: 스크린 리더 및 보조 기술은 올바른 lang 속성을 사용하여 콘텐츠를 정확히 발음하고 해석합니다.
    • 텍스트 렌더링: dir(방향) 속성은 텍스트가 올바른 순서로 렌더링되도록 보장합니다(예: 영어는 왼쪽에서 오른쪽, 아랍어나 히브리어는 오른쪽에서 왼쪽). 이는 가독성에 필수적입니다.

    로케일이 변경될 때 이러한 속성을 동적으로 업데이트하면 지원되는 모든 언어에서 사용자에게 일관되고 접근 가능한 경험을 보장할 수 있습니다.

    Hook 구현

    HTML 속성을 관리하기 위한 커스텀 훅을 생성합니다. 이 훅은 로케일 변경을 감지하고 속성을 적절히 업데이트합니다:

    src/hooks/useI18nHTMLAttributes.tsx
    import { useEffect } from "react";import { useLocale } from "react-intlayer";import { getHTMLTextDir } from "intlayer";/** * 현재 로케일에 따라 HTML <html> 요소의 `lang` 및 `dir` 속성을 업데이트합니다. * - `lang`: 브라우저와 검색 엔진에 페이지의 언어를 알립니다. * - `dir`: 올바른 읽기 방향을 보장합니다 (예: 영어의 경우 'ltr', 아랍어의 경우 'rtl'). * * 이 동적 업데이트는 올바른 텍스트 렌더링, 접근성 및 SEO를 위해 필수적입니다. */export const useI18nHTMLAttributes = () => {  const { locale } = useLocale();  useEffect(() => {    // 현재 로케일로 언어 속성을 업데이트합니다.    document.documentElement.lang = locale;    // 현재 로케일에 따라 텍스트 방향을 설정합니다.    document.documentElement.dir = getHTMLTextDir(locale);  }, [locale]);};

    애플리케이션에서 Hook 사용하기

    로케일 변경 시 HTML 속성이 업데이트되도록 메인 컴포넌트에 훅을 통합합니다:

    src/App.tsx
    import type { FC } from "react";import { IntlayerProvider, useIntlayer } from "react-intlayer";import { useI18nHTMLAttributes } from "./hooks/useI18nHTMLAttributes";import "./App.css";const AppContent: FC = () => {  // 로케일에 따라 <html> 태그의 lang 및 dir 속성을 업데이트하는 훅을 적용합니다.  useI18nHTMLAttributes();  // ... 나머지 컴포넌트};const App: FC = () => (  <IntlayerProvider>    <AppContent />  </IntlayerProvider>);export default App;

    이러한 변경 사항을 적용하면 애플리케이션은 다음을 보장합니다:

    • 언어(lang) 속성이 현재 로케일을 정확히 반영하여 SEO 및 브라우저 동작에 중요합니다.
    • 로케일에 따라 텍스트 방향(dir)을 조정하여 다른 읽기 순서를 가진 언어의 가독성과 사용성을 향상시킵니다.
    • 접근성을 개선하여 보조 기술이 이러한 속성에 의존해 최적의 기능을 수행할 수 있도록 합니다.

    TypeScript 구성

    Intlayer는 TypeScript의 모듈 확장을 사용하여 코드베이스를 더 강력하게 만듭니다.

    alt text

    alt text

    TypeScript 구성에 자동 생성된 타입을 포함해야 합니다.

    tsconfig.json
    {  // ... 기존 TypeScript 구성  "include": [    // ... 기존 TypeScript 구성    ".intlayer/**/*.ts", // 자동 생성된 타입 포함  ],}

    Git 구성

    Intlayer에서 생성된 파일을 무시하는 것이 좋습니다. 이를 통해 해당 파일을 Git 저장소에 커밋하는 것을 방지할 수 있습니다.

    이를 위해 .gitignore 파일에 다음 지침을 추가할 수 있습니다:

    .gitignore
    # Intlayer에서 생성된 파일 무시.intlayer

    추가 학습

    더 나아가려면 시각적 편집기를 구현하거나 CMS를 사용하여 콘텐츠를 외부화할 수 있습니다.

    이 문서를 개선할 아이디어가 있으시면 GitHub에 풀 리퀘스트를 제출하여 자유롭게 기여해 주세요.

    문서에 대한 GitHub 링크