Беда с текстом php радуги

У меня проблемы с функциями текста PHP радуги.
Когда я запускаю эту функцию, выводимый текст не поддерживает вьетнамский язык.

Например: «тои ты»;

<?php
function rainbow($text)
{

/*** initialize the return string ***/
$ret = '';

/*** an array of colors ***/
$colors = array(
'ff00ff', 'ff0099', 'ff0033', 'ff3300',
'ff9900', 'ffff00', '99ff00', '33ff00',
'00ff33', '00ff99', '00ffff', '0099ff',
'0033ff', '3300ff', '9900ff'
);
/*** a counter ***/
$i = 0;
/*** get the length of the text ***/
$textlength = strlen($text);
/*** loop over the text ***/
while($i<=$textlength)
{
/*** loop through the colors ***/
foreach($colors as $value)
{
if ($text[$i] != "")
{
$ret .= '<span style="color:#'.$value.';">'.$text[$i]."</span>";
}
$i++;
}
}
/*** return the highlighted string ***/
$ret = html_entity_decode($ret, ENT_QUOTES, 'UTF-8');
return $ret;
}
echo rainbow('tôi yêu em');
?>

0

Решение

С помощью этой функции вы получите уведомления о неинициализированном смещении строки на любом языке благодаря тому, как вы перебираете байты строки + цвета. Лучше получить доступ к цветам через InfiniteIterator который будет просто зацикливаться.

Ваша специфическая проблема с вьетнамцами заключается в том, что некоторые из этих символов состоят из нескольких байтов. Функции как strlen() и доступ к смещению через скобки массива, такие как $text[$i] не являются многобайтовыми — они работают с отдельными байтами, а не с символами.

Хотя может быть заманчиво просто использовать mb_strlen() на месте strlen() чтобы получить количество символов, а не количество байтов, и mb_substr() скорее, чем $text[$i] чтобы получить символ, а не байт, вы все равно будете разбивать графемы как (который здесь закодирован как e с последующим сочетая серьезный акцент.) Решение состоит в том, чтобы разбить строку на массив с помощью регулярного выражения.


Пример:

function rainbow($text)
{
$text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');
$return = '';

$colors = new InfiniteIterator(
new ArrayIterator(
['ff00ff', 'ff0099', 'ff0033', 'ff3300',
'ff9900', 'ffff00', '99ff00', '33ff00',
'00ff33', '00ff99', '00ffff', '0099ff',
'0033ff', '3300ff', '9900ff']
)
);
$colors->rewind();

// Match any codepoint along with any combining marks.
preg_match_all('/.\pM*+/su', $text, $matches);
foreach ($matches[0] as $char)
{
if (preg_match('/^\pZ$/u', $char)) {
// No need to color whitespace or invisible separators.
$return .= $char;
} else {
$return .= "<span style='color:#{$colors->current()};'>$char</span>";
$colors->next();
}
}

return $return;
}

echo rainbow('tôi yêu em eve&#x300; foo baz');

Выход:

<span style='color:#ff00ff;'>t</span><span style='color:#ff0099;'>ô</span><span style='color:#ff0033;'>i</span> <span style='color:#ff3300;'>y</span><span style='color:#ff9900;'>ê</span><span style='color:#ffff00;'>u</span> <span style='color:#99ff00;'>e</span><span style='color:#33ff00;'>m</span> <span style='color:#00ff33;'>e</span><span style='color:#00ff99;'>v</span><span style='color:#00ffff;'>è</span> <span style='color:#0099ff;'>f</span><span style='color:#0033ff;'>o</span><span style='color:#3300ff;'>o</span> <span style='color:#9900ff;'>b</span><span style='color:#ff00ff;'>a</span><span style='color:#ff0099;'>z</span>
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]