Latest From My Blog

SharePoint: Translate page data using google translation service API

This post will explain how to translate SharePoint page content to any other language using Google translation services API. Google translation is a paid service. However, google also provides a free trial for 3 months. To get started, go to Google Translate API and start the  free trial. It will ask for your billing information. Provide your credit/debit card details. Once you accept the conditions and start a free trial an amount worth a single dollar is deducted from your account. 
Google translation requires creating a project with Google Developers Console. Moreover, billing needs to be enabled before the API can be used in your application. You can create a new project or use out of the box project created in the Developer console. 

Project

Click on the project -> Billing & Settings -> Enable Billing.
Since we will be using client side code (JavaScript/JQuery), we will need to generate a key which can be used in our application. Click on APIs & Auth -> Credentials -> Create New Key. Select Browser key. Here you can also choose to restrict which applications will use this key. This can be left blank during development phase. But it is highly recommended to make use of it during production. The reason is that the application key can be viewed using the page source and hence anyone can use it.

Create Key


The browser key generated will be used in our SharePoint application.

Browser Key

Now the SharePoint part. We will write JavaScript code to read the SharePoint page content and page title. The REST calls will be made to google api to get the data. Here is the documentation https://cloud.google.com/translate/v2/using_rest
A drop down list on the page will show all the available languages for the translation. Selecting a language in the drop down list will send the page content and title to translation API and get back the translated text. Finally, the page will be updated with translated text.
A SharePoint page layout should be created in order to make this reusable across all pages created from that layout instead of using the code in each page. In this post we will focus on the actual code for translation.
First we will read the page content and page title using JavaScript Client Object model JQuery Deferreds:
var retrievePageFieldValues = function () {
    var deferred = jQuery.Deferred();
    var context = new SP.ClientContext.get_current();
    var listId = _spPageContextInfo.pageListId;
    var itemId = _spPageContextInfo.pageItemId;
    var pagesList = context.get_web().get_lists().getById(listId);
    var page = pagesList.getItemById(itemId);
    context.load(page);
    context.executeQueryAsync(Function.createDelegate(this, function () { deferred.resolve(page); }), 
    Function.createDelegate(this, function (sender, args) { deferred.reject(sender, args); }));     
    return deferred.promise();
};
_spPageContextInfo will allow us to access the current page item ID and the current list ID. The page content is stored in PublishingPageContent field. The title and content can be read by calling the above function:
retrievePageFieldValues().then(
    function (page) {
        pageTitle = page.get_item('Title');
        pageContent = page.get_item('PublishingPageContent');                       
    },
    function (sender, args) {
        console.log('An error occurred while retrieving list item:' + args.get_message());
    }
);
The languages method of the google api gives the list of available languages. Following code shows how a call to this method can be used to build the drop down list:
var buildLanguageDropdownList = function () {
    jQuery.ajax({
        dataType: 'jsonp',                 
        url: "https://www.googleapis.com/language/translate/v2/languages",
        data:{ key: appKey, target: 'en' }
    })
    .done(function (response) {
        if(!response.error) {
            languageDropdownList.show();
            languageDropdownList.append('<option>Translate Section</option>');          
            var languages = response.data.languages;
            $.each(languages, function (index, language) {
                languageDropdownList.append('<option value="' + language.language + '">' + language.name + '</option>');
            })
        }
        else {
            console.log(response.error);
        }
    })
    .fail (function (qXHR, textStatus, errorThrown) {
        console.log(errorThrown);
    });
};
The GET request can be made to the api to translate the text. However, The URL for the GET, including parameters, must be less than 2K characters. 
Example of a GET request from the documentation:
https://www.googleapis.com/language/translate/v2?key=INSERT-YOUR-KEY&source=en&target=de&q=Hello%20world
Here "q" specifies the text which is to be translated. Multiple source texts can be sent for translation by specifying this parameter for each text. Example:
https://www.googleapis.com/language/translate/v2?key=INSERT-YOUR-KEY&source=en&target=de&q=Hello%20world&q=My%20name%20is%20Jeff
If the text is going to be longer than 2K, then a POST request can be made as described in the documentation:
Note: You can also use POST to invoke the API if you want to send more data in a single request. The q parameter in the POST body must be less than 5K characters. To use POST, you must use the X-HTTP-Method-Override header to tell the Translate API to treat the request as a GET (use X-HTTP-Method-Override: GET).
Now, in our case we will use POST and send text of the title and page content together in one call to the translation service.
var performTranslation = function (targetLanguage, pageContent, pageTitle) {
    jQuery.ajax({  
        type:"POST",
        headers: {"X-HTTP-Method-Override":"GET"},
        traditional: true,
        url: "https://www.googleapis.com/language/translate/v2",
        dataType: "jsonp",
        data: { key: appKey, target: targetLanguage, q: [pageContent, pageTitle] }
    })
    .done(function (response) {
        if(!response.error) {
            jQuery('.contentDiv').html(response.data.translations[0].translatedText);
            jQuery('.titleDiv').text(response.data.translations[1].translatedText);
        }
        else {
            console.log(response.error);
        }
    })
    .fail (function (qXHR, textStatus, errorThrown) {
        console.log(errorThrown);
    }); 
};
Observe, the use of traditional attribute in ajax call. This will allows us to specify both page content and page title in "q" parameter. If the request is successful, we update page content and title using JQuery. Here is the complete code:
<select style="display:none" id="availableLanguages"></select>
<script language="javascript">
var NY = window.NY || {};
NY.LocalLanguageTranslation = function() {

    // Google translation service key for browser applications
    var appKey = 'YourKeyHere';
    var pageTitle; 
    var pageContent;    
    var languageDropdownList = $("#availableLanguages");   
    var initialize = function () {
        retrievePageFieldValues().then(
            function (page) {
                pageTitle = page.get_item('Title');
                pageContent = page.get_item('PublishingPageContent');
                buildLanguageDropdownList();            
            },
            function (sender, args) {
                console.log('An error occurred while retrieving list item:' + args.get_message());
            }
        );
    };

    var retrievePageFieldValues = function () {
        var deferred = jQuery.Deferred();
        var context = new SP.ClientContext.get_current();
        var listId = _spPageContextInfo.pageListId;
        var itemId = _spPageContextInfo.pageItemId;
        var pagesList = context.get_web().get_lists().getById(listId);
        var page = pagesList.getItemById(itemId);
        context.load(page);
        context.executeQueryAsync(Function.createDelegate(this, function () { deferred.resolve(page); }), 
        Function.createDelegate(this, function (sender, args) { deferred.reject(sender, args); }));     
        return deferred.promise();
    };

    var buildLanguageDropdownList = function () {
        jQuery.ajax({
            dataType: 'jsonp',                 
            url: "https://www.googleapis.com/language/translate/v2/languages",
            data:{ key: appKey, target: 'en' }
        })
        .done(function (response) {
            if(!response.error) {
                languageDropdownList.show();
                languageDropdownList.append('<option>Translate Section</option>');          
                var languages = response.data.languages;
                $.each(languages, function (index, language) {
                    languageDropdownList.append('<option value="' + language.language + '">' + language.name + '</option>');
                })
            }
            else {
                console.log(response.error);
            }
        })
        .fail (function (qXHR, textStatus, errorThrown) {
            console.log(errorThrown);
        });
    };

    var performTranslation = function (targetLanguage, pageContent, pageTitle) {
        jQuery.ajax({  
            type:"POST",
            headers: {"X-HTTP-Method-Override":"GET"},
            traditional: true,
            url: "https://www.googleapis.com/language/translate/v2",
            dataType: "jsonp",
            data: { key: appKey, target: targetLanguage, q: [pageContent, pageTitle] }
        })
        .done(function (response) {
            if(!response.error) {
                jQuery('.contentDiv').html(response.data.translations[0].translatedText);
                jQuery('.titleDiv').text(response.data.translations[1].translatedText);
            }
            else {
                console.log(response.error);
            }
        })
        .fail (function (qXHR, textStatus, errorThrown) {
            console.log(errorThrown);
        }); 
    };

    languageDropdownList.change(function () {
        var targetLanguage = this.value; 
        if ( pageContent && pageTitle) {                           
            performTranslation(targetLanguage, pageContent, pageTitle); 
        }
        else {
            retrievePageFieldValues().then(
            function (page) {
                    pageTitle = page.get_item('Title');
                    pageContent = page.get_item('PublishingPageContent');       
                    performTranslation(targetLanguage, pageContent, pageTitle); 
                },
                function (sender, args) {
                    console.log('An error occured while retrieving list item:' + args.get_message());
                }
            );
        }
    });

    //public interface
    return {
        initialize: initialize      
    };
}();
</script>

<script language="javascript">
_spBodyOnLoadFunctionNames.push("NY.LocalLanguageTranslation.initialize");
</script>
Sample page having Title and Content in English:

English Language

Page translated to French language.

French Language





profile for Nadeem Yousuf at SharePoint Stack Exchange, Q&A for SharePoint enthusiasts

+