снова про локаль на уровне конфигурации сервера (setlocale)

fisher

накатила суть
снова про локаль на уровне конфигурации сервера (setlocale)

собственно, это обсуждалось уже в серединке этого треда, но ответа я не нашел
http://www.phpclub.ru/talk/showthread.php?s=&threadid=41143&highlight=setlocale
задача: я не хочу писать в коде setlocale(...). я хочу изменять эти вещи на уровне настроек сервера. судя по всему, пхп не "наследует" локаль от переменных окружения процесса апача (SAPI) или от шелла в консольном режиме, а ставит какую-то свою дефолтною (кто в сорцах ковырялся - может знаете где? или глючу?) и приходится её явно ставить руками в коде. есть ли способ этого избежать? вопрос почему этого можно хотеть избегать предлагаю оставить в стороне.

отступление: ради интереса был поправлен Zend/zend_operators.c - в zend_binary_strcmp вызов memcmp поменял на strcoll. результат - по прежнему сортировка нормально проходит только с явной простановкой локали в скрипте.
 

tony2001

TeaM PHPClub
что говорит locale в шелле?
в какой кодировке текст?
и в чем проблема?
 

fisher

накатила суть
локаль в шелле стоит ru_RU.KOI8-R:
LANG=ru_RU.KOI8-R
LC_CTYPE=ru_RU.KOI8-R
LC_NUMERIC=ru_RU.KOI8-R
LC_TIME=ru_RU.KOI8-R
LC_COLLATE=ru_RU.KOI8-R
LC_MONETARY=ru_RU.KOI8-R
LC_MESSAGES=ru_RU.KOI8-R
LC_PAPER="ru_RU.KOI8-R"
LC_NAME="ru_RU.KOI8-R"
LC_ADDRESS="ru_RU.KOI8-R"
LC_TELEPHONE="ru_RU.KOI8-R"
LC_MEASUREMENT="ru_RU.KOI8-R"
LC_IDENTIFICATION="ru_RU.KOI8-R"
LC_ALL=

весь текст в ru_RU.KOI8-R. strtoupper/strtolower работают отлично. не работет сортировка без явной простановки локали через вызов setlocale. если ставить этот вызов - всё будет ок. проблема в том, что хочется избежать этого вызова, тк не совсем ясно, почему он нужен в явном виде в данной ситуации.

сам скрипт:

<?
#setlocale(LC_COLLATE,'ru_RU.KOI8-R');

$lo = 'абвгдежзиклмнопрстуфхцчшщэюя';
$up = 'АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЭЮЯ';

echo 'lo->up:';
var_dump(strtoupper($lo));
echo "<br>";
echo 'up->lo:';
var_dump(strtolower($up));

$l = strlen($lo);

$letters = array();
for($i=0;$i<$l;$i++) {
$pos = rand(1,$l);
$letters[$i] = substr($up,$pos,1);
}

$l1 = $letters;
print_r($l1);
sort($l1,SORT_STRING);
print_r($l1);
$l1 = $letters;
usort($l1,'strcoll');
print_r($l1);

?>

здесь обычный sort по умолчанию и не должен сортировать правильно, но я извращаюсь и использую пересобранный пхп с исправленным Zend/zend_operators.c. usort с вызовом strcoll без явного setlocale тоже не сортирует, если ставить явно - все ок. то ли я глючу не по-детски, то ли одно из двух :)
проверено и с export LC_ALL=ru_RU.KOI8-R
 

fixxxer

К.О.
Партнер клуба
запихни setlocale в auto_prepend_file, если тебя так напрягает одну строчку написать...
а насчет шелла:
1)уверен, что шелл запущен под тем юзаром, из которого работает апач?
2)апачу глубоко плевать на всякие ~/.bash_profile и прочее
 

tony2001

TeaM PHPClub
>1)уверен, что шелл запущен под тем юзаром, из которого работает апач?
да, у всех юзеров есть LC_ALL, у apache я тоже проверил.

>2)апачу глубоко плевать на всякие ~/.bash_profile и прочее
profile не имеет отношения к этому.
в phpinfo() есть LANG и он правильный, но LC_COLLATE появляется только после export LC_COLLATE + никак не влияет не влияет на сортировку.
 

fisher

накатила суть
2tony: пасиб
2fixxer: с апачом в данном случае есть ещё-один-не-работающий-как-ожидается вариант. переменные окружения ставятся разумется при старте процесса - сейчас речь не об апаче вовсе. насчет auto_prepend_file: о чем ты? о скрипте который запускатеся при старте всегда по умолчанию? если да, это возможный вариант, но по сути ничем не отличающийся от явного setlocale. ещё раз: дело не в том, чтоб заработало хоть как-то. а в том, что не работает так, как оно по идее должно :)
 

tony2001

TeaM PHPClub
подсказали: сущестования LC_COLLATE недостаточно, надо вызывать setlocale() в любом случае.
так - работает, да.
 

confguru

ExAdmin
Команда форума
fisher

У меня все в конфигах определяется ..
благо они всегда инклюдятся..
для французов своя локаль.. на нас другая..
Еще не забывай что лучше самому определять...
а то французы долго удивлялись русским месяцам :)
 

fisher

накатила суть
2tony: то, что оно так, было почти ясно из практического опыта с самого начала. но вот бы ещё понять, почему оно так :) мне вот логика этого не ясна.
2admin: да, для мультиязычных проектов так правильнее конечно. ну здесь скорее интерес принципиальный.
 

tony2001

TeaM PHPClub
нашлось по пути:
main/main.c:1368: setlocale(LC_CTYPE, "");

не совсем понимаю почему тут выставляется только LC_CTYPE, а не вся LC_ALL, сейчас посмотрим что они скажут на патч..

а sort() работать не будет в любом случае, т.к. там memcmp(), а не strcoll().
 

fisher

накатила суть
2tony: дык, я потому и стал ковырять код. слушай, а может в патч внести ещё одну константу у сортировки sort - STRING_SORT_COLL, для которой сделать отдельную реализацию через strcoll вместо memcpy? было бы всяко удобно - а то кроме usort с strcoll-callback'ом никак...

-~{}~ 18.05.04 17:15:

в догонку - всю LC_ALL имхо плохо. тогда уж CTYPE и COLLATE 2-мя вызовами
 

tony2001

TeaM PHPClub
fisher
>в догонку - всю LC_ALL имхо плохо. тогда уж CTYPE и COLLATE 2-мя вызовами
угу.
только не 2-мя, я 5-ю:
Код:
        setlocale(LC_COLLATE, ""); /* для strcoll() */
        setlocale(LC_CTYPE, ""); /* для preg_*() */
        setlocale(LC_MESSAGES, "");
        setlocale(LC_MONETARY, "");
        setlocale(LC_TIME, ""); /* для strftime() */
        /* LC_NUMERIC is not set due to some issues with serialize/unserialize */
>а может в патч внести ещё одну константу у сортировки sort - STRING_SORT_COLL,
>для которой сделать отдельную реализацию через strcoll вместо memcpy
ага.
надо бы просто переделать sort() и другие ф-ции так, чтобы они юзали не zend_binary_strcmp(), а strcoll().
вкупе с предыдущими измениями это должно работать на 100%.
я попробую написать небольшой патч, но это уже в 5.1, сорри, сейчас feature freeze..
 

fisher

накатила суть
>>я попробую написать небольшой патч
ну да, пасиб
у себя мы и сами пропатчим при необходимости :)
>>надо бы просто переделать sort() и другие ф-ции так,
>>чтобы они юзали не zend_binary_strcmp(), а strcoll()
ну если strcoll окажется значительно медленнее, то можно и отдельным вариантом через константу...
 

si

Administrator
я както давно писал баг репорт на тему local + float separator как обычно меня послали сначала куда подальше (Дерик), а потом по моему Илья это исправлял возножно это оттуда
 

tony2001

TeaM PHPClub
>ну если strcoll окажется значительно медленнее, то можно и отдельным вариантом через константу...
да нет, она медленнее не должна быть, единственное доп. действие в ней - это проверка на \0

>я както давно писал баг репорт на тему local + float separator как обычно меня послали сначала куда подальше (Дерик)
тут всё наоборот - Дерик за нас =)
и имхо это никак не связано.
 
Сверху