Repository navigation
Closed
Labels
area: i18nIssues related to localization and internationalizationIssues related to localization and internationalizationfeatureLabel used to distinguish feature request from other issuesLabel used to distinguish feature request from other issuesfreq3: high
Milestone
Description
I'm submitting a ... (check one with "x")
[x] feature request
Current behavior
#9104 (comment)
I don't think it is possible, like I said before it only works with static text, it won't parse text on the js code, only templates
Expected/desired behavior
Be able to translate strings used anywhere in the code, using an API.
Reproduction of the problem
What is the expected behavior?
I'm referencing the usage of $translate.instant to exposure real use cases:
- Custom rendered text:
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);More examples:
Details
- Getting image's file name from exported image of a HTML rendered report: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;
}- Sometimes you're translating, sometimes use model data (could be very verbose in a template):
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', '');
}
}- Using a third party chart plugin (Highcharts)
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')
}
}
}
});- To setup config variables and render the text without pipes as it's not always a translated string
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')
};- To set window.title :) :
SetWindowTitle(title:string) {
if (!!title) {
this.$window.document.title = this.$translate.instant(title);
}
}- Custom date formatting:
dateHuman(date:Date):string {
return date.getDate() + ' ' + this.$translate.instant('GLOBAL_CALENDAR_MONTH_' + date.getMonth())
+ ' ' + date.getFullYear();
}- Sort things based on translated values:
// 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();
});
}- Export raw data to CSV or Excel with translated values:
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;
}- Set config strings to third party plugins:
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')
]
}
});
}Please tell us about your environment:
- Angular version: 2.0.0-rc.6
- Browser: [all]
- Language: [TypeScript 2.0.2 | ES5 | SystemJS]
Reacted by gfrSE, Florian Kinder, Levente Morva, Olivier Combe, Dirk Raeder, Ievgenii Krevenets, Devendra Shangari, Ilkka Nummi, Ross, Kevin Schneider and 298 more
Reacted by Conan06, Rodrigo Interliche, Dmitry Volynkin, Márcio Reis, Stefano Cappa, Klemen Oslaj, Konstantins Starovoitovs, Ben M, Herman Fransen and Dhiego Hendrix Atencio
Reacted by Nicolas Forney, Tautvydas Derzinskas, Nodarii, 神楽坂玲奈, Conan06, Rodrigo Interliche, Jeppe Rune Mortensen, Jimmy Aumard, Chen Reuven, Justus-Maier and 10 more
Metadata
Metadata
Assignees
Labels
area: i18nIssues related to localization and internationalizationIssues related to localization and internationalizationfeatureLabel used to distinguish feature request from other issuesLabel used to distinguish feature request from other issuesfreq3: high
Activity
Mattes83 commentedon Sep 20, 2016
I think this is a real showstopper, i18n is not ready to use until this is implemented.
E.g. I am not able to set translated validation messages in code
marcalj commentedon Sep 20, 2016
@Mattes83 Did you try this way?
manklu commentedon Sep 20, 2016
😕 The documentation tells you how nice it is to have error messages in code and translation support requires anything in the template. Looks like there is more need for communication.
Mattes83 commentedon Sep 21, 2016
@marcalj I know this way...but I need to have localized strings in my ts files.
@manklu I totally agree
vicb commentedon Sep 30, 2016
If someone want to start a design spec, it would be helpful (ie on Google Docs).
It would need to list all the cases. Quickly thinking about it, I see a need for
fbobbio commentedon Oct 14, 2016
Hi guys, great feature request 👍
Is there any suggested workaround to translate *.ts texts?
mstawick commentedon Oct 17, 2016
@fbobbio What I've been doing is create hidden elements in the template, ex.
<span class="translation" #trans-foo i18n>foo</span>.Bind them using:
@ViewChild('trans-foo) transFoo : ElementRef;.Then retrieve translated value
transFoo.nativeElement.textContent.Looks retarded, but works for my needs.
188 remaining items
JanneHarju commentedon Feb 27, 2019
You can use like this
{
data: 'test data',
title: this.i18n({ value: 'Name', id: 'name' }),
}
inject I18n polyfill in component constructor like this
private i18n: I18n
When using translations in ts file you need to use ngx-extractor and xliffmerge to get those ts files to translated. https://www.npmjs.com/package/ngx-i18nsupport
shobhit12345 commentedon Feb 27, 2019
@JanneHarju
its not working , not getting the data in xlf file.
JanneHarju commentedon Feb 27, 2019
Here is my translation script:
"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",and here is xliffmerge.json
shobhit12345 commentedon Feb 27, 2019
@JanneHarju
Yes i m using same configuration , and able to extract .ts messages in xlf file .
But const i have in different .ts files
export const glossayModel= () => [
{
}
i am importing in component , when i m trying to use i18n with const , it is not extracting the values .
JanneHarju commentedon Mar 7, 2019
What if you use const values like provider.
code might be broken but you maybe get point.
shobhit12345 commentedon Mar 19, 2019
how to translate breadcrumbs
const routes: Routes = [
{
path: './enroll-new.component',
component: EnrollNewComponent,
data: {
breadcrumb: 'Enrollment'
},
}
]
ngehlert commentedon Mar 25, 2019
can you people stop using this thread as a support thread for i18n-polyfill or other issues? if you have a question regarding i18n-polyfill go raise an issue in that repo.
@ocombe maybe you can lock this topic? pretty much everything important should be covered.
whats the angular version you plan on releasing the i18n support mentioned in this topic?
ocombe commentedon Mar 25, 2019
Yes, locked for now.
We are working hard to have ivy available with v8 as an opt-in beta. Runtime i18n will be usable with google closure (what google uses internally) which will let us debug it (it's a very big change). For everyone else you will be able to test ivy with i18n but you won't be able to load translations. The app will run with the original language used to code the app.
The runtime service that is needed to actually translate currently returns the text untranslated. Since we're all working on fixing bugs with the existing code, new features will be limited to after the release. We'll work on it once v8 is out, it should be my first task.
I'll add an update and unlock this thread once we have some news.
petebacondarwin commentedon Aug 8, 2019
For what it is worth the new
$localizetag that we are working on can be used programatically.E.g.
And then will be able to provide translations for
Hello {$name}!that can be replaced at compile-time (or run-time).petebacondarwin commentedon Sep 25, 2020
This is now available (if not documented).