i18n / Translatable Schema Fields
DocuDesk adopts OpenRegister's register-i18n foundation to serve and
store per-language variants of user-facing string fields on its
registered schemas. Translations live in the existing object JSON
column — no DB migration is required.
See OR's register-i18n spec and the i18n-api-language-negotiation spec for the foundation contract. This page documents only how DocuDesk consumes that contract.
Translatable fields by schema
DocuDesk's register is at v5.5.0. The following user-facing string
fields carry "translatable": true and are picked up automatically by
OR's TranslationHandler::getTranslatableProperties() at render time:
| Schema | Schema version | Translatable fields |
|---|---|---|
template | v1.1.0 | name, description, content, category |
templateVersion | v1.1.0 | name, description, changelog |
dossier | v1.1.0 | name, description |
huisstijl | v1.1.0 | name |
base | v1.1.0 | name, description |
correspondence | v1.1.0 | templateName |
signingRequest | v1.1.0 | documentName |
signingSession | v1.1.0 | documentName |
signerRecord | v1.1.0 | displayName, declineReason |
publicationConsent | v1.1.0 | notes, objectionReason, publicationDecision |
publicationProhibition | v1.1.0 | primaryName, reason, notes |
batchCorrespondenceJob | v1.1.0 | templateName |
Adding a new translatable field is a schema-version-bump-only operation — set
"translatable": trueon the property and bump the schema'sversion. OR'snormalizeTranslationsForSave()will wrap existing simple string values under the register's default language on the next write.
Language negotiation in DocuDesk
DocuDesk registers
LanguageNegotiationMiddleware
in Application::register() so requests that hit docudesk routes (not
just OR's own routes) push the resolved language onto OR's
request-scoped LanguageService. TranslationHandler reads that
service when rendering objects, so the right variant comes out.
Priority order (mirrors OR's LanguageMiddleware):
?_lang=<bcp47>query parameter (canonical override)?language=<bcp47>query parameter (alias)Accept-Languageheader (RFC 9110)- Register default language (resolved at render time by OR)
- Hardcoded
nlfallback
Examples — all serve the Dutch variant of the template.name field
for a docudesk object served at
/apps/docudesk/api/objects/template/{uuid}:
# Query override (canonical)
curl 'https://example.tld/index.php/apps/docudesk/api/objects/template/abc?_lang=nl'
# Accept-Language header
curl -H 'Accept-Language: nl,en;q=0.8' \
'https://example.tld/index.php/apps/docudesk/api/objects/template/abc'
# Return-all override
curl 'https://example.tld/index.php/apps/docudesk/api/objects/template/abc?_translations=all'
Write side
POST / PUT / PATCH requests honour
X-Translation-Target-Language: <bcp47> — OR's TranslationHandler
stores translatable string values under that language code:
curl -X PATCH \
-H 'Content-Type: application/json' \
-H 'X-Translation-Target-Language: en' \
-d '{"name":"Dossier with the citizen"}' \
'https://example.tld/index.php/apps/docudesk/api/objects/dossier/abc'
When X-Translation-Target-Language is absent, OR falls back to the
register's default language.
Response headers
Every response from a docudesk controller emits:
Content-Language: <resolved-tag>— the language actually servedX-Content-Language-Fallback: true— present only when OR fell back because the requested language was unavailable on the object
Administrative configuration
The register's default language is set via OR's admin-settings surface
(see OR's register-i18n admin panel). DocuDesk does not duplicate
this configuration; operators configure it once in OR and every
docudesk object inherits the same default.
Operational notes
- No DB migration is required when adding a new translatable field.
Existing simple string values are wrapped under the register's
default language on the next write by OR's
normalizeTranslationsForSave(). - The OPcache must be cleared after a register-version bump for the new translatable flags to be picked up.
- If a request asks for a language the object does not have, OR
falls back through the register's configured language priority
list and emits
X-Content-Language-Fallback: true.
See also
openspec/changes/register-i18n/— the DocuDesk adoption change- OpenRegister's
LanguageMiddleware,LanguageService, andTranslationHandler— the foundation contract tests/unit/Middleware/LanguageNegotiationMiddlewareTest.php— 10 tests covering the docudesk-side bridge