fix(i18n): name attachment PDF previews in the selected language

This commit is contained in:
cesnimda
2026-11-02 21:52:48 +01:00
parent 55adc1dbd7
commit 4939585fb1
3 changed files with 48 additions and 1 deletions
+20
View File
@@ -0,0 +1,20 @@
# Attachment preview accessible label — 2026-11-02
Status: implemented and locally verified; publication recorded in Git history.
The shared Attachments PDF iframe used the generic English title `pdf`. It now reuses `attachmentsPreviewTitle` with the displayed filename, matching the existing dialog title in English and Norwegian Bokmål. This addresses the generic PDF-title item from the literal review (I00-15).
Scope: `Attachments.tsx`, its attachment regression tests, and this evidence. ApplicationWorkspacePage remains the caller. No route, API, file-content, upload/download, object-URL lifecycle, persistence, dependency or generated-content language behavior changed.
Verification:
- RED: two new language cases failed against the previous generic title; three existing attachment cases passed.
- PASSED: attachment and file-picker suites, 13 tests across two suites, zero failures, native exit 0. The language cases open the PDF preview through its translated button and verify the named iframe and blob URL.
- PASSED: `npm run typecheck`, exit 0.
- PASSED: ESLint for both changed source/test files with zero warnings, exit 0.
- An earlier combined test execution passed all 13 assertions but exited 1 because the JSON report directory did not exist. Creating the local artifact directory and rerunning produced the successful execution above. These are overlapping runs, not 26 distinct tests.
- Raw successful Jest evidence: local ignored `job-tracker-ui/.artifacts/attachment-label-results.json`.
Rollback: revert this package; no data conversion is involved. No new translation key was needed. The 80 unresolved dynamic translation calls remain open; this fix does not establish complete i18n or accessibility acceptance. Browser/native assistive-technology checks and a full production build were not rerun for this label-only change.
Next: continue the unresolved dynamic-call inventory and remaining literal triage; retain all independent workstream and release gates.
+27
View File
@@ -22,6 +22,33 @@ const mockedApi = api as jest.Mocked<typeof api>;
beforeEach(() => jest.clearAllMocks());
test.each([
['en', 'Preview: resume.pdf', 'Preview: resume.pdf'],
['nb', 'Forhåndsvis: resume.pdf', 'Forhåndsvisning: resume.pdf'],
])('PDF preview identifies the document in %s', async (language, buttonName, frameTitle) => {
const previousLanguage = localStorage.getItem('uiLanguage');
const originalCreate = URL.createObjectURL;
const originalRevoke = URL.revokeObjectURL;
localStorage.setItem('uiLanguage', language);
URL.createObjectURL = jest.fn(() => 'blob:attachment-preview');
URL.revokeObjectURL = jest.fn();
mockedApi.get.mockResolvedValueOnce({ data: [{ id: 7, fileName: 'resume.pdf', fileType: 'application/pdf', fileSize: 2048, uploadDate: '2026-11-02T10:00:00Z' }] } as any);
mockedApi.get.mockResolvedValueOnce({ data: new Blob(['sample'], { type: 'application/pdf' }) } as any);
const view = render(<ToastProvider><I18nProvider><ConfirmProvider><PromptProvider><Attachments jobId={42} /></PromptProvider></ConfirmProvider></I18nProvider></ToastProvider>);
try {
fireEvent.click(await screen.findByRole('button', { name: buttonName }));
const frame = await screen.findByTitle(frameTitle);
expect(frame.tagName).toBe('IFRAME');
expect(frame).toHaveAttribute('src', 'blob:attachment-preview');
} finally {
view.unmount();
URL.createObjectURL = originalCreate;
URL.revokeObjectURL = originalRevoke;
if (previousLanguage === null) localStorage.removeItem('uiLanguage');
else localStorage.setItem('uiLanguage', previousLanguage);
}
});
test('attachments empty state renders drag and drop guidance', async () => {
mockedApi.get.mockResolvedValueOnce({ data: [] } as any);
@@ -358,7 +358,7 @@ export default function Attachments({ jobId }: { jobId: number }) {
<img src={preview.url} alt={preview.name} style={{ maxWidth: "100%", maxHeight: "70vh", borderRadius: 12 }} />
</Box>
) : isPdfType(preview.type) ? (
<iframe title="pdf" src={preview.url} style={{ width: "100%", height: 560, border: 0, borderRadius: 12 }} />
<iframe title={t("attachmentsPreviewTitle", { name: preview.name })} src={preview.url} style={{ width: "100%", height: 560, border: 0, borderRadius: 12 }} />
) : (
<Typography sx={{ color: "text.secondary" }}>{t("attachmentsNoInlinePreview")}</Typography>
)}