How To Create A Multi-Language Translator Using Angular And Azure Cognitive Services

Ankit Sharma
12 min readFeb 16, 2020

--

Introduction

In this article, we are going to create a multi-language translator using Angular and the Translate Text Azure Cognitive Service. This translator will be able to translate between more than 60 languages which are supported by the Translate Text API. We will supply the text to translate and the target language to our application and it will return the translated text and the detected language of the input text.

Prerequisites

Source Code

You can get the source code from GitHub.

We will use an ASP.NET Core backend for this application. The ASP.NET Core backend provides a straight forward authentication process to access Azure cognitive services. This will also ensure that the end user won’t have the direct access to the cognitive services.

Create the Azure Translator Text Cognitive Services resource

Log in to the Azure portal and search for the cognitive services in the search bar and click on the result. Refer to the image shown below.

On the next screen, click on the Add button. It will open the cognitive services marketplace page. Search for the Translator Text in the search bar and click on the search result. It will open the Translator Text API page. Click on the Create button to create a new Translator Text resource. Refer to the image shown below.

On the Create page, fill in the details as indicated below.

  • Name: Give a unique name for your resource.
  • Subscription: Select the subscription type from the dropdown.
  • Pricing tier: Select the pricing tier as per your choice.
  • Resource group: Select an existing resource group or create a new one.

Click on the Create button. Refer to the image shown below.

After your resource is successfully deployed, click on the “Go to resource” button. You can see the Key and the endpoint for the newly created Translator Text resource. Refer to the image shown below.

Make a note of the key, we will be using this in the latter part of this article to request the translations from the Translator Text API. The values are masked here for privacy.

Creating the ASP.NET Core application

Open Visual Studio 2019 and click on “Create a new Project”. A “Create a new Project” dialog will open. Select “ASP.NET Core Web Application” and click on Next. Now you will be at “Configure your new project” screen, provide the name for your application as ngTranslator and click on create. Refer to the image shown below.

You will be navigated to “Create a new ASP.NET Core web application” screen. Select “.NET Core” and “ASP.NET Core 3.0” from the dropdowns on the top. Then, select “Angular” project template and click on Create. Refer to the image shown below.

This will create our project. The folder structure of the application is shown below.

The ClientApp folder contains the Angular code for our application. The Controllers folders will contain our API controllers. The angular components are present inside the ClientApp\src\app folder. The default template contains few Angular components. These components won’t affect our application, but for the sake of simplicity, we will delete fetchdata and counter folders from ClientApp/app/components folder. Also, remove the reference for these two components from the app.module.ts file.

Adding the Model to the Application

Right-click on the ngTranslator project and select Add >> New Folder. Name the folder as Models. Now right-click on the Models folder and select Add >> class. Name the class file as LanguageDetails.cs and click Add. This file will contain the User model.

Open LanguageDetails.cs and put the following code inside it.

namespace ngTranslator.Models
{
public class LanguageDetails
{
public string Name { get; set; }
public string NativeName { get; set; }
public string Dir { get; set; }
}
}

Similarly, add a new class file TextResult.cs and put the following code inside it.

namespace ngTranslator.Models
{
public class TextResult
{
public string Text { get; set; }
public string Script { get; set; }
}
}

Add a new class file Translation.cs and put the following code inside it.

namespace ngTranslator.Models
{
public class Translation
{
public string Text { get; set; }
public TextResult Transliteration { get; set; }
public string To { get; set; }
}
}

Create a class file DetectedLanguage.cs and put the following code inside it.

namespace ngTranslator.Models
{
public class DetectedLanguage
{
public string Language { get; set; }
public float Score { get; set; }
}
}

Create a class file TranslationResult.cs and put the following code inside it.

namespace ngTranslator.Models
{
public class TranslationResult
{
public DetectedLanguage DetectedLanguage { get; set; }
public TextResult SourceText { get; set; }
public Translation[] Translations { get; set; }
}
}

Create the class file AvailableLanguage.cs and put the following code inside it.

using System.Collections.Generic;namespace ngTranslator.Models
{
public class AvailableLanguage
{
public Dictionary<string, LanguageDetails> Translation { get; set; }
}
}

We will also add two classes as DTO (Data Transfer Object) for sending data back to the client.

Create a new folder and name it DTOModels. Add the new class file AvailableLanguageDTO.cs in the DTOModels Folder and put the following code inside it.

namespace ngTranslator.Models
{
public class AvailableLanguageDTO
{
public string LanguageID { get; set; }
public string LanguageName { get; set; }
}
}

Add TranslationResultDTO.cs file and put the following code inside it.

namespace ngTranslator.Models
{
public class TranslationResultDTO
{
public string DetectedLanguage { get; set; }
public string TranslationOutput { get; set; }
}
}

Adding the Translation Controller

We will add a new controller to our application. Right-click on the Controllers folder and select Add >> New Item. An “Add New Item” dialog box will open. Select “Visual C#” from the left panel, then select “API Controller Class” from templates panel and put the name as TranslationController.cs. Click on Add. Refer to the image below.

The TranslationController will handle the translation request from the client. This controller will also return the list of all the language supported by the Translate Text API.

Open TranslationController.cs file and put the following code inside it.

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using ngTranslator.Models;
using System.Net.Http;
using System.Text;
using ngTranslator.Models;
namespace ngTranslator.Controllers
{
[Produces("application/json")]
[Route("api/[controller]")]
public class TranslationController : Controller
{
[HttpPost("{textToTranslate}/{targetLanguage}")]
public async Task<TranslationResultDTO> Post(string textToTranslate, string targetLanguage)
{
TranslationResult[] translationResultList = await TranslateText(textToTranslate, targetLanguage);
TranslationResultDTO translationResult = new TranslationResultDTO
{
DetectedLanguage = translationResultList[0].DetectedLanguage.Language,
TranslationOutput = translationResultList[0].Translations[0].Text
};
return translationResult;
}
async Task<TranslationResult[]> TranslateText(string inputText, string targetLanguage)
{
string subscriptionKey = "af19d996a3cb4a70a808567aad5bc41a";
string translateTextEndpoint = "https://api.cognitive.microsofttranslator.com/";
string route = $"/translate?api-version=3.0&to={targetLanguage}";
object[] body = new object[] { new { Text = inputText } };
var requestBody = JsonConvert.SerializeObject(body);
using (var client = new HttpClient())
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Post;
request.RequestUri = new Uri(translateTextEndpoint + route);
request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
HttpResponseMessage responseMessage = await client.SendAsync(request).ConfigureAwait(false);
string result = await responseMessage.Content.ReadAsStringAsync();
TranslationResult[] translationResult = JsonConvert.DeserializeObject<TranslationResult[]>(result);
return translationResult;
}
}
[HttpGet]
public async Task<List<AvailableLanguageDTO>> GetAvailableLanguages()
{
string endpoint = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&scope=translation";
var client = new HttpClient();
using (var request = new HttpRequestMessage())
{
request.Method = HttpMethod.Get;
request.RequestUri = new Uri(endpoint);
var response = await client.SendAsync(request).ConfigureAwait(false);
string result = await response.Content.ReadAsStringAsync();
AvailableLanguage deserializedOutput = JsonConvert.DeserializeObject<AvailableLanguage>(result);List<AvailableLanguageDTO> availableLanguage = new List<AvailableLanguageDTO>();foreach (KeyValuePair<string, LanguageDetails> translation in deserializedOutput.Translation)
{
AvailableLanguageDTO language = new AvailableLanguageDTO();
language.LanguageID = translation.Key;
language.LanguageName = translation.Value.Name;
availableLanguage.Add(language);
}
return availableLanguage;
}
}
}
}

The Post method will accept two parameters — textToTranslate and targetLanguage. We will then invoke the TranslateText method which will return an array of TranslationResult. We will then prepare our data transfer object of type TranslationResultDTO and return it to the client.

The TranslateText method will accept two parameters — the text to translate and the target language. We will set the subscription key for the Azure Translator Text cognitive service and define a variable for the global endpoint for Translator Text. The request URL contains the API endpoint along with the target language. We will then create a new HttpRequestMessage. This HTTP request is a Post request. We will pass the subscription key in the header of the request. The Translator Text API returns a JSON object, which will be deserialized to an array of type TranslationResult. This JSON object contain the translated text as well as the language detected for the input text.

The GetAvailableLanguages method is of type HTTPGet. It returns the list of languages supported by the Translate Text API. We will set the request URI and create a HttpRequestMessage which will be a Get request. This request URL will return a JSON object which will be deserialized to an object of type AvailableLanguage. We will then prepare the data transfer object of type AvailableLanguageDTO and return it to the client.

Working on the Client side of the application

The code for the client-side is available in the ClientApp folder. We will use Angular CLI to work with the client code.

Using Angular CLI is not mandatory. I am using Angular CLI here as it is user-friendly and easy to use. If you don’t want to use CLI then you can create the files for components and services manually.

Navigate to ngTranslator\ClientApp folder in your machine and open a command window. We will execute all our Angular CLI commands in this window.

Create the models

Create a folder called models inside the ClientApp\src\app folder. Now we will create a file availablelanguage.ts in the models folder. Put the following code in it.

export class AvailableLanguage {
languageID: string;
languageName: string;
}

Similarly, create another file inside the models folder called translationresult.ts. Put the following code in it.

export class TranslationResult {
detectedLanguage: string;
translationOutput: string;
}

You can observe that both these classes have same definition as the DTO classes we created on the server side. This will allow us to bind the data returned from the server directly to our models.

Create the User Service

We will create an Angular service which will invoke the Web API endpoints, convert the Web API response to JSON and pass it to our component. Run the following command.

ng g s services\Translator

This command will create a folder name as services and then create the following two files inside it.

  • translator.service.ts — the service class file.
  • translator.service.spec.ts — the unit test file for service.

Open translator.service.ts file and put the following code inside it.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class TranslatorService {
baseURL: string;constructor(private http: HttpClient) {
this.baseURL = '/api/Translation';
}
getAvailableLanguage() {
return this.http.get(this.baseURL)
.pipe(response => {
return response;
});
}
getTransaltedText(textToTranslate: string, targetLanguage: string) {
return this.http.post(this.baseURL + `/${textToTranslate}/${targetLanguage}`, {})
.pipe(response => {
return response;
});
}
}

We have defined a variable baseURL which will hold the endpoint URL of our API. We will initialize the baseURL in the constructor and set it to the endpoint of the TranslationController.

The getAvailableLanguage method will send a Get request to the GetAvailableLanguages method of the TranslationController to fetch the list of supported languages for translation.

The getTransaltedText method will send a Post request to the TranslationController and supply textToTranslate and targetLanguage as the parameter. It will fetch the translated text and the language detected for the text to translate.

Create the TextTranslator component

Run the following command in the command prompt to create the TextTranslatorComponent.

ng g c text-translator --module app

The--module flag will ensure that this component will get registered at app.module.ts. Open text-translator.component.html and put the following code in it.

<h3>Multilanguage translator using Microsoft Translator API Cognitive Service</h3>
<hr />
<div class="container">
<div class="row">
<div class="col-md-6">
<select class="form-control" [value]="translationResult?.detectedLanguage">
<option value="">--Select input language--</option>
<option *ngFor="let lang of availbleLanguage" value={{lang.languageID}}>
{{lang.languageName}}
</option>
</select>
<textarea placeholder="Enter text to translate" class="form-control translation-box" rows="5"
[(ngModel)]="inputText"></textarea>
</div>
<div class="col-md-6">
<select class="form-control" (change)="setTargetlanguage($event)">
<option value="">--Select target language--</option>
<option *ngFor="let lang of availbleLanguage" value={{lang.languageID}}>
{{lang.languageName}}
</option>
</select>
<textarea disabled class="form-control translation-box"
rows="5">{{translationResult?.translationOutput}}</textarea>
</div>
</div>
<div class="text-center">
<button [disabled]="loading" class="btn btn-primary btn-lg" (click)="GetTranslation()">
<span *ngIf="loading" class="spinner-border spinner-border-md mr-1"></span>Translate</button>
</div>
</div>

We have defined two dropdown lists one each for input language and the target language. Both dropdowns contain the list of available languages for translation. The Azure Translate Text API will detect the language of the input text. We will use the detected language to set the value of the input language drop down. The dropdown list for target language will invoke the setTargetlanguage method on selection change.

We have also defined two text areas, one each for the input text and the translated text. The text area for the input text will bind the value to the sting variable inputText. Whereas the text area for the translated text will be populated using the translationOutput property of the TranslationResult class.

Open text-translator.component.ts and put the following code in it.

import { Component, OnInit } from '@angular/core';
import { TranslatorService } from '../services/translator.service';
import { AvailableLanguage } from '../models/availablelanguage';
import { TranslationResult } from '../models/translationresult';
@Component({
selector: 'app-text-translator',
templateUrl: './text-translator.component.html',
styleUrls: ['./text-translator.component.css']
})
export class TextTranslatorComponent implements OnInit {
loading = false;
availbleLanguage: AvailableLanguage[];
outputLanguage: string;
inputText: string;
translationResult: TranslationResult;
constructor(private translatorService: TranslatorService) { }ngOnInit() {
this.translatorService.getAvailableLanguage().subscribe(
(result: AvailableLanguage[]) => this.availbleLanguage = result
);
}
GetTranslation() {
if (this.outputLanguage != null) {
this.loading = true;
this.translatorService.getTransaltedText(this.inputText, this.outputLanguage).subscribe
((result: TranslationResult) => {
this.translationResult = result;
this.loading = false;
});
}
}
setTargetlanguage(selectedItem) {
this.outputLanguage = selectedItem.target.value;
}
}

We are injecting the TranslatorService in the constructor of the TextTranslatorComponent. We will invoke the getAvailableLanguage method of our service in the ngOnInit and store the result in an array of type AvailableLanguage.

The GetTranslation method will invoke the getTransaltedText method of our service and bind the result to an object of type TranslationResult.

The setTargetlanguage method will set the outputLanguage to the value selected in the target language drop down.

We will add the styling for the textarea in text-translator.component.css as shown below.

.translation-box {
margin: 15px 0px;
}

Adding the links in Nav Menu

We will add the navigation links for our components in the nav menu. Open nav-menu.component.html and remove the links for Counter and Fetch data components. Add the following lines in the list of navigation links.

<li class="nav-item" [routerLinkActive]="['link-active']">
<a class="nav-link text-dark" routerLink='/text-translator'>Translator</a>
</li>

Execution Demo

Press F5 to launch the application. Click on the Translator link on the nav menu at the top. You can perform the multilanguage translation as shown in the image below.

Summary

We created a Translator Text Cognitive Services resource on Azure. We have used the Translator Text API to create a multilanguage translator using Angular. This translator supports transaltion for over 60 languages. We fetched the list of supported languages for translation from the global API endpoint for Translator Text.

See Also

--

--

Ankit Sharma

SDE III @cisco | GDE for Angular | Microsoft MVP | Author | Speaker | Passionate Programmer https://ankitsharmablogs.com/