Skip to content

fix(intent): server-side PDF renders resolve nomenclature values in the render language (#6947) - #6948

Merged
delchev merged 3 commits into
eclipse-dirigible:masterfrom
NicoleNG18:fix/6947-server-side-print-language
Aug 27, 2026
Merged

fix(intent): server-side PDF renders resolve nomenclature values in the render language (#6947)#6948
delchev merged 3 commits into
eclipse-dirigible:masterfrom
NicoleNG18:fix/6947-server-side-print-language

Conversation

@NicoleNG18

Copy link
Copy Markdown
Contributor

Problem

Fixes #6947.

The two server-side PDF render paths - the immutable snapshot copy minted when a document is issued, and the notify attach: print / recordPrint / report PDF mailed to the recipient - render the .print template in the document's (mint) language but resolve the data values (Payment Method, Sent Method, Status, and any multilingual nomenclature) in the default language. For any document whose language is not the default, the archived copy and the emailed PDF come out with, e.g., Bulgarian labels but English values (ФАКТУРАBank transfer / ISSUED).

This is the same class of defect as the client-side print-language bug (#6945, fixed in #6946), but on a different code path. #6946 is explicitly scoped to the interactive UI dialog and calls this case out as "a different (in-process, thread-local) fix" - which is this PR.

Root cause

Both paths already compute a render language (language: / languageFrom:, falling back to sdk.print.Print.defaultLanguage()) and pass it to Print.render(entity, language, payload), so the template is selected from the right CMS language folder. But the payload is built by calling the generated <Master>PrintFeeder().feed(id) (or, for attach: report, the report repository) in-process. The multilingual overlay a generated repository applies reads sdk.security.User.getLanguage() → the request's Accept-Language header. A BPM service task has no request, so getLanguage() returns null, Translator no-ops, and the values fall back to the base/default language while the template is in the mint language.

Fix

A thread-bound language override that getLanguage() prefers over the (absent) request header - the mechanism the platform lacked for off-request renders. Each server-side render sets it to the language it already computed, around the feed/render, and clears it in a finally so a pooled BPM worker thread never leaks it. The feeder's HTTP @Get("/{id}") contract is untouched (the browser still carries Accept-Language), and every read still goes through the generated repositories (validations / events preserved).

  • components/api/api-security UserFacade: setLanguage(String) / clearLanguage() + an override branch at the top of getLanguage().
  • components/api/api-modules-java sdk.security.User: expose setLanguage / clearLanguage for the generated (client-Java) delegates.
  • template-application-events-java: Snapshot.java.template, Send.java.template and Notification.java.template wrap the feed/render in User.setLanguage(language)finally { User.clearLanguage(); } - for every attach branch (print, recordPrint, report), and for report the override also covers the report findAll whose :language binding reads getLanguage().
  • engine-intent/CLAUDE.md: mint-language bullet updated (the mint language now names the template AND the data).

Scope / notes

Verification

  • UserFacadeLanguageOverrideTest (new, api-security): the override wins over the absent request language, clearLanguage() restores the unresolved state, null/blank leaves it unset. Passing locally (4/4).
  • IntentEmissionCoverageIT: each attach branch (SendBillTransition = attach: print, BillFlowMailBillSend = attach: report, BillFlowShareBillSend = attach: recordPrint) now asserts the generated delegate emits the User.setLanguage(language) / clearLanguage() wrapper around its render - and the IT's client-Java compile proves the emitted code compiles. IntentEngineIT's OrderCopy snapshot compiles the Snapshot template.
  • mvn formatter:validate and the release-profile javadoc build pass on the changed modules.

Reminder: the events templates are bundled into the fat jar - a locally running instance needs template-application-events-java + build/application repackaged and a restart, and target apps need regeneration, to reflect the change.

🤖 Generated with Claude Code

NicoleNG18 and others added 2 commits August 25, 2026 22:21
…he render language (eclipse-dirigible#6947)

The two server-side PDF paths - the immutable snapshot minted on issue and the
notify `attach: print`/`recordPrint`/`report` PDF mailed to the recipient - pick
their `.print` template by the mint language but built the `{document, items}`
payload by calling the generated `<Master>PrintFeeder` (or the report repository)
in-process. The multilingual overlay a generated repository applies reads
`User.getLanguage()`, i.e. the request's Accept-Language - and a BPM service task
has no request. So nomenclature values (Payment Method, Sent Method, Status, any
multilingual nomenclature) fell back to the default language while the template
rendered in the mint language (a Bulgarian invoice reading "Bank transfer" /
"ISSUED"). This is the server-side half of eclipse-dirigible#6945 (fixed client-side in eclipse-dirigible#6946),
which is out of that PR's scope because there is no header to pin.

Fix: a thread-bound language override in `UserFacade`, preferred by
`getLanguage()` over the absent header, set by each render around the feed/render
and cleared in a finally so a pooled worker thread never leaks it. The feeder's
HTTP `@Get("/{id}")` path is untouched; all reads still go through repositories.

- api-security: `UserFacade.setLanguage/clearLanguage` + override in `getLanguage`
- api-modules-java: expose `sdk.security.User.setLanguage/clearLanguage`
- templates: `Snapshot`, `Send`, `Notification` wrap feed/render (each attach branch)
- tests: `UserFacadeLanguageOverrideTest`; `IntentEmissionCoverageIT` asserts the
  set/clear on every attach branch
- docs: engine-intent guide mint-language bullet

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@NicoleNG18
NicoleNG18 marked this pull request as draft August 26, 2026 05:57
…and the extracted render local is byte[] (eclipse-dirigible#6947)

The eclipse-dirigible#6947 render-language fix wrapped the server-side PDF render in a
thread-bound `User.setLanguage`/`clearLanguage` in `Send`, `Notification` and
`Snapshot`, but missed `Transition.java.template` - the transition `notify`
block is a separate render path with its own three render sites (`attach: print`
/ `recordPrint` / `report`). So a transition-driven render (the `SendBill` case,
generated as `SendBillTransition.java`) still resolved nomenclature values in the
default language while the template rendered in the mint language.

The same fix also introduced a latent compile error it never surfaced: extracting
the render into a local typed it `String data`, but `sdk.print.Print.render`
returns `byte[]`. `document.put("data", render(...))` compiled because `put` takes
`Object`; a typed `String` local does not (`javac: byte[] cannot be converted to
java.lang.String`). It broke the whole emission client-Java batch - every runtime
endpoint 404'd - but was masked because `IntentEmissionCoverageIT` failed on the
missing-Transition content assertion before it ever compiled the batch.

- Transition.java.template: bind the language around all three render sites
- Send/Notification/Transition: `String data` -> `byte[] data` (8 sites)
  (Snapshot was already `byte[] pdf`)
- IntentEmissionCoverageIT now passes fully (content + runtime enforcement)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@NicoleNG18
NicoleNG18 marked this pull request as ready for review August 26, 2026 10:40
@delchev
delchev merged commit 4e9adcc into eclipse-dirigible:master Aug 27, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants