基于jQuery及腾讯NLP AI平台的Laravel多语言站点实践

一. 简介

作为一个兼职码农,最近尝试了自己的一个站点的多语言化。发现Laravel本身的locale设定(通过message或者json)适合静态内容,对于文章等动态内容的多语言化还不能满足。因此尝试了通过jQuery结合NLP平台来实现动态内容翻译,已经基本实现功能。

二. Laravel部分

1) 在.env中设定默认语言和语言前缀

APP_LOCALE=en
APP_LOCAL_PREFIX=

APP_LOCAL_PREFIX用于设置URL的默认语言前缀,如果对于默认语言,不希望有语言前缀,可以设置为空。

2)新建一个处理locale的middleware,并完成注册。

public function handle(Request $request, Closure $next)
{

    $locale=in_array($request->segment(1),['en','zh','jp','fr','de','kr'])?  $request->segment(1):env('APP_LOCALE');

    //Set locale
    app()->setLocale($locale);
    //Use session to store the prefix

    if($locale===env('APP_LOCALE') and env('APP_LOCAL_PREFIX')=="")
        session(['locale_prefix' => '']);
    else
        session(['locale_prefix' => $locale]);
    return $next($request);
}

session('locale_prefix')可以用来在链接的URL中动态增加prefix。

3)完成Route更新

  Route::group([ 'middleware' => 'setlocale'], function() {
        Route::get('/', function () {
            return view('welcome');
        });
  });

  Route::group(['prefix' => '{locale}', 'middleware' => 'setlocale'], function() {
        Route::any('/', function(){
            return view('welcome');
        });
        Route::any('/en', 'GMA\WebController@index')->name('home');
  });

对于默认语言,如果不希望有prefix,则Route需要对于有prefix和没有prefix两种逻辑分别处理。如果对于默认语言也需要prefix,则仅需保留第二个Route Group。

4)NLP API,这里采用腾讯AI平台,代码不再赘述,Route设置路径是/api/nlp

三. jQuery部分

var transObjects = $("[id^='trans']");
var text_array=new Array(transObjects.length);
for(let i=0;i<transObjects.length;i++){
    text_array[i]=new Array();
    //Clean each jQuery childNode's HTML data and collect the text into an array
    getNodeText(transObjects[i],text_array[i]);
    text_array[i]=text_array[i].join("\n");
}

// Join text from different divs into one string
var srcText = text_array.join('\n\n');
var transData={
    'source'     : source_lang,
    'target'     : target_lang,
    'text'       : srcText,
}
//Use Ajax to get translated text via Tencent AI Platform
var getTrans=$.ajax({
    type: 'POST',
    url: '/api/nlp',
    data: transData,
    success: function(data){
        //split into contents for div
        let responseText=data.data.target_text
        text_array=responseText.split('\n\n')
        //Processing each div
        for(let i=0;i<transObjects.length;i++){
            //split translated text into different jQuery childNodes
            text_array[i]=text_array[i].split('\n');
            updateNodeText(transObjects[i],text_array[i]);
        }
     },
    dataType: 'json',
});

//Covert all jQuery childNodes' text to array
function getNodeText(TransObj,text_array){
    for(let i=0;i<TransObj.childNodes.length;i++){
        if(TransObj.childNodes[i].childNodes.length>0){
            getNodeText(TransObj.childNodes[i],text_array);
        }
        else{
            if(TransObj.childNodes[i].nodeName==="#text"){
                let parsedText=delExtraSpaces(delNewlines(TransObj.childNodes[i].data))if(parsedText!==""  && parsedText!==" ") text_array.push(parsedText);
            } 
        }
    }
}

//Update jQuery childNodes with translated text
function updateNodeText(TransObj,text_array){
    for(let i=0;i<TransObj.childNodes.length;i++)
{
        if(TransObj.childNodes[i].childNodes.length>0){
            updateNodeText(TransObj.childNodes[i],text_array);
        }
       else{
           if(TransObj.childNodes[i].nodeName==="#text"){
                let parsedText=delExtraSpaces(delNewlines(TransObj.childNodes[i].data)).trim();
                let sentenseEnd=['.','。','?','!'];
                if(parsedText!=="" && parsedText!==" "){
                if(text_array[0]!==undefined){
                    //check the last character of string, remove the . introduced by new line
                    if(!sentenseEnd.includes(parsedText.charAt(parsedText.length-1)) && 
                        sentenseEnd.includes(text_array[0].charAt(text_array[0].length-1)) ){
                        text_array[0]=" "+text_array[0].substring(0,text_array[0].length-2)+parsedText.charAt(parsedText.length-1)+" ";
                    }
                    TransObj.childNodes[i].data=" "+text_array[0];
                    } 
                    text_array.shift();
                } 
            } 
        }
    }
}

//Remove all new line breaks
function delNewlines(nodeText){
    if(nodeText.includes('\n')){
        return delNewlines(nodeText.replace('\n',''));
    }
    return nodeText;
}
//Remove extra white spaces
function delExtraSpaces(nodeText){
    if(nodeText.includes('  ')){
        return delExtraSpaces(nodeText.replace('  ',' '));
    }
    return nodeText;
}

基本原理是通过jQuery获取所有childNodes的内容,对于其中的文本内容进行预处理(删除多余的空格和所有换行符),然后用换行符作为拼接各个childNode内容的分隔符。拼接成一段文字后,通过ajax提交给NLP API翻译,获取翻译内容后再用换行符分隔各个childNodes,然后更新内容。

四. 完整代码

完成代码见Github

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!