# Inconsistent behaviour in i18n between markup and attributes

**URL:** <https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681>\
**Category:** Help Requests\
**Created:** [January 22, 2018, 11:13pm UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681 "2018-01-22T23:13:52Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jeremyholt](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeremyholt/32/1098_2.png) [@jeremyholt](https://discourse.aurelia.io/u/jeremyholt)\
**Post date:** [January 22, 2018, 11:13pm UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681/1 "2018-01-22T23:13:52Z")

</div>

Given the two almost identical pieces of html

`para 1`

```auto
 <p 
    t="[html]tracking-report.span9" 
    t-params.bind="{
    rowNumber: item.rowNumber, 
    sick: item.sick, 
    dead: item.dead, 
    reason: trSicknessReason(item.reason)
    }">              
 </p>      

```

and

`para 2`

```auto
<p>
    ${"tracking-report.span9" & t:
    {
     rowNumber: item.rowNumber, 
     sick: item.sick, 
     dead: item.dead, 
     reason: trSicknessReason(item.reason)
    }
}.              
 </p>

// I added the extra line breaks to try to make the question clearer

```

My problem is that when i18n.locale() changes, `para 1` does not update the function `trSicknessReason(item.reason)`. However, in `para 2` the function gets updated correctly when the locale changes.

The problem is that I need to unescape the result of the contents.

`para 1` works perfectly well when the page is loaded and does the unescaping of the function through the use of the [html] attribute. However, as I said, the function doesn’t get updated when the locale changes.

I’m quite happy to use `para 2` if only I can find a way to unescape the results. I’ve tried decodeURIComponent() on the return value of the function, but of course it immediately gets escaped when the page is loaded.

It doesn’t make sense that the interpolated value updates while the attribute value does not.

I guess it’s worth mentioning that `trSicknessReason()` does some fairly complicated lookups to find the correct value to translate.

In the worse case scenario I will have to prevent the user from entering illegal characters, but French is full of them 😩

---

<div class="post-metadata">

**Author:** ![zewa666](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/zewa666/32/19_2.png) [@zewa666](https://discourse.aurelia.io/u/zewa666)\
**Post date:** [January 23, 2018, 7:28am UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681/2 "2018-01-23T07:28:03Z")

</div>

Hey could you try to create a minimal example? That would help to analyse the issue

---

<div class="post-metadata">

**Author:** ![jeremyholt](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeremyholt/32/1098_2.png) [@jeremyholt](https://discourse.aurelia.io/u/jeremyholt)\
**Post date:** [January 23, 2018, 11:30am UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681/3 "2018-01-23T11:30:21Z")

</div>

Hi. I’ve managed to extract the relevant parts.

The `report` and the `sicknessReasons` are retrieved from the database.

You don’t actually need the translations files but I included them for good measure.

Change the language to French to see the unescaped content.

Actual web site is at [https://sti.amberwoodtrading.com](https://sti.amberwoodtrading.com). You need to register first. Then go to the tracking pool in the middle of the home page. The problem text is just under the main pictures. I had to change the French translation for `d'Azote` to `de Azote` 😩

```auto
import { autoinject } from "aurelia-framework";
import { I18N } from "aurelia-i18n";

@autoinject
export class ErrorTrackingReport {
  public locales: IListItem[] = [
    { id: "en", name: "English" },
    { id: "fr", name: "French" },
    { id: "pt", name: "Portuguese" }
  ];

// dummy data from db
  public report: IInspectionReport = {
    id: undefined,
    dead: 3,
    sick: 12,
    rowNumber: 2,
    notes: "",
    reason: { id: "id-1", name: "default English value" }
  };

// dictionary items from db
  private sicknessReasons: ITranslations[] = [
    {
      id: "id-1",
      name: "Lack of nitrogen", // default value in English
      translations: [
        { id: "fr", name: "Manque d'Azote" },
        { id: "pt", name: "Falta de nitrogênio" }
      ]
    }
  ];

  constructor(private readonly i18n: I18N) {
  }

  public trSicknessReason(sicknessReason: IListItem) {
    const reason = this.sicknessReasons.find(c => c.id === sicknessReason.id);

    return this.trDictionaryTranslation(reason).toLowerCase();
  }

  public trDictionaryTranslation(item: ITranslations) {
    const locale = this.i18n.getLocale();
    const tr = item.translations.find(c => c.id === locale);

    if (tr && tr.name) {
      return tr.name;
    } else {
      return item.name;
    }
  }

  public async setLocale(lng: string) {
    await this.i18n.setLocale(lng);
  }
}

export interface IListItem {
  id: string;
  name: string;
}

export interface ITranslations extends IListItem {
  translations: IListItem[];
}

export interface IInspectionReport {
  dead: number;
  sick: number;
  reason: IListItem;
  rowNumber: number;
  notes: string;
  id: string;
  active?: boolean;
}

```

```auto
<template>
  <label>Language</label>
  <select class="form-contol" value.bind="selectedLng" change.delegate="setLocale(selectedLng)">
    <option repeat.for="lng of locales" model.bind="lng.id">${lng.name}</option>
  </select>

  <h2>This paragraph does not update when locale changes</h2>
  <p class="para-larger mb-0" t="[html]tracking-report.span9" t-params.bind="{rowNumber: report.rowNumber, sick: report.sick, dead: report.dead, reason: trSicknessReason(report.reason)}">
  </p>

  <h2 class="mt-5">This paragraph updates, but returns unescaped report.reason</h2>
  <p class="para-larger mb-0">
    ${"tracking-report.span9" & t: {rowNumber: item.rowNumber, sick: report.sick, dead: report.dead, reason: trSicknessReason(report.reason)}}.
  </p>

  <code>
    translations.en:
    {
      "tracking-report":
      {
        "span9":"In row {{rowNumber}}, there were {{sick}} sick and {{dead}} dead plants due to {{reason}}"
      }
    }

    translations.fr:
    {
      "tracking-report":
      {
        "span9":"Dans la rangée {{rowNumber}}, il y avait {{sick}} plantes malades et {{dead}} morts à cause de {{reason}}",
      }
    }

    translations.pt:
    {
      "tracking-report":
      {
        "span9":"Dans la rangée {{rowNumber}}, il y avait {{sick}} plantes malades et {{dead}} morts à cause de {{reason}}"
      }
    }

  </code>
</template>

```

---

<div class="post-metadata">

**Author:** ![jeremyholt](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeremyholt/32/1098_2.png) [@jeremyholt](https://discourse.aurelia.io/u/jeremyholt)\
**Post date:** [January 23, 2018, 1:08pm UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681/4 "2018-01-23T13:08:14Z")

</div>

Daniel - I’ve given you access to the site. Your email bounced!

---

<div class="post-metadata">

**Author:** ![zewa666](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/zewa666/32/19_2.png) [@zewa666](https://discourse.aurelia.io/u/zewa666)\
**Post date:** [January 24, 2018, 6:27am UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681/5 "2018-01-24T06:27:59Z")

</div>

So what would really help is to create a small, downloadable example, where I can dig in easily. This way its really more second guessing what could be wrong

---

<div class="post-metadata">

**Author:** ![jeremyholt](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeremyholt/32/1098_2.png) [@jeremyholt](https://discourse.aurelia.io/u/jeremyholt)\
**Post date:** [January 24, 2018, 3:44pm UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681/6 "2018-01-24T15:44:30Z")

</div>

OK - hope this is OK

[https://github.com/jeremy-holt/translation-errors](https://github.com/jeremy-holt/translation-errors)

---

<div class="post-metadata">

**Author:** ![zewa666](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/zewa666/32/19_2.png) [@zewa666](https://discourse.aurelia.io/u/zewa666)\
**Post date:** [January 24, 2018, 4:56pm UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681/7 "2018-01-24T16:56:49Z")

</div>

That definitely helped. So the quick fix would be to go with option 2 and instead of interpolating as the value of the paragraph, binding it to the innerhtml attribute.

```auto
<p innerhtml.bind="'tracking-report.span9' & t: {rowNumber: report.rowNumber, sick: report.sick, dead: report.dead, reason: trSicknessReason(report.reason)}"></p>
  </p>

```

Your use case although is pretty special, so I think that a nested translation would also allow to do the same with Option 1

Update:  
Here’s a patch of how I’d go about implementing it with Option 1 and nested translations

> <https://gist.github.com/zewa666/f936db5803df06707e6b7487e3bf3856>

---

<div class="post-metadata">

**Author:** ![jeremyholt](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/jeremyholt/32/1098_2.png) [@jeremyholt](https://discourse.aurelia.io/u/jeremyholt)\
**Post date:** [January 24, 2018, 7:16pm UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681/8 "2018-01-24T19:16:41Z")

</div>

That’s great - thank you so much for your help.

---

<div class="post-metadata">

**Author:** ![zewa666](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/zewa666/32/19_2.png) [@zewa666](https://discourse.aurelia.io/u/zewa666)\
**Post date:** [January 24, 2018, 7:49pm UTC](https://discourse.aurelia.io/t/inconsistent-behaviour-in-i18n-between-markup-and-attributes/681/9 "2018-01-24T19:49:57Z")

</div>

Np glad i could help
