使翻译功能不再翻译结果

时间:2017-03-28 10:47:42

标签: javascript jquery regex

我制作了这个与Google翻译类似的翻译工具的简化版本。我们的想法是为瑞典的少数民族语言“jamska”构建这个简单的工具。该应用程序使用一个函数构建,该函数从textarea获取ID为#svenska的字符串,并使用RegExp替换字符串中的单词。

我创建了一个名为arr的数组,它在函数的for循环中用作字典。每个数组项都如下所示:var arr = [["eldröd", "eillrau"], ["oväder", "over"] ...]。每个数组项中的第一个单词是瑞典语,第二个单词是jamska。如果RegExp在循环中找到匹配的单词,则使用以下代码替换该单词:

function translate() {

var str = $("#svenska").val();
var newStr = "";
for (var i = 0; i < arr.length; i++) {
    var replace = arr[i][0];
    var replaceWith = arr[i][1];
    var re = new RegExp('(^|[^a-z0-9åäö])' + replace + '([^a-z0-9åäö]|$)', 'ig');
    str = str.replace(re, "$1" + replaceWith + '$2');
}

$("#jamska").val(str);

}

然后在translate() #svenska得到textarea时,在事件处理程序中调用keyup,如下所示:$("#svenska").keyup(function() { translate(); });

然后将翻译后的字符串指定为ID为textarea的另一个#jamska的值。到现在为止还挺好。

我有一个问题:如果jamska中的翻译单词也是瑞典语中的单词,那么该函数也会翻译该单词。发生此问题的原因是我使用:str将变量str = str.replace(re, "$1" + replaceWith + '$2');分配给同一变量的翻译版本。该函数反复使用相同的变量来执行转换。

示例: jamska中的瑞典单词“brydd”“fel”“邪恶”也是瑞典语中的一个词,所以我在翻译后得到的词是“felht”,因为瑞典语单词“fel”“felht”

有没有人知道如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

我建议您不要在输入中查找每个Jamska单词并将其替换为相应的翻译,而是建议在文本中找到任何单词([a-z0-9åäö]+),如果找到一个单词,则将其替换为翻译单词在字典中或其他方面:

//var arr = [["eldröd", "eillrau"], ["oväder", "over"] ...]
// I'd better use dictionary instead of array to define your dictionary 
var dict = {
    eldröd: "oväder",
    eillrau: "over"
    // ...
};
var str = "eldröd test eillrau eillrau oväder over";
var translated = str.replace(/[a-z0-9åäö]+/ig, function(m) {
    var word = m.toLowerCase();
    var trans = dict[word];
    return trans === undefined ? word : trans;
});
console.log(translated);

<强>更新

如果字典键可以用短语表示(即技术上显示为带空格的字符串),则应该扩展正则表达式以明确地包括所有这些短语。所以最终的正则表达式看起来像

(?:phrase 1|phrase 2|etc...)(?![a-z0-9åäö])|[a-z0-9åäö]+

它会尝试首先明确地匹配其中一个短语,然后才匹配单个单词。 (?![a-z0-9åäö]) lookbehind有助于过滤掉紧跟字母后面的短语(例如varken bättre eller sämreåäö)。

紧接着字母前面的短语被一个匹配是第一个(因此没有任何字母开头)的事实隐含地过滤掉,或者它不是第一个,因此前一个与当前分开空格。

//var arr = [["eldröd", "eillrau"], ["oväder", "over"] ...]
// I'd better use dictionary instead of array to define your dictionary 
var dict = {
    eldröd: "oväder",
    eillrau: "over",
    bättre: "better",
    "varken bättre eller sämre": "vär å int viller",
    "test test": "double test"
    // ...
};

var str = "eldröd test eillrau eillrau oväder over test test ";
str += "varken bättre eller sämre ";
str += "don't trans: varken bättre eller sämreåäö";
str += "don't trans again: åäövarken bättre eller sämre";

var phrases = Object.keys(dict)
    .filter(function(k) { return /\s/.test(k); })
    .sort(function(a, b) { return b.length - a.length; })
    .join('|');
var re = new RegExp('(?:' + phrases + ')(?![a-z0-9åäö])|[a-z0-9åäö]+', 'ig');

var translated = str.replace(re, function(m) {
    var word = m.toLowerCase();
    var trans = dict[word];
    return trans === undefined ? word : trans;
});
console.log(translated);