├── .gitignore ├── .mdlrc ├── Deepl-Translate.alfred5workflow ├── Deepl-Translate.alfredworkflow ├── Makefile ├── README.md ├── Screenshot-Chinese.png ├── Screenshot-Config.png ├── Screenshot-DLL.png ├── Screenshot-Result.png ├── Screenshot-Search.png ├── deepl-write.sh ├── deepl.bats ├── deepl.sh ├── icon.png ├── info4.plist └── info5.plist /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | info.plist 3 | 4 | -------------------------------------------------------------------------------- /.mdlrc: -------------------------------------------------------------------------------- 1 | rules "~MD013" 2 | -------------------------------------------------------------------------------- /Deepl-Translate.alfred5workflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderWillner/deepl-alfred-workflow2/88d8309732da17147f93ff26567e06142b70a3da/Deepl-Translate.alfred5workflow -------------------------------------------------------------------------------- /Deepl-Translate.alfredworkflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderWillner/deepl-alfred-workflow2/88d8309732da17147f93ff26567e06142b70a3da/Deepl-Translate.alfredworkflow -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=bash 2 | 3 | help: 4 | @echo "Some available commands:" 5 | @echo " * workflow : create workflow" 6 | @echo " * bats : run dynamic tests" 7 | @echo " * test : test shell scripts" 8 | @echo " * style : style shell scripts" 9 | @echo " * harden : harden shell scripts" 10 | @echo " * feedback : create a GitHub issue" 11 | 12 | workflow: dyntest workflow4 workflow5 13 | 14 | workflow4: 15 | @rm -f Deepl-Translate.alfredworkflow 16 | @cp info4.plist info.plist 17 | @zip Deepl-Translate.alfredworkflow icon.png info.plist deepl.sh 18 | @rm info.plist 19 | 20 | workflow5: 21 | @rm -f Deepl-Translate.alfred5workflow 22 | @cp info5.plist info.plist 23 | @zip Deepl-Translate.alfred5workflow icon.png info.plist deepl.sh 24 | @rm info.plist 25 | 26 | feedback: 27 | @open https://github.com/alexanderwillner/deepl-alfred-workflow2/issues 28 | 29 | bats: 30 | @echo "Running dynamic tests..." 31 | @type bats >/dev/null 2>&1 || (echo "Run 'brew install bats-core' first." >&2 ; exit 1) 32 | @bats deepl.bats 33 | 34 | dyntest: 35 | @DEEPL_KEY= ./deepl.sh -l EN "Guten Morgen." 2>&1|grep "Good morning" 36 | @./deepl.sh -l EN "Guten Morgen." 2>&1|grep "Good morning" 37 | 38 | test: 39 | @echo "Running first round of shell checks..." 40 | @type shellcheck >/dev/null 2>&1 || (echo "Run 'brew install shellcheck' first." >&2 ; exit 1) 41 | @shellcheck -x *.sh 42 | @echo "Running second round of shell checks..." 43 | @type shellharden >/dev/null 2>&1 || (echo "Run 'brew install shellharden' first." >&2 ; exit 1) 44 | @shellharden --check deepl.sh 45 | 46 | harden: 47 | @shellharden --replace deepl.sh 48 | 49 | style: 50 | @type shfmt >/dev/null 2>&1 || (echo "Run 'brew install shfmt' first." >&2 ; exit 1) 51 | @shfmt -i 2 -w -s *.sh 52 | 53 | .PHONY: workflow feedback bats test harden style 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alfred DeepL Translation Workflow 2 | 3 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/1772be5a3aa4423a8dd122877896ce36)](https://www.codacy.com/gh/AlexanderWillner/deepl-alfred-workflow2/dashboard?utm_source=github.com&utm_medium=referral&utm_content=AlexanderWillner/deepl-alfred-workflow2&utm_campaign=Badge_Grade) [![download](https://img.shields.io/github/downloads/AlexanderWillner/deepl-alfred-workflow2/total)](https://github.com/AlexanderWillner/deepl-alfred-workflow2/releases) 4 | 5 | ## Usage 6 | 7 | To activate this workflow use the default keyword ```dl```, enter the passage you wanna get translated and end the input with ```.``` (not needed if you've an API key). The source language will be inferred automatically and the target language can be configured. 8 | 9 | ![Search](Screenshot-Search.png) 10 | 11 | After 1-2 seconds you get the translation. This is just an example. 12 | 13 | ![Result](Screenshot-Result.png) 14 | 15 | Press ```↩``` to copy the result or ```⌘ + ↩``` to show result as big screen overlay. 16 | You can also translate any selected text within macOS by pressing ```⌃ + ⌥ + ⌘ + d```. 17 | 18 | Other languages are supported as well: 19 | 20 | ![Chinese](Screenshot-Chinese.png) 21 | 22 | To quickly change the target language, you can use the ```dll``` keyword: 23 | 24 | ![Result](Screenshot-DLL.png) 25 | 26 | ## Caveats 27 | 28 | Please note that the DeepL API is designed to translate up to 600 characters per minute and per customer only. This fact and generally some longer sentences might result in the message ```Error: Too many requests.``` (see #5). 29 | However, you can also get a (free or paid) [```API key```](https://www.deepl.com/pro-api) and configure it in the settings (see screenshot below). 30 | 31 | ## Installing the Workflow 32 | 33 | 1. Simply download the [last release](https://github.com/AlexanderWillner/deepl-alfred-workflow2/releases) 34 | 2. Unzip the file on your computer 35 | 3. Install `Deepl-Translate.alfredworkflow` by double-clicking the workflow file and clicking on "Import". 36 | 37 | You'll now see the workflow listed in the left sidebar of your Workflows preferences pane. 38 | 39 | Once imported, you may want to take a quick look at the workflow settings and setup what keyword you want to use. Further, you can change the target language in the settings as shown in this screenshot: 40 | 41 | ![Config](Screenshot-Config.png) 42 | 43 | ## Command Line 44 | 45 | ```shell 46 | $ # DEEPL_TARGET="FR" 47 | $ ./deepl.sh -l DE "This is just an example." 48 | { 49 | "items": [ 50 | { 51 | "uid": null, 52 | "arg": "Dies ist nur ein Beispiel.", 53 | "valid": "yes", 54 | "autocomplete": "autocomplete", 55 | "title": "Dies ist nur ein Beispiel." 56 | }, 57 | { 58 | "uid": null, 59 | "arg": "Das ist nur ein Beispiel.", 60 | "valid": "yes", 61 | "autocomplete": "autocomplete", 62 | "title": "Das ist nur ein Beispiel." 63 | }, 64 | { 65 | "uid": null, 66 | "arg": "Dies ist nur ein Beispiel dafür.", 67 | "valid": "yes", 68 | "autocomplete": "autocomplete", 69 | "title": "Dies ist nur ein Beispiel dafür." 70 | }, 71 | { 72 | "uid": null, 73 | "arg": "Dies ist nur ein exemplarisches Beispiel.", 74 | "valid": "yes", 75 | "autocomplete": "autocomplete", 76 | "title": "Dies ist nur ein exemplarisches Beispiel." 77 | } 78 | ] 79 | } 80 | ``` 81 | 82 | ## Important configuration variables 83 | 84 | * `DEEPL_KEY`: the DeepL API key 85 | * `DEEPL_PRO`: in case you have a professional DeepL account 86 | * `DEEPL_POSTFIX`: the character to the input should end with to mitigate #5 87 | * `DEEPL_TARGET`: the target language of the default `dl` keyword 88 | 89 | ## Builing the workflow 90 | 91 | To create a modified version of the workflow, edit the files and run ```make workflow``` to create an updated workflow. 92 | 93 | ## Disclaimer 94 | 95 | DeepL is a product from DeepL GmbH. More info: [deepl.com/publisher.html](https://www.deepl.com/publisher.html) 96 | 97 | This package has been heavily inspired by [m9dfukc's DeepL Alfred Workflow](https://github.com/m9dfukc/deepl-alfred-workflow). 98 | -------------------------------------------------------------------------------- /Screenshot-Chinese.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderWillner/deepl-alfred-workflow2/88d8309732da17147f93ff26567e06142b70a3da/Screenshot-Chinese.png -------------------------------------------------------------------------------- /Screenshot-Config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderWillner/deepl-alfred-workflow2/88d8309732da17147f93ff26567e06142b70a3da/Screenshot-Config.png -------------------------------------------------------------------------------- /Screenshot-DLL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderWillner/deepl-alfred-workflow2/88d8309732da17147f93ff26567e06142b70a3da/Screenshot-DLL.png -------------------------------------------------------------------------------- /Screenshot-Result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderWillner/deepl-alfred-workflow2/88d8309732da17147f93ff26567e06142b70a3da/Screenshot-Result.png -------------------------------------------------------------------------------- /Screenshot-Search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderWillner/deepl-alfred-workflow2/88d8309732da17147f93ff26567e06142b70a3da/Screenshot-Search.png -------------------------------------------------------------------------------- /deepl-write.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # setup ####################################################################### 4 | #set -o errexit -o pipefail -o noclobber -o nounset 5 | LANGUAGE="${DEEPL_TARGET:-EN}" 6 | LANGUAGE_SOURCE="${DEEPL_SOURCE:-auto}" 7 | LANGUAGE_PREFERRED="${DEEPL_PREFERRED:-[\"DE\",\"EN\"]}" 8 | KEY="${DEEPL_KEY:-}" 9 | PRO="${DEEPL_PRO:-}" 10 | # see https://developers.deepl.com/docs/api-reference/translate/openapi-spec-for-text-translation 11 | FORMALITY="${DEEPL_FORMALITY:-prefer_less}" 12 | POSTFIX="${DEEPL_POSTFIX:-.}" 13 | VERSION="2.1.0" 14 | PATH="$PATH:/usr/local/bin/" 15 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 16 | ############################################################################### 17 | 18 | # helper functions ############################################################ 19 | function printJson() { 20 | echo '{"items": [{"uid": null,"arg": "'"$1"'","valid": "yes","autocomplete": "autocomplete","title": "'"$1"'"}]}' 21 | } 22 | ############################################################################### 23 | 24 | # parameters ################################################################## 25 | POSITIONAL=() 26 | while [[ $# -gt 0 ]]; do 27 | key="$1" 28 | case "$key" in 29 | -l | --lang) 30 | LANGUAGE="$2" 31 | shift # past argument 32 | shift # past value 33 | ;; 34 | *) # unknown option 35 | POSITIONAL+=("$1") # save it in an array for later 36 | shift # past argument 37 | ;; 38 | esac 39 | done 40 | set -- "${POSITIONAL[@]:-}" # restore positional parameters 41 | ############################################################################### 42 | 43 | # help ######################################################################## 44 | if [ -z "$1" ]; then 45 | echo "Home made DeepL CLI (${VERSION}; https://github.com/AlexanderWillner/deepl-alfred-workflow2)" 46 | echo "" 47 | echo "SYNTAX : $0 [-l language] " >&2 48 | echo "Example: $0 -l EN \"This is just an example.\"" 49 | echo "" 50 | exit 1 51 | fi 52 | ############################################################################### 53 | 54 | # process query ############################################################### 55 | query="$1" 56 | # shellcheck disable=SC2001 57 | query="$(echo "$query" | sed 's/\"/\\\"/g')" 58 | # shellcheck disable=SC2001 59 | query="$(echo "$query" | sed "s/'/\\\'/g")" 60 | query="$(echo "$query" | iconv -f utf-8-mac -t utf-8 | xargs)" 61 | 62 | if [[ $KEY = "" ]] && [[ $query != *"$POSTFIX" ]]; then 63 | printJson "End query with $POSTFIX" 64 | exit 2 65 | fi 66 | ############################################################################### 67 | 68 | # prepare query ############################################################### 69 | # shellcheck disable=SC2001 70 | query="$(echo "$query" | sed "s/\\$POSTFIX$//")" 71 | if [ "$KEY" = "" ]; then 72 | FORM_PARAM='' 73 | else 74 | FORM_PARAM='"formality": "'"$FORMALITY"'", ' 75 | fi 76 | 77 | data='{"jsonrpc":"2.0","method": "LMT_handle_jobs","params":{"jobs":[{"kind":"default","sentences":[{"text":"'"$query"'","id":1,"prefix":""}],"raw_en_context_before":[],"raw_en_context_after":[],"preferred_num_beams":1,"write_variant_requests":["main","variants"],"style_variant":"business"}],"lang":{"target_lang":"'"${LANGUAGE:-EN}"'","preference":{"weight":{},"default":"default"},"source_lang_computed":"'"${LANGUAGE:-EN}"'"},"priority":1,"commonJobParams":{"quality":"normal","regionalVariant":"en-US","mode":"write","browserType":1,"textType":"plaintext","style_variant":"business"},"timestamp":1739745925254},"id":20270141}' 78 | HEADER=( 79 | --compressed 80 | -H 'authority: write-free.www.deepl.com' 81 | -H 'Origin: https://write-free.www.deepl.com' 82 | -H 'Referer: https://www.deepl.com/' 83 | -H 'Accept: */*' 84 | -H 'Content-Type: application/json' 85 | -H 'Accept-Language: en-us' 86 | -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Safari/605.1.15' 87 | ) 88 | ############################################################################### 89 | 90 | # query ####################################################################### 91 | if [ -n "$KEY" ]; then 92 | if [ "$PRO" = "1" ]; then 93 | url="https://api.deepl.com/v2/translate" 94 | else 95 | url="https://api-free.deepl.com/v2/translate" 96 | fi 97 | if [ ! -z "$DEEPL_HOST" ]; then 98 | url="$DEEPL_HOST/v2/translate" 99 | fi 100 | 101 | echo >&2 "curl -s -X POST '$url' -H 'Authorization: DeepL-Auth-Key $KEY' --data-urlencode 'text=$query' -d 'formality=$FORMALITY' -d 'target_lang=${LANGUAGE:-EN}'" 102 | result=$(curl -s -X POST "$url" -H "Authorization: DeepL-Auth-Key $KEY" --data-urlencode "text=$query" -d "formality=$FORMALITY" -d "target_lang=${LANGUAGE:-EN}") 103 | ret=$? 104 | if [[ "x$ret" != "x0" ]] || [[ "$result" == "" ]]; then 105 | echo >&2 "$ret: $result" 106 | http_code=$(curl -s -X POST "$url" -H "Authorization: DeepL-Auth-Key $KEY" --data-urlencode "text=$query" -d "target_lang=${LANGUAGE:-EN}" -d "formality=$FORMALITY" -w %{http_code} -o /dev/null) 107 | if [[ $http_code -eq 403 ]]; then 108 | printJson "Error: Invalid API key" 109 | exit 3 110 | fi 111 | if [[ $ret -eq 6 ]]; then 112 | printJson "Error: DNS resolution failed - no Internet connection?" 113 | exit 4 114 | fi 115 | printJson "Error Code $ret - HTTP Code $http_code" 116 | exit 5 117 | fi 118 | osascript -l JavaScript -e 'function run(argv) { 119 | const translations = JSON.parse(argv[0])["translations"].map(item => ({ 120 | title: item["text"], 121 | arg: item["text"] 122 | })) 123 | 124 | return JSON.stringify({ items: translations }, null, 2) 125 | }' "$result" || echo >&2 "ERROR w/ key: result '$result', query '$query'" 126 | else 127 | echo >&2 "curl -s 'https://write-free.www.deepl.com/jsonrpc' '${HEADER[@]}' --data-binary $'$data'" 128 | result=$(curl -s 'https://write-free.www.deepl.com/jsonrpc' "${HEADER[@]}" --data-binary $"$data") 129 | ret=$? 130 | if [[ "x$ret" != "x0" ]] || [[ "$result" == "" ]]; then 131 | echo >&2 "$ret: $result" 132 | http_code=$(curl -s 'https://write-free.www.deepl.com/jsonrpc' "${HEADER[@]}" --data-binary $"$data" -w %{http_code} -o /dev/null) 133 | if [[ $ret -eq 6 ]]; then 134 | printJson "Error: DNS resolution failed - no Internet connection?" 135 | exit 6 136 | fi 137 | printJson "Error Code $ret - HTTP Code $http_code" 138 | exit 7 139 | fi 140 | if [[ $result == *'"error":{"code":'* ]]; then 141 | message="$(osascript -l JavaScript -e 'function run(argv) { return JSON.parse(argv[0])["error"]["message"] }')" 142 | printJson "Error: $message" 143 | exit 8 144 | else 145 | osascript -l JavaScript -e 'function run(argv) { 146 | const translations = JSON.parse(argv[0])["result"]["translations"][0]["beams"].map(item => ({ 147 | title: item["sentences"], 148 | arg: item["sentences"] 149 | })) 150 | 151 | return JSON.stringify({ items: translations }, null, 2) 152 | }' "$result" || echo >&2 "ERROR w/o key: result '$result', query '$query'" 153 | fi 154 | fi 155 | ############################################################################### 156 | -------------------------------------------------------------------------------- /deepl.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | teardown() { 4 | sleep 1 5 | } 6 | 7 | @test "No parameters" { 8 | run ./deepl.sh 9 | [[ "$status" -eq 1 ]] 10 | } 11 | 12 | @test "Missing dot" { 13 | run ./deepl.sh "Vogel" 14 | [[ "$status" -eq 0 ]] 15 | [[ "$output" == *"End query with a dot"* ]] 16 | } 17 | 18 | @test "Single Word" { 19 | run ./deepl.sh -l EN "Vogel." 20 | [[ "$status" -eq 0 ]] 21 | [[ "$output" == *"bird"* ]] 22 | } 23 | 24 | @test "Trailing spaces" { 25 | run ./deepl.sh " Vogel. " 26 | [[ "$status" -eq 0 ]] 27 | [[ "$output" == *"bird"* ]] 28 | } 29 | 30 | @test "Sentence" { 31 | run ./deepl.sh -l DE "Translate from any language." 32 | [[ "$status" -eq 0 ]] 33 | [[ "$output" == *"aus jeder Sprache"* ]] 34 | } 35 | 36 | @test "Umlaut source" { 37 | run ./deepl.sh -l EN "Erdöl." 38 | [[ "$status" -eq 0 ]] 39 | [[ "$output" == *"oil"* ]] 40 | } 41 | 42 | @test "Umlaut destination" { 43 | run ./deepl.sh -l DE "Oil." 44 | [[ "$status" -eq 0 ]] 45 | [[ "$output" == *"öl"* ]] 46 | } 47 | 48 | @test "Quote source" { 49 | run ./deepl.sh -l DE "I'll." 50 | [[ "$status" -eq 0 ]] 51 | [[ "$output" == *"Ich werde"* ]] 52 | } 53 | 54 | @test "Quote destination" { 55 | run ./deepl.sh -l EN "Ich werde." 56 | [[ "$status" -eq 0 ]] 57 | [[ "$output" == *"I'll be"* ]] 58 | } 59 | 60 | @test "Double quote source" { 61 | run ./deepl.sh -l EN '"Apfel".' 62 | [[ "$status" -eq 0 ]] 63 | [[ "$output" == *'\"Apple\"'* ]] 64 | } 65 | 66 | #todo: fixme #6 67 | #@test "Spanisch" { 68 | # run ./deepl.sh -l EN "El tiempo es una ilusión." 69 | # [[ "$status" -eq 0 ]] 70 | # [[ "$output" == *'\"time\"'* ]] 71 | #} 72 | 73 | #todo: fixme #1 74 | #@test "Long sentences" { 75 | # run ./deepl.sh -l DE "He felt that his whole life was some kind of dream and he sometimes wondered whose it was and whether they were enjoying it." 76 | # [[ "$status" -eq 0 ]] 77 | # [[ "$output" == *'\"Leben\"'* ]] 78 | #} 79 | 80 | #todo: fixme #1 81 | #@test "Multi sentences" { 82 | # run ./deepl.sh -l DE "This planet has - or rather had - a problem, which was this: most of the people living on it were unhappy for pretty much of the time. Many solutions were suggested for this problem, but most of these were largely concerned with the movement of small green pieces of paper, which was odd because on the whole it wasn't the small green pieces of paper that were unhappy." 83 | # [[ "$status" -eq 0 ]] 84 | # [[ "$output" == *'\"unglücklich\"'* ]] 85 | #} 86 | 87 | -------------------------------------------------------------------------------- /deepl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # setup ####################################################################### 4 | #set -o errexit -o pipefail -o noclobber -o nounset 5 | LANGUAGE="${DEEPL_TARGET:-EN}" 6 | LANGUAGE_SOURCE="${DEEPL_SOURCE:-auto}" 7 | LANGUAGE_PREFERRED="${DEEPL_PREFERRED:-[\"DE\",\"EN\"]}" 8 | KEY="${DEEPL_KEY:-}" 9 | PRO="${DEEPL_PRO:-}" 10 | # see https://developers.deepl.com/docs/api-reference/translate/openapi-spec-for-text-translation 11 | FORMALITY="${DEEPL_FORMALITY:-prefer_less}" 12 | POSTFIX="${DEEPL_POSTFIX:-.}" 13 | VERSION="2.1.0" 14 | PATH="$PATH:/usr/local/bin/" 15 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 16 | ############################################################################### 17 | 18 | # helper functions ############################################################ 19 | function printJson() { 20 | echo '{"items": [{"uid": null,"arg": "'"$1"'","valid": "yes","autocomplete": "autocomplete","title": "'"$1"'"}]}' 21 | } 22 | ############################################################################### 23 | 24 | # parameters ################################################################## 25 | POSITIONAL=() 26 | while [[ $# -gt 0 ]]; do 27 | key="$1" 28 | case "$key" in 29 | -l | --lang) 30 | LANGUAGE="$2" 31 | shift # past argument 32 | shift # past value 33 | ;; 34 | *) # unknown option 35 | POSITIONAL+=("$1") # save it in an array for later 36 | shift # past argument 37 | ;; 38 | esac 39 | done 40 | set -- "${POSITIONAL[@]:-}" # restore positional parameters 41 | ############################################################################### 42 | 43 | # help ######################################################################## 44 | if [ -z "$1" ]; then 45 | echo "Home made DeepL CLI (${VERSION}; https://github.com/AlexanderWillner/deepl-alfred-workflow2)" 46 | echo "" 47 | echo "SYNTAX : $0 [-l language] " >&2 48 | echo "Example: $0 -l DE \"This is just an example.\"" 49 | echo "" 50 | exit 1 51 | fi 52 | ############################################################################### 53 | 54 | # process query ############################################################### 55 | query="$1" 56 | # shellcheck disable=SC2001 57 | query="$(echo "$query" | sed 's/\"/\\\"/g')" 58 | # shellcheck disable=SC2001 59 | query="$(echo "$query" | sed "s/'/\\\'/g")" 60 | query="$(echo "$query" | iconv -f utf-8-mac -t utf-8 | xargs)" 61 | 62 | if [[ $KEY = "" ]] && [[ $query != *"$POSTFIX" ]]; then 63 | printJson "End query with $POSTFIX" 64 | exit 2 65 | fi 66 | ############################################################################### 67 | 68 | # prepare query ############################################################### 69 | # shellcheck disable=SC2001 70 | query="$(echo "$query" | sed "s/\\$POSTFIX$//")" 71 | if [ "$KEY" = "" ]; then 72 | FORM_PARAM='' 73 | else 74 | FORM_PARAM='"formality": "'"$FORMALITY"'", ' 75 | fi 76 | data='{"jsonrpc":"2.0","method": "LMT_handle_jobs","params":{"commonJobParams": {'$FORM_PARAM'"browserType": 1, "mode": "translate", "textType": "plaintext"}, "jobs":[{"kind":"default","raw_en_sentence":"'"$query"'","preferred_num_beams":4,"raw_en_context_before":[],"raw_en_context_after":[],"quality":"fast"}],"lang":{"user_preferred_langs":'"${LANGUAGE_PREFERRED}"',"source_lang_user_selected":"'"${LANGUAGE_SOURCE}"'","target_lang":"'"${LANGUAGE:-EN}"'"},"priority":1,"timestamp":1557063997314},"id":79120002}' 77 | HEADER=( 78 | --compressed 79 | -H 'authority: www2.deepl.com' 80 | -H 'Origin: https://www.deepl.com' 81 | -H 'Referer: https://www.deepl.com/translator' 82 | -H 'Accept: */*' 83 | -H 'Content-Type: application/json' 84 | -H 'Accept-Language: en-us' 85 | -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Safari/605.1.15' 86 | ) 87 | ############################################################################### 88 | 89 | # query ####################################################################### 90 | if [ -n "$KEY" ]; then 91 | if [ "$PRO" = "1" ]; then 92 | url="https://api.deepl.com/v2/translate" 93 | else 94 | url="https://api-free.deepl.com/v2/translate" 95 | fi 96 | if [ ! -z "$DEEPL_HOST" ]; then 97 | url="$DEEPL_HOST/v2/translate" 98 | fi 99 | 100 | echo >&2 "curl -s -X POST '$url' -H 'Authorization: DeepL-Auth-Key $KEY' --data-urlencode 'text=$query' -d 'formality=$FORMALITY' -d 'target_lang=${LANGUAGE:-EN}'" 101 | result=$(curl -s -X POST "$url" -H "Authorization: DeepL-Auth-Key $KEY" --data-urlencode "text=$query" -d "formality=$FORMALITY" -d "target_lang=${LANGUAGE:-EN}") 102 | ret=$? 103 | if [[ "x$ret" != "x0" ]] || [[ "$result" == "" ]]; then 104 | echo >&2 "$ret: $result" 105 | http_code=$(curl -s -X POST "$url" -H "Authorization: DeepL-Auth-Key $KEY" --data-urlencode "text=$query" -d "target_lang=${LANGUAGE:-EN}" -d "formality=$FORMALITY" -w %{http_code} -o /dev/null) 106 | if [[ $http_code -eq 403 ]]; then 107 | printJson "Error: Invalid API key" 108 | exit 3 109 | fi 110 | if [[ $ret -eq 6 ]]; then 111 | printJson "Error: DNS resolution failed - no Internet connection?" 112 | exit 4 113 | fi 114 | printJson "Error Code $ret - HTTP Code $http_code" 115 | exit 5 116 | fi 117 | osascript -l JavaScript -e 'function run(argv) { 118 | const translations = JSON.parse(argv[0])["translations"].map(item => ({ 119 | title: item["text"], 120 | arg: item["text"] 121 | })) 122 | 123 | return JSON.stringify({ items: translations }, null, 2) 124 | }' "$result" || echo >&2 "ERROR w/ key: result '$result', query '$query'" 125 | else 126 | echo >&2 "curl -s 'https://www2.deepl.com/jsonrpc' '${HEADER[@]}' --data-binary $'$data'" 127 | result=$(curl -s 'https://www2.deepl.com/jsonrpc' "${HEADER[@]}" --data-binary $"$data") 128 | ret=$? 129 | if [[ "x$ret" != "x0" ]] || [[ "$result" == "" ]]; then 130 | echo >&2 "$ret: $result" 131 | http_code=$(curl -s 'https://www2.deepl.com/jsonrpc' "${HEADER[@]}" --data-binary $"$data" -w %{http_code} -o /dev/null) 132 | if [[ $ret -eq 6 ]]; then 133 | printJson "Error: DNS resolution failed - no Internet connection?" 134 | exit 6 135 | fi 136 | printJson "Error Code $ret - HTTP Code $http_code" 137 | exit 7 138 | fi 139 | if [[ $result == *'"error":{"code":'* ]]; then 140 | message="$(osascript -l JavaScript -e 'function run(argv) { return JSON.parse(argv[0])["error"]["message"] }')" 141 | printJson "Error: $message" 142 | exit 8 143 | else 144 | osascript -l JavaScript -e 'function run(argv) { 145 | const translations = JSON.parse(argv[0])["result"]["translations"][0]["beams"].map(item => ({ 146 | title: item["postprocessed_sentence"], 147 | arg: item["postprocessed_sentence"] 148 | })) 149 | 150 | return JSON.stringify({ items: translations }, null, 2) 151 | }' "$result" || echo >&2 "ERROR w/o key: result '$result', query '$query'" 152 | fi 153 | fi 154 | ############################################################################### 155 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexanderWillner/deepl-alfred-workflow2/88d8309732da17147f93ff26567e06142b70a3da/icon.png -------------------------------------------------------------------------------- /info4.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundleid 6 | ws.willner.alex.alfred.deepl 7 | category 8 | Productivity 9 | connections 10 | 11 | 5233F7C8-9221-45A4-BDE0-DE53175096E1 12 | 13 | 14 | destinationuid 15 | A222FB0A-D703-4C45-9CB0-4EDEA3399BEF 16 | modifiers 17 | 1048576 18 | modifiersubtext 19 | 20 | vitoclose 21 | 22 | 23 | 24 | destinationuid 25 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 26 | modifiers 27 | 0 28 | modifiersubtext 29 | 30 | vitoclose 31 | 32 | 33 | 34 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 35 | 36 | 37 | destinationuid 38 | D7D47F17-02DB-4A30-8F14-C03CBD051929 39 | modifiers 40 | 0 41 | modifiersubtext 42 | 43 | vitoclose 44 | 45 | 46 | 47 | 84FE56AF-330C-4BB8-85E6-34859AAB73A7 48 | 49 | 50 | destinationuid 51 | 91D16594-908E-4665-A005-0B715D96E5C2 52 | modifiers 53 | 0 54 | modifiersubtext 55 | 56 | vitoclose 57 | 58 | 59 | 60 | 91D16594-908E-4665-A005-0B715D96E5C2 61 | 62 | 63 | destinationuid 64 | A222FB0A-D703-4C45-9CB0-4EDEA3399BEF 65 | modifiers 66 | 1048576 67 | modifiersubtext 68 | 69 | vitoclose 70 | 71 | 72 | 73 | destinationuid 74 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 75 | modifiers 76 | 0 77 | modifiersubtext 78 | 79 | vitoclose 80 | 81 | 82 | 83 | AD7C89C1-0978-4469-B62F-245E595DE9BD 84 | 85 | 86 | destinationuid 87 | 91D16594-908E-4665-A005-0B715D96E5C2 88 | modifiers 89 | 0 90 | modifiersubtext 91 | 92 | vitoclose 93 | 94 | 95 | 96 | CAA19D9E-04B6-4AD4-A8DC-0B683215DD14 97 | 98 | 99 | destinationuid 100 | 5233F7C8-9221-45A4-BDE0-DE53175096E1 101 | modifiers 102 | 0 103 | modifiersubtext 104 | 105 | vitoclose 106 | 107 | 108 | 109 | 110 | createdby 111 | Alexander Willner 112 | description 113 | Translation using deepl.com 114 | disabled 115 | 116 | name 117 | Deepl-Translate 118 | objects 119 | 120 | 121 | config 122 | 123 | alignment 124 | 0 125 | backgroundcolor 126 | 127 | fadespeed 128 | 0 129 | fillmode 130 | 0 131 | font 132 | 133 | ignoredynamicplaceholders 134 | 135 | largetypetext 136 | {query} 137 | textcolor 138 | 139 | wrapat 140 | 50 141 | 142 | type 143 | alfred.workflow.output.largetype 144 | uid 145 | A222FB0A-D703-4C45-9CB0-4EDEA3399BEF 146 | version 147 | 3 148 | 149 | 150 | config 151 | 152 | alfredfiltersresults 153 | 154 | alfredfiltersresultsmatchmode 155 | 0 156 | argumenttreatemptyqueryasnil 157 | 158 | argumenttrimmode 159 | 0 160 | argumenttype 161 | 0 162 | escaping 163 | 102 164 | keyword 165 | dl-to-en 166 | queuedelaycustom 167 | 3 168 | queuedelayimmediatelyinitially 169 | 170 | queuedelaymode 171 | 1 172 | queuemode 173 | 1 174 | runningsubtext 175 | Translating to language "EN" using DeepL ... 176 | script 177 | ./deepl.sh -l "EN" "{query}" 178 | 179 | scriptargtype 180 | 0 181 | scriptfile 182 | deepl.sh 183 | subtext 184 | Translate to language "EN" using DeepL 185 | title 186 | DeepL Dictionary 187 | type 188 | 0 189 | withspace 190 | 191 | 192 | type 193 | alfred.workflow.input.scriptfilter 194 | uid 195 | 5233F7C8-9221-45A4-BDE0-DE53175096E1 196 | version 197 | 3 198 | 199 | 200 | config 201 | 202 | action 203 | 0 204 | argument 205 | 1 206 | focusedappvariable 207 | 208 | focusedappvariablename 209 | 210 | hotkey 211 | 14 212 | hotmod 213 | 1835008 214 | hotstring 215 | E 216 | leftcursor 217 | 218 | modsmode 219 | 0 220 | relatedAppsMode 221 | 0 222 | 223 | type 224 | alfred.workflow.trigger.hotkey 225 | uid 226 | CAA19D9E-04B6-4AD4-A8DC-0B683215DD14 227 | version 228 | 2 229 | 230 | 231 | config 232 | 233 | autopaste 234 | 235 | clipboardtext 236 | 237 | ignoredynamicplaceholders 238 | 239 | transient 240 | 241 | 242 | type 243 | alfred.workflow.output.clipboard 244 | uid 245 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 246 | version 247 | 3 248 | 249 | 250 | config 251 | 252 | lastpathcomponent 253 | 254 | onlyshowifquerypopulated 255 | 256 | removeextension 257 | 258 | text 259 | {query} 260 | title 261 | Copied to clipboard: 262 | 263 | type 264 | alfred.workflow.output.notification 265 | uid 266 | D7D47F17-02DB-4A30-8F14-C03CBD051929 267 | version 268 | 1 269 | 270 | 271 | config 272 | 273 | action 274 | 0 275 | argument 276 | 1 277 | focusedappvariable 278 | 279 | focusedappvariablename 280 | 281 | hotkey 282 | 2 283 | hotmod 284 | 1835008 285 | hotstring 286 | D 287 | leftcursor 288 | 289 | modsmode 290 | 0 291 | relatedAppsMode 292 | 0 293 | 294 | type 295 | alfred.workflow.trigger.hotkey 296 | uid 297 | 84FE56AF-330C-4BB8-85E6-34859AAB73A7 298 | version 299 | 2 300 | 301 | 302 | config 303 | 304 | alfredfiltersresults 305 | 306 | alfredfiltersresultsmatchmode 307 | 0 308 | argumenttreatemptyqueryasnil 309 | 310 | argumenttrimmode 311 | 0 312 | argumenttype 313 | 0 314 | escaping 315 | 102 316 | keyword 317 | dl-to-de 318 | queuedelaycustom 319 | 3 320 | queuedelayimmediatelyinitially 321 | 322 | queuedelaymode 323 | 1 324 | queuemode 325 | 1 326 | runningsubtext 327 | Translating to language "de" using DeepL ... 328 | script 329 | DEEPL_KEY="$DEEPL_KEY" ./deepl.sh -l "de" "{query}" 330 | scriptargtype 331 | 0 332 | scriptfile 333 | deepl.sh 334 | subtext 335 | Translate to language "de" using DeepL 336 | title 337 | DeepL Dictionary 338 | type 339 | 0 340 | withspace 341 | 342 | 343 | type 344 | alfred.workflow.input.scriptfilter 345 | uid 346 | 91D16594-908E-4665-A005-0B715D96E5C2 347 | version 348 | 3 349 | 350 | 351 | config 352 | 353 | concurrently 354 | 355 | escaping 356 | 0 357 | script 358 | # THESE VARIABLES MUST BE SET. SEE THE ONEUPDATER README FOR AN EXPLANATION OF EACH. 359 | readonly remote_info_plist='https://raw.githubusercontent.com/AlexanderWillner/deepl-alfred-workflow2/master/info.plist' 360 | readonly workflow_url='https://github.com/AlexanderWillner/deepl-alfred-workflow2/releases/latest/download/Deepl-Translate.alfredworkflow' 361 | readonly download_type='direct' 362 | readonly frequency_check='4' 363 | 364 | # FROM HERE ON, CODE SHOULD BE LEFT UNTOUCHED! 365 | function abort { 366 | echo "${1}" >&2 367 | exit 1 368 | } 369 | 370 | function url_exists { 371 | curl --silent --location --output /dev/null --fail --range 0-0 "${1}" 372 | } 373 | 374 | function notification { 375 | local -r notificator="$(find . -type d -name 'Notificator.app')" 376 | if [[ -n "${notificator}" ]]; then 377 | "${notificator}/Contents/Resources/Scripts/notificator" --message "${1}" --title "${alfred_workflow_name}" --subtitle 'A new version is available' 378 | return 379 | fi 380 | 381 | local -r terminal_notifier="$(find . -type f -name 'terminal-notifier')" 382 | if [[ -n "${terminal_notifier}" ]]; then 383 | "${terminal_notifier}" -title "${alfred_workflow_name}" -subtitle 'A new version is available' -message "${1}" 384 | return 385 | fi 386 | 387 | osascript -e "display notification \"${1}\" with title \"${alfred_workflow_name}\" subtitle \"A new version is available\"" 388 | } 389 | 390 | # Local sanity checks 391 | readonly local_info_plist='info.plist' 392 | readonly local_version="$(/usr/libexec/PlistBuddy -c 'print version' "${local_info_plist}")" 393 | 394 | [[ -n "${local_version}" ]] || abort 'You need to set a workflow version in the configuration sheet.' 395 | [[ "${download_type}" =~ ^(direct|page|github_release)$ ]] || abort "'download_type' (${download_type}) needs to be one of 'direct', 'page', or 'github_release'." 396 | [[ "${frequency_check}" =~ ^[0-9]+$ ]] || abort "'frequency_check' (${frequency_check}) needs to be a number." 397 | 398 | # Check for updates 399 | if [[ $(find "${local_info_plist}" -mtime +"${frequency_check}"d) ]]; then 400 | if ! url_exists "${remote_info_plist}"; then abort "'remote_info_plist' (${remote_info_plist}) appears to not be reachable."; fi # Remote sanity check 401 | 402 | readonly tmp_file="$(mktemp)" 403 | curl --silent --location --output "${tmp_file}" "${remote_info_plist}" 404 | readonly remote_version="$(/usr/libexec/PlistBuddy -c 'print version' "${tmp_file}")" 405 | 406 | if [[ "${local_version}" == "${remote_version}" ]]; then 407 | touch "${local_info_plist}" # Reset timer by touching local file 408 | exit 0 409 | fi 410 | 411 | if [[ "${download_type}" == 'page' ]]; then 412 | notification 'Opening download page…' 413 | open "${workflow_url}" 414 | exit 0 415 | fi 416 | 417 | download_url="$([[ "${download_type}" == 'github_release' ]] && curl --silent "https://api.github.com/repos/${workflow_url}/releases/latest" | grep 'browser_download_url' | head -1 | sed -E 's/.*browser_download_url": "(.*)"/\1/' || echo "${workflow_url}")" 418 | 419 | if url_exists "${download_url}"; then 420 | notification 'Downloading and installing…' 421 | curl --silent --location --output "${HOME}/Downloads/${alfred_workflow_name}.alfredworkflow" "${download_url}" 422 | open "${HOME}/Downloads/${alfred_workflow_name}.alfredworkflow" 423 | else 424 | abort "'workflow_url' (${download_url}) appears to not be reachable." 425 | fi 426 | fi 427 | scriptargtype 428 | 1 429 | scriptfile 430 | 431 | type 432 | 0 433 | 434 | type 435 | alfred.workflow.action.script 436 | uid 437 | 51AFB0E3-C777-4C5E-A677-3AF381488BCC 438 | version 439 | 2 440 | 441 | 442 | config 443 | 444 | alfredfiltersresults 445 | 446 | alfredfiltersresultsmatchmode 447 | 0 448 | argumenttreatemptyqueryasnil 449 | 450 | argumenttrimmode 451 | 0 452 | argumenttype 453 | 0 454 | escaping 455 | 102 456 | keyword 457 | dl 458 | queuedelaycustom 459 | 3 460 | queuedelayimmediatelyinitially 461 | 462 | queuedelaymode 463 | 1 464 | queuemode 465 | 1 466 | runningsubtext 467 | Translating to language "{var:DEEPL_TARGET}" using DeepL ... 468 | script 469 | DEEPL_KEY="$DEEPL_KEY" ./deepl.sh -l "$DEEPL_TARGET" "{query}" 470 | scriptargtype 471 | 0 472 | scriptfile 473 | deepl.sh 474 | subtext 475 | Translate to language "{var:DEEPL_TARGET}" using DeepL 476 | title 477 | DeepL Dictionary 478 | type 479 | 0 480 | withspace 481 | 482 | 483 | type 484 | alfred.workflow.input.scriptfilter 485 | uid 486 | AD7C89C1-0978-4469-B62F-245E595DE9BD 487 | version 488 | 3 489 | 490 | 491 | readme 492 | Using the keyword 'dl' will translate a sentence using deepl.com. You can configure the target language in the workflow configuration. 493 | To avoid the error message 'too many requests', please configure your free (or paid) DeepL API key. 494 | uidata 495 | 496 | 51AFB0E3-C777-4C5E-A677-3AF381488BCC 497 | 498 | colorindex 499 | 12 500 | note 501 | Automatically update workflow to latest version. 502 | xpos 503 | 400 504 | ypos 505 | 460 506 | 507 | 5233F7C8-9221-45A4-BDE0-DE53175096E1 508 | 509 | note 510 | Use this keyword to start the translation to an alternative hard coded language. 511 | xpos 512 | 210 513 | ypos 514 | 30 515 | 516 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 517 | 518 | note 519 | Copy translated text to the clipboard. 520 | xpos 521 | 490 522 | ypos 523 | 270 524 | 525 | 84FE56AF-330C-4BB8-85E6-34859AAB73A7 526 | 527 | note 528 | Send any selected text to the translator using this hotkey. 529 | xpos 530 | 40 531 | ypos 532 | 300 533 | 534 | 91D16594-908E-4665-A005-0B715D96E5C2 535 | 536 | note 537 | Use this keyword to start the translation to the configured language. 538 | xpos 539 | 220 540 | ypos 541 | 300 542 | 543 | A222FB0A-D703-4C45-9CB0-4EDEA3399BEF 544 | 545 | note 546 | Show translation as large text. 547 | xpos 548 | 480 549 | ypos 550 | 30 551 | 552 | AD7C89C1-0978-4469-B62F-245E595DE9BD 553 | 554 | note 555 | Use this keyword to start the translation to the configured language. 556 | xpos 557 | 40 558 | ypos 559 | 490 560 | 561 | CAA19D9E-04B6-4AD4-A8DC-0B683215DD14 562 | 563 | note 564 | Send any selected text to the translator using this hotkey. 565 | xpos 566 | 30 567 | ypos 568 | 40 569 | 570 | D7D47F17-02DB-4A30-8F14-C03CBD051929 571 | 572 | note 573 | Show a notifciation when text was copied to the clipboard. 574 | xpos 575 | 680 576 | ypos 577 | 270 578 | 579 | 580 | variables 581 | 582 | DEEPL_KEY 583 | 584 | DEEPL_POSTFIX 585 | . 586 | DEEPL_PREFERRED 587 | ["DE", "EN"] 588 | DEEPL_PRO 589 | 0 590 | DEEPL_SOURCE 591 | auto 592 | DEEPL_TARGET 593 | en 594 | 595 | version 596 | 1.11 597 | webaddress 598 | https://github.com/AlexanderWillner/deepl-alfred-workflow2 599 | 600 | 601 | -------------------------------------------------------------------------------- /info5.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bundleid 6 | ws.willner.alex.alfred.deepl 7 | category 8 | Productivity 9 | connections 10 | 11 | 5233F7C8-9221-45A4-BDE0-DE53175096E1 12 | 13 | 14 | destinationuid 15 | A222FB0A-D703-4C45-9CB0-4EDEA3399BEF 16 | modifiers 17 | 1048576 18 | modifiersubtext 19 | 20 | vitoclose 21 | 22 | 23 | 24 | destinationuid 25 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 26 | modifiers 27 | 0 28 | modifiersubtext 29 | 30 | vitoclose 31 | 32 | 33 | 34 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 35 | 36 | 37 | destinationuid 38 | D7D47F17-02DB-4A30-8F14-C03CBD051929 39 | modifiers 40 | 0 41 | modifiersubtext 42 | 43 | vitoclose 44 | 45 | 46 | 47 | 84FE56AF-330C-4BB8-85E6-34859AAB73A7 48 | 49 | 50 | destinationuid 51 | 91D16594-908E-4665-A005-0B715D96E5C2 52 | modifiers 53 | 0 54 | modifiersubtext 55 | 56 | vitoclose 57 | 58 | 59 | 60 | 91D16594-908E-4665-A005-0B715D96E5C2 61 | 62 | 63 | destinationuid 64 | A222FB0A-D703-4C45-9CB0-4EDEA3399BEF 65 | modifiers 66 | 1048576 67 | modifiersubtext 68 | 69 | vitoclose 70 | 71 | 72 | 73 | destinationuid 74 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 75 | modifiers 76 | 0 77 | modifiersubtext 78 | 79 | vitoclose 80 | 81 | 82 | 83 | AD7C89C1-0978-4469-B62F-245E595DE9BD 84 | 85 | 86 | destinationuid 87 | A222FB0A-D703-4C45-9CB0-4EDEA3399BEF 88 | modifiers 89 | 1048576 90 | modifiersubtext 91 | 92 | vitoclose 93 | 94 | 95 | 96 | destinationuid 97 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 98 | modifiers 99 | 0 100 | modifiersubtext 101 | 102 | vitoclose 103 | 104 | 105 | 106 | B8B726E5-529C-4F1A-902E-A66B1589922D 107 | 108 | 109 | destinationuid 110 | DA3683E7-31BA-4DE1-9796-2EAB971CA593 111 | modifiers 112 | 0 113 | modifiersubtext 114 | 115 | vitoclose 116 | 117 | 118 | 119 | CAA19D9E-04B6-4AD4-A8DC-0B683215DD14 120 | 121 | 122 | destinationuid 123 | 5233F7C8-9221-45A4-BDE0-DE53175096E1 124 | modifiers 125 | 0 126 | modifiersubtext 127 | 128 | vitoclose 129 | 130 | 131 | 132 | DA3683E7-31BA-4DE1-9796-2EAB971CA593 133 | 134 | 135 | destinationuid 136 | AD7C89C1-0978-4469-B62F-245E595DE9BD 137 | modifiers 138 | 0 139 | modifiersubtext 140 | 141 | vitoclose 142 | 143 | 144 | 145 | 146 | createdby 147 | Alexander Willner 148 | description 149 | Translation using deepl.com 150 | disabled 151 | 152 | name 153 | Deepl-Translate 154 | objects 155 | 156 | 157 | config 158 | 159 | alignment 160 | 0 161 | backgroundcolor 162 | 163 | fadespeed 164 | 0 165 | fillmode 166 | 0 167 | font 168 | 169 | ignoredynamicplaceholders 170 | 171 | largetypetext 172 | {query} 173 | textcolor 174 | 175 | wrapat 176 | 50 177 | 178 | type 179 | alfred.workflow.output.largetype 180 | uid 181 | A222FB0A-D703-4C45-9CB0-4EDEA3399BEF 182 | version 183 | 3 184 | 185 | 186 | config 187 | 188 | alfredfiltersresults 189 | 190 | alfredfiltersresultsmatchmode 191 | 0 192 | argumenttreatemptyqueryasnil 193 | 194 | argumenttrimmode 195 | 0 196 | argumenttype 197 | 0 198 | escaping 199 | 102 200 | keyword 201 | dl-to-en 202 | queuedelaycustom 203 | 3 204 | queuedelayimmediatelyinitially 205 | 206 | queuedelaymode 207 | 1 208 | queuemode 209 | 1 210 | runningsubtext 211 | Translating to language "EN" using DeepL ... 212 | script 213 | ./deepl.sh -l "EN" "{query}" 214 | 215 | scriptargtype 216 | 0 217 | scriptfile 218 | deepl.sh 219 | subtext 220 | Translate to language "EN" using DeepL 221 | title 222 | DeepL Dictionary 223 | type 224 | 0 225 | withspace 226 | 227 | 228 | type 229 | alfred.workflow.input.scriptfilter 230 | uid 231 | 5233F7C8-9221-45A4-BDE0-DE53175096E1 232 | version 233 | 3 234 | 235 | 236 | config 237 | 238 | action 239 | 0 240 | argument 241 | 1 242 | focusedappvariable 243 | 244 | focusedappvariablename 245 | 246 | hotkey 247 | 0 248 | hotmod 249 | 0 250 | leftcursor 251 | 252 | modsmode 253 | 0 254 | relatedAppsMode 255 | 0 256 | 257 | type 258 | alfred.workflow.trigger.hotkey 259 | uid 260 | CAA19D9E-04B6-4AD4-A8DC-0B683215DD14 261 | version 262 | 2 263 | 264 | 265 | config 266 | 267 | autopaste 268 | 269 | clipboardtext 270 | 271 | ignoredynamicplaceholders 272 | 273 | transient 274 | 275 | 276 | type 277 | alfred.workflow.output.clipboard 278 | uid 279 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 280 | version 281 | 3 282 | 283 | 284 | config 285 | 286 | lastpathcomponent 287 | 288 | onlyshowifquerypopulated 289 | 290 | removeextension 291 | 292 | text 293 | {query} 294 | title 295 | Copied to clipboard: 296 | 297 | type 298 | alfred.workflow.output.notification 299 | uid 300 | D7D47F17-02DB-4A30-8F14-C03CBD051929 301 | version 302 | 1 303 | 304 | 305 | config 306 | 307 | action 308 | 0 309 | argument 310 | 1 311 | focusedappvariable 312 | 313 | focusedappvariablename 314 | 315 | hotkey 316 | 0 317 | hotmod 318 | 0 319 | leftcursor 320 | 321 | modsmode 322 | 0 323 | relatedAppsMode 324 | 0 325 | 326 | type 327 | alfred.workflow.trigger.hotkey 328 | uid 329 | 84FE56AF-330C-4BB8-85E6-34859AAB73A7 330 | version 331 | 2 332 | 333 | 334 | config 335 | 336 | alfredfiltersresults 337 | 338 | alfredfiltersresultsmatchmode 339 | 0 340 | argumenttreatemptyqueryasnil 341 | 342 | argumenttrimmode 343 | 0 344 | argumenttype 345 | 0 346 | escaping 347 | 102 348 | keyword 349 | dl-to-de 350 | queuedelaycustom 351 | 3 352 | queuedelayimmediatelyinitially 353 | 354 | queuedelaymode 355 | 1 356 | queuemode 357 | 1 358 | runningsubtext 359 | Translating to language "de" using DeepL ... 360 | script 361 | DEEPL_KEY="$DEEPL_KEY" ./deepl.sh -l "de" "{query}" 362 | scriptargtype 363 | 0 364 | scriptfile 365 | deepl.sh 366 | subtext 367 | Translate to language "de" using DeepL 368 | title 369 | DeepL Dictionary 370 | type 371 | 0 372 | withspace 373 | 374 | 375 | type 376 | alfred.workflow.input.scriptfilter 377 | uid 378 | 91D16594-908E-4665-A005-0B715D96E5C2 379 | version 380 | 3 381 | 382 | 383 | config 384 | 385 | alfredfiltersresults 386 | 387 | alfredfiltersresultsmatchmode 388 | 2 389 | argumenttreatemptyqueryasnil 390 | 391 | argumenttrimmode 392 | 0 393 | argumenttype 394 | 1 395 | escaping 396 | 102 397 | keyword 398 | dll 399 | queuedelaycustom 400 | 3 401 | queuedelayimmediatelyinitially 402 | 403 | queuedelaymode 404 | 0 405 | queuemode 406 | 1 407 | runningsubtext 408 | 409 | script 410 | langs=(${(s/,/)${DEEPL_PREFERRED//[\[\]\" ]/}}) 411 | 412 | out='' 413 | for file in $langs; do 414 | out="${out:+$out,}{\"title\":\"$file\",\"arg\":\"$file\"}" 415 | done 416 | 417 | echo "{\"items\":[$out]}" 418 | scriptargtype 419 | 0 420 | scriptfile 421 | 422 | subtext 423 | 424 | title 425 | Select Language 426 | type 427 | 11 428 | withspace 429 | 430 | 431 | type 432 | alfred.workflow.input.scriptfilter 433 | uid 434 | B8B726E5-529C-4F1A-902E-A66B1589922D 435 | version 436 | 3 437 | 438 | 439 | config 440 | 441 | alfredfiltersresults 442 | 443 | alfredfiltersresultsmatchmode 444 | 0 445 | argumenttreatemptyqueryasnil 446 | 447 | argumenttrimmode 448 | 0 449 | argumenttype 450 | 0 451 | escaping 452 | 102 453 | keyword 454 | dl 455 | queuedelaycustom 456 | 3 457 | queuedelayimmediatelyinitially 458 | 459 | queuedelaymode 460 | 1 461 | queuemode 462 | 1 463 | runningsubtext 464 | Translating to language "{var:DEEPL_TARGET}" using DeepL ... 465 | script 466 | DEEPL_KEY="$DEEPL_KEY" ./deepl.sh -l "$DEEPL_TARGET" "{query}" 467 | scriptargtype 468 | 0 469 | scriptfile 470 | deepl.sh 471 | subtext 472 | Translate to language "{var:DEEPL_TARGET}" using DeepL 473 | title 474 | DeepL Dictionary 475 | type 476 | 0 477 | withspace 478 | 479 | 480 | type 481 | alfred.workflow.input.scriptfilter 482 | uid 483 | AD7C89C1-0978-4469-B62F-245E595DE9BD 484 | version 485 | 3 486 | 487 | 488 | config 489 | 490 | argument 491 | 492 | passthroughargument 493 | 494 | variables 495 | 496 | DEEPL_TARGET 497 | {query} 498 | 499 | 500 | type 501 | alfred.workflow.utility.argument 502 | uid 503 | DA3683E7-31BA-4DE1-9796-2EAB971CA593 504 | version 505 | 1 506 | 507 | 508 | readme 509 | Using the keyword 'dl' will translate a sentence using deepl.com. You can configure the target language in the workflow configuration. 510 | To avoid the error message 'too many requests', please configure your free (or paid) DeepL API key. 511 | uidata 512 | 513 | 5233F7C8-9221-45A4-BDE0-DE53175096E1 514 | 515 | note 516 | Use this keyword to start the translation to an alternative hard coded language. 517 | xpos 518 | 300 519 | ypos 520 | 30 521 | 522 | 61BF4F8C-DC18-4BB4-8DDD-A87C45C0F79E 523 | 524 | note 525 | Copy translated text to the clipboard. 526 | xpos 527 | 580 528 | ypos 529 | 270 530 | 531 | 84FE56AF-330C-4BB8-85E6-34859AAB73A7 532 | 533 | note 534 | Send any selected text to the translator using this hotkey. 535 | xpos 536 | 130 537 | ypos 538 | 300 539 | 540 | 91D16594-908E-4665-A005-0B715D96E5C2 541 | 542 | note 543 | Use this keyword to start the translation to the configured language. 544 | xpos 545 | 310 546 | ypos 547 | 300 548 | 549 | A222FB0A-D703-4C45-9CB0-4EDEA3399BEF 550 | 551 | note 552 | Show translation as large text. 553 | xpos 554 | 570 555 | ypos 556 | 30 557 | 558 | AD7C89C1-0978-4469-B62F-245E595DE9BD 559 | 560 | note 561 | Use this keyword to start the translation to the configured language. 562 | xpos 563 | 310 564 | ypos 565 | 500 566 | 567 | B8B726E5-529C-4F1A-902E-A66B1589922D 568 | 569 | xpos 570 | 30 571 | ypos 572 | 500 573 | 574 | CAA19D9E-04B6-4AD4-A8DC-0B683215DD14 575 | 576 | note 577 | Send any selected text to the translator using this hotkey. 578 | xpos 579 | 120 580 | ypos 581 | 40 582 | 583 | D7D47F17-02DB-4A30-8F14-C03CBD051929 584 | 585 | note 586 | Show a notifciation when text was copied to the clipboard. 587 | xpos 588 | 770 589 | ypos 590 | 270 591 | 592 | DA3683E7-31BA-4DE1-9796-2EAB971CA593 593 | 594 | xpos 595 | 205 596 | ypos 597 | 530 598 | 599 | 600 | userconfigurationconfig 601 | 602 | 603 | config 604 | 605 | default 606 | 607 | placeholder 608 | 609 | required 610 | 611 | trim 612 | 613 | 614 | description 615 | Get one at https://www.deepl.com/pro-api for higher limits. 616 | label 617 | API Key 618 | type 619 | textfield 620 | variable 621 | DEEPL_KEY 622 | 623 | 624 | config 625 | 626 | default 627 | 628 | required 629 | 630 | text 631 | You have a professional DeepL account 632 | 633 | description 634 | 635 | label 636 | DeepL Pro 637 | type 638 | checkbox 639 | variable 640 | DEEPL_PRO 641 | 642 | 643 | config 644 | 645 | default 646 | 647 | placeholder 648 | 649 | required 650 | 651 | trim 652 | 653 | 654 | description 655 | E.g., http://localhost:1188. 656 | label 657 | DeepLX Host 658 | type 659 | textfield 660 | variable 661 | DEEPL_HOST 662 | 663 | 664 | config 665 | 666 | default 667 | default 668 | pairs 669 | 670 | 671 | More Formal 672 | prefer_more 673 | 674 | 675 | Less Formal 676 | prefer_less 677 | 678 | 679 | Default 680 | default 681 | 682 | 683 | 684 | description 685 | Sets whether the translated text should lean towards formal or informal language. 686 | label 687 | Formality 688 | type 689 | popupbutton 690 | variable 691 | DEEPL_FORMALITY 692 | 693 | 694 | config 695 | 696 | default 697 | ["DE", "EN"] 698 | placeholder 699 | 700 | required 701 | 702 | trim 703 | 704 | 705 | description 706 | 707 | label 708 | Preferred Languages 709 | type 710 | textfield 711 | variable 712 | DEEPL_PREFERRED 713 | 714 | 715 | config 716 | 717 | default 718 | auto 719 | placeholder 720 | 721 | required 722 | 723 | trim 724 | 725 | 726 | description 727 | 728 | label 729 | Source Language 730 | type 731 | textfield 732 | variable 733 | DEEPL_SOURCE 734 | 735 | 736 | config 737 | 738 | default 739 | en 740 | placeholder 741 | 742 | required 743 | 744 | trim 745 | 746 | 747 | description 748 | 749 | label 750 | Target Language 751 | type 752 | textfield 753 | variable 754 | DEEPL_TARGET 755 | 756 | 757 | config 758 | 759 | default 760 | . 761 | placeholder 762 | 763 | required 764 | 765 | trim 766 | 767 | 768 | description 769 | Add this to the end of your query if you have not set an API key. 770 | label 771 | Query Postfix 772 | type 773 | textfield 774 | variable 775 | DEEPL_POSTFIX 776 | 777 | 778 | variablesdontexport 779 | 780 | version 781 | 2.2.2 782 | webaddress 783 | https://github.com/AlexanderWillner/deepl-alfred-workflow2 784 | 785 | 786 | --------------------------------------------------------------------------------