Reputation: 381
With new Angular 9 @angular/localize is now possible to translate code directly from typescript. As its usage is not officially well documented, I found some tips on this post.
$localize`:@@my-trans-unit-id:` // IT WORKS
That works correctly when ID is directly passed to the function, but if I want ID to be dynamic (and pass a variable), it does not work, rendering ID without parsing nor translating.
I tried it by passing the variable this way:
const id = "my-trans-unit-id";
$localize`:@@${id}:`; // NOT WORKING
$localize`:@@`+id+`:`; // NOT WORKING
Upvotes: 11
Views: 6723
Reputation: 731
This works.
Don't ask me to explain, I got this by trial and error:
const localize = $localize;
const id = "my-trans-unit-id";
const translation = localize(<any>{ '0': `:@@${id}:${id}`, 'raw': [':'] });
Upvotes: 9
Reputation: 547
You can create your own tagged templates function to handle transformation of the trans-unit id:
const transUnitId = '@@Messages.Greeting';
const name = 'Joe';
const message = $localizeId`${transUnitId}:TRANSUNITID:Hi ${name}:NAME:, translated with run-time created trans-unit id.`;
// Original
// message = Hi Joe, translated with run-time created trans-unit id.
// German
// message = Hallo Joe, übersetzt mit einer zur Laufzeit erstellten Trans-Unit-Id.
export function $localizeId(messageParts: TemplateStringsArray, ...expressions: any[]): string {
// Create writeable copies
const messagePartsCopy: any = [...messageParts];
const messagePartsRawCopy = [...messageParts.raw];
// Strip trans-unit-id element
const prefix = messagePartsCopy.shift();
const prefixRaw = messagePartsRawCopy.shift();
const transUnitId = expressions.shift();
// Re-add prefix and replace :TRANSUNITID: with transUnitId.
messagePartsCopy[0] = prefix + messagePartsCopy[0].replace(':TRANSUNITID:', `:@@${transUnitId}:`);
messagePartsRawCopy[0] = prefixRaw + messagePartsRawCopy[0].replace(':TRANSUNITID:', `:${transUnitId}:`);
// Create messageParts object
Object.defineProperty(messagePartsCopy, 'raw', {value: messagePartsRawCopy});
// Call original localize function
return $localize(messagePartsCopy as TemplateStringsArray, ...expressions);
}
Upvotes: 1
Reputation: 381
Angular does not provide any mechanism to generate dynamic translations as they are generated at compile time.
I ended up creating pipes and calling them every time I need a translation. Instead of using 1 unique instruction to translate the string, I use multiple $localize
calls inside a switch to return proper translation by ID.
This is an example for translating order status that can be called on runtime:
import { Pipe, PipeTransform } from '@angular/core';
import { OrderStatusEnum } from 'installation-status.enum';
@Pipe({
name: 'orderStatusRenderer'
})
export class OrderStatusRendererPipe implements PipeTransform {
constructor() {}
transform(value: number, ...args: any[]): any {
switch (value) {
case OrderStatusEnum.PREPARING:
return $localize`:@@order.status.preparing:`;
case OrderStatusEnum.SHIPPED:
return $localize`:@@order.status.shipped:`;
case OrderStatusEnum.COMPLETED:
return $localize`:@@order.status.completed:`;
}
}
}
Upvotes: 10