Вычисление длины японской многобайтовой строки с половинной шириной каны в PHP - PullRequest
8 голосов
/ 12 апреля 2011

Итак, у меня есть строка в кодировке UTF-8, которая может содержать кандзи полной ширины, кана полной ширины, кана полуширины, ромадзи, цифры или японские символы каваий, такие как ★ или ♥.

Если я хочу использовать длину, я использую mb_strlen(), и каждый из них считается равным 1. Что хорошо для большинства целей.

Но меня (японский клиент) попросили считать кана только половинной ширины как 0,5 (с целью максимальной длины текстового поля), потому что, очевидно, именно так японские веб-сайты делают это. Я делаю это, используя mb_strwidth(), который считает полную ширину как 2, а половинную ширину как 1, затем я делю на 2.

Однако этот метод также считает символы ромадзи как 1, так что что-то вроде Chocアイス будет считаться как 7 ... тогда я разделю на 2 для учета иероглифов и получу 3,5. но на самом деле я хочу 5,5 (4 для ромадзи + 1,5 для 3 половинной каны).

// РЕДАКТИРОВАТЬ: Еще немного информации: любой символ (даже не кана), имеющий целые и половину, должен быть 1 для полной ширины и 0,5 для полуширины. например, такие символы, как ¥、3@(, должны быть равны 1, а такие символы, как ¥,3@(, должны быть равны 0,5

.

// ДОПОЛНИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ: символы типа ☆ и ♥ должны быть равны 1, но метод mb_strwidth / 2 возвращает их как 0,5

Существует ли стандартный способ подсчета длины строки в японских системах? Или все просто зацикливаются на своих строках и подсчитывают символы, которые не соответствуют стандартным правилам ширины?

Ответы [ 3 ]

3 голосов
/ 12 апреля 2011

Один из способов - преобразовать половинную ширину катаканы в полную ширину и вычесть разницу в ширине из первоначальной длины:

$raw = 'Chocアイス';
$full = mb_convert_kana($raw, 'K');
$len = mb_strlen($raw) - (mb_strwidth($full) - mb_strwidth($raw))/2;
assert($len === 5.5);

Однако , вы уверены , что вы должны рассматривать базовые латинские символы в качестве полной ширины?Существуют также полноразмерные разновидности базовых латинских символов, то есть Choc следует считать такими же, как Choc?

Обычно такие символы, как "A" и "ア", будут иметьширина 1, но "A" и "ア" будут иметь ширину 2 (что и делает mb_strwidth).Я бы с осторожностью отнесся к этому.


Учитывая ваше редактирование , mb_strwidth (или mb_strwidth/2) делает именно то, что вы хотите.

0 голосов
/ 25 апреля 2011

Посмотрите на модуль Perl Unicode :: GCString : он дает правильные столбцы для всех Unicode, включая восточноазиатские штуки.

Это базовый компонент Unicode :: LineBreak , который я считаю абсолютно необходимым для правильной сегментации текста азиатских сценариев.

Как вы можете себе представить, оба Made in Japan ™. :)

0 голосов
/ 25 апреля 2011

Итак, я не нашел ответа на этот вопрос.

Я исправил это, буквально повторяя и проверяя каждый символ и вручную применяя правила подсчета, которые просил мой клиент.

...