文本匹配不工作的阿拉伯语问题可能是由于阿拉伯语的正则表达式



我一直在努力为我的多语言网站添加一个功能,在那里我必须突出显示匹配的标签关键字。

此功能适用于英文版本,但不适用于阿拉伯语版本。

我已经在JSFiddle上设置了示例

示例代码
    function HighlightKeywords(keywords)
    {        
        var el = $("#article-detail-desc");
        var language = "ar-AE";
        var pid = 32;
        var issueID = 18; 
        $(keywords).each(function()
        {
           // var pattern = new RegExp("("+this+")", ["gi"]); //breaks html
            var pattern = new RegExp("(\b"+this+"\b)(?![^<]*?>)", ["gi"]); //looks for match outside html tags
            var rs = "<a class='ad-keyword-selected' href='http://www.alshindagah.com/ar/search.aspx?Language="+language+"&PageId="+pid+"&issue="+issueID+"&search=$1' title='Seach website for:  $1'><span style='color:#990044; tex-decoration:none;'>$1</span></a>";
            el.html(el.html().replace(pattern, rs));
        });
    }   
HighlightKeywords(["you","الهدف","طهران","سيما","حاليا","Hello","34","english"]);
//Popup Tooltip for article keywords
     $(function() {
        $("#article-detail-desc").tooltip({
        position: {
            my: "center bottom-20",
            at: "center top",
            using: function( position, feedback ) {
            $( this ).css( position );
            $( "<div>" )
            .addClass( "arrow" )
            .addClass( feedback.vertical )
            .addClass( feedback.horizontal )
            .appendTo( this );
        }
        }
        });
    });

我将关键字存储在数组&然后将它们与特定div中的文本进行匹配。

我不确定问题是由于Unicode或什么。感谢您在这方面的帮助。

这个答案有三个部分

  1. 为什么不工作

  2. 一个关于如何用英语接近它的例子(意味着由对阿拉伯语有所了解的人改编成阿拉伯语)

  3. 一个对阿拉伯语一无所知的人(我)尝试做阿拉伯语版本:-)

为什么不工作

至少部分问题在于您依赖于b断言,该断言(与其对应的BwW一样)是以英语为中心的。在其他语言中你不能依赖它(甚至,实际上,在英语中——见下文)。

规范中b的定义如下:

生产断言:: b通过返回一个内部AssertionTester闭包来求值,该闭包接受State参数x,并执行以下操作:

  • exendIndex
  • 调用IsWordChar(e–1),让a作为Boolean的结果。
  • 调用IsWordChar(e),设bBoolean的结果。
  • 如果atrue, bfalse,则返回true
  • 如果afalse, btrue,则返回true
  • 返回false .

…其中IsWordChar被进一步定义为以下63个字符中的一个:

a b b b b b b b b b b b b b b b b b b b b b b b b bA, b, c, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I0 1 2 3 4 5 6 7 8 9 _ 

。英文字母a ~ z的大小写,数字0 ~ 9_的大小写。(这意味着您甚至不能依赖b, B, wW的英文,因为English有外来词,如"Voilà",但那是另一个故事。)

第一个使用英语的例子

您必须使用不同的机制来检测阿拉伯语中的单词边界。如果你能想出一个字符类包含所有的阿拉伯码点;(Unicode的说法)组成单词,您可以使用类似这样的代码:

var keywords = {
    "laboris": true,
    "laborum": true,
    "pariatur": true
    // ...and so on...
};
var text = /*... get the text to work on... */;
text = text.replace(
    /([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]+)([^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]+)?/g,
    replacer);
function replacer(m, c0, c1) {
    if (keywords[c0]) {
        c0 = '<a href="#">' + c0 + '</a>';
    }
    return c0 + c1;
}

注释:

  • 我使用类[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]来表示"单词字符"。显然,你必须(显著地)改变这个阿拉伯语。
  • 我使用类[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]来表示"非单词字符"。这与前面的类在开始时具有否定(^)相同。
  • 正则表达式查找任意一系列的"单词字符"。后面跟着一个可选的非单词字符系列,对两者都使用捕获组((...))。
  • String#replace调用replacer函数,将匹配的全文后跟每个捕获组作为参数。
  • replacer函数查找keywords映射中的第一个捕获组(单词),以查看它是否是关键字。如果是,它会将其包装在锚中。
  • replacer函数返回可能被换行的单词以及后面的非单词文本。
  • String#replace使用replacer的返回值替换匹配的文本。

这里有一个完整的例子:Live Copy | Live Source

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Replacing Keywords</title>
</head>
<body>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  
  <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
  <script>
    (function() {
      // Our keywords. There are lots of ways you can produce
      // this map, here I've just done it literally
      var keywords = {
        "laboris": true,
        "laborum": true,
        "pariatur": true
      };
      
      // Loop through all our paragraphs (okay, so we only have one)
      $("p").each(function() {
        var $this, text;
        
        // We'll use jQuery on `this` more than once,
        // so grab the wrapper
        $this = $(this);
        
        // Get the text of the paragraph
        // Note that this strips off HTML tags, a
        // real-world solution might need to loop
        // through the text nodes rather than act
        // on the full text all at once
        text = $this.text();
        // Do the replacements
        // These character classes match JavaScript's
        // definition of a "word" character and so are
        // English-centric, obviously you'd change that
        text = text.replace(
          /([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]+)([^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]+)?/g,
          replacer);
        
        // Update the paragraph
        $this.html(text);
      });
      // Our replacer. We define it separately rather than
      // inline because we use it more than once      
      function replacer(m, c0, c1) {
        // Is the word in our keywords map?
        if (keywords[c0]) {
          // Yes, wrap it
          c0 = '<a href="#">' + c0 + '</a>';
        }
        return c0 + c1;
      }
    })();
  </script>
</body>
</html>

尝试用阿拉伯语

我试了试阿拉伯语版本。根据维基百科Unicode页面上的阿拉伯语脚本,使用了几个代码范围,但您示例中的所有文本都属于U+0600到U+06FF的主要范围。

这是我想到的:Fiddle(我更喜欢JSBin,我上面用的,但我不能让文本以正确的方式显示出来。)

(function() {
    // Our keywords. There are lots of ways you can produce
    // this map, here I've just done it literally
    var keywords = {
        "الهدف": true,
        "طهران": true,
        "سيما": true,
        "حاليا": true
    };
    
    // Loop through all our paragraphs (okay, so we only have two)
    $("p").each(function() {
        var $this, text;
        
        // We'll use jQuery on `this` more than once,
        // so grab the wrapper
        $this = $(this);
        
        // Get the text of the paragraph
        // Note that this strips off HTML tags, a
        // real-world solution might need to loop
        // through the text nodes rather than act
        // on the full text all at once
        text = $this.text();
        
        // Do the replacements
        // These character classes just use the primary
        // Arabic range of U+0600 to U+06FF, you may
        // need to add others.
        text = text.replace(
            /([u0600-u06ff]+)([^u0600-u06ff]+)?/g,
            replacer);
        
        // Update the paragraph
        $this.html(text);
    });
    
    // Our replacer. We define it separately rather than
    // inline because we use it more than once      
    function replacer(m, c0, c1) {
        // Is the word in our keywords map?
        if (keywords[c0]) {
            // Yes, wrap it
            c0 = '<a href="#">' + c0 + '</a>';
        }
        return c0 + c1;
    }
})();

我对上面的英语函数所做的就是:

  • 使用[u0600-u06ff]作为"文字字符"和[^u0600-u06ff]为"非单词字符"。您可能需要添加这里列出的一些其他范围(例如适当的数字样式),但是同样,示例中的所有文本都属于这些范围。
  • 将关键字从示例中更改为三个(其中只有两个似乎在文本中)。

对于我的非常非阿拉伯语阅读的眼睛来说,它似乎有效。

最新更新