مشخصات مقاله
-
891
-
0.0
-
3033
-
0
-
0
تعریف جهانی سازی (i18n) در Angular 6
جهانی سازی (i18n)
جهانی سازی نرم افزار عرصهای از برنامه نویسی است که جنبههای متعددی دارد. با کمک این قابلیت میتوان نرم افزارها را به صورتی کاربر پسند برای کاربران جهانی عرضه کرد. در این صفحه به ابزار جهانی سازی Angular (i18n) میپردازیم. با کمک این ابزار میتوانید نرم افزار خود را با زبانهای متعددی بسازید.
برای دیدن نمونهی کاربردی از این قابلیت به «مثال i18n» مراجعه کنید. برنامهی به کار رفته در این مثال که به صورت جلوتر از زمان کامپایل (AOT-compiled) شده است به زبان فرانسوی ترجمه شده است.
Angular و i18n
جهانی سازی به فرآیند طراحی و آمادگی برنامه گفته میشود، به گونهای که برنامهتان در زبانهای مختلف قابل استفاده باشد. محلی سازی به فرآیند ترجمهی برنامهی جهانی سازی شدهتان به زبان مشخص برای زبان مشخص گفته میشود.
Angular جنبههای جهانی سازی زیر را تسهیل میکند:
- نمایش تاریخ، اعداد، درصد و ارز به صورت قالبی از یک موقعیت جغرافیایی
- آماده سازی متن در قالبهای مؤلفهای برای ترجمه
- رسیدگی به شکل جمع لغات
- رسیدگی به متون جایگزین
برای انجام محلی سازی میتوانید از Angular CLI استفاده کنید. با استفاده از این قابلیت میتوانید اغلب متون استاندارد مورد نیاز برای ایجاد فایلهای مترجمان را تولید کنید. همچنین نرم افزار خود را با زبانهای متعددی منتشر کنید. بعد از آن که برنامهتان را مهیای استفاده از i18n کردید CLI میتواند به شما در مراحل زیر کمک کند:
- استخراج متون دارای قابلیت محلی سازی در فایلی که بتوانید آن را برای ترجمه کردن به بیرون بفرستید.
- ساختن و آماده کردن برنامه برای یک زبان مشخص با استفاده از متن ترجمه شده
- ایجاد نسخههای چند زبانه از برنامهتان
راه اندازی تنظیمات زبانی برنامه
یک زبان (locale) شناسهای (id) است که به مجموعهای از اولویتهای کاربر که تمایل دارد در محدودهای از جهان مانند یک کشور به اشتراک گذاشته شود گفته میشود. در این آموزش به شناسهی زبانی به اختصار «زبان» یا «آیدی زبان» می گوییم.
یک شناسهی محلی یونیکد متشکل از یک شناسهی زبانی یونیکد و (در صورت تمایل) کاراکتر - است که این کاراکتر پس از یک افزونهی محلی میآید. (بنا بر دلایل تاریخی، کاراکتر _ به عنوان جایگزینی برای کاراکتر – استفاده میشود.) برای مثال، در آیدی زبانی fr-CA بخش fr به شناسهی زبان فرانسوی اشاره داشته و CA به افزونهی زبانی کانادا اشاره دارد.
Angular از قرارداد Unicode LDML پیروی میکند. در این قرارداد بر اساس قاعدهی BCP47 از شناسههای پایدار (شناسههای محلی یونیکد) استفاده میشود. خیلی مهم است که زمانی که میخواهید تنظیمات زبانی خود را تعریف کنید از این قرارداد پیروی کنید؛ زیرا ابزار i18n در Angular برای آن که بتواند دادههای زبانی متناظر صحیح را پیدا کند از این شناسه استفاده میکند.
Angular به صورت پیش فرض از تنظیمات زبانی en-US استفاده میکند که زبان انگلیسی رایج در ایالت متحدهی آمریکا است.
برای آن که تنظیمات زبانی برنامهی خود را به مقدار دیگری تغییر دهید، از پارامتر –configuration مربوط به CLI استفاده کنید. همراه با این پارامتر، مقدار آیدی زبانی مورد نظرتان را نیز وارد کنید.
ng serve --configuration=fr
اگر از JIT استفاده میکنید، باید در ماژول اصلیتان از ارائه دهندهی LOCALE_ID استفاده کنید:
src/app/app.module.ts
import { LOCALE_ID, NgModule } from '@Angular/core';
import { BrowserModule } from '@Angular/platform-browser';
import { AppComponent } from '../src/app/app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
providers: [ { provide: LOCALE_ID, useValue: 'fr' } ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
برای دریافت اطلاعات بیشتر در رابطه با شناسههای محلی یونیکد به «مشخصات اصلی CLDR» مراجعه کنید.
برای مشاهدهی لیست کاملی از مناطق پشتیبانی شده توسط Angular به « گنجینهی Angular» مراجعه کنید.
شناسههایی که توسط CLDR و Angular مورد استفاده قرار میگیرند، مبتنی بر BCP47 هستند. این مشخصات به مرور زمان تغییر میکنند. در جدول زیر شناسههای قدیمی و شناسههایی که در زمان نوشتن این آموزش وجود دارند، نشان داده شده است:
پایپهای i18n
از پایپهای موجود در Angular میتوانید برای انجام جهانی سازی کمک بگیرید که عبارتاند از : DatePipe, CurrencyPipe, DecimalPipe و PercentPipe . این پایپها برای قالب بندی دادهها بر اساس LOCALE_ID از دادههای زبانی استفاده میکنند.
Angular به صورت پیش فرض برای en-US تنها شامل دادههای زبانی است. اگر شما مقدار LOCALE_ID را بر روی زبان دیگری قرار دهید، باید دادههای زبانی مربوط به این زبان جدید را import کنید. اگر به کمک ng serve و ng build از پارامتر –configuration استفاده کنید، CLI دادههای زبانی را برای شما import خواهد کرد.
اگر قصد دارید که دادههای زبانی دیگر را import کنید، میتوانید این کار را به صورت دستی انجام دهید:
src/app/app.module.ts
import { registerLocaleData } from '@Angular/common';
import localeFr from '@Angular/common/locales/fr';
// the second parameter 'fr' is optional
registerLocaleData(localeFr, 'fr');
اولین پارامتر شئ است که شامل دادههای زبانی import از @Angular/common/locales است. این دادهها به صورت پیش فرض با آیدی زبانیای ثبت میشوند که این آیدی در خود دادههای زبانی Angular تعریف شده است. اگر میخواهید این دادهها را با آیدی زبانی دیگری ثبت کنید، از پارامتر دوم استفاده کنید تا بتوانید آیدی زبانی اختصاصیای را مشخص کنید. برای مثال دادههای زبانی Angular آیدی محلی زبان فرانسوی را به صورت «fr» تعریف میکند. اگر میخواهید از شناسهی اختصاصی fr-FR به جای این شناسه استفاده کنید، میتوانید از پارامتر دوم استفاده کنید.
فایلهای موجود در @Angular/common/locales اغلب دادههای زبانی مورد نیازتان را در بر میگیرد، اما اگر به امکانات قالب بندی پیشرفتهای نیاز دارید، میتوانید این امکانات موجود در مجموعه دادههای اضافی را از @Angular/common/locales/extra وارد کنید. یک پیام خطا به شما نشان خواهد داد که حالت مربوط به این موقعیت چه زمانی رخ میدهد.
src/app/app.module.ts
import { registerLocaleData } from '@Angular/common';
import localeFr from '@Angular/common/locales/fr';
import localeFrExtra from '@Angular/common/locales/extra/fr';
registerLocaleData(localeFr, 'fr-FR', localeFrExtra);
تمامی دادههای زبانی استفاده شده توسط Angular از گنجینهی دادههای زبانی رایج (CLDR) کنسرسیوم یونیکد استخراج شدهاند.
ترجمهی قالب
در این آموزش به یک واحد از متن قابل ترجمه «متن»، «پیام» و یا «پیام متنی» اطلاق میشود.
فرآیند ترجمهی قالب i18n دارای 4 مرحلهی زیر است:
- نشانه گذاری پیامهای متنی موجود در قالبهای مؤلفهای شما برای انجام ترجمه
- ایجاد فایل ترجمه : استفاده از دستور xi18n مربوط به Angular CLI جهت استخراج متن نشانه گذاری شده در یک سورس فایل ترجمهای استاندارد.
- ویرایش فایل ترجمهی تولید شده : ترجمهی متن استخراج شده به زبان مقصد
-
ترکیب فایل ترجمهی تکمیل شده در برنامه. برای انجام این کار از دستور build در Angular CLI استفاده کنید تا بتوانید برنامه را کامپایل کنید، یک پیکربندی را برای محل مشخصی انتخاب کنید و یا امکانات دستوری زیر را تعیین کنید.
- --i18nFile = مسیر به سمت فایل ترجمه شده
- --i18nFormat = قالب فایل ترجمه شده
- --i18nLocale = آیدی محل
این دستور جای پیامهای اصلی را با متن ترجمه شده عوض میکند و نسخهی جدیدی از برنامه را به زبان مقصد تولید میکند.
برای هر یک از زبانهای پشتیبانی شده، شما باید نسخهی مجزایی از برنامه را ساخته و گسترش دهید.
نشانه گذاری متن به کمک مشخصهی i18n
مشخصهی i18n متون قابل ترجمه را علامت گذاری میکند. این مشخصه را درون تگ هر المانی که میخواهید متن ثابت موجود در آن را ترجمه کنید، قرار دهید. در مثال زیر داخل تگ < h1 > به زبان انگلیسی سلام «Hello i18n!» نوشته شده است.
src/app/app.component.html < h1 >Hello i18n!< /h1 >
برای آن که این عبارت را ترجمه کنید، تنها کافیست که مشخصهی i18n را به تگ < h1> اضافه کنید.
src/app/app.component.html < h1 i18n! >Hello i18n!< /h1 >
i18n یک مشخصهی اختصاصی است که توسط کامپایلرها و ابزارهای Angular به رسمیت شناخته میشود. بعد از انجام ترجمه کامپایلر این مشخصه را حذف میکند. در ضمن این مشخصه جزء دستورالعملهای Angular نیست.
با توصیف و معنی به مترجم کمک کنید
برای آن که بتوانید ترجمهی دقیقی از متن داشته باشید، باید اطلاعات و یا متون اضافی را در اختیار مترجم قرار دهید.
میتوانید توصیف متن را به صورت مقداری از مشخصهی i18n اضافه کنید. مانند مثال زیر :
src/app/app.component.html < h1 i18n="An introduction header for this sample" >Hello i18n!< /h1 >
همچنین مترجم باید بداند که معنی و منظور از این پیام متنی درون زمینهی این برنامهی مشخص چیست.
زمینه را به ابتدای مقدار مشخصهی i18n به همراه معنی اضافه کنید و آن را با کاراکتر | از توصیف جدا کنید:
< meaning >|< description > src/app/app.component.html < h1 i18n="site header|An introduction header for this sample" >Hello i18n!< /h1 >
تمامی رویدادهای یک پیام متنی که معنای یکسانی دارند، ترجمهی یکسانی نیز خواهند داشت. پیام متنیای که به معانی متفاوتی ارتباط دارد میتواند ترجمههای متفاوتی نیز داشته باشد.
ابزار استخراج Angular معنی و توصیف را درون فایل منبع ترجمه نگه میدارد تا ترجمههای مختص به زمینه را آسانتر کند. اما تنها ترکیب معنی و پیامهای متنی جهت تولید آیدی مشخصی از یک ترجمه استفاده میشود. اگر دو پیام متنی مشابه با توصیف مختلف داشته باشید (با معنای یکسان) در این صورت، این دو تنها یک بار استخراج میشوند.
برای نگهداری و ماندگاری بیشتر از یک آیدی اختصاصی استفاده کنید
ابزار استخراج کنندهی i18n در Angular فایلی را به همراه یک ورودی ترجمهای برای هر یک از مشخصههای i18n موجود در قالب تولید میکند. این ابزار به صورت پیش فرض، به هر یک از واحدهای ترجمهای یک آیدی منحصر به فرد مانند زیر اختصاص میدهد.
< trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html" >
زمانی که متن قابل ترجمه را تغییر دهید، ایزار استخراج کننده آیدی جدیدی برای آن واحد ترجمهای تولید میکند. بعد از این کار شما باید فایل ترجمه را به همراه یک آیدی جدید به روز رسانی کنید.
به عنوان جایگزین میتوانید با استفاده از پیشوند @@ یک آیدی اختصاصی را در مشخصهی i18n تعیین کنید. در مثال زیر آیدی اختصاصی introductionHeader تعریف شده است:
app/app.component.html < h1 i18n="@@introductionHeader" >Hello i18n!< /h1 >
زمانی که یک آیدی اختصاصی را تعیین کنید، ابزار استخراج کننده و کامپایلر یک واحد ترجمه را با این آیدی اختصاصی ایجاد میکند.
< trans-unit id="introductionHeader" datatype="html" >
این آیدی ماندگار است. در صورت تغییر متن قابل ترجمه ابزار استخراج کننده این آیدی را تغییر نمیدهد. بنابراین نیازی به به روز رسانی ترجمه وجود ندارد. این شیوه کار نگهداری از برنامه را نیز آسانتر میکند.
استفاده از یک آیدی اختصاصی به همراه توصیف
برای آن که در کنار یک آیدی اختصاصی از توصیف نیز استفاده کنید، باید هر دوی اینها را داخل مقدار مشخصهی i18n قرار دهید. در مثال زیر مقدار مشخصهی i18n شامل توصیف و یک آیدی اختصاصی است:
app/app.component.html < h1 i18n="An introduction header for this sample@@introductionHeader" >Hello i18n!< /h1 >
همچنین میتوانید مانند مثال زیر، معنی را نیز به این دو اضافه کنید:
app/app.component.html < h1 i18n="site header|An introduction header for this sample@@introductionHeader" >Hello i18n!< /h1 >
تعریف کردن آیدی های اختصاصی منحصر به فرد
از منحصر به فرد بودن آیدی های اختصاصی مطمئن شوید. اگر برای دو پیام متنی متفاوت از یک آیدی یکسان استفاده کنید، تنها اولین پیام استخراج میشود. و به جای هر دو پیام متنی اصلی، ترجمهی آن به کار میرود. در مثال زیر آیدی اختصاصی myId برای دو پیام مختلف استفاده شده است:
< h3 i18n="@@myId" >Hello< /h3 > < !-- ... -- > < p i18n="@@myId" >Good bye< /p >
ترجمهی زیر به زبان فرانسوی را در نظر بگیرید:
< trans-unit id="myId" datatype="html" > < source >Hello< /source > < target state="new" >Bonjour< /target > < /trans-unit >
با توجه به این که آیدی اختصاصی بالا یکسان است، هر دو المان در ترجمهی حاصل متن یکسان Bonjour را نمایش خواهند داد.
< h3 >Bonjour< /h3 > < !-- ... -- > < p >Bonjour< /p >
ترجمهی متن بدون ایجاد یک المان
اگر بخشی از متن را میخواهید ترجمه کنید، میتوانید آن را درون تگ < span > قرار دهید. با این حال اگر میخواهید برای راحتتر کردن کار ترجمه المان DOM جدیدی را ایجاد نکنید، میتوانید این متن را درون المان < ng-container > قرار دهید. این المان به یک کامنت HTML تبدیل میشود:
src/app/app.component.html < ng-container i18n >I don't output any element< /ng-container >
ترجمهی مشخصهها
گاهی اوقات متن نمایش داده شده به جای آن که به عنوان محتوای تگ نمایش داده شود، به عنوان مقداری از یک مشخصه ارائه میشود. برای مثال اگر قالب شما دارای تصویری به همراه مشخصهی title است، مقدار متنی این مشخصه باید ترجمه شود.
src/app/app.component.html < img [src]="logo" title="Angular logo" >
برای آن که مشخصهای را برای ترجمه کردن علامت گذاری کنید، این مشخصه را به فرم i18n-x اضافه کنید که x اسم مشخصهای است که باید ترجمه شود. در مثال زیر با اضافه کردن مشخصهی i18n-title به تگ img چگونگی علامت گذاری مشخصهی title برای ترجمه نشان داده شده است:
src/app/app.component.html < img [src]="logo" i18n-title title="Angular logo" / >
این تکنیک برای هر مشخصهای از هر المانی جواب میدهد. همچنین میتوانید با استفاده از سینتکس زیر معنی، توصیف و آیدی را نیز به برنامهی خود تخصیص دهید:
i18n-x="< meaning >|< description >@@< id >"
عبارتهای رایج برای Plural و Select
زبانهای مختلف ساختارهای گرامری و قوانین جمع بندی مختلفی دارند که این امر باعث پیچیدهتر شدن کار ترجمه میشود. برای آن که در این حالتها به کار ترجمه کمک کنید، میتوانید از عبارتهای رایج Plural و Select استفاده کنید.
جمع بندی کلمات
فرض کنید که میخواهید بگویید چیزی « X دقیقهی قبل به روز رسانی شده است». در زبان انگلیسی با توجه به تعداد دقیقهها میتوانید عبارتهایی مانند « just now» ، « one minute ago» و یا « x minutes ago» را نمایش دهید (که X یک عدد حقیقی است). ممکن است که در زبانهای دیگر کاردینالیتی به شیوهی متفاوتی بیان شود.
در مثال زیر چگونگی استفاده از یک عبارت ICU (plural ) نشان داده شده است. به کمک این عبارت میتوان بر اساس زمان انجام به روز رسانی، یکی از این سه گزینه را نمایش داد:
src/app/app.component.html
< span i18n >Updated {minutes, plural, =0 {just now} =1 {one minute ago} other { { { minutes }} minutes ago }}< /span >
- اولین پارامتر کلید است. این پارامتر داخل مشخصهی کامپوننت (minutes) محاط شده است. این مشخصه تعداد دقیقهها را تعیین میکند.
- دومین پارامتر این کلمه را به عنوان نوع plural ترجمه شناسایی میکند.
- سومین پارامتر الگوی جمع بندیای را تعریف میکند که متشکل از گروههای جمع بندی و مقادیر مطابق آنها است.
همان طور که در قوانین جمع بندی CLDR بیان شده است، این سینتکس از فرمت پیام دهی ICU پشتیبانی میکند.
گروههای جمع بندی عبارتاند از (با توجه به زبان مورد نظر):
- 0= یا هر عدد دیگری
- صفر
- یک
- دو
- اندک
- زیاد
- سایر موارد
بعد از گروههای جمع بندی، زبان پیش فرض انگلیسی را درون آکولاد قرار دهید ({}).
در مثال بالا، سه گزینهی موجود بر اساس این الگوی جمع بندی مشخص شدهاند. اگر میخواهید در رابطه با صفر دقیقه صحبت کنید از =0 {just now} استفاده کنید، برای یک دقیقه از =1 {one minute} و در صورتی که موردی برای کاردینالیتی پیدا نشد از other { { {minutes}} minutes ago} استفاده کنید. اگر قوانین جمع بندی متفاوت باشند، میتوانید برای 2 ، 3 و یا هر عدد دیگری الگوهایی را اضافه کنید. برای مثال مربوط به "minute" در زبان انگلیسی تنها همین سه الگو کفایت میکنند.
میتوانید برای ترجمههای خود از اینترپولاسیون ها و نشانه گذاری HTML استفاده کنید.
انتخاب از میان پیامهای متنی مختلف
اگر نیاز است که قالب شما بر اساس مقدار یک متغیر، پیامهای متنی متفاوتی را نمایش دهد، باید تمامی این متون مختلف را ترجمه کنید. برای انجام این کار میتوانید از عبارت ICU (select) استفاده کنید. این کار مشابه با عبارتهای plural است، با این تفاوت که شما به جای یک عدد بر اساس یک مقدار رشتهای از میان ترجمههای مختلف به انتخاب میپردازید و این مقادیر را شما تعریف میکنید.
پیام فرمت زیر داخل قالب کامپوننت به مشخصهی gender کامپوننت مقید میشود. خروجی این کار یکی از سه مقدار رشتهای m ، f یا o است. این پیام، این مقادیر را برای ترجمهی مناسب نمایش میدهد:
src/app/app.component.html
< span i18n >The author is {gender, select, male {male} female {female} other {other}}< /span >
جمع تو در تو و انتخاب عبارتهای ICU
همان طور که در مثال زیر مشاهده میکنید، میتوانید عبارتهای ICU مختلفی را نیز به صورت تو در تو استفاده کنید:
src/app/app.component.html
< span i18n >Updated: {minutes, plural,
=0 {just now}
=1 {one minute ago}
other { { {minutes}} minutes ago by {gender, select, male {male} female {female} other {other}}}}
< /span >
ایجاد یک سورس فایل ترجمه
بعد از این که برنامهتان آماده شد، میتوانید برای استخراج پیامهای متنیای که با i18n و مشخصههایی که با i18n-x علامت گذاری شدهاند، داخل یک سورس فایل ترجمه از Angular CLI استفاده کنید. در دایرکتوری روت پروژهی خود یک پنجرهی ترمینال را باز کنید و دستور CLI موسوم به xi18n را اجرا کنید.
ng xi18n
این دستور به صورت پیش فرض در پوشهی src/ شما فایلی به نام messages.xlf را ایجاد میکند.
اگر از CLI استفاده نمیکنید، میتوانید از دو گزینهی زیر استفاده کنید:
- میتوانید مستقیماً از بستهی نرم افزاری @Angular/compiler-cli از ابزار ng-xi18n استفاده کنید. برای اطلاعات بیشتر به آموزش i18n در CLI مراجعه کنید.
- میتوانید از طریق بستهی نرم افزاری @ngtools/webpack از پلاگین AngularCompilerPlugin استفاده کنید. پارامترهای i18nOutFile و i18nOutFormat را به گونهای تنظیم کنید که کار استخراج را آغاز کنند. برای اطلاعات بیشتر به آموزش مربوط به پلاگین Angular Ahead-of-Time Webpack مراجعه کنید.
گزینههای خروجی
اگر میخواهید فرمت، اسم، مکان و محل منبع فایل استخراج شده را تغییر دهید، میتوانید از گزینههای دستوری استفاده کنید. برای مثال، برای آن که فایلی را در پوشهی src/locale ایجاد کنید، مسیر خروجی را به صورت زیر تعریف کنید.
ng xi18n --output-path src/locale
دستور xi18n به صورت پیش فرض در XLIFF ورژن 1.2 فایل ترجمهای به نام messages.xlf را ایجاد میکند.
این دستور میتواند فایلها را به سه فرمت ترجمهای زیر بخواند و بنویسد:
- XLIFF 1.2 (پیش فرض)
- XLIFF 2
- XML Message Bundle (XMB)
اگر میخواهید به صورت مستقیم فرمت ترجمه را مشخص کنید، همان طور که در نمونه دستورات زیر نشان داده شده است میتوانید از گزینهی دستوری --i18nFormat استفاده کنید:
ng xi18n --i18n-format=xlf ng xi18n --i18n-format=xlf2 ng xi18n --i18n-format=xmb
در نمونهی به کار رفته در این آموزش از فرمت پیش فرض XLIFF 1.2 استفاده شده است.
فرمت فایلهای XLIFF به صورت .xlf است. فرمت XMB سورس فایلهای .xmb را تولید میکند، اما از فایلهای ترجمهی .xtb (XML Translation Bundle: XTB) استفاده میکند.
اگر میخواهید اسم سورس فایل ترجمه که توسط ابزار استخراجی تولید شده است را تغییر دهید میتوانید از گزینهی دستوری –outFile استفاده کنید:
ng xi18n --out-file source.xlf
برای آن که تنظیمات زبانی اصلی برنامه خود را مشخص کنید، از گزینهی دستوری --i18n-locale استفاده کنید.
ng xi18n --i18n-locale fr
ابزار استخراجی برای اضافه کردن اطلاعات زبانی برنامه به سورس فایل ترجمهتان از locale استفاده میکند. این اطلاعات کاربردی برای Angular ندارد، اما ابزارهای خارجی ترجمه ممکن است به آنها نیاز داشته باشد.
ترجمهی متن منبع
دستور ng xi18n سورس فایل ترجمهای به نام messages.xlf را در پوشهی src ایجاد میکند. قدم بعدی این است که رشتههای نمایش داده شده در این سورس فایل به فایلهای ترجمهی زبان مشخصی ترجمه شوند. در نمونهی به کار رفته در این آموزش، یک فایل ترجمهی فرانسوی ایجاد میشود.
ایجاد یک پوشهی محلی سازی
اغلب برنامهها به بیش از یک زبان ترجمه میشوند، به همین دلیل بهتر است که ساختار پروژه، کل کارهای جهانی سازی را بازتاب دهد.
یکی از روشهای انجام این کار اختصاص یک پوشه به محلی سازی و ذخیره سازی Asset های مرتبط است. مانند فایلهای جهانی سازی.
محلی سازی و جهانی سازی متفاوت هستند اما معانی نزدیک به همی دارند.
در این آموزش از همین روش پیروی شده است. طی این روش یک پوشهی locale تحت src/ وجود دارد. فرمت اسم فایل Asset های موجود در این پوشه با زبان مربوطهی آنها تطابق دارد.
ایجاد فایلهای ترجمه
در هر یک از سورس فایلهای ترجمه، حداقل باید یک فایل ترجمهی زبانی برای ترجمهی حاصل وجود داشته باشد.
برای این مثال:
- فایل messages.xlf را کپی کنید.
- فایل کپی شده را در پوشهی locale قرار دهید.
- برای ترجمهی انگلیسی به فرانسوی، اسم فایل را به messages.fr.xlf تغییر دهید.
اگر زبان مقصدتان متفاوت است، همین مراحل را متناسب با همان زبان تکرار کنید.
ترجمهی گرههای متنی
در پروژههای ترجمهی بزرگ، بهتر است که فایل messages.fr.xlf را برای یک مترجم فرانسوی ارسال کنید که این مترجم با استفاده از یک ویرایشگر فایل XLIFF ترجمهها را وارد کند.
ترجمهی این فایل نمونه راحت است و نیازی به ویرایشگر خاص و یا داشتن دانش خاصی از زبان فرانسوی ندارد.
-
messages.fr.xlf را باز کنید و اولین بخش < trans-unit > را پیدا کنید:
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 >
این المان XML ترجمهی سلام موجود در تگرا نشان میدهد که شما قبلاً در همین آموزش با استفاده از مشخصهی i18n آن را علامت گذاری کردید.
توجه داشته باشید که واحد ترجمهی id=introductionHeader از آیدی اختصاصیای به دست آمده است که قبلاً آن را تنظیم کردید. با این تفاوت که از پیشوند @@ در HTML استفاده نشده است. -
تگ < source / > را کپی کنید، اسم آن را target بگذارید و جای محتوای داخل آن را با سلام فرانسوی عوض کنید. اگر ترجمهی شما پیچیدهتر از این میبود، میتوانستید برای آن که انتخاب بهتری از ترجمهی فرانسوی داشته باشید، در کنار اطلاعات و زمینه از المانهای منبع، توصیف و معنی استفاده کنید.
src/locale/messages.fr.xlf (< trans-unit >, after translation) < 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 >
آیدی های تولید شده برای هر یک از این واحدهای ترجمهای توسط ابزار i18n Angular تولید شدهاند، آنها را تغییر ندهید. هر یک از آیدی ها به محتوای متن قالب و معنای اختصاص داده شده به آن وابسته هستند. اگر شما متن یا معنی را تغییر دهید، در این صورت آیدی نیز تغییر میکند. برای اطلاعات بیشتر به «بحث و بررسی نگهداری از فایل ترجمه» مراجعه کنید.
ترجمهی عبارتهای select و plural
عبارتهای آی سی یو select و plural به صورت مجزا استخراج میشوند. به همین دلیل هنگام آماده شدن برای ترجمه باید توجه ویژهای به آنها داشت. به دنبال این عبارتها بگردید به گونهای که این عبارات به واحدهای ترجمهای دیگری که در جای دیگری و در قالب منبع دیگری مشاهده کردهاید ارتباط داشته باشند. در این مثال، شما می دانید که واحد ترجمهی select حتماً باید زیر واحد ترجمهی logo قرار داشته باشد.
ترجمهی plural
برای ترجمهی یک plural باید مقادیر تطبیقی فرمت ICU آن را ترجمه کنید:
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 >
شما میتوانید حالتهای plural را اضافه و یا حذف کنید. به گونهای که هر یک از زبانها کاردینالیتی مخصوص به خود را داشته باشد. (به قوانین جمع CLDR مراجعه کنید.)
ترجمهی Select
در کد زیر محتوای مربوط به مثال عبارت آی سی یو select داخل قالب کامپوننت را میتوانید مشاهده کنید:
src/app/app.component.html
< span i18n >The author is {gender, select, male {male} female {female} other {other}}< /span >
ابزار استخراجی این عبارت را به دو واحد ترجمه تقسیم کرده است، زیرا عبارتهای ICU به صورت مجزا استخراج میشوند.
اولین واحد شامل متنی است که خارج از select قرار داشت. به جای select، placeholder، < x id="ICU" > ، وجود دارد که بیانگر پیام select است. این متن را ترجمه کنید و در صورت نیاز جای placeholder را عوض کنید، اما آن را حذف نکنید. اگر این placeholde را حذف کنید، عبارت ICU دیگر در برنامهی ترجمهی شما وجود نخواهد داشت.
src/locale/messages.fr.xlf (< trans-unit >)
< /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 >
دومین واحد ترجمه که بلافاصله زیر اولین واحد آمده است، شامل پیام 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 >
< 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 >
ترجمهی یک عبارت تو در تو
عبارتهای تو در تو مانند مثالهای قبل هستند. همان طور که در مثال قبل مشاهده میکنید، در اینجا دو واحد ترجمه وجود دارد. اولین واحد شامل متن خارج از عبارت تو در تو است:
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 >
ترجمهی کل قالب کامل شد. قدم بعدی این است که توصیف کنیم که این ترجمه چگونه باید در نرم افزار بارگیری شود.
نرم افزار و فایل ترجمهی آن
تا به اینجای کار این نمونه نرم افزار و فایل ترجمهی آن به صورت زیر در آمدهاند:
src/app/app.component.html
< h1 i18n="User welcome|An introduction header for this sample@@introductionHeader" >
Hello i18n!
< /h1 >
< ng-container i18n >I don't output any element< /ng-container >
< br / >
< img [src]="logo" i18n-title title="Angular logo" / >
< br >
< button (click)="inc(1)" >+< /button > < button (click)="inc(-1)" >-< /button >
< span i18n >Updated {minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago}}< /span >
({{minutes}})
< br >< br >
< button (click)="male()" >♂< /button > < button (click)="female()" >♀< /button > < button (click)="other()" >⚧< /button >
< span i18n >The author is {gender, select, male {male} female {female} other {other}}< /span >
< br >< br >
< span i18n >Updated: {minutes, plural,
=0 {just now}
=1 {one minute ago}
other {{{minutes}} minutes ago by {gender, select, male {male} female {female} other {other}}}}
< /span >
src/app/app.component.ts
import { Component } from '@Angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
minutes = 0;
gender = 'female';
fly = true;
logo = 'https://Angular.io/assets/images/logos/Angular/Angular.png';
heroes: string[] = ['Magneta', 'Celeritas', 'Dynama'];
inc(i: number) {
this.minutes = Math.min(5, Math.max(0, this.minutes + i));
}
male() { this.gender = 'male'; }
female() { this.gender = 'female'; }
other() { this.gender = 'other'; }
}
src/app/app.module.ts
import { NgModule } from '@Angular/core';
import { BrowserModule } from '@Angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
src/main.ts
import { enableProdMode } from '@Angular/core';
import { platformBrowserDynamic } from '@Angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);
src/locale/messages.fr.xlf
< ?xml version="1.0" encoding="UTF-8" ? >
< xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2" >
< file source-language="en" datatype="plaintext" original="ng2.template" >
< body >
< 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 >
< 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 >
< 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 >
< 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 >
< /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 >
< 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 >
< /body >
< /file >
< /xliff >
ادغام فایل ترجمه شدهی کامل در نرم افزار
برای ادغام متن ترجمه شده در قالبهای کامپوننت، نرم افزار را با فایل ترجمه شدهی کامل کامپایل کنید.
اطلاعات مربوط به ترجمهی زیر را در اختیار کامپایلر Angular قرار دهید:
- فایل ترجمه
- فرمت فایل ترجمه
- زبان (برای مثال fr یا en-US)
فرمت فایل ترجمه چه .xlf باشد چه هر فرمت دیگری که Angular آن را میشناسد (مانند .xtb)، تفاوتی در فرآیند کامپایل کردن به وجود نمیآید.
این که شما چگونه این اطلاعات را در اختیار Angular قرار دهید، به نوع کامپایلر شما (AOT یا JIT) بستگی دارد.
- اگر کامپایلر شما AOT باشد، شما اطلاعات را به عنوان پیکربندی در اختیار میگذارید.
- اگر کامپایلر شما JIT باشد، شما اطلاعات را در زمان bootstrap در اختیار میگذارید.
ادغام با کامپایلر AOT
این کامپایلر بخشی از فرآیند ساخت است که بستههای نرم افزاری آماده به اجرا، سریع و کوچک را معمولاً برای نسخههای نهایی مخصوص به مشتری ایجاد میکند.
اگر بخواهید به کمک این کامپایلر نرم افزار خود را جهانی سازی کنید، باید به ازای هر یک از زبانها، بستهی نرم افزاری مجزایی را از قبل ساخته باشید و بر اساس شناسایی زبان سمت سرور و یا پارامترهای URL بستهی مناسب را مدیریت کنید.
برای آن که به این کامپایلر به گونهای دستورالعمل دهید که از پیکربندی ترجمهی شما استفاده کند، در فایل Angular.json خود سه گزینهی پیکربندی ساخت i18n را تنظیم کنید.
- i18nFile : مسیر فایل ترجمه
- i18nFormat : فرمت فایل ترجمه
- i18nLocale : آیدی زبان
همچنین باید خروجی را به یک پوشهی مخصوص به زبان، هدایت کنید تا بتوانید با تنظیم گزینهی پیکربندی outputPath آن را جدا از دیگر نسخههای زبانی برنامهتان نگهداری کنید.
build": {
...
"configurations": {
...
"fr": {
"aot": true,
"outputPath": "dist/my-project-fr/",
"i18nFile": "src/locale/messages.fr.xlf",
"i18nFormat": "xlf",
"i18nLocale": "fr",
...
}
}
},
"serve": {
...
"configurations": {
...
"fr": {
"browserTarget": "*project-name*:build:fr"
}
}
}
میتوانید این پیکربندی را به دستورات ng serve یا ng build بدهید. در مثال زیر چگونگی رسیدگی به فایل زبان فرانسوی ایجاد شده در بخشهای قبلی این آموزش نشان داده شده است.
ng serve --configuration=fr
برای نسخههای نهایی مخصوص مشتری، باید در فایل پیکربندی سی آل آی Angular.json پیکربندی مجزای production-fr را تعریف کنید.
...
"architect": {
"build": {
"builder": "@Angular-devkit/build-Angular:browser",
"options": { ... },
"configurations": {
"fr": {
"aot": true,
"outputPath": "dist/my-project-fr/",
"i18nFile": "src/locale/messages.fr.xlf",
"i18nFormat": "xlf",
"i18nLocale": "fr",
"i18nMissingTranslation": "error",
}
// ...
"serve": {
"builder": "@Angular-devkit/build-Angular:dev-server",
"options": {
"browserTarget": "my-project:build"
},
"configurations": {
"production": {
"browserTarget": "my-project:build:production"
},
"fr": {
"browserTarget": "my-project:build:fr"
}
}
},
همین امکانات پیکربندی را میتوان از طریق CLI همراه با پیکربندی production موجود خود نیز ارائه کرد.
ng build --prod --i18n-file src/locale/messages.fr.xlf --i18n-format xlf --i18n-locale fr
ادغام با کامپایلر JIT
این کامپایلر هم زمان با بارگیری برنامه، برنامهی شما را در مرورگر کامپایل میکند. برای آن که این کامپایلر از ترجمه پشتیبانی کند، باید کارهای زیر را انجام دهید:
- فایل ترجمهی زبانی مناسب را به عنوان یک ثابت رشتهای Import کنید.
- ارائه دهندههای ترجمهی متناظر را برای این کامپایلر ایجاد کنید.
- برنامه را با کمک این ارائه دهندگان Bootstrap کنید.
این ارائه دهندگان به کامپایلر JIT می گویند که چگونه متنهای قالب را برای زبان خاصی در حال کامپایل کردن برنامه، ترجمه کند:
- TRANSLATIONS رشتهای است که شامل محتوای فایل ترجمه است.
- TRANSLATIONS_FORMAT فرمت فایل است: xlf ، xlf2 یا xtb.
- LOCALE_ID بیانگر زبان مقصد است.
متد bootstrapModule در Angular دارای پارامتر دومی به نام compilerOptions است. این پارامتر بر رفتار کامپایلر اثر میگذارد. برای مشخص کردن ارائه دهندگان ترجمه میتوانید از این پارامتر استفاده کنید:
src/main.ts
import { enableProdMode, TRANSLATIONS, TRANSLATIONS_FORMAT } from '@Angular/core';
import { platformBrowserDynamic } from '@Angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
// use the require method provided by webpack
declare const require;
// we use the webpack raw-loader to return the content as a string
const translations = require(`raw-loader!./locale/messages.fr.xlf`);
platformBrowserDynamic().bootstrapModule(AppModule, {
providers: [
{provide: TRANSLATIONS, useValue: translations},
{provide: TRANSLATIONS_FORMAT, useValue: 'xlf'}
]
});
سپس LOCALE_ID را در اختیار ماژول اصلی قرار دهید.
src/app/app.module.ts
import { LOCALE_ID, NgModule } from '@Angular/core';
import { BrowserModule } from '@Angular/platform-browser';
import { AppComponent } from '../src/app/app.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
providers: [ { provide: LOCALE_ID, useValue: 'fr' } ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
گزارش ترجمههای ترجمه
به صورت پیش فرض وقتی ترجمهای وجود ندارد، کامپایلر به نتیجه میرسد اما هشداری مانند Missing translation for message "foo" را تولید میکند. اگر میخواهید سطح هشداری که توسط کامپایلر Angular تولید میشود را پیکربندی کنید، میتوانید به صورت زیر عمل کنید:
- خطا : خطا میدهد. اگر از کامپایلر AOT استفاده میکنید، در این صورت کامپایلر با شکست مواجه خواهد شد. اگر از کامپایلر JIT استفاده میکنید، در این صورت برنامه بارگیری نخواهد شد.
- هشدار (پیش فرض) : داخل کنسول یا شِل هشداری مبنی بر 'Missing translation' را نشان میدهد.
این کار تعیین سطح هشدار در بخش configurations مربوط به Angular CLI build configuration انجام میشود. در ادامه نحوهی تعیین سطح هشدار جهت نمایش دادن خطا نشان داده شده است:
"configurations": {
...
"fr": {
...
"i18nMissingTranslation": "error"
}
}
اگر از کامپایلر JIT استفاده میکنید، در این صورت برای تعیین سطح هشدار باید به پیکربندی کامپایلر و در بوت استرپ بروید و مشخصهی 'MissingTranslationStrategy' را اضافه کنید. در مثال زیر نحوهی تنظیم سطح هشدار بر روی خطا نشان داده شده است :
import { MissingTranslationStrategy } from '@Angular/core';
import { platformBrowserDynamic } from '@Angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
// ...
platformBrowserDynamic().bootstrapModule(AppModule, {
missingTranslation: MissingTranslationStrategy.Error,
providers: [
// ...
]
});
نسخهی نرم افزاری چند زبانه
زمانی که برای ساخت برنامهی چند زبانیتان از دستورات serve یا build استفاده میکنید، با استفاده از گزینهی دستوری --outputPath (همراه با دستورات مختص به i18n) مسیر خروجی را تغییر دهید تا فایلهای ترجمه در مکان متفاوتی ذخیره شوند. اگر در حال رسیدگی به یک نسخهی مختص به زبان از یک زیر دایرکتوری هستید، میتوانید URL اصلی که توسط برنامهتان استفاده میشود را با مشخص کردن گزینهی --baseHref تغییر دهید.
مثلاً اگر وب سایت https://myapp.com/fr/ در حال رسیدگی به نسخهی فرانسوی برنامهی شما است، در این صورت مانند زیر برنامهی خود را برای نسخهی فرانسوی پیکربندی کنید:
"configurations": {
"fr": {
"aot": true,
"outputPath": "dist/my-project-fr/",
"baseHref": "/fr/",
"i18nFile": "src/locale/messages.fr.xlf",
"i18nFormat": "xlf",
"i18nLocale": "fr",
"i18nMissingTranslation": "error",
}
برای دریافت اطلاعات بیشتر در رابطه با چگونگی ایجاد اسکریپت برای تولید برنامههای چند زبانی و چگونگی تنظیم Apache 2 برای رسیدگی به این زبانها از زیر دایرکتوریهای مختلف به آموزش ارائه شده توسط فیلیپ مارتین مراجعه کنید.