Repository: xiCO2k/laravel-vue-i18n
Pull request #13 (2022-01-31 06:53:38)

add new wTrans and wTransChoice
will watch any changes happens to the activeMessages object and then return the correct translation

the new wTrans and wTransChoice returns a Ref<T> `ComputedRef<T>` which enables vue to watch and recalculate any changes that happens to the translation.

so any changes to the current language or the files loading took more time it will always return the newest version of the translation. 


Patch:
diff --git a/README.md b/README.md
index f034cb4..5f510d5 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,32 @@ trans('Welcome, :name!', { name: 'Francisco' }) // Bem-vindo Francisco!
 trans('Welcome, :NAME!', { name: 'Francisco' }) // Bem-vindo FRANCISCO!
 ```
 
+### `wTrans(message: string, replacements: {})`
+
+The `wTrans()` same as `trans()` but returns a reactive obj with translated value,
+use it instead of `trans()` to watch any changes (language changes or lang files loaded) and set the new value.
+```jsx
+// lang/pt.json
+{
+    "Welcome!": "Bem-vindo!",
+    "Welcome, :name!": "Bem-vindo, :name!",
+}
+
+import { wTrans } from 'laravel-vue-i18n';
+
+setup() {
+    return {
+        welcomeLabel: wTrans('Welcome!'),
+        welcomeFrancisco: wTrans('Welcome, :name!', { name: 'Francisco' })
+    } 
+}
+
+<template>
+    <div>{{ welcomeLabel }}</div> // <div>Bem-vindo!</div>
+    <div>{{ welcomeFrancisco }}</div> // <div>Bem-vindo, Francisco!</div>
+</template>
+```
+
 ### `transChoice(message: string, count: number, replacements: {})`
 
 The `transChoice()` method can translate a given message based on a count,
@@ -97,6 +123,36 @@ transChoice('{0} There are none|[1,19] There are some|[20,*] There are many', 19
 transChoice('{1} :count minute ago|[2,*] :count minutes ago', 10); // Há 10 minutos.
 ```
 
+
+### `wTransChoice(message: string, count: number, replacements: {})`
+
+The `wTransChoice()` same as `transChoice()` but returns a reactive obj with translated value,
+use it instead of `transChoice()` to watch any changes (language changes or lang files loaded) and set the new value.
+
+
+```jsx
+// lang/pt.json
+{
+    "There is one apple|There are many apples": "Existe uma maça|Existe muitas maças",
+    "{0} There are none|[1,19] There are some|[20,*] There are many": "Não tem|Tem algumas|Tem muitas",
+    "{1} :count minute ago|[2,*] :count minutes ago": "{1} há :count minuto|[2,*] há :count minutos",
+}
+
+import { wTransChoice } from 'laravel-vue-i18n';
+
+setup() {
+    return {
+        oneAppleLabel: wTransChoice('There is one apple|There are many apples', 1),
+        multipleApplesLabel: wTransChoice('{0} There are none|[1,19] There are some|[20,*] There are many', 19)
+    } 
+}
+
+<template>
+    <div>{{ oneAppleLabel }}</div> // <div>Existe uma maça</div>
+    <div>{{ multipleApplesLabel }}</div> // <div>Tem algumas</div>
+</template>
+```
+
 ### `loadLanguageAsync(lang: string)`
 
 The `loadLanguageAsync()` can be used to change the location during the runtime.
diff --git a/src/index.ts b/src/index.ts
index 9579d0e..852eade 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,4 +1,4 @@
-import { reactive, Plugin } from 'vue'
+import { reactive, Plugin, computed, ComputedRef } from 'vue'
 import { OptionsInterface } from './interfaces/options'
 import { LanguageInterface } from './interfaces/language'
 import { LanguageJsonFileInterface } from './interfaces/language-json-file'
@@ -67,22 +67,36 @@ export function loadLanguageAsync(lang: string): Promise<string | void> {
  * Get the translation for the given key.
  */
 export function trans(key: string, replacements: ReplacementsInterface = {}): string {
+  return wTrans(key, replacements).value
+}
+
+/**
+ * Get the translation for the given key and watch for any changes.
+ */
+export function wTrans(key: string, replacements: ReplacementsInterface = {}): ComputedRef<string> {
   if (!activeMessages[key]) {
     activeMessages[key] = key
   }
 
-  return makeReplacements(activeMessages[key], replacements)
+  return computed(() => makeReplacements(activeMessages[key], replacements))
 }
 
 /**
  * Translates the given message based on a count.
  */
 export function transChoice(key: string, number: number, replacements: ReplacementsInterface = {}): string {
-  const message = trans(key, replacements)
+  return wTransChoice(key, number, replacements).value
+}
+
+/**
+ * Translates the given message based on a count and watch for changes.
+ */
+export function wTransChoice(key: string, number: number, replacements: ReplacementsInterface = {}): ComputedRef<string> {
+  const message = wTrans(key, replacements)
 
   replacements.count = number.toString()
 
-  return makeReplacements(choose(message, number, options.lang), replacements)
+  return computed(() => makeReplacements(choose(message.value, number, options.lang), replacements))
 }
 
 /**


Test patch:
diff --git a/test/fixtures/lang/en.json b/test/fixtures/lang/en.json
index 2a8a55e..fa7a1da 100644
--- a/test/fixtures/lang/en.json
+++ b/test/fixtures/lang/en.json
@@ -1,5 +1,6 @@
 {
     "Welcome!": "Wecome!",
     "Welcome, :name!": "Bem-vindo, :name!",
-    "Only Available on EN": "Only Available on EN"
+    "Only Available on EN": "Only Available on EN",
+    "{1} :count minute ago|[2,*] :count minutes ago": "{1} :count minute ago|[2,*] :count minutes ago"
 }
diff --git a/test/plurization.test.ts b/test/plurization.test.ts
index e6e348c..1104cae 100644
--- a/test/plurization.test.ts
+++ b/test/plurization.test.ts
@@ -1,4 +1,4 @@
-import { trans_choice, transChoice } from '../src';
+import { trans_choice, transChoice, wTransChoice, loadLanguageAsync } from '../src';
 
 it.each([
   ['first', 'first', 1],
@@ -71,3 +71,18 @@ it('translates even using an alias "trans_choice"', async () => {
   expect(trans_choice('{1} :count minute ago|[2,*] :count minutes ago', 3))
     .toBe('há 3 minutos');
 })
+
+
+it('translates "wTransChoice" and test language change values', async () => {
+  await global.mountPlugin()
+
+  const translation = wTransChoice('{1} :count minute ago|[2,*] :count minutes ago', 3)
+  expect(translation.value)
+    .toBe('há 3 minutos');
+
+  await loadLanguageAsync('en');
+  
+  expect(translation.value)
+    .toBe('3 minutes ago');
+
+})
diff --git a/test/translate.test.ts b/test/translate.test.ts
index 04c076c..4af6bf7 100644
--- a/test/translate.test.ts
+++ b/test/translate.test.ts
@@ -1,5 +1,5 @@
 import { mount } from '@vue/test-utils'
-import { i18nVue, trans, trans_choice, loadLanguageAsync, reset, getActiveLanguage, isLoaded } from '../src'
+import { i18nVue, trans, trans_choice, loadLanguageAsync, reset, getActiveLanguage, isLoaded, wTrans } from '../src'
 
 beforeEach(() => reset());
 
@@ -94,3 +94,16 @@ it('checks if is a lang is loaded', async () => {
   await loadLanguageAsync('zh_TW');
   expect(isLoaded('zh_TW')).toBe(true);
 })
+
+it('checks if watching translation works', async () => {
+  await global.mountPlugin();
+
+  const translated = wTrans("Welcome!");
+  expect(translated.value)
+    .toBe('Bem-vindo!')
+
+  await loadLanguageAsync('en')
+
+  expect(translated.value)
+    .toBe('Wecome!')
+})