feat(docworker, tdk): Support Document Template Locale - #460
feat(docworker, tdk): Support Document Template Locale#460MarekSuchanek wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Missing modules break TDK and document-worker startup, and POT readiness is not updated after generation.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds document-template language and locale support, including Jinja translations, POT extraction, and related storage, model, and database updates.
Changes:
- Adds language metadata and validation.
- Adds locale-aware rendering and translation helpers.
- Adds POT generation, storage, and readiness tracking.
- Updates dependencies, tests, documentation, and changelogs.
File summaries
| File | Change | Final review note |
|---|---|---|
uv.lock |
Locks translation dependencies. | — |
packages/dsw-tdk/tests/test_cmd_new.py |
Updates template creation tests for language. | — |
packages/dsw-tdk/tests/fixtures/test_example01/template.json |
Adds language metadata. | — |
packages/dsw-tdk/tests/fixtures/test_example01/src/template.json.j2 |
Adds translatable strings. | — |
packages/dsw-tdk/README.md |
Documents the POT command. | — |
packages/dsw-tdk/pyproject.toml |
Adds Babel dependency. | — |
packages/dsw-tdk/dsw/tdk/validation.py |
Validates language metadata. | — |
packages/dsw-tdk/dsw/tdk/utils.py |
Exposes language builder accessors. | — |
packages/dsw-tdk/dsw/tdk/model.py |
Loads and serializes language metadata. | Moderate (1 vote): Empty language values are replaced with en before validation; default only when the value is None. |
packages/dsw-tdk/dsw/tdk/core.py |
Adds POT generation integration. | Critical (3 votes): The imported dsw/tdk/pot.py is absent, causing ModuleNotFoundError before TDK commands can start. |
packages/dsw-tdk/dsw/tdk/consts.py |
Adds locale and POT constants. | — |
packages/dsw-tdk/dsw/tdk/cli.py |
Adds language prompting and the pot command. |
Nit (1 vote): Add tests for extraction output, --force, and skipped/unparseable files. |
packages/dsw-tdk/CHANGELOG.md |
Records TDK changes. | — |
packages/dsw-storage/dsw/storage/s3storage.py |
Adds locale and POT storage paths. | — |
packages/dsw-storage/CHANGELOG.md |
Records storage changes. | — |
packages/dsw-models/dsw/models/document_template/metadata.py |
Adds the metadata language field. | — |
packages/dsw-models/CHANGELOG.md |
Records model changes. | — |
packages/dsw-document-worker/support/steps/jinja.md |
Documents translation behavior. | Moderate (2 votes): policy.urlize.extra_schemes is assigned to truncate.leeway, so the documented option is not applied. Nit (2 votes): The Translations.md migration link targets a missing file. |
packages/dsw-document-worker/support/DocumentContext.md |
Documents locale context fields. | Nit (1 vote): The Translations.md reference targets a missing file. |
packages/dsw-document-worker/README.md |
Links translation documentation. | Nit (3 votes): The support/Translations.md link targets a missing file. |
packages/dsw-document-worker/pyproject.toml |
Adds translation dependencies. | — |
packages/dsw-document-worker/dsw/document_worker/worker.py |
Adds locale preparation and POT jobs. | Critical (3 votes): The absent dsw/document_worker/pot.py makes startup fail with ModuleNotFoundError, including ordinary jobs; include PotFileJob (also affecting line 23). |
packages/dsw-document-worker/dsw/document_worker/templates/templates.py |
Adds render locale state. | Critical (3 votes): The absent locales.py prevents importing Template; add LocaleLoader, RenderContext, and TemplateLocale. |
packages/dsw-document-worker/dsw/document_worker/templates/steps/template.py |
Enables Jinja i18n support. | — |
packages/dsw-document-worker/dsw/document_worker/templates/steps/base.py |
Adds translation helpers. | — |
packages/dsw-document-worker/dsw/document_worker/templates/formats.py |
Propagates render context. | — |
packages/dsw-document-worker/dsw/document_worker/plugins/specs.py |
Documents translation plugin hooks. | — |
packages/dsw-document-worker/dsw/document_worker/model/context.py |
Adds document locale context models. | — |
packages/dsw-document-worker/dsw/document_worker/consts.py |
Adds locale and POT constants. | — |
packages/dsw-document-worker/CHANGELOG.md |
Records worker changes. | — |
packages/dsw-database/dsw/database/model.py |
Adds template language and POT readiness fields. | — |
packages/dsw-database/dsw/database/database.py |
Adds the POT readiness update query. | Critical (1 vote): No changed-tree caller sets pot_file_ready after successful S3 generation; update the flag from the POT job. |
packages/dsw-database/CHANGELOG.md |
Records database changes. | — |
.cspell/dictionary.txt |
Adds translation terminology. | — |
Review details
Suppressed comments (4)
packages/dsw-document-worker/dsw/document_worker/worker.py:23
- The worker now imports
TemplateLocalefromdsw.document_worker.templates.locales, but notemplates/locales.pymodule is present. This makes the worker fail at import time; add the locale implementation to the package before enabling this import.
from .templates.locales import TemplateLocale
packages/dsw-document-worker/support/DocumentContext.md:55
- The new
./Translations.mdreference targets a file that is not present in the package, so the locale documentation link in the document-context guide is broken. Add the referenced document to the change or remove the link.
* `locale` (`Optional[`[`DocumentTemplateLocale`](#documenttemplatelocale)`]`) - locale used for the translations, see [Translations](./Translations.md)
packages/dsw-tdk/dsw/tdk/cli.py:574
- The new
potcommand has no test in the TDK command suite, while neighboring commands cover success, overwrite, and failure paths. Please add coverage for extraction output,--force, and skipped/unparseable files so this feature does not regress silently.
@main.command(help='Create POT file with translatable strings of a template.', name='pot')
@click.argument('TEMPLATE-DIR', type=DIR_TYPE, default=CURRENT_DIR, required=False)
@click.option('-o', '--output', default=consts.POT_FILE_DEFAULT, type=click.Path(writable=True),
show_default=True, help='Target POT file.')
@click.option('-f', '--force', is_flag=True, help='Overwrite POT file if already exists.')
packages/dsw-tdk/dsw/tdk/model.py:191
- When
template.jsoncontains"language": "",_common_loadpasses the empty string here, butorreplaces it withenbefore the new non-empty validator runs. This silently accepts and changes invalid metadata; default only whenlanguage is None.
self.language: str = language or consts.DEFAULT_LANGUAGE
- Files reviewed: 33/34 changed files
- Comments generated: 7
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
8d82751 to
a4049fa
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Four unresolved moderate findings affect i18n POT extraction and POT job state/cleanup.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (3)
packages/dsw-document-worker/dsw/document_worker/pot.py:224
- The database method returns
Falsewhen no template row is updated, but that result is discarded. In that case the POT has already been stored in S3 whilepot_file_readyremains false, yet the command still succeeds; treat a false result as an error so the job reports the inconsistent state.
self.ctx.app.db.update_document_template_pot_file_ready(
template_uuid=self.rq.document_template_uuid,
tenant_uuid=self.rq.tenant_uuid,
ready=True,
)
packages/dsw-document-worker/dsw/document_worker/pot.py:186
- The POT contract says its
LanguageandPlural-Formsheaders come from the template's declared language, but this job uses the command payload instead. If a queued/older command omitslanguageor carries a stale value,PotFileRequest.loaddefaults toen, so a non-English template gets the wrong plural rules and the server POT diverges fromdsw-tdk pot; use the fetched DB template language as the source of truth here.
language=self.rq.language,
packages/dsw-document-worker/dsw/document_worker/worker.py:499
- If POT generation raises during
run()(for example on an S3 or database failure), the exception is handled byCommandQueueand processing continues/retries, but this cleanup is skipped. The next command can inherit the failed job's trace/document IDs; put the job call and the tag/ID cleanup in afinallyblock.
PotFileJob(command=command).run()
- Files reviewed: 43/44 changed files
- Comments generated: 2
- Review effort level: Lite
a4049fa to
cec2869
Compare
No description provided.