Skip to content

Instantly share code, notes, and snippets.

@dmattera
Last active April 8, 2018 19:05
Show Gist options
  • Save dmattera/2c480e41c85802fb9af07aa7a7d3d4ca to your computer and use it in GitHub Desktop.
Save dmattera/2c480e41c85802fb9af07aa7a7d3d4ca to your computer and use it in GitHub Desktop.
Pythonista translator extension
import appex, console, clipboard
import html, requests
from urllib.parse import quote_plus, urlencode
# translate from the share menu in most apps # (e.g. WhatsApp - like so: https://imgur.com/a/6D5fi) or from the clipboard
# translations come from Google Translate API and require a free API key. https://cloud.google.com/translate/docs/quickstart
# Current working environment
# iOS 11.3
# WhatsApp 2.18.40
# Pythonista 3.2
TARGET_LANG = "en" # uses ISO-639-1 codes: https://cloud.google.com/translate/docs/languages
SOURCE_LANG = "auto" # uses ISO codes or 'auto' to utilize Google's auto-detect ability
API_KEY = 'YOUR_API_KEY'
def main():
if appex.is_running_extension():
text = get_appex_text() # returns a list of dictionaries or None if no text is present
else:
text = [{'orig_text': clipboard.get()}]
if text:
if SOURCE_LANG == "auto":
detected_text = detect(text)
translated_text = translate(text=detected_text)
else:
translated_text = translate(text=text)
display_text(translated_text)
else:
console.alert('Error', 'No text selected.','OK', hide_cancel_button=True)
def get_appex_text():
appex_text = appex.get_text()
if appex_text:
if '\n' in appex_text:
seperate_texts = appex_text.split('\n')
text = []
for t in seperate_texts:
if t != '':
text.append({'orig_text': t})
else:
text = [{'orig_text': appex_text}]
return text
else:
return None
def api_url(text, method):
url = "https://www.googleapis.com/language/translate/v2"
if method == "detect":
url += "/detect?key=" + API_KEY
for t in text:
payload = {'q': t['orig_text']}
encoded_payload = urlencode(payload, quote_via=quote_plus)
url += "&" + encoded_payload
elif method == "translate":
url += "?key=" + API_KEY
for t in text:
if SOURCE_LANG == "auto":
payload = {'q': t['orig_text'], 'source': t['language'], 'target': TARGET_LANG}
else:
payload = {'q': t['orig_text'], 'source': SOURCE_LANG, 'target': TARGET_LANG}
encoded_payload = urlencode(payload, quote_via=quote_plus)
url += '&' + encoded_payload
return url
def detect(text):
r = requests.get(url=api_url(text, method="detect"))
detections = r.json()['data']['detections']
detected_messages = []
for n, det in enumerate(detections):
temp = {}
temp['language'] = det[0]['language']
temp['confidence'] = det[0]['confidence']
temp['orig_text'] = text[n]['orig_text']
detected_messages.append(temp)
return detected_messages
def translate(text):
r = requests.get(url=api_url(text=text, method="translate"))
translations = r.json()['data']['translations']
translated_text = []
for n, t in enumerate(text):
temp = {}
temp['orig_text'] = t['orig_text']
temp['language'] = t['language']
temp['confidence'] = t['confidence']
temp['trans_text'] = html.unescape(s=translations[n]['translatedText'])
translated_text.append(temp)
return translated_text
def display_text(translated_text):
output = ''
for text in translated_text:
if SOURCE_LANG == "auto":
source_long_name = lookup_language(text['language'])
else:
source_long_name = lookup_language(SOURCE_LANG)
target_long_name = lookup_language(TARGET_LANG)
output += '[{}] {}\n[{}] {}\n\n'.format(source_long_name, text['orig_text'], target_long_name, text['trans_text'])
if len(translated_text) > 1:
title = "Translation"
else:
title = "Translations"
console.alert(title, str(output), 'OK', hide_cancel_button=True)
def lookup_language(code):
# returns full language name based on the given ISO-639-1 code
language = ""
lang_codes = {
'af': 'Afrikaans',
'sq': 'Albanian',
'am': 'Amharic',
'ar': 'Arabic',
'hy': 'Armenian',
'az': 'Azeerbaijani',
'eu': 'Basque',
'be': 'Belarusian',
'bn': 'Bengali',
'bs': 'Bosnian',
'bg': 'Bulgarian',
'ca': 'Catalan',
'ceb (ISO-639-2)': 'Cebuano',
'zh-CN (BCP-47)': 'Chinese (Simplified)',
'zh-TW (BCP-47)': 'Chinese (Traditional)',
'co': 'Corsican',
'hr': 'Croatian',
'cs': 'Czech',
'da': 'Danish',
'nl': 'Dutch',
'en': 'English',
'eo': 'Esperanto',
'et': 'Estonian',
'fi': 'Finnish',
'fr': 'French',
'fy': 'Frisian',
'gl': 'Galician',
'ka': 'Georgian',
'de': 'German',
'el': 'Greek',
'gu': 'Gujarati',
'ht': 'Haitian Creole',
'ha': 'Hausa',
'haw (ISO-639-2)': 'Hawaiian',
'iw': 'Hebrew',
'hi': 'Hindi',
'hmn (ISO-639-2)': 'Hmong',
'hu': 'Hungarian',
'is': 'Icelandic',
'ig': 'Igbo',
'id': 'Indonesian',
'ga': 'Irish',
'it': 'Italian',
'ja': 'Japanese',
'jw': 'Javanese',
'kn': 'Kannada',
'kk': 'Kazakh',
'km': 'Khmer',
'ko': 'Korean',
'ku': 'Kurdish',
'ky': 'Kyrgyz',
'lo': 'Lao',
'la': 'Latin',
'lv': 'Latvian',
'lt': 'Lithuanian',
'lb': 'Luxembourgish',
'mk': 'Macedonian',
'mg': 'Malagasy',
'ms': 'Malay',
'ml': 'Malayalam',
'mt': 'Maltese',
'mi': 'Maori',
'mr': 'Marathi',
'mn': 'Mongolian',
'my': 'Myanmar (Burmese)',
'ne': 'Nepali',
'no': 'Norwegian',
'ny': 'Nyanja (Chichewa)',
'ps': 'Pashto',
'fa': 'Persian',
'pl': 'Polish',
'pt': 'Portuguese (Portugal, Brazil)',
'pa': 'Punjabi',
'ro': 'Romanian',
'ru': 'Russian',
'sm': 'Samoan',
'gd': 'Scots Gaelic',
'sr': 'Serbian',
'st': 'Sesotho',
'sn': 'Shona',
'sd': 'Sindhi',
'si': 'Sinhala (Sinhalese)',
'sk': 'Slovak',
'sl': 'Slovenian',
'so': 'Somali',
'es': 'Spanish',
'su': 'Sundanese',
'sw': 'Swahili',
'sv': 'Swedish',
'tl': 'Tagalog (Filipino)',
'tg': 'Tajik',
'ta': 'Tamil',
'te': 'Telugu',
'th': 'Thai',
'tr': 'Turkish',
'uk': 'Ukrainian',
'ur': 'Urdu',
'uz': 'Uzbek',
'vi': 'Vietnamese',
'cy': 'Welsh',
'xh': 'Xhosa',
'yi': 'Yiddish',
'yo': 'Yoruba',
'zu': 'Zulu'
}
for key, value in lang_codes.items():
if code == key:
language = value
return language
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment