Arsip: Format Indonesia untuk angka, dll.


by _lmz in Articles more 18 years ago 4677
Rutin dalam Delphi untuk melakukan format tanggal, waktu, angka, dan uang biasanya akan mengambil formatnya dari system. Nah, kalau sistem itu memang disetting menggunakan bahasa Indonesia sih hasilnya bagus, tapi bagaimana kalau sistem itu disetting dengan bahasa lain (misalnya English(US))? Bagaimana kita dapat menggunakan procedure dan function yang disediakan Delphi untuk memformat tanggal menurut konvensi Indonesia (tanpa menyuruh user mengubah Regional Settings)?

Peringatan: Yang di bawah ini cuma dicoba di Delphi versi 7. Saya tidak tahu cara melakukan ini di Delphi .NET -- mohon kakak-kakak yang lebih mengetahui untuk turut berbagi ilmu.

Procedure dan function Delphi untuk memformat sesuatu (tanggal, waktu, angka, uang, ...) menjadi string biasanya datang dalam dua versi. Misalkan saja fungsi umum Format().

function Format(const Format: string; const Args: array of const): string; overload;
function Format(const Format: string; const Args: array of const; const FormatSettings: TFormatSettings): string; overload;

Perbedaan yang pertama dan kedua adalah bahwa versi kedua memiliki sebuah parameter bertipe TFormatSettings. Tentang TFormatSettings sendiri akan dibahas kemudian.

Bagaimana Delphi sendiri mencari cara format string? Jawabannya bisa dilihat di unit SysUtils bagian initialization. Procedure yang dipanggil adalah GetFormatSettings. Dalam procedure ini sendiri Delphi akan memanggil fungsi GetLocaleChar() dan GetLocaleStr() milik Windows. Hasil dari pemanggilan fungsi di atas akan dimasukkan ke beberapa variabel global milik unit SysUtils seperti CurrencyString, ThousandSeparator, dll. Semua fungsi format string Delphi akan menggunakan variabel global ini untuk menentukan cara format yang baik dan benar.

Bagaimana Delphi tahu dia harus meminta format untuk bahasa apa? Jawabnya ada di satu parameter pertama untuk GetLocaleStr() dan GetLocaleChar() yaitu DefaultLCID yang merupakan variabel lokal procedure GetFormatSettings. Baris yang melakukan pengisian berbunyi DefaultLCID := GetThreadLocale;.

Mungkin sekarang anda sudah mendapat inspirasi untuk langsung mengubah semua variabel global yang digunakan untuk formatting milik unit SysUtils di dalam file .dpr anda. Tapi sebenarnya kan malas juga kalau harus mengetik 24 nama bulan (12 pendek, 12 panjang) dan 14 nama hari (7 pendek, 7 panjang). Kenapa tidak biarkan Windows saja yang mengisikannya? Kalau dari potongan prosedur GetFormatSettings tadi dia memanggil GetThreadLocale maka kenapa kita tidak memanggil SetThreadLocale()?. Deklarasi dari SetThreadLocale() dalam unit Windows adalah sebagai berikut:

type
LCID = DWORD;
function SetThreadLocale(Locale: LCID): BOOL; stdcall;

Tapi apakah LCID untuk bahasa Indonesia? Kalau anda seorang programmer C yang langsung menggunakan windows.h dari Microsoft maka anda akan menulis:

// dalam winnt.h
#defineLANG_INDONESIAN                  0x21
#defineSUBLANG_NEUTRAL                  0x00    // language neutral
#defineSORT_DEFAULT                     0x0     // sorting default
#defineMAKELANGID(p, s)       ((((WORD  )(s)) << 10) | (WORD  )(p))
#defineMAKELCID(lgid, srtid)  ((DWORD)((((DWORD)((WORD  )(srtid))) << 16) |  \
((DWORD)((WORD  )(lgid)))))
// dalam program
SetThreadLocale(MAKELCID(MAKELANGID(LANG_INDONESIAN, SUBLANG_NEUTRAL), SORT_DEFAULT));

Sayangnya, makro MAKELANGID dan MAKELCID tidak disertakan dalam unit Windows milik Delphi meskipun konstanta untuk bahasa, sub-bahasa, dan urutan sorting ada. Terjemahannya makro-makro itu dapat ditemukan di unit JclWin32 milik JCL (Jedi Code Library). Untuk gampangnya saja maka terjemahannya dalam Delphi untuk hasil MAKELCID adalah $21. Sehingga potongan program untuk mengubah Thread Locale menjadi bahasa Indonesia lalu memaksa unit SysUtils mengambil format lagi adalah:

SetThreadLocale($21); SysUtils.GetFormatSettings;

Berikut program untuk mengujinya:

program locale; {$APPTYPE CONSOLE} {$WARN SYMBOL_PLATFORM OFF} uses Windows, // JclWin32, SysUtils; begin writeln(Format('Current language: %s', [Languages.NameFromLocaleID[GetThreadLocale]])); writeln('Setting to indonesian/neutral'); // SetThreadLocale(MAKELCID(MAKELANGID(LANG_INDONESIAN, SUBLANG_NEUTRAL), SORT_DEFAULT)); SetThreadLocale($21); SysUtils.GetFormatSettings; writeln(Format('Current language: %s', [Languages.NameFromLocaleID[GetThreadLocale]])); writeln(Format('10000 as money (indonesian/neutral): %m', [10000.0])); writeln('Setting to english/us'); // SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)); SetThreadLocale($409); SysUtils.GetFormatSettings; writeln(Format('Current language: %s', [Languages.NameFromLocaleID[GetThreadLocale]])); writeln(Format('10000 as money (english/us): %m', [10000.0])); readln; end.

Tentu saja masih ada beberapa kekurangan misalnya yang terlihat di atas yaitu format uang yang tidak menggunakan dua angka di belakang titik desimal tetapi hal itu dapat diatasi dengan mengutak-atik isi variabel global unit SysUtils setelah memanggil SetThreadLocale() dan GetFormatSettings.

Tentang tipe TFormatSettings sendiri isinya adalah beberapa variabel (persis yang ada di unit SysUtils) tapi dimasukkan dalam record sehingga dapat disetting berbeda dari setting globalnya. Dikatakan dalam dokumentasi Delphi bahwa TFormatSettings bersifat thread-safe di mana variabel global tidak thread-safe di mana satu thread dapat merubahnya dan semua thread lain harus ikut "menelan getahnya". Berikut contoh penggunaan TFormatSettings.

var fmt : TFormatSettings;
begin
GetLocaleFormatSettings(MAKELCID(MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), SORT_DEFAULT), fmt);
writeln(Format('10000 (uang Jerman nih...): %m', [10000.0], fmt));
end;

Untuk lebih banyak informasi mengenai Locale dan LCID tentu saja referensinya adalah dokumentasi Windows Platform SDK. Di file winnt.h terdapat diagram tentang bentuk bit-bit dalam LCID. Untuk informasi tentang variabel dalam unit SysUtils dan formatnya dapat dicari di dokumentasi Delphi (cari saja CurrencyString di helpnya).

AI Forward

๐Ÿš€ We're thrilled to partner with Alibaba Cloud for "AI Forward - Alibaba Cloud Global Developer Summit 2025" in Jakarta! Join us and explore the future of AI. Register now: https://int.alibabacloud.com/m/1000400772/
#AlibabaCloud #DeveloperSummit #Jakarta #AIFORWARD

Local Business Directory, Search Engine Submission & SEO Tools FreeWebSubmission.com SonicRun.com