Repository: xiCO2k/laravel-vue-i18n (ts)

Issue:
Support for html in translation strings
Some of my translation strings contain html, but when the strings are displayed the html breaks. This is because the "/" characters are replaced with ".".

Example:

`<div v-html="$t('Hello <strong>:name</strong>!', { name: 'World' })" />`

outputs:

`<div>Hello <strong>World<.strong>!</div>`

Is there a way to circumvent this behavior? (without removing the html from the translations...)

All `/` are replaced with `.`
If a translatable key is not in the source file, then the `wTrans()` will replace all slashes with dots in it.

That's the case when English strings are used as an input to the translation functions with the plan for later to become IDs for their localizations.

**Current behavior:**

```javascript
import { trans } from 'laravel-vue-i18n';

console.assert(trans('Active / Overdue') === 'Active . Overdue'); // true
```

**Expected behavior**

```javascript
import { trans } from 'laravel-vue-i18n';

console.assert(trans('Active / Overdue') === 'Active / Overdue'); // true
```

To overcome this issue, you're forced to create the `en.json` where keys and values are going to be equal however why would you need that file to translate English into English?

Pull request:
fix: Translations with `/` no need to replace with `.`.
Closes #114 and #115.

Patch:
diff --git a/src/index.ts b/src/index.ts
index 3a68bd2..eb0caa5 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -381,22 +381,7 @@ export class I18n {
    * Get the translation for the given key and watch for any changes.
    */
   wTrans(key: string, replacements: ReplacementsInterface = {}): ComputedRef<string> {
-    if (!this.activeMessages[key] && !this.activeMessages[`${key}.0`]) {
-      key = key.replace(/\//g, '.')
-    }
-
-    if (!this.activeMessages[key]) {
-      const hasChildItems = this.activeMessages[`${key}.0`] !== undefined
-
-      if (hasChildItems) {
-        const childItems = Object.entries(this.activeMessages)
-          .filter((item) => item[0].startsWith(`${key}.`))
-          .map((item) => item[1])
-        this.activeMessages[key] = reactive(childItems)
-      } else {
-        this.activeMessages[key] = key
-      }
-    }
+    this.activeMessages[key] = this.findTranslation(key) || this.findTranslation(key.replace(/\//g, '.')) || key
 
     return computed(() => this.makeReplacements(this.activeMessages[key], replacements))
   }
@@ -419,6 +404,27 @@ export class I18n {
     return computed(() => this.makeReplacements(choose(message.value, number, this.options.lang), replacements))
   }
 
+  /**
+   * Find translation in memory.
+   */
+  findTranslation(key) {
+    if (this.activeMessages[key]) {
+      return this.activeMessages[key]
+    }
+
+    const hasChildItems = this.activeMessages[`${key}.0`] !== undefined
+
+    if (hasChildItems) {
+      const childItems = Object.entries(this.activeMessages)
+        .filter((item) => item[0].startsWith(`${key}.`))
+        .map((item) => item[1])
+
+      return reactive(childItems)
+    }
+
+    return this.activeMessages[key]
+  }
+
   /**
    * Make the place-holder replacements on a line.
    */
diff --git a/src/mix.ts b/src/mix.ts
index 2fd3b89..ac6bb1f 100644
--- a/src/mix.ts
+++ b/src/mix.ts
@@ -51,10 +51,7 @@ mix.extend(
 
       config.plugins.push(
         new BeforeBuildPlugin(() => {
-          files = generateFiles(this.langPath, [
-            ...parseAll(this.frameworkLangPath),
-            ...parseAll(this.langPath)
-          ])
+          files = generateFiles(this.langPath, [...parseAll(this.frameworkLangPath), ...parseAll(this.langPath)])
         })
       )
 


Test patch:
diff --git a/test/fixtures/lang/pt.json b/test/fixtures/lang/pt.json
index 4afd8fe..0dcbd72 100644
--- a/test/fixtures/lang/pt.json
+++ b/test/fixtures/lang/pt.json
@@ -5,5 +5,6 @@
     "{1} :count minute ago|[2,*] :count minutes ago": "{1} há :count minuto|[2,*] há :count minutos",
     "foo.bar": "baz",
     "Start/end": "Início/Fim",
-    "Get started.": "Comece."
+    "Get started.": "Comece.",
+    "<div>Welcome</div>": "<div>Bem-vindo</div>"
 }
diff --git a/test/translate.test.ts b/test/translate.test.ts
index 5dc4d9b..1e3b434 100644
--- a/test/translate.test.ts
+++ b/test/translate.test.ts
@@ -233,3 +233,15 @@ it('does not translate existing strings which contain delimiter symbols', async
   expect(trans('Start/end')).toBe('Início/Fim');
   expect(trans('Get started.')).toBe('Comece.');
 })
+
+it('allows to use html tags on translations', async () => {
+  await global.mountPlugin()
+
+  expect(trans('<div>Welcome</div>')).toBe('<div>Bem-vindo</div>');
+})
+
+it('allows to use html tags on translations even if the key does not exist', async () => {
+  await global.mountPlugin()
+
+  expect(trans('<div>Not Exist</div>')).toBe('<div>Not Exist</div>');
+})