Content & Product Engineering / Museum case study
One Edit, Two Languages: A Museum’s Publishing Workflow on Semitexa
An editor corrects a museum page in Ukrainian. Its English version now needs the same attention. Semitexa’s CMS connects that save to a translation queue, while the museum application decides which fields to translate and how visitors read them. The source code shows a practical way to make multilingual publishing part of everyday editorial work.
Every correction creates work in another language
Imagine an editor correcting an exhibition description, saving it, then spotting another sentence to improve. This is an illustrative editing sequence. For a bilingual site, each save raises the same question: does the English page still say what the Ukrainian page says?
The Chernivtsi Regional Museum’s English website offers English navigation and translated exhibition and news content. Maintaining that experience requires a process for later corrections, alongside the original translations. An old English paragraph can continue to look credible after its source has changed.
The inspected application connects a museum-specific page editor and translator to Semitexa’s shared CMS. The editor saves the source record. The CMS schedules translation work. The public page reads a stored language overlay. That connection makes keeping the versions in step an application responsibility.
From correction to language version
- Edit the sourceSave Ukrainian page fields
- Queue the workWait for the editing window
- Translate the recordStore returned English fields
- Render the pageRead the stored language overlay
The editor changes the record the website reads
RegmusPageEditor exposes the title, short description, HTML body, and search metadata. It loads and saves through the museum’s page repository, which the public page handler also uses. The title must remain nonempty.
The shared CMS save handler uses the declared field types to sanitize submitted HTML and checks required values again after sanitization. It then calls the museum editor’s save operation. This joins a general editing interface to the application’s existing content model.
After the source write, the handler finds a registered translator for that editor, asks for a source fingerprint, and queues the record when a fingerprint exists. The provider call happens later. Saving a corrected paragraph therefore does not require waiting for translation to finish.
Those writes are separate. If source content reaches its repository but a later metadata or queue step fails, the handler reports a warning rather than claiming the text was never saved. The distinction helps an editor understand whether to re-enter content or address the follow-up work. It also means this path is not one atomic “all languages published” transaction.
Give a series of corrections time to settle
TranslationQueue defaults to a ten-minute waiting window. Saving again pushes the deadline out. In an ordinary sequence of quick corrections, this consolidates work around the text the editor eventually leaves in place.
For example, a save at 10:00 makes the record due at 10:10. A further save at 10:03 moves it to 10:13. These are illustrative times. With the default five-minute scheduler cadence, an eligible record can be picked up on a later tick; backlog and provider response time add to the delay. Ten minutes is a scheduling window, not a promise that English will be ready in exactly ten minutes.
The queue stores a source hash and the hash last recorded as translated. When the current fingerprint matches the translated one, it clears the outstanding deadline. A source edit can restart work and clear its previous failure count. This gives the queue a way to distinguish work owed from a version it already considers handled.
Before translating, the drain recalculates the fingerprint from the current record. When settling a result, it clears the deadline only if the queued source hash still matches the translated hash. That bookkeeping avoids declaring a newly queued edit finished on the strength of an older fingerprint. It does not establish an atomic snapshot across the page write and the provider call.
The museum defines what English means for a page
RegmusPageTranslator selects three fields: title, description, and content. It gathers eligible nonempty source values and sends them through RegmusTranslator, which uses Semitexa’s LLM provider integration. A change triggers a translation of the eligible field set; this path does not compute a separate translation job for each changed field.
The provider is instructed to return the same JSON keys and preserve HTML tags, attributes, links, numbers, and dates. The adapter parses the response and accepts nonempty string values for requested keys. Those instructions express the intended translation behavior; the adapter does not independently prove that every date or piece of markup was preserved.
Returned values are merged into translations['en']. Existing English values remain for fields the response does not replace. The public template calls Page::t() for localized fields. That accessor uses a nonempty stored translation and falls back to the Ukrainian base value when a translation is absent or empty.
The implementation has a deliberate size boundary. An HTML body over 12,000 bytes after trimming is excluded from the automatic translation request and from its fingerprint. Titles and descriptions remain eligible. An existing English body is retained. This protects the queue from a single large request, but it also means a long article’s body can require a separate editorial translation process.
The translator’s three-field scope excludes SEO fields. Likewise, a partially populated provider response can update some fields while preserving older values for others. “Automatically translated” therefore describes this defined path; it does not certify that every field or every page is fully synchronized.
A provider failure becomes queued work
If the translation adapter returns no usable result, the page translator throws an exception. The drain catches it and records a failed attempt. The queue schedules a retry thirty minutes later, stores a truncated error message, and excludes tasks once they reach five failed attempts.
The source content remains saved. Until a replacement is written, the English overlay can continue serving its previous values. The accessor’s fallback helps when a value is missing; it does not detect that an existing translation is stale.
| Situation | What this path does | Editorial consequence |
|---|---|---|
| Several quick saves | Move the translation deadline later. | Allow corrections to settle before queued work runs. |
| No usable provider result | Record failure and schedule a bounded retry. | The English version may remain behind the source. |
| Body exceeds the size limit | Translate eligible short fields and retain the existing body. | Plan a separate update for the long translation. |
A team adopting this pattern should decide who checks terminology, what happens to exhausted tasks, and which content requires human approval. The inspected route updates the English overlay directly; it does not add a translator approval screen or a guarantee of linguistic accuracy. Those are further product decisions.
Each site has its own translation work
The museum runs within a project containing several site modules. Its page editor and translator declare tenant: 'regmus'. The CMS surface registry filters tenant-specific implementations against the current tenant before returning an editor or translator.
The translation queue stores a tenant identifier and explicitly scopes its repository through forTenant(). The scheduled job declares tenantMode: 'per_tenant', a default five-minute cadence, an overlap policy of skip, and batches of ten records. The console command cms:translate:drain uses the same drain service.
These are concrete boundaries around CMS surfaces and queued translation tasks. They let sites share the mechanism while supplying their own translators. They do not, by themselves, establish complete isolation of every table, asset, or application operation in the wider project.
Our article on tenant context in background work explains the wider execution concern. This museum case shows the editorial effect: a site’s saved content needs follow-up work in that site’s context.
Make the next editorial step part of the product
The practical benefit is a connected routine: edit the source once, let the application schedule the eligible English update, and keep the result beside the content visitors already read. The architecture can reduce the need to remember a separate translation task after each correction. The source review does not measure staff hours or provider spending saved.
Semitexa’s CMS provides the editor and translator contracts, surface discovery, save integration, and queued execution. The museum supplies its page repository, field selection, English overlay, translation adapter, and public rendering. The reusable mechanism and the site’s editorial policy meet at those contracts.
That division gives product teams clear decisions to make: which fields to translate, how long to wait, what a failure should do, and when a person must approve the result. The museum’s current implementation answers those questions for a specific Ukrainian-to-English workflow. A different language pair or approval process needs its own implementation and checks.
What was checked
This article follows the local museum application and installed CMS source inspected on September 30, 2026. The public English homepage was also observed on that date. Public content demonstrates an English visitor experience; it does not establish how a particular translation was produced or whether the production scheduler is running.
The existing TranslationTaskTest and ContentSaveReportingTest suites passed: 10 tests, 28 assertions. They cover translation task state copying and save-reporting helpers. They do not exercise provider calls, database queue isolation, the scheduler, or an end-to-end editorial save.
Implementation references and review scope
Museum sources: RegmusPageEditor, RegmusPageTranslator, RegmusTranslator, Page::t(), and the public page template. Shared CMS sources: ContentSaveHandler, ContentSurfaceRegistry, TranslationQueue, TranslationDrain, and ContentTranslateJob.
The inspected project HEAD was 333bcc5. Claims refer to the local source and installed package snapshot, which can include work beyond that commit. No production content was edited and no paid translation was requested for this review. This describes the current workflow, independently of the museum’s initial delivery time.
Start with the editor’s next task. A useful multilingual product connects source edits, translation work, and visible language versions, with clear handling for the cases automation leaves to people.