diff --git a/__tests__/changeLanguage.spec.ts b/__tests__/changeLanguage.spec.ts index b3c5ccee..c4a0d181 100644 --- a/__tests__/changeLanguage.spec.ts +++ b/__tests__/changeLanguage.spec.ts @@ -1,11 +1,11 @@ import { beforeEach, describe, expect, it } from 'vitest' -import { nextTick } from 'vue-demi' +import { isVue3, nextTick } from 'vue-demi' import { FluentBundle, FluentResource } from '@fluent/bundle' import ftl from '@fluent/dedent' import type { FluentVue } from '../src' -import { createFluentVue } from '../src' +import { createFluentVue, useFluent } from '../src' import { mountWithFluent } from './utils' describe('language change', () => { @@ -104,6 +104,111 @@ describe('language change', () => { expect(mounted.html()).toEqual('link text') }) + it('updates locale even if component is unmounted github.com/orgs/fluent-vue/discussions/834', async () => { + // Arrange + bundleEn = new FluentBundle('en-US') + bundleUk = new FluentBundle('uk-UA') + + const fluent = createFluentVue({ + bundles: [bundleUk], + }) + + const child = { + template: '{{ $t("child") }}', + fluent: { + 'en-US': new FluentResource(ftl` + child = Child message + `), + 'uk-UA': new FluentResource(ftl` + child = Повідомлення + `), + }, + } + + const component = { + components: { + child, + }, + data: () => ({ + show: true, + }), + template: '', + } + + // Act + const mounted = mountWithFluent(fluent, component) + + expect(mounted.html()).toEqual('Повідомлення') + + await mounted.setData({ show: false }) + + if (isVue3) + expect(mounted.html()).toEqual('') + else + expect(mounted.html()).toEqual('') + + fluent.bundles = [bundleEn] + + await mounted.setData({ show: true }) + + // Assert + expect(mounted.html()).toEqual('Child message') + }) + + it('useFluent updates locale even if component is unmounted github.com/orgs/fluent-vue/discussions/834', async () => { + // Arrange + bundleEn = new FluentBundle('en-US') + bundleUk = new FluentBundle('uk-UA') + + const fluent = createFluentVue({ + bundles: [bundleUk], + }) + + const child = { + setup() { + useFluent() + }, + template: '{{ $t("child") }}', + fluent: { + 'en-US': new FluentResource(ftl` + child = Child message + `), + 'uk-UA': new FluentResource(ftl` + child = Повідомлення + `), + }, + } + + const component = { + components: { + child, + }, + data: () => ({ + show: true, + }), + template: '', + } + + // Act + const mounted = mountWithFluent(fluent, component) + + expect(mounted.html()).toEqual('Повідомлення') + + await mounted.setData({ show: false }) + + if (isVue3) + expect(mounted.html()).toEqual('') + else + expect(mounted.html()).toEqual('') + + fluent.bundles = [bundleEn] + + await mounted.setData({ show: true }) + + // Assert + expect(mounted.html()).toEqual('Child message') + }) + it('works when dynamically adding bundles', async () => { // Arrange bundleEn = new FluentBundle('en-US') diff --git a/src/composition.ts b/src/composition.ts index e074f1c0..e1f5f3a5 100644 --- a/src/composition.ts +++ b/src/composition.ts @@ -12,5 +12,5 @@ export function useFluent(): TranslationContext { const rootContext = inject(RootContextSymbol) assert(rootContext != null, 'useFluent called without installing plugin') - return getContext(rootContext, instance.proxy) + return getContext(rootContext, instance.proxy, true) } diff --git a/src/getContext.ts b/src/getContext.ts index 365f8a51..f5113dfb 100644 --- a/src/getContext.ts +++ b/src/getContext.ts @@ -13,6 +13,7 @@ function * flatMap(iterable: Iterable, mapper: (element: T) => TR[]): export function getContext( rootContext: TranslationContext, instance: VueComponent | null | undefined, + fromSetup = false, ): TranslationContext { if (instance == null) return rootContext @@ -50,7 +51,10 @@ export function getContext( const context = new TranslationContext(overriddenBundles, rootContext.options) - options._fluent = context + // If we are in script setup, we cannot cache the context + // because after component is unmounted, computed will not be updated + if (!fromSetup) + options._fluent = context return context } diff --git a/src/types/vue.d.ts b/src/types/vue.d.ts index 729cee04..732acf01 100644 --- a/src/types/vue.d.ts +++ b/src/types/vue.d.ts @@ -1,6 +1,6 @@ import type Vue from 'vue-2' import type { FluentResource } from '@fluent/bundle' -import type { FluentVue } from '../index' +import type { TranslationContext } from '../TranslationContext' declare module 'vue-2/types/options' { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -8,7 +8,10 @@ declare module 'vue-2/types/options' { fluent?: Record /** @private */ - _fluent?: FluentVue + _fluent?: TranslationContext + + /** @private */ + _fluentSetup?: TranslationContext } }