diff --git a/components/email/email-viewer.tsx b/components/email/email-viewer.tsx index ad126598..b670c9db 100644 --- a/components/email/email-viewer.tsx +++ b/components/email/email-viewer.tsx @@ -804,6 +804,7 @@ export function EmailViewer({ const t = useTranslations('email_viewer'); const tNotifications = useTranslations('notifications'); const tCommon = useTranslations('common'); + const tSmime = useTranslations('smime'); const tFiles = useTranslations('files'); const externalContentPolicy = useSettingsStore((state) => state.externalContentPolicy); const mailAttachmentAction = useSettingsStore((state) => state.mailAttachmentAction); @@ -3944,8 +3945,8 @@ export function EmailViewer({ setSmimeUnlockError(null); }} onSubmit={handleSmimeUnlockSubmit} - title={tCommon('smime.unlock_key')} - description={tCommon('smime.unlock_key_desc')} + title={tSmime('unlock_key')} + description={tSmime('unlock_key_desc')} error={smimeUnlockError} /> diff --git a/lib/__tests__/translations.test.ts b/lib/__tests__/translations.test.ts index 2b6ff524..d4634c89 100644 --- a/lib/__tests__/translations.test.ts +++ b/lib/__tests__/translations.test.ts @@ -87,6 +87,22 @@ function extractUsedKeys(filePath: string): string[] { return [...new Set(keys)]; } +function collectUsedKeysByFile(files: string[]): Map { + const keyToFiles = new Map(); + + for (const filePath of files) { + for (const key of extractUsedKeys(filePath)) { + const existing = keyToFiles.get(key) ?? []; + if (!existing.includes(filePath)) { + existing.push(filePath); + keyToFiles.set(key, existing); + } + } + } + + return keyToFiles; +} + const locales = fs .readdirSync(localesDir) .filter((entry) => fs.statSync(path.join(localesDir, entry)).isDirectory()); @@ -120,19 +136,22 @@ describe('translations completeness', () => { describe('translations used in source code exist in en locale', () => { const srcDirs = ['components', 'app', 'hooks', 'lib', 'stores', 'contexts'].map((d) => path.join(rootDir, d)); const allFiles = srcDirs.flatMap((d) => getSourceFiles(d)); - const usedKeys = new Set(); - for (const f of allFiles) { - for (const k of extractUsedKeys(f)) { - usedKeys.add(k); - } - } + const usedKeysByFile = collectUsedKeysByFile(allFiles); + const usedKeys = [...usedKeysByFile.keys()].sort(); it('all translation keys referenced in source should exist in en locale', () => { - const missing = [...usedKeys].sort().filter((key) => resolveKey(referenceData, key) === undefined); + const missing = usedKeys.filter((key) => resolveKey(referenceData, key) === undefined); + const details = missing.map((key) => { + const relativeFiles = (usedKeysByFile.get(key) ?? []) + .map((filePath) => path.relative(rootDir, filePath)) + .sort(); + + return `${key}\n used in:\n - ${relativeFiles.join('\n - ')}`; + }); expect( missing, - `${missing.length} translation key(s) used in source code but missing from en locale:\n${missing.join('\n')}`, + `${missing.length} translation key(s) used in source code but missing from en locale:\n${details.join('\n')}`, ).toEqual([]); }); }); diff --git a/package.json b/package.json index 1964ce79..fbabd126 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "start": "next start", "lint": "next lint", "lint:fix": "next lint --fix", + "test:translations": "vitest run lib/__tests__/translations.test.ts", "prepare": "husky", "typecheck": "tsc --noEmit" },