deepl/SKILL.md
Übersetzt Texte, Dokumente und XLIFF-Dateien via DeepL API. Verwende für Übersetzungen mit /deepl translate, /deepl file oder /deepl xliff.
npx skillsauth add atxinsky/skills deeplInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Übersetzt Texte, Dokumente und XLIFF-Dateien via DeepL API.
Erforderlich:
DEEPL_API_KEY - DeepL API-SchlüsselOptional:
DEEPL_TARGET_LANG - Standard-Zielsprache (Default: DE)| Befehl | Beschreibung |
|--------|--------------|
| /deepl translate "<text>" | Text übersetzen |
| /deepl file <path> | Dokument übersetzen |
| /deepl xliff <path> | XLIFF-Datei übersetzen |
--to <LANG> - Zielsprache (z.B. EN, DE, FR)--from <LANG> - Quellsprache (sonst Auto-Detect)Vor jedem API-Call prüfen:
if [ -z "$DEEPL_API_KEY" ]; then
echo "❌ DEEPL_API_KEY nicht gesetzt"
echo ""
echo "Setup:"
echo " export DEEPL_API_KEY='your-api-key'"
echo ""
echo "API-Key erhältlich unter: https://www.deepl.com/pro-api"
exit 1
fi
DeepL Free Keys enden auf :fx:
if [[ "$DEEPL_API_KEY" == *":fx" ]]; then
DEEPL_API_URL="https://api-free.deepl.com/v2"
else
DEEPL_API_URL="https://api.deepl.com/v2"
fi
TARGET_LANG="${DEEPL_TARGET_LANG:-DE}"
# Kann mit --to überschrieben werden
Übersetzt freien Text.
/deepl translate "<text>" [--to LANG] [--from LANG]
/deepl translate "Hello, how are you?"
/deepl translate "Guten Morgen" --to EN
/deepl translate "Bonjour" --from FR --to DE
Parameter parsen:
--to und --from Flags verarbeitenAPI-Call ausführen:
# Variablen setzen
TEXT="{{user_text}}"
TARGET="${TARGET_LANG}" # aus --to oder Environment
SOURCE_PARAM=""
if [ -n "$SOURCE_LANG" ]; then
SOURCE_PARAM="--data-urlencode \"source_lang=$SOURCE_LANG\""
fi
# API-Call
RESPONSE=$(curl -s -X POST "$DEEPL_API_URL/translate" \
-H "Authorization: DeepL-Auth-Key $DEEPL_API_KEY" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "text=$TEXT" \
--data-urlencode "target_lang=$TARGET" \
$SOURCE_PARAM)
# Ergebnis extrahieren
TRANSLATED=$(echo "$RESPONSE" | jq -r '.translations[0].text // empty')
DETECTED_LANG=$(echo "$RESPONSE" | jq -r '.translations[0].detected_source_language // empty')
if [ -z "$TRANSLATED" ]; then
ERROR=$(echo "$RESPONSE" | jq -r '.message // "Unbekannter Fehler"')
echo "❌ Übersetzung fehlgeschlagen: $ERROR"
exit 1
fi
echo "📝 Original ($DETECTED_LANG): $TEXT"
echo "✅ Übersetzung ($TARGET): $TRANSLATED"
| HTTP Code | Bedeutung | Aktion | |-----------|-----------|--------| | 403 | Ungültiger API-Key | Key prüfen | | 429 | Rate Limit | 1s warten, retry | | 456 | Quota überschritten | DeepL-Konto prüfen |
Übersetzt Dokumente (DeepL-native Formate).
| Format | Extension | |--------|-----------| | Microsoft Word | .docx | | Microsoft PowerPoint | .pptx | | PDF | .pdf (nur Pro) | | HTML | .html, .htm | | Plain Text | .txt |
/deepl file <path> [--to LANG] [--from LANG] [--output <path>]
/deepl file README.txt --to EN
/deepl file document.docx --to FR --output document_fr.docx
FILE_PATH="{{user_path}}"
if [ ! -f "$FILE_PATH" ]; then
echo "❌ Datei nicht gefunden: $FILE_PATH"
exit 1
fi
# Extension prüfen
EXT="${FILE_PATH##*.}"
case "$EXT" in
docx|pptx|pdf|html|htm|txt) ;;
md)
# Markdown als txt behandeln
EXT="txt"
;;
*)
echo "❌ Format nicht unterstützt: .$EXT"
echo "Unterstützt: docx, pptx, pdf, html, txt"
exit 1
;;
esac
UPLOAD_RESPONSE=$(curl -s -X POST "$DEEPL_API_URL/document" \
-H "Authorization: DeepL-Auth-Key $DEEPL_API_KEY" \
-F "file=@$FILE_PATH" \
-F "target_lang=$TARGET_LANG")
DOC_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.document_id // empty')
DOC_KEY=$(echo "$UPLOAD_RESPONSE" | jq -r '.document_key // empty')
if [ -z "$DOC_ID" ]; then
ERROR=$(echo "$UPLOAD_RESPONSE" | jq -r '.message // "Upload fehlgeschlagen"')
echo "❌ $ERROR"
exit 1
fi
echo "📤 Dokument hochgeladen (ID: $DOC_ID)"
echo "⏳ Übersetze..."
while true; do
STATUS_RESPONSE=$(curl -s -X POST "$DEEPL_API_URL/document/$DOC_ID" \
-H "Authorization: DeepL-Auth-Key $DEEPL_API_KEY" \
-d "document_key=$DOC_KEY")
STATUS=$(echo "$STATUS_RESPONSE" | jq -r '.status')
case "$STATUS" in
"done")
echo "✅ Übersetzung fertig"
break
;;
"error")
ERROR=$(echo "$STATUS_RESPONSE" | jq -r '.message')
echo "❌ Fehler: $ERROR"
exit 1
;;
"translating"|"queued")
sleep 2
;;
esac
done
# Output-Pfad bestimmen
if [ -z "$OUTPUT_PATH" ]; then
BASENAME="${FILE_PATH%.*}"
OUTPUT_PATH="${BASENAME}_${TARGET_LANG}.${EXT}"
fi
curl -s -X POST "$DEEPL_API_URL/document/$DOC_ID/result" \
-H "Authorization: DeepL-Auth-Key $DEEPL_API_KEY" \
-d "document_key=$DOC_KEY" \
-o "$OUTPUT_PATH"
echo "📥 Gespeichert: $OUTPUT_PATH"
Übersetzt XLIFF-Dateien (TYPO3, Symfony, etc.).
/deepl xliff <path> [--to LANG] [--force] [--dry-run] [--output <path>]
| Option | Beschreibung |
|--------|--------------|
| --force | Alle Übersetzungen neu erstellen |
| --dry-run | Nur zeigen was übersetzt würde |
| --output <path> | In neue Datei schreiben |
/deepl xliff locallang.xlf --to DE
/deepl xliff locallang.xlf --force --to FR
/deepl xliff locallang.xlf --dry-run
XLIFF_PATH="{{user_path}}"
if [ ! -f "$XLIFF_PATH" ]; then
echo "❌ Datei nicht gefunden: $XLIFF_PATH"
exit 1
fi
# XML validieren
if ! xmllint --noout "$XLIFF_PATH" 2>/dev/null; then
echo "❌ Ungültiges XML in: $XLIFF_PATH"
exit 1
fi
# XLIFF 1.2: <trans-unit> mit leerem/fehlendem <target>
# XLIFF 2.0: <unit>/<segment> mit leerem/fehlendem <target>
# Für XLIFF 1.2:
UNITS_TO_TRANSLATE=$(xmllint --xpath "//trans-unit[not(target) or target='']" "$XLIFF_PATH" 2>/dev/null)
# Bei --force: alle Units
if [ "$FORCE" = "true" ]; then
UNITS_TO_TRANSLATE=$(xmllint --xpath "//trans-unit" "$XLIFF_PATH" 2>/dev/null)
fi
# Alle source-Texte extrahieren
SOURCES=$(xmllint --xpath "//trans-unit/source/text()" "$XLIFF_PATH" 2>/dev/null)
# Als Array für Batch-Übersetzung
readarray -t SOURCE_ARRAY <<< "$SOURCES"
# DeepL unterstützt mehrere Texte in einem Request
# Baue JSON-Array für text Parameter
TRANSLATIONS=()
for SOURCE in "${SOURCE_ARRAY[@]}"; do
RESPONSE=$(curl -s -X POST "$DEEPL_API_URL/translate" \
-H "Authorization: DeepL-Auth-Key $DEEPL_API_KEY" \
--data-urlencode "text=$SOURCE" \
--data-urlencode "target_lang=$TARGET_LANG")
TRANSLATED=$(echo "$RESPONSE" | jq -r '.translations[0].text')
TRANSLATIONS+=("$TRANSLATED")
done
if [ "$DRY_RUN" = "true" ]; then
echo "📋 Würde übersetzen:"
echo ""
for i in "${!SOURCE_ARRAY[@]}"; do
echo " Source: ${SOURCE_ARRAY[$i]}"
echo " Target: ${TRANSLATIONS[$i]}"
echo ""
done
echo "Gesamt: ${#SOURCE_ARRAY[@]} Einheiten"
exit 0
fi
Da XML-Manipulation in Bash komplex ist, verwende Python wenn verfügbar:
import xml.etree.ElementTree as ET
tree = ET.parse(xliff_path)
root = tree.getroot()
# Namespace handling für XLIFF
ns = {'xliff': 'urn:oasis:names:tc:xliff:document:1.2'}
for i, unit in enumerate(root.findall('.//xliff:trans-unit', ns)):
target = unit.find('xliff:target', ns)
if target is None:
target = ET.SubElement(unit, 'target')
if force or not target.text:
target.text = translations[i]
tree.write(output_path, encoding='utf-8', xml_declaration=True)
Fallback für reines Bash (einfachere Variante mit sed):
# Backup erstellen
cp "$XLIFF_PATH" "${XLIFF_PATH}.bak"
# Für jede Übersetzung
for i in "${!SOURCE_ARRAY[@]}"; do
SOURCE="${SOURCE_ARRAY[$i]}"
TARGET="${TRANSLATIONS[$i]}"
# Escape für sed
SOURCE_ESC=$(printf '%s\n' "$SOURCE" | sed 's/[[\.*^$()+?{|]/\\&/g')
TARGET_ESC=$(printf '%s\n' "$TARGET" | sed 's/[&/\]/\\&/g')
# Leeres target füllen
sed -i '' "s|<source>$SOURCE_ESC</source>\s*<target></target>|<source>$SOURCE_ESC</source><target>$TARGET_ESC</target>|g" "$XLIFF_PATH"
# Fehlendes target einfügen
sed -i '' "s|<source>$SOURCE_ESC</source>\s*</trans-unit>|<source>$SOURCE_ESC</source><target>$TARGET_ESC</target></trans-unit>|g" "$XLIFF_PATH"
done
echo "✅ XLIFF aktualisiert: $OUTPUT_PATH"
echo " Übersetzt: ${#TRANSLATIONS[@]} Einheiten"
| Code | Bedeutung | Reaktion | |------|-----------|----------| | 200 | Erfolg | Weiter | | 400 | Bad Request | Parameter prüfen | | 403 | Forbidden | API-Key ungültig | | 404 | Not Found | Endpunkt prüfen | | 413 | Payload too large | Text/Datei zu groß | | 429 | Too Many Requests | 1s warten, max 3 Retries | | 456 | Quota exceeded | DeepL-Konto prüfen | | 5xx | Server Error | Retry mit Backoff |
deepl_request() {
local max_retries=3
local retry_count=0
local wait_time=1
while [ $retry_count -lt $max_retries ]; do
RESPONSE=$(curl -s -w "\n%{http_code}" "$@")
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
BODY=$(echo "$RESPONSE" | sed '$d')
case "$HTTP_CODE" in
200) echo "$BODY"; return 0 ;;
429|5*)
retry_count=$((retry_count + 1))
echo "⏳ Retry $retry_count/$max_retries in ${wait_time}s..." >&2
sleep $wait_time
wait_time=$((wait_time * 2))
;;
403)
echo "❌ API-Key ungültig. Bitte prüfen:" >&2
echo " export DEEPL_API_KEY='your-key'" >&2
return 1
;;
456)
echo "❌ DeepL-Quota überschritten." >&2
echo " Prüfe dein Konto: https://www.deepl.com/pro-account" >&2
return 1
;;
*)
echo "❌ API-Fehler ($HTTP_CODE): $BODY" >&2
return 1
;;
esac
done
echo "❌ Max Retries erreicht" >&2
return 1
}
Vor API-Calls immer prüfen:
DEEPL_API_KEY gesetzt?BG, CS, DA, DE, EL, EN, EN-GB, EN-US, ES, ET, FI, FR, HU, ID, IT,
JA, KO, LT, LV, NB, NL, PL, PT, PT-BR, PT-PT, RO, RU, SK, SL, SV,
TR, UK, ZH, ZH-HANS, ZH-HANT
development
Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like "the xlsx in my downloads") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved.
testing
Use when creating new skills, editing existing skills, or verifying skills work before deployment
development
Use when you have a spec or requirements for a multi-step task, before touching code
documentation
Create detailed implementation plan with bite-sized tasks