In this part of the lesson, you will write code to translate text using the translator service.
The speech service REST API doesn't support direct translations, instead you can use the Translator service to translate the text generated by the speech to text service, and the text of the spoken response. This service has a REST API you can use to translate the text, but to make it easier to use this will be wrapped in another HTTP trigger in your functions app.
-
Open your
smart-timer-trigger
project in VS Code, and open the terminal ensuring the virtual environment is activated. If not, kill and re-create the terminal. -
Open the
local.settings.json
file and add settings for the translator API key and location:"TRANSLATOR_KEY": "<key>", "TRANSLATOR_LOCATION": "<location>"
Replace
<key>
with the API key for your translator service resource. Replace<location>
with the location you used when you created the translator service resource. -
Add a new HTTP trigger to this app called
translate-text
using the following command from inside the VS Code terminal in the root folder of the functions app project:func new --name translate-text --template "HTTP trigger"
This will create an HTTP trigger called
translate-text
. -
Replace the contents of the
__init__.py
file in thetranslate-text
folder with the following:import logging import os import requests import azure.functions as func location = os.environ['TRANSLATOR_LOCATION'] translator_key = os.environ['TRANSLATOR_KEY'] def main(req: func.HttpRequest) -> func.HttpResponse: req_body = req.get_json() from_language = req_body['from_language'] to_language = req_body['to_language'] text = req_body['text'] logging.info(f'Translating {text} from {from_language} to {to_language}') url = f'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0' headers = { 'Ocp-Apim-Subscription-Key': translator_key, 'Ocp-Apim-Subscription-Region': location, 'Content-type': 'application/json' } params = { 'from': from_language, 'to': to_language } body = [{ 'text' : text }] response = requests.post(url, headers=headers, params=params, json=body) return func.HttpResponse(response.json()[0]['translations'][0]['text'])
This code extracts the text and the languages from the HTTP request. It then makes a request to the translator REST API, passing the languages as parameters for the URL and the text to translate as the body. Finally, the translation is returned.
-
Run your function app locally. You can then call this using a tool like curl in the same way that you tested your
text-to-timer
HTTP trigger. Make sure to pass the text to translate and the languages as a JSON body:{ "text": "Définir une minuterie de 30 secondes", "from_language": "fr-FR", "to_language": "en-US" }
This example translates Définir une minuterie de 30 secondes from French to US English. It will return Set a 30-second timer.
💁 You can find this code in the code/functions folder.
-
Open the
smart-timer
project in VS Code if it is not already open. -
Your smart timer will have 2 languages set - the language of the server that was used to train LUIS (the same language is also used to build the messages to speak to the user), and the language spoken by the user. Update the
LANGUAGE
constant in theconfig.h
header file to be the language that will be spoken by the user, and add a new constant calledSERVER_LANGUAGE
for the language used to train LUIS:const char *LANGUAGE = "<user language>"; const char *SERVER_LANGUAGE = "<server language>";
Replace
<user language>
with the locale name for language you will be speaking in, for examplefr-FR
for French, orzn-HK
for Cantonese.Replace
<server language>
with the locale name for language used to train LUIS.You can find a list of the supported languages and their locale names in the Language and voice support documentation on Microsoft docs.
💁 If you don't speak multiple languages you can use a service like Bing Translate or Google Translate to translate from your preferred language to a language of your choice. These services can then play audio of the translated text.
For example, if you train LUIS in English, but want to use French as the user language, you can translate sentences like "set a 2 minute and 27 second timer" from English into French using Bing Translate, then use the Listen translation button to speak the translation into your microphone.
-
Add the translator API key and location below the
SPEECH_LOCATION
:const char *TRANSLATOR_API_KEY = "<KEY>"; const char *TRANSLATOR_LOCATION = "<LOCATION>";
Replace
<KEY>
with the API key for your translator service resource. Replace<LOCATION>
with the location you used when you created the translator service resource. -
Add the translator trigger URL below the
VOICE_URL
:const char *TRANSLATE_FUNCTION_URL = "<URL>";
Replace
<URL>
with the URL for thetranslate-text
HTTP trigger on your function app. This will be the same as the value forTEXT_TO_TIMER_FUNCTION_URL
, except with a function name oftranslate-text
instead oftext-to-timer
. -
Add a new file to the
src
folder calledtext_translator.h
. -
This new
text_translator.h
header file will contain a class to translate text. Add the following to this file to declare this class:#pragma once #include <Arduino.h> #include <ArduinoJson.h> #include <HTTPClient.h> #include <WiFiClient.h> #include "config.h" class TextTranslator { public: private: WiFiClient _client; }; TextTranslator textTranslator;
This declares the
TextTranslator
class, along with an instance of this class. The class has a single field for the WiFi client. -
To the
public
section of this class, add a method to translate text:String translateText(String text, String from_language, String to_language) { }
This method takes the language to translate from, and the language to translate to. When handling speech, the speech will be translated from the user language to the LUIS server language, and when giving responses it will translate from the LUIS server language to the users language.
-
In this method, add code to construct a JSON body containing the text to translate and the languages:
DynamicJsonDocument doc(1024); doc["text"] = text; doc["from_language"] = from_language; doc["to_language"] = to_language; String body; serializeJson(doc, body); Serial.print("Translating "); Serial.print(text); Serial.print(" from "); Serial.print(from_language); Serial.print(" to "); Serial.print(to_language);
-
Below this, add the following code to send the body to the serverless function app:
HTTPClient httpClient; httpClient.begin(_client, TRANSLATE_FUNCTION_URL); int httpResponseCode = httpClient.POST(body);
-
Next, add code to get the response:
String translated_text = ""; if (httpResponseCode == 200) { translated_text = httpClient.getString(); Serial.print("Translated: "); Serial.println(translated_text); } else { Serial.print("Failed to translate text - error "); Serial.println(httpResponseCode); }
-
Finally, add code to close the connection and return the translated text:
httpClient.end(); return translated_text;
-
Open the
main.cpp
file. -
Add an include directive at the top of the file for the
TextTranslator
class header file:#include "text_translator.h"
-
The text that is said when a timer is set or expires needs to be translated. To do this, add the following as the first line of the
say
function:text = textTranslator.translateText(text, LANGUAGE, SERVER_LANGUAGE);
This will translate the text to the users language.
-
In the
processAudio
function, text is retrieved from the captured audio with theString text = speechToText.convertSpeechToText();
call. After this call, translate the text:String text = speechToText.convertSpeechToText(); text = textTranslator.translateText(text, LANGUAGE, SERVER_LANGUAGE);
This will translate the text from the users language into the language used on the server.
-
Build this code, upload it to your Wio Terminal and test it out through the serial monitor. Once you see
Ready
in the serial monitor, press the C button (the one on the left-hand side, closest to the power switch), and speak. Ensure your function app is running, and request a timer in the user language, either by speaking that language yourself, or using a translation app.Connecting to WiFi.. Connected! Got access token. Ready. Starting recording... Finished recording Sending speech... Speech sent! {"RecognitionStatus":"Success","DisplayText":"Définir une minuterie de 2 minutes 27 secondes.","Offset":9600000,"Duration":40400000} Translating Définir une minuterie de 2 minutes 27 secondes. from fr-FR to en-US Translated: Set a timer of 2 minutes 27 seconds. Set a timer of 2 minutes 27 seconds. {"seconds": 147} Translating 2 minute 27 second timer started. from en-US to fr-FR Translated: 2 minute 27 seconde minute a commencé. 2 minute 27 seconde minute a commencé. Translating Times up on your 2 minute 27 second timer. from en-US to fr-FR Translated: Chronométrant votre minuterie de 2 minutes 27 secondes. Chronométrant votre minuterie de 2 minutes 27 secondes.
💁 You can find this code in the code/wio-terminal folder.
😀 Your multilingual timer program was a success!