先交代下项目背景:项目为流程系统,项目架构并没有多语言版本设计,在项目中期,HR的妹子突然提需求说要做一个多语言版本。本来做这个最简单的方法是新开一个分支做成两个版本,但这个方案被经理枪毙了,两套代码不利于后期维护,更改了一个版本另一个很难更改。所以任务就落到了楼主头上。
简述完毕,下面进入正题,要做一个完全前端的翻译方案,基本思路就是查找替换方式,但是需面对以下一些难点:
1、如何查找出中文字符串,并且是完全匹配字符串还是只匹配中文字符串。
这个还是比较好解决的,我定义了两种自定义标签,一种叫“Translate”,使用精确打击的策略。对单独一个标签的值进行替换。这个可以对单独一个使用,完全匹配字符串的方式来翻译原文。
第二种叫“TranslatB”,使用大范围的模糊匹配的方式来翻译,只要在body处使用一次即可,采用循环遍历的方式,查找所有标签的叶子标签中的textcontent,对字符串翻译。
2、标点符号问题,由于中文跟英语语法上的问题,一句中文翻译后可能多出来一个“,”,“。”这样的符号。
这个问题要灵活应用了,如果是大段的文字,我的建议是使用方法一“Translate”标签,对字符串精确匹配完全替换,这样就不用考虑标点符号的问题了。部分短语使用了“TranslateB”,大范围替换方法,在“TranslateB”中我自动实现了将中文标点“,”,“。”替换为英文的‘,’,‘.’标点符号。
3、input标签的text类型的值到底要不要翻译。如果要翻译,切换回中文后是否要显示回中文,而不是英文。
对于input这样的标签,要想翻译而又不影响原来的功能,最方便的方法,是把原来的标签复制出来,更改name和ID属性,原来的input的type改为hidden。然后对新的input进行“Translat”。这样就不影响原来的功能,也能在切换回中文时,输入框的值还是中文,保存翻译效果一致性。
4、脚本中的字符如何翻译,如alert conform等的提示。
在脚本中的文字翻译,并不像html标签一样有东西可以遍历。即使遍历的所达到的效果也不是很理想的。所有我采用自定义脚本方法的方式,采用字符串原型定义一个“Translat()”方法来达到翻译的目的。
以下在补充部分,在项目的开端可以判断浏览器语言版本,根据浏览器语言版本自动设置cookies。前端保存cookies使用cookies来确定脚本使用个语言版本。
以下是部分脚本代码,及示例。
var menuDict = [
{ Key: '工作区', Value: 'Work Area', Order: "1" },
{ Key: '待办任务', Value: 'To-Do Task', Order: "1" },
{ Key: '已办任务', Value: 'Completed Task', Order: "1" },
{ Key: '我发起的流程', Value: 'My Application', Order: "1" },
{ Key: '草稿箱', Value: 'Draft', Order: "1" },
{ Key: '代理设定', Value: 'Proxy Setting', Order: "1" },
{ Key: '发起流程', Value: 'Applications', Order: "1" },
{ Key: '欢迎', Value: 'Welcome', Order: "1" },
{ Key: '注销', Value: 'Logout', Order: "1" }
]
//html翻译,完全匹配才翻译,可添加Order排序查找翻译内容。
function TranslateA(languageDict) {
var language = $.cookie('language');
if (language == "English") {
if (languageDict == undefined) {
languageDict = dict;
}
//$("[placeholder]").each(function (k, v) {
// var Skey = $(v).attr("placeholder");
// var Tvalue = "";
// var myReg = /^[u4e00-u9fa5]+$/;//中文验证
// $.each(languageDict, function (a, b) {
// if (b.Key.indexOf(Skey) >= 0) {
// Tvalue = b.Value;
// return false;
// }
// })
// if (Tvalue != "") {
// $(v).attr("placeholder", Tvalue);
// }
//})
$("[Translate]").each(function (k, v) {
var Skey = v.textContent;
var Sorder = $(v).attr("Translate");
var Tvalue = v.textContent;
var myReg = /^[u4e00-u9fa5]+$/;//中文验证
$.each(languageDict, function (a, b) {
if (Sorder == "") {
if (b.Key == Skey) {
Tvalue = b.Value;
return false;
}
}
else {
if (b.Key == Skey && b.Order == Sorder) {
Tvalue = b.Value;
return false;
}
}
})
v.textContent = Tvalue;
})
$("[RegTranslate]").each(function (k, v) {
if (v.tagName == "INPUT") {//输入框的Value替换掉
var myReg = /^[u4e00-u9fa5]+$/;//中文验证
var Sval = v.value;
var TempVal = "";
var TempStr = "";
for (var i = 0; i < Sval.length; i++) {
if (myReg.test(Sval[i])) {
TempStr = TempStr + Sval[i];
}
else {
var isTanslate = false;
$.each(languageDict, function (a, b) {
if (b.Key == TempStr) {
TempVal = TempVal + b.Value;
TempStr = "";//还原临时字符串
isTanslate = true;
return false;
}
})
if (!isTanslate) {
TempVal = TempVal + TempStr;
TempVal = TempVal + Sval[i];
TempStr = "";//还原临时字符串
}
else {
TempVal = TempVal + Sval[i];
}
}
}
if (TempStr != "") {
var isTanslate = false;
$.each(languageDict, function (a, b) {
if (b.Key == TempStr) {
TempVal = TempVal + b.Value;
isTanslate = true;
TempStr = "";
}
})
if (!isTanslate) {
TempVal = TempVal + TempStr;
TempStr = "";
}
}
v.value = TempVal;
}
else {
var myReg = /^[u4e00-u9fa5]+$/;//中文验证
var Sval = v.textContent;
var TempVal = "";
var TempStr = "";
for (var i = 0; i < Sval.length; i++) {
if (myReg.test(Sval[i])) {
TempStr = TempStr + Sval[i];
}
else {
var isTanslate = false;
$.each(languageDict, function (a, b) {
if (b.Key == TempStr) {
TempVal = TempVal + b.Value;
TempStr = "";//还原临时字符串
isTanslate = true;
return false;
}
})
if (!isTanslate) {
TempVal = TempVal + TempStr;
TempVal = TempVal + Sval[i];
TempStr = "";//还原临时字符串
}
else {
TempVal = TempVal + Sval[i];
}
}
}
if (TempStr != "") {
var isTanslate = false;
$.each(languageDict, function (a, b) {
if (b.Key == TempStr) {
TempVal = TempVal + b.Value;
isTanslate = true;
TempStr = "";
}
})
if (!isTanslate) {
TempVal = TempVal + TempStr;
TempStr = "";
}
}
v.textContent = TempVal;
}
})
$("[DeptTranslate]").each(function (k, v) {
if (v.tagName == "INPUT") {
var Sval = v.value;
if (Sval != "") {
$.ajax({
type: "post",
async: false,
url: '/Handle/PunchHandler.ashx',
data: { 'type': 'GetDeptNameEN', 'deptName': Sval },
dataType: "text",
error: function (result) {
console.log(v.value + '部门翻译失败');
},
success: function (result) {
if (result != "" && result != undefined) {
v.value = result;
}
}
});
}
}
})
}
}
function TranslateChine() {
$("[Translate]").each(function (k, v) {
var Skey = v.textContent;
var Sorder = $(v).attr("Translate");
var Tvalue = v.textContent;
var myReg = /^[u4e00-u9fa5]+$/;//中文验证
$.each(dict, function (a, b) {
if (Sorder == "") {
if (b.Value.indexOf(Skey) >= 0) {
Tvalue = b.Key;
return false;
}
}
else {
if (b.Value.indexOf(Skey) >= 0 && b.Order == Sorder) {
Tvalue = b.Key;
return false;
}
}
})
v.textContent = Tvalue;
})
$("[placeholder]").each(function (k, v) {
var Skey = $(v).attr("placeholder");
var Tvalue = v.textContent;
var myReg = /^[u4e00-u9fa5]+$/;//中文验证
$.each(dict, function (a, b) {
if (b.Value.indexOf(Skey) >= 0) {
Tvalue = b.Key;
return false;
}
})
$(v).attr("placeholder", Tvalue);
})
}
function TranslateB(lang) {
var language = $.cookie('language');
if (language == "English") {
$("[TranslateB]").each(function (k, v) {
TranslateVersion(v, lang);
})
}
}
//html翻译,递归遍历子元素方式(只匹配中文,不匹配标点符号、数字等符号,不能翻译字符保留不变)
function TranslateVersion(o, languageDict) {
if (languageDict == undefined) {
languageDict = dict;
}
$.each(o.childNodes, function (a, b) {
if (b.childNodes != undefined) {
if (b.childNodes.length == 0 ) {//最末节点没有子元素了
if (b.tagName == "INPUT" || b.tagName == "TEXTAREA" || b.tagName == "BUTTON") {//如果为Input元素则不翻译Value
if (b.tagName == "BUTTON") {
$.each(languageDict, function (a5, b5) {
if (b5.Key == b.textContent) {
b.textContent = b5.Value;
return false;
}
})
}
else {
if (b.type == "button") {
$.each(languageDict, function (a4, b4) {
if (b4.Key == b.value) {
b.value = b4.Value;
return false;
}
})
}
if (b.placeholder != undefined && b.placeholder != "") {
$.each(languageDict, function (a3, b3) {
if (b3.Key == b.placeholder) {
b.placeholder = b3.Value;
return false;
}
})
}
}
}
else {
var myReg = /^[u4e00-u9fa5]+$/;//中文验证
var TempVal = "";
var TempStr = "";
var Sval = "";
if (b.innerHTML == undefined) {//没有InnerHTML只有TextContent的元素。
Sval = b.textContent;
}
else {
Sval = b.innerHTML;
}
for (var i = 0; i < Sval.length; i++) {
if (myReg.test(Sval[i])) {
TempStr = TempStr + Sval[i];
}
else {
var isTanslate = false;
$.each(languageDict, function (a1, b1) {
if (b1.Key == TempStr) {
TempVal = TempVal + b1.Value;
TempStr = "";//还原临时字符串
isTanslate = true;
return false;
}
})
if (!isTanslate) {
TempVal = TempVal + TempStr;
if (Sval[i] == ",") {//标点符号转换
TempVal = TempVal + ',';
}
else if (Sval[i] == "。") {
TempVal = TempVal + '.';
}
else {
TempVal = TempVal + Sval[i];
}
TempStr = "";//还原临时字符串
}
else {
TempVal = TempVal + Sval[i];
}
}
}
if (TempStr != "") {//处理最后一个字符串
var isTanslate = false;
$.each(languageDict, function (a2, b2) {
if (b2.Key == TempStr) {
TempVal = TempVal + b2.Value;
isTanslate = true;
TempStr = "";
return false;
}
})
if (!isTanslate) {
if (TempStr == ",") {//标点符号转换
TempVal = TempVal + ',';
}
else if (TempStr == "。") {
TempVal = TempVal + '.';
}
else {
TempVal = TempVal + TempStr;
}
TempStr = "";
}
}
if (b.innerHTML == undefined) {
b.textContent = TempVal;
}
else {
b.innerHTML = TempVal;//更换
}
}
}
else {
TranslateVersion(b, languageDict);//递归
}
}
})
}
//脚本字符串翻译(只匹配中文,不匹配标点符号、数字等符号,不能翻译字符保留不变)
String.prototype.Translate = function (Sorder) {
var me = this;
if (me != undefined) {
var language = $.cookie('language');
if (language == "English") {
var myReg = /^[u4e00-u9fa5]+$/;//中文字符验证(不包括标点符号、数字、特殊字符)
var TempVal = "";
var TempStr = "";
var Sval = me.toString();
for (var i = 0; i < Sval.length; i++) {
if (myReg.test(Sval[i])) {
TempStr = TempStr + Sval[i];
}
else {
var isTanslate = false;
$.each(dict, function (a1, b1) {
if (b1.Key == TempStr) {
TempVal = TempVal + b1.Value;
TempStr = "";//还原临时字符串
isTanslate = true;
return false;
}
})
if (!isTanslate) {
TempVal = TempVal + TempStr;
if (Sval[i] == ",") {//标点符号转换
TempVal = TempVal + ',';
}
else if (Sval[i] == "。") {
TempVal = TempVal + '.';
}
else {
TempVal = TempVal + Sval[i];
}
TempStr = "";//还原临时字符串
}
else {
if (Sval[i] == ",") {//标点符号转换
TempVal = TempVal + ',';
}
else if (Sval[i] == "。") {
TempVal = TempVal + '.';
}
else {
TempVal = TempVal + Sval[i];
}
}
}
}
if (TempStr != "") {//处理最后一个字符串
var isTanslate = false;
$.each(dict, function (a2, b2) {
if (b2.Key == TempStr) {
TempVal = TempVal + b2.Value;
isTanslate = true;
TempStr = "";
return false;
}
})
if (!isTanslate) {
if (TempStr == ",") {//标点符号转换
TempVal = TempVal + ',';
}
else if (TempStr == "。") {
TempVal = TempVal + '.';
}
else {
TempVal = TempVal + TempStr;
}
TempStr = "";
}
}
return TempVal;
}
else {
return me.toString();
}
}
}
String.prototype.TranslateAll = function (Sorder) {
var me = this;
if (me != undefined) {
var language = $.cookie('language');
if (language == "English") {
var TempVal = "";
var TempStr = "";
var Sval = me.toString();
$.each(dict, function (a1, b1) {
if (b1.Key == Sval) {
TempVal = b1.Value;
isTanslate = true;
return false;
}
})
return TempVal;
}
else {
return me.toString();
}
}
}