19 Mayıs 2015 Salı

Locale İşlemleri

Not : Java ile ilgili şeyleri buraya taşıdım. C# ile ilgili şeyleri buraya taşıdım.


Locale Nedir?
Uygulamalar farklı ülkelerin standartlarına göre çalışmak için, o ülkenin gösterim için kullandığı formatlama bilgisini kullanırlar. Bu formatlama bilgisini saklayan sınıfa Locale denilir.

Örneğin her ülkenin tarih, para, zaman için belirlediği ayraçlar bulunur. Nesnelerin toString() veya benzeri bir metodları çağrıldığında, otomatik olarak seçili locale'i kullanarak string oluşturmaları beklenir.

Locale Hangi Alanlardan Oluşur
Programlama dillerinden locale kavramsal olarak alt parçalara ayrılmıştır. Farklı diller bile olsalar alt parçalar arasında kısmi bir örtüşme görülebilir.

C++
C++'ta LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME şeklinde sabitler kullanılarak para, sayı, zaman şeklinde başlıklara bölünmüş.

Locale Bilgisini Saklayan Sınıflar
C++
facet nedir? - Locale alt parçalarının kalıttığı sınıf
C++ dilinde locale ile ilgili formatlama bilgileri facet temel sınıfından türeyen hiyerarşide tutulur. Yani facet, locale alt parçalarının kalıttığı sınıftır.

facet sınıfı kopyalanamaz. C++ standardında bir çok facet sınıfı hazır geliyor. Örneğin ctype sınıfının std::locale::facet sınıfında türediği burada görülebilir.

Aşağıdaki facet şeklini de buradan aldım ve kalıtım görülebilir.


facet'ten türetme
Kendi facet sınıfımızı hazır gelen sınıflardan kalıtarak oluşturabiliriz. Örnekte rakamlar hariç diğer tüm karakterleri boşluk (space) olarak okuyan bir ctype facet var.

struct digits_only: std::ctype<char> {
    digits_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table() {
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
        return &rc[0];
    }
};

locale sınıfı nedir? - Tüm facetleri birleştiren sınıf
locale sınıfı, facetlerden kalıtan tüm nesneleri birleştirip belli bir ülke ile eşleştiren sınıftır.

Bir locale bir çok facet'ten oluşmaktadır. Aşağıdaki şekili buradan aldım ve bunu gösteriyor.
ctype facet ne işe yarar
Bu facet ile karakterler sınıflandırılır (isdigit(), isascii() vs.) ve karakterlerin büyük, küçük harf dönüşümü yapılabilir.

Locale Sınıfı İçindeki Facet'e Nasıl Erişilir
std::use_facet() metodu ile erişilir. Örnek'te local'den ctype facet alınıyor. Daha sonra facet'in toupper() metodu çağırılıyor.
std::ctype<char> const &ctype_facet = std::use_facet<std::ctype<char> >(some_locale);
char upper_a = ctype_facet.toupper('a');

Locale Sınıfına Yeni Facet Tipi Nasıl Yerleştirilir
En kolay yöntemi locale sınıfının constructor metoduna facet nesnesinin parametre olarak verilmesi. Örnek: Facet sınıfının desctructor metodu protected olduğu için heap'te yaratılması gerekir.
std::locale numbers(std::locale(), new digits_only);
 
Clasic Locale ve Facet Kullanımı
Örnek:

std::stringstream ss;
local_time_facet* output_facet = new local_time_facet();
ss.imbue(std::locale(std::locale::classic(), output_facet));
output_facet->format("%Y-%m-%dT%H:%M:%S %Q");
ss << ldt;
Stream'in Kendi Locale Nesnesi ve Facet Kullanımı
getloc() metodu ile stream'in locale nesnesi alınabilir.
Örnek:


Ayraçlara Göre Formatlama Yapan Metodlar

Win32
GetDateFormat metodu
Örnek:
SYSTEMTIME create_local_time;

TCHAR time[128] = {0};
const TCHAR *format = _T("yyyy/MM/dd");
GetLocalTime(&create_local_time);
GetDateFormat( LOCALE_USER_DEFAULT, 0, &create_local_time, format, time, 128);
Locale ve String Karşılaştırma
Bazı ülkelerde farklı karakterler aynı gibi algılanıyor. Örneğin Almanca'da Hauptstrasse ve Hauptstraße aynı kelimeler. Bu kelimeleri farklı işlemek istersek StringComparer sınıfını kullanarak aşağıdaki gibi yapabiliriz.



Kabuktan Locale'i Ayarlamak
Uygulamalar çalıştırıldıkları kabuğun locale ayarlarını kullanırlar. Bazen uygulama yerine kabuk locale ayarlarını değiştirmek daha kolay olabilir.

bash'te locale için kullanılabilecek her alanı locale komutu ile görebiliriz. Diğer Unix türevlerinde alanların isimler değişiklik gösterir. Türkçe Linux'ta alanların değeri "tr_TR.UTF-8" dir
root@icubes:[~]# locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
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"
LC_ALL=

LC_ALL her alanı ayrı ayrı ayarlamak yerine tümüne birden bir değer atamak için kullanılır.
C locale'ini kullanmak istersek en başa aşağıdaki satırları yazmak gerek.
# Set to "C" locale so we can parse messages from commands
LANG=C
export LANG
Locale dosyaları nerededir?
Linux'ta locale dosyaları /usr/share/i18n/locales/ dizini altında. Örneğin Türkçe locale dosyası /usr/share/i18n/locales/tr_TR. Bu dosya okunabilir denemez. Kendine göre bir formatı var.


Hiç yorum yok:

Yorum Gönder