2010-09-11 03:01:20 +00:00
|
|
|
import htmlentitydefs
|
|
|
|
import re
|
|
|
|
|
|
|
|
from util import hook, http
|
|
|
|
|
|
|
|
########### from http://effbot.org/zone/re-sub.htm#unescape-html #############
|
|
|
|
|
|
|
|
|
|
|
|
def unescape(text):
|
|
|
|
def fixup(m):
|
|
|
|
text = m.group(0)
|
|
|
|
if text[:2] == "&#":
|
|
|
|
# character reference
|
|
|
|
try:
|
|
|
|
if text[:3] == "&#x":
|
|
|
|
return unichr(int(text[3:-1], 16))
|
|
|
|
else:
|
|
|
|
return unichr(int(text[2:-1]))
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
# named entity
|
|
|
|
try:
|
|
|
|
text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
|
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
return text # leave as is
|
|
|
|
|
|
|
|
return re.sub("&#?\w+;", fixup, text)
|
|
|
|
|
|
|
|
##############################################################################
|
|
|
|
|
|
|
|
|
|
|
|
def goog_trans(text, slang, tlang):
|
|
|
|
url = 'http://ajax.googleapis.com/ajax/services/language/translate?v=1.0'
|
|
|
|
parsed = http.get_json(url, q=text, langpair=(slang + '|' + tlang))
|
|
|
|
if not 200 <= parsed['responseStatus'] < 300:
|
|
|
|
raise IOError('error with the translation server: %d: %s' % (
|
2010-09-11 03:08:35 +00:00
|
|
|
parsed['responseStatus'], parsed['responseDetails']))
|
2010-09-11 03:01:20 +00:00
|
|
|
if not slang:
|
|
|
|
return unescape('(%(detectedSourceLanguage)s) %(translatedText)s' %
|
|
|
|
(parsed['responseData']))
|
|
|
|
return unescape(parsed['responseData']['translatedText'])
|
|
|
|
|
|
|
|
|
|
|
|
def match_language(fragment):
|
|
|
|
fragment = fragment.lower()
|
|
|
|
for short, _ in lang_pairs:
|
2010-09-11 04:18:26 +00:00
|
|
|
if fragment in short.lower().split():
|
2010-09-11 03:01:20 +00:00
|
|
|
return short.split()[0]
|
|
|
|
|
|
|
|
for short, full in lang_pairs:
|
|
|
|
if fragment in full.lower():
|
|
|
|
return short.split()[0]
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
@hook.command
|
|
|
|
def translate(inp):
|
|
|
|
'.translate [source language [target language]] <sentence> -- translates' \
|
|
|
|
' <sentence> from source language (default autodetect) to target' \
|
|
|
|
' language (default English) using Google Translate'
|
|
|
|
|
|
|
|
args = inp.split(' ', 2)
|
|
|
|
|
2010-09-11 03:08:35 +00:00
|
|
|
try:
|
|
|
|
if len(args) >= 2:
|
|
|
|
sl = match_language(args[0])
|
|
|
|
if not sl:
|
|
|
|
return goog_trans(inp, '', 'en')
|
|
|
|
if len(args) >= 3:
|
|
|
|
tl = match_language(args[1])
|
|
|
|
if not tl:
|
|
|
|
if sl == 'en':
|
|
|
|
return 'unable to determine desired target language'
|
|
|
|
return goog_trans(args[1] + ' ' + args[2], sl, 'en')
|
|
|
|
return goog_trans(args[2], sl, tl)
|
|
|
|
return goog_trans(inp, '', 'en')
|
|
|
|
except IOError, e:
|
|
|
|
return e
|
2010-09-11 03:01:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
languages = 'ja fr de ko ru zh'.split()
|
|
|
|
language_pairs = zip(languages[:-1], languages[1:])
|
|
|
|
|
|
|
|
|
|
|
|
def babel_gen(inp):
|
|
|
|
for language in languages:
|
|
|
|
inp = inp.encode('utf8')
|
|
|
|
trans = goog_trans(inp, 'en', language).encode('utf8')
|
|
|
|
inp = goog_trans(trans, language, 'en')
|
|
|
|
yield language, trans, inp
|
|
|
|
|
|
|
|
|
|
|
|
@hook.command
|
|
|
|
def babel(inp):
|
|
|
|
".babel <sentence> -- translates <sentence> through multiple languages"
|
|
|
|
|
|
|
|
try:
|
|
|
|
return list(babel_gen(inp))[-1][2]
|
|
|
|
except IOError, e:
|
|
|
|
return e
|
|
|
|
|
|
|
|
|
|
|
|
@hook.command
|
|
|
|
def babelext(inp):
|
|
|
|
".babelext <sentence> -- like .babel, but with more detailed output"
|
|
|
|
|
|
|
|
try:
|
|
|
|
babels = list(babel_gen(inp))
|
|
|
|
except IOError, e:
|
|
|
|
return e
|
|
|
|
|
|
|
|
out = u''
|
|
|
|
for lang, trans, text in babels:
|
|
|
|
out += '%s:"%s", ' % (lang, text.decode('utf8'))
|
|
|
|
|
|
|
|
out += 'en:"' + babels[-1][2].decode('utf8') + '"'
|
|
|
|
|
|
|
|
if len(out) > 300:
|
|
|
|
out = out[:150] + ' ... ' + out[-150:]
|
|
|
|
|
|
|
|
return out
|
|
|
|
|
|
|
|
|
|
|
|
lang_pairs = [
|
|
|
|
("no", "Norwegian"),
|
|
|
|
("it", "Italian"),
|
|
|
|
("ht", "Haitian Creole"),
|
|
|
|
("af", "Afrikaans"),
|
|
|
|
("sq", "Albanian"),
|
|
|
|
("ar", "Arabic"),
|
|
|
|
("hy", "Armenian"),
|
|
|
|
("az", "Azerbaijani"),
|
|
|
|
("eu", "Basque"),
|
|
|
|
("be", "Belarusian"),
|
|
|
|
("bg", "Bulgarian"),
|
|
|
|
("ca", "Catalan"),
|
2010-09-11 04:18:26 +00:00
|
|
|
("zh-CN zh", "Chinese"),
|
2010-09-11 03:01:20 +00:00
|
|
|
("hr", "Croatian"),
|
|
|
|
("cs", "Czech"),
|
|
|
|
("da", "Danish"),
|
|
|
|
("nl", "Dutch"),
|
|
|
|
("en", "English"),
|
|
|
|
("et", "Estonian"),
|
|
|
|
("tl", "Filipino"),
|
|
|
|
("fi", "Finnish"),
|
|
|
|
("fr", "French"),
|
|
|
|
("gl", "Galician"),
|
|
|
|
("ka", "Georgian"),
|
|
|
|
("de", "German"),
|
|
|
|
("el", "Greek"),
|
|
|
|
("ht", "Haitian Creole"),
|
|
|
|
("iw", "Hebrew"),
|
|
|
|
("hi", "Hindi"),
|
|
|
|
("hu", "Hungarian"),
|
|
|
|
("is", "Icelandic"),
|
|
|
|
("id", "Indonesian"),
|
|
|
|
("ga", "Irish"),
|
|
|
|
("it", "Italian"),
|
2010-09-11 04:18:26 +00:00
|
|
|
("ja jp jpn", "Japanese"),
|
2010-09-11 03:01:20 +00:00
|
|
|
("ko", "Korean"),
|
|
|
|
("lv", "Latvian"),
|
|
|
|
("lt", "Lithuanian"),
|
|
|
|
("mk", "Macedonian"),
|
|
|
|
("ms", "Malay"),
|
|
|
|
("mt", "Maltese"),
|
|
|
|
("no", "Norwegian"),
|
|
|
|
("fa", "Persian"),
|
|
|
|
("pl", "Polish"),
|
|
|
|
("pt", "Portuguese"),
|
|
|
|
("ro", "Romanian"),
|
|
|
|
("ru", "Russian"),
|
|
|
|
("sr", "Serbian"),
|
|
|
|
("sk", "Slovak"),
|
|
|
|
("sl", "Slovenian"),
|
|
|
|
("es", "Spanish"),
|
|
|
|
("sw", "Swahili"),
|
|
|
|
("sv", "Swedish"),
|
|
|
|
("th", "Thai"),
|
|
|
|
("tr", "Turkish"),
|
|
|
|
("uk", "Ukrainian"),
|
|
|
|
("ur", "Urdu"),
|
|
|
|
("vi", "Vietnamese"),
|
|
|
|
("cy", "Welsh"),
|
|
|
|
("yi", "Yiddish")
|
|
|
|
]
|