i18n - 크라우드인 사용하기
도큐사우루스의 i18n 시스템은 다른 외부 번역 소프트웨어와 결합되어 있지 않습니다.
다만 번역 파일을 적절한 위치에 배치해서 도큐사우루스와 여러분이 선택한 도구와 SaaS형 서비스를 통합할 수 있습니다.
이런 통합의 예제 중 하나로 크라우드인(Crowdin)을 사용하는 방법을 살펴봅니다.
caution
도큐사우루스 사이트를 번역하는 유일한 선택이 크라우드인만 있는 건 절대 아닙니다. 다만 제스트(Jest), 도큐사우루스(Docusaurus), 리즌ML(ReasonML) 같은 페이스북의 프로젝트 문서에 잘 사용하고 있긴 합니다.
좀 더 자세한 정보는 크라우드인 가이드 문서, 크라우드인 기술지원을 참고하세요.
tip
도큐사우루스와 크라우드인 조합과 관련한 토론은 깃허브 이슈 게시판에 남겨주세요.
#
크라우드인 개요크라우드인은 SaaS형 번역 소프트웨어입니다. 오픈소스 프로젝트는 무료 플랜을 사용할 수 있습니다.
아래와 같은 순서로 번역을 진행하는 것을 권장합니다.
- 크라우드인에 소스(번역하지 않은 파일)를 업로드합니다.
- 크라우드인에서 콘텐츠를 번역합니다.
- 크라우드인에서 번역(선택한 언어로 번역한 파일)을 내려받습니다
크라우드인은 번역 절차를 자동화할 수 있도록 명령행 도구를 통해 소스를 업로드하거나 번역 결과를 내려받을 수 있도록 지원합니다.
crowdin.yml
설정 파일은 도큐사우루스에 적용할 수 있으며 번역된 파일을 원하는 경로( i18n/<locale>/..
)에 내려받을 수 있습니다.
좀 더 상세한 기능이나 다양한 작업 방식이 궁금하다면 공식 가이드 문서를 참고하세요.
#
크라우드인 따라해보기이미 여러분이 i18n 따라해보기를 살펴보았다면 이번에는 크라우드인을 사용해 새로 만든 영문 도큐사우루스 웹 사이트를 프랑스어로 번역하는 과정을 따라가보겠습니다.
번역 결과는 docusaurus-crowdin-example.netlify.app (저장소)에서 확인해볼 수 있습니다.
#
도큐사우루스 사이트 준비하기새로운 도큐사우루스 사이트를 초기화합니다.
npx @docusaurus/init@latest init website classic
프랑스어 번역을 위해 site 설정을 아래와 같이 추가합니다.
module.exports = { i18n: { defaultLocale: 'en', locales: ['en', 'fr'], }, themeConfig: { navbar: { items: [ // ... { type: 'localeDropdown', position: 'left', }, // ... ], }, }, // ...};
홈페이지를 번역합니다.
import React from 'react';import Translate from '@docusaurus/Translate';import Layout from '@theme/Layout';
export default function Home() { return ( <Layout> <h1 style={{margin: 20}}> <Translate description="The homepage main heading"> Welcome to my Docusaurus translated site! </Translate> </h1> </Layout> );}
#
크라우드인 프로젝트 만들기크라우드인 서비스에 가입하고 프로젝트를 만듭니다.
소스 언어로 영어를 설정하고 대상 언어로 프랑스어를 설정합니다.
프로젝트가 만들어졌지만 아직은 아무것도 없습니다. 다음 단계에서 번역할 파일을 업로드할 겁니다.
#
크라우드인 설정 만들기설정(관련 문서 참조)은 크라우드인 명령행 도구 실행 시 필요한 매핑 정보를 담습니다.
- 업로드할 소스 파일(JSON, 마크다운)을 어디서 찾아야 하는지
- 번역이 끝나고 파일을 어디에 내려받아야 하는지(
i18n/<locale>
)
웹 사이트
에 crowdin.yml
파일을 아래와 같이 만듭니다.
project_id: '123456'api_token_env: 'CROWDIN_PERSONAL_TOKEN'preserve_hierarchy: truefiles: [ # JSON translation files { source: '/i18n/en/**/*', translation: '/i18n/%two_letters_code%/**/%original_file_name%', }, # Docs Markdown files { source: '/docs/**/*', translation: '/i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name%', }, # Blog Markdown files { source: '/blog/**/*', translation: '/i18n/%two_letters_code%/docusaurus-plugin-content-blog/**/%original_file_name%', }, ]
크라우드인은 소스/번역 파일의 경로를 설정하는 자체 구문을 가지고 있습니다.
**/*
: 하위 디렉터리에 있는 모든 항목%two_letters_code%
: 크라우드인에서 번역할 언어를 설정하는 2글자 코드(지금 사용하는 건fr
)**/%original_file_name%
: 번역 작업 시 원본의 디렉터리/파일 계층 구조를 유지할지 여부
info
크라우드인 명령행 도구에서 보여지는 경고 메시지 일부는 이해하기 어려울 수 있습니다.
그래서 아래와 같이 작업할 것을 권장합니다.
- 한 번에 하나 씩만 변경하기
- 설정을 변경했다면 소스를 다시 업로드하기
/
로 시작하는 경로 사용하기(./
경로는 잘 동작하지 않습니다)/docs/**/*.(md|mdx)
같이 화려한 글로브 패턴은 피하기(잘 동작하지 않습니다)
#
토큰 접근하기api_token_env
속성은 크라우드인 명령행 도구에서 읽은 env variable name을 정의합니다.
your personal profile page에서 Personal Access Token
을 발급받을 수 있습니다.
tip
생성한 접근 토큰으로 여러분의 컴퓨터나 CI 서버에 CROWDIN_PERSONAL_TOKEN
환경 변수로 설정하면 기본값을 계속 유지할 수 있습니다.
caution
개인 접근 토큰은 여러분의 크라우드인 프로젝트를 읽고 쓸 수 있는 권한을 가지게 합니다.
토큰값은 절대 커밋하지 마세요. 그리고 개인 계정 대신 크라우드인 그룹 프로필을 사용하는 것을 권장합니다.
#
추가로 설정해야 하는 값project_id
: 직접 입력할 수 있으며https://crowdin.com/project/<MY_PROJECT_NAME>/settings#api
에서 확인할 수 있습니다.preserve_hierarchy
: 모든 파일을 나열하는 대신 크라우드인 UI에서 원래 디렉터리 계층 구조를 유지할지 여부를 설정합니다.
#
크라우드인 명령행 도구 설치하기아래 내용은 3.5.2
버전 명령행 도구를 사용해 작성했습니다. 3.x
릴리스라면 무리 없이 동작할 겁니다.
여러분의 도큐사우루스 사이트에 NPM 패키지로 크라우드인 명령행 도구를 설치합니다.
- npm
- Yarn
npm install @crowdin/cli@3
yarn add @crowdin/cli@3
crowdin
스크립트를 추가합니다.
{ "scripts": { "crowdin": "crowdin" }}
크라우드인 명령행 도구가 정상적으로 설치됐는지 확인합니다.
- npm
- Yarn
npm run crowdin -- --version
yarn run crowdin -- --version
여러분의 컴퓨터에 CROWDIN_PERSONAL_TOKEN
환경 변수를 설정했다면 명령행 도구에서 크라우드인 API에 접근할 수 있습니다.
tip
필요한 경우 일시적으로 개인 토큰을 crowdin.yml
파일 내 api_token: 'MY-TOKEN'
항목으로 설정해서 사용할 수도 있습니다.
#
소스 업로드하기website/i18n/en
경로에 기본 언어 JSON 번역 파일을 생성합니다.
- npm
- Yarn
npm run write-translations
yarn run write-translations
JSON, 마크다운 번역 파일을 업로드합니다.
- npm
- Yarn
npm run crowdin upload
yarn run crowdin upload
업로드한 소스 파일은 크라우드인 화면에서 확인할 수 있습니다. https://crowdin.com/project/<MY_PROJECT_NAME>/settings#files
#
소스 번역하기https://crowdin.com/project/<MY_PROJECT_NAME>
에 접속해서 프랑스어 항목을 클릭합니다.
마크다운 파일을 번역합니다.
tip
번역하지 않아도 되는 항목은 Hide String
으로 체크합니다.
- 프런트 매터:
id
,slug
,tags
... - 준수 사항 단락:
:::
,:::note
,:::tip
...
JSON 파일을 번역합니다.
info
JSON 번역 파일에 작성한 description
속성은 크라우드인에서 번역 작업 시 도움이 될 수 있도록 화면에 표시됩니다.
tip
여러분의 사이트를 기계 번역으로 미리 번역하고 번역된 내용을 확인하면서 수정할 수 있습니다(처음 설정에서 번역 메모리 사용 여부를 활성화해줍니다).
크라우드인에서 제공하는 기계 번역이 맘에 든다면 Hide String
기능을 먼저 사용해보세요.
#
번역 다운로드하기번역한 JSON, 마크다운 파일을 크라우드인 명령행 도구를 사용해 내려받습니다.
- npm
- Yarn
npm run crowdin download
yarn run crowdin download
번역한 콘텐츠는 i18n/fr
경로 아래에 내려받습니다.
이제 프랑스어 사이트를 시작해봅니다.
- npm
- Yarn
npm run start -- --locale fr
yarn run start -- --locale fr
프랑스어로 번역한 여러분의 웹 사이트는 http://localhost:3000/fr/
에서 확인할 수 있습니다.
#
CI로 자동화하기빌드 시 크라우드인에서 번역한 파일을 내려받고 깃에 반영될 수 있도록 CI를 설정해보겠습니다.
website/i18n
디렉터리에 .gitignore
파일을 추가합니다.
여러분의 CI 환경 변수에 CROWDIN_PERSONAL_TOKEN
을 설정합니다.
아래와 같이 npm 스크립트에 크라우드인에서 소스를 추출하고 업로드하고 번역한 파일을 내려받을 수 있도록 sync
항목을 추가합니다.
{ "scripts": { "crowdin:sync": "docusaurus write-translations && crowdin upload && crowdin download" }}
CI에서 도큐사우루스 사이트 빌드 전에 npm run crowdin:sync
명령을 실행합니다.
tip
배포할 내용 미리보기를 빠르게 처리하고 싶다면 번역 파일을 내려받지 말고 npm run build -- --locale en
명령을 사용해 피처 브랜치에 바로 배포합니다.
caution
크라우드인은 동시에 여러 버전을 업로드하거나 내려받는 것을 지원하지 않습니다. 번역은 운영 배포에만 포함하고 배포 미리보기는 번역하지 않는 상태로 유지하는 것을 권장합니다.
#
크라우드인 좀 더 살펴보기#
MDXcaution
MDX 문서를 다룰 때는 문서 내 JSX 조각을 주의해주세요.
크라우드인은 공식적으로 MDX를 지원하지 않습니다. 하지만 .mdx
확장자 파일은 사용할 수 있으며 일반 텍스트가 아닌 마크다운처럼 다룰 수 있습니다.
#
MDX 파일 사용 시 문제점크라우드인에서 JSX 구문을 HTML으로 인식해서 번역 파일을 내려받을 때 JSX 마크업이 훼손될 수 있습니다. 이로 인해 잘못된 JSX 구문으로 빌드 실패의 원인이 됩니다.
<Username name="Sebastien"/>
같이 간단한 문자열만 가지고 있는 JSX 조각은 별 문제가 없습니다.
<User person={{name: "Sebastien"}}/>
처럼 오브젝트/배열 속성을 가지고 있는 복잡한 JSX 조각은 HTML과 다르게 생겨서 구문 처리를 적절하게 하지 못합니다.
#
MDX 파일 사용 시 우회 방안복잡한 JSX 코드는 별도로 독립적인 컴포넌트로 설정하는 것을 권장합니다.
아니면 mdx-code-block
구문을 아래와 같이 사용할 수 있습니다.
# How to deploy Docusaurus
To deploy Docusaurus, run the following command:
````mdx-code-blockimport Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs defaultValue="bash" values={[ { label: 'Bash', value: 'bash' }, { label: 'Windows', value: 'windows' }]}> <TabItem value="bash">
```bash GIT_USER=<GITHUB_USERNAME> yarn deploy ```
</TabItem> <TabItem value="windows">
```batch cmd /C "set "GIT_USER=<GITHUB_USERNAME>" && yarn deploy" ```
</TabItem></Tabs>````
이렇게 하면
- 크라우드인에서는 코드 블럭으로 처리합니다(파일을 내려받을 때 마크업 코드를 훼손하지 않습니다).
- 도큐사우루스에서는 일반적인 JSX 코드로 처리합니다(다른 코드 블럭과 다르게).
- 아쉽지만 MDX 도구(IDE 구문 강조, 코드 정렬 같은)는 적용할 수 없습니다.
#
문서 버전에 따른 번역 작업website/versioned_docs
디렉터리에 번역 파일을 준비합니다.
새로운 버전을 만들 때 소스 문자열은 현재 번역(website/docs
)과 매우 유사합니다. 새로운 버전 문서라고 다시 번역하고 싶지는 않겠죠.
크라우드인에서는 중복 문자열
설정 기능을 지원합니다.
Hide
기능을 사용하는 것을 권장합니다. 하지만 버전 간 얼마나 차이가 있는지에 따라 어떤 설정이 좋은지 판단해야 합니다.
caution
Hide
기능을 사용하지 않으면 할당할 소스 문자열
의 양이 늘어나고 번역 비용에도 영향을 미칠 수 있습니다.
#
멀티 인스턴스 플러그인각 플러그인 인스턴스에 대한 번역 작업이 필요할 수 있습니다.
id=ios
인 문서 플러그인 인스턴스를 가지고 있다면 해당 소스 파일도 처리해주어야 합니다.
website/ios
website/ios_versioned_docs
(버전이 나누어 있다면)
#
사이트 관리하기깃에서 소스 파일을 삭제하거나 이름을 변경한 경우에는 크라우드인 명령행 도구에서 경고를 표시합니다.
소스 리팩토링 작업을 한 경우에도 크라우드인 UI에서 수작업으로 파일을 업데이트해주어야 합니다.
#
버전 관리 시스템(깃) 통합하기크라우드인은 다양한 버전 관리 시스템과의 통합을 지원합니다. 깃허브(GitHub), 깃랩(GitLab), 비트버킷(Bitbucket) 등을 사용할 수 있습니다.
warning
하지만 이렇게 사용하는 건 권장하지 않습니다.
깃과 크라우드인 양쪽에서 번역 작업을 하는 것은 두 시스템 간에 양방향 동기화를 처리할 수 있다면 도움이 될 수도 있습니다.
하지만 몇 가지 이유로 잘 동작하지 않습니다.
- 크라우드인 -> 깃 사이의 동기화는 잘 동작합니다(풀 리퀘스트를 사용해서)
- 깃 -> 크라우드인 사이의 동기화는 수작업이 필요합니다(버튼을 직접 클릭해주어야 합니다).
- 크라우드인에서 기존 마크다운 번역을 마크다운 소스와 연결하기 위해 사용하는 접근법은 100% 신뢰할 수는 없습니다. 깃과 동기화 작업 후에 크라우드인 UI에서 결과를 직접 검토해주어야 합니다.
- 2명의 번역자가 깃과 크라우드인에서 동시에 작업하는 경우에는 번역 작업 간 충돌이 생길 수 있습니다.
crowdin.yml
파일이 저장소 루트에 있어야 합니다.
#
In-Context 번역크라우드인은 In-Context 번역 기능을 지원합니다.
caution
아쉽게도 기술적인 이유로 잘 동작하지 않습니다. 나중에라도 문제가 해결되기를 바랍니다.
크라우드인은 마크다운 문자열을 내부 id 값(crowdin:id12345
같은)으로 대체해주고 있지만 숨겨진 문자열을 포함해 너무 과도하게 처리하고 있고 프런트 매터나 준수 사항 단락, jsx 등 항목이 훼손될 수 있습니다.
#
번역한 화면 URL 편집하기사용자가 /fr/doc1
페이지에 방문했을때 편집하기 버튼은 번역되지 않은 기본 페이지인 website/docs/doc1.md
에 연결됩니다.
여러분은 이런 동작 대신 크라우드인 화면에 연결되는 편집 버튼을 원할 수도 있고 editUrl
함수를 사용해 로케일마다 기본 동작하는 편집 기능을 수정할 수도 있습니다.
const DefaultLocale = 'en';
module.exports = { presets: [ [ '@docusaurus/preset-classic', { docs: { editUrl: ({locale, versionDocsDirPath, docPath}) => { // Link to Crowdin for French docs if (locale !== DefaultLocale) { return `https://crowdin.com/project/docusaurus-v2/${locale}`; } // Link to Github for English docs return `https://github.com/facebook/docusaurus/edit/master/website/${versionDocsDirPath}/${docPath}`; }, }, blog: { editUrl: ({locale, blogDirPath, blogPath}) => { if (locale !== DefaultLocale) { return `https://crowdin.com/project/docusaurus-v2/${locale}`; } return `https://github.com/facebook/docusaurus/edit/master/website/${blogDirPath}/${blogPath}`; }, }, }, ], ],};
note
현재는 크라우드인에 있는 특정 파일에 링크를 연결할 수는 없습니다.
#
설정 예시아래는 멀티 인스턴스를 사용하는 도큐사우루스 v2 설정 파일 예시입니다.
project_id: '428890'api_token_env: 'CROWDIN_PERSONAL_TOKEN'preserve_hierarchy: truelanguages_mapping: &languages_mapping two_letters_code: 'pt-BR': 'pt-BR'files: [ { source: '/website/i18n/en/**/*', translation: '/website/i18n/%two_letters_code%/**/%original_file_name%', languages_mapping: *languages_mapping, }, { source: '/website/docs/**/*', translation: '/website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name%', languages_mapping: *languages_mapping, }, { source: '/website/community/**/*', translation: '/website/i18n/%two_letters_code%/docusaurus-plugin-content-docs-community/current/**/%original_file_name%', languages_mapping: *languages_mapping, }, { source: '/website/versioned_docs/**/*', translation: '/website/i18n/%two_letters_code%/docusaurus-plugin-content-docs/**/%original_file_name%', languages_mapping: *languages_mapping, }, { source: '/website/blog/**/*', translation: '/website/i18n/%two_letters_code%/docusaurus-plugin-content-blog/**/%original_file_name%', languages_mapping: *languages_mapping, }, { source: '/website/src/pages/**/*', translation: '/website/i18n/%two_letters_code%/docusaurus-plugin-content-pages/**/%original_file_name%', ignore: ['/**/*.js', '/**/*.jsx', '/**/*.ts', '/**/*.tsx', '/**/*.css'], languages_mapping: *languages_mapping, }, ]