Kors Posted September 8, 2014 Report Share Posted September 8, 2014 В админке на странице импорта в ImportAdmin.php проверяется возможность установки локали таким кодом // Проверяем локаль $old_locale = setlocale(LC_ALL, 0); setlocale(LC_ALL, $this->locale); if(setlocale(LC_ALL, 0) != $this->locale) { $this->design->assign('message_error', 'locale_error'); $this->design->assign('locale', $this->locale); } setlocale(LC_ALL, $old_locale); При этом значение $old_locale есть строка типа LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=en_US.UTF-8;LC_MESSAGES=en_US.UTF-8;LC_PAPER=en_US.UTF-8;LC_NAME=en_US.UTF-8;LC_ADDRESS=en_US.UTF-8;LC_TELEPHONE=en_US.UTF-8;LC_MEASUREMENT=en_US.UTF-8;LC_IDENTIFICATION=en_US.UTF-8 Поэтому оператор в последней строке заранее обречен на неудачу, так как в такой ситуации передаваемая переменная никак не может содержать верное имя локали.Последний оператор тем самым никогда не восстанавливает исходную локаль, как задумано и как быть должно.А иногда, при соответствующих настройках, и дает предупреждения, о которых сообщалось в темахhttp://forum.simplacms.ru/topic/8123-%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B0-%D0%B2-%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8/http://forum.simplacms.ru/topic/1231-%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B0-specified-locale-name/ У меня локально работает правильно, если меняю код на // Проверяем локаль $old_locale = setlocale(LC_ALL, 0); setlocale(LC_ALL, $this->locale); if(setlocale(LC_ALL, 0) != $this->locale) { $this->design->assign('message_error', 'locale_error'); $this->design->assign('locale', $this->locale); } $old_locale=preg_replace("/.*=([^;]+).*/", '\\1', $old_locale) ; setlocale(LC_ALL, $old_locale); Quote Link to post Share on other sites
yr4ik Posted September 9, 2014 Report Share Posted September 9, 2014 По сути Ваш способ тоже не правильный...Поскольку даже на вашем примере он установит LC_ALL в последнее значение перед =. То есть это будет en_US.UTF-8. Я думаю так лучше будет: $old_locale = explode(';', setlocale(LC_ALL, 0)); $new_locale = setlocale(LC_ALL, $this->locale); if(!$new_locale || $new_locale != $this->locale) { $this->design->assign('message_error', 'locale_error'); $this->design->assign('locale', $this->locale); }else{ foreach($old_locale as $locale_str){ if(strpos($locale_str, '=') !== false) { list ($category, $locale) = explode('=', $locale_str); }else{ $category = 'LC_ALL'; $locale = $locale_str; } setlocale(constant($category), $locale); } } Quote Link to post Share on other sites
Kors Posted September 9, 2014 Author Report Share Posted September 9, 2014 Я думаю так лучше будет: $old_locale = explode(';', setlocale(LC_ALL, 0)); $new_locale = setlocale(LC_ALL, $this->locale); if(!$new_locale || $new_locale != $this->locale) { $this->design->assign('message_error', 'locale_error'); $this->design->assign('locale', $this->locale); }else{ foreach($old_locale as $locale_str){ if(strpos($locale_str, '=') !== false) { list ($category, $locale) = explode('=', $locale_str); }else{ $category = 'LC_ALL'; $locale = $locale_str; } setlocale(constant($category), $locale); } } Судя по "Я думаю", Вы не проверили, прежде чем постить... А если бы затратили пару минут для проверки, то убедились бы, что не только так лучше не будет, а так просто никуда не годится.$new_locale != $this->locale - всегда true, так как сравнивает строку и массив. Следовательно, Ваш код ВСЕГДА будет выводить ошибку. А часть else с циклом просто не будет выполняться НИКОГДА. ТО есть даже если у пользователя все нормально с локалью, Ваш метод ВСЕГДА будет гарантированно пугать его красной надписью! И уж точно не будет никогда возвращать исходную локаль... А вот идея Ваша с перебором всех значений, несомненно, очень даже хороша. Quote Link to post Share on other sites
yr4ik Posted September 9, 2014 Report Share Posted September 9, 2014 Судя по "Я думаю", Вы не проверили, прежде чем постить... А если бы затратили пару минут для проверки, то убедились бы, что не только так лучше не будет, а так просто никуда не годится. Вот тут Вы ошиблись. Код - рабочий!$new_locale != $this->locale - всегда true, так как сравнивает строку и массив. Следовательно, Ваш код ВСЕГДА будет выводить ошибку. А часть else с циклом просто не будет выполняться НИКОГДА. ТО есть даже если у пользователя все нормально с локалью, Ваш метод ВСЕГДА будет гарантированно пугать его красной надписью! И уж точно не будет никогда возвращать исходную локаль...Где Вы тут массив увидели? Почитайте прежде описание функции http://php.net/manual/ru/function.setlocale.php setlocale - возвращает имя локали (если она установилась) и false в случае ошибки. Соответственно и проверка if(!$new_locale || $new_locale != $this->locale) если $new_locale отрицательный или локаль не равна требуемой то выводим ошибку. Если все ок то восстанавливаем прежнюю... Quote Link to post Share on other sites
Kors Posted September 9, 2014 Author Report Share Posted September 9, 2014 Да, с массивом я промахнулся, признаю свою ошибку. Но я бы не спешил с категоричными утверждения типа "Код - рабочий!"... Запускаю Ваш код, предварительно установив private $locale = 'rus';Получаю для $new_locale строку 'Russian_Russia.1251'. Локаль прекрасно работает, а Ваш код дает в результате красное предупреждение... Quote Link to post Share on other sites
yr4ik Posted September 9, 2014 Report Share Posted September 9, 2014 $old_locale = explode(';', setlocale(LC_ALL, 0)); $new_locale = setlocale(LC_ALL, $this->locale); if($new_locale==false){ $this->design->assign('message_error', 'locale_error'); $this->design->assign('locale', $this->locale); }else{ foreach($old_locale as $locale_str){ if(strpos($locale_str, '=') !== false) { list ($category, $locale) = explode('=', $locale_str); }else{ $category = 'LC_ALL'; $locale = $locale_str; } setlocale(constant($category), $locale); } } Думаю можно убрать 2-ю проверку. По сути если вернет не false то можно считать что локаль та что нужно... Quote Link to post Share on other sites
Kors Posted September 9, 2014 Author Report Share Posted September 9, 2014 Убрать не "можно", а НУЖНО!Вы ведь сами написали "возвращает имя локали (если она установилась) и false в случае ошибки", а проверяете совсем другое! А еще в цикле могут устанавливаться как отдельные категории, так и LC_ALL. Возможны конфликты, когда несколько раз переустанавливается одна и та же категория - один раз сама по себе, и несколько раз LC_ALL с непонятно какими значениями... Quote Link to post Share on other sites
yr4ik Posted September 9, 2014 Report Share Posted September 9, 2014 Ну на счет "нужно" - не совсем уверен. Поскольку в разных системах бывают разные локали.Хотя с точки зрения универсальности данная проверка (на false) лучше всего подходит. А еще в цикле могут устанавливаться как отдельные категории, так и LC_ALL. Возможны конфликты, когда несколько раз переустанавливается одна и та же категория - один раз сама по себе, и несколько раз LC_ALL с непонятно какими значениями... Нет LC_ALL не передастся туда. Результатом setlocale(LC_ALL, 0) может быть либо строка вида en_US.UTF-8 (если установлена LC_ALL) либо набор локалей в виде того что вы показали в 1 посте.Правда на всех системах я этого не проверял. Но для большей надежности можно еще поставить break при установке LC_ALL.Или можно сделать массив с разрешенными группами. И при переборе проверять можно ли ее ставить...Но я думаю это лишнее... Лучше всего поставить проверку на присутствие константы перед установкой setlocale(constant($category), $locale); и на этом все. Quote Link to post Share on other sites
Kors Posted September 10, 2014 Author Report Share Posted September 10, 2014 Ну на счет "нужно" - не совсем уверен. Поскольку в разных системах бывают разные локали.Хотя с точки зрения универсальности данная проверка (на false) лучше всего подходит.Странная аргументация. А с какой точки зрения она подходит НЕ ЛУЧШЕ ВСЕГО? $old_locale = explode(';', setlocale(LC_ALL, 0)); $new_locale = setlocale(LC_ALL, $this->locale); if($new_locale!==false){ $this->design->assign('message_error', 'locale_error'); $this->design->assign('locale', $this->locale); }else{ foreach($old_locale as $locale_str){ if(strpos($locale_str, '=') !== false) { list ($category, $locale) = explode('=', $locale_str); }else{ $category = 'LC_ALL'; $locale = $locale_str; } setlocale(constant($category), $locale); } } А в этом варианте условный операторif($new_locale!==false)работает не правильно, а как раз с точностью до наоборот... Quote Link to post Share on other sites
yr4ik Posted September 10, 2014 Report Share Posted September 10, 2014 опечатку сделал. Уберите ! Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.