From 0ad1037c71f1d09bde39f78b896116b2305a9923 Mon Sep 17 00:00:00 2001
From: m3tm3re
Date: Tue, 10 Feb 2026 20:02:30 +0100
Subject: [PATCH] doc-translator
---
.gitignore | 10 ++
skills/doc-translator/SKILL.md | 252 +++++++++++++++++++++++++++++++++
2 files changed, 262 insertions(+)
create mode 100644 .gitignore
create mode 100644 skills/doc-translator/SKILL.md
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f394199
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+.todos/
+
+# Sidecar worktree state files
+.sidecar/
+.sidecar-agent
+.sidecar-task
+.sidecar-pr
+.sidecar-start.sh
+.sidecar-base
+.td-root
diff --git a/skills/doc-translator/SKILL.md b/skills/doc-translator/SKILL.md
new file mode 100644
index 0000000..47911dc
--- /dev/null
+++ b/skills/doc-translator/SKILL.md
@@ -0,0 +1,252 @@
+---
+name: doc-translator
+description: "Translates external documentation websites to specified language(s) and publishes to Outline wiki. Use when: (1) Translating SaaS/product documentation into German or Czech, (2) Publishing translated docs to Outline wiki, (3) Re-hosting external images to Outline. Triggers: 'translate docs', 'translate documentation', 'translate to German', 'translate to Czech', 'publish to wiki', 'doc translation', 'TEEM translation'."
+compatibility: opencode
+---
+
+# Doc Translator
+
+Translate external documentation websites to German (DE) and/or Czech (CZ), then publish to the company Outline wiki at `https://wiki.az-gruppe.com`. All images are re-hosted on Outline. UI terms use TEEM format.
+
+## Core Workflow
+
+### 1. Validate Input & Clarify
+
+Before starting, confirm:
+
+1. **URL accessibility** - Check with `curl -sI ` for HTTP 200
+2. **Target language(s)** - Always ask explicitly using the `question` tool:
+
+```
+question: "Which language(s) should I translate to?"
+options: ["German (DE)", "Czech (CZ)", "Both (DE + CZ)"]
+```
+
+3. **Scope** - If URL is an index page with multiple sub-pages, ask:
+
+```
+question: "This page links to multiple sub-pages. What should I translate?"
+options: ["This page only", "This page + all linked sub-pages", "Let me pick specific pages"]
+```
+
+4. **Target collection** - Use `Outline_list_collections` to show available collections, then ask which one to publish to
+
+If URL fetch fails, use `question` to ask for an alternative URL or manual content paste.
+
+### 2. Fetch & Parse Content
+
+Use the `webfetch` tool to retrieve page content:
+
+```
+webfetch(url="", format="markdown")
+```
+
+From the result:
+- Extract main content body (ignore navigation, footers, sidebars, cookie banners)
+- Preserve document structure (headings, lists, tables, code blocks)
+- Collect all image URLs into a list for Step 3
+- Note any embedded videos or interactive elements (these cannot be translated)
+
+For multi-page docs, repeat for each page.
+
+### 3. Download Images
+
+Download all images to a temporary directory:
+
+```bash
+mkdir -p /tmp/doc-images
+
+# For each image URL:
+curl -sL "IMAGE_URL" -o "/tmp/doc-images/$(basename IMAGE_URL)"
+```
+
+Track a mapping of: `original_url -> local_filename -> outline_attachment_url`
+
+If an image download fails, log it and continue. Use a placeholder in the final document:
+
+```markdown
+> **[Image unavailable]** Original: IMAGE_URL
+```
+
+### 4. Upload Images to Outline
+
+mcp-outline cannot create attachments. Use direct API calls via `bash`.
+
+**Required env:** `OUTLINE_API_KEY`
+
+For each downloaded image:
+
+```bash
+#!/usr/bin/env bash
+set -euo pipefail
+
+IMAGE_PATH="/tmp/doc-images/screenshot.png"
+IMAGE_NAME="$(basename "$IMAGE_PATH")"
+CONTENT_TYPE="image/png" # Detect from extension: png->image/png, jpg/jpeg->image/jpeg, gif->image/gif, svg->image/svg+xml, webp->image/webp
+
+# 1. Get file size (cross-platform)
+FILESIZE=$(stat -f%z "$IMAGE_PATH" 2>/dev/null || stat -c%s "$IMAGE_PATH")
+
+# 2. Create attachment record
+RESPONSE=$(curl -s -X POST "https://wiki.az-gruppe.com/api/attachments.create" \
+ -H "Authorization: Bearer $OUTLINE_API_KEY" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"name\": \"$IMAGE_NAME\",
+ \"contentType\": \"$CONTENT_TYPE\",
+ \"size\": $FILESIZE
+ }")
+
+# 3. Extract URLs from response
+UPLOAD_URL=$(echo "$RESPONSE" | jq -r '.data.uploadUrl')
+ATTACHMENT_URL=$(echo "$RESPONSE" | jq -r '.data.attachment.url')
+
+# 4. Check for errors
+if [ "$UPLOAD_URL" = "null" ] || [ -z "$UPLOAD_URL" ]; then
+ echo "ERROR: Failed to create attachment. Response: $RESPONSE" >&2
+ exit 1
+fi
+
+# 5. Upload binary to signed URL
+curl -s -X PUT "$UPLOAD_URL" \
+ -H "Content-Type: $CONTENT_TYPE" \
+ --data-binary "@$IMAGE_PATH"
+
+# 6. Output the attachment URL for use in markdown
+echo "$ATTACHMENT_URL"
+```
+
+Replace image references in the translated markdown:
+```markdown
+
+```
+
+**Content-Type detection by extension:**
+
+| Extension | Content-Type |
+|-----------|-------------|
+| `.png` | `image/png` |
+| `.jpg`, `.jpeg` | `image/jpeg` |
+| `.gif` | `image/gif` |
+| `.svg` | `image/svg+xml` |
+| `.webp` | `image/webp` |
+
+### 5. Translate with TEEM Format
+
+Translate the entire document into each target language. Apply TEEM format to UI elements.
+
+#### TEEM Rules
+
+**Format:** `**English UI Term** (Translation)`
+
+**Apply TEEM to:**
+- Button labels
+- Menu items and navigation tabs
+- Form field labels
+- Dialog/modal titles
+- Toolbar icons with text
+- Status messages from the app
+
+**Translate normally (no TEEM):**
+- Your own explanatory text
+- Document headings you create
+- General descriptions and conceptual explanations
+- Code blocks and technical identifiers
+
+#### German Examples
+
+```markdown
+Click **Settings** (Einstellungen) to open preferences.
+Navigate to **Dashboard** (Übersicht) > **Reports** (Berichte).
+Press the **Submit** (Absenden) button.
+In the **File** (Datei) menu, select **Export** (Exportieren).
+```
+
+#### Czech Examples
+
+```markdown
+Click **Settings** (Nastavení) to open preferences.
+Navigate to **Dashboard** (Přehled) > **Reports** (Sestavy).
+Press the **Submit** (Odeslat) button.
+In the **File** (Soubor) menu, select **Export** (Exportovat).
+```
+
+#### Ambiguous UI Terms
+
+If a UI term has multiple valid translations depending on context, use the `question` tool:
+
+```
+question: "The term 'Board' appears in the UI. Which translation fits this context?"
+options: ["Pinnwand (pinboard/bulletin)", "Tafel (whiteboard)", "Gremium (committee)"]
+```
+
+### 6. Publish to Outline
+
+Use mcp-outline tools to publish:
+
+1. **Find or create collection:**
+ - `Outline_list_collections` to find target collection
+ - `Outline_create_collection` if needed
+
+2. **Create document:**
+ - `Outline_create_document` with translated markdown content
+ - Set `publish: true` for immediate visibility
+ - Use `parent_document_id` if nesting under an existing doc
+
+3. **For multi-language:** Create one document per language, clearly titled:
+ - `[Product Name] - Dokumentation (DE)`
+ - `[Product Name] - Dokumentace (CZ)`
+
+## Error Handling
+
+| Issue | Action |
+|-------|--------|
+| URL fetch fails | Use `question` to ask for alternative URL or manual paste |
+| Image download fails | Continue with placeholder, note in completion report |
+| Outline API error (attachments) | Save markdown to `/tmp/doc-translator-backup-TIMESTAMP.md`, report error |
+| Outline API error (document) | Save markdown to `/tmp/doc-translator-backup-TIMESTAMP.md`, report error |
+| Ambiguous UI term | Use `question` to ask user for correct translation |
+| Large document (>5000 words) | Ask user if splitting into multiple docs is preferred |
+| Multi-page docs | Ask user about scope before proceeding |
+| Rate limiting | Wait and retry with exponential backoff |
+
+If Outline publish fails, always save the translated markdown locally as backup before reporting the error.
+
+## Completion Report
+
+After each translation, output:
+
+```
+Translation Complete
+
+Documents Created:
+- DE: [Document Title] - ID: [xxx] - URL: https://wiki.az-gruppe.com/doc/[slug]
+- CZ: [Document Title] - ID: [xxx] - URL: https://wiki.az-gruppe.com/doc/[slug]
+
+Images Processed: X of Y successfully uploaded
+
+Items Needing Review:
+- [Any sections with complex screenshots]
+- [Any failed image uploads with original URLs]
+- [Any unclear UI terms that were best-guessed]
+```
+
+## Language Codes
+
+| Code | Language | Native Name |
+|------|----------|-------------|
+| DE | German | Deutsch |
+| CZ | Czech | Čeština |
+
+## Environment Variables
+
+| Variable | Purpose |
+|----------|---------|
+| `OUTLINE_API_KEY` | Bearer token for wiki.az-gruppe.com API |
+
+## Integration with Other Skills
+
+| Need | Skill | When |
+|------|-------|------|
+| Wiki document management | outline | Managing existing translated docs |
+| Browser-based content extraction | playwright / dev-browser | When webfetch cannot access content (login-required pages) |