diff --git a/src/components/NcCounterBubble/NcCounterBubble.vue b/src/components/NcCounterBubble/NcCounterBubble.vue index ec8d91e661..acc27b534b 100644 --- a/src/components/NcCounterBubble/NcCounterBubble.vue +++ b/src/components/NcCounterBubble/NcCounterBubble.vue @@ -162,12 +162,20 @@ const props = withDefaults(defineProps<{ type: '', }) +// Special case: browsers do not shorten numbers in German +// Fallback to English to have 2K instead of 2048 +// TODO: what about Italian with the same issue? +let locale = getCanonicalLocale() +if (locale === 'de' || locale === 'de-DE') { + locale = 'en' +} + const humanizedCount = computed(() => { if (props.raw) { return props.count.toString() } - const formatter = new Intl.NumberFormat(getCanonicalLocale(), { + const formatter = new Intl.NumberFormat(locale, { notation: 'compact', compactDisplay: 'short', }) diff --git a/tests/unit/components/NcCounterBubble/NcCounterBubble.spec.ts b/tests/unit/components/NcCounterBubble/NcCounterBubble.spec.ts index 67cdc832df..4889fff265 100644 --- a/tests/unit/components/NcCounterBubble/NcCounterBubble.spec.ts +++ b/tests/unit/components/NcCounterBubble/NcCounterBubble.spec.ts @@ -3,10 +3,23 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ +import type { MockedFunction } from 'vitest' + +import { getCanonicalLocale } from '@nextcloud/l10n' import { mount } from '@vue/test-utils' -import { describe, expect, it } from 'vitest' +import { afterEach, describe, expect, it, vi } from 'vitest' import NcCounterBubble from '../../../../src/components/NcCounterBubble/NcCounterBubble.vue' +vi.mock('@nextcloud/l10n', async () => { + const actual = await vi.importActual('@nextcloud/l10n') + return { + ...actual, + getCanonicalLocale: vi.fn(() => 'en'), + } +}) + +const getCanonicalLocaleMock = getCanonicalLocale as unknown as MockedFunction + describe('NcCounterBubble', () => { describe('displaying count', () => { it('should render count from prop', () => { @@ -16,10 +29,8 @@ describe('NcCounterBubble', () => { }) describe('with humanization', () => { - it('should render count 1020 with humanization as "1K"', () => { - const wrapper = mount(NcCounterBubble, { props: { count: 1042 } }) - expect(wrapper.text()).toBe('1K') - expect(wrapper.attributes('title')).toBe('1042') + afterEach(() => { + vi.restoreAllMocks() }) it('should render count 12 without humanization and without title', () => { @@ -28,6 +39,33 @@ describe('NcCounterBubble', () => { expect(wrapper.attributes('title')).toBeUndefined() }) + it('should render count 1042 with humanization as "1K" in English', () => { + const wrapper = mount(NcCounterBubble, { props: { count: 1042 } }) + expect(wrapper.text()).toBe('1K') + expect(wrapper.attributes('title')).toBe('1042') + }) + + it('should render count 12000 with humanization as "1.2万" in Chinese', () => { + getCanonicalLocaleMock.mockReturnValue('zh') + const wrapper = mount(NcCounterBubble, { props: { count: 12_000 } }) + expect(wrapper.text()).toBe('1.2万') + expect(wrapper.attributes('title')).toBe('12000') + }) + + it('should render count 1042 with humanization as "1K" in German', () => { + getCanonicalLocaleMock.mockReturnValue('de') + const wrapper = mount(NcCounterBubble, { props: { count: 1042 } }) + expect(wrapper.text()).toBe('1K') + expect(wrapper.attributes('title')).toBe('1042') + }) + + it('should render count 1042 with humanization as "1042" in Italian', () => { + getCanonicalLocaleMock.mockReturnValue('it') + const wrapper = mount(NcCounterBubble, { props: { count: 1042 } }) + expect(wrapper.text()).toBe('1042') + expect(wrapper.attributes('title')).toBeUndefined() + }) + it('should not humanize with raw', () => { const wrapper = mount(NcCounterBubble, { props: { count: 1042, raw: true } }) expect(wrapper.text()).toBe('1042')