Translation
The translator package is a single adapter, llm_translator, that translates a document from one language to another with an LLM while keeping markdown, URLs, and structure intact. The system prompt is tuned for banking and financial content, and the defaults target the most common Factflow case: Norwegian → English. The adapter injects llm_factory and runs inside a route like any other.
Configuration
Section titled “Configuration”llm_profile is the only required field — it selects which configured client the LLM factory builds. Languages are written as full names ("Norwegian", "English"), not ISO codes — they're interpolated straight into the prompt.
| Field | Default | Purpose |
|---|---|---|
llm_profile | (required) | LLM profile used for translation, e.g. rai-chat-azure-openai |
source_language | Norwegian | Language to translate from |
target_language | English | Language to translate to |
preserve_formatting | true | Keep markdown formatting in the output |
timeout | 120.0 | Per-request LLM timeout in seconds (10–300) |
skip_english_paths | true | Skip documents whose URL path marks them already-English |
skip_path_patterns | ["/en/", "/en-", "-en/", "-en."] | URL fragments that indicate English content |
accepted_content_types | ["text/html", "application/xhtml+xml"] | Only translate these source content types |
require_content_type | true | Skip content with no source_content_type metadata |
rate_limit | null | Optional AIMD limiter (max_concurrency, floor) |
- type: "llm_translator" config: llm_profile: "rai-chat-azure-openai" source_language: "Norwegian" target_language: "English" timeout: 240 skip_english_paths: true skip_path_patterns: ["/en/", "/en-", "-en/", "-en."]What it skips (and why)
Section titled “What it skips (and why)”The adapter is deliberate about not translating things it shouldn't. Each skip drops the message from the pipeline (continue_pipeline=False) with a reason in metadata — it never raises:
- Empty content — nothing to translate.
- Non-HTML source — if
require_content_typeis set andsource_content_typeis missing, or the type isn't inaccepted_content_types, the document is skipped. Translation only runs on HTML. - Already English — if the source URL contains any
skip_path_patternsfragment (/en/, …), the page is treated as already-English and passed over.
This is what lets you point the translator at a mixed-language crawl and have it touch only the Norwegian HTML.
Input and output
Section titled “Input and output”Input requires content (string or bytes); object_key, document_id, url, title, and source_content_type are read when present. Output is shaped for markdown_storage_writer: the translated text lands in markdown (and content), original_object_key is preserved for lineage, and a metadata.translation block carries per-call stats — input_chars, output_chars, tokens_in, tokens_out, elapsed_ms, finish_reason.
On failure the error is classified (fatal / retryable) so the broker's redelivery and dead-letter policy applies.
Where it fits
Section titled “Where it fits”The shipped demo/dnb-translation.yaml runs it between storage retrieval and the markdown writer:
storage_retriever → llm_translator → markdown_storage_writerstorage_retriever supplies the Norwegian markdown and its source_content_type; llm_translator translates the HTML pages and skips the rest; markdown_storage_writer persists the English variant to its own stage.
Related
Section titled “Related”factflow-translatorreference — the package API surface- LLM clients — how
llm_profileresolves to a client - Rate limiting — the AIMD limiter behind
rate_limit