setlocale Türkçe hatası

Bu hata ile ilk defa kohana 3 framework ile bir betik geliştirme sırasında karşılaştım. İlk karşılaşmamda üzerinde durmayıp kohana foruma konu açmıştım, bir süre sorunu kendim çözmüştüm, bugün tesadüfen bu konuyla tekrar karşılaştım. Kohana da ilk önce I18n sınıfı etkileniyordu.

Bu hata 2005 yılında bildirilmiş, halen düzeltilmediği görünüyor.

Test ortamım

Test ortamı centos, cpanel, php 5.3.4 bileşenlerini içeren bir paylaşımcı sunucu idi. Windows ortamında UTF-8 çalışmıyor, setlocale(LC_ALL, ‘turkish’) çalışıyor o da doğal olarak ISO-8859-9 çıktı veriyor.

Hata nedir?

Hata, setlocale(LC_ALL, ‘tr_TR.UTF-8’) kullandığımızda ” I ” harfi ile başlayan fonksiyonları çağırdığımızda çıkıyor.

Hemen hata veren örnek bir betik yazayım:

<?php
setlocale(LC_ALL, 'tr_TR.UTF-8');

class foo
{
  function IsHere()
  {
    echo 'here';
  }
}
$f = new foo();
$f->IsHere();
?>

Bu kodların sonucunda şöyle bir hata ile karşılaşıyoruz:
Fatal error: Call to undefined method foo::IsHere() in /test/setlocale.php on line xx

Başka bir sorun da strtolower() fonksiyonunda çıkıyor, normalde strtolower(‘I’) kullanımı ” i ” değerini veriken setlocale(LC_ALL, ‘tr_TR.UTF-8’) kullanıldığında ” I ” değeri olduğu gibi kalmakta, ” ı ” olmasını bekliyordum ama olmadı.

Çözümler

  1. cpanel, custom module bölümünde “Turkish locale patch for PHP5” diye bir yama var. İndirdim inceledim, php kaynak kodu üzerinde değişiklik yapıyor. Ancak bilinmesi gereken bu yamanın bir 3. şahıs tarafından yazıldığı ve cpanel in buna destek vermediği.
    --- Zend/zend_operators.c.orig  2007-09-06 12:37:18.000000000 +0300
    +++ Zend/zend_operators.c  2007-09-18 15:31:21.000000000 +0300
    @@ -39,9 +39,18 @@
     /* this is true global! may lead to strange effects on ZTS, but so is setlocale() */
     #define zend_tolower(c) _tolower_l(c, current_locale)
     #else
    -#define zend_tolower(c) tolower(c)
    +#define zend_tolower(c) zend_ascii_tolower(c)
     #endif
    
    +ZEND_API int zend_ascii_tolower(int i)
    +{
    +    if (64 < i && i < 91) {
    +        return (i + 32);
    +    } else {
    +        return i;
    +    }
    +}
    +
     ZEND_API int zend_atoi(const char *str, int str_len)
     {
       int retval;
  2. Şu şekilde bir kullanım yapıldığında sorun bypass ediliyor ve istediğimiz gibi çalışıyor:
    setlocale(LC_ALL, 'tr_TR.utf-8');
    setlocale(LC_CTYPE, 'C');

    LC_CTYPE için php manual da yazan açıklama “character classification and conversion, for example strtoupper()”.

Test için kullandığım örnek php betiği:

<?php
header('Content-type: text/html; charset=utf-8');

// http://bugs.php.net/bug.php?id=35050
// http://www.topolis.lt/php/#35050
setlocale(LC_ALL, 'tr_TR.utf-8');
setlocale(LC_CTYPE, 'C'); // character classification and conversion, for example strtoupper()

/* class test */
class foo
{
  function IsHere()
  {
    echo 'here<br />';
  }
}
$f = new foo();
$f->IsHere();

/* strtolower test */
$text = 'I18n';
$text = strtolower($text);
echo $text . '<br />';

/* date test */
// http://php.net/manual/en/function.strftime.php
echo strftime('%d %B %Y, %A', time()) . '<br />';

/* array sort test */
$array = array('Ali','Şule','Ömer','Çetin', 'Ilgaz', 'ılgaz');
sort($array, SORT_LOCALE_STRING);
echo '<pre>';
print_r($array);
asort($array, SORT_LOCALE_STRING);
print_r($array);
echo '<br />';

/* Test numeric formatting */
print_r(localeconv());

?>

2 thoughts on “setlocale Türkçe hatası
  1. selim

    Aynı sorunla bende karşılaştım,
    setlocale(LC_CTYPE, ‘C’);
    işimi gördü tşk ederim

Bir Cevap Yazın