Translating Website Data Using Azure Translator API in ASP.NET MVC
                                        
                                    
                                
                                
                            
Translating Website Data Using Azure Translator API in ASP.NET MVC
In this article, we'll explore how to integrate Microsoft Azure Translator API into an ASP.NET MVC application to translate website text dynamically.
Prerequisites
- Azure Subscription with Translator Text API enabled.
- ASP.NET MVC application.
- Newtonsoft.Json package for JSON processing.
Code Explanation
The HomeController is responsible for handling the translation functionality. Let's break down each part of the code:
1. Setting up Azure Translator API Credentials
We define the API endpoint, subscription key, and region required to access the Azure Translator API.
private static readonly string TranslatorEndpoint = 
    "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0";
private static readonly string SubscriptionKey = "YOUR_AZURE_SUBSCRIPTION_KEY";
private static readonly string Region = "centralindia"; // Replace with your region
    
    Ensure that you replace YOUR_AZURE_SUBSCRIPTION_KEY with your actual Azure Translator API key.
2. Handling Language Culture
The OnActionExecuting method is overridden to set the current thread's culture based on the language parameter in the route.
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    string culture = (string)filterContext.RouteData.Values["lang"] ?? "en";
    Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
    base.OnActionExecuting(filterContext);
}
    
    This ensures that translations follow the selected culture throughout the application.
3. Translating Text using Azure Translator API
The TranslateTextAsync method sends a POST request to Azure Translator API with the text to be translated.
private async TaskTranslateTextAsync(string text, string targetLanguage = "es") { using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", SubscriptionKey); client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Region", Region); var requestBody = new[] { new { Text = text } }; string requestJson = JsonConvert.SerializeObject(requestBody); StringContent content = new StringContent(requestJson, Encoding.UTF8, "application/json"); HttpResponseMessage response = await client.PostAsync($"{TranslatorEndpoint}&to={targetLanguage}", content); response.EnsureSuccessStatusCode(); string responseJson = await response.Content.ReadAsStringAsync(); var translations = JsonConvert.DeserializeObject (responseJson); return translations[0].translations[0].text; } } public async Task<ActionResult> TranslatePage(string[] texts, string targetLanguage = "es") { using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", SubscriptionKey); client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Region", Region); var requestBody = texts.Select(text => new { Text = text }).ToArray(); string requestJson = JsonConvert.SerializeObject(requestBody); StringContent content = new StringContent(requestJson, Encoding.UTF8, "application/json"); HttpResponseMessage response = await client.PostAsync($"{TranslatorEndpoint}&to={targetLanguage}", content); response.EnsureSuccessStatusCode(); string responseJson = await response.Content.ReadAsStringAsync(); var translations = JsonConvert.DeserializeObject<dynamic>(responseJson); // Use a loop instead of LINQ List<string> translatedTexts = new List<string>(); foreach (var item in translations) { translatedTexts.Add((string)item.translations[0].text); } return Json(translatedTexts.ToArray(),JsonRequestBehavior.AllowGet); } } 
This method:
- Creates an HTTP client.
- Sets the necessary authentication headers.
- Serializes the text into JSON format.
- Sends a POST request to the Translator API.
- Parses the JSON response and extracts the translated text.
4. Calling Translation in the Index Action
In the Index action, we invoke TranslateTextAsync to translate the word "Contact" into Spanish.
public async TaskIndex() { var data = await TranslateTextAsync("Contact"); return View(); } 
5. Other Actions
The controller includes basic actions like About and Contact, which display static pages.
public ActionResult About()
{
    ViewBag.Message = "Your application description page.";
    return View();
}
public ActionResult Contact()
{
    ViewBag.Message = "Your contact page.";
    return View();
}
    
Now copy following code on your Layout view
@using TranslatePOC.Helpers
@{
    string currentLanguage = ViewContext.RouteData.Values["lang"]?.ToString() ?? "en";
    string currentUrl = HttpContext.Current.Request.RawUrl;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark bg-dark">
        <div class="container">
            @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            <button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" title="Toggle navigation" aria-controls="navbarSupportedContent"
                    aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse d-sm-inline-flex justify-content-between">
                <ul class="navbar-nav flex-grow-1">
                    <ul class="navbar-nav flex-grow-1">
                        @*<li>@Html.ActionLink(TranslatePOC.Resources.Resource.Home, "Index", "Home", new { area = "" }, new { @class = "nav-link" })</li>
        <li>@Html.ActionLink(TranslatePOC.Resources.Resource.About, "About", "Home", new { area = "" }, new { @class = "nav-link" })</li>
        <li>@Html.ActionLink(TranslatePOC.Resources.Resource.Contact, "Contact", "Home", new { area = "" }, new { @class = "nav-link" })</li>*@
                        <li>
                            @Html.ActionLinkWithDataTranslate("Home", "Index", "Home", "home_link", null, new { @class = "nav-link" })
                        </li>
                        <li>
                            @Html.ActionLinkWithDataTranslate("About", "About", "Home", "about_link", null, new { @class = "nav-link" })
                        </li>
                        <li>
                            @Html.ActionLinkWithDataTranslate("Contact", "Contact", "Home", "contact_link", null, new { @class = "nav-link" })
                        </li>
                    </ul>
                </ul>
                <div class="language-selector">
                    <label for="languageSelector" style="color:white !important" data-translate>Language:</label>
                    <select id="languageDropdown" onchange="changeLanguage(this.value)">
                        <option value="en" @(ViewContext.RouteData.Values["lang"]?.ToString() == "en" ? "selected" : "")>English</option>
                        <option value="es" @(ViewContext.RouteData.Values["lang"]?.ToString() == "es" ? "selected" : "")>Spanish</option>
                        <option value="he" @(ViewContext.RouteData.Values["lang"]?.ToString() == "he" ? "selected" : "")>Hebrew</option>
                    </select>
                </div>
            </div>
        </div>
    </nav>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>© @DateTime.Now.Year </p>
        </footer>
    </div>
    <script>
        function changeLanguage(selectedLanguage) {
            let currentUrl = window.location.pathname;
            // Check if the URL already includes a language code
            let regex = /^\/(en|es|he)/;
            if (regex.test(currentUrl)) {
                // Replace the language code in the URL
                currentUrl = currentUrl.replace(regex, `/${selectedLanguage}`);
            } else {
                // Add the language code to the URL
                currentUrl = `/${selectedLanguage}${currentUrl}`;
            }
            // Redirect to the updated URL
            window.location.href = currentUrl;
        }
    </script>
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    <script>
         $(document).ready(function () {
     debugger;
     var targetLanguage = $('#languageDropdown').val();
     // Collect all elements with `data-translate` attribute
     var elements = $('[data-translate]');
     var texts = elements.map(function () { return $(this).text(); }).get();
     // Send texts to server for translation
     $.post('/' + targetLanguage +'/Home/TranslatePage', { texts: texts, targetLanguage: targetLanguage }, function (response) {
         console.log(response)
         if (response) {
             // Update the DOM with translated texts
             elements.each(function (index) {
                 $(this).text(response[index]);
             });
         } else {
             alert('Error: ' + response.message);
         }
     });
 });
    </script>
    @RenderSection("scripts", required: false)
</body>
</html>
Copy following code on your Index.html add data-translate class on elements you want to translate
@{
    ViewBag.Title = "Home Page";
  
}
<main>
    <section class="row" aria-labelledby="aspnetTitle">
       
        <h1 id="title" data-translate>Welcome to Translate Demo</h1>
        <p class="lead" data-translate>ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
      <p><a href="https://asp.net" class="btn btn-primary btn-md" data-translate>Learn more »</a></p>
    </section>
  
</main>
<script>
    // JavaScript to handle language change
    document.getElementById("languageSelector").addEventListener("change", function () {
        window.location.href = this.value; // Redirect to selected language
    });
</script>
Conclusion
By implementing this approach, you can dynamically translate website content using Azure Translator API in your ASP.NET MVC application.
Next Steps:
- Extend the functionality to translate entire pages dynamically.
- Store translations in a database for faster retrieval.
- Allow users to select their preferred language.
