Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -610,9 +610,10 @@ Google Translate
#### Preview

Here's a snippet showing a simple usage example. The example shows how to detect the language of
some text and how to translate some text. The example assumes that the `GOOGLE_API_KEY` is set and
contains a valid API key. Alternatively, you can use the `apiKey(String)` setter in
`TranslateOptions.Builder` to set the API key. Complete source code can be found at
some text and how to translate some text. The example assumes that either default application
credentials or a valid api key are available. An api key stored in the `GOOGLE_API_KEY` environment
variable will be automatically detected. Alternatively, you can use the `apiKey(String)` setter in
`TranslateOptions.Builder`. Complete source code can be found at
[DetectLanguageAndTranslate.java](./google-cloud-examples/src/main/java/com/google/cloud/examples/translate/snippets/DetectLanguageAndTranslate.java).

```java
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public class DetectLanguageAndTranslate {

public static void main(String... args) {
// Create a service object
// API key is read from the GOOGLE_API_KEY environment variable
// Default application credentials or an API key from the GOOGLE_API_KEY environment variable
// are used to authenticate requests
Translate translate = TranslateOptions.getDefaultInstance().getService();

// Detect the language of some text
Expand Down
31 changes: 20 additions & 11 deletions google-cloud-translate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,25 @@ Getting Started
---------------
#### Prerequisites
For this tutorial, you need a [Google Developers Console](https://console.developers.google.com/)
project with "Translate API" enabled via the console's API Manager. You will also need a to enable
billing via the [Google Developers Console](https://console.developers.google.com/) project and to
retrieve an API key. See [Translate quickstart](https://cloud.google.com/translate/v2/quickstart)
for more details.
project with "Translate API" enabled via the console's API Manager. You also need to enable
billing via the [Google Developers Console](https://console.developers.google.com/).

Finally, you must set up the local development environment by
[installing the Google Cloud SDK](https://cloud.google.com/sdk/) and running the following command
in command line: `gcloud auth application-default login`. Alternatively, you can authenticate
Translate requests using an API key. See
[Translate quickstart](https://cloud.google.com/translate/v2/quickstart) for more details.

#### Installation and setup
You'll need to obtain the `google-cloud-translate` library. See the [Quickstart](#quickstart)
section to add `google-cloud-translate` as a dependency in your code.

#### Creating an authorized service object
To make authenticated requests to Google Translates, you must create a service object with an API
key. By default, API key is looked for in the `GOOGLE_API_KEY` environment variable. Once the API
key is set, you can make API calls by invoking methods on the Translate service object. To create a
service object, given that `GOOGLE_API_KEY` is set, use the following code:
To make authenticated requests to Google Translate, you must create a service object with
credentials or with an API key. The simplest way to authenticate is to use
[Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials).
These credentials are automatically inferred from your environment, so you only need the following
code to create your service object:

```java
import com.google.cloud.translate.Translate;
Expand All @@ -86,7 +91,11 @@ import com.google.cloud.translate.TranslateOptions;
Translate translate = TranslateOptions.getDefaultInstance().getService();
```

Or you can explicitly set the API key as follows:
Notice that this code can be also used with an API key. By default, an API key is looked for in the
`GOOGLE_API_KEY` environment variable. Once the API key is set, you can make API calls by invoking
methods on the Translate service created via `TranslateOptions.getDefaultInstance().getService()`.

You can also explicitly set the API key as follows:
```java
Translate translate = TranslateOptions.newBuilder().setApiKey("myKey").getService();
```
Expand Down Expand Up @@ -131,8 +140,8 @@ Translation translation = translate.translate(

In
[DetectLanguageAndTranslate.java](../google-cloud-examples/src/main/java/com/google/cloud/examples/translate/snippets/DetectLanguageAndTranslate.java)
we put together all the code shown above into one program. The program assumes that a valid api key
is available.
we put together all the code shown above into one program. The program assumes that either default
application credentials or a valid api key are available.

Troubleshooting
---------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,19 @@ public static TranslateOption sourceLanguage(String sourceLanguage) {
public static TranslateOption targetLanguage(String targetLanguage) {
return new TranslateOption(TranslateRpc.Option.TARGET_LANGUAGE, targetLanguage);
}

/**
* Sets the language translation model. You can use this parameter to take advantage of Neural
* Machine Translation. Possible values are {@code base} and {@code nmt}. Google Translate could
* use a different model to translate your text, use {@link Translation#getModel()} to know
* which model was used for translation. Please notice that you must be whitelisted to use this
* option, otherwise translation will fail.
*
* @param model the language translation model
*/
public static TranslateOption model(String model) {
return new TranslateOption(TranslateRpc.Option.MODEL, model);
}
}

/**
Expand Down Expand Up @@ -170,6 +183,8 @@ public static TranslateOption targetLanguage(String targetLanguage) {
* @param texts the texts to translate
* @return a list of objects containing information on the language translation, one for each
* provided text, in order.
* @throws TranslateException upon failure or if {@link TranslateOption#model(String)} is used by
* a non-whitelisted user
*/
List<Translation> translate(List<String> texts, TranslateOption... options);

Expand All @@ -189,6 +204,8 @@ public static TranslateOption targetLanguage(String targetLanguage) {
*
* @param text the text to translate
* @return an object containing information on the language translation
* @throws TranslateException upon failure or if {@link TranslateOption#model(String)} is used by
* a non-whitelisted user
*/
Translation translate(String text, TranslateOption... options);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,17 @@

import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;

public class TranslateOptions extends
HttpServiceOptions<Translate, TranslateRpc, TranslateOptions> {

private static final long serialVersionUID = -572597134540398216L;
private static final String DEFAULT_HOST = "https://translation.googleapis.com";
private static final String API_KEY_ENV_NAME = "GOOGLE_API_KEY";
private static final Set<String> SCOPES = ImmutableSet.of();
private static final Set<String> SCOPES =
ImmutableSet.of("https://www.googleapis.com/auth/cloud-platform");

private final String apiKey;
private final String targetLanguage;
Expand Down Expand Up @@ -97,17 +100,6 @@ public Builder setProjectId(String projectId) {
return self();
}

/**
* Sets the service authentication credentials. Setting credentials has no impact on the
* {@link Translate} service.
*
* @return the builder
*/
public Builder setCredentials(Credentials credentials) {
super.setCredentials(credentials);
return self();
}

/**
* Sets the API key used to issue requets. If not set, the API key is looked for in the
* {@code GOOGLE_API_KEY} environment variable. For instructions on how to get an API key see
Expand Down Expand Up @@ -158,18 +150,13 @@ public Builder setTargetLanguage(String targetLanguage) {

@Override
public TranslateOptions build() {
// Auth credentials are not used by Translate
setCredentials(NoCredentials.getInstance());
return new TranslateOptions(this);
}
}

private TranslateOptions(Builder builder) {
super(TranslateFactory.class, TranslateRpcFactory.class, builder);
this.apiKey = builder.apiKey != null ? builder.apiKey : getDefaultApiKey();
checkArgument(this.apiKey != null,
"An API key is required for this service but could not be determined from the builder "
+ "or the environment. Please set an API key using the builder.");
this.targetLanguage = firstNonNull(builder.targetLanguage, Locale.ENGLISH.getLanguage());
}

Expand All @@ -193,6 +180,11 @@ protected Set<String> getScopes() {
return SCOPES;
}

@Override
protected String getDefaultHost() {
return DEFAULT_HOST;
}

@Deprecated
protected String defaultApiKey() {
return getDefaultApiKey();
Expand Down Expand Up @@ -250,8 +242,8 @@ public boolean equals(Object obj) {
}
TranslateOptions options = (TranslateOptions) obj;
return baseEquals(options)
&& apiKey.equals(options.apiKey)
&& targetLanguage.equals(options.targetLanguage);
&& Objects.equals(apiKey, options.apiKey)
&& Objects.equals(targetLanguage, options.targetLanguage);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.common.base.MoreObjects;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

/**
Expand All @@ -43,10 +44,12 @@ public Translation apply(TranslationsResource translationPb) {

private final String translatedText;
private final String sourceLanguage;
private final String model;

private Translation(String translatedText, String sourceLanguage) {
private Translation(String translatedText, String sourceLanguage, String model) {
this.translatedText = translatedText;
this.sourceLanguage = sourceLanguage;
this.model = model;
}

/**
Expand Down Expand Up @@ -81,6 +84,18 @@ public String getSourceLanguage() {
return sourceLanguage;
}

/**
* Returns the translation model used to translate the text. This value is only available if
* {@link Translate.TranslateOption#model(String)} was passed to
* {@link Translate#translate(List, Translate.TranslateOption...)}.
*
* <p>Please notice that you must be whitelisted to use the
* {@link Translate.TranslateOption#model(String)} option, otherwise translation will fail.
*/
public String getModel() {
return model;
}

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
Expand Down Expand Up @@ -108,7 +123,8 @@ public final boolean equals(Object obj) {
}

static Translation fromPb(TranslationsResource translationPb) {
// TODO remove get("model") as soon as REST apiary supports model
return new Translation(translationPb.getTranslatedText(),
translationPb.getDetectedSourceLanguage());
translationPb.getDetectedSourceLanguage(), (String) translationPb.get("model"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,29 @@

package com.google.cloud.translate.spi;

import static com.google.cloud.translate.spi.TranslateRpc.Option.MODEL;
import static com.google.cloud.translate.spi.TranslateRpc.Option.SOURCE_LANGUAGE;
import static com.google.cloud.translate.spi.TranslateRpc.Option.TARGET_LANGUAGE;
import static com.google.common.base.MoreObjects.firstNonNull;

import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.translate.Translate;
import com.google.api.services.translate.model.DetectionsListResponse;
import com.google.api.services.translate.model.DetectionsResourceItems;
import com.google.api.services.translate.model.LanguagesListResponse;
import com.google.api.services.translate.model.LanguagesResource;
import com.google.api.services.translate.model.TranslationsListResponse;
import com.google.api.services.translate.model.TranslationsResource;
import com.google.cloud.translate.TranslateException;
import com.google.cloud.translate.TranslateOptions;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;

import java.io.IOException;
Expand All @@ -56,11 +64,27 @@ private static TranslateException translate(IOException exception) {
return new TranslateException(exception);
}

private GenericUrl buildTargetUrl(String path) {
GenericUrl genericUrl = new GenericUrl(translate.getBaseUrl() + "v2/" + path);
if (options.getApiKey() != null) {
genericUrl.put("key", options.getApiKey());
}
return genericUrl;
}

@Override
public List<List<DetectionsResourceItems>> detect(List<String> texts) {
try {
Map<String, ?> content = ImmutableMap.of("q", texts);
HttpRequest httpRequest = translate.getRequestFactory()
.buildPostRequest(buildTargetUrl("detect"),
new JsonHttpContent(translate.getJsonFactory(), content))
.setParser(translate.getObjectParser());
List<List<DetectionsResourceItems>> detections =
translate.detections().list(texts).setKey(options.getApiKey()).execute().getDetections();
httpRequest.execute().parseAs(DetectionsListResponse.class).getDetections();
// TODO use REST apiary as soon as it supports POST
// List<List<DetectionsResourceItems>> detections =
// translate.detections().list(texts).setKey(options.getApiKey()).execute().getDetections();
return detections != null ? detections : ImmutableList.<List<DetectionsResourceItems>>of();
} catch (IOException ex) {
throw translate(ex);
Expand All @@ -70,12 +94,21 @@ public List<List<DetectionsResourceItems>> detect(List<String> texts) {
@Override
public List<LanguagesResource> listSupportedLanguages(Map<Option, ?> optionMap) {
try {
List<LanguagesResource> languages = translate.languages()
.list()
.setKey(options.getApiKey())
.setTarget(
firstNonNull(TARGET_LANGUAGE.getString(optionMap), options.getTargetLanguage()))
.execute().getLanguages();
Map<String, ?> content = ImmutableMap.of("target",
firstNonNull(TARGET_LANGUAGE.getString(optionMap), options.getTargetLanguage()));
HttpRequest httpRequest = translate.getRequestFactory()
.buildPostRequest(buildTargetUrl("languages"),
new JsonHttpContent(translate.getJsonFactory(), content))
.setParser(translate.getObjectParser());
List<LanguagesResource> languages =
httpRequest.execute().parseAs(LanguagesListResponse.class).getLanguages();
// TODO use REST apiary as soon as it supports POST
// List<LanguagesResource> languages = translate.languages()
// .list()
// .setKey(options.getApiKey())
// .setTarget(
// firstNonNull(TARGET_LANGUAGE.getString(optionMap), options.getTargetLanguage()))
// .execute().getLanguages();
return languages != null ? languages : ImmutableList.<LanguagesResource>of();
} catch (IOException ex) {
throw translate(ex);
Expand All @@ -85,16 +118,18 @@ public List<LanguagesResource> listSupportedLanguages(Map<Option, ?> optionMap)
@Override
public List<TranslationsResource> translate(List<String> texts, Map<Option, ?> optionMap) {
try {
String targetLanguage =
firstNonNull(TARGET_LANGUAGE.getString(optionMap), options.getTargetLanguage());
final String sourceLanguage = SOURCE_LANGUAGE.getString(optionMap);
List<TranslationsResource> translations =
translate.translations()
.list(texts, targetLanguage)
.setSource(sourceLanguage)
.setKey(options.getApiKey())
.execute()
.getTranslations();
// TODO use POST as soon as usage of "model" causes error in non-whitelisted projects
String targetLanguage =

This comment was marked as spam.

firstNonNull(TARGET_LANGUAGE.getString(optionMap), options.getTargetLanguage());
final String sourceLanguage = SOURCE_LANGUAGE.getString(optionMap);
List<TranslationsResource> translations =
translate.translations()
.list(texts, targetLanguage)
.setSource(sourceLanguage)
.setKey(options.getApiKey())
.set("model", MODEL.getString(optionMap))
.execute()
.getTranslations();
return Lists.transform(
translations != null ? translations : ImmutableList.<TranslationsResource>of(),
new Function<TranslationsResource, TranslationsResource>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public interface TranslateRpc {

enum Option {
SOURCE_LANGUAGE("source"),
TARGET_LANGUAGE("target");
TARGET_LANGUAGE("target"),
MODEL("model");

private final String value;

Expand Down
Loading