Azhar Muhammad
Azhar Muhammad

Reputation: 154

Only reverse the direction of consecutive Hebrew words in a string including non-Hebrew characters

I am trying to reverse a string containing Hebrew from RTL to LTR, but my coding attempt is reversing brackets as well. strrev() didn't work because it does not actually work for UTF8 strings. So I wrote a custom function, below is my code:

$str = 'תירס גדול A-10 (פרי גליל)';
function utf8_strrev($str)
{
    $arr = '';
    $words = explode(" ", $str);
    $start_tag = '(';
    $end_tag = ')';
    foreach ($words as $word)
    {
        if (preg_match("/\p{Hebrew}/u", $word))
        {
                preg_match_all('/./us', $word, $ar);
                echo print_r($ar[0]);
                echo '<br>';
                
                $arr = join('', array_reverse($ar[0])) . " " . $arr;
        } else
        {
            preg_match_all('/./us', $word, $ar);
            $arr = join('', $ar[0]) . " " . $arr;
        }
    }
    return $arr;
}

OUTPUT :

)לילג ירפ( A-10 לודג סרית 

what it should be:

(לילג ירפ) A-10 לודג סרית

Upvotes: 2

Views: 495

Answers (2)

mickmackusa
mickmackusa

Reputation: 47894

I don't speak/read Hebrew, but this seems to work as desired.

I generally dislike nesting preg_ calls inside preg_ calls, but in this case, splitting the unicode characters into an array then reversing the elements prevents the need to bother with mb_encodings.

Code: (Demo)

$str = 'תירס גדול A-10 (פרי גליל)';
echo preg_replace_callback(
         "/\p{Hebrew}+(?: \p{Hebrew}+)*/u",
         fn($m) => implode(
             array_reverse(
                 preg_split('~~u', $m[0], 0, PREG_SPLIT_NO_EMPTY)
             )
         ),
         $str
     );

Output:

סרית A-10 (לילג ירפ)

The preg_replace_callback() pattern isolates consecutive space-delimited Hebrew words, then the anonymous function splits the multibyte letters into individual array elements, before reversing their order and joining the elements back into a single mutated string.

Upvotes: 0

Jhecht
Jhecht

Reputation: 4435

Found this function in the comments on the docs that KoenHoeijmakers posted. I tested it, but I don't read Hebrew so it is hard for me to tell if it's working correctly.

function utf8_strrev($str){
    preg_match_all('/./us', $str, $ar);
    return join('',array_reverse($ar[0]));
}

Edit

Based on reading your question again, I think this works as you need it to?

function utf8_strrev($str)
{

    $arr = '';
    $words = explode(" ", $str);
    $start_tag = '(';
    $end_tag = ')';
    foreach ($words as $word)
    {
        if (preg_match("/\p{Hebrew}/u", $word))
        {
                preg_match_all('/./us', $word, $ar);
                $arr = join('', array_reverse($ar[0])) . " " . $arr;
        } else
        {
            preg_match_all('/./us', $word, $ar);
            $arr = join('', $ar[0]) . " " . $arr;
        }
    }

    return preg_replace(array('/\)(.)/','/(.)\(/','/\}(.)/','/(.)\{/'),array('($1','$1)','{$1','$1}'),$arr);
}
$str='תירס גדול A-10 {פרי גליל}';

echo utf8_strrev($str);

Outut

{לילג ירפ} A-10 לודג סרית

Again, I don't read Hebrew, but hopefully it answers your question.

Note The reason I used preg_replace instead of str_replace is because the string replace method was giving me issues text like ( somthing something ( or ) something something )

Upvotes: 2

Related Questions