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

i18n - 따라해보기

This tutorial will walk you through the basics of the Docusaurus i18n system.

We will add French translations to a newly initialized English Docusaurus website.

Initialize a new site with npx [email protected] website classic (like this one).

Configure your site

Modify docusaurus.config.js to add the i18n support for the French language.

Site configuration

Use the site i18n configuration to declare the 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에서 이름이 생략됩니다.

Docusaurus uses the locale names to provide sensible defaults: the <html lang="..."> attribute, locale label, calendar format, etc. You can customize these defaults with the localeConfigs.

Theme configuration

Add a navbar item of type localeDropdown so that users can select the locale they want:

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

Start your site

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

npm run start -- --locale fr

Your site is accessible at http://localhost:3000/fr/.

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

Docusaurus provides default translations for generic theme labels, such as "Next" and "Previous" for the pagination.

Please help us complete those default translations.

주의

Each locale is a distinct standalone single-page application: it is not possible to start the Docusaurus sites in all locales at the same time.

Translate your site

All translation data for the French locale is stored in website/i18n/fr. Each plugin sources its own translated content under the corresponding folder, while the code.json file defines all text labels used in the React code.

참고

After copying files around, restart your site with npm run start -- --locale fr. 복사한 파일을 편집할 때는 변경된 부분만 반영(Hot-reload)할 수 있습니다.

Translate your React code

For any React code you've written yourself: React pages, React components, etc., you will use the translation APIs.

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

  • The <Translate> component wraps a string as a JSX element;
  • The translate() callback takes a message and returns a string.

상황에 따라 더 적절한 것을 사용하세요. For example, the <Translate> can be used as React children, while for props that expect a string, the callback can be used.

주의

A JSX element is an object, not a string. Using it in contexts expecting strings (such as the children of <option>) would coerce it to a string, which returns "[object Object]". While we encourage you to use <Translate> as JSX children, only use the element form when it actually works.

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>
);
}
정보

Docusaurus provides a very small and lightweight translation runtime on purpose, and only supports basic placeholders interpolation, using a subset of the ICU Message Format.

Most documentation websites are generally static and don't need advanced i18n features (plurals, genders, etc.). Use a library like react-intl for more advanced use-cases.

The docusaurus write-translations command will statically analyze all React code files used in your site, extract calls to these APIs, and aggregate them in the code.json file. 번역 파일은 ID부터 번역 메시지 오브젝트(번역된 라벨과 라벨에 대한 설명 포함)까지를 맵 형태로 저장합니다. In your calls to the translation APIs (<Translate> or translate()), you need to specify either the default untranslated message or the ID, in order for Docusaurus to correctly correlate each translation entry to the API call.

text labels must be static

The docusaurus write-translations command only does static analysis of your code. 여러분의 사이트에서 실제 동작하지는 않습니다. Therefore, dynamic messages can't be extracted, as the message is an expression, not a string:

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

function ItemsList() {
return (
<ul>
{/* DON'T DO THIS: doesn't work with the write-translations command */}
{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>
{/* The titles are now already translated when rendering! */}
{items.map((item) => (
<li key={item.id}>{item.title}</li>
))}
<ul>
);
}

You can see the calls to the translation APIs as purely markers that tell Docusaurus that "here's a text label to be replaced with a translated message".

Pluralization

When you run write-translations, you will notice that some labels are pluralized:

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

Every language will have a list of possible plural categories. Docusaurus will arrange them in the order of ["zero", "one", "two", "few", "many", "other"]. For example, because English (en) has two plural forms ("one" and "other"), the translation message has two labels separated by a pipe (|). For Polish (pl) which has three plural forms ("one", "few", and "many"), you would provide three labels in that order, joined by pipes.

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

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

function ItemsList({items}) {
// `usePluralForm` will provide the plural selector for the current locale
const {selectMessage} = usePluralForm();
// Select the appropriate pluralized label based on `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>
</>
);
}
참고

Docusaurus uses Intl.PluralRules to resolve and select plural forms. It is important to provide the right number of plural forms in the right order for selectMessage to work.

Translate plugin data

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

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

Run the write-translations command:

npm run write-translations -- --locale fr

명령이 실행되면 번역이 필요한 항목을 추출해서 JSON 번역 파일을 초기화합니다. The code.json file at the root includes all translation API calls extracted from the source code, which could either be written by you or provided by the themes, some of which may already be translated by default.

i18n/fr/code.json
{
// No ID for the <Translate> component: the default message is used as 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"
}
}

Translate the message attribute in the JSON files of i18n/fr, and your site layout and homepage should now be translated.

Translate Markdown files

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

Translate the docs

Copy your docs Markdown files from docs/ to i18n/fr/docusaurus-plugin-content-docs/current, and translate them:

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

Notice that the docusaurus-plugin-content-docs plugin always divides its content by versions. The data in ./docs folder will be translated in the current subfolder and current.json file. See the doc versioning guide for more information about what "current" means.

Translate the blog

Copy your blog Markdown files to i18n/fr/docusaurus-plugin-content-blog, and translate them:

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

Translate the pages

Copy your pages Markdown files to i18n/fr/docusaurus-plugin-content-pages, and translate them:

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
주의

We only copy .md and .mdx files, as React pages are translated through JSON translation files already.

Use explicit heading IDs

By default, a Markdown heading ### Hello World will have a generated ID hello-world. Other documents can link it with [link](#hello-world). However, after translation, the heading becomes ### Bonjour le Monde, with ID bonjour-le-monde.

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

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

For localized sites, it is recommended to use explicit heading IDs.

Deploy your site

You can choose to deploy your site under a single domain or use multiple (sub)domains.

Single-domain deployment

아래 명령을 실행합니다.

npm run build

Docusaurus will build one single-page application per locale:

  • website/build: for the default, English language
  • website/build/fr: for the French language

You can now deploy the build folder to the static hosting solution of your choice.

참고

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

Static hosting providers generally redirect /unknown/url to /404.html by convention, always showing an English 404 page.

Localize your 404 pages by configuring your host to redirect /fr/* to /fr/404.html.

This is not always possible, and depends on your host: GitHub Pages can't do this, Netlify can.

Multi-domain deployment

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

npm run build -- --locale fr

Docusaurus will not add the /fr/ URL prefix.

On your static hosting provider:

  • 로케일마다 배포 파일을 만듭니다.
  • configure the appropriate build command, using the --locale option
  • 선택한 배포 대상에 따라 (하위) 도메인을 설정해줍니다.
주의

This strategy is not possible with GitHub Pages, as it is only possible to have a single deployment.

Hybrid

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

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

  • Deploy your site as fr.docusaurus.io
  • Configure a CDN to serve it from docusaurus.io/fr

Managing translations

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

We will share two common translation collaboration strategies: using git and using Crowdin.