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

Update translation #2731

Merged
merged 5 commits into from
Nov 14, 2016
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 0 additions & 2 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,6 @@ Running System Tests
`docs <https://cloud.google.com/storage/docs/authentication#generating-a-private-key>`__
for more details. In order for Logging system tests to work, the Service Account
will also have to be made a project Owner. This can be changed under "IAM & Admin".
- ``GOOGLE_CLOUD_TESTS_API_KEY``: The API key for your project with
the Google Translate API (and others) enabled.

- Examples of these can be found in ``system_tests/local_test_setup.sample``. We
recommend copying this to ``system_tests/local_test_setup``, editing the
Expand Down
1 change: 0 additions & 1 deletion system_tests/local_test_setup.sample
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export GOOGLE_APPLICATION_CREDENTIALS="app_credentials.json.sample"
export GOOGLE_CLOUD_TESTING_REMOTE="upstream"
export GOOGLE_CLOUD_TESTING_BRANCH="master"
export GOOGLE_CLOUD_TESTS_API_KEY="abcd1234"
12 changes: 3 additions & 9 deletions system_tests/translate.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,11 @@
# limitations under the License.


import os

import unittest

from google.cloud import translate


ENV_VAR = 'GOOGLE_CLOUD_TESTS_API_KEY'


class Config(object):
"""Run-time configuration to be modified at set-up.

Expand All @@ -33,8 +28,7 @@ class Config(object):


def setUpModule():
api_key = os.getenv(ENV_VAR)
Config.CLIENT = translate.Client(api_key=api_key)
Config.CLIENT = translate.Client()


class TestTranslate(unittest.TestCase):
Expand All @@ -61,8 +55,8 @@ def test_detect_language(self):
def test_translate(self):
values = ['hvala ti', 'dankon',
'Me llamo Jeff', 'My name is Jeff']
translations = Config.CLIENT.translate(values,
target_language='de')
translations = Config.CLIENT.translate(
values, target_language='de', model='nmt')
self.assertEqual(len(values), len(translations))

self.assertEqual(
Expand Down
59 changes: 40 additions & 19 deletions translate/google/cloud/translate/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,47 @@
"""Client for interacting with the Google Cloud Translate API."""


import httplib2
import six

from google.cloud._helpers import _to_bytes
from google.cloud.client import Client as BaseClient
from google.cloud.translate.connection import Connection


ENGLISH_ISO_639 = 'en'
"""ISO 639-1 language code for English."""


class Client(object):
class Client(BaseClient):
"""Client to bundle configuration needed for API requests.

:type target_language: str
:param target_language: (Optional) The target language used for
translations and language names. (Defaults to
:data:`ENGLISH_ISO_639`.)

:type api_key: str
:param api_key: The key used to send with requests as a query
parameter.
:param api_key: (Optional) The key used to send with requests as a
query parameter.

:type credentials: :class:`oauth2client.client.OAuth2Credentials`
:param credentials: (Optional) The OAuth2 Credentials to use for the
connection owned by this client. If not passed (and
if no ``http`` object is passed), falls back to the
default inferred from the environment.

:type http: :class:`httplib2.Http` or class that defines ``request()``.
:param http: (Optional) HTTP object to make requests. If not
passed, an :class:`httplib.Http` object is created.

:type target_language: str
:param target_language: (Optional) The target language used for
translations and language names. (Defaults to
:data:`ENGLISH_ISO_639`.)
"""

def __init__(self, api_key, http=None, target_language=ENGLISH_ISO_639):
_connection_class = Connection

def __init__(self, target_language=ENGLISH_ISO_639, api_key=None,
credentials=None, http=None):
self.api_key = api_key
if http is None:
http = httplib2.Http()
self._connection = Connection(http=http)
self.target_language = target_language
super(Client, self).__init__(credentials=credentials, http=http)

This comment was marked as spam.

This comment was marked as spam.


def get_languages(self, target_language=None):
"""Get list of supported languages for translation.
Expand All @@ -70,7 +77,9 @@ def get_languages(self, target_language=None):
dictionary will also contain the name of each supported
language (localized to the target language).
"""
query_params = {'key': self.api_key}
query_params = {}
if self.api_key is not None:
query_params['key'] = self.api_key
if target_language is None:
target_language = self.target_language
if target_language is not None:
Expand Down Expand Up @@ -114,7 +123,9 @@ def detect_language(self, values):
single_value = True
values = [values]

query_params = [('key', self.api_key)]
query_params = []
if self.api_key is not None:
query_params.append(('key', self.api_key))
query_params.extend(('q', _to_bytes(value, 'utf-8'))
for value in values)
response = self._connection.api_request(
Expand Down Expand Up @@ -146,7 +157,8 @@ def detect_language(self, values):
return detections

def translate(self, values, target_language=None, format_=None,
source_language=None, customization_ids=()):
source_language=None, customization_ids=(),
model=None):
"""Translate a string or list of strings.

See: https://cloud.google.com/translate/v2/\
Expand All @@ -173,7 +185,11 @@ def translate(self, values, target_language=None, format_=None,
for translation. Sets the ``cid`` parameter
in the query.

:rtype: str or list list
:type model: str
:param model: (Optional) The model used to translate the text. The
only accepted values are ``base`` and ``nmt``.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


:rtype: str or list
:returns: A list of dictionaries for each queried value. Each
dictionary typically contains three keys (though not
all will be present in all cases)
Expand All @@ -183,10 +199,11 @@ def translate(self, values, target_language=None, format_=None,
* ``translatedText``: The translation of the text into the
target language.
* ``input``: The corresponding input value.
* ``model``: The model used to translate the text.

If only a single value is passed, then only a single
dictionary will be returned.
:raises: :class:`ValueError <exceptions.ValueError>` if the number of
:raises: :class:`~exceptions.ValueError` if the number of
values and translations differ.
"""
single_value = False
Expand All @@ -199,14 +216,18 @@ def translate(self, values, target_language=None, format_=None,
if isinstance(customization_ids, six.string_types):
customization_ids = [customization_ids]

query_params = [('key', self.api_key), ('target', target_language)]
query_params = [('target', target_language)]
if self.api_key is not None:
query_params.append(('key', self.api_key))
query_params.extend(('q', _to_bytes(value, 'utf-8'))
for value in values)
query_params.extend(('cid', cid) for cid in customization_ids)
if format_ is not None:
query_params.append(('format', format_))
if source_language is not None:
query_params.append(('source', source_language))
if model is not None:
query_params.append(('model', model))

response = self._connection.api_request(
method='GET', path='', query_params=query_params)
Expand Down
5 changes: 4 additions & 1 deletion translate/google/cloud/translate/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
class Connection(_http.JSONConnection):
"""A connection to Google Cloud Translate via the JSON REST API."""

API_BASE_URL = 'https://www.googleapis.com'
API_BASE_URL = 'https://translation.googleapis.com'
"""The base of the API call URL."""

API_VERSION = 'v2'
"""The version of the API, used in building the API call's URL."""

API_URL_TEMPLATE = '{api_base_url}/language/translate/{api_version}{path}'
"""A template for the URL of a particular API call."""

SCOPE = ('https://www.googleapis.com/auth/cloud-platform',)

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

"""The scopes required for authenticating."""
46 changes: 26 additions & 20 deletions translate/unit_tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,30 @@ def test_ctor(self):
from google.cloud.translate.client import ENGLISH_ISO_639

http = object()
client = self._make_one(self.KEY, http=http)
client = self._make_one(http=http)
self.assertIsInstance(client._connection, Connection)
self.assertIsNone(client._connection.credentials)
self.assertIs(client._connection.http, http)
self.assertIsNone(client.api_key)
self.assertEqual(client.target_language, ENGLISH_ISO_639)

def test_ctor_non_default(self):
from google.cloud.translate.connection import Connection

http = object()
target = 'es'
client = self._make_one(self.KEY, http=http, target_language=target)
client = self._make_one(
target_language=target, api_key=self.KEY, http=http)
self.assertIsInstance(client._connection, Connection)
self.assertIsNone(client._connection.credentials)
self.assertIs(client._connection.http, http)
self.assertEqual(self.KEY, client.api_key)
self.assertEqual(client.target_language, target)

def test_get_languages(self):
from google.cloud.translate.client import ENGLISH_ISO_639

client = self._make_one(self.KEY)
client = self._make_one(api_key=self.KEY, http=object())
supported = [
{'language': 'en', 'name': 'English'},
{'language': 'af', 'name': 'Afrikaans'},
Expand All @@ -77,7 +80,8 @@ def test_get_languages(self):
{'key': self.KEY, 'target': ENGLISH_ISO_639})

def test_get_languages_no_target(self):
client = self._make_one(self.KEY, target_language=None)
client = self._make_one(
target_language=None, http=object())
supported = [
{'language': 'en'},
{'language': 'af'},
Expand All @@ -96,12 +100,13 @@ def test_get_languages_no_target(self):
# Verify requested.
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(len(req), 3)
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/languages')
self.assertEqual(req['query_params'], {'key': self.KEY})
self.assertEqual(req['query_params'], {})

def test_get_languages_explicit_target(self):
client = self._make_one(self.KEY)
client = self._make_one(api_key=self.KEY, http=object())
target_language = 'en'
supported = [
{'language': 'en', 'name': 'Spanish'},
Expand All @@ -127,7 +132,7 @@ def test_get_languages_explicit_target(self):
{'key': self.KEY, 'target': target_language})

def test_detect_language_bad_result(self):
client = self._make_one(self.KEY)
client = self._make_one(api_key=self.KEY, http=object())
value = 'takoy'
conn = client._connection = _Connection({})

Expand All @@ -146,7 +151,7 @@ def test_detect_language_bad_result(self):
self.assertEqual(req['query_params'], query_params)

def test_detect_language_single_value(self):
client = self._make_one(self.KEY)
client = self._make_one(api_key=self.KEY, http=object())
value = 'takoy'
detection = {
'confidence': 1.0,
Expand Down Expand Up @@ -176,7 +181,7 @@ def test_detect_language_single_value(self):
self.assertEqual(req['query_params'], query_params)

def test_detect_language_multiple_values(self):
client = self._make_one(self.KEY)
client = self._make_one(http=object())
value1 = u'fa\xe7ade' # facade (with a cedilla)
detection1 = {
'confidence': 0.6166008,
Expand Down Expand Up @@ -210,14 +215,13 @@ def test_detect_language_multiple_values(self):
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/detect')
query_params = [
('key', self.KEY),
('q', value1.encode('utf-8')),
('q', value2.encode('utf-8')),
]
self.assertEqual(req['query_params'], query_params)

def test_detect_language_multiple_results(self):
client = self._make_one(self.KEY)
client = self._make_one(api_key=self.KEY, http=object())
value = 'soy'
detection1 = {
'confidence': 0.81496066,
Expand All @@ -242,7 +246,7 @@ def test_detect_language_multiple_results(self):
client.detect_language(value)

def test_translate_bad_result(self):
client = self._make_one(self.KEY)
client = self._make_one(api_key=self.KEY, http=object())
value = 'hvala ti'
conn = client._connection = _Connection({})

Expand All @@ -255,14 +259,14 @@ def test_translate_bad_result(self):
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '')
query_params = [
('key', self.KEY),
('target', 'en'),
('key', self.KEY),
('q', value.encode('utf-8')),
]
self.assertEqual(req['query_params'], query_params)

def test_translate_defaults(self):
client = self._make_one(self.KEY)
client = self._make_one(http=object())
value = 'hvala ti'
translation = {
'detectedSourceLanguage': 'hr',
Expand All @@ -285,14 +289,13 @@ def test_translate_defaults(self):
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '')
query_params = [
('key', self.KEY),
('target', 'en'),
('q', value.encode('utf-8')),
]
self.assertEqual(req['query_params'], query_params)

def test_translate_multiple(self):
client = self._make_one(self.KEY)
client = self._make_one(api_key=self.KEY, http=object())
value1 = 'hvala ti'
translation1 = {
'detectedSourceLanguage': 'hr',
Expand Down Expand Up @@ -321,15 +324,15 @@ def test_translate_multiple(self):
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '')
query_params = [
('key', self.KEY),
('target', 'en'),
('key', self.KEY),
('q', value1.encode('utf-8')),
('q', value2.encode('utf-8')),
]
self.assertEqual(req['query_params'], query_params)

def test_translate_explicit(self):
client = self._make_one(self.KEY)
client = self._make_one(api_key=self.KEY, http=object())
value = 'thank you'
target_language = 'eo'
source_language = 'en'
Expand All @@ -346,9 +349,11 @@ def test_translate_explicit(self):

cid = '123'
format_ = 'text'
model = 'nmt'
result = client.translate(value, target_language=target_language,
source_language=source_language,
format_=format_, customization_ids=cid)
format_=format_, customization_ids=cid,
model=model)
self.assertEqual(result, translation)

# Verify requested.
Expand All @@ -357,12 +362,13 @@ def test_translate_explicit(self):
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '')
query_params = [
('key', self.KEY),
('target', target_language),
('key', self.KEY),
('q', value.encode('utf-8')),
('cid', cid),
('format', format_),
('source', source_language),
('model', model),
]
self.assertEqual(req['query_params'], query_params)

Expand Down