fix(pdf): respect export-request language over DB template language#537
Merged
Conversation
The react-pdf resume templates picked their localized section headings via `meta.language || data.language`, where `meta.language` comes from the resolved DB template row. The seed only ships one variant per design (English), so when a user exported Harvard Classic + German, the language-variant lookup in application.processor.ts fell back to the English row, meta.language was 'en', and the resume rendered with English headings (Experience / Education / Skills) even though the LLM-generated body was correctly in German — partial-language bug reported in #536. Flip the precedence in all three registered templates so the explicit export-request language (data.language, set from the export DTO by the application processor) wins over the DB row's static language column. This makes export-time language correctness independent of which language variants happen to be seeded. Adds a unit test that renders each template at the factory level with data.language='de' against a stubbed meta.language='en' and asserts the rasterised PDF text contains German headings (Berufserfahrung, Ausbildung, Fähigkeiten) and not their English equivalents. Fixes #536
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #536.
Problem
For Harvard Classic (and latently for the other two registered designs), selecting German in the application edit flow renders correctly in the in-app preview but the exported PDF comes out with English section headings (
Education,Skills,Professional Experience) while the body text (LLM-generated bullets, summary, cover letter prose) is in German.Root cause
The preview renders client-side via a frontend component that takes the user-chosen
languagedirectly as a prop.The export, however, renders server-side via
ReactPdfRendererService, which constructsmeta.languagefrom the resolved DB template row'slanguagecolumn. The three registered templates picked their localized section headings with:seed-multilingual-templates.tsonly seeds one variant per design (English), soapplication.processor.ts → resolveTemplateForLanguage('<category>', 'de', …)doesn't find a German variant and falls back to the English row (with a warning log).meta.languageis then'en', the precedence above picks'en', and the localized headings render in English — even thoughdata.languagewas set to'de'from the export request and the LLM body is already in German.Fix
Flip the precedence in all three resume templates so the explicit export-request language wins over the DB row's static language column:
This makes export-time language correctness independent of which language variants happen to be seeded — a one-line change in each of:
The processor's
languagepropagation, controller (requestExport), and DTO are all already correct — no other code needed to change.Regression coverage
Adds apps/api/src/pdf-v2/templates/language-precedence.unit.spec.ts which, for each of the 3 registered templates:
react-pdf-loader.tsdynamic-import shim that doesn't work under Vitest's transform),data.language='de'against a stubbedmeta.language='en'(simulating the DE-variant-missing fallback path),pdf-parseand asserts German headings (Berufserfahrung,Ausbildung,Fähigkeiten) are present and English equivalents are NOT.Sanity-checked by reverting the source fix and confirming all 3 tests fail without it.
Out of scope
Template not found for category … falling back to Englishwarning log and gives PDF metadata a correct language tag, but the template-layer fix is complete on its own — should be a separate cleanup issue.application.processor.tsregenerate path (regenerate(), line ~2247) doesn't passlanguagewhen re-enqueueing FAILED applications. Pre-existing, separate from the export flow this issue is about.meta: _metaunderscore-discard — left as-is since the CL body is already language-correct (from LLM) and there's no localized chrome to translate.Verification
pnpm vitest run src/pdf-v2/templates/language-precedence.unit.spec.ts→ 3 passedpnpm lint→ 0 lint issues introduced on touched files (the 299 pre-existing warnings live elsewhere)