-
[Agent] Notify user of custom translation glossary.
Tell the user: """
Disclaimer: This translation was generated by a large language model and has not been reviewed by a professional human translator. AI-generated translations may contain errors, omissions, or inaccuracies, particularly with idiomatic expressions, industry-specific terminology, cultural nuances, and context-dependent phrasing. This output should not be used as a final, authoritative translation for legal, regulatory, medical, financial, or safety-critical purposes without review and approval by a qualified human translator. Use at your own discretion.
Starting translation....
You can edit your custom translation glossary for future translations in:
Settings → Capabilities → Skills → Microsoft Document Translator → references → glossary.csv.
"""
Do NOT wait for a response. Continue immediately.
-
[Decide] Validate input file and detect format:
- Confirm the file exists
- Check file extension:
.docx → set doc_format = "docx"
.pptx → set doc_format = "pptx"
- Any other extension → inform user: "Supported formats: .docx and .pptx" and stop
- If file doesn't exist → ask user for a valid file
-
[Agent] Load Phase 1 scripts (extraction) and extract:
a. Use file_read to load ONLY Phase 1 scripts from the skill's install directory:
- ALWAYS load (both formats):
scripts/state.py (TranslationState class + _STATE singleton, loaded FIRST)
scripts/extract.py (extraction for DOCX + PPTX, batching, extract_document())
scripts/glossary.py (glossary parsing and batch serialization, loaded LAST)
- Do NOT load reconstruction scripts yet. They load in Phase 2 during worker time.
b. In a SINGLE run_python call, pass as code the concatenation of the Phase 1 scripts plus:
- Line 1:
file_path = "<absolute path>" (use WORKSPACE_DIR for attached files, absolute paths for local files)
- Lines 2+: The ENTIRE content of the Phase 1 scripts verbatim (concatenated in order: state.py → extract.py → glossary.py)
- Final line:
extracted_batches, stats = extract_document(file_path)
c. After execution: extracted_batches, stats, and all functions persist in namespace. The _STATE singleton holds translations (empty dict), run_map, batches, file_path, and doc_format, all persisting across subsequent run_python calls.
d. Load the glossary: Use file_read to get references/glossary.csv from the skill directory. Then in run_python: glossary = load_glossary_from_content("""<glossary csv content>"""). If file_read fails (file doesn't exist), set glossary = [].
Validate: stats["total_paragraphs"] > 0.
If fails: the file has no extractable text. Inform the user the document appears empty or unreadable and stop.
-
[Agent] Detect source language:
sample_text = get_first_words(400)
print(sample_text[:200])
From the printed text, determine the source language. Store as source_language.
-
[Agent] Match glossary columns:
glossary_source, glossary_target, all_headers = match_glossary_columns(glossary, source_language, target_language)
print(f"Glossary: source='{glossary_source}', target='{glossary_target}', headers={all_headers}")
If glossary_target is empty, the glossary won't be used for this language pair, and that's fine.
-
[Agent] Spawn translation workers:
a. Create a task group and confirm batch count:
print(f"Total batches to translate: {len(extracted_batches)}")
b. In a SINGLE run_python call, with start_task injected as an available tool, spawn ALL workers in a for-loop.
This is CRITICAL. Do NOT call start_task directly from the agent. Spawning must happen
inside run_python to batch the requests. Do NOT split batches into smaller sub-groups
(e.g., 15+14 is WRONG for 29 batches, so spawn all 29 in one call). Up to 30 workers
per run_python call is safe and tested. For documents with more than 30 batches, use
multiple run_python calls of up to 30 each, and spawn ALL calls before waiting.
for batch_idx, batch in enumerate(extracted_batches):
batch_json = sanitize_batch_for_embedding(batch)
glossary_block = get_glossary_instruction(batch, glossary, glossary_source, glossary_target)
objective = f"""<worker prompt below with {batch_json} and {glossary_block} substituted>"""
thread_id = start_task(
objective=objective,
model="smart",
mode="continue_then_receive",
name=f"batch-{batch_idx}",
group_id=task_group_id,
tools="file_only"
)
print(f"Spawned batch-{batch_idx}: {thread_id}")
c. The worker objective prompt (use EXACTLY as written, substitute values only):
"""
You are a translation worker. Translate the following text from {source_language} to {target_language}.
RULES:
- Translate ONLY the "text" field in each run. Keep "para_id" and "id" exactly as-is.
- Provide the translation as a JSON array with no explanation, no markdown, no commentary.
- Use the "full_paragraph" field for context but do NOT include it in your output.
- Preserve proper nouns, brand names, code, URLs, and measurement units unchanged.
{glossary_instruction}
INPUT:
{batch_json}
OUTPUT FORMAT (respond with ONLY this JSON, nothing else):
[{"para_id": , "runs": [{"id": , "text": ""}]}]
"""
d. Where is the output of get_glossary_instruction(), either an empty string or a GLOSSARY block.
e. Do NOT call get_task_group_result yet. Proceed immediately to Step 7 to load Phase 2 scripts while workers translate.
-
[Agent] Load Phase 2 scripts (reconstruction). Do this IMMEDIATELY after spawning, while workers are translating:
a. Use file_read to load scripts/reconstruct.py (handles both DOCX and PPTX reconstruction).
b. In a SINGLE run_python call, execute the Phase 2 script:
<content of reconstruct.py>
print("Phase 2 loaded: reconstruction functions ready.")
c. After execution: store_translation_result, check_translation_coverage, backfill_missing_translations, reconstruct_document, and all format-specific reconstruction functions persist in namespace alongside Phase 1 functions.
d. This step runs in parallel with workers, so users see zero additional latency.
e. NOW call get_task_group_result(group_id=task_group_id) to wait for all workers to complete.
-
[Agent] Collect results as they arrive:
CRITICAL CONTEXT MANAGEMENT: The purpose of store_translation_result() is to offload state from your context into _STATE (managed by code, not by you). Once you call it, the data is GONE from your responsibility. Do NOT summarize, count, comment on, or acknowledge the content of results. Do NOT repeat or echo the raw text in your response. Call store_translation_result and immediately move to the next event. When multiple results arrive simultaneously, batch ALL store_translation_result() calls into a SINGLE run_python call. Your context window is finite, so treat each processed result as garbage-collected.
-
[Agent] Check coverage and handle failures:
missing = check_translation_coverage()
-
[Agent] Reconstruct the document:
output_path = reconstruct_document(target_language, WORKSPACE_DIR)
Open the result for the user with open_in_session_tab.