Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support baidu translator api #208

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Rosetta can be configured via the following parameters, to be defined in your pr
* ``ROSETTA_ENABLE_TRANSLATION_SUGGESTIONS``: Enable AJAX translation suggestions. Defaults to ``False``.
* ``YANDEX_TRANSLATE_KEY``: Translation suggestions from Yandex `Yandex.Translate API <http://api.yandex.com/translate/>`_. To use this service you must first `obtain an AppID key <http://api.yandex.com/key/form.xml?service=trnsl>`_, then specify the key here. Defaults to ``None``.
* ``AZURE_CLIENT_SECRET``: Translation suggestions using the Microsoft Azure Translator API. To use this service, you must first `register for the service <https://docs.microsoft.com/en-us/azure/cognitive-services/Translator/translator-text-how-to-signup>`_, and set ``AZURE_CLIENT_SECRET`` to either of the keys listed for your subscription. Defaults to ``None``.
* ``BAIDU_FANYI_APPID`` and ``BAIDU_FANYI_SECRETKEY``: Translation suggestions from `Baidu Translator API <https://fanyi-api.baidu.com/api/trans/product/prodinfo>`_. Defaults to ``None``.
* ``ROSETTA_MESSAGES_SOURCE_LANGUAGE_CODE`` and ``ROSETTA_MESSAGES_SOURCE_LANGUAGE_NAME``: Change these if the source language in your PO files isn't English. Default to ``'en'`` and ``'English'`` respectively.
* ``ROSETTA_WSGI_AUTO_RELOAD`` and ``ROSETTA_UWSGI_AUTO_RELOAD``: When running WSGI daemon mode, using ``mod_wsgi`` 2.0c5 or later, this setting controls whether the contents of the gettext catalog files should be automatically reloaded by the WSGI processes each time they are modified. For performance reasons, this setting should be disabled in production environments. Default to ``False``.
* ``ROSETTA_EXCLUDED_APPLICATIONS``: Exclude applications defined in this list from being translated. Defaults to ``()``.
Expand Down
6 changes: 5 additions & 1 deletion rosetta/conf/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
MESSAGES_PER_PAGE = getattr(settings, 'ROSETTA_MESSAGES_PER_PAGE', 10)


# Enable Google translation suggestions
# Enable translation suggestions by different translation services.
ENABLE_TRANSLATION_SUGGESTIONS = getattr(settings, 'ROSETTA_ENABLE_TRANSLATION_SUGGESTIONS', False)


Expand All @@ -15,6 +15,10 @@
# https://docs.microsoft.com/en-us/azure/cognitive-services/Translator/translator-text-how-to-signup
AZURE_CLIENT_SECRET = getattr(settings, 'AZURE_CLIENT_SECRET', None)

# Can be obtained for free here: https://fanyi-api.baidu.com
BAIDU_FANYI_APPID = getattr(settings, 'BAIDU_FANYI_APPID', None)
BAIDU_FANYI_SECRETKEY = getattr(settings, 'BAIDU_FANYI_SECRETKEY', None)

# Displays this language beside the original MSGID in the admin
MAIN_LANGUAGE = getattr(settings, 'ROSETTA_MAIN_LANGUAGE', None)

Expand Down
30 changes: 29 additions & 1 deletion rosetta/templates/rosetta/js/rosetta.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,35 @@ google.setOnLoadCallback(function() {
orig = unescape(orig).replace(/<br\s?\/?>/g,'\n').replace(/<code>/,'').replace(/<\/code>/g,'').replace(/&gt;/g,'>').replace(/&lt;/g,'<');
a.attr('class','suggesting').html('...');

$.getJSON("{% url 'rosetta.translate_text' %}", {
$.getJSON("{% url 'rosetta.translate_text_azure' %}", {
from: sourceLang,
to: destLang,
text: orig
},
function(data) {
if (data.success){
trans.val(unescape(data.translation).replace(/&#39;/g,'\'').replace(/&quot;/g,'"').replace(/%\s+(\([^\)]+\))\s*s/g,' %$1s '));
a.hide();
} else {
a.text(data.error);
}
}
);
});
{% elif rosetta_settings.BAIDU_FANYI_APPID %}
$('a.suggest').click(function(e){
e.preventDefault();
var a = $(this);
var str = a.html();
var orig = $('.original .message', a.parents('tr')).html();
var trans=$('textarea',a.parent());
var sourceLang = '{{ rosetta_settings.MESSAGES_SOURCE_LANGUAGE_CODE }}';
var destLang = '{{ rosetta_i18n_lang_code }}';

orig = unescape(orig).replace(/<br\s?\/?>/g,'\n').replace(/<code>/,'').replace(/<\/code>/g,'').replace(/&gt;/g,'>').replace(/&lt;/g,'<');
a.attr('class','suggesting').html('...');

$.getJSON("{% url 'rosetta.translate_text_baidu' %}", {
from: sourceLang,
to: destLang,
text: orig
Expand Down
2 changes: 1 addition & 1 deletion rosetta/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ def test_46_search_string_with_unicode_symbols(self):

@vcr.use_cassette('fixtures/vcr_cassettes/test_47_azure_ajax_translation.yaml', match_on=['method', 'scheme', 'host', 'port', 'path', 'query', 'raw_body'], record_mode='new_episodes')
def test_47_azure_ajax_translation(self):
r = self.client.get(reverse('rosetta.translate_text') + '?from=en&to=fr&text=hello%20world')
r = self.client.get(reverse('rosetta.translate_text_azure') + '?from=en&to=fr&text=hello%20world')
self.assertContains(r, '"Salut tout le monde"')

def test_48_requires_auth_not_respected_issue_203(self):
Expand Down
12 changes: 9 additions & 3 deletions rosetta/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,14 @@
name='rosetta-download-file',
),

url(r'^translate/$',
views.translate_text,
name='rosetta.translate_text',
url(r'^translate/azure/$',
views.translate_text_azure,
name='rosetta.translate_text_azure',
),

url(r'^translate/baidu/$',
views.translate_text_baidu,
name='rosetta.translate_text_baidu',
),

]
81 changes: 77 additions & 4 deletions rosetta/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import os.path
import re
import random
try:
# Python 3
from urllib.parse import urlencode
Expand Down Expand Up @@ -658,7 +659,7 @@ def get(self, request, *args, **kwargs):


@user_passes_test(lambda user: can_translate(user), rosetta_settings.LOGIN_URL)
def translate_text(request):
def translate_text_azure(request):

def translate(text, from_language, to_language, subscription_key):
"""
Expand Down Expand Up @@ -702,10 +703,8 @@ def translate(text, from_language, to_language, subscription_key):
data = {'success': True, 'translation': text}
else:
# run the translation:
AZURE_CLIENT_SECRET = getattr(settings, 'AZURE_CLIENT_SECRET', None)

try:
api_response = translate(text, language_from, language_to, AZURE_CLIENT_SECRET)
api_response = translate(text, language_from, language_to, rosetta_settings.AZURE_CLIENT_SECRET)

# result will be a dict if there is an error, e.g.
# {
Expand Down Expand Up @@ -749,5 +748,79 @@ def translate(text, from_language, to_language, subscription_key):
return JsonResponse(data)


BAIDU_LANGUAGE_MAP = {
'zh-hans': 'zh',
'zh-hant': 'cht',
'en': 'en',
'ja': 'jp',
'ko': 'kor',
'fr': 'fra',
'es': 'spa',
'ar': 'ara',
'bg': 'bul',
'et': 'est',
'da': 'dan',
'fi': 'fin',
'ro': 'rom',
'sl': 'slo',
'sv': 'swe',
'vi': 'vie',
}


def baidu_translate(appid, secretkey, q, fromlang, tolang):
baseurl = 'http://api.fanyi.baidu.com/api/trans/vip/translate'
salt = random.randint(32768, 65536)
sign = appid+q+str(salt)+secretkey
sign = hashlib.md5(sign.encode('utf-8')).hexdigest()
url = baseurl + '?' + urlencode({
'appid': appid,
'q': q,
'from': BAIDU_LANGUAGE_MAP.get(fromlang, fromlang),
'to': BAIDU_LANGUAGE_MAP.get(tolang, tolang),
'salt': str(salt),
'sign': sign
})
try:
print('url', url)
response = requests.get(url).text
except requests.exceptions.RequestException as err:
data = {
'success': False,
'error': "Error connecting to Baidu Translation Service: {0}".format(err)
}
else:
rsp = json.loads(response)
if 'error_code' in rsp:
data = {
'success': False,
'error': 'Baidu translation service error: {0} {1}'.format(
rsp['error_code'], rsp['error_msg']
)
}
elif not rsp.get('trans_result'):
data = {
'success': False,
'error': 'Baidu translation service don\'t return translation result'
}
else:
data = {
'success': True,
'translation': rsp['trans_result'][0]['dst']
}

return data


@user_passes_test(lambda user: can_translate(user), rosetta_settings.LOGIN_URL)
def translate_text_baidu(request):
appid = rosetta_settings.BAIDU_FANYI_APPID
secretkey = rosetta_settings.BAIDU_FANYI_SECRETKEY
if not appid or not secretkey:
return JsonResponse(data={'success': False, 'error': 'Baidu fanyi service is not configed'})
return JsonResponse(baidu_translate(
appid, secretkey, request.GET['text'], request.GET['from'], request.GET['to']))


def urlencode_safe(query):
return urlencode({k: force_bytes(v) for k, v in query.items()})