Skip to content

Commit 245bf12

Browse files
committed
feat: show translation progress in locale picker
Inspired by https://opencollective.com/
1 parent e4c6642 commit 245bf12

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

app/pages/settings.vue

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ const canGoBack = useCanGoBack()
44
const { settings } = useSettings()
55
const { locale, locales, setLocale: setNuxti18nLocale } = useI18n()
66
const colorMode = useColorMode()
7-
const { currentLocaleStatus, isSourceLocale } = useI18nStatus()
7+
const { currentLocaleStatus, isSourceLocale, getLocaleStatus } = useI18nStatus()
8+
9+
const localeItems = computed(() =>
10+
locales.value.map(loc => ({
11+
label: formatLocaleLabel(loc.name ?? '', getLocaleStatus(loc.code)),
12+
value: loc.code,
13+
})),
14+
)
815
916
// Escape to go back (but not when focused on form elements or modal is open)
1017
onKeyStroke(
@@ -219,7 +226,7 @@ const setLocale: typeof setNuxti18nLocale = locale => {
219226
<ClientOnly>
220227
<SelectField
221228
id="language-select"
222-
:items="locales.map(loc => ({ label: loc.name ?? '', value: loc.code }))"
229+
:items="localeItems"
223230
v-model="locale"
224231
@update:modelValue="setLocale($event as typeof locale)"
225232
block

app/utils/locale-label.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { I18nLocaleStatus } from '#shared/types'
2+
3+
/**
4+
* Format a locale label for the language selector, appending the completion
5+
* percentage when the locale is not fully translated.
6+
*/
7+
export function formatLocaleLabel(name: string, localeStatus: I18nLocaleStatus | null): string {
8+
if (localeStatus && localeStatus.percentComplete < 100) {
9+
return `${name} (${localeStatus.percentComplete}%)`
10+
}
11+
return name
12+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { describe, it, expect } from 'vitest'
2+
import { formatLocaleLabel } from '../../../../app/utils/locale-label'
3+
import type { I18nLocaleStatus } from '#shared/types'
4+
5+
function makeStatus(percentComplete: number): I18nLocaleStatus {
6+
return {
7+
lang: 'fr-FR',
8+
label: 'Français',
9+
totalKeys: 200,
10+
completedKeys: Math.round((percentComplete / 100) * 200),
11+
missingKeys: [],
12+
percentComplete,
13+
githubEditUrl: '',
14+
githubHistoryUrl: '',
15+
}
16+
}
17+
18+
describe('formatLocaleLabel', () => {
19+
it('appends percentage when locale is partially translated', () => {
20+
expect(formatLocaleLabel('Français', makeStatus(85))).toBe('Français (85%)')
21+
})
22+
23+
it('appends percentage when locale is 0% translated', () => {
24+
expect(formatLocaleLabel('العربية', makeStatus(0))).toBe('العربية (0%)')
25+
})
26+
27+
it('does not append percentage when locale is 100% complete', () => {
28+
expect(formatLocaleLabel('English (US)', makeStatus(100))).toBe('English (US)')
29+
})
30+
31+
it('returns plain name when locale status is null', () => {
32+
expect(formatLocaleLabel('English', null)).toBe('English')
33+
})
34+
})

0 commit comments

Comments
 (0)