컴포넌트 번역 준비가 끝나면 Angular CLI의 extract-i18n 명령으로 컴포넌트에서 표시한 텍스트를 원본 언어 파일로 추출하세요.
표시된 텍스트에는 컴포넌트 번역 준비하기에서 설명한 것처럼 i18n으로 표시한 텍스트, i18n-어트리뷰트 로 표시한 어트리뷰트, $localize 태그가 붙은 텍스트가 포함됩니다.
프로젝트의 번역 파일을 생성하고 갱신하려면 다음 단계를 진행하세요.
- 원본 언어 파일을 추출합니다.
- 필요하면 위치, 형식, 이름을 변경합니다.
- 원본 언어 파일을 복사해 언어별 번역 파일을 만듭니다.
- 각 번역 파일을 번역합니다.
- 복수형 표현식과 선택 표현식을 별도로 번역합니다.
원본 언어 파일 추출하기
원본 언어 파일을 추출하려면 다음 단계를 진행하세요.
- 터미널 창을 엽니다.
- 프로젝트의 최상위 디렉터리로 이동합니다.
- 다음 CLI 명령을 실행합니다.
ng extract-i18n
extract-i18n 명령은 프로젝트의 최상위 디렉터리에 messages.xlf라는 원본 언어 파일을 생성합니다.
XML Localization Interchange File Format(XLIFF, 버전 1.2)에 대한 자세한 내용은 XLIFF를 참고하세요.
원본 언어 파일의 위치, 형식, 파일 이름을 변경하려면 extract-i18n 명령에서 다음 옵션을 사용하세요.
| 명령 옵션 | 설명 |
|---|---|
--format |
출력 파일의 형식을 설정합니다. |
--out-file |
출력 파일의 이름을 설정합니다. |
--output-path |
출력 디렉터리의 경로를 설정합니다. |
원본 언어 파일 위치 변경하기
src/locale 디렉터리에 파일을 생성하려면 옵션으로 출력 경로를 지정하세요.
extract-i18n --output-path 예제
다음 예제는 옵션으로 출력 경로를 지정합니다.
ng extract-i18n --output-path src/locale
원본 언어 파일 형식 변경하기
extract-i18n 명령은 다음 번역 형식으로 파일을 생성할 수 있습니다.
| 번역 형식 | 설명 | 파일 확장자 |
|---|---|---|
| ARB | Application Resource Bundle | .arb |
| JSON | JavaScript Object Notation | .json |
| XLIFF 1.2 | XML Localization Interchange File Format, 버전 1.2 | .xlf |
| XLIFF 2 | XML Localization Interchange File Format, 버전 2 | .xlf |
| XMB | XML Message Bundle | .xmb (.xtb) |
--format 명령 옵션으로 번역 형식을 명시적으로 지정하세요.
도움말: XMB 형식에서는 원본 언어 파일을 .xmb로 생성하지만, 번역 파일은 .xtb를 사용합니다.
extract-i18n --format 예제
다음 예제는 여러 번역 형식을 보여줍니다.
ng extract-i18n --format=xlf
ng extract-i18n --format=xlf2
ng extract-i18n --format=xmb
ng extract-i18n --format=json
ng extract-i18n --format=arb
원본 언어 파일 이름 변경하기
추출 도구가 생성하는 원본 언어 파일의 이름을 변경하려면 --out-file 명령 옵션을 사용하세요.
extract-i18n --out-file 예제
다음 예제는 출력 파일의 이름을 지정하는 방법을 보여줍니다.
ng extract-i18n --out-file source.xlf
언어별 번역 파일 만들기
지역이나 언어에 맞는 번역 파일을 만들려면 다음 단계를 진행하세요.
원본 언어 파일을 복사해 언어별 번역 파일을 만듭니다.
번역 파일 이름에 지역을 추가합니다.
messages.xlf --> messages.{locale}.xlf프로젝트 최상위 경로에
locale이라는 디렉터리를 만듭니다.src/locale새 디렉터리로 번역 파일을 옮깁니다.
번역 파일을 번역자에게 전달합니다.
애플리케이션에 추가할 언어마다 위 단계를 반복합니다.
프랑스어용 extract-i18n 예제
예를 들어 프랑스어 번역 파일을 만들려면 다음 단계를 진행하세요.
extract-i18n명령을 실행합니다.- 원본 언어 파일인
messages.xlf를 복사합니다. - 프랑스어(
fr) 번역에 사용할 사본의 이름을messages.fr.xlf로 변경합니다. fr번역 파일을src/locale디렉터리로 옮깁니다.fr번역 파일을 번역자에게 전달합니다.
각 번역 파일 번역하기
해당 언어에 능숙하고 번역을 편집할 시간도 충분한 경우가 아니라면, 보통 다음 단계를 진행하게 됩니다.
- 각 번역 파일을 번역자에게 전달합니다.
- 번역자는 XLIFF 파일 편집기를 사용해 다음 작업을 수행합니다.
- 번역을 작성합니다.
- 번역을 편집합니다.
프랑스어 번역 과정 예제
번역 과정을 알아보려면 Angular 국제화 예제 애플리케이션의 messages.fr.xlf 파일을 살펴보세요.
Angular 국제화 예제 애플리케이션에는 프랑스어 번역이 포함되어 있어, 별도의 XLIFF 편집기가 없거나 프랑스어를 몰라도 편집해 볼 수 있습니다.
프랑스어 번역 과정은 다음과 같습니다.
messages.fr.xlf를 열고 첫 번째<trans-unit>엘리먼트를 찾습니다. 이 엘리먼트는 텍스트 노드 라고도 하는 번역 단위 이며, 앞서i18n어트리뷰트로 표시한<h1>인사말 태그의 번역을 나타냅니다.src/locale/messages.fr.xlf (<trans-unit>)
<trans-unit id="introductionHeader" datatype="html"> <source>Hello i18n!</source> <note priority="1" from="description">An introduction header for this sample</note> <note priority="1" from="meaning">User welcome</note> </trans-unit>id="introductionHeader"는 커스텀 ID이지만, 원본 HTML에서 필요한@@접두사는 포함하지 않습니다.텍스트 노드의
<source>... </source>엘리먼트를 복제하고 이름을target으로 바꾼 다음, 내용을 프랑스어 텍스트로 교체합니다.src/locale/messages.fr.xlf (<trans-unit>, 번역 후)
<trans-unit id="introductionHeader" datatype="html"> <source>Hello i18n!</source> <target>Bonjour i18n !</target> <note priority="1" from="description">An introduction header for this sample</note> <note priority="1" from="meaning">User welcome</note> </trans-unit>더 복잡한 번역에서는 설명과 의미 엘리먼트의 정보와 문맥이 적절한 번역 어휘를 고르는 데 도움이 됩니다.
다른 텍스트 노드를 번역합니다. 다음 예제는 번역하는 방법을 보여줍니다.
src/locale/messages.fr.xlf (<trans-unit>)
<trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html"> <source>I don't output any element</source> <target>Je n'affiche aucun élément</target> </trans-unit> <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html"> <source>Angular logo</source> <target>Logo d'Angular</target> </trans-unit>
중요: 번역 단위의 ID를 변경하지 마세요.
각 id 어트리뷰트는 Angular가 생성하며, 컴포넌트 텍스트의 내용과 지정된 의미에 따라 결정됩니다.
텍스트나 의미 중 하나를 변경하면 id 어트리뷰트도 변경됩니다.
텍스트 갱신과 ID 관리에 대한 자세한 내용은 커스텀 ID를 참고하세요.
복수형 번역하기
각 언어에 맞게 필요한 복수형 경우를 추가하거나 제거하세요.
도움말: 언어별 복수형 규칙은 CLDR 복수형 규칙을 참고하세요.
minute의 plural 예제
plural을 번역하려면 ICU 형식에서 각 경우에 대응하는 값을 번역하세요.
just nowone minute ago<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago
다음 예제는 번역하는 방법을 보여줍니다.
src/locale/messages.fr.xlf (<trans-unit>)
<trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" datatype="html">
<source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago} }</source>
<target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>
</trans-unit>
선택 표현식 번역하기
Angular는 값을 선택하는 select ICU 표현식도 별도의 번역 단위로 추출합니다.
gender의 select 예제
다음 예제는 컴포넌트 템플릿에 있는 select ICU 표현식을 보여줍니다.
app.component.html
<span i18n>The author is {gender, select, male {male} female {female} other {other}}</span>
이 예제에서 Angular는 표현식을 두 개의 번역 단위로 추출합니다.
첫 번째 번역 단위에는 select 절 바깥의 텍스트가 들어 있으며, select 대신 플레이스홀더(<x id="ICU">)를 사용합니다.
src/locale/messages.fr.xlf (<trans-unit>)
<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
<source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
<target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
</trans-unit>
중요: 텍스트를 번역할 때 필요하면 플레이스홀더를 옮길 수 있지만, 제거해서는 안 됩니다. 플레이스홀더를 제거하면 번역된 애플리케이션에서 ICU 표현식이 사라집니다.
다음 예제는 select 절이 들어 있는 두 번째 번역 단위를 보여줍니다.
src/locale/messages.fr.xlf (<trans-unit>)
<trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">
<source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>
<target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>
</trans-unit>
다음 예제는 번역이 끝난 두 번역 단위를 보여줍니다.
src/locale/messages.fr.xlf (<trans-unit>)
<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
<source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
<target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
</trans-unit>
<trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">
<source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>
<target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>
</trans-unit>
중첩된 표현식 번역하기
Angular는 중첩된 표현식을 선택 표현식과 같은 방식으로 처리합니다. Angular는 표현식을 두 개의 번역 단위로 추출합니다.
중첩된 plural 예제
다음 예제는 중첩된 표현식 바깥의 텍스트가 들어 있는 첫 번째 번역 단위를 보여줍니다.
src/locale/messages.fr.xlf (<trans-unit>)
<trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">
<source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>
<target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>
</trans-unit>
다음 예제는 중첩된 표현식 전체가 들어 있는 두 번째 번역 단위를 보여줍니다.
src/locale/messages.fr.xlf (<trans-unit>)
<trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">
<source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>
<target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>
</trans-unit>
다음 예제는 번역이 끝난 두 번역 단위를 보여줍니다.
src/locale/messages.fr.xlf (<trans-unit>)
<trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">
<source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>
<target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>
</trans-unit>
<trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">
<source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>
<target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>
</trans-unit>