import collections import six from autotranslate.compat import goslate, googleapiclient from django.conf import settings class BaseTranslatorService: """ Defines the base methods that should be implemented """ def translate_string(self, text, target_language, source_language='en'): """ Returns a single translated string literal for the target language. """ raise NotImplementedError('.translate_string() must be overridden.') def translate_strings(self, strings, target_language, source_language='en', optimized=True): """ Returns a iterator containing translated strings for the target language in the same order as in the strings. :return: if `optimized` is True returns a generator else an array """ raise NotImplementedError('.translate_strings() must be overridden.') class GoSlateTranslatorService(BaseTranslatorService): """ Uses the free web-based API for translating. https://bitbucket.org/zhuoqiang/goslate """ def __init__(self): assert goslate, '`GoSlateTranslatorService` requires `goslate` package' self.service = goslate.Goslate() def translate_string(self, text, target_language, source_language='en'): assert isinstance(text, six.string_types), '`text` should a string literal' return self.service.translate(text, target_language, source_language) def translate_strings(self, strings, target_language, source_language='en', optimized=True): assert isinstance(strings, collections.Iterable), '`strings` should a iterable containing string_types' translations = self.service.translate(strings, target_language, source_language) return translations if optimized else [_ for _ in translations] class GoogleAPITranslatorService(BaseTranslatorService): """ Uses the paid Google API for translating. https://github.com/google/google-api-python-client """ def __init__(self, max_segments=128): assert googleapiclient, '`GoogleAPITranslatorService` requires `google-api-python-client` package' self.developer_key = getattr(settings, 'GOOGLE_TRANSLATE_KEY', None) assert self.developer_key, ('`GOOGLE_TRANSLATE_KEY` is not configured, ' 'it is required by `GoogleAPITranslatorService`') from googleapiclient.discovery import build self.service = build('translate', 'v2', developerKey=self.developer_key) # the google translation API has a limit of max # 128 translations in a single request # and throws `Too many text segments Error` self.max_segments = max_segments self.translated_strings = [] def translate_string(self, text, target_language, source_language='en'): assert isinstance(text, six.string_types), '`text` should a string literal' response = self.service.translations() \ .list(source=source_language, target=target_language, q=[text]).execute() return response.get('translations').pop(0).get('translatedText') def translate_strings(self, strings, target_language, source_language='en', optimized=True): assert isinstance(strings, collections.MutableSequence), \ '`strings` should be a sequence containing string_types' assert not optimized, 'optimized=True is not supported in `GoogleAPITranslatorService`' if len(strings) == 0: return [] elif len(strings) <= self.max_segments: setattr(self, 'translated_strings', getattr(self, 'translated_strings', [])) response = self.service.translations() \ .list(source=source_language, target=target_language, q=strings).execute() self.translated_strings.extend([t.get('translatedText') for t in response.get('translations')]) return self.translated_strings else: self.translate_strings(strings[0:self.max_segments], target_language, source_language, optimized) _translated_strings = self.translate_strings(strings[self.max_segments:], target_language, source_language, optimized) # reset the property or it will grow with subsequent calls self.translated_strings = [] return _translated_strings