์ ์ถ ์ค์ ๋๋ค ... ( "x"๋ก ํ๋ ์ ํ)
[x] feature request
ํ์ฌ ํ๋
https://github.com/angular/angular/issues/9104#issuecomment -244909246
์ ์ ํ ์คํธ์์๋ง ์๋ํ๊ธฐ ์ ์ ๋งํ๋ฏ์ด js ์ฝ๋์ ํ ์คํธ๋ ๊ตฌ๋ฌธ ๋ถ์ํ์ง ์๊ณ ํ ํ๋ฆฟ๋ง ๊ตฌ๋ฌธ ๋ถ์ํฉ๋๋ค.
์์/์ํ๋ ํ๋
API๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๋์ ์ด๋ ๊ณณ์์๋ ์ฌ์ฉ๋๋ ๋ฌธ์์ด์ ๋ฒ์ญํ ์ ์์ต๋๋ค.
์์๋๋ ๋์์ ๋ฌด์์
๋๊น?
์ค์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋
ธ์ถํ๊ธฐ ์ํด $translate.instant
์ ์ฌ์ฉ๋ฒ์ ์ฐธ์กฐํ๊ณ ์์ต๋๋ค.
if (data._current_results === data._total) {
content = this.$translate.instant('CLIPPINGS__LIST__SUMMARY_ALL', {'num': data._current_results});
} else {
if (undefined === data._total) {
data._total = '...';
}
content = this.$translate.instant('CLIPPINGS__LIST__SUMMARY', {
'num': data._current_results,
'total': data._total
});
}
// Put 'mentions' first
data = angular.merge({}, {
mentions: mentions
}, data);
_.each(data, (value:number, key:string):void => {
if (value) {
details += value + ' ' + this.$translate.instant('CLIPPINGS__LIST__SUMMARY_TYPE_' + key) + ', ';
}
});
if (details) {
details = '(' + _.trim(details, ', ') + ')';
}
content = content.replace(':details', details);
๋ ๋ง์ ์:
getExportImageName(hideExtension:boolean):string {
let fileName:string;
fileName = this.$translate.instant('D_CHART_FACET_authors__EXPORT_FILENAME', {
'profileName': this.ExportService.GetProfileName(),
'period': this.ExportService.GetPeriodString(this.SearchFilter.GetPeriodFromInterval())
});
if (!Boolean(hideExtension)) {
fileName += '.png';
}
return fileName;
}
private _getTitle():string {
if (this.inShareColumn) {
return this.$translate.instant('COMPARISONS__SHARE_COLUMN_share_of_voice_TITLE');
} else if (this.inTotalsColumn) {
return this.$translate.instant('COMPARISONS__TOTAL_COLUMN_share_of_voice_TITLE');
} else {
return _.get<string>(this.group, 'profileName', '');
}
}
this.chart = new Highcharts.Chart(<any>{
title: {
text: this.$translate.instant('REPORTS_BLOG_MAPPING_CHART_TITLE_tone').toUpperCase(),
},
xAxis: {
title: {
text: this.$translate.instant('REPORTS_BLOG_MAPPING_CHART_TITLE_tone_xaxis')
}
},
yAxis: {
min: 0,
title: {
text: this.$translate.instant('REPORTS_BLOG_MAPPING_CHART_TITLE_tone_yaxis')
}
},
plotOptions: {
scatter: {
tooltip: {
headerFormat: '<b>{point.key}</b><br>',
pointFormat: '{point.y} ' + this.$translate.instant('REPORTS_BLOG_MAPPING_CHART_mentions')
}
}
}
});
this.config = {
requiredList: true,
bannedList: false,
allowSpaces: false,
allowComma: false,
colorsType: false,
defaultEnterAction: 'required',
requiredTooltip: this.$translate.instant('D_CLIPPING_TAGS__REQUIRED_TOOLTIP'),
bannedTooltip: this.$translate.instant('D_CLIPPING_TAGS__BANNED_TOOLTIP')
};
SetWindowTitle(title:string) {
if (!!title) {
this.$window.document.title = this.$translate.instant(title);
}
}
dateHuman(date:Date):string {
return date.getDate() + ' ' + this.$translate.instant('GLOBAL_CALENDAR_MONTH_' + date.getMonth())
+ ' ' + date.getFullYear();
}
// Sort types
tmpTypes = _.sortBy(tmpTypes, (type:string):string => {
// 'MISC' at the end
if ('MISC' === type) {
return 'zzzzz';
}
return this.$translate.instant('FACET_phrases2__TYPE_' + type);
});
GetSortedLanguages():IFacetLangDetectedCommonServiceLanguageObject[] {
// We have to sort by translated languages!
return _.sortBy(_.map(this.facetOptions, (item:string):any => {
return {
key: item,
label: this.$translate.instant('FACET_langDetected_' + item),
cssStyle: (_.includes(['english', 'catalan', 'spanish', 'french', 'italian'], item))
? {'font-weight': 'bold'} : null,
flag: _.get(this.lutFlags, item, null)
};
}), (item):string => {
return item.label.toLowerCase();
});
}
getDataExportStacked(inputData:any):any {
let exportData = angular.copy(inputData);
if (angular.isArray(exportData) && exportData.length) {
exportData[0].name = this.$translate.instant('CLIPPINGS__CHARTS_volume_TITLE');
exportData[0].data = _.map(exportData[0].data, (inputDataItem:any):any => {
return {
'label': inputDataItem.association.profileName,
'value': inputDataItem.value
};
});
}
return exportData;
}
UpdateCalendarStrings():void {
Highcharts.setOptions({
lang: {
months: [
this.$translate.instant('GLOBAL_CALENDAR_MONTH_January'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_February'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_March'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_April'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_May'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_June'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_July'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_August'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_September'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_October'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_November'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_December')
],
shortMonths: [
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Jan'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Feb'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Mar'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Apr'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_May'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Jun'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Jul'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Aug'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Sep'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Oct'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Nov'),
this.$translate.instant('GLOBAL_CALENDAR_MONTH_SHORT_Dec')
],
weekdays: [
this.$translate.instant('GLOBAL_CALENDAR_DAY_Sunday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Monday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Tuesday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Wednesday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Thursday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Friday'),
this.$translate.instant('GLOBAL_CALENDAR_DAY_Saturday')
]
}
});
}
ํ๋์ ๋ฐ๊พธ๋ ๋๊ธฐ/์ฌ์ฉ ์ฌ๋ก๋ ๋ฌด์์
๋๊น?
ํ
ํ๋ฆฟ ์ธ๋ถ์์ ๋ฌธ์์ด์ ๋ฒ์ญํ ์ ์์ต๋๋ค.
๊ทํ์ ํ๊ฒฝ์ ๋ํด ์๋ ค์ฃผ์ญ์์ค.
@vicb
์ด๊ฒ์ด ์ง์ ํ ์ผ์คํ ํผ๋ผ๊ณ ์๊ฐํฉ๋๋ค. i18n์ ์ด๊ฒ์ด ๊ตฌํ๋ ๋๊น์ง ์ฌ์ฉํ ์ค๋น๊ฐ ๋์ง ์์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ฝ๋์์ ๋ฒ์ญ๋ ์ ํจ์ฑ ๊ฒ์ฌ ๋ฉ์์ง๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
@Mattes83 ์ด๋ ๊ฒ ํด๋ณด์ จ๋์?
<p [hidden]="!alertManagerRowForm.controls.sendTo.hasError('validateEmail')" class="help-error">
{{ 'ALERTMANAGER__FORM__FIELD__sendTo__ERROR__validateEmail' | translate }}
</p>
:confused: ๋ฌธ์๋ ์ฝ๋์ ์ค๋ฅ ๋ฉ์์ง๊ฐ ์๋ค๋ ๊ฒ์ด ์ผ๋ง๋ ์ข์์ง ์๋ ค์ฃผ๊ณ ๋ฒ์ญ ์ง์์ ํ ํ๋ฆฟ์ ์ด๋ค ๊ฒ์ด๋ ํ์๋ก ํฉ๋๋ค. ์ํต์ด ๋ ํ์ํ ๊ฒ ๊ฐ์ต๋๋ค.
@marcalj ๋๋ ์ด๊ฒ์ ์๊ณ ์์ต๋๋ค ...ํ์ง๋ง ๋ด ts ํ์ผ์ ํ์งํ ๋ ๋ฌธ์์ด์ด ํ์ํฉ๋๋ค.
@manklu ์ ์ ์ผ๋ก ๋์ํฉ๋๋ค
์ด๊ฒ์ด ์ง์ ํ ์ผ์คํ ํผ๋ผ๊ณ ์๊ฐํฉ๋๋ค. i18n์ ์ด๊ฒ์ด ๊ตฌํ๋ ๋๊น์ง ์ฌ์ฉํ ์ค๋น๊ฐ ๋์ง ์์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ฝ๋์์ ๋ฒ์ญ๋ ์ ํจ์ฑ ๊ฒ์ฌ ๋ฉ์์ง๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
์, ์ฌ๊ธฐ์์ ๋์ผํฉ๋๋ค. ์ ๋ OOTB ๋ชจ๋์ ์ฌ์ฉํ๋ ๊ฒ์ ์ ํธํ๊ธฐ ๋๋ฌธ์ ng2-translate์์ Angular2 i18n์ผ๋ก ์ ํํ์ผ๋ฉฐ ๋ฒ์ญ์ ์ถ์ถํ๋ ๊ฒ์ด ํจ์ฌ ์ฝ์ต๋๋ค(ng2-translate๋ IMO์ ๋ ๋ง์ ์๊ฐ์ด ์์๋จ)
์ด ๋จ๊ณ์์๋ ๋ด ์๋น์ค์์ ๋ฐ์ํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ฒ์ญํ ์ ์์ต๋๋ค. ํด๊ฒฐ ๋ฐฉ๋ฒ๋ ์์ต๋๋ค.
๋๊ตฐ๊ฐ๊ฐ ๋์์ธ ์ฌ์์ ์์ํ๊ณ ์ถ๋ค๋ฉด ๋์์ด ๋ ๊ฒ์ ๋๋ค(์: Google ๋ฌธ์๋๊ตฌ์์).
๋ชจ๋ ๊ฒฝ์ฐ๋ฅผ ๋์ดํด์ผ ํฉ๋๋ค. ๋นจ๋ฆฌ ์๊ฐํด๋ณด๋ฉด ๊ทธ๋ด ํ์๊ฐ ์์ด.
_.('static text');
_.('with {{ parameter }}', {parameter: "parameter" });
_.plural(count, {'few': '...'});
_.select(on, {'value': '...'});
์๋ ํ์ธ์ ์ฌ๋ฌ๋ถ, ๋ฉ์ง ๊ธฐ๋ฅ ์์ฒญ :+1:
*.ts ํ ์คํธ๋ฅผ ๋ฒ์ญํ๊ธฐ ์ํด ์ ์๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
@fbobbio ๋ด๊ฐํ๊ณ ์๋ ๊ฒ์ ํ
ํ๋ฆฟ์ ์จ๊ฒจ์ง ์์๋ฅผ ๋ง๋๋ ๊ฒ์
๋๋ค. ์.
<span class="translation" #trans-foo i18n>foo</span>
.
๋ค์์ ์ฌ์ฉํ์ฌ ๋ฐ์ธ๋ฉํฉ๋๋ค.
@ViewChild('trans-foo) transFoo : ElementRef;
.
๊ทธ๋ฐ ๋ค์ ๋ฒ์ญ๋ ๊ฐ์ ๊ฒ์ํฉ๋๋ค.
transFoo.nativeElement.textContent
.
์ง์ฐ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ๋ด ํ์์ ๋ง๊ฒ ์๋ํฉ๋๋ค.
ng-xi18n์ ์ด๋ฏธ ์ ์ฒด TS ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ๋ฏ๋ก (string-) ์์ฑ์ ๋ํด @i18n()
์ ๊ฐ์ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ๊ตฌํํ์ง ์๋ ์ด์ ๋ ๋ฌด์์
๋๊น? ๊ทธ๋ฐ ๋ค์ @Input()
๊ฐ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ๊ณผ ํจ๊ป ์ฌ์ฉ๋๋ ๊ฒ์ฒ๋ผ ๋ฒ์ญ๋ ๊ฐ์ผ๋ก ์ฑ์์ง ์ ์์ต๋๋ค.
๋ฒ์ญ๋์ง ์์ ๊ฐ์ ์ฝ๋์์ ์ฝ๊ฒ ์ถ์ถํ ์ ์๋ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ์ธ์์ ๋ฃ์ต๋๋ค.
@i18n( {
source : 'Untranslated value',
description: 'Some details for the translator'
} )
public set translatedProperty( value : string ) {
this._translatedProperty = value;
}
๋ฒ์ญ ๋์์ด ์์ ๋ ์์ค๋ฅผ ์์ฑ์ ์ ๊ณตํฉ๋๋ค.
์ด๊ฒ์ ์ ์ฒด ๊ตญ์ ํ ์ฃผ๊ธฐ์ธ IMO์์ ํ์ ํญ๋ชฉ์ ๋๋ค.
๋ด ๊ฐ๊ฒ์์ ์ฐ๋ฆฌ๋ ๋ฒ์ญ์๋ฅผ ์ํ ์ฌ์ ํ์ผ์ ๋ฃ์ ํ์๋ ํ ์คํธ๋ฅผ ์ฐพ๋ ๋ชจ๋ ์ ํ์ ์์ค ํ์ผ์ ํฌ๋กค๋งํ๋ "ng-xi18n - like" ๋๊ตฌ(xgettext์ ํ์ฅ์)์ ์ต์ํฉ๋๋ค.
๋๋ HTML ํ ํ๋ฆฟ์ ๊นจ๋ํ๊ณ ์ฌ์ด i18n ๋งํฌ์ ์ ์ข์ํ๊ณ Typescript ์ฝ๋์์๋ ๊ฐ์ ๊ฒ์ ๊ธฐ๋ํ์ต๋๋ค.
@vicb ๊ทํ์ ์ฌ์ฉ ์ฌ๋ก ์ธ์๋ TS ์ฝ๋์์ ๋ณด๊ฐ๋ ๋ฌธ์์ด์ ํ์งํ๋ฅผ ์ง์ํ ๊ฐ๋ฅ์ฑ์ ๋ํด ์๊ฐํ๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ์๋๋ฆฌ์ค๋ฅผ ์ง์ํ๋ ค๋ฉด TS ์ฝ๋๋ฅผ ๋ค์ ์์ฑํด์ผ ํ ์ ์์ต๋๋ค. ์ ํจํ ์ ๊ทผ ๋ฐฉ์์ด ๋ ๊น์?
์ด๊ฒ์ Angular 2๊ฐ ์ ๊ณตํ๋ ๋ฒ์ญ์ ๋ํ ๊ธฐ๋ณธ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ์ง ๋ชปํ๊ฒ ํ๋ ์ฃผ์ ๊ธฐ๋ฅ์ ๋๋ค. HTML์ ์ ์ฅ๋์ง ์์ ์ผ๋ถ ๋ฉํ๋ฐ์ดํฐ์์ ํค๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉํ๋ฐ์ดํฐ ๊ธฐ๋ฐ ๊ตฌ์ฑ ์์๊ฐ ๋ง์ด ์์ต๋๋ค. ํ์ดํ๋ฅผ ํตํด ๋๋ ์ฌ์ฉ ๊ฐ๋ฅํ TRANSLATIONS์ ๋ํด ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ๋ฒ์ญํ ์ ์๋ค๋ฉด ์ด๋ฌํ ๊ตฌ์ฑ ์์๊ฐ ์ ์ ํ ๋ฌธ์์ด์ ํ์ํ๋๋ก ํ ์ ์์ต๋๋ค.
๊ทธ ๋์ ์ฐ๋ฆฌ๋ ์ด๋ฌํ ์ ํ ๋๋ฌธ์ ng-translate์ ๊ฐ์ ๊ฒ์ผ๋ก ์ ํ๋ฉ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ด ์์ฉ ํ๋ก๊ทธ๋จ ์ ์ฒด์์ ์ฌ์ฉ๋๋ ์๋น์ค์ ๋น 'lang' ๊ฐ์ฒด๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฐ ๋ค์ div์ ๋ชจ๋ ๋ฒ์๋ฅผ ์ฝ๊ณ ํด๋น ๊ฐ์ฒด์ ๊ฐ์ ์ ์ฅํ๋ ์ง์๋ฌธ์ ์ ์ฉํฉ๋๋ค. ์จ๊ฒจ์ง ์์ฑ์ด ์๋ ํ์ด์ง ํ๋จ์ ํ ํ๋ฆฟ์ ๋ชจ๋ ๋ฌธ์์ด์ ๋ฐฐ์นํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ํ ํ๋ฆฟ ๋๋ ๊ตฌ์ฑ ์์์์ ๋ฌธ์์ด์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. ๋ณด๊ธฐ ํํ๊ณ ๋์ผํ ID๋ก ํญ๋ชฉ์ ์ฝ๊ฒ ๋ฎ์ด์ธ ์ ์์ต๋๋ค. ํ์ง๋ง ์๋ ๊ฒ๋ณด๋ค๋ ๋ซ์ต๋๋ค.
์๋น์ค
@Injectable()
export class AppService {
//Language string object.
private _lang:Object = new Object();
get lang():Object {
return this._lang;
}
}
์ง๋ น
@Directive({
selector: '[lang]'
})
export class LangDirective implements OnInit {
constructor(
public element: ElementRef,
public app: AppService) {
}
ngOnInit() {
let ele = this.element.nativeElement;
for (var i = 0; i < ele.children.length; i++) {
let id = ele.children[i].getAttribute('id');
let value = ele.children[i].innerHTML;
this.app.lang[id]=value;
}
}
}
์ฃผํ
<button>{{app.lang.myButtonText}}</button>
<div lang hidden >
<span id="myButtonText" i18n="Test Button">Testing</span>
</div>
์๋ ํ์ธ์ @lvlbmeunier
๊ณต์ ๊ตฌํ์ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ ์ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๊ทํ์ ์๋ฃจ์ ์ ๊ตฌํํ๋ ค๊ณ ํ์ง๋ง ๋์ ๋ฒ์ญ ํค๋ฅผ ์ธ์ํ ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋๋ ๋ค์๊ณผ ๊ฐ์ด ํ๋ ค๊ณ ํ๋ค.
<p *ngFor="let d of dataEntry">{{app.lang[d.name]}}</p>
<div lang hidden >
<span id="{{d.name}}" *ngFor="let d of dataEntry" i18n>{{d.name}}</span>
</div>
๊ทธ ์ ํค๋ ๋ด xliff ํ์ผ์ ํ์๋์ง ์์ต๋๋ค. ์๋ฃจ์ ์ผ๋ก ์ด๋ฅผ ๋ฌ์ฑํ ์ ์์ต๋๊น?
๋๋ ๊ทธ๊ฒ์ ์๋ํ ์ ์ด ์์ง๋ง xliff ํ์ผ์ ๋น๋๊ฐ ์ฝ๋๋ฅผ ์คํํ์ง ์๋๋ค๊ณ ๊ฑฐ์ ํ์ ํฉ๋๋ค. i18n์ ๋์ ๊ฐ์ ๊ฐ๋ ๊ฒ์ ๊ฐ๋ ์ ๋ฐ๋๋ฉ๋๋ค. ๋ชฉ๋ก์ ์๋ ๋ชจ๋ ์ด๋ฆ์ ํ์คํ ์๊ณ ์๋ค๋ฉด ๋ชจ๋ ๋ ๋ฆฝ์ ์ผ๋ก ์ ์ธํด์ผ ํ๋ฉฐ for ๋ฃจํ์์๋ ์ ์ธํ์ง ์์์ผ ํฉ๋๋ค.
ํค๋ฅผ ์๋์ผ๋ก ์ถ๊ฐํ๋ ๊ฒ์ ํจ๊ณผ๊ฐ ์์ง๋ง ๋น์ค์ฉ์ ์ ๋๋ค. ์ ๊ฒฝ์ฐ์๋ API์์ ๋ฒ์ญ์ด ํ์ํ ์๋ฐฑ ๊ฐ์ ํ ์คํธ ํค๋ฅผ ๋ฐ์์ต๋๋ค.
์ฝ๋๋ฅผ ์คํํ๊ณ ์์ค๋ฅผ ๊ฐ์ ธ์ ํ์ผ์ ๋ณต์ฌํ ์ ์์ต๋๋ค. x18n ํ์ผ์ ์์ฑ์ ์ ์ ํ์ผ์ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค.
4.0.0-beta
๋ฅผ ์ฌ์ฉํ๋ฉด i18n
์ ID๋ฅผ ํ ๋นํ ์ ์์ต๋๋ค(์: mainTitle:
<span i18n="title@@mainTitle">
์ด๊ฒ์ผ๋ก ์ต์ํ JIT ์ปดํ์ผ๋ฌ์ ๊ฒฝ์ฐ ๋ชจ๋ "์ถ๊ฐ" ๋ฒ์ญ์ ์ฌ์ฉํ์ฌ ๋๋ฏธ ๊ตฌ์ฑ ์์(์ฑ html์ ์ถ๊ฐํ ํ์๋ ์๊ณ ์ฑ ๋ชจ๋๋ง ์ถ๊ฐํ ์ ์์)๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
์ฐ์ ์ปดํ์ผ๋ฌ๋ฟ๋ง ์๋๋ผ ์ฑ ๋ชจ๋์๋ ๊ณต๊ธ์๋ฅผ ์ถ๊ฐํฉ๋๋ค.
// bootstrap.ts
getTranslationProviders().then(providers => {
const options = { providers };
// here we pass "options.providers" to "platformBrowserDynamic" as extra providers.
// otherwise when we inject the token TRANSLATIONS it will be empty. The second argument of
// "bootstrapModule" will assign the providers to the compiler and not our AppModule
platformBrowserDynamic(<Provider[]>options.providers).bootstrapModule(AppModule, options);
});
๊ทธ๋ฐ ๋ค์ ์ถ๊ฐ ๋ฒ์ญ์ ์์ฉํ ๋๋ฏธ ๊ตฌ์ฑ ์์๋ฅผ ๋ง๋ค ๊ฒ์
๋๋ค declarations
of AppModule
์ ๊ตฌ์ฑ ์์๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค. ์ด๊ฒ์ ng-xi18n
์ด html(๋ด ์๊ฐ์)์ ์ฐพ์ ๋ฒ์ญ ํ์ผ์ ์ถ๊ฐํ ์ ์๋๋ก ํ๊ธฐ ์ํ ๊ฒ์
๋๋ค.
//tmpI18N.ts
import {Component} from '@angular/core';
@Component({
selector: 'tmpI18NComponent',
moduleId: module.id,
templateUrl: 'tmp.i18n.html'
})
export class TmpI18NComponent {
}
tmp.i18n.html
์ ๋ฒ์ญ ์ถ๊ฐ:
<!-- tmp.i18n.html -->
<span i18n="test@@mainTitle">
test {{something}}
</span>
์ด์ ๋ฒ์ญ์ ๊ฐ์ ธ์ฌ ์ ์๋ ์๋น์ค๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
import {Injectable, Inject, TRANSLATIONS} from '@angular/core';
import {I18NHtmlParser, HtmlParser, Xliff} from '@angular/compiler';
@Injectable()
export class I18NService {
private _source: string;
private _translations: {[name: string]: any};
constructor(
@Inject(TRANSLATIONS) source: string
) {
let xliff = new Xliff();
this._source = source;
this._translations = xliff.load(this._source, '');
}
get(key: string, interpolation: any[] = []) {
let parser = new I18NHtmlParser(new HtmlParser(), this._source);
let placeholders = this._getPlaceholders(this._translations[key]);
let parseTree = parser.parse(`<div i18n="@@${key}">content ${this._wrapPlaceholders(placeholders).join(' ')}</div>`, 'someI18NUrl');
return this._interpolate(parseTree.rootNodes[0]['children'][0].value, this._interpolationWithName(placeholders, interpolation));
}
private _getPlaceholders(nodes: any[]): string[] {
return nodes
.filter((node) => node.hasOwnProperty('name'))
.map((node) => `${node.name}`);
}
private _wrapPlaceholders(placeholders: string[]): string[] {
return placeholders
.map((node) => `{{${node}}}`);
}
private _interpolationWithName(placeholders: string[], interpolation: any[]): {[name: string]: any} {
let asObj = {};
placeholders.forEach((name, index) => {
asObj[name] = interpolation[index];
});
return asObj;
}
private _interpolate(pattern: string, interpolation: {[name: string]: any}) {
let compiled = '';
compiled += pattern.replace(/{{(\w+)}}/g, function (match, key) {
if (interpolation[key] && typeof interpolation[key] === 'string') {
match = match.replace(`{{${key}}}`, interpolation[key]);
}
return match;
});
return compiled;
}
}
์ด์ ๋ค์๊ณผ ๊ฐ์ด ํ ์ ์์ต๋๋ค.
export class AppComponent {
constructor(i18nService: I18NService) {
// Here we pass value that should be interpolated in our tmp template as a array and
// not an object. This is due to the fact that interpolation in the translation files (xlf for instance)
// are not named. They will have names such as `<x id="INTERPOLATION"/>
// <x id="INTERPOLATION_1"/>`. And so on.
console.log(i18nService.get('mainTitle', ['magic']));
}
}
์ด๊ฒ์ ํดํน๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ต์ํ ์ฐ๋ฆฌ๋ ๋ฒ์ญ ํ์ผ์ ํ์ฉํ๊ณ , ํค๋ก ์ป๊ณ , ๋ณด๊ฐํ ์ ์์ผ๋ฉฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์จ๊ฒจ์ง html์ด ์์ด๋ ๋ฉ๋๋ค.
์ฐธ๊ณ : 4.0.0-๋ฒ ํ์ ํ์ฌ @angular/compiler-cli
NPM ํจํค์ง์๋ @angular/tsc-wrapped
์ ์๋ชป๋ ์ข
์์ฑ ๋ฒ์ ์ด ์์ต๋๋ค. 0.4.2๋ฅผ ๊ฐ๋ฆฌํค๋ฉฐ 0.5.0์ด์ด์ผ ํฉ๋๋ค. @vicb ์ด๊ฑฐ ์ฝ๊ฒ ๊ณ ์ณ์ง๋์? ์๋๋ฉด ๋ค์ ๋ฆด๋ฆฌ์ค๋ฅผ ๊ธฐ๋ค๋ ค์ผ ํฉ๋๊น?
@fredrikredflag ๊ต์ฅํฉ๋๋ค! ๊ทธ๋ฆฌ๊ณ AOT๋ ์ด๋ป์ต๋๊น?
@ghidoz AOT๋ ๋ ๋ค๋ฅธ ์ด์ผ๊ธฐ์
๋๋ค. ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์ถ์ ๊ฒ์ ๋ชจ๋ ๋ฒ์ญ์ ๋ฏธ๋ฆฌ ์ปดํ์ผํ์ฌ ํค๋ก ์ป์ ์ ์๋๋ก ํ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ngc
๋ ๋ชจ๋ i18n
๋ฅผ ์ฌ๋ฐ๋ฅธ ๋ฒ์ญ์ผ๋ก ๋์ฒดํ๋ฏ๋ก ์ด๋ฅผ ํ์ฉํ ์ ์์ต๋๋ค. ngc
์์ ๊ตฌ๋ฌธ ๋ถ์๋ ๋ฒ์ญ์ ํฌํจํ๋ ๋
ธ์ถ๋ ์ต์
/์์ฑ์ ์ฐพ์ ์ ์์ต๋๋ค. TRANSLATION
ํ ํฐ์ ์ฌ์ ํ ์ ๊ณตํ๋ xlt ํ์ผ์ ๊ฐ์ ธ์์ JIT์ ๋์ผํ ๋์ ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ AOT์ ๋ชฉ์ ์ ์ด๊ธ๋ฉ๋๋ค.
์ด๋ค ํ๋ก๋์ ์ฑ์๋ ํ์ง ๋ง์ญ์์ค .
/// bootstrap.aot.ts
function fetchLocale() {
const locale = 'sv';
const noProviders: Object[] = [];
const translationFile = `./assets/locale/messages.${locale}.xlf`;
return window['fetch'](translationFile)
.then(resp => resp.text())
.then( (translations: string ) => [
{ provide: TRANSLATIONS, useValue: translations },
{ provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
{ provide: LOCALE_ID, useValue: locale }
])
.catch(() => noProviders);
}
fetchLocale().then(providers => {
const options = { providers };
platformBrowser(<Provider[]>options.providers).bootstrapModuleFactory(AppModuleNgFactory);
});
์ด๊ฒ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ํ์ฌ ์๊ฐ:
@Component()
class MyComp {
// description, meaning and id are constants
monday = __('Monday', {description?, meaning?, id?});
}
__(...)
๋ฅผ ์ง์ํ ์ ์์ต๋๋ค./cc @ocombe
__()
๋ ์์ง ์ด๋ฆ์ด ์๋ ๋ฉ์๋์ ๋ํ ๊ฒ์
๋๋ค. (๊ทธ๋ฆฌ๊ณ ๋ฉ์๋๋ ์ค์ ๋ก __
๊ฐ ์๋๊ฒ ์ฃ ?)
ํด๋์ค์์ ์ฌ์ฉํ ์ ์๋ ์ ์ ๋ฒ์ญ์ ๋ํ ์ข์ ์์ด๋์ด์ด๋ฉฐ ๊ตฌํํ๊ธฐ๊ฐ ๋งค์ฐ ๊ฐ๋จํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
์๋์ __()
๋ ์ด๋ฆ์ด ๋ง์์ ๋ค์ง ์์ต๋๋ค :)
๋ฒ์ญ ํ๋ ์์ํฌ์์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋์ง๋ง ๋ค๋ฅธ ์ด๋ฆ์ ์ ํธํ๋ ๊ฒฝ์ฐ import {__ as olivier} from '@angular/core'
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค!
eeeeeeeh ์์ฒด ์ค๋ช
์ด ์๋๋๋ค. :D
๊ทธ๊ฒ์ ๋งค์ฐ ์ฌ์ ์ธ ๊ธฐ๋ฅ์ฒ๋ผ ๋ณด์
๋๋ค.
์ ๋ ___ ๋ฉ์๋ ์ด๋ฆ์ด ๋ง์์ ๋ค์ง ์์ต๋๋ค. :) ์๋น์ค๊ฐ ๋ ๊ฑฐ๋ผ๊ณ ์์ํ๋์?
์ด์จ๋ ๋ฐ์ ํ๋ ๋ชจ์ต์ด ๋ณด๊ธฐ ์ข๋ค์ ๐
์ข์์ __()! :D ๋งค์ฐ gettext-y์ด๋ฉฐ ์งง์ต๋๋ค.
JS ์ธ๊ณ์์๋ @ocombes ng2-translate์ ๋ํ ๊ฒฝํ๋ง ์์ต๋๋ค. ์ฌ๊ธฐ์ this._translateService.instant()๋ก ๋ชจ๋ ํ ์คํธ๋ฅผ ํ์ํ๋ฉด ์ฌ๊ธฐ์ ์ ์๋ ๊ฒ์ฒ๋ผ ์งง์ ๋์์ ๋นํด ์ฝ๋๋ฅผ ์ฝ๊ธฐ๊ฐ ๋ค์ ์ด๋ ค์์ง๋๋ค.
ng2 ๋ฒ์ญ ์๋น์ค์ ์ด๋ฆ์ __
๋ก ๋ฐ๊พธ๋ ๊ฒ์ ๋ง์ ์๋ ์์ต๋๋ค. :)
์ฌ์ค, ๋๋ DI ์๋น์ค ๋ฉ์๋๋ฅผ ๊ฐ๋จํ ํจ์๋ก ์ด๋ป๊ฒ ๋ํํ๋์ง ์ ํ ๋ชจ๋ฆ ๋๋ค. - ์ด์จ๋ , ์ ๊ฒฝ์ฐ์ง ๋ง์ธ์. ๊ทธ๊ฒ์ ์ด ๋ฌธ์ ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ฉ๋๋ค:-) ์ ์๊ฒฌ์ __๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ํ +1์ผ ๋ฟ์ ๋๋ค. ์ ์ด๋ PHP ์ธ๊ณ์์๋ ๋ค๋ฅธ ๋ฒ์ญ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํด ๋ณธ ์ ์ด ์์ต๋๋ค.
์ข์, ์๋ง๋ ___๊ฐ ๊ด์ฐฎ๊ณ "this.translationService.getTranslation()"๋ณด๋ค ํจ์ฌ ์งง์ต๋๋ค.
์, ์ํ๋ ๊ฒฝ์ฐ ์ด๋ฆ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
__(...)
i18n(...)
$๋ ์ด๋ป์ต๋๊น?
์ด๋ฆ์ ๋ํ ๋ ผ์์ ์ค๋จํ์ญ์์ค. ๊ทธ๊ฒ ์์ ์ด ์๋๋๋ค. ๊ฐ์ฌ ํด์.
monday = __('Monday', {description: 'First day of the week', id: 'firstDatOfWeek'});
๊ฐ ์๋ @vicb ๋ id๋ก ํด๊ฒฐํ ์ ์์ต๋๊น? ์:
__('@<strong i="8">@firstDatOfWeek</strong>') // Monday
๋ํ Monday
๋ ์ ์๋ ํด๋์ค์ ๊ตญํ๋๊ฑฐ๋ ์ด๋์์๋ ํด๊ฒฐํ ์ ์์ต๋๊น? "๋ซ๋ค", "์ด๋ค" ๋ฑ๊ณผ ๊ฐ์ ์ผ๋ฐ์ ์ธ ๋ฒ์ญ์ ์๊ฐํ๊ณ ์์ต๋๋ค.
๊ณต์ ๋ฆด๋ฆฌ์ค๊ฐ ์ง์ํ ๋๊น์ง AOT์ ํจ๊ป ์ฌ์ฉํ๋๋ก ๊ถ์ฅํ๋ ํ์ฌ ๊ฐ์ฅ ์ข์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ๋ฌด์์ธ์ง ๊ถ๊ธํฉ๋๋ค.
๋ฌธ์ ์ธ์ฌ,
์
Angular 2 ์ฃผ๋ฐฉ ์ฑํฌ๋: http://ng2.javascriptninja.io
๋ฐ ์์ค@ https://github.com/born2net/Angular-kitchen-sink
@vicb ์์์ด ์์ต๋๋ค ^^
์ด ๊ธฐ๋ฅ์ด ๊ตฌํ๋ ๋๊น์ง๋ ์์ฑ ๋ฒ์ญ ๊ธฐ๋ฅ ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
import {Component, Input, OnInit} from '@angular/core';
@Component({
selector: 'app-sandbox',
templateUrl: 'sandbox.html'
})
export class SandboxComponent implements OnInit {
@Input()
public title: string;
constructor() {
}
ngOnInit() {
console.log('Translated title ', this.title);
}
}
์์ ๊ตฌ์ฑ์์ ํ ํ๋ฆฟ์์:
<app-sandbox i18n-title title="Sandbox"></app-sandbox>
ํด๊ฒฐ ๋ฐฉ๋ฒ์ด์ง๋ง ์ฌ์ ํ ์ง๊ธ๊น์ง ๊ฐ์ฅ ๊นจ๋ํ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ts
title
์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
์ ๋ ์ด ๊ธฐ๋ฅ์ ๋ํ ์์ ์ ์์ํ๊ณ ์์ต๋๋ค. ๊ณง ๋์์ธ ๋ฌธ์๊ฐ ๋์ฌ ๊ฒ์ผ๋ก ๊ธฐ๋ํฉ๋๋ค :-)
์ด๊ฒ์ ๊ฐ์ฅ ๊ธฐ๋๋๋ ๊ธฐ๋ฅ์ด ๋ ๊ฒ์ ๋๋ค
์ข์ ์์์ด๋ค์. @ocombe ๊ฐ์ฌํฉ๋๋ค.
๋์์ธ ๋ฌธ์๋ https://goo.gl/jQ6tQf ์์ ๋ณผ ์ ์์ต๋๋ค.
๋ชจ๋ ํผ๋๋ฐฑ์ ๊ฐ์ฌํฉ๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
๋ฌ์ฝคํ, ์ต๋ํ ๋นจ๋ฆฌ ์ฝ์ ๊ฒ์ ๋๋ค!
@ocombe ๊ฐ์ฌํฉ๋๋ค
๋ฌธ์๋ฅผ ์ฝ์์ต๋๋ค. ์๋ฆ๋ค์ด ์์ฝ.
ts ํ์ผ์์ ๋ฌธ์์ด์ ์ถ์ถํ ์ ์๋ค๋ ๊ฒ์ ์ ๋ง ๋ฉ์ง ์ผ์ ๋๋ค.
Angular4์์ Typescript ์ ๊ทธ๋ ์ด๋๋ฅผ ์ธ์ ์ฌ์ฉํ ์ ์๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
๊ฑฐ์ ๋ชจ๋ ์ฌ๋์ด ์ด ์ ํ์ ๋ถ๋ช์ณค๊ธฐ ๋๋ฌธ์ ์ด ๊ธฐ๋ฅ์ ์ด๋ฏธ ๋ช ๊ฐ์ ๋์ ์ฌ์ฉํ ์ ์์ด์ผ ํ์ผ๋ฉฐ ์ ์ด๋ 3/6๊ฐ์์ด ๋ ์ง๋๊ธฐ ์ ์๋ ์ด ์๋ฃจ์ ์ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
ํ ํ๋ฆฟ์ Angular i18n์ ์ฌ์ฉํ๋ ๋์ ์ปจํธ๋กค๋ฌ์์ ๋ฒ์ญ์ ๊ด๋ฆฌํ๊ธฐ ์ํด ngx-translate๋ฅผ ์ฌ์ฉํ๋ ์ฌ๋์ ์ง๊ธ ์ ๋ง์ด ์๋ ์๋ ์์ต๋๋ค.
๋ชจ๋ ๊ฒ์ i18n์ ๋ณํฉํ๋ ค๋ ๋ชฉํ๋ ๋ถ๋ช ํ ํ๋ฅญํฉ๋๋ค.
๊ทธ๋ฌ๋ ๊ฐ๋ ํ๋ ์์ํฌ์์ i18n์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๋ค๋ ์ธก๋ฉด์์ ๋จ์ํ๋ฅผ ์ ์ธํ๊ณ ์ด ์ ๊ทผ ๋ฐฉ์์ด ํ์ฌ์ ngx-translate ๊ตฌํ๊ณผ ๋น๊ตํ์ฌ ์ค์ ๋ก ์ฑ๋ฅ์ ํฅ์์ํฌ๊น์?
๋ด๊ฐ ์ง๊ธ ์ดํดํ๋ ๋ฐ์ ๋ฐ๋ฅด๋ฉด ์ ์ผํ ๋ณด๋์ค๋ ์ปจํธ๋กค๋ฌ์์ ๋ฌธ์์ด์ ์ถ์ถํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
๋ํ ํ์ฌ ํฐ ์ ํ ์ฌํญ์ ๋ณต์ํ์ ๋๋ค. ์ ์ฒด ์ ๊ทธ๋ ์ด๋๋ฅผ ๋ฆด๋ฆฌ์คํ ๋ ์ ๋๋ก ์๋ํ๋์ง ํ์ธํ์ญ์์ค. xliff์ xmb๊ฐ ๋ชจ๋ ์ด๊ฒ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ i18n ๊ด๋ จ ํฐ์ผ์ ๋ง์ด ์ฝ์์ต๋๋ค. ์ด๊ฒ์ ์๋ํ๋ ์๋ฃจ์ ์ ์ ๊ณตํ๊ธฐ ์ํด ngx-translate๋ก ๋ค์ ์ ํํด์ผ ํ๋ ๋ ํ๋์ ๊ฒฝ์ฐ์ ๋๋ค.
@ocombe ์์ธํ ์ค๊ณ ๋ฌธ์์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ด๊ฒ์ ์ด ๊ธฐ๋ฅ ์์ฒญ์ ๋ํ ์ ๋ง ์ข์ ์๋ฃจ์ ์ธ ๊ฒ ๊ฐ์ต๋๋ค. ํ์ฌ ๋์์ธ์ ๋ด๊ฐ ํด๊ฒฐํ๋ ค๋ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ๋ค๋ฃจ๊ณ ์์ต๋๋ค.
ํ ๊ฐ์ง ์ง๋ฌธ: ์ค๊ณ๋ JIT ๋ชจ๋์ฉ I18N ์๋น์ค์ AOT ๋ชจ๋์ฉ TS 2.2.x Transformer์ ๋ํด ์ค๋ช ํฉ๋๋ค. ๋ณํ๊ธฐ๊ฐ ์๋น์ค ๋ฉ์๋์ ๋ํ ํธ์ถ์ ์ ์ ๋ณํ์ผ๋ก ๋์ฒดํ๊ณ I18N ์๋น์ค์ ๋ํ ๋๋จธ์ง ์ฐธ์กฐ๋ฅผ ๋ชจ๋ ์ ๊ฑฐํ๋ค๊ณ ๊ฐ์ ํ๋ ๊ฒ์ด ๋ง์ต๋๊น?
@Thommas Angular 4 ๋ TypeScript 2.1(์ฆ, ์ ๊ทธ๋ ์ด๋ ํด์ผ ํจ)์ ์ฌ์ฉํ์ง๋ง ์ค์ ๋ก๋ Angular 2 ๋๋ 4์์ ์ต์ ๋ฒ์ ์ TypeScript(์: 2.2.1)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ngx-translate์ ๋ํ ์ฑ๋ฅ ํฅ์ ์ธก๋ฉด์์ AOT๋ฅผ ์ฌ์ฉํ๋์ง ์ฌ๋ถ์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค. AOT๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋์ด์ง๋ง ์ฐจ์ด๋ฅผ ๋๋ผ์ง ๋ชปํ ๊ฒ์
๋๋ค. JIT(AOT ์์)์์๋ ์ด๋์ด ์์ต๋๋ค(์ค์ ๋ก get
์ต์ ๋ฒ๋ธ ๋๋ ๋๊ธฐ์ instant
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ต์ ๋ฒ๋ธ ๋น์ฉ์ด ๊ฐ๋จํ ํจ์ ํธ์ถ๋ณด๋ค ๋น์๋๋ค).
์ฌ๊ธฐ ์ฝ๋์์ i18n์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค. ํ
ํ๋ฆฟ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์๋ค๋ฉด ๋ฐ์ธ๋ฉ์ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ Angular i18n(AOT ๋ฐ JIT์์)์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ค์ ๋ก ๋์ ๋ณด์ด๋ ์ด๋์ด ์์ต๋๋ค. ๋ ๋ง์ ๋ฒ์ญ์ ์ฌ์ฉํ ์๋ก ๋ ๋ง์ ๊ฒ์ ์ป์ ์ ์์ต๋๋ค.
๋ณต์ํ๊ฐ ํ ํ๋ฆฟ์ ๋ํด ์ํํ๋ ๊ฒ๊ณผ ์ ํํ ๋์ผํ๊ฒ ์๋ํ๋์ง ํ์ธํ๊ฒ ์ต๋๋ค. ์ง๊ธ ํ ํ๋ฆฟ์ ๋ฌธ์ ๊ฐ ์์ต๋๊น?
@schmuli Angular๊ฐ ์ฝ๋๋ฅผ ๋์ฒดํ ์ ์๋ ์ ์ผํ ์๊ฐ์ AOT๋ฅผ ์ฌ์ฉํ ๋์
๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์๋น์ค ํธ์ถ์ด ์ฝ๋์์ ๋์ผํ๊ฒ ์ ์ง๋ฉ๋๋ค.
๊ทธ๋ฌ๋ AOT๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์๋น์ค ํธ์ถ์ ์ ์ ๋ณํ์ผ๋ก ๋์ฒด๋ฉ๋๋ค(์ฌ์ฉํ ์ ์๋ ๋ณ์๋ง ๋์ ์ํ๋ก ์ ์ง๋จ). I18n ์๋น์ค์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ๊ฑฐํ ์ง ์ฌ๋ถ๋ ํ์คํ์ง ์์ต๋๋ค. I18n ์๋น์ค๋ ํฅํ ๋ค๋ฅธ ์ฉ๋๋ก ์ฌ์ฉ๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ฝ๋ ์์ฑ์ ์์ํ๋ฉด ๋ณํ๊ธฐ๋ก ๋ฌด์์ด ๊ฐ๋ฅํ์ง ํ์ธํด์ผ ํ ๊ฒ์
๋๋ค. ์ด๊ฒ์ด ๋ฌธ์ ๊ฐ ๋ ์ฌ์ฉ ์ฌ๋ก์ ๋ํด ์๊ฐํ๊ณ ์์ต๋๊น?
@ocombe ์ฌ์ฉ๋์ง ์์ ์ถ๊ฐ DI ์ฃผ์ ์ ๊ณ ๋ คํ์ง ์๋ ํ ์ฝ๋๋ฅผ ๋จ๊ฒจ๋๋ ๊ฒ์ด ๋ฌธ์ ๊ฐ ๋๋ ์ ์ค ์ผ์ด์ค๋ฅผ ์๊ฐํ ์ ์์ต๋๋ค(์ด๊ฒ์ด ์ค์ ๋ฌธ์ ์ ๋๊น?).
์์ผ๋ก ์๋น์ค๊ฐ ๋ค๋ฅธ ์ฉ๋๋ก ์ฌ์ฉ๋ ์ ์๋ค๋ ๊ธ๊ณผ ์ฌ์ฉ์์ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ์ฌ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ ๊ณ ๋ คํ๋ฉด ์ฝ๋๋ฅผ ์์ ์ญ์ ํ์ง ์๋ ๊ฒ์ด ๋ ๋์ ๊ฒ ๊ฐ์ต๋๋ค.
์๋น์ค๋ฅผ ์ฌ์ฉํ์ฌ AOT์์ ํ์ฌ ๋ก์ผ์ผ์ ๊ฐ์ ธ์ค๋ ๊ฒ์ด ์ ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์ฌ๋ฌ ์ธ์ด๋ก ํ ์คํธ๋ฅผ ๋ฐํํ ์ ์๋ ์๋ฒ๊ฐ ์๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด ๋ณด์ญ์์ค. ๋ฐ๋ผ์ ์์ฒญ์ ํฌํจํ ํ์ฌ ๋ก์บ์ด ํ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ํญ์ ์์๋ก ๋ฒ์ญ๋ ๋ฌธ์์ด์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
@diego0020 ์ด๋ฏธ ๋ก์ผ์ผ์ ์ป์ ์ ์์ต๋๋ค. ์ฝ์ด์์ LOCALE_ID
๋ฅผ ์ฃผ์
ํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
@ocombe ๋ณต์ํ๋ xliff๋ก ๊ตฌํ๋์ง ์์ผ๋ฉฐ Google ์ธ๋ถ์ ๋๊ตฌ๋ xmb์ ํจ๊ป ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๋จ์๊ฐ ์์ต๋๋ค. ์ฐธ์กฐ: https://github.com/angular/angular/issues/13780
์ด์จ๋ , ์ง๊ธ ๋น์ฅ ์ฐ๋ฆฌ์ i18n ๊ตฌํ์ ์ฐจ๋จํ๋ ๊ฒ์ ์์ต๋๋ค. ngx-translate with pluralization pipe๋ ์ง๊ธ ๋น์ฅ์ ํ ๊ฒ์ ๋๋ค. ๋ฐ๋ผ๊ฑด๋ ๋ชจ๋ ๊ฒ์ด NG4์์ ๋ ์ข์ ๋ณด์ด๊ณ ๋ฌธ์์ ๊ฐ์ ์ฌํญ์ด ๋ฐ์๋ ๊ฒ์ ๋๋ค. ๊ฐ์ฌ ํด์.
@Thommas ICU with xliff๋ ๊ณง ์์ ๋ ์์ ์ ๋๋ค: https://github.com/angular/angular/pull/15068 ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ๋ฒ์ ์๊ณ ์ถ๋ค๋ฉด https://angular.io/docs/ ๋ฌธ์์ ์์ต๋๋ค.
์ฃ์กํฉ๋๋ค. ETA๊ฐ ์์ต๋๊น? ng4.0.0 ๋ฆด๋ฆฌ์ค์์ ์ฌ์ฉํ ์ ์๋ค๊ณ ๋ค์์ง๋ง ์๋์! ๊ฐ์ฌ ํด์
์ฐธ์กฐ @ocombe
์ฐ๋ฆฌ๋ ์ฌ์ ํ ๋์์ธ ์์
์ ํ๊ณ ์์ต๋๋ค. ๊ณ ๋ คํด์ผ ํ ์๊ธฐ์น ์์ ์ฌํญ์ด ๋ง์ด ์์ต๋๋ค(์: ๋์๊ด์ด ์์ฒด ๋ฒ์ญ์ ์ ๊ณตํ ์ ์๋ ๋ฐฉ๋ฒ), ...
์ด๊ฒ์ 4.2์์ ์์๋์ง๋ง ๋ณด์ฅ๋์ง๋ ์์ต๋๋ค.
ok ๊ฐ์ฌ ํฉ๋๋ค @ocombe , ๋ ๊ฐ์ง ์ง๋ฌธ์ด ์์ต๋๋ค.
<span i18n>This is {{myValue}}</span>
Could not mark an element as translatable inside a translatable section
@istiti
<div i18n><span i18n>my text</span></div>
- ์ข์ง ์์ต๋๋ค<div><span i18n>my text</span></div>
- ์ข์ต๋๋ค.@royiHalp
๊ฐ์ฌ ํด์
@istiti
<span i18n>This is {{myValue}}</span>
<source>This is <x id="INTERPOLATION"/></source>
<x id="INTERPOLATION"/>
๋ฅผ ๋ฌธ์ฅ์ ์ฌ๋ฐ๋ฅธ ์์น์ ๋ฐฐ์นํด์ผ ๋ค๋ฅธ ์ฌ๋๋ค์ด ๊ทํ์ ์๋ฏธ๋ฅผ ์ดํดํ ์ ์๋๋ก ๋ค์๊ณผ ๊ฐ์ด i18n ์ง์๋ฌธ์ ์ค๋ช
์ ์ถ๊ฐํ ์ ์์ต๋๋ค.Could not mark an element as translatable inside a translatable section
์ค๋ฅ๋ ๋ด๊ฐ ์ค๋ช
ํ ๋๋ก ์ค๋ฅ๋ฅผ ์ฃผ์ ๊น๊ฒ ์ฝ์ผ๋ฉด ์ด๋ค ํ์ผ์ ๋ฌธ์ ๊ฐ ์๋์ง ์ ์ ์๋ค๋ ๊ฒ์ ๊ธฐ์ตํฉ๋๋ค.@fredrikredflag ๊ฐ์ฌํฉ๋๋ค!
๊ทํ์ ์ฝ๋๋ ๋งค์ฐ ์ ์ฉํฉ๋๋ค! xliff.load
๊ฐ ์์ฆ์๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ๊ฒ ๊ฐ์์ ํ ๊ฐ์ง ๋ฌธ์ ๋ฅผ ์์ ํด์ผ ํ์ต๋๋ค. ๋ฐ๋ผ์ this._translations
๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์กฐ์ ํด์ผ ํฉ๋๋ค.
const loaded = xliff.load(this._source, '');
this._translations = loaded['i18nNodesByMsgId'] ? loaded['i18nNodesByMsgId'] : {};
์กด์ฌํ์ง ์๋ ํค๋ฅผ ์์ฒญํ๋ ๊ฒฝ์ฐ get
๋ฉ์๋์์ ์ฝ๊ฐ์ ์ ํจ์ฑ ๊ฒ์ฌ:
const placeholders = this._getPlaceholders(this._translations[key] ? this._translations[key] : []);
๋ํ ๋น i18n ๊ตฌ์ฑ ์์๊ฐ ํธ๋ฆฌ ํ๋ค๋ ธ๊ฑฐ๋ ๋ค์๊ณผ ๊ฐ์ด ํด๋น ๊ตฌ์ฑ ์์ ํ ํ๋ฆฟ์ ๋ฌธ์์ด์ ํฌํจํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
<span hidden i18n="@@MY_STRING_1">String 1</span>
<span hidden i18n="@@MY_STRING_2">String 2</span>
๋คํํ AoT๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก๋์
์์ ํ๋ฅญํ๊ฒ ์๋ํ๋๋ก ๋ด miniApp์ ์ฝ๊ฐ์ ๋ฌธ์์ด๋ง ํ์ํฉ๋๋ค.
๋ค์ ํ๋ฒ ๊ฐ์ฌํฉ๋๋ค!!!
P/S: Martin Roob์ xliffmerge ๋๊ตฌ๋ ํ์ฌ ๋ฐ๋์ ์ฌ์ฉํด์ผ ํ๋ฉฐ ๊ทธ์ TinyTranslator ๋ B-)
์ ๋ AoT ์ปดํ์ผ์ ์ฌ์ฉํ๊ณ ์ ํ๋ก์ ํธ๋ ์์ด์ ๋ฌ์์์ด์ ๋ ๊ฐ์ง ์ธ์ด๋ฅผ ์ง์ํฉ๋๋ค. ํ๊ฒฝ ๊ตฌ์ฑ์ ์ฌ์ฉํ์ฌ ๋ฌธ์ ์ ๋ํ ์์ ์๋ฃจ์ ์ ์ฐพ์์ต๋๋ค.
environments/environment.ts
ํ์ผ์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค.
import { messagesEn } from '../messages/messages-en';
export const environment = {
production: false
};
export const messages = messagesEn;
๋ํ ๋ค์ ๋ด์ฉ์ด ํฌํจ๋ environment.prod-en.ts
๋ฐ environment.prod-ru.ts
๋ ๊ฐ์ ๋ค๋ฅธ ํ์ผ์ด ์์ต๋๋ค.
import { messagesEn } from '../messages/messages-en';
export const environment = {
production: true
};
export const messages = messagesEn;
๊ทธ๋ฆฌ๊ณ ๋ฌ์์์ด์ ๊ฒฝ์ฐ:
import { messagesRu } from '../messages/messages-ru';
export const environment = {
production: true
};
export const messages = messagesRu;
๊ฐ ๋ฉ์์ง ํ์ผ์๋ ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ด ํฌํจ๋ ์ ์์ต๋๋ค.
export const messages = {
MessageKey: 'Translation',
AnotherMessageKey: 'Translation',
Group: {
MessageKey: 'Translation',
AnotherMessageKey: 'Translation',
}
};
๋ด ์ฝ๋(๊ตฌ์ฑ ์์, ์๋น์ค ๋ฑ)์์ ๋ฉ์์ง๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
import { messages } from '../../environments/environment';
๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ๋ค์ ์ฌ์ฉํ์ญ์์ค:
alert(messages.MessageKey);
.angular-cli.json
์์ ๋ค์ ํ๋ก๋์
ํ๊ฒฝ์ ์ง์ ํ์ต๋๋ค.
"environments": {
"dev": "environments/environment.ts",
"prod-en": "environments/environment.prod-en.ts",
"prod-ru": "environments/environment.prod-ru.ts"
}
ํจ๊ณผ๊ฐ์๋ค!
@alex-chuev JIT๋ก ์ด๊ฒ์ ์๋ ํ์ต๋๊น?
@ocombe ๋๋ต์ ์ธ ์ถ์ ์ ์ธ์ ๊ฐ๋ฅํฉ๋๊น?
์ข์ ๊ธฐ๋ฅ btw :)
์ปดํ์ผ๋ฌ๊ฐ ๋ณ๊ฒฝ๋ ๋๊น์ง ๋ณด๋ฅ๋๋ฏ๋ก 4.2๊ฐ ์๋๋ผ 4.3์๋ ์ ์ฉ๋๊ธฐ๋ฅผ ํฌ๋งํฉ๋๋ค.
๋๊ตฌ๋ ์ง ๋ค์ ์์์ [title]๊ณผ ๊ฐ์ด param ๊ฐ์์ i18n์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์๊ณ ์์ต๋๋ค.
์ฆ, HELLO๋ผ๋ ๋จ์ด์ ๋ฒ์ญ์ ์ถ๊ฐํ์ญ์์ค.
๋ฌธ์ ์ธ์ฌ
์
HELLO๊ฐ HTML ํ
ํ๋ฆฟ์ ์
๋ ฅํ๋ ๋ฌธ์์ด์ผ ๊ฒฝ์ฐ ๋ค์์ ์ํํ ์ ์์ต๋๋ค.
```html
````
๋ฌธ์์ ์ด์ ๋ํ ์๊ฐ ์์ต๋๋ค. ์ฌ๊ธฐ๋ฅผ ๋ณด์ธ์: https://angular.io/docs/ts/latest/cookbook/i18n.html#! #translate-attributes
๊ตฌ์ฑ ์์์ ๋ฌธ์์ด ์์ฑ์ ๋ฐ์ธ๋ฉํด์ผ ํ๋ ๊ฒฝ์ฐ ์ด ๊ธฐ๋ฅ์ ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋ ์ฌ์ฉ์ ์ ์ ๋ฒ์ญ ๋ฐฉ์์ ๊ตฌํํด์ผ ํฉ๋๋ค(๋ด๊ฐ ์๋ ํ).
@์ค์ฝค๋ฒ
์ฐ๋ฆฌ๋ ์ฌ์ ํ ๋์์ธ ์์ ์ ํ๊ณ ์์ต๋๋ค. ๊ณ ๋ คํด์ผ ํ ์๊ธฐ์น ์์ ์ฌํญ์ด ๋ง์ด ์์ต๋๋ค(์: ๋์๊ด์ด ์์ฒด ๋ฒ์ญ์ ์ ๊ณตํ ์ ์๋ ๋ฐฉ๋ฒ), ...
์ด๊ฒ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ์ด๊ฒ๋ ์ด ๊ธฐ๋ฅ์ ์ผ๋ถ์ด๊ธธ ๋ฐ๋๋๋ค. ํ์ฌ๋ก์๋ ํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๊ทํ์ ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ฒ์ญ์ ์ ๊ณตํ ์ ์๋ ๋ฐฉ๋ฒ์ ์์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋น๋ํ๋ ๋์ 1๊ฐ์ XLIFF ํ์ผ๋ง ์ง์ ํ ์ ์์ผ๋ฉฐ, ์ธ์ด๋ฅผ ๋ฒ์ญํ ์ ์๋๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฏธ๋ฆฌ ๋น๋ํด์ผ ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๋ค ์ ๋ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ต๋๋ค! ์ด๊ฒ์ ์์ด๋ฅผ ์ฌ์ฉํ์ง ์๋ ์ฒญ์ค์ ๋์์ผ๋ก ํ๋ ํ๋ก์ ํธ์ ๋งค์ฐ ์ค์ํฉ๋๋ค!
๊ทธ๊ฒ์ ํ์คํ ์ฐ๋ฆฌ๊ฐ ์ง์ํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค. ํ์ ์ฐ๋ฆฌ๊ฐ ๊ทธ๋ ๊ฒ ํ ์ ์๋๋ก ์ปดํ์ผ๋ฌ๋ฅผ ๋ฆฌํฉํ ๋งํ๋ ์์ ์ ํ๊ณ ์์ต๋๋ค :-)
๋์์ด ๋ ๋ฒ์ ์ ๋ํ ์์์ด ์์ต๋๊น? ๋๋ ๊ทธ๊ฒ์ด ์ฝ 4.3 ์ผ์ง๋ ๋ชจ๋ฅธ๋ค๋ ๊ฒ์ ์ด๋๊ฐ์์ ์ฝ์๋ค.
ํ์ํ ๋ฆฌํฉํ ๋ง(๋ฐ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ) ๋๋ฌธ์ v5 ์ด์ ์๋ ์์ ๊ฒ์ ๋๋ค.
์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์์ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ใ ์ ์ธ์ด. v5๊ฐ ์ธ์ ์ธ์ง ๊ถ๊ธํฉ๋๋ค. ๊ฐ์ฌ ํด์
@์ค์ฝค๋ฒ
@istiti ๋ณด์ฅ๋ ๋ ์ง๊ฐ ์๋๋ผ๊ณ ํ๋๊ตฐ์ ;-)
๋ฆด๋ฆฌ์ค ์ผ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. https://github.com/angular/angular/blob/master/docs/RELEASE_SCHEDULE.md
v5์ ์ต์ข
๋ฆด๋ฆฌ์ค๋ 2017โ09โ18์ด์ง๋ง ๊ทธ ์ ์ ๋ฒ ํ ๋ฐ RC๊ฐ ์์ต๋๋ค.
๊ฐ ๊ตฌ์ฑ ์์์ ๋ํด ํ๋์ ๋ก์ผ์ผ ํ์ผ์ ๋ง๋๋ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ต๋๊น? messages.xlf
๋ฉ์ด๋ฆฌ๋ฅผ ๋ง๋๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์: messages.{component}.{locale}.xlf
๋ฐ ์๋ฅผ ๋ค์ด ๊ธฐ๋ณธ ์ธ์ด์ ๊ฒฝ์ฐ messages.{component}.xlf
.
์์ง
@ocombe ๋น๋ ์๊ฐ์ผ๋ก ์ธํด ์์์ด ์๊ฒฉํ๊ฒ ์ต์ํ๋ฉ๋๋ค.
ํผ๋์ค๋ฌ์์... ์ด ๋ณ๊ฒฝ์์ฒญ/๋ณ๊ฒฝ์ด ๊ณต์ํ ๋๋ ๊ฑด๊ฐ์?
์ฌ๊ธฐ์ ๋์ผํ ๋ฌธ์ ๊ฐ ์์ง๋ง ๋ฒ์ญ์ ํ
ํ๋ฆฟ์๋ง ์ ์ฉ๋์ง ์์ต๋๋ค.
redux, ์ฌ์ฉ์ ์ ์ treeview ๊ตฌ์ฑ ์์ ๋ฑ ... ๋ชจ๋ ํ
ํ๋ฆฟ์ด ์๋ ์ฝ๋์ ์๋ฐ ์คํฌ๋ฆฝํธ ๊ฐ์ฒด์์ ์์ฑ๋จ
๊ณต์์ ์ด๋ฉฐ ๊ณง ์ถ์๋ ์์ ์ด์ง๋ง ๋จผ์ ์ปดํ์ผ๋ฌ๋ฅผ ํฌ๊ฒ ๋ณ๊ฒฝํด์ผ ํ๊ธฐ ๋๋ฌธ์ 4.3์์๋ ์ค๋น๋์ง ์์์ต๋๋ค.
์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๊ฑฐ๋ ๊ณํ ์ค์ธ ์ ํํ ๋ฒ์ ์ด ๋ฌด์์ธ์ง ์๊ณ ์์ต๋๊น? 4.3.1, 4.3.2 ... 4.3.X ?
4.x ๋ธ๋์น์๋ ๋ ์ด์ ๋ฉ์ด์ /๋ง์ด๋ ๋ฒ์ ์ด ์์ต๋๋ค(ํจ์น๋ง: https://github.com/angular/angular/blob/master/docs/RELEASE_SCHEDULE.md). ์ฆ, 5.x์ฉ์ด ๋ฉ๋๋ค. , ์ด๋ ๊ฒ์ด ํ์คํ์ง ์์ต๋๋ค.
์ด๊ฒ์ด ์ฌ์ ํ 5.x์ ํฌํจ๋ ๊ฒ์ผ๋ก ์์๋ฉ๋๊น? ๋ฒ ํ์์๋ ์๋ณด์ด๋ค์. ๊ฐ์ฌ ํด์
v5.x๊ฐ ์๋ v50.x์ ์์ ์ ์์ต๋๋ค ๐
5.x ์, ํ์ง๋ง 5.0์๋ ์์ ๊ฒ์ ๋๋ค.
๋ฅด์ฅฌ. 3 aoรปt 2017 ร 12:56, vltr [email protected] a รฉcrit :
v5.x๊ฐ ์๋ v50.x์ ์์ ์ ์์ต๋๋ค ๐
โ
๋น์ ์ด ์ธ๊ธ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ณ GitHub์์ ํ์ธํ์ธ์.
https://github.com/angular/angular/issues/11405#issuecomment-319936876 ,
๋๋ ์ค๋ ๋ ์์๊ฑฐ
https://github.com/notifications/unsubscribe-auth/AAQMorXMbyI8l6K3QA4jmXEKawiEC46xks5sUad0gaJpZM4J2pkr
.
์๋ ํ์ธ์ @ocombe ์ ๋ ์ด ์์ ์ ์ํํ๋ ํ๋ก์ธ์ค์ ๋งค์ฐ ๊ด์ฌ์ด ์์ผ๋ฉฐ ํ์ฌ ์ปดํ์ผ๋ฌ๊ฐ ์๋ํ๋ ๋ฐฉ์์ ์ด ์์ ์ ๋ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค. ํ์๋ผ์ธ์ด ์ด๋ป๊ฒ ์๊ฒผ๋์ง ๋ช ํํ๊ฒ ์ ์ ์์ต๋๊น? ์๋๋ฉด ์ด๊ฒ์ด ์ฌ์ ํ 5.0์ด ์๋๋ผ 5.x์ผ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๊น?
@arackow ์๋ง๋ 5.x์ ์์ ๊ฒ์ ๋๋ค. @vicb ๋ ๋ง์นจ๋ด ์ด๊ฒ์ ๊ฐ๋ฅํ๊ฒ ํ ์ปดํ์ผ๋ฌ์ ๋ง์ง๋ง ๋ณ๊ฒฝ ์์ ์ ํ๊ณ ์์ต๋๋ค.
@ocombe ... ํ ํ๋ฆฟ ์ธ๋ถ์ ๋ฌธ์์ด์ ๋ํ ์๋ฃจ์ ์ ๊ฐ๋ ์ ์ค๋ช ํ๋ ๋์์ธ ๋ฌธ์๊ฐ ์์ต๋๊น? ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ์๋ ๊ฒ์ด ์ข์ ํ๋ก์ ํธ ๊ฐ๋ฐ ๋จ๊ณ์ ์์ผ๋ฏ๋ก ์์ ์๋ฃจ์ ์ ์ด๋ป๊ฒ๋ ์ค๋นํ ์ ์๊ณ ๋์ค์ ์ต์ข Angular ๊ตฌ๋ฌธ์ผ๋ก ์ ํํ๋ ๊ฒ์ด ํจ์ฌ ๋ ์ฌ์ธ ๊ฒ์ ๋๋ค.
์ฐ๋ฆฌ๋ ๋์์ธ ๋ฌธ์๋ฅผ ๊ฐ์ง๊ณ ์์์ง๋ง ๊ทธ๊ฒ์ ์ปดํ์ผ๋ฌ์ ์ด์ ๋ฒ์ ์ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ ์๋ง๋ ์ฐ๋ฆฌ๊ฐ ๋๋ด๊ฒ ๋ ๊ตฌํ์ ์๋ ๊ฒ์ ๋๋ค. ์๋ก์ด ๊ตฌํ์ ๋ํ ๋ ๋์ ์์ด๋์ด๊ฐ ๋์ค๋ฉด ์๋ก์ด ๊ณต๊ณต ๋์์ธ ๋ฌธ์๋ฅผ ์์ฑํ ๊ฒ์ ๋๋ค.
@ocombe ์ด ๊ธฐ๋ฅ์ +1ํด์ผ ํฉ๋๋ค. ์ง๊ธ ๋น์ฅ ํ์ํฉ๋๋ค lol :+1: ๋๋ผ์ด ๋๊ตฌ๋ฅผ ๋ง๋ค์ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค! :)
ํ์ฌ ์ค๊ณ ๋ฌธ์๋ฅผ ์ดํดํ๊ณ ์์ผ๋ฏ๋ก AOT ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์๋ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๋ค์ํ ์์ฉ ํ๋ก๊ทธ๋จ์ ํ์ํ ๋ชจ๋ ์ธ์ด์ ๋ํ ๋ฒ์ญ์ ์ ๊ณตํด์ผ ํฉ๋๋ค.
๋ด๊ฐ ์ด๊ฒ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋๊ฐ?
์ด๊ฒ์ ์ข์ ์ง์ ์
๋๋ค @gms1.
๋๋ ์ด๊ฒ์ ์ฌ๊ธฐ์์ ์ํํ๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฑ์๋ i18n ํ๊ทธ๋ง ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ " ngfactories "๋ก ์ปดํ์ผํด์๋ ์ ๋ฉ๋๋ค(ng-conf 2017์์ Jason Aden์ ์ฐ์ค ์ฐธ์กฐ). ๊ทธ๋ฌ๋ฉด ๋ฒ์ญ ํ๊ทธ๊ฐ ๋์ฒด๋์ง ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ng xi18n
๋ช
๋ น์ ์คํํ ๋ node_modules ํด๋์ ํ์ผ์ ๋ํ xliff์ ๋ฒ์ญ๋ ์ป์ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ๋ฒ์ญ์ ์ ๊ณตํ ํ์๋ ์์ง๋ง ์ ์ฉํ ์๋ฏธ๋ฅผ ๊ฐ์ง i18n ํ๊ทธ๋ฅผ ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค.
๋์์ธ ๋ฌธ์์์ ์ธ์ฉ:
AOT์ ๊ฒฝ์ฐ ์์ค ์ฝ๋๋ ์๋น์ค ํธ์ถ์ ์ ์ ๋ฒ์ญ์ผ๋ก ๋์ฒดํ๋๋ก ๋ณํ๋ฉ๋๋ค. ์ด๋ฅผ ์ํด TypeScript ๋ณํ๊ธฐ๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค.
๊ทธ๋ ๋ค๋ฉด Angular(AOT) ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ผ๋ฐ์ ์ผ๋ก ํธ๋์คํ์ผ ํ์์ผ๋ก ์ถํ๋๋ค๋ฉด ์ด๊ฒ์ ๋ฌด์์ ์๋ฏธํ ๊น์? ์ด ๋ฌธ์์์ .metadata.json์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ฐพ์ง ๋ชปํ์ต๋๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ต์ข ์ฝ๋๋ก ์ปดํ์ผํด์๋ ์ ๋๋ฉฐ ๊ฐ๋ฐ์๊ฐ ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํ์ผํ ์ ์๋๋ก ์ค๋นํด์ผ ํฉ๋๋ค. @jasonaden ์ด ์ฌ๊ธฐ์์ ์ธ๊ธํ ๋ด์ฉ์ ์ฐธ์กฐํ์ธ์. ์ด๊ฒ์ ๋ํ i18n ํ๊ทธ๋ฅผ ์ถ๊ฐํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฒ์ญ ๊ฐ๋ฅํ๊ฒ ๋ง๋ค ์ ์์์ ์๋ฏธํฉ๋๋ค.
@gms1 ๋ด๊ฐ ๋งํ๋ฏ์ด :
์ฐ๋ฆฌ๋ ๋์์ธ ๋ฌธ์๋ฅผ ๊ฐ์ง๊ณ ์์์ง๋ง ๊ทธ๊ฒ์ ์ปดํ์ผ๋ฌ์ ์ด์ ๋ฒ์ ์ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ ์๋ง๋ ์ฐ๋ฆฌ๊ฐ ๋๋ด๊ฒ ๋ ๊ตฌํ์ ์๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ AOT ์ปดํ์ผ๋ฌ๋ v5์ ๋ํด ๊ด๋ฒ์ํ๊ฒ ๋ณ๊ฒฝ๋๊ณ ์์ผ๋ฏ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ "aot-ready" ์ฝ๋๋ฅผ ๊ฒ์ํ๋ ๊ฒ์ด ๋ ์ฌ์์ผ ํฉ๋๋ค.
i18n์ ๊ฒฝ์ฐ ์ด๋ฅผ ์ต๋ํ ์ฝ๊ณ ์ ์ฐํ๊ฒ ๋ง๋ค๊ณ ์ ํฉ๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ฌ์ฉํ ์ ์๋ ๋ฒ์ญ ํ์ผ์ ๊ฒ์ํ ์ ์์ง๋ง ์ํ๋ ๊ฒฝ์ฐ ์ฌ์ ์ํ ์๋ ์๊ณ ๋ค์๊ณผ ๊ฐ์ด ์ ๊ณตํ ์ ์์ด์ผ ํฉ๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ์ง ์๋ ๊ฒฝ์ฐ ์ถ๊ฐ ์ธ์ด
์ด ์ค๋ช ์ ๋ํด @ocombe ์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!
@ocombe ์ด๊ฒ์ ngx-translate์ ๊ธฐ๋ฅ์ ๊ฐ๋ ์์ฒด์์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๊น?
@montreal91 ngx-translate์ ์ด๋ค ๋ถ๋ถ๋ Angular๋ก ๊ตฌํ๋ ์ ์์ต๋๋ค. ์ lib๋ ๋งค์ฐ ์์งํ ์ ๊ทผ ๋ฐฉ์์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ "๋๋ถ๋ถ" ์๋ํ์ง๋ง ํ๋ ์์ํฌ์์ ํจ์ฌ ๋ ํจ์จ์ ์ด๊ธฐ๋ฅผ ์ํฉ๋๋ค.
์ฆ, angular๋ ์ ์ฌํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค(์ต์ข
๊ตฌํ์ด ๋ค๋ฅผ์ง๋ผ๋).
์ด๊ฒ์ (https://github.com/PointInside/ng2-toastr) ๊ธฐ๋ฐ์ UI ์๋ฆผ ์์คํ ์์ ์์ ํ๋ ๋์์ ์ ๊ทผ ๋ฐฉ์(FLUX)์ ๋๋ค. ๋ฌธ์ ๋ ์๋ฆผ ๋ด์ฉ์ด Angular i18n ์์คํ (xi18n)์์ ๊ด๋ฆฌํ ํ ํ๋ฆฟ์ด ์๋ ์๋น์ค ํธ์ถ์ ์ ์๋์ด ์๋ค๋ ๊ฒ์ ๋๋ค.
๋ด๊ฐ ์ํ๋ ๊ฒ์ ์๋์ง๋ง _working_ ์๋ฃจ์ ์ ๋๋ค. ๋ค์ ์ฝ๋ ์กฐ๊ฐ์์ ์์ด๋์ด๋ฅผ _์ถ์ถ_ํ ์ ์์ต๋๋ค. ๋์์ด ๋๊ธธ ๋ฐ๋๋๋ค :)
์ด๋๊ฐ์
// this call in any other component, service...
// "info" method parameter is the "id" of the HTML element in template NotificationComponent.html
this.notificationActionCreator.success("myMessage");
์๋ฆผ ๊ตฌ์ฑ ์์.ts
@Component({
selector: 'notification-cmp',
templateUrl: '../../public/html/NotificationComponent.html'
})
export class NotificationComponent implements OnInit, OnDestroy, AfterViewInit {
notificationMap: Map<string, any> = new Map();
subscription: Subscription;
constructor(private toastr: ToastsManager,
private vcr: ViewContainerRef,
private store: NotificationStore,
private elementRef: ElementRef) {
this.toastr.setRootViewContainerRef(vcr);
}
ngOnInit() {
this.subscription = this.store.payload
.subscribe((payload: NotificationStorePayload) => this.handleStorePayload(payload));
}
ngOnDestroy(): void {
this.store.destroy();
if (null != this.subscription) {
this.subscription.unsubscribe();
}
}
ngAfterViewInit(): void {
this.elementRef.nativeElement.querySelectorAll("div[notification-title][notification-text]")
.forEach(el => this.notificationMap.set(el.id, {
title: el.attributes["notification-title"].value,
text: el.attributes["notification-text"].value,
})
);
}
handleStorePayload(payload: NotificationStorePayload): void {
if (null != payload.action) {
let notification = this.notificationMap.get(payload.notification.id);
switch (payload.notification.type) {
case NotificationType.SUCCESS:
this.toastr.success(notification.text, notification.title);
break;
case NotificationType.INFO:
this.toastr.info(notification.text, notification.title);
break;
case NotificationType.WARNING:
this.toastr.warning(notification.text, notification.title);
break;
case NotificationType.ERROR:
this.toastr.error(notification.text, notification.title);
break;
}
}
}
}
์๋ฆผ ๊ตฌ์ฑ ์์.html
<div hidden
id="myMessage"
i18n-notification-title="@@notificationTitleMyMessage"
i18n-notification-text="@@notificationTextMyMessage"
notification-title="Greeting"
notification-text="Hello world"></div>
<div hidden
id="error"
i18n-notification-title="@@notificationTitleError"
i18n-notification-text="@@notificationTextError"
notification-title="Error"
notification-text="Something went wrong!"></div>
์ด์ Angular 5๊ฐ ์ถ์๋์์ผ๋ฏ๋ก i18n ๋ชจ๋์ ๋ณ๊ฒฝ ์ฌํญ์ด ์ธ์ ํตํฉ๋ฉ๋๊น?
์ด ๊ธฐ๋ฅ์ ์ต๊ทค๋ฌ ์ปดํ์ผ๋ฌ์ ๋ณ๊ฒฝ ์ฌํญ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง ์ปดํ์ผ๋ฌ๋ฅผ ๋ด๋นํ๋ ํ์ ๊ด์ฌ์ด ์ ์ ๊ฒ ๊ฐ์ต๋๋ค. ์์ ์ด๋ PR ๋๋ ์ปค๋ฐ์ฒ๋ผ ๋ณด์ด์ง ์์ต๋๋ค:- (. ์ฃ์กํฉ๋๋ค. ํ์ง๋ง ๋ค๋ฅธ ๋ชจ๋ ๋ฒ์ญ ํ๋ ์์ํฌ์ ์๋ ๋งค์ฐ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋ฅ์ ์ค๋ช ํ๋ ์ด ๊ธฐ๋ฅ ์์ฒญ์ ์ด์ 1๋ ์ด ๋์์ต๋๋ค. ์ด ํ์ ๊ธฐ๋ฅ์ด ๋์ฐฉํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ์ ์ด๋ 5.x์์๋...
์๋ค์ ์นจ์ฐฉํด๋ผ AOT ์ปดํ์ผ๋ฌ์ ๊ตฌํํ๋ ๊ฒ์ ์ด๋ฆฌ์์ ์ผ์ด ์๋๋๋ค. @ocombe ๋ ๋ค์๊ณผ ๊ฐ์ด ๋งํ์ต๋๋ค.
"์๋ง๋ 5.x์ ์์ ๊ฒ์ ๋๋ค. @vicb ๋ ๋ง์นจ๋ด ์ด๊ฒ์ ๊ฐ๋ฅํ๊ฒ ํ ์ปดํ์ผ๋ฌ์ ๋ํ ๋ง์ง๋ง ๋ณ๊ฒฝ ์์ ์ ํ๊ณ ์์ต๋๋ค."
์, ์ฐ๋ฆฌ๋ ์ง๊ธ ์ฒซ ๋ฒ์งธ ๋จ๊ณ์ธ ๋ฐํ์ i18n์ ์์
์ค์
๋๋ค.
๋ฐํ์ i18n์ ๋ค์์ ์๋ฏธํฉ๋๋ค. ๋ชจ๋ ์ธ์ด์ ๋ํ ํ๋์ ๋ฒ๋ค, AOT ์ปดํ์ผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ i18n์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ๋์ค์ ๋ฐํ์์ ์ธ์ด๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ๊ทธ๊ฒ์ ๋ํ ์ฐ๋ฆฌ๊ฐ ๋ฐํ์์ ๋ฒ์ญ์ ํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์ด๊ฒ์ ์ฝ๋ ๋ด๋ถ์ ๋ฒ์ญ์ ํ์ํฉ๋๋ค(์๋ํ๋ฉด ๋ฒ์ญ์ ์ํ ๋ฐํ์ ํ์๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์
๋๋ค...).
์ด๊ฒ์ด ์๋ฃ๋๋ฉด ๋ค์ ์ฐ์ ์์๋ ์ฝ๋ ๋ด๋ถ์ ๋ฒ์ญ์ด ๋ ๊ฒ์
๋๋ค.
๊ทธ๋ฌ๋ typescript ๋ณํ๊ธฐ๋ฅผ ์ฌ์ฉํ๋๋ก ์ปดํ์ผ๋ฌ๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ์ ์๋ ๋ฐํ์ i18n์ ์ํํ ์ ์์์ต๋๋ค(5.0์์ ์ํ๋จ).
์ด๋ค 5.x ๋ฒ์ ์ ์ด๋ค i18n์ด ๊ฐ์ ๋ ์ง ์์ญ๋๊น? 5.0.0 ์์ฒด์ ํจ๊ป ์ถ์๋๋ ๊ฒ์ด ์์ต๋๊น?
5.0:
5.1 ๋๋ 5.2(์๊ธฐ์น ์์ ์ฐจ๋จ๊ธฐ๊ฐ ์๋ ๊ฒฝ์ฐ):
5.x:
๊ทธ๋ฆฌ๊ณ ์ถ๊ฐํ ์์ ์ด์ง๋ง ์์ง ๊ฒฐ์ ๋์ง ์์ ๊ธฐํ ์ฌํญ(https://github.com/angular/angular/issues/16477์ ํ๋ก์ฐํ ์ ์์).
์กฐ๊ธ ๋ฆ์์ง๋ง TS ํ์ผ์์ i18n ์ง์์ ๊ณ ๋ คํ๋ ๊ฒ๋ง์ผ๋ก๋ ์ฃผ์ ๊ตฌ๋ฌธ์ ๋ํด ์๊ฐํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? (๋๊ตฐ๊ฐ๊ฐ ์์์๋ ์ธ๊ธํ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค)
์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
@i18n (id='message1')
message1 = "๋ฒ์ญํด์ผ ํ ๋ฉ์์ง์
๋๋ค.";
@i18n (id='๋์ ๋ฉ์์ง')
dynamicMessage = "์ด๊ฒ์ {0}์ด(๊ฐ) ํฌํจ๋ ๋์ ๋ฉ์์ง์
๋๋ค.";
dynamicMessage์ ๋ํ ์ฃผ์์ ์ฌ์ฉํ๋ฉด ์ด๋ฆ์ด format ์ธ ์ด ๋ฌธ์์ด ์ธ์คํด์ค์ ์ฃผ์์ ํตํด ํจ์๋ฅผ ์ฃผ์
ํ ์ ์์ผ๋ฉฐ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
var finalMessage = dynamicMessage.format('๊ฐ1')
๋ช ๋ช ๋ ๋งค๊ฐ๋ณ์ ๋ฑ์ ์ฒ๋ฆฌํ๋ ๋ฐ ๋น์ทํ ์ ๊ทผ ๋ฐฉ์์ด ๊ฐ๋ฅํฉ๋๋ค.
์ข์ ๊ฐ๋ฐ์ ๊ฒฝํ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ํ ์ง๋ฌธ์ด ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ปดํ์ผ์ ๋ํ ์ง๋ฌธ์ ๋๋ค.
๋ํ message1์ ๋ค๋ฅธ ๋ฌธ์์ด๋ก ๋ณ๊ฒฝํ๋ฉด ์ด๋ป๊ฒ ๋ฉ๋๊น? ๋ชจ๋ i18n ๋ณ์๋ ํญ์ ์์์ฌ์ผ ํฉ๋๋ค. ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ํ ํจ๊ณผ๊ฐ ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ์๋ฅผ ๋ค์ด Symfony์๋ JS ๊ตฌ๋ฌธ์์ ๋ค์๊ณผ ๊ฐ์ด ์๋ํ๋ ๋ฒ์ญ ๊ธฐ๋ฅ์ด ์๋ ๋ฒ์ญ ์๋น์ค๊ฐ ์์ต๋๋ค. let translated = this.translator.trans('Hello %name%', [{'%name%': nameVariable}]);
๊ฒฐ๊ณผ: <source>Hello %name%</source> <target>Bonjour %name%</target>
@MickL ํ์ฌ -aot ๋ฒ์ญ์ ์์ ์ ์ต์ํ์ ํจ์จ์ ์ธ ํ๋ก๊ทธ๋จ์ ๋ง๋๋ ๊ฒ์
๋๋ค. ์ด๊ฒ์ด ๋์ ๋ฒ์ญ์ ๋ํ ์ ๊ทผ ๋ฐฉ์์ด ์์ง ์กด์ฌํ์ง ์๋ ์ด์ ์
๋๋ค.
๋๋ ์ฐ๋ฆฌ๊ฐ ๋ฌธ์์ด์ ๋ฒ์ญํ๊ธฐ ์ํด ๋ค์ด๋๋ฏน ์๋น์ค๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๋ ์ ์์ ํ์ฌ์ ์ ๊ทผ ๋ฐฉ์์ด ์ ๋ง ํ๋ฅญํ๋ค๊ณ ๊ตณ๊ฒ ๋ฏฟ์ต๋๋ค. ์ฆ, ์ผ๋ถ ํ
์คํธ๊ฐ ์ ์ ์ด๋ผ๋ ๊ฒ์ ์๊ณ ์๋ค๋ฉด ์๋น์ค๋ฅผ ์ฌ์ฉํ์ง ์๋ ๋ฐฉ์์ผ๋ก ๋ฒ์ญํ์ญ์์ค.
๋์ ๋ฒ์ญ์ ๋ฌธ์ ๋ ๊ฐ๋จํฉ๋๋ค. ๋ฌธ์์ด์ ํ์ํ ๋๋ง๋ค ๋ฌธ์์ด์ ๋ฒ์ญํ๋ ค๋ ๊ฒฝ์ฐ์
๋๋ค. ์ ๋ง ์ข์ ๋ฐฉ๋ฒ์ ์๋์ง๋ง,
์์?
๋ด ๊ด์ ์์ ๋ฏธ๋์ ์๋ฃจ์ ์ ๋ค์๊ณผ ๊ฐ์์ผ ํฉ๋๋ค.
์๊ฐํด ๋ณด์ธ์. ํ์ํ ๋์ ํ ์คํธ๊ฐ ์ ๋ง ์๋ค๋ฉด ๋ฐฑ์๋์์ ๋ฐ์ ์ ์๊ณ "๋์ ํ ์คํธ"์ ๋ณต์ฌ๋ณธ์ด ์ ๋ง๋ก ํ์ํ ๊ฒฝ์ฐ ํญ์ ์บ์๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ ์๊ฐ์๋ ๋ ์ด์ ์ด ๋ฌธ์ ๋ฅผ ๋ ผ์ํ ํ์๊ฐ ์์ต๋๋ค. ์ค์ ๋ก i18n์์ ํํ์์ผ๋ก ์ผํ๋ ์ฌ๋(Olivier Combe)์ด ์์ต๋๋ค. AOT๋ ๋งค์ฐ ํน๋ณํ๋ฉฐ ์ด ๋ฌธ์ ๋ฅผ ๊ฐ๋ฅ์ ๊ฐ๊น๊ฒ ๋ง๋ค๊ธฐ๊น์ง ๋ง์ ์์ ์ ์ํํด์ผ ํ์ต๋๋ค. ๊ณง ๋์ ๋ฒ์ญ์ด ๊ฐ๋ฅํด์ง๋๋ค. ๋ ์ด์ ๊ฐ ์ธ์ด๋ฅผ ๋ณ๋๋ก ๊ตฌ์ถํ ํ์๊ฐ ์์ต๋๋ค! ์ด ์์ ์ด ์๋ฃ๋๋ฉด ๋์ค์ ์ฝ๋ ๋ด์์ ๋ฒ์ญ(์ด ๋ฌธ์ )์ ๊ฐ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ ์ด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ ๋๊น์ง ์์ผ๋ก ๋ฐ๋ ์ด ๊ฑธ๋ฆด ๊ฒ์ด๋ผ๊ณ ๋งํ๋ค.
๊ด์ฌ์ด ์์ผ์๋ฉด 07.11.17์ Angular Connect์์ Angular์์ i18n์ ํ์ฌ์ ๋ฏธ๋์ ๋ํ ์ฐ์ค์ ํ์ธํ์ธ์. https://youtu.be/DWet6RvhHWI?t=21m12s
์ด๊ฒ์ typescript ํ๊ทธ๊ฐ ์ง์ ๋ ํ ํ๋ฆฟ ๋ฌธ์์ด์ ๋ํ ์ข์ ์ฌ์ฉ ์ฌ๋ก์ฒ๋ผ ๋ณด์ ๋๋ค...
์ด๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ๋์๊ฐ๋ฉ๋๋ค. ๋๋ ์ด ์ค๋ ๋๋ฅผ ๋งค๋ฌ ํ ๋ฒ ๋ฐฉ๋ฌธํ์ฌ ์งํ ์ํฉ์ ํ์ธํ๊ณ ๊ธฐ๋์น๊ฐ ๋ฎ์์ ธ ์ค๋ง์ ๋ฉ์ท์ต๋๋ค. ๊ฐ๋ฐ์๊ฐ ์ํ๋ ์ ์ผํ ๊ฒ์ ํ ํ๋ฆฟ์์์ ๊ฐ์ด ์ฝ๋์์ ๋ฌธ์์ด ๋ฒ์ญ์ ๋ํด ๋์ผํ ์ต์ ์ ๊ฐ๋ ๊ฒ์ ๋๋ค. ๋ด ์ฝ๋๋ ์ด๋ฌํ ๊ธฐ๋ฅ ๋ถ์กฑ์ผ๋ก ์ธํด ์จ๊ฒจ์ง ๋ฒ์ญ๋ ํ ํ๋ฆฟ ๋ฌธ์์ด๋ก ๊ฐ๋ ์ฐจ ์์ต๋๋ค. ์ด๊ฒ์ด ๊ฒฐ๊ตญ ์๋น์ค ๋๋ ์ฃผ์์ผ๋ก ์ํ๋๋์ง ์ฌ๋ถ๋ ๊ด๋ จ์ด ์์ผ๋ฉฐ ์ถ๊ฐ๋ก ๋ฐ๋ฆฌ์ด๊ฐ ์์๋๋์ง ์ฌ๋ถ๋ ์ค์ํ์ง ์์ต๋๋ค. ์ฝ๋์์ ๋ฌธ์์ด์ ์ ํํ ๋ ๋ณ๊ฒฝ ์ฌํญ์ด ์๋์ง ์ด๋ฏธ ๋ณด๊ณ ์์ต๋๋ค . ์ ์ผํ ์๊ตฌ ์ฌํญ์ ์ฝ๋๊ฐ ๊ตฌ๋ฌธ ๋ถ์๋๊ณ ๊ด๋ จ ๋ฌธ์์ด์ด ๋ด ํ ํ๋ฆฟ ๊ธฐ๋ฐ ๋ฒ์ญ๊ณผ ๋์ผํ ํ์์ ๋์ผํ ํ์ผ๋ก ๋๋๋ ๊ฒ์ ๋๋ค.
@eliasre ์ฝ๋ ๋ฒ์ญ์ด ๊ธํ ๊ฒฝ์ฐ https://github.com/ngx-translate/i18n-polyfill ์ ์๋ํ ์ ์์ต๋๋ค.
๊ทธ๊ฒ์ด ๊ฐ์ ๊ฒ์ด๋ผ๋ ์ฝ์์ ์์ง๋ง ์ค์ ๋ก๋ ์๋ง๋ ๋ค๋ฅผ ๊ฒ์
๋๋ค(์ฌ์ฉํ๊ธฐ ์ฝ๊ธฐ ๋๋ฌธ์), ์ง๊ธ ๊ฐ๋ฅํ ๊ฒ์ ์ ํ์ด ์์ต๋๋ค... ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉํ ์ฑ์ ~80ko๋ฅผ ์ถ๊ฐํ ๊ฒ์
๋๋ค ๊ทธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๊ธฐ๋ค๋ฆฌ์ง ์์ผ๋ ค๋ฉด ngx-translate๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
@ocombe ์ฌ์ฉํ ํ๋ฌ๊ทธ์ธ์ด๋ ํ๋ ์์ํฌ์ ๋ํ ๊ฒฐ์ ์ ๊ธฐ๋ค๋ฆด ๋ ๊ฐ๋ฐ ์ผ์ ์ ๋ฐ๋ผ ์ถ์ ํ๊ณ ๊ณํํ ์ ์๋๋ก ์งํ ์ํฉ์ ๋ํ ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ณตํด ์ฃผ์๊ฒ ์ต๋๊น? ๊ทธ๊ฒ์ ๋งค์ฐ ๋์์ด๋๊ณ ๊ฐ์ฌ ํ ๊ฒ์ ๋๋ค
@eliasre ๊ตฌ๊ธ์ด ํ๋ฒ์ ์ข์ ์๋ฃจ์ ์ ๋ง๋ค๊ณ ์ถ๋ค๋ ์๊ฐ์ด ๋ญ๋๋ค. ์์ผ๋ก๋ ๋ณํจ์์ด. ์ฐ๋ฆฌ๊ฐ ์๊ฐํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋ ์ค๋ ๊ฑธ๋ฆฐ๋ค๋ ๋ฐ ๋์ํฉ๋๋ค.
๊ฐ๋ํ @ocombe ๋ฅผ ๊ดด๋กญํ์ง ๋ง์ญ์์ค. ๊ทธ๋ ๋งค์ฐ ์ด์ฌํ ์ผํ๊ณ ์์ต๋๋ค!
๊ณ์ ํด! :)
์ ๊ฐ ์ด ๊ธฐ๋ฅ์ ํ๋ ์ฌ๋์ด ์๋๊ณ ํด์ผ์ด๋ผ ๋ ์๊ฒ ๋๋๋๋ก ์๋ ค๋๋ฆฌ๊ฒ ์ต๋๋ค
@ocombe ๊ฐ์ฌํฉ๋๋ค
@ocombe ๊ฐ์ฌํฉ๋๋ค. ์ ๋ฐ์ดํธ๊ฐ ์์ผ๋ฉด ์ฌ๊ธฐ์์ ํฌ๊ฒ ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ๋๋ ์ง๋ ๋ช ๋ฌ ๋์ ๋ฐํ์ i18n์ ๊ฐ์ ํ ๊ธฐ๋ค๋ ธ๊ณ ๋ง์ง๋ง ๋น๋ ETA๋ 5.2์์ต๋๋ค. ์ ๋ฐ์ดํธ๋ ETA๋ฅผ ์ฌ๊ธฐ์์ ์๋ ค ์ฃผ์๊ฒ ์ต๋๊น?
๋์ง๊ธฐ๊ฒ ํด์ ๋ฏธ์ํ์ง๋ง 20๊ฐ ์ธ์ด๋ก ๋น๋ํ๋ ๊ฒ์ ํ์ฌ๋ก์๋ ์์ฒญ๋๊ฒ ๋๋ฆฝ๋๋ค.
Angular 5.2๊ฐ ๋์๊ณ ๋ถํํ๋ i18n ๊ณผ ๊ด๋ จ๋ ๊ฒ์ ์ฐพ์ ์ ์์์ต๋๋ค. i18n์ ๋ํ ๊ทํ์ ๋ ธ๋ ฅ์ ๋ํด ๋ง์ด & thx ๋ง์ด!
@ocombe ๋ ์ฐ๋ฆฌ๊ฐ ์ฌ๊ธฐ์ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ ์ฌ๋์ด ์๋๋๋ค... ์ด ๋๊ธ์ YouTube ๋งํฌ๋ฅผ ํ์ธํ์ธ์: https://github.com/angular/angular/issues/11405#issuecomment -343933617
๊ณํ์ ์ง์์ ์ผ๋ก ๋ฐ์ ํ๊ณ ์์ต๋๋ค. ๋ด๊ฐ ๊ฐ๋ฅํ ์ถ์ ๋ ์ง๋ฅผ ์ค ๋๋ง๋ค ๋ค๋ฅธ ๊ฒ์ด ์ฐ์ ์์๋ฅผ ์ป๊ฑฐ๋ ํ์๊ฐ ๋์ด ๋ ์ง๋ฅผ ๋ค์ ํ ๋ฒ ๋ณ๊ฒฝํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ๊ธฐ๋ค๋ ค์ฃผ์ ์ฌ๋ฌ๋ถ๊ป ์ผ๋ง๋ ์ค๋ง์ค๋ฌ์ด์ง ์ ์๊ณ ์์ผ๋ฉฐ ์ฐ์ ์์๋ฅผ ๋์ด๊ธฐ ์ํด ์ต์ ์ ๋คํ๊ณ ์์ต๋๋ค.
๋ด์ผ i18n ๋ฐฑ๋ก๊ทธ/๊ณํ์ ๋ํด ๋
ผ์ํ๊ธฐ ์ํ ํ์๊ฐ ์์ต๋๋ค. ์๋ก์ด ์์์ด ์์ผ๋ฉด ์๋ ค ๋๋ฆฌ๊ฒ ์ต๋๋ค.
@ocombe ์ด๋ฒ๋ฌ ์ i18n ์ถ์๋๋ฉด ์์ ๋งฅ์ฃผ 24ํฉ ์ฌ์ค๊ฒ
Angular Elements ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ง์์ด ๋ฌด์์ ํ๋์ง ๋ฌป๋๋ค๋ฉด ๋ ์ผ ๋งฅ์ฃผ 24๋ณ๊ณผ 24๋ณ์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค. ๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์ง ์ ๋ณด๋ฅผ ์ป์ง ๋ชปํ๋ ์ ์ฅ.
@ocombe ๊ฐ๋น์ผ ์์ ๋งฅ์ฃผ 72๋ณ์ ๊ตฌ์ ํ๊ณ ๊ฐ๋ฐ ์ปค๋ฎค๋ํฐ๋ฅผ ํ๋ณตํ๊ฒ ํ ์ ์๋ ์ผ์์ ํ ๋ฒ๋ฟ์ธ ๋๋ฌธ ๊ธฐํ์ ๋๋ค. ๋น์ ์ด ์ด๊ฒ์ ์ฑ์ทจํ๋ค๋ฉด ์ฐ๋ฆฌ๋ ์ฐ๋ฆฌ์ ์ฝ์์ ์ดํํ ๊ฒ์ ๋๋ค ์น๊ตฌ.
@MickL Angualr Elments, ๋ด๊ฐ ์ดํดํ๋ ๊ฒ์ฒ๋ผ SPA๊ฐ ์๋ ํ์ด์ง๋ฅผ ๋น๋ํ๊ณ ๊ฐ๋ ๊ตฌ์ฑ ์์๋ฅผ ๊ธฐ๋ณธ ์์(์์ฒด ์์ ฏ์ผ๋ก๋ ์ฌ์ฉ)๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ค ์๊ฒ ์ต๋๋ค. ์ด๊ฒ์ ๋ชจ๋๊ฐ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ 2๊ฐ์ ๋ค๋ฅธ ๊ธฐ๋ฅ์ด์ง๋ง ์ํ๊ฐ ๋ฌด์์ด๋ฉฐ ์ธ์ ์์ํ ์ ์๋์ง๋ ์๋ฌด๋ ๋ชจ๋ฆ ๋๋ค...
๋๊ตฐ๊ฐ๊ฐ ๋ง์ง๋ง 27๋ณ์ ๋งฅ์ฃผ๋ฅผ ์ถ๊ฐํ๊ฒ ๋ค๊ณ ์ฝ์ํ๋ค๋ฉด, ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ๋ค์ ์
์ ์์ต๋๋ค!
http://www.99-bottles-of-beer.net/language-javascript-1948.html
@ocombe ๋ฅผ ์ถ๊ฐํ๊ฒ ์ต๋๋ค : ์ข์ํ๋ ๋ธ๋๋ ์ด๋ฆ์ ์ง์ ํ์ธ์ :D
ํธ์ง : ๋๊ตฐ๊ฐ beerbounty :p๋ผ๋ eth bounty์ ์ ์ฌํ ์๋น์ค๋ฅผ ๋ง๋ญ๋๋ค.
์ฝ์๋๋ก ์ฝ๊ฐ์ ์
๋ฐ์ดํธ: ์ฐ๋ฆฌ๋ ์ฌ์ ํ v6์์ ๋ฐํ์ i18n์ ์ถ์ํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๊ณ ์์ต๋๋ค. ๊ทธ๊ฒ์ ์งง์ ๊ฒ์ด๊ณ ์๋ง๋ ๋ง์ง๋ง ๋ฆด๋ฆฌ์ค ์ค ํ๋์ ์ถ๊ฐ๋ ๊ฒ์ด๋ฉฐ ํ๋๊ทธ ๋ค์ ์์ ๊ฒ์
๋๋ค.
๋ฐํ์ i18n์ ์ฝ๋ ๋ฒ์ญ๊ณผ ํจ๊ป ์ ๊ณต๋์ด์ผ ํฉ๋๋ค. ์๋ํ๋ฉด ๊ทธ๊ฒ์ด ์ด์จ๋ ํ
ํ๋ฆฟ์์๋ ์๋ํ๋ ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์
๋๋ค(๋์ผํ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํด์ผ ํจ).
๋ค๋ง, ์๋น์ค๊ฐ 100% ์ค๋น๋ ์ง๋ ๋ฏธ์ง์์ด๋ฉฐ, ์ถ์ ์งํ ์ค๋จ๋์ง ์๋๋ก ํ๋ ๊ฒ์ด ์ณ์ ์ ํ์ด๋ผ๊ณ ํ๋จ๋๋ฉด ์ฐ๊ธฐํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ ์ด๋ค ๊ฒฝ์ฐ์๋ ๋ฐํ์ i18n์ ๋ฐ๋ฅผ ๊ฒ์ด๋ฉฐ(์ด๊ฒ์ด ์ฐ๋ฆฌ์ ๋ก๋๋งต์
๋๋ค) ํ๋๊ทธ ๋ค์ ์์ ๊ฒ์ด๊ณ ์ด์จ๋ ์๋ฌด ๊ฒ๋ ๊นจ๋จ๋ฆฌ์ง ์์์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ฆด๋ฆฌ์คํ๊ธฐ ์ํด ์ฃผ ๋ฒ์ ์ด ํ์ํ์ง ์์ต๋๋ค.
์ ๋ ๊ณต๊ฐํ๋ ๊ฒ์ ๋ฐฉํดํ ์ ์๋ ๊ฒ:
- 3๋ ๋์ PascalPrecht์ ๋ฒ์ญ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด ์จ AngularJS ์์ ๊ฐ๋ฐ์์ ๋๋ค.
- ๋๋ฅผ ํฅ๋ถ์์ผฐ๋ค. ์ต๊ทค๋ฌ2 ์ ์ธ. ์์งํ๊ฒ ํ์ https://angular.io/guide/i18n
- i18n์ ๋ด ์ ๋ฌธ ํ๋ก์ ํธ์ ์ฑ๊ณต์ ์ผ๋ก ํตํฉ
- 100+kb xlf ํ์ผ๋ก ํฌํ ํ๋ ๋ชจ๋ ํ๋ก ํธ ์๋ ํ๋ ์ฝ๋ฉ ๋ ์ด๋ธ์ ์ด์ง๋ฝํ๋ ๋ฐ ํ๋ฃจ ์ข ์ผ ์๋น
- ng ์๋น์ค ๋ด์์ ์์ ๋ ์ด๋ธ์ ๋ฒ์ญํด์ผ ํ๋ ๊ฒฝ์ฐ
- ๊ตฌ๊ธ์์ ์ฐพ์๋ณด๋ฉด ์ฌ๊ธฐ ์์ด
Angular 6์๋ ์ด์ ์๋ ํด๊ฒฐ์ฑ ์ด ์๋ค๋ ๊ฒ์ ์์๋ด์ญ์์ค.- ๋ rn
@Macadoshis ์ง๊ธ์ ๋ด polyfill ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. https://github.com/ngx-translate/i18n-polyfill
@Macadoshis ๋ ์ด์ alpha.46 ์ดํ๋ก ์ฐ๋ฆฌ๊ฐ ๊ฒช์๋ ์ผ์ ์์ํด ๋ณด์ธ์! ;)
i18n-polyfill @ocombe ๋ฅผ ์๋ ค์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค. ํ์ง๋ง ๋ฒ์ญ ํค์ ๋น๋๊ธฐ ๋ก๋๋ฅผ ์ง์ํ๋ฏ๋ก ngx-translate ๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
TRANSLATIONS
์ ๊ณต์๋ฅผ ์ํ i18n-polyfill ํฉํ ๋ฆฌ๋ ๋ถํธ์คํธ๋ฉ ์ด์ ์ ์๋ ค์ง ๊ณ ์ ๋ก์ผ์ผ์ ๋๊ธฐํ ์์ ๋ก๋ฉ๋ง ์ง์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
// sync loading
return require(`raw-loader!../locale/messages.${locale}.xlf`);
// @ngx-translate/i18n-polyfill/esm5/ngx-translate-i18n-polyfill.js
Tokenizer.prototype._advance = function () {
//...
this._index++;
// "this._input" needs to be a string and can't handle a Promise or an Observable
this._peek = this._index >= this._length ? $EOF : this._input.charCodeAt(this._index);
this._nextPeek = this._index + 1 >= this._length ? $EOF : this._input.charCodeAt(this._index + 1);
}
@ocombe ๋น์ ์ด ์์ฑํ ํด๋ฆฌํ์ด ์ถ์๋๋ ๊ฒ์ ์ผ๋ง๋ ๊ฐ๊น์ต๋๊น? ์ฐ๋ฆฌ๊ฐ ์๊ณ ์๊ฑฐ๋ ์ค๋นํด์ผ ํ ๊ฒ์ด ์์ต๋๊น? ๋ํ ๋ฒ์ 6์์ ๋ฆด๋ฆฌ์ค๋๋ i18n์ ๊ธฐ๋ฅ ๋ชฉ๋ก๊ณผ i18n์ ํ ์คํธ๊ฐ ์ด๋ป๊ฒ ์งํ๋๊ณ ์๋์ง ์๋ ค์ฃผ์๊ฒ ์ต๋๊น?
์ง๊ธ์ ์ฝ๋ ๋ฒ์ญ ์๋น์ค์ ๋ํ ์์ธํ ๋ด์ฉ์ด ์์ต๋๋ค. ์๋ง๋ ๋ค์ ์ฃผ์ ์์
ํ ๊ฒ์
๋๋ค(์ ๋ ๋ง์ดํด ๋ทฐ๋ก ์ฌํ ์ค์
๋๋ค). ๋ด๊ฐ ์๋ ๊ฒ์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ํด๋ก์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ goog.getMsg
์ ์ ์ฌํ ๊ฒ์ด๋ผ๋ ๊ฒ๋ฟ์
๋๋ค(ํ์ฌ Google์์ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์): https://github.com/google/closure-library /blob/db9bc1a2e71d4b6ee8f57eebe37eb0c6494e9d7e/closure/goog/base.js#L2379 -L2387 ์ด๋ ๋ด ํด๋ฆฌํ๊ณผ๋ ์ ์ฌํฉ๋๋ค.
v6์์ ์ฐ๋ฆฌ๋ ๋ฐํ์ i18n์ ์ถ์ํ ๊ฒ์ ๋๋ค: ๋ชจ๋ ๋ก์ผ์ผ์ ๋ํ ํ๋์ ๋ฒ๋ค, ๋ฐํ์์ ํด์๋ ๋ฒ์ญ, ์๊ฐ์ด ์๋ค๋ฉด ์ฝ๋ ๋ฒ์ญ์ผ ์๋ ์์ต๋๋ค(๊ทธ๋ ์ง ์์ผ๋ฉด ๊ณง ๋์ฌ ๊ฒ์ ๋๋ค). ์ ํฌ ํ ์คํธ๋ฅผ ๊ฑฐ์น์ง ์์ ์ ๋ ๋๋ฌ(ng-ivy๋ผ๊ณ ํจ)๋ฅผ ์ฌ์ฉํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ด ๋ชจ๋ ๊ฒ์ด ํ๋๊ทธ ๋ค์ ์์ต๋๋ค.
๊ณ ๋ง์! @ocombe ... ์ ๋ง ์ข์ ๊ฒ ๊ฐ์ต๋๋ค!
ํ
ํ๋ฆฟ ๋ฒ์ญ์ ์ํ ๊ตฌ๋ฌธ์ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ต๋๊น? ์ง๊ธ ํ๋ก์ ํธ์ ๋ฒ์ญ์ ์ถ๊ฐํ ์๊ฐ์
๋๋ค. ํ์ง๋ง ๋ช ์ฃผ ์์ ์์ ํ ๋ค์ ํ๊ณ ์ถ์ง๋ ์์ต๋๋ค.
์๋์, ํ ํ๋ฆฟ ๊ตฌ๋ฌธ์ ๋์ผํฉ๋๋ค.
์ข์ ์์์ ์๋ ค์ค @ocombe ์๊ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ด๊ฒ์ ๋งค์ฐ ์ ๋งํฉ๋๋ค. v6๊ณผ ํจ๊ป ์ถ์๋ ng-ivy ๋ ๋๋ฌ์์ ์ด๋ค ์ข ๋ฅ์ ํ๋ก๋์ ์ค๋น๋ฅผ ๊ธฐ๋ํ ์ ์์ต๋๊น? ๋๋ ๊ทธ๊ฒ์ด ์ ํฌ ํ ์คํธ๋ฅผ ๊ฑฐ์น์ง ์์ ๊ฒ์ด๋ผ๋ ๊ฒ์ ์ดํดํ์ง๋ง ์ฌ์ ํ ํ๋ก๋์ ์ฌ์ฉ์ ์ํด ์ค๋น๋๊ณ ๊ฑฐ์ ์ต์ ๋ฒ์ ์ ๋ชจ๋ ์ฃผ์ ๋ธ๋ผ์ฐ์ ์์ ์๋ํฉ๋๋ค. ๋ง์ต๋๊น?
์ฌ๊ธฐ์์ ์งํ ์ํฉ์ ํ์ธํ ์ ์์ต๋๋ค. https://github.com/angular/angular/issues/21706
๋ชจ๋ ๊ฒ์ด v6์ ๋ํด ์ค๋น๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ํ๋๊ทธ ์๋์ ์๊ธฐ ๋๋ฌธ์ v6 ๋ฆด๋ฆฌ์ค ํ์๋ ๊ณ์ ์งํํ ๊ฒ์
๋๋ค(๋ธ๋ ์ดํน ์ฒด์ธ์ง ๋๋ ๊ทธ ๋ฐ์ ๊ฒ์ ์๋)
์์งํ ๊ทธ ๋ชจ๋ ๊ฒ๋ค์ด ๋ฌด์์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค :D
๋๋ cli์ hello world ์ฑ์ด ์ด๋ฏธ ์๋ํ๊ณ ์๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค.
์ ๋ ๋๋ฌ์ ์ต์ ํ์์ ์ด์ ์ ์ป์ผ๋ ค๋ฉด ์ด๋ฌํ ๊ฒ๋ค ์ค ์ผ๋ถ๊ฐ ํ์ํ๋ค๊ณ ์๊ฐํ์ง๋ง ๋ชจ๋ ๊ฒ์ ํ์ธํ์ง ์๊ณ ๋ ์๋ํ ์ ์์ต๋๋ค.
์ฆ, ์์ฐ ์ค๋น๊ฐ ๋์ง ์์์ผ๋ฏ๋ก ์์ง ์ ํ์ ๋ฒ ํ
ํ์ง ๋ง์ญ์์ค. ๋ด๋ถ Google ์ฑ์์๋ ํ
์คํธ๋์ง ์์ผ๋ฉฐ ๋ฌธ์ ๋ฅผ ์์ ํ๊ธฐ ์ํด ๋ช ๊ฐ์ง ์ฃผ์ ๋ณ๊ฒฝ ์์
์ ์ํํด์ผ ํ ์ ์์ต๋๋ค. ์ ๋ ๋๋ฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ฌ์ฉ์์ ์ฌ๋์ ๋ฐ๋ผ ์ํ์ ๊ฐ์ํด์ผ ํฉ๋๋ค.
v6-beta4์ ์ด ์ค ํ๋๊ฐ ์์ต๋๊น?
์๋์. ์ด ๋ก๋๋งต ์ ํ์ธํ์ญ์์ค. ์ด ๊ธฐ๋ฅ์ i18n ๋ฐํ์์ ์ํด ์ฐจ๋จ๋ฉ๋๋ค.
์ ๋ฐ์ดํธ @ocombe ?
๋ฐํ์ i18n์ ์ฒซ ๋ฒ์งธ PR์ด ๊ธฐ๋ฅ์ ํ
์คํธํ๋ ๋ฐ ์ฌ์ฉํ Hello World ๋ฐ๋ชจ ์ฑ๊ณผ ํจ๊ป ๋ง์คํฐ์ ๋ณํฉ๋์์ต๋๋ค. ๋ฐํ์์ ์๋ํ๋ฉฐ ์์ง ์๋น์ค๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ์ด๋ก ์ ์ผ๋ก ์ฝ๋ ๋ฒ์ญ์ ์ง์ํฉ๋๋ค.
์ง๊ธ์ ๋งค์ฐ ์ต์ํ์ ์ง์(์ ์ ๋ฌธ์์ด)์ด๋ฉฐ ์๋ก์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ์์
์ ํ๊ณ ์์ต๋๋ค(๋ค์ ์ฃผ์ ์ถ์ถ ์์
์ ์ํํ ๋ค์ ์๋ฆฌ ํ์์์ ๋ณ์๊ฐ ์๋ ๋์ ๋ฌธ์์ด).
๊ทธ ํ ์ฝ๋ ๋ฒ์ญ ์๋น์ค๋ฅผ ํด๋๋ฆฝ๋๋ค.
์ ๊ธฐ๋ฅ์ด ์๋ฃ๋๋ฉด ๋ง์คํฐ์ ๋ณํฉ๋๋ฏ๋ก ์ ์ ๊ณต์ ๊ธฐ๋ค๋ฆด ํ์๊ฐ ์์ต๋๋ค.
@ocombe i heart i18n ๊ธฐ๋ฅ์ ์ด๋ฏธ v4.3์ ์์ด์ผ ํฉ๋๋ค!! ๋๋ฌด ๋ง์ ๋ฆด๋ฆฌ์ค๊ฐ ์์ง๋ง i18n์๋ ์๋ฌด๊ฒ๋ ์์ต๋๋ค. Angular ํ ๊ด๋ฆฌ์๊ฐ ๋ ๋ง์ ์์ /๊ฐ๋ฐ์๋ฅผ ํ ๋นํ ์ ์๋์? ํผ์ ๋๋ ๋ ๋ช ์ ๊ฐ๋ฐ์๊ฐ ๋น ๋ฅด๊ฒ ์งํํ ์ ์๋ค๋ ๊ฒ์ ์ดํดํ ์ ์์ต๋๋ค. ์ด i 18n ๊ธฐ๋ฅ์ Angular๊ฐ ๋น์ฆ๋์ค ์ฑ/๋ํ ์ฑ์ผ๋ก ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋น๋๋๋ ํ์ ๊ธฐ๋ฅ์ ๋๋ค. ์ด ๋ ๊ฐ์ง ๊ธฐ๋ฅ์ ๋ํ ์ฑ์์ ๊ฐ์ฅ ์ค์ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๊น? ๊ฐ์ฌ ํด์
@ocombe ์๊ฒ ํ ์ ์๋ ๋ง์ ๊ทธ๊ฐ ์ด ๊ธฐ๋ฅ์ ์๋ ๋ชจ๋ ๋ ธ๋ ฅ์ ๋ํด ๊ฐ์ฌํ๋ค๋ ๋ง๋ฟ์ ๋๋ค. ๋ ์ด์ ๊ฐ๋ฐ์๊ฐ ์๋ค๋ฉด ๊ทธ๊ฐ ์์ฒญํ์ง ์์๊ธฐ ๋๋ฌธ์ด ์๋๋ผ๊ณ ํ์ ํฉ๋๋ค. ๊ทธ๋ฅ ๋๋์ธ์. ์ถ์๋๋ฉด ํํํ์ง ์์ ๊ฑฐ์์.
์ฐธ๊ณ ๋ก...
json
ํ์ผ์ ์ ์ฅ๋ ๋ฌธ์์ด์ ๋ํ ์ง์์ ํฌํจํ์ฌ ์๋ Aurelia์ ํจ๊ป ์ฌ์ฉํ๋๋ก ๊ฐ๋ฐ๋ ๋ฌธ์์ด ๊ฐ์ ธ์ค๊ธฐ ๋ฐ ๋ด๋ณด๋ด๊ธฐ๋ฅผ ์ํ ๋์ฒด ๋๊ตฌ๊ฐ ์์ต๋๋ค. Webpack์์ json
๋ฅผ ์ง์ ๊ฐ์ ธ์ฌ ์ ์์ผ๋ฏ๋ก ๋งค์ฐ ํธ๋ฆฌํฉ๋๋ค. ts
ํ์ผ์ ์ถ๊ฐํ์ฌ ์ฝ๋์์ ํด๋น ๋ฌธ์์ด์ ์ฝ๊ฒ ์ก์ธ์คํ ์ ์์ต๋๋ค.
์ด ๋๊ตฌ๋ Angular ํ ํ๋ฆฟ๊ณผ๋ ์๋ํ๋ฉฐ ๋ค๋ฅธ ํธ๋ฆฌํ ๊ธฐ๋ฅ์ด ๋ง์ด ์์ต๋๋ค. ์ํ๋ ๊ฒฝ์ฐ ์ฌ์ฉํ๊ฑฐ๋ Angular ๋๊ตฌ๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด ์์ ๋กญ๊ฒ ์์ด๋์ด๋ฅผ ๋น๋ฆด ์ ์์ต๋๋ค. ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ Webpack ๋ก๋๋ ์์ต๋๋ค. ๋ฌธ์์ ๋งํฌ๋ฅผ ์ฐธ์กฐํ์ธ์.
์ฐ๋ฆฌ๋ ๋ ๊ฐ๋จํ ๋ฌธ์ ๊ฐ ์๊ณ ์์ผ๋ก ๋์ฌ ๊ธฐ๋ฅ(๋๋ @ocombe์ ํด๋ฆฌํ)์ด ํ์ํ์ง ํ์ ์ด ์์ง ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ๊ฐ ์์ ์์์ ์์ฑ์ ์ค์ ํ๋ ์์๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๋ฐ์ ์์์ ๊ตฌ์กฐ๋ฅผ ์ ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด:
loginForm = [
{
type: 'email',
placeholder: 'EMAILPLACEHOLDER' // "Your email"
},
{
type: 'password,
placeholder: 'PASSWORDPLACEHOLDER' // "Your password"
}
];
ํ์ฌ ์ฐ๋ฆฌ๋ ngx-translate
๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ํ
ํ๋ฆฟ์์ ๋ค์๊ณผ ๊ฐ์ด ๋ฌธ์์ด์ ๋ฒ์ญํฉ๋๋ค.
<input *ngFor="let ele of loginForm" [type]="ele.type" [placeholder]="ele.placeholder | translate">
์ด์ Angular i18n์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๊ณ ์ถ์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ ๋ฌธ์์ด์ด ํ ํ๋ฆฟ์ ์๋ ๊ฒ์ ์๋๊ธฐ ๋๋ฌธ์ Angular i18n์ ์ฆ์ ์ฌ์ฉํ ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ฐ๋ฆฌ์ ์ํฉ์ ๋ฐํ์์ ๋ฒ์ญ์ ๊ฒ์ํด์ผ ํ๋ ์ํฉ๋ณด๋ค ๊ฐ๋จํด ๋ณด์ ๋๋ค. ์ฐ๋ฆฌ์ ๋ชจ๋ ํ ์คํธ๋ ์์์ ๋ฏธ๋ฆฌ ์ ์๋์ด ์์ผ๋ฉฐ x18n์ด ํ์ฌ ํ ํ๋ฆฟ์ ๋ฌธ์์ด์ ๋ํด ์ํํ๋ ๊ฒ์ฒ๋ผ ์ปดํ์ผ ์๊ฐ์ ๋์ฒด๋ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ ๋ ๋ณต์กํ ๋ฌธ์์ด์ ๊ฐ์ง ์ ์์ต๋๋ค.
placeholder: 'I18N:description|meaning@<strong i="16">@PASSWORDPLACEHOLDER</strong>:Your password'
์ปดํ์ผ ์๊ฐ์ ๋ฌธ์์ด์ ๋ค์์ผ๋ก ๋์ฒด๋ ์ ์์ต๋๋ค.
placeholder: 'Your password'
์ด๊ฒ์ด ๊ตฌํ์ ์ํด ๊ณ ๋ ค๋ ์ ์๋ ๊ฒ์ ๋๊น?
๋ฐํ์ i18n์ผ๋ก ํ์คํ ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์๋ฆฌ ํ์์๋ฅผ ๋ฒ์ญ์ผ๋ก ๋ณํํ๊ธฐ ์ํด ํ์ดํ์์ ์๋ก์ด i18n ์๋น์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ด ์ค๋ ๋๊ฐ ์ผ๋ง ๋์ ์ด๋ ค ์๋ค๋ ๊ฒ์ ์์์ต๋๋ค. HTML๊ณผ ๊ตฌ์ฑ ์์ ์ฝ๋ ํ
์คํธ๋ฅผ ๋ชจ๋ ๋ฐ์ ํ๊ฒ ์ฒ๋ฆฌํ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ผ๋ก Angular์์ ๋ค๊ตญ์ด ์ฌ์ดํธ๋ฅผ ๊ฐ๋ฐํ๋ ๋ฐ ๋ํ ์ฃผ์ ๊ด์ฌ์ ๋ณด์ฌ์ค๋๋ค.
ocombe ๋ชจ๋ ๊ตฌ๋
์์๊ฒ ์๋ฆผ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ๊ฒ์ ์์ง ๋ง์ธ์. 2018๋
5์์ด ์ฝ์์ธ ๊ฒ์ผ๋ก ์๊ณ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ๋ถ์ ์น์ ํ ๊ธฐ์ฌ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!
@ocombe ์ด ๋ฐํ์ ์๋น์ค๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด Ivy๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๊น ์๋๋ฉด ์ด์ ์์ง์์๋ ์๋ํฉ๋๊น?
๋ด์์ด๋ฉ๊ตด๋ง ๊ฐ๋ฅํ๋ฉฐ ์์ง ๋ฏธ์์ฑ์ด๋ผ ์ฌ์ฉ๋ถ๊ฐ
@ocombe ์ ๋ชจ๋ ๋ ธ๋ ฅ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!
์ด ์๋ก์ด ๊ธฐ๋ฅ์ ์ผ๋ง๋ ๋นจ๋ฆฌ ์ฌ์ฉํ ์ ์๋์ง์ ๋ํด ๋ง์ํด ์ฃผ์๊ฒ ์ต๋๊น?
Ivy๋ ํ์ฌ ์ํํ ์ํ์์ ์ปดํ์ผ๋ฌ ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ Angular 6์์ ํ์ฑํํ ์ ์์ต๋๋ค. ์ด ์๋ก์ด 18n ๊ธฐ๋ฅ์ ํ์ฌ Ivy ์ํํ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๊น?
์์ง๊น์ง๋ ์๋์ง๋ง, ๋๋ ์ข์ ์ง์ ์ ์ด๋ฃจ๊ณ ์์ต๋๋ค(์ง๊ธ ์ด ์ผ์ ๋ํด ํํ์์ผ๋ก ์ผํ๊ณ ์์ต๋๋ค). ๋ง์คํฐ์์ ํ ์คํธํ ์ ์๊ฒ ๋๋ฉด ์ฌ๊ธฐ์ ์ ๋ฐ์ดํธ๋ฅผ ๊ฒ์ํ๊ฒ ์ต๋๋ค.
@ocombe ์ ๋ง ๊ฐ์ฌ ํฉ๋๋ค! ๋น์ ์ ๋ ธ๋ ฅ์ผ๋ก ๋ง์ ์ฌ๋๋ค์ด ํํ์ ๋ฐ๊ณ ์์ต๋๋ค. ์ฐ๋ฆฌ ๋ชจ๋๋ ๊ทธ๊ฒ์ ํฌ๊ฒ ๊ฐ์ฌํฉ๋๋ค!
@ocombe ts์ ์ ์ ๋ฒ์ญ์ ์์ง ๊ณํ ์ค์
๋๊น? typescript ๋ณํ์ผ๋ก ์ปดํ์ผ ํ์ ํํ์ ๊ต์ฒด๋ฅผ ์๋ฏธํฉ๋๋ค.
๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์ฌ์ฉ์ ์ง์ ts ๋ณํ์ ์ถ์ถํ์ง ์๊ณ ng build
ํ์ดํ๋ผ์ธ์ ์ฐ๊ฒฐํ ์ ์์ต๋๊น?
@TinyMan ์ด ๋ฌด์จ ๋ง์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋น๋ ์๊ฐ์ ๋ฒ์ญ์ ๋ณํฉํ ์ ์๋ค๋ ๋ป์ธ๊ฐ์(์ง๊ธ์ฒ๋ผ), ์๋๋ฉด ts ์ฝ๋์์ ๋ฒ์ญ์ ์ฌ์ฉํ ์ ์๋ค๋ ๋ป์ธ๊ฐ์(์ฐ๋ฆฌ๊ฐ ์ด๋ฏธ ๊ฐ์ง๊ณ ์๋ ํ ํ๋ฆฟ ๋ฒ์ญ ์ ์ธ)?
@ocombe ๋ด ๋ง์ ts์์ ๋ฒ์ญ์ ์ฌ์ฉํ ์ ์์ง๋ง ์๋น์ค๋ DI/๋ฐํ์ ๋ฒ์ญ์ ํตํด์๋ ์ฌ์ฉํ ์ ์๋ค๋ ๋ป์ ๋๋ค. ์ปดํ์ผ ํ์ ๋ฒ์ญ์ ์๋ฏธํ์ง๋ง typescript์ฉ์ ๋๋ค. C ์ ์ฒ๋ฆฌ๊ธฐ์ฒ๋ผ. ๋๋ ๊ทธ๊ฒ์ด vicb ์๊ฒฌ ์ ๋ฐ๋ผ ๊ณํ๋์๋ค๊ณ ์๊ฐํ์ต๋๋ค.
- ์ค๋๋ ํ ํ๋ฆฟ์ ๋ํด ์ํํ๋ ๊ฒ์ฒ๋ผ ์ ์ ๋ฒ์ญ์ ์ง์ํ ์๋ ์์ต๋๋ค. ๋ฌธ์์ด์ ์ปดํ์ผ ์๊ฐ์ ๋์ฒด๋๊ณ ์ฑ๋ฅ์ ๋ ์ข์ง๋ง ๋ก์ผ์ผ๋น ํ๋์ ์ฑ ๋ฒ์ ,
์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด ์ธ ์ ์๊ธฐ๋ฅผ ์ํฉ๋๋ค.
export const Notifications = {
newComment: i18n("New comment notification@@newComment", "New comment on your story !"),
newStory: i18n("New story notification@@newStory", "{{0}} wrote a new story !"),
}
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ (in fr)๊ณผ ๊ฐ์ด ๋ณํ๋ฉ๋๋ค.
export const Notifications = {
newComment: "Un nouveau commentaire a รฉtรฉ ajoutรฉ a votre article !",
newStory: "{{0}} a รฉcrit un nouvel article !",
}
ํ์ฌ ๊ทธ ๋ชฉ์ ์ ์ํด ์ถ์ถ์ ์ํ ์ฌ์ฉ์ ์ ์ ๋ง์ปค์ ํจ๊ป ngx-translate๋ฅผ ์ฌ์ฉํ๊ณ (์ด ์์์๋ i18n
) ๋ฉ์์ง๋ฅผ ํ์ํด์ผ ํ ๋ ๋ฒ์ญ์ ์ํํ๋ this.translate.instant(Notifications.newStory, ["TinyMan"])
๋ฅผ ํธ์ถํด์ผ ํฉ๋๋ค. + ๋ณด๊ฐ. ๋ด ๋ง์ ๋ฒ์ญ ์๋น์ค๋ฅผ ํธ์ถํ์ง ์๊ณ Notifications.newComment
๋ฅผ ์ธ ์ ์์ด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฌธ์์ด ๋ณด๊ฐ์ ์ํด ICU์ ๋ณด๊ฐ๋ง ์ํํ๋ ๋ณด๊ฐ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค(ํ
ํ๋ฆฟ ๋ฌธ์์ด์ ์ด๋ฏธ ๋ฒ์ญ๋์์ ๊ฒ์
๋๋ค).
Notification.newStory // {{0}} a รฉcrit un nouvel article, static string, no runtime translation
template(Notification.newStory, "TinyMan") // TinyMan a รฉcrit un nouvel article !
์ฌ๊ธฐ์ ์ฐ๋ฆฌ๋ ๋ฒ์ญ HTTP ์์ฒญ ๋ฐ ์๋น์ค ์ค๋ฒํค๋๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
๋๋ ๊ทธ๊ฒ์ด ๋ช ํ ํด์ง๊ธฐ๋ฅผ ํฌ๋งํฉ๋๊น?
๋น์ ์ด ์ค๋ช
ํ๋ ๊ฒ์ ์ค์ ๋ก i18n์ ๋ก๋๋งต์ ์์ต๋๋ค.
ํ์ฌ๋ก์๋ https://github.com/ngx-translate/i18n-polyfill ์ด ์์
์ ์ํํฉ๋๋ค.
@TinyMan ์๋น์ค ๋๋ ์ ์ญ ๊ธฐ๋ฅ์ ํตํ ๊ฒ์ธ์ง ์์ง ํ์คํ์ง ์์ต๋๋ค. ๋ ๋ค ๊ฐ๋ฅํ์ง๋ง ์๋น์ค์๋ ๋ง์ ์ฅ์ ์ด ์์ต๋๋ค. ํ
์คํธ๋ฅผ ์ํด ๋ชจ์ํ๊ฑฐ๋ ์์ ์ ๊ฒ์ผ๋ก ๋ฐ๊ฟ ์ ์์ผ๋ฉฐ ๊ฐ ๋ชจ๋/๊ตฌ์ฑ ์์์ ๋ํ ๋์์ ๋ณ๊ฒฝํ ์๋ ์์ต๋๋ค.
๋ด๋ถ์ ์ผ๋ก Google์ ์ ์ญ ํจ์์ธ Closure i18n( goog.getMsg
๋ฅผ ํตํด)์ ์ฌ์ฉํ ๊ฒ์ด๋ฉฐ ์ด ํจ์๋ ์ ์ญ ํ๋๊ทธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ปดํ์ผํ๋ ๋์ ์๋น์ค๋ก ๋์ฒด๋ ๊ฐ๋ฅ์ฑ์ด ๋๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ํด๋น ํ๋๊ทธ๋ฅผ ์ธ๋ถ์์๋ ์ฌ์ฉํ ์ ์๋์ง ํ์ธํ๋ ค๊ณ ํ๊ฒ ์ง๋ง ์ ์๋๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ํ์ง๋ง ๊ทธ๊ฒ์ ์ฌ์ฉํ๋ค๋ฉด ํ
ํ๋ฆฟ ๊ณผ ์ฝ๋ ๋ฒ์ญ์ ์ํ ๊ฒ์
๋๋ค.
@ocombe ์ฌ๊ธฐ์๋ ๊ฐ์ฌ ์ธ์ฌ๋ฅผ ์ ํ๊ณ ์ถ์ต๋๋ค. ๋๋ ๋น์ ์ด ์ด ์ผ์ ํ๊ณ ์๋ ๊ฒ์ ๋ํด ๋งค์ฐ ๊ฐ์ฌํ๊ฒ ์๊ฐํฉ๋๋ค. ์ด ์์ ์ ์ ์ผ์ ์์ฒญ๋๊ฒ ๋์์ด ๋ ๊ฒ์ ๋๋ค. ํ ๊ฐ์ง ์ง๋ฌธ: ํ ์คํธ๋ฅผ ์ฐพ์ ๋ ์ฌ๋ฐ๋ฅธ ๋ฌธ์์ด์ ์ป๊ธฐ ์ํด ๋ฐํ์์ xlf๋ฅผ ์ฐธ์กฐํ๋ ํ ์ธํธ์ ๋ฒ๋ค ํ์ผ๋ง ๋ง๋๋ AOT ์ปดํ์ผ์ ์ํํ๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น, ์๋๋ฉด ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
๋ฐ๋ผ์ ๋ณธ์ง์ ์ผ๋ก ์ธ์ด๋น 1๊ฐ์ xlf ํ์ผ๊ณผ 5๊ฐ ๋๋ 6๊ฐ์ ๋ฒ๋ค ํ์ผ์ด ํ์ํฉ๋๋ค. ํ์ฌ 10๊ฐ ์ธ์ด์ AOT ์ปดํ์ผ์ด ์๋ ๊ฒฝ์ฐ 50๊ฐ ์ด์์ ํ์ผ์ด ์์ต๋๋ค. ์ธ์ด๋น ๋ฒ๋ค ํ์ผ ์ธํธ...
๋๋ ๊ทธ๋ฐ ๋ ธ๋ ฅ์ด๋ ๋ณต์ก์ฑ์ ๋ชจ๋ฅด์ง๋ง 1 ์ธํธ์ ํ์ผ ๋ง ์์ผ๋ฉด ์ปดํ์ผ์ด ์์ผ๋ฉด ์ข์ ๊ฒ์ ๋๋ค.
์, ๊ทธ๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ivy, ๋ฐํ์ i18n์ผ๋ก ํ ์ผ์
๋๋ค.
์ฑ์ ํ ๋ฒ ๋ฒ๋คํ๊ณ ๋ฐํ์์ ๋ฒ์ญ์ ๋ก๋ํฉ๋๋ค(๋ฒ์ญ์ ์ง์ฐ ๋ก๋ํ ์ ์์).
@๊ทธ๋ ๊ตฌ๋ . ์ด๋ค. ๋ฏฟ์ ์์๋.
๋ฏฟ์ ์ ์์ ์ ๋๋ก ํ๋ณตํฉ๋๋ค. ๊ฐ์ฌ ํด์!
์ธ๋ถ ํ
ํ๋ฆฟ์ ๋ฒ์ญํ ์ ์๋ i18n
๊ธฐ๋ฅ์ ๋์๊ฒ ์์ ํ ์ธ๋ชจ๊ฐ ์์ต๋๋ค.
@ocombe ์๋
ํ์ธ์ ์ฌ๋ฆฌ๋น์!
์
๋ฐ์ดํธ๊ฐ ์์ต๋๊น?
๊ฐ์ฌ ํด์!
์๋ฃ๋๋ฉด Angular 7(2018๋ 9์/10์)๋ก ์์ ๋ Ivy๊ฐ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ฏ๋ก ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
Angular 7์์๋ ์ด ๋ฌธ์ ๊ฐ 2๋
๋ LOL์ด ๋ฉ๋๋ค.
์ด์จ๋ Ivy๋ ์ด ์๋ก์ด ๊ธฐ๋ฅ์ ๊ฐ์ฅ ์ง์ฐ์ํจ ๊ฒ์ด์์ต๋๋ค...
@ocombe , ๋ฃ๊ธฐ ์ข์ต๋๋ค. ์ฐ๋ฆฌ๋ ํ์ฌ ์์ ํ ์ด๋ฌํ ์ด์ ๋ก ์ฒ์๋ถํฐ ๋กค๋งํ ๋ ๊ฑฐ์ i18n ์๋น์ค๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. JS์์ ํ ์ ์๋ค๋ ๊ฒ์ ์ฐ๋ฆฌ๋ฅผ ์ํด ๋ช ๊ฐ์ง ๊ฐ๋จํ ์ผ์ ํ๋ ๊ฒ์ ๊ทน๋๋ก ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค.
types
์ค๋ฅ๋ฅผ ๋ฐํํฉ๋๋ค. ์ฐ๋ฆฌ์ ๋งฅ๋ฝ์์ ์ฐ๋ฆฌ๋ ์ด๋ฌํ ์ค๋ฅ๋ฅผ ๋์ ์ผ๋ก ์ง์ญํํด์ผ ํ๋ฉฐ ํ
ํ๋ฆฟ ๊ธฐ๋ฐ ์ ๊ทผ ๋ฐฉ์์ ๋ณต์กํฉ๋๋ค.TitleService
๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ง๋ง ํ์งํ๋ ํ
์คํธ๋ฅผ ์ ๊ณตํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค!Angular ํ์ด ํ์ฌ ์ด๊ฒ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋์ง ๊ถ๊ธํฉ๋๋ค...
์๋
ํ์ธ์ @vincentjames501 ,
์ฐ๋ฆฌ ํ์ฌ์์๋ ์ง๊ธ ํ๊ณ ์๋ ๊ฒ๊ณผ ๋๊ฐ์ด ํ๋ ค๊ณ ํ์ง๋ง ๋๋ฌด ๋ฒ๊ฑฐ๋ก์์ ์ด ์ค๋ ๋์์ ์ด์ ์ ์ธ๊ธํ i18n-polyfill ์ ์ฌ์ฉํ๊ฒ ๋์๊ณ ์ง๊ธ๊น์ง ์ ์๋ํ๊ณ ์์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ๊ฐ์ง ์ ์ผํ ๋จ์ ์ ์ฑ ๋ฒ๋ค์ ํฌ๊ธฐ์
๋๋ค. ์ฐ๋ฆฌ๋ ์ธ ๊ฐ์ ๋ฒ์ญ ํ์ผ์ ๊ฐ์ง๊ณ ์๊ณ ๊ฐ ๋ฒ๋ค์ ๊ทธ ์์ ๊ทธ๊ฒ๋ค์ ๋ชจ๋ ํฌํจํ๊ณ ์์ต๋๋ค(์ฌ์ฉํ๋ ๋ฒ์ญ๋ง์ผ๋ก ๋ฒ๋ค์ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ฐพ์ง ๋ชปํ์ต๋๋ค). ๊ทธ๋ฌ๋ ์ด ๋ชจ๋ ๊ฒ์ Ivy๊ฐ ์ถ์๋๋ฉด ํด๊ฒฐ๋๊ธฐ๋ฅผ ๋ฐ๋ผ๋ ์ฑ๊ฐ์ ์ผ์
๋๋ค.
๊ฑด๋ฐฐ,
๋ฒ์ญ ๋งต์ ํฌํจํ๊ณ ๊ฐ ์ธ์ด์ environment.ts ํ์ผ์ ๋ค์ ๋ด๋ณด๋์ต๋๋ค. ๋ฌธ์ ์์ด ์๋ํ๊ณ ๋ชจ๋ ๋ฒ๋ค์ ํฌํจ๋์ด ์์ง ์์ผ๋ฉฐ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํ์ง ์์ต๋๋ค. ๋ด๊ฐ ๊ฐ์ง ์ ์ผํ ๋ฌธ์ ๋ evey ์ฌ์ดํธ๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ์ธ์ด์ ๋ํด ๋์ผํ ์๋น์ค ์์ ์๋ฅผ ๊ฐ์ง ์ ์์ผ๋ฉฐ ๋๊ตฐ๊ฐ ์ธ์ด๋ฅผ ์ ํํ๋ฉด ๋ด ์ฌ์ดํธ์์ ๊ทธ๊ฐ ์ด๋ฏธ ํธ์ ์๋ฆผ์ ๋ฑ๋ก๋์๋์ง ์ฌ๋ถ๋ฅผ ์ ์ ์๋ค๋ ๊ฒ์ ๋๋ค...
@ocombe Angular 6์ ๋ํ ์์์ด ์์ต๋๊น?
์์์ ์ค๋ช ํ ๊ฒ์ฒ๋ผ Angular v6์๋ ์์ต๋๋ค. v7์ฉ์ผ๋ก ์์ ๋์ด ์๋ Ivy์ ์์กดํ๊ณ ์์ต๋๋ค.
@ocombe ์ด ์ค๋ ๋๋ฅผ ์ ๊ทธ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ทธ๋์ผ ํ๋ง ์ ์ ํ ๋ ์๋ฏธ ์๋ ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ณตํ ์ ์๊ณ ๊ทํ๊ฐ ๊ณ์ ๋๋ตํ๋ ๋ฐ๋ณต์ ์ธ ์ง๋ฌธ์ ํผํ ์ ์์ต๋๋ค.
ํ์ฌ Angular์ ํจ๊ป ์ฌ์ฉํ๊ธฐ ์ํ ๋ด ํดํน์ ng-template
๋ฅผ ์ฌ์ฉํ๊ณ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์๋ฒ ๋๋ ๋ทฐ๋ฅผ ์์ฑํฉ๋๋ค.
<ng-template #messagetotranslate i18n>This message should be translated</ng-template>
๊ทธ๋ฐ ๋ค์ ๊ตฌ์ฑ ์์ ts ํ์ผ์์:
@ViewChild('messagetotranslate') messagetotranslate: TemplateRef<any>;
createTranslatedMessage(): string {
return this.messagetotranslate.createEmbeddedView({}).rootNodes[0].textContent;
}
createTranslatedMessage
๋ฉ์๋๋ ๋ฒ์ญ๋ ๋ฉ์์ง๋ฅผ ๋ฐํํฉ๋๋ค. ์ต์ ์ด ์๋ ๋ฉ์์ง๋ฅผ ์ ์ธํ๊ธฐ ์ํด ํ
ํ๋ฆฟ์ ์ฌ์ฉํ๊ณ ์์ง๋ง ์ด๋ ๊ฒ ํ๋ฉด CLI ๋ฒ์ญ ๋๊ตฌ๊ฐ ์ด๋ฅผ xlf ํ์ผ์ ๋ฑ๋กํ ์ ์์ผ๋ฉฐ ํ
ํ๋ฆฟ ์ธ๋ถ์์ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ๋ฒ์ญ๋ ๋ฉ์์ง๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
API๊ฐ ๊ฒฝ๋ก์์๋ ์๋ํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค! ์๋ฅผ ๋ค์ด
export const routes: Routes = [
{
path: '',
component: HomeComponent,
data: {
title: i18n('Home'),
breadcrumb: i18n('Home')
}
}
]
์ด ๊ธฐ๋ฅ์ด ์ถ์๋๋ค๋ฉด ํ์ฌ์ i18n API์ ํฐ ๋ณํ๊ฐ ์์๊น์? ์ง๊ธ i18n์ผ๋ก ํ๋ก์ ํธ๋ฅผ ์์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์๋๋ฉด Angular 7์ด ์ถ์๋ ๋ ์๋ก์ด i18n API๋ฅผ ๊ธฐ๋ค๋ ค์ผ ํฉ๋๊น?
์ ๋ฐ์ดํธ ์ธ์ ๋ฐํ์ ๋ฐ ๋์ ๋ฒ์ญ ์ง์์ ๋ฐ์ ์ ์์ต๋๊น?
๋ฐํ์ ๋ฒ์ญ์ด ์๋ฃ๋๊ณ ๋ณํฉ๋์ง๋ง(ivy๋ก) ์ปดํ์ผ๋ฌ ์ธก์ด ์์ง ์๋ฃ๋์ง ์์์ต๋๋ค.
๋๋ ์ง๊ธ ICU ํํ์ ์ฐ๊ตฌํ๊ณ ์์ต๋๋ค.
์์ง ๋์ ๋ฒ์ญ(์๋น์ค) ์ฝ๋ฉ์ ์์ํ์ง ์์์ง๋ง ์๋ง๋ ICU ํํ์ ํ์ ํ ๋ค์ ์์
์ผ ๊ฒ์
๋๋ค.
@vincentjames501 ICU ํํ์๊ณผ ํจ๊ป i18n-polyfill์ ์ฌ์ฉํ ์ ์๋์? ๊ตฌํ ๋ฐฉ๋ฒ์ ๋ํ ์๋ฃจ์ ์ด ์์ต๋๋ค.
@ocombe , ๋ฐํ์๊ณผ ๋์ ๋ฒ์ญ์ ์ฐจ์ด์ ์ ๋ช ํํ ํด์ฃผ์ค ์ ์์ต๋๊น?
์๋ง๋ ๊ณต์์ ์ธ ๋ช ์นญ์ ์์ง๋ง ๋ด๊ฐ ๋ณด๋ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ๊ฐ๋ฐ ์ค์ธ ํ์ฌ ํ๋ก์ ํธ์ i18n ์ง์์ ์ถ๊ฐํ๋ ๊ฒ์ ์ฐ๊ธฐํ์ง๋ง ๋ฆด๋ฆฌ์ค์ ๊ฐ๊น์์ง๊ณ ์์ต๋๋ค. ์ด๊ฒ์ด Angular 7์์ ์ต์ข ์ ์ธ ๊ฒ์ธ์ง ์ ์ ์์๊น์? ์๋๋ฉด ๋ฒ์ญ์ ์ถ๊ฐํ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๊ณ ๋ คํด์ผ ํฉ๋๊น?
@andrei-tatar i18n์ Angular 2 ์ดํ๋ก ์๋ฒฝํ๊ฒ ์๋ํฉ๋๋ค. ์ ์ผํ ๋จ์ :
๋ง์ง๋ง ๋ ์ง์ ์ ๋ํด์๋ @ngx-translate๋ฅผ ๋์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ Angular์ ๋ด์ฅ i18n๊ณผ ๋ค๋ฅด๊ฒ ์๋ํ๋ฏ๋ก ์ดํ ์ ๋ฐ์ดํธ์๋ ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์์ต๋๋ค. ํด๋ฆฌํ์ ๊ฒฝ์ฐ ์ ๋ฐ์ดํธ๋ ์๋ง๋ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ ๊ฒ์ ๋๋ค.
@shobhit12345
ngSwitch๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๋ฉ์์ง๋ฅผ ํ ํ๋ฆฟํํ๋ฏ๋ก i18n ํ๊ทธ๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ์ฒจ๋ถํ ์ ์์ต๋๋ค.
<div>
<ng-container [ngSwitch]="paymentMethod.historyOpned">
<ng-container *ngSwitchCase="true" i18n="@@hide">Hide</ng-container>
<ng-container *ngSwitchCase="false" i18n="@@show">Show</ng-container>
</ng-container>
<ng-container> <ng-container>
<ng-container i18n="@@history">History</ng-container>
</div>
์ฐ๋ฆฌ๋ ๋๋ฝ๋ ๋์ ๋ฒ์ญ์ ํด๊ฒฐํ๊ธฐ ์ํด ์ด ๋ฐฉ๋ฒ์ ๋ง์ด ์ฌ์ฉํฉ๋๋ค. ์กฐ๊ธ๋ง ์๊ฐํด๋ณด๋ฉด ๋๋ผ์ด ์์ ํ ์คํธ๋ฅผ ํ ํ๋ฆฟ์์ ์ด๋ฐ ๋ฐฉ์์ผ๋ก ํํํ ์ ์์ต๋๋ค. ์ผ๋ฐ์ ์ธ ํจํด์ ๋ฉ์์ง ๋ฐฐ์ด์ ๊ฐ์ง๊ณ ngFor ๋ฐ ngSwitch์ ํจ๊ป ์ฌ์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ด ๋ฉ์์ง๋ฅผ ํ ํ๋ฆฟํํ๋ ๊ฒ์ ๋๋ค.
TS
messsages = [ 'this is the first message', 'this is the second message' ]
````
html
```
๋ค์ ์ฅํฉํ์ง๋ง ์๋ํฉ๋๋ค!
๋๋ถ์ ์์ด๋์ด๊ฐ ๋ ์ฌ๋์ต๋๋ค.
2018๋
8์ 24์ผ ๊ธ์์ผ, 16:56 David Walther Birk Lauridsen, <
[email protected]>์ ๋ค์๊ณผ ๊ฐ์ด ์ผ์ต๋๋ค.
@shobhit12345 https://github.com/shobhit12345
์ฐ๋ฆฌ๋ ngSwitch๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๋ฉ์์ง๋ฅผ ํ ํ๋ฆฟํํ๋ฏ๋ก i18n-tag๋ฅผ ๋ค์์ ์ฒจ๋ถํ ์ ์์ต๋๋ค.
๊ฐ๋ณ์ ์ผ๋ก.์จ๋ค ๋ณด์ฌ ์ฃผ๋ค ์ญ์ฌ ์ฐ๋ฆฌ๋ ๋๋ฝ๋ ๋์ ๋ฒ์ญ์ ํด๊ฒฐํ๊ธฐ ์ํด ์ด ๋ฐฉ๋ฒ์ ๋ง์ด ์ฌ์ฉํฉ๋๋ค.
์กฐ๊ธ๋ง ์๊ฐํด๋ณด๋ฉด ๋๋ผ์ด ์์ ํ ์คํธ๋ฅผ ๋ค์์ผ๋ก ํํํ ์ ์์ต๋๋ค.
ํ ํ๋ฆฟ์์ ์ด๋ฐ ์์ผ๋ก. ์ผ๋ฐ์ ์ธ ํจํด์ ๋ฉ์์ง ๋ฐฐ์ด์ ๊ฐ๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ฐ ๋ค์ ์ด๊ฒ์ ngFor ๋ฐ ngSwitch์ ํจ๊ป ์ฌ์ฉํ์ฌ ๋ฉ์์ง๋ฅผ ํ ํ๋ฆฟํํฉ๋๋ค.
์ด ๊ฐ์:TS
๋ฉ์์ง = [ '์ด๊ฒ์ ์ฒซ ๋ฒ์งธ ๋ฉ์์ง์ ๋๋ค', '์ด๊ฒ์ ๋ ๋ฒ์งธ ๋ฉ์์ง์ ๋๋ค' ]
HTML
i18n="@@firstMesssage">์ฒซ ๋ฒ์งธ ๋ฉ์์ง์ ๋๋ค. i18n="@@secondMesssage">๋ ๋ฒ์งธ ๋ฉ์์ง์ ๋๋ค. ๋ค์ ์ฅํฉํ์ง๋ง ์๋ํฉ๋๋ค!
โ
๋น์ ์ด ์ธ๊ธ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ณ GitHub์์ ํ์ธํ์ธ์.
https://github.com/angular/angular/issues/11405#issuecomment-415731284 ,
๋๋ ์ค๋ ๋ ์์๊ฑฐ
https://github.com/notifications/unsubscribe-auth/AGwM6jcWIpwtGxhkH1fwnVXNagRxmMnoks5uT-LxgaJpZM4J2pkr
.
์๋ฃ๋๋ฉด Angular 7(2018๋ 9์/10์)๋ก ์์ ๋ Ivy๊ฐ ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ฏ๋ก ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
๋ฒ์จ 10์์ ๋๋ค. 10์ ๋ง๊น์ง ์๋ก์ด ๊ธฐ๋ฅ์ด ์ ๊ณต๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ญ๋๊น?
https://is-angular-ivy-ready.firebaseapp.com ์ ๋ฐ๋ฅด๋ฉด @lizzymendivil Ivy๋ 65% ์๋ฃ๋์์ผ๋ฉฐ 30์ผ ๋ง์ ์๋ฃ๋ ๊ฒ ๊ฐ์ง ์์ต๋๋ค.
์, ์์ด๋น๋ ํ ๋ฌ ์์ ๋๋์ง ์์ ๊ฒ์ ๋๋ค.
@ocombe ๋น์ ๋ง ์ ๋ฐ์ดํธ๋ฅผ ๊ฒ์ํ ์ ์๋๋ก ์ ๊ธ ์ ์์ต๋๋ค. "์ธ์ ์๋ฃ๋์๋์?" ์ฝ๋ฉํธ
@ocombe Ivy๋ ์ด์ ๋๋ต 94%๊ฐ ๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ฐ๋ง์ฏค์๋ ์ค๋น๊ฐ ๋ ๊ฒ ๊ฐ์ต๋๊น?
๋๋ ๊ทธ๋ ๊ฒ ์๊ฐํ์ง ์๋๋ค. ๊ธฐ๋ฅ์ด ์ค๋น๋์ด ์๊ณ ๋ฒ๊ทธ๊ฐ ์๋ ๊ฒ(= ์ฌ์ฉ ๊ฐ๋ฅํจ)์ ๋งค์ฐ ๋ค๋ฆ ๋๋ค. ํ์ฌ ๋๋ถ๋ถ ์์ ์์ ์ ํ๊ณ ์์ต๋๋ค.
@ocombe i18n์ด Angular 8๋ณด๋ค ๋จผ์ ๋์๋ค๋ ์ฌ์ค์ ๋ฏฟ์ ์ ์์ต๋๊น?
๋๋ ๊ทธ๋ ๊ฒ ์๊ฐํ์ง ์๋๋ค. ๊ธฐ๋ฅ์ด ์ค๋น๋์ด ์๊ณ ๋ฒ๊ทธ๊ฐ ์๋ ๊ฒ(= ์ฌ์ฉ ๊ฐ๋ฅํจ)์ ๋งค์ฐ ๋ค๋ฆ ๋๋ค. ํ์ฌ ๋๋ถ๋ถ ์์ ์์ ์ ํ๊ณ ์์ต๋๋ค.
๋ค, ์ ์ํ ๋ต๋ณ ๊ฐ์ฌํฉ๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
Angular์์ I18N ์ง์์ ์ํด "ํ ํ๋ฆฟ ๋ฒ์ญ"๊ณผ ํจ๊ป "์ฝ๋ ๋ฒ์ญ" ๋ถ๋ถ์ ์ฌ์ฉํ ์ ์์ ๊ฒ์ผ๋ก ์์ํด์ผ ํ ๋(์ฐ๋ง์ ๋ง์ง๋ง ๋ช ๊ฐ์ง ์๊ฒฌ ์ฐธ์กฐ) ์ ๋ฐ์ดํธ @ocombe ๊ฐ ์์ต๋๊น? ์ฐ๋ฆฌ๋ Angular I18n ๊ธฐ๋ฅ๊ณผ ํจ๊ป ngx-translate-polyfill์ ํด๋ฝํํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ง๋ง https://github.com/biesbjerg/ngx-translate-extract CLI๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ์กด xlf ํ์ผ์ ๋ณํฉํ๋ ๋ฐ xlf ์ง์์ ์ฌ์ฉํ ์ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. .
๊ฐ์ฌ ํด์ !
@์๋ฒ ์ฝฉ๊ฒ
ngSwitch๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๋ฉ์์ง๋ฅผ ํ ํ๋ฆฟํํ๋ฏ๋ก i18n ํ๊ทธ๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ์ฒจ๋ถํ ์ ์์ต๋๋ค.
๋ค์ ์ฅํฉํ์ง๋ง ์๋ํฉ๋๋ค!
์ ์ ๊ฐ์ฌํฉ๋๋ค! ๊ฐ์ฅ ์ดํดํ๊ธฐ ์ฌ์ด ๊ฒ ๊ฐ์ต๋๋ค. ์ ์ง๋ฌธ์ ๋ฐฐ์ด์ 10๊ฐ ์ด์๊ณผ ๊ฐ์ด "๋ง์" ๊ฐ์ด ์๋ ์ํฉ์์ ์ด ๊ตฌํ์ ๊ณ์ ์ฌ์ฉํฉ๋๊น? ์ฝ๋๊ฐ ๋งค์ฐ ์ปค์ง ๊ฒ ๊ฐ์ต๋๋ค.
๋๋ ์ฐ๋ฆฌ๊ฐ ๊ทธ ๋ง์ ์ฌ๋๋ค๊ณผ ํจ๊ป ์๋์ง ๋ชจ๋ฅด์ง๋ง ์ ๊ทธ๋ ์ง ์์ต๋๋ค. ๋ฉ์์ง๊ฐ ์ฌ๋ฌ ์์น์์ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค์์น์ i18n ํ๊ทธ์ธ ์์ i18n ๊ตฌ์ฑ ์์๋ฅผ ๋ง๋ญ๋๋ค.
๋ฐ์ด๋น๋
๋ด 23. 1์ 2019 ํด. 19.24 skrev Andrew Bissada [email protected] :
@์๋ฒ ์ฝฉ๊ฒ
ngSwitch๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๋ฉ์์ง๋ฅผ ํ ํ๋ฆฟํํ๋ฏ๋ก i18n ํ๊ทธ๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ์ฒจ๋ถํ ์ ์์ต๋๋ค.
๋ค์ ์ฅํฉํ์ง๋ง ์๋ํฉ๋๋ค!์ ์ ๊ฐ์ฌํฉ๋๋ค! ๊ฐ์ฅ ์ดํดํ๊ธฐ ์ฌ์ด ๊ฒ ๊ฐ์ต๋๋ค. ์ ์ง๋ฌธ์ ๋ฐฐ์ด์ 10๊ฐ ์ด์๊ณผ ๊ฐ์ด "๋ง์" ๊ฐ์ด ์๋ ์ํฉ์์ ์ด ๊ตฌํ์ ๊ณ์ ์ฌ์ฉํฉ๋๊น? ์ฝ๋๊ฐ ๋งค์ฐ ์ปค์ง ๊ฒ ๊ฐ์ต๋๋ค.
โ
๋น์ ์ด ์ธ๊ธ๋์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๋ฐ๋ ๊ฒ์ ๋๋ค.
์ด ์ด๋ฉ์ผ์ ์ง์ ๋ต์ฅํ๊ฑฐ๋ GitHub์์ ๋ณด๊ฑฐ๋ ์ค๋ ๋๋ฅผ ์์๊ฑฐํ์ธ์.
Validator ํด๋์ค์์ i18n-polifills๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ. i18n ์๋น์ค๋ฅผ ํตํด ์๋ฐํ ์ ํจ์ฑ ๊ฒ์ฌ๊ธฐ ๋ฉ์์ง๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
//์ปดํฌ๋ท์์
this.crForm= this.fb.group({
์ฌ์ฉ์ ์ด๋ฆ: [''],
์ ์๋น๋ฐ๋ฒํธ: [''],
}, { ๊ฒ์ฆ์ธ: ์๋ก์ด AccValidator(this.i18n).validate()}
);
//๊ฒ์ฆ๊ธฐ
import { AbstractControl, ValidationErrors, FormGroup, FormControl } from '@angular/forms';
'@ngx-translate/i18n-polyfill'์์ { I18n } ๊ฐ์ ธ์ค๊ธฐ;
๋ด๋ณด๋ด๊ธฐ ํด๋์ค AccValidator{
์์ฑ์(i18n:I18n)
{
}
validate() {
return (group: FormGroup): createAccountError => {
if (group) {
this.i18n("test");
}}}
์ค๋ฅ ์๋์ ์ ์
RROR ์ค๋ฅ: ์กํ์ง ์์(์ฝ์ ์ค): TypeError: i18n์ ํจ์๊ฐ ์๋๋๋ค.
TypeError: i18n์ ํจ์๊ฐ ์๋๋๋ค.
FormGroup.eval์์ [๊ฒ์ฆ์ธ์ผ๋ก] (acc-validator.ts:9)
FormGroup.AbstractControl._runValidator์์(forms.js:3433)
FormGroup.AbstractControl.updateValueAndValidity(forms.js:3387)์์
์ FormGroup์์(forms.js:4326)
FormBuilder.group์์(forms.js:7864)
@์ค์ฝค๋ฒ
.ts ํ์ผ์์ const์ ํจ๊ป i18n-polyfills๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
๋ด๋ณด๋ด๊ธฐ const ์ฉ์ด ๋ชจ๋ธ= () => [
{
์ ๋ชฉ: 'ํ
์คํธ ๋ฐ์ดํฐ',
ํ์ฑ: ์ฌ์ค,
๋ฐ์ดํฐ: [
[
{
title: 'test data',
data: "test data."
},
{
title: 'test data',
data: "test data"
},
{
title: 'test data',
data: "test data"
},
{
title: 'test data',
data: "test data."
},
{
title: 'Past Due',
data: "test data."
}
]]}];
์น๋ช
์ ### & ์น๊ณผ{Catastrophic y Dental} ์น๋ช
์ {Catastrophic} }
ํน์ ๋ฌธ์๊ฐ ์๋ ICU ํํ์์ ์ฌ์ฉํ ๋ ๋ณํ๋์ง ์์ต๋๋ค.
@ocombe i18n-polyfill์ ์ฌ์ฉํ์ฌ ์ด๋ ๊ฒฝ๋ก๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?
๋ด๋ณด๋ด๊ธฐ const ๊ฒฝ๋ก: ๊ฒฝ๋ก = [
{
๊ธธ: '',
๊ตฌ์ฑ ์์: ํ ๊ตฌ์ฑ ์์,
๋ฐ์ดํฐ: {
์ ๋ชฉ: '์ง',
์ด๋ ๊ฒฝ๋ก: 'ํ'
}
}
]
@์ค์ฝค๋ฒ
.ts ํ์ผ์์ const์ ํจ๊ป i18n-polyfills๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
๋ด๋ณด๋ด๊ธฐ const ์ฉ์ด ๋ชจ๋ธ= () => [
{
์ ๋ชฉ: 'ํ ์คํธ ๋ฐ์ดํฐ',
ํ์ฑ: ์ฌ์ค,
๋ฐ์ดํฐ: [[ { title: 'test data', data: "test data." }, { title: 'test data', data: "test data" }, { title: 'test data', data: "test data" }, { title: 'test data', data: "test data." }, { title: 'Past Due', data: "test data." }
]]}];
๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
{
๋ฐ์ดํฐ: 'ํ
์คํธ ๋ฐ์ดํฐ',
์ ๋ชฉ: this.i18n({ ๊ฐ: '์ด๋ฆ', id: '์ด๋ฆ' }),
}
๋ค์๊ณผ ๊ฐ์ด ๊ตฌ์ฑ ์์ ์์ฑ์์ I18n ํด๋ฆฌํ์ ์ฃผ์
ํ์ญ์์ค.
๊ฐ์ธ i18n: I18n
ts ํ์ผ์์ ๋ฒ์ญ์ ์ฌ์ฉํ ๋ ํด๋น ts ํ์ผ์ ๋ฒ์ญํ๋ ค๋ฉด ngx-extractor ๋ฐ xliffmerge๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. https://www.npmjs.com/package/ngx-i18nsupport
@ JanneHarju
์๋ํ์ง ์๊ณ xlf ํ์ผ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค์ง ์์ต๋๋ค.
์ฌ๊ธฐ ๋ด ๋ฒ์ญ ์คํฌ๋ฆฝํธ๊ฐ ์์ต๋๋ค:
"translate-i18n": "ng xi18n --output-path locale && ngx-extractor -i src/**/*.ts projects/**/*.ts -f xlf -o src/locale/messages.xlf && xliffmerge --profile xliffmerge.json fi en",
์ฌ๊ธฐ xliffmerge.json์ด ์์ต๋๋ค.
{
"xliffmergeOptions": {
"srcDir": "src/locale",
"genDir": "src/locale",
"i18nFile": "messages.xlf",
"defaultLanguage": "en",
"useSourceAsTarget": true
}
}
@ JanneHarju
์, ๋์ผํ ๊ตฌ์ฑ์ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ xlf ํ์ผ์์ .ts ๋ฉ์์ง๋ฅผ ์ถ์ถํ ์ ์์ต๋๋ค.
ํ์ง๋ง const๋ ๋ค๋ฅธ .ts ํ์ผ์ ์์ต๋๋ค.
๋ด๋ณด๋ด๊ธฐ const ์ฉ์ด ๋ชจ๋ธ= () => [
{
}
i18n์ const์ ํจ๊ป ์ฌ์ฉํ๋ ค๊ณ ํ ๋ ๊ตฌ์ฑ ์์์์ ๊ฐ์ ธ์ค๊ณ ์๋๋ฐ ๊ฐ์ ์ถ์ถํ์ง ์์ต๋๋ค.
provider์ ๊ฐ์ const ๊ฐ์ ์ฌ์ฉํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
{
provide: glossayModel,
useFactory: () => glossayModel()
}
์ฝ๋๊ฐ ๊นจ์ง ์ ์์ง๋ง ํฌ์ธํธ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
๋นต ๋ถ์ค๋ฌ๊ธฐ๋ฅผ ๋ฒ์ญํ๋ ๋ฐฉ๋ฒ
const ๊ฒฝ๋ก: ๊ฒฝ๋ก = [
{
๊ฒฝ๋ก: './enroll-new.component',
๊ตฌ์ฑ ์์: EnrollNewComponent,
๋ฐ์ดํฐ: {
์ด๋ ๊ฒฝ๋ก: '๋ฑ๋ก'
},
}
]
์ด ์ค๋ ๋๋ฅผ i18n-polyfill ๋๋ ๊ธฐํ ๋ฌธ์ ์ ๋ํ ์ง์ ์ค๋ ๋๋ก ์ฌ์ฉํ๋ ๊ฒ์ ์ค๋จํ ์ ์์ต๋๊น? i18n-polyfill์ ๋ํ ์ง๋ฌธ์ด ์๋ ๊ฒฝ์ฐ ํด๋น ์ ์ฅ์์์ ๋ฌธ์ ๋ฅผ ์ ๊ธฐํ์ญ์์ค.
@ocombe ์ด ์ฃผ์ ๋ฅผ ์ ๊ธ ์ ์์ต๋๊น? ๊ฑฐ์ ๋ชจ๋ ์ค์ํ ๊ฒ์ ๋ค๋ฃจ์ด์ผ ํฉ๋๋ค.
์ด ์ฃผ์ ์์ ์ธ๊ธํ i18n ์ง์์ ์ถ์ํ Angular ๋ฒ์ ์ ๋ฌด์์
๋๊น?
์, ์ง๊ธ์ ์ ๊ฒจ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ์ตํธ์ธ ๋ฒ ํ๋ก v8์์ ์์ด๋น๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ์ด์ฌํ ๋
ธ๋ ฅํ๊ณ ์์ต๋๋ค. ๋ฐํ์ i18n์ google ํด๋ก์ (google์ด ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ)์ ํจ๊ป ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ์ด๋ฅผ ํตํด ๋๋ฒ๊ทธํ ์ ์์ต๋๋ค(๋งค์ฐ ํฐ ๋ณํ์
๋๋ค). ๋ค๋ฅธ ๋ชจ๋ ์ฌ๋๋ค์ i18n์ผ๋ก ์์ด๋น๋ฅผ ํ
์คํธํ ์ ์์ง๋ง ๋ฒ์ญ์ ๋ก๋ํ ์๋ ์์ต๋๋ค. ์ฑ์ ์ฑ์ ์ฝ๋ฉํ๋ ๋ฐ ์ฌ์ฉ๋ ์๋ ์ธ์ด๋ก ์คํ๋ฉ๋๋ค.
์ค์ ๋ก ๋ฒ์ญํ๋ ๋ฐ ํ์ํ ๋ฐํ์ ์๋น์ค๋ ํ์ฌ ๋ฒ์ญ๋์ง ์์ ํ
์คํธ๋ฅผ ๋ฐํํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๋ชจ๋ ๊ธฐ์กด ์ฝ๋๋ก ๋ฒ๊ทธ๋ฅผ ์์ ํ๊ธฐ ์ํด ๋
ธ๋ ฅํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์๋ก์ด ๊ธฐ๋ฅ์ ๋ฆด๋ฆฌ์ค ์ดํ๋ก ์ ํ๋ฉ๋๋ค. v8์ด ๋์ค๋ฉด ์์
ํ ๊ฒ์
๋๋ค. ์ด๊ฒ์ด ์ ์ ์ฒซ ๋ฒ์งธ ์์
์ด ๋์ด์ผ ํฉ๋๋ค.
์๋ก์ด ์์์ด ์์ผ๋ฉด ์
๋ฐ์ดํธ๋ฅผ ์ถ๊ฐํ๊ณ ์ด ์ค๋ ๋์ ์ ๊ธ์ ํด์ ํ๊ฒ ์ต๋๋ค.
์ฐ๋ฆฌ๊ฐ ์์
ํ๊ณ ์๋ ์๋ก์ด $localize
ํ๊ทธ๋ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
์
const name = 'World';
$localize `Hello ${name}:name!`;
๊ทธ๋ฐ ๋ค์ ์ปดํ์ผ ํ์(๋๋ ๋ฐํ์)์ ๋์ฒดํ ์ ์๋ Hello {$name}!
์ ๋ํ ๋ฒ์ญ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
์ด์ ์ฌ์ฉํ ์ ์์ต๋๋ค(๋ฌธ์ํ๋์ง ์์ ๊ฒฝ์ฐ).
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ด๊ฒ์ด ์ง์ ํ ์ผ์คํ ํผ๋ผ๊ณ ์๊ฐํฉ๋๋ค. i18n์ ์ด๊ฒ์ด ๊ตฌํ๋ ๋๊น์ง ์ฌ์ฉํ ์ค๋น๊ฐ ๋์ง ์์์ต๋๋ค.
์๋ฅผ ๋ค์ด ์ฝ๋์์ ๋ฒ์ญ๋ ์ ํจ์ฑ ๊ฒ์ฌ ๋ฉ์์ง๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.