SuperAPI AI Directory

deepl

Writing & research

View repository

Updated 10-16 04:19

About this skill

DeepL Translation Skill

Translates texts, documents, and XLIFF files via the DeepL API.

Configuration

Required:

  • DEEPL_API_KEY - DeepL API key

Optional:

  • DEEPL_TARGET_LANG - Default target language (default: DE)

Available Commands

Command Description
/deepl translate "<text>" Translate text
/deepl file <path> Translate document
/deepl xliff <path> Translate XLIFF file

Common Options

  • --to <LANG> - Target language (e.g. EN, DE, FR)
  • --from <LANG> - Source language (otherwise auto-detect)

API Configuration

API Key Validation

Check before every API call:

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

Determine API Endpoint

DeepL Free keys end with :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

Determine Target Language

TARGET_LANG="${DEEPL_TARGET_LANG:-DE}"
# Kann mit --to überschrieben werden

/deepl translate

Translates free text.

Syntax

/deepl translate "<text>" [--to LANG] [--from LANG]

Examples

/deepl translate "Hello, how are you?"
/deepl translate "Guten Morgen" --to EN
/deepl translate "Bonjour" --from FR --to DE

Instructions

  1. Parse parameters:

    • Extract text from quotation marks
    • --to and --from process flags
  2. Execute API call:

# 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"

Error Handling

HTTP Code Meaning Action
403 Invalid API key Check key
429 Rate limit Wait 1s, retry
456 Quota exceeded Check DeepL account

/deepl file

Translates documents (DeepL-native formats).

Supported Formats

Format Extension
Microsoft Word .docx
Microsoft PowerPoint .pptx
PDF .pdf (Pro only)
HTML .html, .htm
Plain Text .txt

Syntax

/deepl file <path> [--to LANG] [--from LANG] [--output <path>]

Examples

/deepl file README.txt --to EN
/deepl file document.docx --to FR --output document_fr.docx

Instructions

  1. Check file:
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
  1. Upload document:
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)"
  1. Check status (polling):
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
  1. Download document:
# 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"

/deepl xliff

Translates XLIFF files (TYPO3, Symfony, etc.).

Syntax

/deepl xliff <path> [--to LANG] [--force] [--dry-run] [--output <path>]

Options

Option Description
--force Recreate all translations
--dry-run Only show what would be translated
--output <path> Write to new file

Examples

/deepl xliff locallang.xlf --to DE
/deepl xliff locallang.xlf --force --to FR
/deepl xliff locallang.xlf --dry-run

Instructions

  1. Read and validate XLIFF file:
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
  1. Extract trans-units that need translation:
# 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
  1. Collect source texts:
# 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"
  1. Batch translation via API:
# 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
  1. With --dry-run: Only display:
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
  1. Update XLIFF file:

Since XML manipulation in Bash is complex, use Python if available:

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 for pure Bash (simpler variant with 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
  1. Output result:
echo "✅ XLIFF aktualisiert: $OUTPUT_PATH"
echo "   Übersetzt: ${#TRANSLATIONS[@]} Einheiten"

Error Handling

HTTP Status Codes

Code Meaning Response
200 Success Continue
400 Bad Request Check parameters
403 Forbidden API key invalid
404 Not Found Check endpoint
413 Payload too large Text/file too large
429 Too Many Requests Wait 1s, max 3 retries
456 Quota exceeded Check DeepL account
5xx Server Error Retry with backoff

Retry logic

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
}

Validation

Always check before API calls:

  1. DEEPL_API_KEY set?
  2. File exists? (for file/xliff)
  3. File format supported?
  4. Target language valid?

Valid language codes

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