Skip to content
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
75 changes: 75 additions & 0 deletions java/translate_text/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# 🌐 Translate text from one language to another

A Java Cloud Function for translating text from one language to another. Includes support for [Google](https://translate.google.com/), [AWS](https://aws.amazon.com/translate/), and [Azure](https://azure.microsoft.com/en-us/products/cognitive-services/translator/)

_Example input:_

```json
{
"provider": "google",
"text": "Hello from Open Runtimes",
"from": "en",
"to": "es"
}
```

_Example output:_

```json
{
"response": {
"message": "Hola desde Open Runtimes",
"success": true,
"from": "en"
},
"stdout": "",
"stderr": ""
}
```

## 📝 Variables

#### Translating with `google`

No variables required

- **API_KEY** - Access key for GCP

#### Translate with `aws`

- **AWS_ACCESS_KEY** - Access key for AWS
- **AWS_SECRET_KEY** - Secret Key for AWS

#### Translating with `azure`

- **TRANSLATOR_KEY** - Translator Key for Azure
- **REGION** - Region for Azure

## 🚀 Deployment

1. Clone this repository, and enter this function folder:

```bash
git clone https://github.com/open-runtimes/examples.git && cd examples
cd java/translate_text
```

2. Build the code:

```bash
docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-8.0 sh /usr/local/src/build.sh
```

3. Spin-up open-runtime:

```bash
docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/java:v2-8.0 sh /usr/local/src/start.sh
```

Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Java runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/java-8.0).

## 📝 Notes

- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions).
- This example is compatible with JAVA 8. Other versions may work but are not guarenteed to work as they haven't been tested.
- For aws as a provider, default region US_WEST_2 has been configured
8 changes: 8 additions & 0 deletions java/translate_text/deps.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
dependencies {
implementation platform('com.google.cloud:libraries-bom:25.4.0')
implementation platform('software.amazon.awssdk:bom:2.15.0')
implementation 'software.amazon.awssdk:translate'
implementation 'com.google.code.gson:gson:2.9.0'
implementation 'com.google.cloud:google-cloud-translate'
implementation 'com.squareup.okhttp3:okhttp:3.2.0'
}
275 changes: 275 additions & 0 deletions java/translate_text/index.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
package io.translate_text.java;

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.translate.Translate;
import com.google.api.services.translate.model.TranslationsListResponse;
import com.google.api.services.translate.model.TranslationsResource;
import com.google.gson.Gson;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.translate.TranslateClient;
import software.amazon.awssdk.services.translate.model.TranslateException;
import software.amazon.awssdk.services.translate.model.TranslateTextRequest;
import software.amazon.awssdk.services.translate.model.TranslateTextResponse;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import okhttp3.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.*;

final Gson gson = new Gson();

public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception {
// Validate that values present in the request are not empty (payload, variables)
RuntimeResponse errorResponse = checkEmptyPayloadAndVariables(req, res);
if (errorResponse != null) {
return errorResponse;
}

// Validate the requested payload
String payloadString = req.getPayload().toString();

errorResponse = validatePayload(payloadString, res);
if (errorResponse != null) {
return errorResponse;
}

Map<String, Object> payload = gson.fromJson(payloadString, Map.class);

// Get provider from payload
String provider = payload.get("provider").toString();
String sourceLanguageCode = payload.get("from").toString();

String API_KEY = "API_KEY";
String REGION = "REGION";
String SECRET_ACCESS_KEY = "SECRET_ACCESS_KEY";

errorResponse = validateVariables(req, res, API_KEY, SECRET_ACCESS_KEY, REGION, provider);
if (errorResponse != null) {
return errorResponse;
}

Map<String, String> variables = req.getVariables();
String apiKey = variables.get(API_KEY);

String translatedText = "";
Map<String, Object> responseData = new HashMap<>();

try {
translatedText = translateText(payload, variables, apiKey);
} catch (Exception e) {
responseData.put("success", false);
responseData.put("message", "Something went wrong while translating the text, please check with the developers. Error: " + e.getMessage());
return res.json(responseData);
}
responseData.put("success", true);
responseData.put("message", translatedText);
responseData.put("from", sourceLanguageCode);

return res.json(responseData);
}

public String translateText(Map<String, Object> payload, Map<String, String> variables, String apiKey) throws GeneralSecurityException, IOException {
String provider = payload.get("provider").toString();
String sourceLanguageCode = payload.get("from").toString();
String targetLanguageCode = payload.get("to").toString();
String text = payload.get("text").toString();

if (Objects.equals("aws", provider)) {
String secretAccessKey = variables.get("SECRET_ACCESS_KEY");
return translateTexteUsingAWS(text, sourceLanguageCode, targetLanguageCode, apiKey, secretAccessKey);
} else if (Objects.equals("google", provider)) {
return translateTextUsingGCP(text, targetLanguageCode, apiKey);
} else if (Objects.equals("azure", provider)) {
String region = variables.get("REGION");
return translateTexteUsingAzure(text, sourceLanguageCode, targetLanguageCode, apiKey, region);
}

return null;
}


public String translateTextUsingGCP(String text, String targetLanguage, String apiKey) throws GeneralSecurityException, IOException {
Translate t = new Translate.Builder(GoogleNetHttpTransport.newTrustedTransport(), GsonFactory.getDefaultInstance(), null)
.setApplicationName("Interacto")
.build();

Translate.Translations.List list = t.new Translations().list(
Arrays.asList(text), targetLanguage);
TranslationsListResponse translateResponse = list.setKey(apiKey).execute();
List<TranslationsResource> translationsResourceList = translateResponse.getTranslations();
return translationsResourceList.get(0).getTranslatedText();
}

public String translateTexteUsingAWS(String text, String sourceLanguageCode, String targetLanguageCode, String accessKeyId, String secretAccessKey) {

try {
Region region = Region.US_WEST_2;
TranslateClient translateClient = TranslateClient.builder()
.region(region)
.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKeyId, secretAccessKey)))
.build();

TranslateTextRequest textRequest = TranslateTextRequest.builder()
.sourceLanguageCode(sourceLanguageCode)
.targetLanguageCode(targetLanguageCode)
.text(text)
.build();

TranslateTextResponse textResponse = translateClient.translateText(textRequest);
System.out.println(textResponse.translatedText());
translateClient.close();
return textResponse.translatedText();
} catch (TranslateException e) {
System.err.println(e.getMessage());
System.exit(1);
}
return text;
}

public String translateTexteUsingAzure(String text, String sourceLanguageCode, String targetLanguageCode, String apiKey, String region) throws IOException {
String endpointUrl = "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=" + sourceLanguageCode + "&to=" + targetLanguageCode;
String requestBody = "[{\"text\":\"" + text + "\"}]";

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType,
requestBody);
Request request = new Request.Builder()
.url(endpointUrl)
.post(body)
.addHeader("Ocp-Apim-Subscription-Key", apiKey)
// location required if you're using a multi-service or regional (not global) resource.
.addHeader("Ocp-Apim-Subscription-Region", region)
.addHeader("Content-type", "application/json")
.build();
Response response = client.newCall(request).execute();
String res = response.body().string();
JsonParser parser = new JsonParser();
JsonElement json = parser.parse(res);
String answer = json.getAsJsonArray().getAsJsonArray().get(0).getAsJsonObject().get("translations").getAsJsonArray().get(0).getAsJsonObject().get("text").getAsString();

return answer;
}

private RuntimeResponse validateVariables(RuntimeRequest req, RuntimeResponse res, String apiKey, String secretAccessKey, String region, String provider) {
Map<String, String> variables = req.getVariables();

if (!variables.containsKey(apiKey) || variables.get(apiKey) == null || variables.get(apiKey).trim().isEmpty()) {
Map<String, Object> responseData = new HashMap<>();
responseData.put("success", false);
responseData.put("message", "Please pass a non-empty API Key(s) " + apiKey + " for translateText");
return res.json(responseData);
}

if (Objects.equals("aws", provider) && (!variables.containsKey(secretAccessKey) || variables.get(secretAccessKey) == null || variables.get(secretAccessKey).trim().isEmpty())) {
Map<String, Object> responseData = new HashMap<>();
responseData.put("success", false);
responseData.put("message", "Please pass a non-empty " + secretAccessKey + " for translateText");
return res.json(responseData);
}

if (Objects.equals("azure", provider) && (!variables.containsKey(region) || variables.get(region) == null || variables.get(region).trim().isEmpty())) {
Map<String, Object> responseData = new HashMap<>();
responseData.put("success", false);
responseData.put("message", "Please pass a non-empty " + region + " for translateText");
return res.json(responseData);
}

return null;
}

private RuntimeResponse validatePayload(String payloadString, RuntimeResponse res) {
Map<String, Object> responseData = new HashMap<>();
Map<String, Object> payload;
;
try {
payload = gson.fromJson(payloadString, Map.class);
} catch (Exception e) {
responseData.put("success", false);
responseData.put("message", "The payload is invalid. Example of valid payload:{\"provider\":\"aws\",\"from\":\"cs\",\"to\":\"en\",\"text\":\"Ahoj svet.\"}");
return res.json(responseData);
}

if (!payload.containsKey("provider")) {
responseData.put("success", false);
responseData.put("message", "Please provide a valid provider");
return res.json(responseData);
}


if (!payload.containsKey("from")) {
responseData.put("success", false);
responseData.put("message", "Please provide a valid from");
return res.json(responseData);
}

if (!payload.containsKey("to")) {
responseData.put("success", false);
responseData.put("message", "Please provide a valid to");
return res.json(responseData);
}

if (!payload.containsKey("text")) {
responseData.put("success", false);
responseData.put("message", "Please provide a valid text");
return res.json(responseData);
}

String provider = payload.get("provider").toString();
String from = payload.get("from").toString();
String to = payload.get("to").toString();
String text = payload.get("text").toString();

if (provider == null || provider.isEmpty()) {
responseData.put("success", false);
responseData.put("message", "Provided provider: " + provider + " is not valid, please provide a valid provider");
return res.json(responseData);
}

if (from == null || from.isEmpty()) {
responseData.put("success", false);
responseData.put("message", "Provided from: " + from + " is not valid, please provide a valid from value");
return res.json(responseData);
}

if (to == null || to.isEmpty()) {
responseData.put("success", false);
responseData.put("message", "Provided to: " + to + " is not valid, please provide a valid to value");
return res.json(responseData);
}

if (text == null || text.isEmpty()) {
responseData.put("success", false);
responseData.put("message", "Provided text: " + text + " is not valid, please provide a valid text value");
return res.json(responseData);
}

return null;
}

private RuntimeResponse checkEmptyPayloadAndVariables(RuntimeRequest req, RuntimeResponse res) {

Map<String, Object> responseData = new HashMap<>();

if (req.getPayload() == null || req.getPayload().trim().isEmpty() || req.getPayload().trim().equals("{}")) {
responseData.put("success", false);
responseData.put("message", "Payload is empty, expected a payload with {\"provider\":\"aws\",\"from\":\"cs\",\"to\":\"en\",\"text\":\"Ahoj svet.\"}");
return res.json(responseData);

}
if (req.getVariables() == null) {
responseData.put("success", false);
responseData.put("message", "Empty function variables found. You need to pass an API_KEY");
return res.json(responseData);
}

return null;
}