基于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 协议》,转载必须注明作者和本文链接