메인 컨텐츠로 이동
버전: 2.2.0

i18n - 따라해보기

도큐사우루스 i18n 시스템이 어떻게 동작하는지 간단한 예제를 따라해보면서 살펴봅니다.

영어로 만든 도큐사우루스 웹 사이트프랑스어 번역을 추가해볼 겁니다.

npx [email protected] website classic 명령으로 새로운 사이트를 초기화합니다(이런 형태 파일 구조가 만들어집니다).

사이트 설정하기

프랑스어 i18n 지원에 필요한 설정을 docusaurus.config.js 파일에 추가합니다.

사이트 설정

사이트 i18n 설정을 참조해 i18n locales 항목을 아래와 같이 설정합니다.

docusaurus.config.js
module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr', 'fa'],
localeConfigs: {
en: {
htmlLang: 'en-GB',
},
// 기본값을 재정의할 필요가 없는 경우 로케일(fr 같은)은 생략할 수 있습니다.
fa: {
direction: 'rtl',
},
},
},
};

로케일 이름은 번역된 파일 위치와 번역된 로케일 base URL에 사용됩니다. 모든 로케일 빌드 시 기본 로케일만 base URL에서 이름이 생략됩니다.

도큐사우루스는 로케일 이름을 사용해 <html lang="..."> 속성, 로케일 라벨, 달력 포맷 등에 적절한 기본값을 제공합니다. 기본값은 localeConfigs에서 수정할 수 있습니다.

테마 설정

원하는 로케일을 선택할 수 있도록 navbar item 항목의 type 값을 localeDropdown으로 설정합니다.

docusaurus.config.js
module.exports = {
themeConfig: {
navbar: {
items: [
{
type: 'localeDropdown',
position: 'left',
},
],
},
},
};

사이트 시작하기

선택한 로케일 옵션으로 번역된 사이트를 개발 모드에서 시작합니다.

npm run start -- --locale fr

http://localhost:3000/fr/ 주소로 여러분의 번역된 사이트에 접근할 수 있습니다.

기본으로 제공되는 번역은 없습니다. 최초 생성되는 사이트는 번역되지 않는 상태로 만들어집니다.

"다음"이나 "이전" 같은 도큐사우루스 기본 테마에 포함된 표현들은 번역을 제공합니다.

기본 번역이 적절하게 제공될 수 있도록 참여를 부탁드립니다.

주의

각 로케일은 별개의 독립적인 단일 페이지 애플리케이션입니다. 모든 로케일의 도큐사우루스 사이트를 동시에 시작할 수는 없습니다.

사이트 번역하기

프랑스어 로케일에 대한 모든 번역 데이터는 website/i18n/fr에 저장됩니다. 각 플러그인은 해당 폴더 아래에 자체 번역된 콘텐츠를 제공하지만 리액트 코드에 사용되는 모든 텍스트 라벨은 code.json 파일에서 설정합니다.

참고

파일을 복사하고 npm run start -- --locale fr 명령으로 사이트를 다시 시작합니다. 복사한 파일을 편집할 때는 변경된 부분만 반영(Hot-reload)할 수 있습니다.

리액트 코드 번역하기

직접 작성한 모든 리액트 코드(리액트 페이지, 리액트 컴포넌트 등)에 대해 번역 API를 사용합니다.

사용자에게 표시될 리액트 코드의 모든 텍스트 라벨을 찾아 번역 API를 적용하세요. API는 두 가지 종류가 있습니다.

  • <Translate> 컴포넌트는 문자열을 JSX 요소로 래핑합니다.
  • translate() 콜백 함수는 메시지를 받아 문자열을 반환합니다.

상황에 따라 더 적절한 것을 사용하세요. 예를 들어 <Translate>는 리액트 자식 요소로 사용할 수 있지만 문자열이 필요한 속성인 경우에는 콜백 함수를 사용할 수 있습니다.

주의

JSX 요소는 문자열이 아니라 오브젝트입니다. 문자열로 처리되는 상황(예를 들어 <option>의 자식)에서 이를 사용하면 문자열로 강제 변환되어 "[object Object]" 형태로 반환됩니다. <Translate>를 JSX 자식으로 사용할 것을 권장하며 실제 적용 시에는 요소 형식만을 사용해야 합니다.

src/pages/index.js
import React from 'react';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';

export default function Home() {
return (
<Layout>
<h1>Welcome to my website</h1>
<main>
You can also visit my
<Link to="https://docusaurus.io/blog">blog</Link>
<img
src="/img/home.png"
alt="Home icon"
/>
</main>
</Layout>
);
}
정보

도큐사우루스는 의도적으로 번역 기능을 매우 작고 가볍게 제공합니다. ICU 메시지 형식의 하위 집합을 사용해 기본 틀을 채우는 방식을 지원합니다.

대부분의 문서 웹 사이트는 일반적으로 정적인 파일로 구성됩니다. 때문에 i18n 고급 기능(plurals, genders 등)을 사용할 필요는 없습니다. 고급 기능을 사용하고 싶다면 react-intl 같은 라이브러리를 사용하세요.

docusaurus write-translations 명령은 사이트에서 사용하는 모든 리액트 코드 파일을 정적으로 분석하고 API에 대한 호출을 찾아서 code.json 파일에 모아놓습니다. 번역 파일은 ID부터 번역 메시지 오브젝트(번역된 라벨과 라벨에 대한 설명 포함)까지를 맵 형태로 저장합니다. 번역 API(<Translate> 또는 translate()) 호출 시 도큐사우루스가 각 번역 항목을 API 호출을 적절하게 연결하려면 번역되지 않은 기본 메시지나 ID를 지정해야 합니다.

텍스트 라벨은 정적이어야 합니다

docusaurus write-translations 명령은 코드에 대한 정적 분석만 수행합니다. 여러분의 사이트에서 실제 동작하지는 않습니다. 메시지는 문자열이 아닌 표현식이라서 메시지를 추출할 수 없습니다.

const items = [
{id: 1, title: 'Hello'},
{id: 2, title: 'World'},
];

function ItemsList() {
return (
<ul>
{/* 사용하지 마세요: write-translations 명령으로 동작하지 않습니다 */}
{items.map((item) => (
<li key={item.id}>
<Translate>{item.title}</Translate>
</li>
))}
<ul>
);
}

이것은 런타임에서 올바르게 작동하긴 합니다. 하지만 향후에는 "no-runtime" 메커니즘을 제공해 런타임 시 API를 호출하는 대신 Babel transformation을 통해 리액트 코드에서 번역을 인라인으로 삽입할 수 있게 할겁니다. 따라서 미래를 대비하려면 항상 정적 분석이 가능한 메시지를 선호해야 합니다. 예를 들어 위의 코드는 다음과 같이 리팩토링할 수 있습니다.

const items = [
{id: 1, title: <Translate>Hello</Translate>},
{id: 2, title: <Translate>World</Translate>},
];

function ItemsList() {
return (
<ul>
{/* 렌더링 시 제목이 이미 번역된 상태입니다! */}
{items.map((item) => (
<li key={item.id}>{item.title}</li>
))}
<ul>
);
}

번역 API에 대한 호출은 도큐사우루스에 "번역된 메시지로 대체할 텍스트 라벨이 있다"고 알려주는 마커 역할만 하게 됩니다.

복수화

write-translations을 실행하면 일부 라벨이 복수화되었음을 알 수 있습니다.

i18n/en/code.json
{
// ...
"theme.blog.post.plurals": "One post|{count} posts"
// ...
}

모든 언어에는 가능한 복수 카테고리 목록이 있습니다. 도큐사우루스는 ["zero", "one", "two", "few", "many", "other"]의 순서로 정렬합니다. 예를 들어 영어(en)에는 두 가지 복수형("one", "other")이 있으므로 번역 메시지는 파이프(|)로 구분된 두 개 라벨이 있습니다. 폴란드어(pl)는 세 가지 복수형("one", "few", "many")이 있어 파이프로 연결된 세 개의 라벨을 순서대로 제공합니다.

여러분의 코드 메시지를 복수화할 수도 있습니다.

import {translate} from '@docusaurus/Translate';
import {usePluralForm} from '@docusaurus/theme-common';

function ItemsList({items}) {
// `usePluralForm`은 현재 로케일에 대한 복수형 선택기를 제공합니다.
const {selectMessage} = usePluralForm();
// `items.length`에 따라 적절한 복수형 라벨을 선택합니다.
const message = selectMessage(
items.length,
translate(
{message: 'One item|{count} items'},
{count: items.length},
),
);
return (
<>
<h2>{message}</h2>
<ul>{items.map((item) => <li key={item.id}>{item.title}</li>)}<ul>
</>
);
}
참고

도큐사우루스는 복수형을 확인하고 선택하기 위해 Intl.PluralRules를 사용합니다. selectMessage가 작동하려면 적절한 수의 복수형을 올바른 순서로 제공하는 것이 중요합니다.

플러그인 데이터 번역하기

코드에 산재된 모든 항목에 JSON 번역 파일이 사용됩니다.

  • 위에서 처리한 번역된 라벨을 포함한 리액트 코드
  • 테마 설정 내에 메뉴바와 푸터 라벨
  • sidebars.js의 문서 사이드바 카테고리 라벨
  • 플러그인 옵션의 블로그 사이드바 제목
  • ...

아래와 같이 write-translations 명령을 실행합니다.

npm run write-translations -- --locale fr

명령이 실행되면 번역이 필요한 항목을 추출해서 JSON 번역 파일을 초기화합니다. 루트의 code.json 파일에는 소스 코드에서 추출된 모든 번역 API 호출이 포함되어 있습니다. 이 호출은 사용자가 작성하거나 테마에서 제공될 수 있으며 그 중 일부는 이미 기본 번역되어 있을 수 있습니다.

i18n/fr/code.json
{
// <Translate> 컴포넌트에 대한 ID가 없음: 기본 메시지가 ID로 사용됩니다
"Welcome to my website": {
"message": "Welcome to my website"
},
"home.visitMyBlog": {
"message": "You can also visit my {blog}",
"description": "The homepage message to ask the user to visit my blog"
},
"homepage.visitMyBlog.linkLabel": {
"message": "Blog",
"description": "The label for the link to my blog"
},
"Home icon": {
"message": "Home icon",
"description": "The homepage icon alt message"
}
}

플러그인이나 테마도 아래와 같은 JSON 번역 파일을 가지고 있습니다.

i18n/fr/docusaurus-theme-classic/navbar.json
{
"title": {
"message": "My Site",
"description": "The title in the navbar"
},
"item.label.Docs": {
"message": "Docs",
"description": "Navbar item with label Docs"
},
"item.label.Blog": {
"message": "Blog",
"description": "Navbar item with label Blog"
},
"item.label.GitHub": {
"message": "GitHub",
"description": "Navbar item with label GitHub"
}
}

i18n/fr 디렉터리에 있는 JSON 파일의 message 항목을 번역하면 여러분의 사이트 레이아웃과 홈페이지가 번역되는 것입니다.

마크다운 파일 번역하기

공식적인 도큐사우루스 콘텐츠 플러그인은 다양한 부분에 마크다운/MDX 파일을 사용하며 이를 번역할 수 있습니다.

문서 번역하기

마크다운 파일을 docs/에서 i18n/fr/docusaurus-plugin-content-docs/current로 복사하고 이를 번역합니다.

mkdir -p i18n/fr/docusaurus-plugin-content-docs/current
cp -r docs/** i18n/fr/docusaurus-plugin-content-docs/current
정보

docusaurus-plugin-content-docs 플러그인은 항상 콘텐츠를 버전에 따라 나누는 것에 유의하세요. ./docs 폴더의 데이터는 current 하위 폴더와 current.json 파일로 번역됩니다. "현재(current)"의 의미에 대한 자세한 내용은 문서 버전 관리 가이드를 참고하세요.

블로그 번역하기

블로그 마크다운 파일을 i18n/fr/docusaurus-plugin-content-blog 디렉터리 아래에 복사하고 이를 번역합니다.

mkdir -p i18n/fr/docusaurus-plugin-content-blog
cp -r blog/** i18n/fr/docusaurus-plugin-content-blog

페이지 번역하기

페이지 마크다운 파일을 i18n/fr/docusaurus-plugin-content-pages 디렉터리 아래에 복사하고 이를 번역합니다.

mkdir -p i18n/fr/docusaurus-plugin-content-pages
cp -r src/pages/**.md i18n/fr/docusaurus-plugin-content-pages
cp -r src/pages/**.mdx i18n/fr/docusaurus-plugin-content-pages
주의

리액트 페이지는 JSON 번역 파일에서 번역하기 때문에 .md, .mdx 파일만 복사하면 됩니다.

명시적인 제목 ID 사용하기

기본적으로 마크다운에서 제목으로 ### Hello World을 설정하면 hello-world로 ID가 만들어집니다. 다른 문서에서 링크를 연결할 때는 [link](#hello-world) 형식을 사용합니다. 하지만 번역 후에 제목은 ### Bonjour le Monde이 되고 ID는 bonjour-le-monde이 됩니다.

이렇게 만들어지는 ID가 번역된 사이트에 항상 적합한 것은 아닙니다. 여러분이 적절한 링크를 직접 수정해주어야 합니다.

- [link](#hello-world).
+ [link](#bonjour-le-monde)

번역된 사이트는 명시적인 제목 ID를 사용하는 것을 권장합니다.

사이트를 배포합니다.

여러분의 사이트는 하나의 도메인을 사용할 수도 있고 여러(하위) 도메인을 사용할 수도 있습니다.

단일 도메인에 배포하기

아래 명령을 실행합니다.

npm run build

도큐사우루스는 로케일 별로 하나의 단일 페이지 애플리케이션을 만듭니다.

  • website/build: 기본값으로 영어 애플리케이션을 만듭니다.
  • website/build/fr: 프랑스어 애플리케이션을 위한 디렉터리입니다.

여러분은 이제 원하는 호스팅 서비스에 build 디렉터리를 배포할 수 있습니다.

참고

도큐사우루스 v2 웹 사이트는 아래와 같은 형태를 사용합니다.

호스팅 서비스에서는 일반적으로 /unknown/url 페이지는 규칙에 따라 /404.html로 리다이렉트합니다. 해당 페이지는 영어로 작성된 404 페이지를 보여줍니다.

/fr/* 하위 디렉터리 페이지는 /fr/404.html로 리다이렉트할 수 있도록 호스팅 서비스를 설정하면 여러분의 언어에 맞는 404 페이지를 처리할 수 있습니다.

모든 호스팅 서비스에서 지원하는 건 아닙니다. 깃허브 페이지는 지원하지 않으며 네트리파이(Netlify)는 지원합니다.

여러 도메인에 배포하기

하나의 로케일만 지원하도록 사이트를 빌드할 수 있습니다.

npm run build -- --locale fr

도큐사우루스에서는 /fr/ URL 접두사를 추가하지 않습니다.

여러분이 이용하는 호스팅 서비스에서 아래와 같은 작업이 필요합니다.

  • 로케일마다 배포 파일을 만듭니다.
  • --locale 옵션을 사용해 적절한 빌드 명령을 설정합니다.
  • 선택한 배포 대상에 따라 (하위) 도메인을 설정해줍니다.
주의

위에서 설명한 방법은 깃허브 페이지에서는 사용할 수 없습니다. 개별적인 배포 방식에 한정된 방법입니다.

혼합 방식

일부는 하위 경로 일부는 하위 도메인을 사용하도록 설정할 수 있습니다.

각 로케일 파일을 별도의 하위 도메인에 배포하고 CDN 수준에서 하나의 통합된 도메인의 하위 도메인으로 조합할 수 있습니다.

  • 사이트를 fr.docusaurus.io에 배포합니다.
  • CDN 설정으로 docusaurus.io/fr에서 서비스가 되도록 합니다.

번역 관리

도큐사우루스에서는 여러분이 번역 결과를 관리하는 방법은 신경쓰지 않습니다. 빌드 시 파일 시스템에서 모든 번역 파일(JSON, 마크다운, 기타 데이터 파일)을 사용할 수 있게 지원할 뿐입니다. 하지만 사이트 관리자는 번역에 기여하는 이들이 원활하게 협업할 수 있도록 번역을 관리하는 방법을 고려해야 합니다.

우리는 두 가지 일반적인 번역 시 협업 전략을 공유해드릴 수 있습니다. 깃 사용하기 and 크라우드인 사용하기