Search code examples
javascriptregexarabic-support

Replace certain arabic words in text string using Javascript


I have a text string in arabic and i want to make some words Bold and add icons before the word

the method I am using for this for english text is

var wordsToBold = ["Properties", "How To Use"];

    function makeBold(input, wordsToBold) {
        return input.replace(new RegExp('(\\b)(' + wordsToBold.join('|') + ')(\\b)', 'ig'),
            '<br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i>$1<b>$2</b>$3');
    }

When i use this method with arabic words it does not working

var wordsToBold = ["الخصائص", "طريقة الاستعمال"];

A text for testing:

فرانكوا اراب الخصائص: لوريم ايبسوم دولار سيت أميت ,كونسيكتيتور أدايبا يسكينج أليايت,سيت دو أيوسمود تيمبور

أنكايديديونتيوت لابوري ات دولار ماجنا أليكيوا . طريقة الاستعمال: وت انيم أد مينيم فينايم,كيواس نوستريد

أكسير سيتاشن يللأمكو لابورأس


Solution

  • You can build your own Unicode word boundaries:

    1. Left-hand (leading) word boundary pattern can be defined as a position that is not immediately preceded with letter + any potential diacritics or a digit or an underscore: (?<!\p{L}\p{M}*|[\p{N}_])
    2. Right-hand (trailing) word boundary pattern can be defined as a position that is not immediately followed with a letter, digit or underscore: (?![\p{L}\p{N}_]).

    Thus, you can use

    var wordsToBold = ["Properties", "How To Use"];
    
    function makeBold(input, wordsToBold) {
        return input.replace(new RegExp('(?<!\\p{L}\\p{M}*|[\\p{N}_])(?:' + wordsToBold.join('|') + ')(?![\\p{L}\\p{N}_])', 'igu'),
            '<br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>$&</b>');
    }
    console.log(makeBold("How To Use These Properties: 00How To Use These Properties00", wordsToBold));
    // => <br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>How To Use</b> These <br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>Properties</b>: 00How To Use These Properties00
    var wordsToBold = ["الخصائص", "طريقة الاستعمال"];
    var arString = `فرانكوا اراب الخصائص: لوريم ايبسوم دولار سيت أميت ,كونسيكتيتور أدايبا يسكينج أليايت,سيت دو أيوسمود تيمبور
    
    أنكايديديونتيوت لابوري ات دولار ماجنا أليكيوا . طريقة الاستعمال: وت انيم أد مينيم فينايم,كيواس نوستريد
    
    أكسير سيتاشن يللأمكو لابورأس`;
    console.log(makeBold(arString, wordsToBold));
    // => فرانكوا اراب <br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>الخصائص</b>: لوريم ايبسوم دولار سيت أميت ,كونسيكتيتور أدايبا يسكينج أليايت,سيت دو أيوسمود تيمبور أنكايديديونتيوت لابوري ات دولار ماجنا أليكيوا . <br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>طريقة الاستعمال</b>: وت انيم أد مينيم فينايم,كيواس نوستريد أكسير سيتاشن يللأمكو لابورأس

    If you want a more generic Unicode-aware \b, you should keep in mind what a Unicode-aware \w actually matches ([\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]), and keeping in mind that \b can be written as (?:(?<=^)(?=\w)|(?<=\w)(?=$)|(?<=\W)(?=\w)|(?<=\w)(?=\W)), you can use the following:

    const w = String.raw`[\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]`;
    const nw = String.raw`[^\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]`;
    const uwb = String.raw`(?:(?<=^)(?=${w})|(?<=${w})(?=$)|(?<=${nw})(?=${w})|(?<=${w})(?=${nw}))`;
    console.log(uwb);

    The makeBold function will look like

    const w = String.raw`[\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]`;
    const nw = String.raw`[^\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]`;
    const uwb = String.raw`(?:(?<=^)(?=${w})|(?<=${w})(?=$)|(?<=${nw})(?=${w})|(?<=${w})(?=${nw}))`;
    
    function makeBold(input, wordsToBold) {
        return input.replace(new RegExp(`${uwb}(?:${wordsToBold.join('|')})${uwb}`, 'gu'),
            '<br><br><i class="fas fa-ellipsis-h fa-xs mr-2"></i><b>$&</b>');
    }
    
    // Test
    var wordsToBold = ["الخصائص", "طريقة الاستعمال"];
    var arString = `فرانكوا اراب الخصائص: لوريم ايبسوم دولار سيت أميت ,كونسيكتيتور أدايبا يسكينج أليايت,سيت دو أيوسمود تيمبور     أنكايديديونتيوت لابوري ات دولار ماجنا أليكيوا . طريقة الاستعمال: وت انيم أد مينيم فينايم,كيواس نوستريد     أكسير سيتاشن يللأمكو لابورأس`;
    console.log(makeBold(arString, wordsToBold));

    Please bear in mind the u flag that makes it possible to use Unicode category classes inside the ECMAScript 2018+ compliant RegExp patterns.