Core: Translate directive whitespace handling can cause erroneous recursive translation

Created on 31 Jan 2019  路  8Comments  路  Source: ngx-translate/core

Current behavior

An HTML element with a translate directive and whose content is a translation key with leading/trailing spaces/newlines will return an erroneous recursive translation when the en.json file has an additional key matching the VALUE of the referenced translation key.

Example HTML:

<div translate>
  NAV_BAR.LINK_TEXT
</div>

Example en.json:

  "NAV_BAR": {
    "LINK_TEXT": "EXAMPLE"
  },
  "EXAMPLE": {
    "THIS": "this",
    "THAT": "that"
  }

With this example setup, the <div> will display [object Object].

Note that the following HTML will _not_ trigger the bug:
<div translate>NAV_BAR.LINK_TEXT</div>

Expected behavior

The <div> should display EXAMPLE.

How do you think that we should fix this?

On this line: https://github.com/ngx-translate/core/blob/master/projects/ngx-translate/core/src/lib/translate.directive.ts#L82

Change if (content!== node.currentValue)
to
if (trimmedContent !== node.currentValue)
because
https://github.com/ngx-translate/core/blob/master/projects/ngx-translate/core/src/lib/translate.directive.ts#L115
explicitly preserves whitespace in the node content, so only the trimmed content must be treated as the key.

Minimal reproduction of the problem with instructions

https://github-ghfrtw.stackblitz.io

Environment


ngx-translate version: 10.0.2
Angular version: 6.1.10

This is still an issue in the latest ngx-translate version.
This was not an issue in ngx-translate 8.0.0

Browser:
- [X ] Chrome (desktop) Version 71.0.3578.98 (Official Build) (64-bit)
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

(Presumably other browsers as well; I didn't check them.)

All 8 comments

I can confirm that this bug exists. I have a similar working example. In my version, the initial binding does work just fine (event with line breaks), but when I change the language at runtime, these values doesn't get updated.

Render Stackblitz
Editor Stackblitz

I also can confirm, that this error is browser independent. Looks the same in Edge (41) and Firefox (64).

@dpmott When you add this missing translation to the fr.json, your initial binding will be correctly show your English translation (that sounds weird, but it works), but when you change the translations at runtime (via translate.use('fr')) the translations with whitespaces wont be updated. You can refer to my example.

I can also confirm, that the error is fixed, when applying the fix mentioned by @dpmott

@BADFOOD Thanks for your thorough investigation.

Do you need a PR from me?

@dpmott I'm no maintainer of the project. I'm just a guy that stumbles upon the same error.

But feel free to create a PR, I did it myself but was not yet able to fix the failing test: 脳 should update the DOM when the lang changes and the translation ends with space

@dpmott Finally I was able to create a PR with no failing tests. But I don't think there will be an bug fix release for 10.X, so I think we have to update to latest angular.

As long as the Pull-Request is not merged, I have use the translate pipe, instead of the translate directive

Instead of using this

<div translate>
   MyText
</div>

becomes

<div >
   {{'MyText' | translate}}
</div>

If you have to translate enums or something else with prefixes, I use this:
Instead of

<div translate>RunState.{{ details?.infusion.status }}</div>

```html

{{ details?.infusion.status | prefix:'RunState.' | translate}}
The prefix pipe is implemented as:
```typescript
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'prefix',
  pure: true
})
export class PrefixPipe implements PipeTransform {
  transform(value: any, args?: any): any {
    const msg = <string>value;
    if (value == null) {
      return null;
    }

    return `${args}${msg}`;
  }
}

When using 12.0.0 with Angular 9 the issue really just got worse for me instead of better.
Before the update the translations via the directive worked initially and just failed to update on language change, now it doesn't work at all when there is a line break.

So like in the example by BADF00D

<div translate>
   MyText
</div>

this would work initially in 11.0.0, but would not update correctly on language change, now it does not work at all anymore...
Only removing the whitespace completely fixes it now (or using the pipe of course)

In the angular apps that I've been writing, I haven't included a dynamic option to change the language. However, the comment from @Crylion above caught my attention, and I've been able to reproduce the described behavior.

I'll file a new issue (as it doesn't seem that a new issue has been created yet), and I'll investigate a fix that will work for everyone.

Update: Opened https://github.com/ngx-translate/core/issues/1163

Was this page helpful?
0 / 5 - 0 ratings