Сортировочный массив с сортировкой
У меня есть массив со словами на французском языке: ['États-Unis', 'Espagne' и т. Д.], Который я хотел бы отсортировать в алфавитном порядке в соответствии с его локализацией (fr_FR)
Я использую следующий код:
$collator = new Collator('fr-FR');
echo $collator->getErrorMessage();
$collator->asort($array);
Но я получаю сообщение об ошибке U_USING_DEFAULT_WARNING, когда я предполагаю, что используется английский или какой-либо другой язык. Что еще более важно, массив отсортирован неправильно (США появляются раньше Испании, если бы я ожидал, что произойдет обратное)
У меня установлен пакет intl, и моя система имеет соответствующие локали (Ubuntu)
$locale -a
C
C.UTF-8
en_US.utf8
es_ES.utf8
fr_FR
fr_FR.iso88591
fr_FR.utf8
POSIX
Я пробовал разные комбинации при построении объекта сортировки, без какого-либо хорошего результата: "fr-FR", "fr-FR.UTF8" и т. Д.
Есть ли что-нибудь еще, чего мне не хватает?
3 answers
Согласно этому сообщению в блоге , для слов кот, котэ, кот и кот (уже отсортированы на английском языке), порядок сортировки на французском языке: кот, кот-д'ивуар, котэ и котэ. Приведенный ниже код сортирует слова во французском сопоставлении:
$words = array('cote', 'coté', 'côte', 'côté');
print_r($words);
$collator = new Collator('fr_FR');
// print info about locale
echo 'French Collation ' . (($collator->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON) ? 'On' : 'Off') . "\n";
echo $collator->getLocale(Locale::VALID_LOCALE) . "\n";
echo $collator->getLocale(Locale::ACTUAL_LOCALE) . "\n";
$collator->asort($words);
print_r($words);
И напечатанный результат выглядит следующим образом:
Array
(
[0] => cote
[1] => coté
[2] => côte
[3] => côté
)
French Collation On
fr_FR
fr
Array
(
[0] => cote
[2] => côte
[1] => coté
[3] => côté
)
В том же сообщении в блоге автор говорит:
[...] диакритические знаки оцениваются справа налево, а не слева направо. Таким образом, кот появляется перед кот, а не после него, как это происходит в таких языках, как английский, которые оценивают их слева направо. Потому что слово кот не имеет ОСТРОЙ буквы "е" в конце слова, в то время как кот имеет. На английском и большинстве других языков оценка начинается слева, и поэтому ОКРУЖНОСТЬ или ее отсутствие на букве "о" является определяющим фактором в заказ.
Итак, если у вас есть массив со словами Испания и США, они будут иметь одинаковый порядок на английском и французском языках.
Вы также должны иметь в виду, что метод asort
поддерживает ассоциацию индексов массива. Видите разницу:
asort:
Array
(
[0] => cote
[2] => côte
[1] => coté
[3] => côté
)
sort:
Array
(
[0] => cote
[1] => côte
[2] => coté
[3] => côté
)
О предупреждении об U_USING_DEFAULT_
В соответствии с этой документацией API:
U_USING_DEFAULT_WARNING указывает, что использовались данные локали по умолчанию; не удалось найти ни запрошенный язык, ни какой-либо из его резервных языков.
Когда я использую локаль fr_FR, например, я получаю предупреждение U_USING_FALLBACK_, которое указывает, что использовалась резервная локаль, в данном случае локаль fr.
Локаль
Как кажется, ваш компьютер не поддерживает французский язык (или поддерживает, но каким-то образом PHP не может его использовать, а затем вернуться к языку по умолчанию), хотя команда locale -a
отображает французские пакеты. У меня есть несколько предложений, которые вы можете попробовать.
Сначала перечислите все поддерживаемые языки:
cat /usr/share/i18n/SUPPORTED
Теперь сгенерируйте нужные вам языки:
sudo locale-gen fr_FR.UTF-8
sudo locale-gen fr_FR.ISO-8859-1
sudo dpkg-reconfigure locales
Если это не сработает, попробуйте установить пакеты language-pack-fr и language-support-fr и снова сгенерировать языки.
Эта проблема странная. У меня есть виртуальная машина с Ubuntu 11.04 и PHP 5.3.8, и она отлично работает, в моем Debian 6 тоже, и я не установил ни одного пакета или настроил что-нибудь.
Я использую cygwin:
$ locale -a | grep fr_FR
fr_FR
fr_FR.utf8
fr_FR@euro
(обратите внимание, что у меня нет fr_FR.iso88591
на выходе)
Код (кодировка файла UTF-8):
$collator = new Collator('fr_FR');
var_dump($collator->getErrorMessage());
// FRENCH_COLLATION is OFF
$arr = array('États-Unis', 'Espagne');
var_dump($collator->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON);
var_dump($collator->getLocale(Locale::VALID_LOCALE));
var_dump($collator->getLocale(Locale::ACTUAL_LOCALE));
$collator->asort($arr);
var_dump($arr);
// FRENCH_COLLATION is ON
$collator->setAttribute(Collator::FRENCH_COLLATION, Collator::ON);
$arr = array('États-Unis', 'Espagne');
var_dump($collator->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON);
var_dump($collator->getLocale(Locale::VALID_LOCALE));
var_dump($collator->getLocale(Locale::ACTUAL_LOCALE));
$collator->asort($arr);
var_dump($arr);
Вывод:
string(23) "U_USING_DEFAULT_WARNING"
bool(false)
string(5) "fr_FR"
string(4) "root"
array(2) {
[1]=>
string(7) "Espagne"
[0]=>
string(11) "États-Unis"
}
bool(true)
string(5) "fr_FR"
string(4) "root"
array(2) {
[1]=>
string(7) "Espagne"
[0]=>
string(11) "États-Unis"
}
И вот в чем хитрость: Я конвертирую кодировку файла в ISO 8859-1 (в vim я делаю :set fileencoding=iso-8859-1
) и повторяю попытку:
string(23) "U_USING_DEFAULT_WARNING"
bool(false)
string(5) "fr_FR"
string(4) "root"
array(2) {
[0]=>
string(10) "▒tats-Unis"
[1]=>
string(7) "Espagne"
}
bool(true)
string(5) "fr_FR"
string(4) "root"
array(2) {
[0]=>
string(10) "▒tats-Unis"
[1]=>
string(7) "Espagne"
}
Некоторые символы сломаны, но я думаю, это потому, что мой терминал не поддерживает данную кодовую страницу. Главное, что порядок строк сейчас именно такой, как вы описали: "Espagne" следует после "Этац-Унис".
Итак, я думаю, что это кодировка файла.
Попробуйте просто "FR", это должно работать для вашей системы, я думаю:
$collator = new Collator('FR');