Institute of English Studies · University of Łódź
A practical methodology for constructing a lightweight, agent-assisted Translation Management System using SQLite, Python, and structured workflows. Covers database design, quality assurance with MQM, file-system architecture, and a phased implementation roadmap for students and freelance translators.
This document describes a working Translation Management System (TMS) developed for the Translation Technology course at the University of Łódź. It is not a theoretical blueprint. Every component described here has been implemented, tested with live jobs, and refined through three design increments. Students can read this document and build a comparable system from scratch.
That said, the architecture does not belong to a single institution. The same SQLite database, the same folder tree, and the same agent pipeline can serve a solo freelancer, a small agency, or an NGO running multi-year programmes across three continents.
Four groups of readers will get the most from this document.
Translation Studies students. If you are studying at a university Translation Studies programme, this document is a practical manual for building translation infrastructure. You will learn how to structure a database, how to route jobs through a state machine, how to enforce quality gates, and how to build a reusable corpus. Every section includes enough detail that you can reimplement the system on a standard Linux workstation without guessing.
Solo freelance translators. A single practitioner running their own practice needs three things: a private translation memory that grows with every job, a self-audit mechanism that catches errors before the client sees them, and an audit log that defends against disputes. The TMS provides all three. No adaptation is required — the solo mode is the default.
Freelancers who want a custom system. The owner built this TMS not to sell a product but to demonstrate that a single freelancer can own their entire pipeline. Every script is plain Python: if your clients prefer British English instead of American, change one variable in the requirements template. If you need a new file format, write a twenty-line handler and add it to the format CHECK constraint. If you want stricter MQM thresholds for sworn translations and looser ones for internal emails, edit the severity weights in the requirements-gathering questionnaire. The system is not a black box — it is a starter kit that assumes you will modify it. This document shows you the default configuration; your configuration will differ, and that is the point.
NOTE! This is version 1.2 – it is not final and requires further tailoring.
Translators everywhere handle heterogeneous document streams: conference abstracts, medical consent forms, lease agreements, software strings, book chapters, sworn diplomas. Commercial CAT tools — SDL Trados, MemoQ — assume a professional agency workflow with project managers, vendor pools, and invoice pipelines. That assumption does not map neatly onto a solo translator, a university course, or a non-profit with one staff linguist. Spreadsheets degrade once you have more than a few dozen jobs. Email folders lose track of versions. Shared drives overwrite each other's files.
The TMS described here fills that gap: a lightweight, agent-assisted system that tracks state, enforces quality checks, and builds a reusable corpus without the overhead of enterprise licensing. It is small enough for one person and structured enough for a team of ten.
Traditional CAT tools excel at segment-level translation memory, terminology matching, and format preservation. They do not, however, reason about register, audience, or institutional context. An AI agent can read a source text alongside a set of context documents and ask: “This is a sworn translation for a legalised diploma — should I use British or American conventions?” A CAT tool cannot ask that question. The trade-off is that the agent needs structure: a database to record state, a file system to isolate versions, and a quality framework to stop bad translations from reaching the client. This document provides that structure.
This document does not describe a lightweight CAT tool with fewer features. It describes a fundamentally different approach to translation memory. Commercial CAT tools begin with segmentation: they chop a document into sentences, match each sentence against a database of previous sentences, and suggest replacements. This architecture excels when source texts repeat verbatim, but it struggles with morphologically rich languages such as Polish, where inflection means that even slight grammatical variation defeats exact-match retrieval and where fuzzy matching returns noisy, low-value suggestions.
The TMS reverses the priority. It begins with the document as a whole. Before translating, the Translator queries QMD using the first 500 words of the source text, retrieving conceptually similar whole documents from the corpus. The translator reads those documents for register, terminology, and style cues — not isolated sentences, but paragraphs in context. Only as a last resort does the system fall back to the segment_cache for verbatim phrase reuse. The segment cache is intentionally primitive: it is a lightweight fallback, not the primary memory mechanism.
This is not a replacement for SDL Trados or MemoQ. It is an alternative architecture for translators whose work is too heterogeneous, too context-dependent, or too morphologically complex for segment-first matching to add value.
The system was built according to two principles.
KISS (Keep It Simple, Stupid): every feature added after the prototype was justified by a concrete failure or bottleneck. There is no plugin architecture, no REST API, no container orchestration. The entire system is a SQLite file, a folder tree, a handful of Python scripts, and an HTML viewer.
Gall's Law: “A complex system that works is invariably found to have evolved from a simple system that worked.” The TMS began as three database tables and four job states. Corpus storage, AI review, and QMD semantic search were added only after the basic pipeline proved it could ingest, translate, and deliver a document without losing data.
The architecture was born in a university Translation Studies programme. It is not trapped there. Below are three contexts where the same components apply, with notes on what each context needs and what (if anything) must change. Another five are listed as possible implementations after heavy modifications (methodology and practical application).
MAIN:
1. Solo freelance translators. A single translator running their own practice needs three things: a private translation memory that grows with every job, a self-audit mechanism that catches errors before the client sees them, and an audit log that defends against disputes. The TMS provides all three. No adaptation is required — the solo mode is the default.
2. Small translation agencies (2–10 translators). Shared terminology becomes essential once more than one person translates for the same client. The SQLite terminology table is readable by every translator; approved entries propagate instantly. The AI reviewer enforces the same QA standard across the team, and client-facing MQM reports justify revision requests or price premiums. The only change needed is a convention: one designated “Orchestrator” operator who handles database writes, since SQLite does not support concurrent writers.
3. NGOs and non-profits. Donor-funded programmes often require audit trails: who translated what, when, and at what quality level. The audit_log table answers that question without extra paperwork. Terminology consistency across multi-year projects prevents “sustainable development” from becoming three different Polish phrases in consecutive annual reports. The system carries zero licensing cost, which matters when the budget is grants and donations.
OPTIONAL:
1. Legal practices and notary offices. Certified translations demand format fidelity and translator accountability. The placeholder protection layer preserves case numbers, statute references, and party names. The AI reviewer flags Critical errors — mistranslated damages figures or misidentified parties — before the document carries a translator's stamp. The audit log provides the traceability that sworn-translator regulations increasingly require. No schema changes are needed, though the requirements-gathering phase should explicitly ask whether the output needs a sworn-translator clause.
2. Publishing houses (book translation). Long-form texts break most lightweight systems. The TMS handles them through chunked AI review: a 60,000-word novel is reviewed in 2,000-word slices, each scored separately. Corpus search lets a translator check whether the protagonist's voice was consistent across chapters translated six months apart. The segment cache stores recurring phrases — “He drained his glass” — so the translator does not reinvent the wheel on page 400.
3. Healthcare and medical translation. Patient safety turns translation quality into a liability issue. The AI reviewer treats Critical errors as a hard gate: a single mistranslated drug dosage or anatomical reference halts the pipeline until it is fixed. The terminology bank stores drug names, procedure names, and anatomical terms with domain tags, so “appendix” is never confused between vermiform and document. Adaptation: the requirements phase should flag medical jobs explicitly so the AI reviewer loads the medical severity rubric.
4. Software localisation (post-editing). User-interface strings repeat across products and versions. The segment cache serves as a lightweight TM for exact-match reuse; placeholder protection ensures that variables like %s and {username} survive translation untouched. The MTPE pipeline treats machine-translated source as a draft file type, triggering post-editing rather than translation from scratch. The only adaptation is format: source files are often .po, .xliff, or .json, which are not in the default format list but can be added by extending the format CHECK constraint and writing a word-count handler.
5. Subtitling and audiovisual translation. Recurring dialogue — “Cut!” — benefits from segment cache lookup. Timing constraints are not enforced by the TMS itself, but the AI reviewer can be configured to flag length violations (a target line exceeding 42 characters) as a Locale Conventions or Design error. Adaptation: source files are typically .srt or .vtt; like software strings, these require a format handler extension.
The same architecture handles different text domains because the requirements phase, the terminology layer, and the MQM framework are all domain-agnostic. What changes is the emphasis.
| Domain | Key Requirement | How the TMS Adapts | MQM Emphasis |
|---|---|---|---|
| Academic | Register consistency, citation preservation | Placeholder protection for citations; corpus search for field-specific terminology | Accuracy, Style |
| Administrative | Speed, volume, consistency | Batch intake; template-based DOCX generation for forms | Accuracy, Locale Conventions |
| Certified / Sworn | Format compliance, translator accountability | Audit log for every change; owner sign-off as legal trace | All dimensions, with Critical as mandatory pass |
| Legal | Liability, format fidelity, certified output | Placeholder protection for case numbers and statute references; DOCX format preservation | Critical errors (legal or financial harm) |
| Literary | Voice preservation, cultural adaptation | Corpus search for character voice consistency; chunked review for long texts | Style, Audience Appropriateness |
| Marketing | Brand voice, persuasion | Requirements phase captures brand guidelines; AI reviewer checks register | Style, Audience Appropriateness |
| Medical | Safety, precision, regulatory compliance | Terminology bank for drug names and procedures; MQM Critical as hard gate | Critical errors, Terminology |
| Technical | Terminology precision, UI consistency | Segment cache for repeated strings; placeholder protection for code | Terminology, Accuracy |
The principle is simple: the pipeline does not care whether the text is a poem or a patent. The agents care, because the requirements phase tells them which rules to load. The database stores the domain tag in corpus_entries.domain_tag so that future queries can filter by field.
An honest architecture document admits its own boundaries.
Enterprise LSPs (50+ translators). SQLite's file-level locking and single-writer design cannot scale to a large agency with simultaneous project managers, translators, and proofreaders all writing to the same database. An enterprise LSP needs PostgreSQL, a REST API, and role-based access control. The TMS is not that.
Real-time interpretation. The TMS is asynchronous by design: files drop, agents process, states advance. Simultaneous interpretation happens in seconds, not hours. The architecture is the wrong shape entirely.
High-volume MT-only pipelines. If the goal is to translate ten million words per day for the lowest possible cost, raw machine translation with no human review is cheaper. The TMS incurs agent-compute and human-proofreading cost that only makes sense when quality, not throughput, is the priority.
Non-text translation. Image OCR post-editing, audio transcription, and video dubbing are out of scope. The pipeline assumes a text file entering at one end and a text file leaving at the other.
Start with a SQLite file, four job states, and a folder tree. Only add complexity after the simple version proves it can translate a document from inbox to delivery without losing data.
The TMS is organised around a single source of truth — the SQLite database — with five functional layers surrounding it:
+---------------------+
| Owner / Human |
| (proofreading, |
| sign-off, inbox) |
+----------+----------+
|
+----------v----------+ +------------------+
| Orchestrator |<--->| HTML Viewer |
| (routes tasks, | | (projects, |
| manages state) | | filters, |
| | | file links) |
+----------+----------+ +------------------+
|
+------+------+
| |
v v
+------+ +--------+
|Translator | AI |
|Agent |Reviewer |
|(Polish-EN) | Agent |
+------+ +--------+
| |
+------+------+
|
+----------v----------+
| File Handler / |
| Cataloguer |
| (word counts, DB |
| writes, moves) |
+----------+----------+
|
+----------v----------+
| Ingest / Repo |
| Manager |
| (corpus, terminology|
| QMD updates) |
+----------+----------+
|
+----------v----------+
| SQLite Database |
| (single source of |
| truth) |
+---------------------+
|
+----------v----------+
| File System |
| (project folders, |
| corpus, inbox) |
+---------------------+
| Component | Technology | Role |
|---|---|---|
| Database | SQLite (translations.db) | Canonical state storage: clients, projects, files, corpus, terminology, audit log, segment cache |
| File System | Standard Linux folders | Project isolation, version history, deliverable separation |
| Orchestrator | Agent role (human interface) | Inbox monitoring, task routing, owner communication, state transitions |
| Translator | Agent role (Polish–English) | Draft translation, register adaptation, terminology compliance |
| AI Reviewer | Agent role (quality reviewer) | MQM-dimensioned review, severity scoring, fix authorisation |
| File Handler | Agent role (operations) | File classification, word counting, format conversion, DB writes |
| Ingest Manager | Agent role (repository) | Corpus ingest, terminology curation, QMD index refresh |
| Viewer | HTML + JavaScript (viewer/index.html) | Read-only project browser with filters, status badges, file links, termbase editing |
| Server | Python http.server (viewer/server.py) | Serves viewer, auto-loads DB, provides /open-folder, /update-project, /edit-term, /delete-term endpoints |
A job enters the system through the inbox and progresses through phases:
Inbox drop → Project creation → Requirements → Translation → AI Review → (Fixes) → Proofreading → Final Target → Delivery → Corpus & Terminology Ingest → Close
The system uses two columns to track progress: a coarse status (4 states) and a fine-grained sub_status (9 phases). Only the Orchestrator advances status; agents advance sub_status within the boundaries of the current status.
| Status | Meaning | Gates |
|---|---|---|
| PENDING | Detected in inbox, not yet processed | No work can proceed |
| ACTIVE | Work is underway | Translation, proofreading, fixing, repository ingest all happen here |
| REVIEW | Awaiting external quality review | AI review only |
| DONE | Complete and archived | No further edits; deliverable is in job/target/ |
| Sub-Status | Parent State | Description |
|---|---|---|
| IDENTIFYING | ACTIVE | Folder scanned, files being classified |
| REQUIREMENTS | ACTIVE | Gathering audience, register, English variant, job type |
| TRANSLATING | ACTIVE | Draft being produced |
| MQM_REVIEW | REVIEW | Under AI quality review |
| FIXING | ACTIVE | Translator addressing AI reviewer issues |
| PROOFREADING | ACTIVE | Owner reviewing the draft |
| COMPLETE | ACTIVE | Translation finished, pre-review |
| REPO_INGEST | ACTIVE | Corpus and terminology being ingested |
| CLOSED | DONE | Final state |
The rule is simple: status controls what can happen next. sub_status records where you are. Only the Orchestrator advances status; agents advance sub_status within the boundaries of the current status.
The system could have used a spreadsheet. It does not, for reasons that become obvious once you have handled more than twenty jobs:
| Criterion | SQLite | Spreadsheet (ODS/XLSX) |
|---|---|---|
| Relational integrity | Foreign keys, ACID transactions | None — data drifts |
| Concurrent access | File-level locking; WAL mode allows readers during writes | Corruption risk if opened simultaneously |
| Queryability | Full SQL; fast filtering | Limited to spreadsheet functions |
| Scale | Tested to hundreds of thousands of rows | Degrades noticeably above ~1,000 rows |
| Automation | Python reads/writes directly | Requires LibreOffice headless automation |
| Backup | Single-file copy | ZIP of XML internals |
| Viewer | Reuse existing HTML viewer pattern | Requires compatible spreadsheet application |
The canonical database lives at Translations/translations.db. All tables use INTEGER PRIMARY KEY AUTOINCREMENT for surrogate IDs. Foreign keys are enforced.
clients
CREATE TABLE clients (
client_id INTEGER PRIMARY KEY AUTOINCREMENT,
client_name TEXT NOT NULL UNIQUE,
contact_info TEXT,
notes TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_clients_name ON clients(client_name);
projects
CREATE TABLE projects (
project_id INTEGER PRIMARY KEY AUTOINCREMENT,
project_key TEXT NOT NULL UNIQUE, -- e.g. ID2026-01-01-001
client_id INTEGER NOT NULL REFERENCES clients(client_id),
language_pair TEXT NOT NULL CHECK(language_pair IN ('EN-PL','PL-EN')),
direction TEXT NOT NULL CHECK(direction IN ('source_to_target','target_to_source')),
start_date TEXT NOT NULL DEFAULT (datetime('now')),
delivery_date TEXT,
status TEXT NOT NULL DEFAULT 'PENDING'
CHECK(status IN ('PENDING','ACTIVE','REVIEW','DONE')),
sub_status TEXT DEFAULT 'IDENTIFYING'
CHECK(sub_status IN (
'IDENTIFYING','REQUIREMENTS','TRANSLATING',
'MQM_REVIEW','FIXING','PROOFREADING',
'COMPLETE','REPO_INGEST','CLOSED'
)),
summary TEXT,
translator_agent TEXT,
reviewer_agent TEXT,
owner_sign_off TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
word_count INTEGER,
price REAL,
currency TEXT NOT NULL DEFAULT 'PLN'
CHECK(currency IN ('PLN','EUR','USD','GBP')),
paid_status TEXT DEFAULT 'NOT PAID'
CHECK(paid_status IN ('PAID','NOT PAID')),
invoice_pdf_path TEXT,
invoice_number TEXT,
domain TEXT CHECK(domain IN ('academic','administrative','certified','general','legal','literary','marketing','medical','technical')),
job_type TEXT CHECK(job_type IN ('translation','proofreading','other'))
);
Key columns added since v1.0:
project_files
CREATE TABLE project_files (
file_id INTEGER PRIMARY KEY AUTOINCREMENT,
project_id INTEGER NOT NULL REFERENCES projects(project_id) ON DELETE CASCADE,
file_name TEXT NOT NULL,
file_path TEXT NOT NULL,
file_type TEXT NOT NULL
CHECK(file_type IN ('source','draft','mqm_reviewed','fixed','proofreading','target','context','terminology')),
format TEXT NOT NULL
CHECK(format IN ('txt','odt','pdf','html','md','docx','xlsx','ods','csv','rtf','other')),
checksum TEXT,
word_count INTEGER,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
Note: word_count is stored per file as well as per project, enabling granular billing and progress tracking.
corpus_entries
CREATE TABLE corpus_entries (
entry_id INTEGER PRIMARY KEY AUTOINCREMENT,
project_id INTEGER NOT NULL REFERENCES projects(project_id),
source_document TEXT NOT NULL,
target_document TEXT NOT NULL,
language_pair TEXT NOT NULL,
domain_tag TEXT,
source_file_name TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_corpus_pair ON corpus_entries(language_pair);
CREATE INDEX idx_corpus_domain ON corpus_entries(domain_tag);
CREATE INDEX idx_corpus_project ON corpus_entries(project_id);
terminology_entries
CREATE TABLE terminology_entries (
term_id INTEGER PRIMARY KEY AUTOINCREMENT,
source_term TEXT NOT NULL,
target_term TEXT NOT NULL,
language_pair TEXT NOT NULL,
part_of_speech TEXT,
domain TEXT,
context_note TEXT,
source_project_id INTEGER REFERENCES projects(project_id),
approved BOOLEAN DEFAULT FALSE,
occurrence_count INTEGER DEFAULT 1,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
confidence_score REAL,
updated_at TEXT,
source_file TEXT
);
CREATE INDEX idx_term_source ON terminology_entries(source_term);
CREATE INDEX idx_term_target ON terminology_entries(target_term);
CREATE INDEX idx_term_pair ON terminology_entries(language_pair);
CREATE INDEX idx_term_domain ON terminology_entries(domain);
CREATE INDEX idx_term_approved ON terminology_entries(approved);
CREATE INDEX idx_term_dedup ON terminology_entries(source_term COLLATE NOCASE, target_term COLLATE NOCASE, language_pair);
Key columns:
audit_log
CREATE TABLE audit_log (
log_id INTEGER PRIMARY KEY AUTOINCREMENT,
project_id INTEGER REFERENCES projects(project_id),
agent_name TEXT NOT NULL,
action TEXT NOT NULL,
details TEXT,
timestamp TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_audit_project ON audit_log(project_id);
CREATE INDEX idx_audit_agent ON audit_log(agent_name);
CREATE INDEX idx_audit_timestamp ON audit_log(timestamp);
segment_cache
CREATE TABLE segment_cache (
segment_id INTEGER PRIMARY KEY AUTOINCREMENT,
source_segment TEXT NOT NULL,
target_segment TEXT NOT NULL,
language_pair TEXT NOT NULL,
project_id INTEGER REFERENCES projects(project_id),
domain TEXT,
quality_score REAL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_seg_source ON segment_cache(source_segment);
CREATE INDEX idx_seg_pair ON segment_cache(language_pair);
The database is created with:
PRAGMA journal_mode = WAL;
Write-Ahead Logging allows multiple readers to access the database while a single writer commits changes. Without WAL, every write locks the entire file, causing “database is locked” errors when the viewer and a script try to read simultaneously.
Only the Orchestrator (or an agent explicitly delegated by the Orchestrator) issues INSERT, UPDATE, or DELETE against translations.db. All other agents read only. This is a convention, not a technical enforcement, but breaking it leads to contention and potential corruption.
Before any write operation, the database is backed up with a timestamp:
backup/auto-backups/YYYY-MM-DD/database/translations.db.bak.HHMMSS
If WAL files exist, they are backed up too. A dedicated script (scripts/backup_db.py) performs this automatically. The script copies both translations.db and translations.db-wal if present. Backup snapshots are retained for 7 days.
Translations/
translations.db -- canonical database
"Project database.sh" -- launcher
"Project database.desktop" -- double-clickable desktop entry
launch-background.sh -- background launcher (no terminal window)
stop-server.sh -- stops the background server
Translation_inbox/ -- owner drops jobs here
(one subfolder per job)
Projects/ -- all project folders
ID2026-01-01-001/
job/
source/ -- original client files
in_progress/ -- working drafts, fixes, proofreading
target/ -- FINAL DELIVERABLE ONLY
context/ -- reference material
terminology/ -- glossary files
temp/ -- working files for agents
project_manifest.yaml -- read-only export from DB
output_config.json -- project-level format settings
viewer/
index.html -- HTML viewer (works offline)
server.py -- tiny HTTP server with DB mutation endpoints
scripts/
create_project.py -- project intake from inbox
generate_docx.py -- DOCX deliverable generation
repo_ingest.py -- corpus + terminology + QMD update
backup_db.py -- timestamped DB backup
terminology_query.py -- search terminology entries
terminology_approve.py -- approve pending terminology (legacy)
ingest_termbase.py -- manual curated termbase ingest
export_manifest.py -- export project manifest from DB
install_dependencies.sh -- one-shot dependency installer
corpus/ -- exported whole-document text files
templates/ -- DOCX templates for deliverables
Every file entering the system is classified into one of eight types. The File Handler applies these rules in order; the first matching rule wins:
| Rule | Condition | Classification |
|---|---|---|
| 1 | File is inside a subfolder named terminology/, glossary/, slownik/, or glosariusz/ | terminology |
| 2 | Filename contains terminology, glossary, slownik, or glosariusz (case-insensitive) | terminology |
| 3 | Filename ends with .csv or .xlsx AND is in a terminology/ subfolder | terminology |
| 4 | Filename contains context or ctx (case-insensitive) | context |
| 5 | Filename ends with a recognised source extension | source |
| 6 | Any file not matching rules 1–5 | context |
The owner can override classification by placing a manifest_override.yaml in the inbox folder:
overrides:
- file: "notes.txt"
classify_as: "context"
- file: "glossary.csv"
classify_as: "terminology"
The File Handler computes word counts using format-appropriate tools:
| Format | Tool | Notes |
|---|---|---|
| .txt, .md, .html, .csv, .rtf | wc -w | After stripping markup tags where applicable |
| .odt, .docx, .xlsx, .ods | libreoffice --headless --convert-to txt | Then wc -w on extracted text |
| pdftotext | Then wc -w | |
| .po, .xliff | Custom handler (if extended) | Parses source or msgid segments |
Total word count is stored in projects.word_count; per-file counts go to project_files.word_count.
This is the most important rule in the file system. Only files in job/target/ are deliverables. Everything else is a working version.
| file_type | Folder | Purpose |
|---|---|---|
| source | job/source/ | Original client file |
| draft | job/in_progress/ | Translator's first output |
| mqm_reviewed | job/in_progress/ | Draft after AI review annotations |
| fixed | job/in_progress/ | Corrected version after addressing AI reviewer issues |
| proofreading | job/in_progress/ | Owner's proofread version |
| target | job/target/ | Final approved translation only |
| context | context/ | Reference material |
| terminology | terminology/ | Glossaries and termbases |
Generated during intake if the source format suggests a default output format (e.g. PDF sources default to DOCX output). Contains project-level settings:
{
"default_output_format": "docx",
"template_path": "templates/basic_translation_template.docx"
}
The system assigns work to five functional roles. Each role has a defined function, personality traits, domain expertise, operating rules, tool requirements, and error reporting protocol. In a student implementation, these roles could be separate scripts, separate user accounts, or simply documented conventions followed by a single operator.
Function: Routes tasks, manages state, interfaces with the owner. The Orchestrator is the only role that may write to translations.db. It monitors the inbox on owner command, initiates project creation, assigns work to other roles, advances status, and generates summary reports.
Personality traits: Methodical, patient, conservative about state transitions. Never auto-advances a job past owner-dependent phases without explicit confirmation (with one exception: the 3-cycle AI review loop guard).
Domain expertise: Higher education administration, Translation Studies workflow design, project management conventions.
Operating rules:
Tools needed: SQLite access (read/write), Bash (folder scanning, file moves), YAML parsing.
Error reporting: Halts and reports to owner on database lock failures, missing inbox folders, or unresolvable file classification conflicts.
Function: Performs the actual translation. Polish↔English specialist. Adapts register, terminology, and audience. Works from placeholder-masked source text and restores non-translatable elements after translation.
Personality traits: Linguistically conservative, terminology-aware, register-sensitive. Asks questions when requirements are unclear rather than guessing.
Domain expertise: Polish-English linguistics, institutional register adaptation (British English default), domain-specific terminology conventions, CAT tool conventions, terminology management, sworn translation requirements.
Operating rules:
Tools needed: Plain-text editing, format conversion tools (libreoffice, pandoc, pdftotext), terminology query access.
Error reporting: Reports to Orchestrator when source text is ambiguous, when placeholders appear malformed, or when terminology conflicts arise.
Function: Reviews translation quality using the MQM framework. Also handles standalone proofreading jobs (no MQM scoring, just error detection). Operates after the Translator produces a draft and before owner proofreading.
Personality traits: Rigorous, detail-oriented, sceptical of the Translator's output. Separates translation quality from translation effort.
Domain expertise: MQM typology (seven dimensions), severity weighting, Polish-English error patterns, domain-specific translation norms (academic, legal, medical, technical, and others).
Operating rules:
Tools needed: MQM scoring rubric, side-by-side text comparison, database read access.
Error reporting: Reports critical errors directly to Orchestrator with dimension, severity, and segment reference.
Function: File operations, word counting, format conversion, database writes (under Orchestrator delegation). Classifies files, computes checksums, counts words per format, moves files between folders.
Personality traits: Pedantic about paths, defensive about data loss, never overwrites without confirmation.
Domain expertise: File systems, text extraction pipelines, SHA-256 integrity checking, Python scripting.
Operating rules:
Tools needed: wc, libreoffice, pdftotext, pandoc, python-docx, openpyxl, odfpy, SHA-256, SQLite (under delegation).
Error reporting: Reports extraction failures, unrecognised formats, and checksum mismatches.
Function: Corpus and terminology ingest, QMD index updates. Runs after a project reaches DONE status. Extracts source and target text, stores whole-document blobs, populates segment cache, manages curated terminology, updates semantic search index.
Personality traits: Batch-oriented, idempotent, tolerant of partial failure.
Domain expertise: Text alignment heuristics, QMD semantic search, corpus linguistics, terminology curation.
Operating rules:
Tools needed: pandoc, pdftotext, QMD binary, SQLite (under delegation).
Error reporting: Reports corpus extraction failures, QMD binary absence, and terminology parse errors.
The pipeline has phases. Each phase is labelled with the design increment in which it was introduced.
Before any work begins, the Orchestrator asks the owner: “What type of job is this?” The answer determines the active pipeline.
The functional roles in the table below are generic. Assign your own names when building the system.
| Job Type | Workflow | Active Phases | Status Flow |
|---|---|---|---|
| translation | Translator → AI Reviewer → Owner proofreading → delivery | Ingest → Requirements → Translation → AI Review → (Fixes) → Proofreading → Complete → Repo Ingest → Close | PENDING → ACTIVE (IDENTIFYING→REQUIREMENTS→TRANSLATING→MQM_REVIEW→PROOFREADING→COMPLETE→REPO_INGEST) → DONE (CLOSED) |
| proofreading | Owner provides existing text → AI Reviewer → Owner proofreads again | Ingest → Requirements → AI Review → (Fixes) → Proofreading → Complete → Close | PENDING → ACTIVE (IDENTIFYING→REQUIREMENTS→MQM_REVIEW→PROOFREADING→COMPLETE→REPO_INGEST) → DONE (CLOSED) |
| other | Owner explains the task; Orchestrator evaluates capability | Custom routing | Owner decides; Orchestrator confirms feasibility |
Proofreading jobs skip the TRANSLATING phase because the source text is treated as the owner’s draft. The AI reviewer evaluates the existing text directly.
This phase is a hard gate. The Orchestrator cannot advance to translation work until the owner has answered every question.
Runs only for job_type = 'translation'.
Runs for both translation and proofreading jobs.
Runs only when the AI reviewer flags issues.
This phase is a hard gate.
+-----------+
| PENDING |
+-----+-----+
| owner drops files
v
+-----------------------+
| ACTIVE |
| sub: IDENTIFYING |<-------------------------+
+-----------+-----------+ |
| classification complete |
v |
+-----------------------+ |
| ACTIVE | |
| sub: REQUIREMENTS | |
+-----------+-----------+ |
| requirements confirmed |
v |
+-----------------------+ |
| ACTIVE | |
| sub: TRANSLATING | |
+-----------+-----------+ |
| draft complete |
v |
+--------------------+--------------------+ |
| | |
| job_type = translation | job_type = proofreading
v v |
+-----------------------+ +-----------------------+ |
| REVIEW | | REVIEW | |
| sub: MQM_REVIEW | | sub: MQM_REVIEW | |
+-----------+-----------+ +-----------+-----------+ |
| | |
| score OK | score OK |
v v |
+-----------+ +-----------------------+ |
| DONE | | ACTIVE | |
| CLOSED | | sub: PROOFREADING |---+
+-----------+ +-----------+-----------+
^
| fixes needed
+-----------+-----------+
| ACTIVE |
| sub: FIXING |
+-----------------------+
Note on MQM_REVIEW: the workflow discussions refer to this phase as “AI_REVIEW”. The database CHECK constraint still contains the original MQM_REVIEW string. The two names are synonymous in practice.
Multidimensional Quality Metrics (MQM) is an industry-standard error typology for translation quality assessment. Unlike holistic “good/bad” scoring, MQM breaks quality down into dimensions, each checked for errors classified by severity. The system uses MQM Core, which defines seven high-level dimensions.
| Dimension | What It Covers |
|---|---|
| Terminology | Correct and consistent use of domain-specific terms |
| Accuracy | Fidelity to source meaning; no additions, omissions, or distortions |
| Linguistic conventions | Grammar, syntax, morphology, spelling |
| Style | Appropriateness to audience, register, and client style guides |
| Locale conventions | Date formats, number formats, currency, address formats |
| Audience appropriateness | Suitability for intended readers |
| Design and markup | Preservation of formatting, tags, placeholders, structural elements |
The system uses a fixed-deduction model: each error deducts a flat penalty regardless of document length. This makes scores comparable across jobs.
| Severity | Weight | Definition |
|---|---|---|
| Critical | 10 | Risk of legal, financial, or safety harm; meaning completely wrong |
| Major | 5 | Significant meaning distortion, unacceptable terminology, or broken grammar that impedes comprehension |
| Minor | 1 | Cosmetic issue (punctuation, minor style deviation) that does not impede understanding |
Per-dimension score:
dimension_penalty = (critical_count * 10) + (major_count * 5) + (minor_count * 1)
dimension_score = max(0, 100 - dimension_penalty)
overall_score = mean of seven dimension scores
Example: a 100-word text and a 1,000-word text each with 1 major error both score 95 in that dimension.
A default threshold of 90/100 is documented as a placeholder. It is not enforced automatically until at least five sample translations have been scored by a human calibrated rater and the owner confirms the threshold is appropriate for Polish-English institutional translation (calibrate per domain). Until then, the AI reviewer reports the score and flags critical errors, but the Orchestrator advances the job based on owner command, not the score alone.
For documents exceeding 5,000 words, the AI reviewer reviews in chunks of ~2,000 words to maintain focus. Each chunk receives a provisional score; the overall score is the mean of chunk scores.
The AI fix loop (MQM_REVIEW <-> FIXING) is capped at 3 cycles. After the third cycle, the job is forced to ACTIVE / PROOFREADING with flag MQM_CYCLES_EXHAUSTED. This prevents oscillation when the Translator and AI reviewer disagree on error severity.
The TMS provides three levels of corpus reuse, in order of priority:
| Table | Purpose | Grows With |
|---|---|---|
| projects | Job tracking | Every new job |
| corpus_entries | Whole-document pairs | Every completed translation |
| terminology_entries | Curated bilingual terms | Every termbase ingest |
| segment_cache | Reusable segments | Every corpus ingest |
| audit_log | Action traceability | Every agent action |
The system stores completed translations as whole-document blobs in corpus_entries. This is a deliberate choice:
QMD (a semantic search tool) indexes the corpus for conceptual similarity. After every repository ingest, the Orchestrator runs:
PATH="/path/to/qmd:$PATH" qmd update
During translation (Increment 3), the Translator queries QMD using the first 500 words of the source text. Results are cached in temp/[project_key]_tm_suggestions.md. Per-segment queries during translation are rejected as unworkable — they add latency without proportional benefit.
The terminology bank is manually curated. There is no automatic extraction pipeline.
How entries are added:
Key design decisions:
Script usage example:
python3 \
scripts/ingest_termbase.py \
--source-file "terminology/general_glossary.txt" \
--domain general \
--source-name "general_glossary"
Supported formats: .xlsx (two-column style with en/pl headers) and .txt (single-line style with = delimiters and ; variant separators).
The segment_cache table acts as a lightweight translation memory. Because paragraph alignment is unreliable when source and target paragraph counts differ (see Weakness #18), the segment cache is intentionally treated as a best-effort fallback rather than an authoritative translation memory. It stores individual source-target segment pairs extracted during repository ingest. Querying it is simple:
SELECT target_segment FROM segment_cache
WHERE source_segment = ? AND language_pair = ?;
Limitation: The segment cache supports exact-match lookup only. There is no fuzzy matching. If the source sentence differs by even one word, the cache returns nothing. This is a known limitation (see Section 12).
The table below summarises the feature-level differences. What follows is a domain-by-domain argument for when the TMS offers capabilities that commercial CAT tools cannot replicate, at a cost commercial tools cannot match.
| Feature | This TMS | SDL Trados | MemoQ | OmegaT |
|---|---|---|---|---|
| Semantic / Conceptual Search | QMD indexes whole-document corpus; Translator queries with first 500 words of source text | Not available (or limited concordance) | Not available | Not available |
| Translation Memory | Whole-document corpus + QMD semantic search (conceptual similarity); exact-match segment cache as fallback. No fuzzy matching. | Full TM with fuzzy matching (50–100%) | Full TM with fuzzy matching | Full TM with fuzzy matching |
| Terminology | SQLite table with curated manual ingest; bidirectional search. | Integrated termbase (MultiTerm) | Integrated termbase | Integrated glossary |
| QA Framework | MQM fixed-deduction scoring with 7 dimensions | Customisable QA checks (spelling, numbers, tags) | Customisable QA checks | Basic QA (glossary, regex) |
| Format Preservation | Format-specific scripts (DOCX, ODT, PDF→text) | Native filters for 100+ formats | Native filters for 100+ formats | Native filters for common formats |
| Cost | Free (open-source tools only) | Expensive (annual licensing) | Expensive (annual licensing) | Free |
| Customisation | Full source code access; modify any script | Limited (SDK available) | Limited (SDK available) | Full source code (Java) |
| Speed | Agent-dependent; human-in-the-loop | Real-time TM/terminology lookup | Real-time TM/terminology lookup | Real-time TM/terminology lookup |
| Accuracy | High for Polish-English institutional translation; AI review loop with domain-adaptive severity weights | Depends on TM quality and settings | Depends on TM quality and settings | Depends on TM quality and settings |
| Accountability | Full audit log (audit_log table) | Limited (project history) | Limited (project history) | Limited (version control if configured) |
| Scalability | Single-user; SQLite handles ~100K projects | Multi-user server architecture | Multi-user server architecture | Single-user baseline |
Customisation is not a feature — it is the architecture. Every component is exposed for modification because the system assumes no two freelancers have identical needs.
The TMS intentionally substitutes whole-document semantic search for fuzzy TM. See Section 1, “A different paradigm.”
The honest assessment: this TMS is not a replacement for Trados in a commercial agency. It is a replacement for the spreadsheet-and-email workflow of a freelance translator — whether academic, legal, medical, technical, or literary — who needs a customisable, quality-enforced translation pipeline without licensing fees. The same architecture serves a solo freelancer, a small agency, or a non-profit language programme; only the requirements-gathering questionnaire changes.
Academic translation lives or dies on register consistency and citation integrity. A CAT tool will match “hermeneutic circle” from a previous job, but it will not warn you that the current client's style guide prefers “hermeneutic cycle.” The TMS requirements phase captures the style guide explicitly; the AI reviewer checks against it during the MQM Style dimension. Placeholder protection ensures that LaTeX citations, DOI strings, and bibliography keys survive translation untouched. The corpus stores whole documents, so a translator can verify whether they used the same rendering of “performative utterance” in a paper six months ago. For Polish↔English academic work, the AI review loop catches register drift and citation corruption that CAT QA modules do not even attempt to detect.
The honest limitation: the TMS has no fuzzy matching. If the source text contains “performative utterances” (plural), the exact-match segment cache returns nothing. The translator must recognise the variant manually or rely on corpus search.
University faculties, HR departments, and student offices produce high-volume, repetitive document streams: council minutes, Erasmus agreements, degree confirmations. Speed matters, but so does consistency — “Rector” must not become “Vice-Chancellor” halfway through a reporting cycle. The TMS handles this through template-based DOCX generation, batch intake, and the segment cache for recurring phrases. The audit log provides the traceability that institutional audits demand. Most importantly, the zero licensing cost means a language centre can deploy the system without begging the bursar for a software budget.
The honest limitation: the TMS does not support real-time multi-user collaboration. If two staff members try to update the same project simultaneously, SQLite's file locking serialises the writes. A convention — one designated Orchestrator operator — prevents conflicts.
Certified translations carry legal liability. A mistranslated date of birth on a sworn diploma or a misidentified party in a notarised contract can invalidate the document and expose the translator to disciplinary proceedings. The TMS treats MQM Critical errors as a hard gate: the AI reviewer halts the pipeline until the error is fixed. The owner_sign_off timestamp is a legal traceability record: the owner confirmed the final text before delivery. The audit log records every change with agent name and timestamp. No commercial CAT tool provides a built-in legal traceability layer of this granularity.
The honest limitation: placeholder detection is regex-based. Unusual formatting or non-standard citation styles are missed. Lowercase proper names (e.g. “iPhone”) may be translated in error. The owner must review temp/[key]_placeholders.json before translation.
Legal translation demands precision for liability reasons, but it also demands consistency across document families. A lease agreement and its addendum must use identical terminology for “force majeure” and “termination clause.” The TMS terminology bank stores these terms with domain tags, and the bidirectional search ensures that a Polish query finds the English equivalent even though only the EN→PL direction is stored. The AI reviewer loads a legal severity rubric during the requirements phase, weighting Critical errors more heavily for financial and contractual terms. Corpus search lets a translator verify how they rendered “indemnification” in a previous mandate.
The honest limitation: the TMS does not generate sworn-translator clauses or certification stamps automatically. The requirements phase must capture this need, and the owner must insert the clause manually.
Literary translation is the domain where CAT tools are weakest and the TMS is strongest. A CAT tool treats “He drained his glass” as a reusable segment; the TMS treats it as a phrase whose register and emotional colouring must match the protagonist's voice across 400 pages. Corpus search — especially QMD semantic search — lets a translator check whether the voice was consistent across chapters translated months apart. The chunked AI review strategy handles long novels in 2,000-word slices without reviewer fatigue. The requirements phase captures audience age, genre conventions, and cultural adaptation needs.
The honest limitation: the TMS has no sentence alignment. Paragraph-level alignment is coarse. A translator searching the corpus for a specific sentence may receive the entire paragraph. For literary work, this is often a feature (context is everything), but it wastes storage.
Marketing translation is about persuasion, not fidelity. A slogan that works in Polish may be nonsense in English if translated literally. The TMS requirements phase captures brand guidelines, tone-of-voice documents, and competitor positioning. The AI reviewer checks the Style and Audience Appropriateness dimensions against these guidelines. The segment cache is less useful here — marketing copy rarely repeats verbatim — but the corpus search lets a translator check how the brand spoke about itself in previous campaigns.
The honest limitation: the TMS does not integrate with design tools (InDesign, Figma). Format preservation handles text files only; desktop publishing workflows are out of scope.
Patient safety makes medical translation the most liability-sensitive domain in this list. A single mistranslated drug dosage, anatomical reference, or contraindication can cause serious harm. The AI reviewer treats every Critical error as a pipeline halt. Your curated terminology bank stores domain-tagged entries from your chosen termbases — for example, a general-domain glossary and a specialised medical glossary. A query for “appendix” returns different results in the medical domain (vermiform appendix) and the general domain (document appendix) because the domain filter routes the query correctly. The MQM Terminology dimension is weighted most heavily for medical jobs.
The honest limitation: the terminology bank does not include drug interaction data or dosage conversion tables. It is a linguistic resource, not a clinical decision support system. The translator — not the TMS — bears final responsibility for medical accuracy.
Technical translation lives on terminology precision and string reuse. Software strings, user manuals, and safety instructions repeat across product versions. The segment cache serves as a lightweight TM for exact-match reuse. Placeholder protection ensures that variables, code snippets, and UI element IDs survive translation untouched. The requirements phase captures the product's terminology conventions and UI style guide.
The honest limitation: the segment cache is exact-match only. If a software string changes from “Save file” to “Save document,” the cache returns nothing. There is no fuzzy matching for near-misses. For high-volume software localisation, a dedicated CAT tool with fuzzy TM is more efficient.
General-domain translation — letters, emails, casual web content — is where the TMS is least differentiated from a CAT tool. The requirements phase is lighter, the MQM threshold is lower, and the segment cache provides modest benefit because general texts rarely repeat. Where the TMS still wins is cost: a freelance translator doing occasional general work cannot justify a Trados licence. The TMS provides terminology search, corpus lookup, and audit logging at zero licensing cost.
The honest limitation: for pure general-domain volume work, the TMS's agent-compute overhead may not be worth the quality gain. If the client cares only about speed and cost, raw MT with minimal post-editing is cheaper.
Journal submissions, research grant proposals, conference abstracts. The system handles LaTeX-like citation syntax protection and academic register adaptation. The same pipeline handles legal contracts, medical consent forms, and technical manuals — the requirements phase loads the appropriate register and terminology set.
Faculty council minutes, HR documents, student records. These often require certified or sworn translation notes; the requirements-gathering phase captures this.
Short, high-visibility texts where terminology accuracy is critical. AI review is strongly recommended.
Long-form texts where chunked AI review and corpus reuse provide the most benefit.
Diplomas, transcripts, legalised documents. The system records sworn translator notes and certification requirements in projects.summary.
Machine-translated texts brought in for human refinement. The source is treated as a draft file type; the Translator performs post-editing rather than translation from scratch.
Owner provides a completed translation for AI review and final polish. The job_type = 'proofreading' path skips the translation phase.
| Issue | Severity | Workaround / Future Fix |
|---|---|---|
| Chunk misalignment | Medium | Manual review of repo_ingest.py output; future: integrate hunalign or bleualign |
| Placeholder detection misses | Medium | Owner reviews temp/[key]_placeholders.json before translation; future: spaCy NER |
| No invoice generation | Low | Use external accounting system; store reference in projects.invoice_pdf_path |
| No payment tracking | Low | Binary PAID/NOT PAID flag only; editable via viewer dropdown |
| QMD dependency | Medium | Falls back to SQLite LIKE queries if QMD unavailable |
| No fuzzy segment matching | Medium | Intentional design choice — QMD semantic search and whole-document corpus provide conceptual and contextual matching. Segment cache handles verbatim reuse only. See Section 8 and Section 1. |
| No sentence alignment | High | repo_ingest.py attempts heuristic alignment only when counts match |
| Single-user SQLite | Medium | WAL mode mitigates reader contention; writer serialization is by convention |
The viewer is a single HTML file (viewer/index.html) that uses sql.js (a JavaScript build of SQLite) to load the database entirely in the browser. This choice has three advantages:
viewer/server.py is a tiny Python http.server subclass with additions:
The launcher script (Project database.sh) starts the server, records its PID, opens the browser, and tails the log file.
| Tool | Purpose |
|---|---|
| libreoffice (headless) | ODT-to-text conversion, DOCX generation |
| pdftotext | PDF text extraction |
| pandoc | RTF-to-text, format conversion |
| wc | Word counting for plain text |
| xdg-open | Folder opening from viewer |
| Library | Purpose | Install |
|---|---|---|
| python-docx | DOCX read/write | pip install python-docx |
| docxtpl | DOCX template rendering | pip install docxtpl |
| openpyxl | XLSX read/write | pip install openpyxl |
| odfpy | ODS read/write | pip install odfpy |
| pandas | Data manipulation | pip install pandas |
| PyMuPDF (fitz) | PDF manipulation | pip install PyMuPDF |
| Tool | Purpose | Install |
|---|---|---|
| QMD | Semantic search over corpus | Requires Bun runtime; configure the binary path to match your installation |
Any modern browser (Chrome, Firefox, Edge, Safari). The viewer uses vanilla JavaScript with no frameworks. sql.js ASM build is included as a vendor file; no WASM file is needed, so file:// protocol works.
Goal: A working system that can ingest a job, track it in a database, and display it in a viewer.
Goal: End-to-end translation with quality gating.
Goal: Reusable repository, semantic search, and curated terminology.