JavaScript动态删除阿拉伯文本的变音符号

17
如何动态地去除阿拉伯语音符号?我正在设计一本包含多个阿拉伯文本的电子书“chm”。但有时搜索引擎会突出显示某些带有音符的阿拉伯单词。因此,在页面加载时是否可以使用JavaScript函数来剥离阿拉伯文本中的音符?但必须有启用选项,以便我不想永久从HTML中删除它,而是临时删除。
问题在于,我不知道从何处开始以及使用哪个正确的函数。
谢谢 :)
例如:
Text : الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ
converted to : الحمد لله رب العالمين 
8个回答

15

我编写了这个函数,处理包含混合阿拉伯语和英语字符的字符串,删除特殊字符(包括音标)并规范化一些阿拉伯字符,例如将所有的 ة 转换为 ه。

normalize_text = function(text) {

  //remove special characters
  text = text.replace(/([^\u0621-\u063A\u0641-\u064A\u0660-\u0669a-zA-Z 0-9])/g, '');

  //normalize Arabic
  text = text.replace(/(آ|إ|أ)/g, 'ا');
  text = text.replace(/(ة)/g, 'ه');
  text = text.replace(/(ئ|ؤ)/g, 'ء')
  text = text.replace(/(ى)/g, 'ي');

  //convert arabic numerals to english counterparts.
  var starter = 0x660;
  for (var i = 0; i < 10; i++) {
    text.replace(String.fromCharCode(starter + i), String.fromCharCode(48 + i));
  }

  return text;
}
<input value="الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ" type="text" id="input">
<button onclick="document.getElementById('input').value = normalize_text(document.getElementById('input').value)">Normalize</button>


非常好...只是要注意,ى不是ي,应该是ا,它被称为الألف المقصورة。 - Khalid Almannai
1
在比较文本是否相等时,包含一些误判的情况可能比错过一个真正匹配的情况更有益。例如,在搜索功能中,你可能希望将原始文本中的"على"与搜索词"علي"进行匹配,以防原始文本存在拼写错误,或者按照埃及的书写方式,有时会省略字母"ي"的点。这就是答案中规范化部分的最初原因。 - Rashad Saleh

9

试试这个

Text : الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ
converted to : الحمد لله رب العالمين 

http://www.suhailkaleem.com/2009/08/26/remove-diacritics-from-arabic-text-quran/

这段代码是用C#编写的,而不是javascript。仍在尝试如何在javascript中实现它。

编辑:显然,在javascript中很容易实现。 这些变音符号被存储为单独的“字母”,可以很容易地去除它们。

var CHARCODE_SHADDA = 1617;
var CHARCODE_SUKOON = 1618;
var CHARCODE_SUPERSCRIPT_ALIF = 1648;
var CHARCODE_TATWEEL = 1600;
var CHARCODE_ALIF = 1575;

function isCharTashkeel(letter)
{
    if (typeof(letter) == "undefined" || letter == null)
        return false;

    var code = letter.charCodeAt(0);
    //1648 - superscript alif
    //1619 - madd: ~
    return (code == CHARCODE_TATWEEL || code == CHARCODE_SUPERSCRIPT_ALIF || code >= 1612 && code <= 1631); //tashkeel
}

function stripTashkeel(input)
{
  var output = "";
  //todo consider using a stringbuilder to improve performance
  for (var i = 0; i < input.length; i++)
  {
    var letter = input.charAt(i);
    if (!isCharTashkeel(letter)) //tashkeel
      output += letter;                                
  }


return output;                   
}

编辑:这里还有一种使用BuckData的方法:http://qurandev.github.com/

优势 Buck使用更少的带宽。在Javascript中,您可以一次性搜索整个Buck古兰经文本。相对于阿拉伯语搜索,直观易懂。将Buck转换为阿拉伯语或阿拉伯语转换为Buck只需一个简单的js调用。在此处尝试实时样本:http://jsfiddle.net/BrxJP/ 您可以在几毫秒内从Buck文本中去除所有元音。 为什么这样做?您可以在JavaScript中进行搜索,忽略taskheel差异(Fathah,Dammah,Kasrah)。这导致命中率更高。正则表达式+buck文本可以导致令人惊奇的优化。所有搜索都可以在本地运行。http://qurandev.appspot.com 数据是如何生成的?只需使用一对一映射即可:http://corpus.quran.com/java/buckwalter.jsp


Sameer这只适用于《古兰经》还是所有阿拉伯文本都适用? - abbood
abbood我认为它适用于所有阿拉伯文本。 - Sameer Alibhai

4
这里有一段 JavaScript 代码,可以几乎总是处理删除阿拉伯语变音符号的问题。
var arabicNormChar = {
    'ك': 'ک', 'ﻷ': 'لا', 'ؤ': 'و', 'ى': 'ی', 'ي': 'ی', 'ئ': 'ی', 'أ': 'ا', 'إ': 'ا', 'آ': 'ا', 'ٱ': 'ا', 'ٳ': 'ا', 'ة': 'ه', 'ء': '', 'ِ': '', 'ْ': '', 'ُ': '', 'َ': '', 'ّ': '', 'ٍ': '', 'ً': '', 'ٌ': '', 'ٓ': '', 'ٰ': '', 'ٔ': '', '�': ''
}

var simplifyArabic  = function (str) {
    return str.replace(/[^\u0000-\u007E]/g, function(a){ 
        var retval = arabicNormChar[a]
        if (retval == undefined) {retval = a}
        return retval; 
    }).normalize('NFKD').toLowerCase();
}

//now you can use simplifyArabic(str) on Arabic strings to remove the diacritics

注意:您可以根据自己的喜好覆盖arabicNormChar。

2

使用这个正则表达式来匹配所有的阿拉伯语符号

[ؐ-ًؚٟ]


1
我尝试了以下解决方案,它可以正常工作:

const str = 'الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ';
const withoutDiacs = str.replace(/([^\u0621-\u063A\u0641-\u064A\u0660-\u0669a-zA-Z 0-9])/g, '');
console.log(withoutDiacs); //الحمد لله رب العالمين

Reference: https://www.overdoe.com/javascript/2020/06/18/arabic-diacritics.html


我在C#中使用了这个正则表达式,但是它并不正确,因为它从句子中删除了 ی。例如,对于这个阿亚 'بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِیمِ' 返回的结果是 بسم الله الرحمن الرحم - Sayed Abolfazl Fatemi

0
一个更简短的方法来去除阿拉伯语变音符号(无论是8个基本变音符号还是完整的52个变音符号)可以如下所示:
去除基本变音符号

function removeTashkeelBasic(s) {return s.replace(/[ً-ْ]/g,'');}



//===================
//     Test Cases
//===================
console.log(removeTashkeelBasic('حِسَابٌ وَحِسَابًا مِنْ ثَلَاثُمِئَةِ رِيَالٍ قَطَرِيٍّ'));
console.log(removeTashkeelBasic('بِسْمِ ٱللَّٰهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ'));

去除所有阿拉伯语变音符号

function removeTashkeelAll(s) {return s.replace(/[ؐ-ًؕ-ٖٓ-ٟۖ-ٰٰۭ]/g,'');}


//===================
//     Test Cases
//===================
console.log(removeTashkeelAll('حِسَابٌ وَحِسَابًا مِنْ ثَلَاثُمِئَةِ رِيَالٍ قَطَرِيٍّ'));
console.log(removeTashkeelAll('بِسْمِ ٱللَّٰهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ'));


0

这个网站有一些用于Javascript Unicode规范化的例程,可以用来实现你所尝试的功能。如果没有其他办法,它也可以提供一个很好的起点。

如果你能预处理数据,Python有很好的Unicode例程,可以轻松完成这些转换。如果你能预处理CHM文件以生成一个单独的索引文件,然后将其合并到CHM中,这可能是一个不错的选择:

import unicodedata

def _strip(text):
    return ''.join([c for c in unicodedata.normalize('NFD', text) \
        if unicodedata.category(c) != 'Mn'])

composed = u'\xcd\xf1\u0163\u0115\u0155\u0148\u0101\u0163\u0129\u014d' \
    u'\u0146\u0105\u013c\u012d\u017e\u0119'

_strip(composed)
'Internationalize'

0

这里是另一种基于阿拉伯语Unicode块的方法:

const map = {
  'آ': 'ا',
  'أ': 'ا',
  'إ': 'ا',
  'ا': 'ا',
  'ٱ': 'ا',
  'ٲ': 'ا',
  'ٳ': 'ا',
  'ؤ': 'و',
  'ئ': 'ى',
  'ؽ': 'ؽ',
  'ؾ': 'ؾ',
  'ؿ': 'ؿ',
  'ي': 'ى',
  'ب': 'ب',
  'ت': 'ت',
  'ؠ': 'ؠ',
  'ة': 'ه',
  'ث': 'ث',
  'ج': 'ج',
  'ح': 'ح',
  'خ': 'خ',
  'د': 'د',
  'ذ': 'ذ',
  'ر': 'ر',
  'ز': 'ز',
  'س': 'س',
  'ش': 'ش',
  'ص': 'ص',
  'ض': 'ض',
  'ط': 'ط',
  'ظ': 'ظ',
  'ع': 'ع',
  'غ': 'غ',
  'ػ': 'ک',
  'ؼ': 'ک',
  'ف': 'ف',
  'ق': 'ق',
  'ك': 'ك',
  'ګ': 'ك',
  'ڬ': 'ك',
  'ڭ': 'ڭ',
  'ڮ': 'ك',
  'ل': 'ل',
  'م': 'م',
  'ن': 'ن',
  'ه': 'ه',
  'و': 'و',
  'ى': 'ى',
  'ٸ': 'ى',
  'ٵ': 'ءا', // hamza alef?
  'ٶ': 'ءو', // hamza waw?
  'ٹ': 'ٹ',
  'ٺ': 'ٺ',
  'ٻ': 'ٻ',
  'ټ': 'ت',
  'ٽ': 'ت',
  'پ': 'پ',
  'ٿ': 'ٿ',
  'ڀ': 'ڀ',
  'ځ': 'ءح',
  'ڂ': 'ح',
  'ڃ': 'ڃ',
  'ڄ': 'ڄ',
  'څ': 'ح',
  'چ': 'چ',
  'ڇ': 'ڇ',
  'ڈ': 'ڈ',
  'ډ': 'د',
  'ڊ': 'د',
  'ڋ': 'د',
  'ڌ': 'ڌ',
  'ڍ': 'ڍ',
  'ڎ': 'ڎ',
  'ڏ': 'د',
  'ڐ': 'د',
  'ڑ': 'ڑ',
  'ڒ': 'ر',
  'ړ': 'ر',
  'ڔ': 'ر',
  'ڕ': 'ر',
  'ږ': 'ر',
  'ڗ': 'ر',
  'ژ': 'ژ',
  'ڙ': 'ڙ',
  'ښ': 'س',
  'ڛ': 'س',
  'ڜ': 'س',
  'ڝ': 'ص',
  'ڞ': 'ص',
  'ڟ': 'ط',
  'ڠ': 'ع',
  'ڡ': 'ڡ',
  'ڢ': 'ڡ',
  'ڣ': 'ڡ',
  'ڤ': 'ڤ',
  'ڥ': 'ڡ',
  'ڦ': 'ڦ',
  'ڧ': 'ق',
  'ڨ': 'ق',
  'ک': 'ک',
  'ڪ': 'ڪ',
  'گ': 'گ',
  'ڰ': 'گ',
  'ڱ': 'ڱ',
  'ڲ': 'گ',
  'ڳ': 'ڳ',
  'ڴ': 'گ',
  'ڵ': 'ل',
  'ڶ': 'ل',
  'ڷ': 'ل',
  'ڸ': 'ل',
  'ڹ': 'ن',
  'ں': 'ں',
  'ڻ': 'ڻ',
  'ڼ': 'ن',
  'ڽ': 'ن',
  'ھ': 'ه',
  'ڿ': 'چ',
  'ۀ': 'ه',
  'ہ': 'ہ',
  'ۂ': 'ءہ',
  'ۃ': 'ہ',
  'ۄ': 'و',
  'ۅ': 'ۅ',
  'ۆ': 'ۆ',
  'ۇ': 'ۇ',
  'ۈ': 'ۈ',
  'ۉ': 'ۉ',
  'ۊ': 'و',
  'ۋ': 'ۋ',
  'ی': 'ی',
  'ۍ': 'ي',
  'ێ': 'ي',
  'ۏ': 'و',
  'ې': 'ې',
  'ۑ': 'ي',
  'ے': 'ے',
  'ۓ': 'ے',
  'ە': 'ە',
  'ۺ': 'ش',
  'ۻ': 'ض',
  'ۼ': 'ۼ',
  'ۿ': 'ه'
}

function removeDiacritics(text) {
  const symbols = [...text]
  const result = []
  for (const symbol of symbols) {
    if (map[symbol]) {
      result.push(symbol)
    }
  }
  return result.join('')
}

有些字母仍然可以被认为是带有变音符号的,比如ژ“jeh”,它看起来像ر“reh”。但由于在阿拉伯语中它有一个不同的基本名称,我让它不会被剥离其“额外标记”而变成“reh”。这在一些情况下发生了,比如ڡ“feh”和ڢ“下点feh”,但ڤڦ被赋予了基本名称,但例如ڥ没有。不确定最好的方法是什么。我不知道什么是变音符号,什么不是100%的定义,但这应该是一个很好的开始。

此外,“hamza + letter”连字被转换为独立的hamza和字母。

如果您知道如何改进此内容,请评论并添加修复。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接