From 1d21fe0d45bfedb34fe1be342e0d0a66e359170c Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 20 Mar 2026 12:46:32 -0300 Subject: [PATCH 1/8] test(vue): update AdminSupportBanner spec to assert direct markup with inline t() Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../admin/AdminSupportBanner.spec.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/tests/components/admin/AdminSupportBanner.spec.ts b/src/tests/components/admin/AdminSupportBanner.spec.ts index 00a7996..d7f747a 100644 --- a/src/tests/components/admin/AdminSupportBanner.spec.ts +++ b/src/tests/components/admin/AdminSupportBanner.spec.ts @@ -6,6 +6,16 @@ import { mount } from '@vue/test-utils' import { defineComponent, nextTick } from 'vue' import AdminSupportBanner from '../../../components/AdminSupportBanner.vue' +vi.mock('@nextcloud/l10n', () => ({ + t: (_app: string, text: string, parameters?: Record) => { + if (parameters === undefined) { + return `tr:${text}` + } + + return Object.entries(parameters).reduce((translated, [key, value]) => translated.replace(`{${key}}`, value), `tr:${text}`) + }, +})) + vi.mock('@nextcloud/vue', () => ({ NcButton: defineComponent({ name: 'NcButton', @@ -24,6 +34,15 @@ afterEach(() => { }) describe('AdminSupportBanner', () => { + it('renders translated copy and actions', () => { + const wrapper = mount(AdminSupportBanner) + + expect(wrapper.text()).toContain('tr:Help keep Profile Fields sustainable.') + expect(wrapper.text()).toContain('tr:Sponsor LibreSign') + expect(wrapper.text()).toContain('tr:Maybe later') + expect(wrapper.text()).toContain('tr:Give Profile Fields a star on GitHub') + }) + it('opens sponsor page when sponsor button is clicked', async() => { const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null) const wrapper = mount(AdminSupportBanner) From aa8d2c9e47117412f05ad47cc1cd865095f06660 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 20 Mar 2026 12:46:37 -0300 Subject: [PATCH 2/8] test(vue): update AdminSelectOptionsSection spec to assert inline t() labels Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../admin/AdminSelectOptionsSection.spec.ts | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/tests/components/admin/AdminSelectOptionsSection.spec.ts b/src/tests/components/admin/AdminSelectOptionsSection.spec.ts index 7eb7036..15f4fd1 100644 --- a/src/tests/components/admin/AdminSelectOptionsSection.spec.ts +++ b/src/tests/components/admin/AdminSelectOptionsSection.spec.ts @@ -6,6 +6,24 @@ import { mount } from '@vue/test-utils' import { defineComponent } from 'vue' import AdminSelectOptionsSection from '../../../components/admin/AdminSelectOptionsSection.vue' +vi.mock('@nextcloud/l10n', () => ({ + n: (_app: string, singular: string, plural: string, count: number, parameters?: Record) => { + const template = count === 1 ? singular : plural + if (parameters === undefined) { + return `tr:${template}` + } + + return Object.entries(parameters).reduce((translated, [key, value]) => translated.replace(`{${key}}`, String(value)), `tr:${template}`) + }, + t: (_app: string, text: string, parameters?: Record) => { + if (parameters === undefined) { + return `tr:${text}` + } + + return Object.entries(parameters).reduce((translated, [key, value]) => translated.replace(`{${key}}`, String(value)), `tr:${text}`) + }, +})) + vi.mock('@nextcloud/vue', () => ({ NcActionButton: defineComponent({ template: '
' }), NcActions: defineComponent({ template: '
' }), @@ -38,6 +56,30 @@ const DraggableStub = defineComponent({ }) describe('AdminSelectOptionsSection', () => { + it('renders translated headings and pluralized meta', () => { + const wrapper = mount(AdminSelectOptionsSection, { + props: { + modelValue: [{ id: 'option-0', value: 'Alpha' }], + isSaving: false, + }, + global: { + stubs: { + Draggable: DraggableStub, + NcDialog: false, + NcTextArea: false, + NcActionButton: false, + NcActions: false, + NcIconSvgWrapper: false, + NcInputField: false, + }, + }, + }) + + expect(wrapper.text()).toContain('tr:Options') + expect(wrapper.text()).toContain('tr:option') + expect(wrapper.text()).toContain('tr:Add single option') + }) + it('emits updated model when adding a new option', async() => { const wrapper = mount(AdminSelectOptionsSection, { props: { From 2e37650a8e35598a7d91be480a1b6448c073eca0 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 20 Mar 2026 12:46:42 -0300 Subject: [PATCH 3/8] refactor(vue): inline t() directly in visibilityOptions labels Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/utils/visibilityOptions.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/utils/visibilityOptions.ts b/src/utils/visibilityOptions.ts index 6702454..13f6d19 100644 --- a/src/utils/visibilityOptions.ts +++ b/src/utils/visibilityOptions.ts @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2026 LibreCode coop and LibreCode contributors // SPDX-License-Identifier: AGPL-3.0-or-later +import { t } from '@nextcloud/l10n' import type { FieldVisibility } from '../types' export type VisibilityOption = { @@ -9,7 +10,7 @@ export type VisibilityOption = { } export const visibilityOptions: VisibilityOption[] = [ - { value: 'public', label: 'Show to everyone' }, - { value: 'users', label: 'Show to logged in accounts only' }, - { value: 'private', label: 'Hide' }, + { value: 'public', label: t('profile_fields', 'Show to everyone') }, + { value: 'users', label: t('profile_fields', 'Show to logged in accounts only') }, + { value: 'private', label: t('profile_fields', 'Hide') }, ] From c1b90ad83fe1bd0c8f4a486585fa49eb51a221ea Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 20 Mar 2026 12:46:42 -0300 Subject: [PATCH 4/8] refactor(vue): inline t() directly in AdminSupportBanner, remove v-for arrays Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/components/AdminSupportBanner.vue | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/AdminSupportBanner.vue b/src/components/AdminSupportBanner.vue index acd878a..6f0a30a 100644 --- a/src/components/AdminSupportBanner.vue +++ b/src/components/AdminSupportBanner.vue @@ -7,25 +7,27 @@ SPDX-License-Identifier: AGPL-3.0-or-later
-

Help keep Profile Fields sustainable.

-

Profile Fields is open source under the AGPL license and maintained by the LibreCode team, creators of LibreSign.

-

If your organization depends on it, please help us sustain its development and maintenance.

+

{{ t('profile_fields', 'Help keep Profile Fields sustainable.') }}

+

{{ t('profile_fields', 'Profile Fields is open source under the AGPL license and maintained by the LibreCode team, creators of LibreSign.') }}

+

{{ t('profile_fields', 'If your organization depends on it, please help us sustain its development and maintenance.') }}

- Sponsor LibreSign + {{ t('profile_fields', 'Sponsor LibreSign') }} - Maybe later + {{ t('profile_fields', 'Maybe later') }}
@@ -34,6 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later