Skip to content

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.

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.

FieldDefaultPurpose
llm_profile(required)LLM profile used for translation, e.g. rai-chat-azure-openai
source_languageNorwegianLanguage to translate from
target_languageEnglishLanguage to translate to
preserve_formattingtrueKeep markdown formatting in the output
timeout120.0Per-request LLM timeout in seconds (10–300)
skip_english_pathstrueSkip 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_typetrueSkip content with no source_content_type metadata
rate_limitnullOptional 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."]

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_type is set and source_content_type is missing, or the type isn't in accepted_content_types, the document is skipped. Translation only runs on HTML.
  • Already English — if the source URL contains any skip_path_patterns fragment (/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 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.

The shipped demo/dnb-translation.yaml runs it between storage retrieval and the markdown writer:

storage_retriever → llm_translator → markdown_storage_writer

storage_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.