Closed mrin9 closed 7 years ago
[translateParams] also not working with [innerHTML]
I'm having same problem, any update on this?
You cannot have angular directive / components / pipes / ... in your translations, it's a limitation of angular because you cannot call the compiler after bootstrap (unless you're lazy loading a module, and that's just in JIT). I'm sorry but it's not possible with this library. You can do it with angular i18n (the official thing), but not with any external library.
import { AfterViewInit, Directive, ElementRef, Input, OnDestroy, Renderer2 } from '@angular/core'; import { TranslateService } from 'translate-core'; import { Router } from '@angular/router';
@Directive({ selector: '[appTranslate]' }) export class TranslateDirective implements AfterViewInit, OnDestroy { @Input() appTranslate: string; listenClickFunc: Function;
constructor(private element: ElementRef, private translate: TranslateService, private router: Router, private renderer: Renderer2) {}
ngAfterViewInit() { this.translate.get(this.appTranslate).subscribe((translateText: string) => { this.element.nativeElement.innerHTML = translateText; // this.cdRef.detectChanges();
const navigationElements = Array.prototype.slice.call(this.element.nativeElement.querySelectorAll('a[routerLink]'));
navigationElements.forEach(elem => {
this.listenClickFunc = this.renderer.listen(elem, 'click', (event) => {
event.preventDefault();
this.router.navigate([elem.getAttribute('routerLink')]);
});
});
});
}
ngOnDestroy() { this.listenClickFunc(); }
}
<div [appTranslate]="'MSG'"></div>
@vadost thanks for the workaround, I am doing something similar at present.
@ocombe, First of all thanks for such an awesome and simple to use framework, we found it much more easier than angular's own i18n.
Though I cannot fully comprehend how it is a limitation, as I didnt got into the internal workings of it, but If it is a limitation, was wondering would it be possible to take care of only few special/popular directives to preserve them as is in the final output?
At runtime (when the library runs), the compiler is not available, which means that you cannot compile the templates.
If you need a directive / component / pipe, you have to put it outside of your translations (by splitting the translations for example).
In the case of You may <a routerLink='/login'> Sign in </a> again
you would need to split it in 3: "You may", "Sign in" and "again".
It's a pain, I know, but there's no other way.
now I see why thats an issue, Thanks for explaining this !
@ocombe That would not work for many languages as they need to shift words in sentence like:
<a routerLink='/login'> Sign in </a>you may again.
It's very common to do that in Chinese.
@duall That's exactly why you split it into 3. Languages that don't need text before the link have a blank value for the first key.
@christarczon Do you really want to put a blank value before every element in your website ?
@duall Create your custom directive! An example you can see from above!
@vadost Sorry, for angular4 who is
import { TranslateService } from 'translate-core';
I'm trying to apply the directive but something is missing... could you have a plunker??
So, to be clear, does this mean that an existing, working angularJS app that features custom directives inserted by ng-bind-html, then compiled with $compile, cannot be upgraded to angular 2+? And that there isn't even a workaround? Given that for back-compatibilty reasons the inserted HTML content cannot be changed, is the app now stuck with the end-of-life angularJS forever? I'm sorry, but that seems to be a major hole in angular, which I would hope to see addressed in a release sooner rather than later.
Yes, there is no alternative to $compile. Custom runtime-created templates will be possible with the next renderer (ivy) in Angular 7, but probably not for 7.0, it will just be "possible" with the new architecture, which doesn't mean that it'll be available immediately when ivy is released
Thanks for your reply. As I have already invested a lot of time in upgrading the static HTML parts of the app (by far the bigger part of it) to angular 5, I was wondering if a workaround along the following lines might be possible to avoid throwing all that work away.
Keep the angular 5 upgraded components that use static HTML templates. Refactor the angularJS element directive that hosts dynamically added attribute directives, as an angularJS component. So the app now functions as an angular 5/angularJS hybrid, at least until angular 7.x brings runtime template creation.
My question is, will an angularJS component in a hybrid app support the use of $compile in the same way that the element directive in a pure angularJS app does?
I have no idea, maybe @samjulien could tell you
The workaround proposed by @vadost is not ideal from an accessibility point of view, because the href
attribute is missing from the anchor element. Usually the routerLink directive adds the correct href
attribute (see router_link.ts). But since custom directives in translation strings are not possible with with library I propose the following workaround using translate parameters.
HTML
<div [innerHTML]="'MSG' | translate:{ path: '#/login' }"></div>
TRANSLATION
"MSG": "You may <a href=\"{{ path }}\">Sign in</a> again."
Based on the locationStrategy
used in your project, the path parameter has preceding hash symbol (like here) or not.
I'm submitting a ... (check one with "x")
Current behavior
I have the below translation token (includes HTML tag with an angular directive)
"MSG":"You may <a routerLink='/login'> Sign in </a> again"
and my component HTML is
<div [innerHTML]="'MSG' | translate"></div>
The final translation strips of the
routerLink
directiveExpected/desired behavior The final translation should have
routerLink
directiveng2-translate version: 6.0.1