Reputation: 672
I am working on an Angular@11 application and facing an issue. In my app there are two panels, left and right. I want to translate the left panel in Spanish and the right one in German.
Using @ngx-translate/core, it will translate both panels in any one language at a time, but I want to translate both panels in different languages.
Any kind of help is appreciable.
Upvotes: 2
Views: 2838
Reputation: 6706
You can achieve that by creating your own translate
pipe, to use it instead of the default one provided by ngx-translte
.
The new custom translate
pipe should depend on the same translations provided by TranslateService
, and handle the most logic handled by the default translate
pipe, but without handling the onLangChange
, onDefaultLangChange
, or onTranslationChange
events.
You can try something like the following:
import {
ChangeDetectorRef,
Injectable,
Pipe,
PipeTransform,
} from '@angular/core';
import { isObservable } from 'rxjs';
import { TranslateService } from '@ngx-translate/core';
@Injectable()
@Pipe({
name: 'translateBy',
pure: false, // required to update the value when the promise is resolved
})
export class TranslatePipe implements PipeTransform {
value: string = '';
lastKey: string;
lastParams: any[];
constructor(
private translate: TranslateService,
private _ref: ChangeDetectorRef
) {}
updateValue(
key: string,
interpolateParams?: Object,
translations?: any
): void {
let onTranslation = (res: string) => {
this.value = res !== undefined ? res : key;
this.lastKey = key;
this._ref.markForCheck();
};
if (translations) {
let res = this.translate.getParsedResult(
translations,
key,
interpolateParams
);
if (isObservable(res.subscribe)) {
res.subscribe(onTranslation);
} else {
onTranslation(res);
}
} else this.translate.get(key, interpolateParams).subscribe(onTranslation);
}
transform(query: string, lang: string, ...args: any[]): any {
if (!query || !query.length) {
return query;
}
// if we ask another time for the same key, return the last value
if (equals(query, this.lastKey) && equals(args, this.lastParams)) {
return this.value;
}
let interpolateParams: Object;
if (!!args[0] && args.length) {
if (typeof args[0] === 'string' && args[0].length) {
// we accept objects written in the template such as {n:1}, {'n':1}, {n:'v'}
// which is why we might need to change it to real JSON objects such as {"n":1} or {"n":"v"}
let validArgs: string = args[0]
.replace(/(\')?([a-zA-Z0-9_]+)(\')?(\s)?:/g, '"$2":')
.replace(/:(\s)?(\')(.*?)(\')/g, ':"$3"');
try {
interpolateParams = JSON.parse(validArgs);
} catch (e) {
throw new SyntaxError(
`Wrong parameter in TranslatePipe. Expected a valid Object, received: ${args[0]}`
);
}
} else if (typeof args[0] === 'object' && !Array.isArray(args[0])) {
interpolateParams = args[0];
}
}
// store the query, in case it changes
this.lastKey = query;
// store the params, in case they change
this.lastParams = args;
// set the value
this.updateValue(
query,
interpolateParams,
this.translate.translations[lang] // <<<<< This is the main requried change to return the translation for the provided lang.
);
return this.value;
}
}
And in the component, you can use it like the following:
<span>ES Value: {{ "MAIN_TITLE" | translateBy: "es" }}</span>
<span>DE Value: {{ "MAIN_TITLE" | translateBy: "de" }}</span>
P.S. The above custom pipe (and the original pipe also) uses the equals
function to check if the args
and lastParams
are equal or not. You can copy the ngx-translate
eqauls function and use it in your code, or you can use any other deeply equals
functions (e.g. lodash
isEqual)
Upvotes: 3