From 245bf12fcc46b96d2ecd5936d5904af3e2fd22d1 Mon Sep 17 00:00:00 2001 From: Philippe Serhal Date: Mon, 9 Feb 2026 19:38:21 -0500 Subject: [PATCH] feat: show translation progress in locale picker Inspired by https://opencollective.com/ --- app/pages/settings.vue | 11 ++++++-- app/utils/locale-label.ts | 12 +++++++++ test/unit/app/utils/locale-label.spec.ts | 34 ++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 app/utils/locale-label.ts create mode 100644 test/unit/app/utils/locale-label.spec.ts diff --git a/app/pages/settings.vue b/app/pages/settings.vue index 14d50e110..d048c50c1 100644 --- a/app/pages/settings.vue +++ b/app/pages/settings.vue @@ -4,7 +4,14 @@ const canGoBack = useCanGoBack() const { settings } = useSettings() const { locale, locales, setLocale: setNuxti18nLocale } = useI18n() const colorMode = useColorMode() -const { currentLocaleStatus, isSourceLocale } = useI18nStatus() +const { currentLocaleStatus, isSourceLocale, getLocaleStatus } = useI18nStatus() + +const localeItems = computed(() => + locales.value.map(loc => ({ + label: formatLocaleLabel(loc.name ?? '', getLocaleStatus(loc.code)), + value: loc.code, + })), +) // Escape to go back (but not when focused on form elements or modal is open) onKeyStroke( @@ -219,7 +226,7 @@ const setLocale: typeof setNuxti18nLocale = locale => { { + it('appends percentage when locale is partially translated', () => { + expect(formatLocaleLabel('Français', makeStatus(85))).toBe('Français (85%)') + }) + + it('appends percentage when locale is 0% translated', () => { + expect(formatLocaleLabel('العربية', makeStatus(0))).toBe('العربية (0%)') + }) + + it('does not append percentage when locale is 100% complete', () => { + expect(formatLocaleLabel('English (US)', makeStatus(100))).toBe('English (US)') + }) + + it('returns plain name when locale status is null', () => { + expect(formatLocaleLabel('English', null)).toBe('English') + }) +})