← Tüm rehberler Masaüstü · Epson

Termal Fiş Yazıcılarda Türkçe Karakter Sorunu ve Kesin Çözüm Rehberi

Termal fiş yazıcılarla çalışan yazılım geliştiricilerin ve POS entegratörlerinin karşılaştığı en kronik problem, Türkçe karakterlerin fiş üzerinde bozuk çıkmasıdır: “ş” yerine ters soru işareti ”¿”, “ı” yerine garip bir grafik sembolü, “ğ” yerine boşluk veya silik bir kutucuk basılması.

Bu sorun bir donanım arızası veya kablo bozukluğu değildir. Termal yazıcıların dahili ROM belleğinde metinlerin nasıl yorumlanacağını belirleyen kod sayfası (Code Page) mimarisi ile modern web sistemlerinin varsayılan standardı olan UTF-8 (Unicode) arasındaki bayt uyuşmazlığından kaynaklanır.

Bu kapsamlı mühendislik kılavuzunda; ESC/POS kod sayfası mantığını, CP857 (DOS) ve Windows-1254 (CP1254) tablolarını, JavaScript/Node.js ile bayt dönüşümünü ve donanım desteği olmayan yazıcılar için akıllı transliterasyon mimarisini inceliyoruz.


1. Sorunun Kök Nedeni: Neden Türkçe Karakterler Bozulur?

Modern web ve bulut sistemleri metinleri UTF-8 ile kodlar. UTF-8’de standart İngilizce ASCII karakterleri (A-Z, 0-9) tek bir bayt (0-127 arası) ile temsil edilirken; Türkçe’ye özgü harfler (ç, ğ, ı, ö, ş, ü, Ç, Ğ, İ, Ö, Ş, Ü) 2 baytlık diziler olarak bellekte saklanır:

Geleneksel termal fiş yazıcıların mikrodenetleyicileri ise 8-bit genişletilmiş ASCII (0-255 arası) dünyasında yaşar. Yazıcıya UTF-8 formatında ş (0xC5 0x9F) gönderdiğinizde, yazıcı bunu tek bir harf olarak değil; arka arkaya gelen bağımsız iki farklı grafik sembolü olarak algılar. Sonuç olarak fişte ÅŸ gibi anlamsız glifler belirir.


2. Termal Yazıcı Kod Sayfaları (Code Pages)

Termal yazıcılarda 128 ile 255 arasındaki baytların hangi bölgesel alfabelere karşılık geleceği Kod Sayfası (Code Page) komutuyla seçilir. ESC/POS standardında kod sayfası seçimi şu komutla yapılır:

$$\text{ESC } t \text{ } n \quad \longrightarrow \quad \text{Hex: } \texttt{0x1B 0x74 [n]}$$

Buradaki $n$ parametresi yazıcının donanım üreticisine göre değişen kod sayfası indeks numarasıdır.

2.1. CP857 (IBM DOS / Türk Standardı)

Türkiye pazarındaki Epson, Bixolon, Xprinter ve Hoin yazıcıların büyük çoğunluğunda Türkçe karakter seti CP857 olarak gömülüdür.

CP857 Türkçe Karakter Hex Tablosu:

KarakterUnicode (Hex)CP857 Hex DeğeriOndalık (Dec)
çU+00E70x87135
ÇU+00C70x80128
ğU+011F0xA6166
ĞU+011E0xA7167
ı (noktasız)U+01310x8D141
İ (noktalı)U+01300x98152
öU+00F60x94148
ÖU+00D60x99153
şU+015F0x9F159
ŞU+015E0x9E158
üU+00FC0x81129
ÜU+00DC0x9A154

2.2. Windows-1254 (CP1254 / ISO-8859-9)

Windows tabanlı sürücüler ve bazı modern yazıcılar Windows-1254 tablosunu kullanır:

KarakterWindows-1254 HexCP857 HexFark
ğ / Ğ0xF0 / 0xD00xA6 / 0xA7Tamamen farklı bayt dizilimi
ı / İ0xFD / 0xDD0x8D / 0x98Farklı bayt
ş / Ş0xFE / 0xDE0x9F / 0x9EFarklı bayt

⚠️ En Yaygın Hata: Yazıcıyı CP857 moduna alıp veriyi Windows-1254 ile kodlanmış baytlarla gönderirseniz “ş” harfi kutu veya yanlış simge olarak çıkar. Kod sayfası seçimi ile gönderilen baytların haritası birebir eşleşmelidir.


3. Kod Sayfasını Öğrenme: Yazıcı Self-Test Raporu

Kullandığınız fiş yazıcının hangi kod sayfasını hangi indeks numarasıyla desteklediğini tahmin etmek yerine yazıcıdan Self-Test (Dahili Durum) Raporu almalısınız:

  1. Yazıcının güç anahtarını kapatın.
  2. Kağıt besleme (FEED) tuşuna parmağınızı basılı tutun.
  3. Parmağınızı FEED tuşundan çekmeden güç anahtarını açın.
  4. Yazıcı ciyaklama sesi verip ilk parametreleri basmaya başlayınca FEED tuşunu bırakın.
  5. Yazdırılan fişin en altındaki “Character Code Table” veya “Page List” bölümünü inceleyin:
    • Page 18: Turkish (CP857)
    • Page 50: CP857
    • Page 70: Windows-1254

Burada görünen sayfa numarası, göndermeniz gereken ESC t [n] komutunun $n$ parametresidir.


4. Yazılım Katmanında Çözüm Uygulaması (Node.js & JavaScript)

4.1. Node.js iconv-lite ile Bayt Dönüşümü

Node.js ortamında UTF-8 metinleri CP857 bayt dizisine çevirmek için endüstri standardı iconv-lite kütüphanesidir:

import iconv from 'iconv-lite';

export function buildTurkishReceipt(): Buffer {
  const buffers: Buffer[] = [];

  // 1. Yazıcıyı Başlat (ESC @)
  buffers.push(Buffer.from([0x1B, 0x40]));

  // 2. Kod Sayfasını CP857 olarak seç (ESC t 18 -> 0x1B, 0x74, 0x12)
  buffers.push(Buffer.from([0x1B, 0x74, 18]));

  // 3. Yazdırılacak Türkçe Metin
  const receiptText = 
    "=== PRINTZEN LEZZET RESTORAN ===\n" +
    "Sipariş Tarihi: 10.09.2026 14:35\n" +
    "Masa: Bahçe 04\n" +
    "--------------------------------\n" +
    "1x Kaşarlı Pide          240.00 TL\n" +
    "1x Acılı Şalgam Suyu      45.00 TL\n" +
    "1x Fıstıklı Künefe       180.00 TL\n" +
    "--------------------------------\n" +
    "TOPLAM:                  465.00 TL\n" +
    "Afiyet Olsun. Yine Bekleriz!\n\n\n";

  // 4. Metni CP857 baytlarına dönüştür
  const encodedBody = iconv.encode(receiptText, 'cp857');
  buffers.push(encodedBody);

  // 5. Kağıt Kes (GS V 66 0 -> Tam Kesim)
  buffers.push(Buffer.from([0x1D, 0x56, 66, 0]));

  return Buffer.concat(buffers);
}

4.2. Tarayıcı Ortamında (Frontend / Pure JS) Bayt Eşleme

Frontend’de veya harici kütüphane eklenemeyen Web Bluetooth / WebUSB senaryolarında, 12 Türkçe karakteri doğrudan CP857 bayt karşılıklarına dönüştüren saf fonksiyon:

function encodeTurkishCP857(text) {
  const cp857Map = {
    'ç': 0x87, 'Ç': 0x80,
    'ğ': 0xA6, 'Ğ': 0xA7,
    'ı': 0x8D, 'I': 0x49,
    'i': 0x69, 'İ': 0x98,
    'ö': 0x94, 'Ö': 0x99,
    'ş': 0x9F, 'Ş': 0x9E,
    'ü': 0x81, 'Ü': 0x9A
  };

  const bytes = [];
  for (let i = 0; i < text.length; i++) {
    const char = text[i];
    if (cp857Map[char] !== undefined) {
      bytes.push(cp857Map[char]);
    } else {
      const code = char.charCodeAt(0);
      // Standart ASCII aralığı
      bytes.push(code < 128 ? code : 0x3F); // Tanınmayanlara '?'
    }
  }
  return new Uint8Array(bytes);
}

5. Donanımı Değiştirilemeyen Yazıcılar İçin: Transliterasyon (Yumuşatma)

Bazı çok ucuz taşınabilir mobil fiş yazıcılarında (veya Uzak Doğu menşeli etiket makinelerinde) ROM belleğinde Türkçe karakter tablosu hiç bulunmaz. Bu yazıcılara CP857 gönderseniz bile harfler yine bozuk çıkar.

Bu durumda en temiz ve profesyonel yaklaşım, baskı öncesinde Türkçe karakterleri uluslararası ASCII karşılıklarına dönüştürmektir (Transliteration):

export function transliterateTurkish(str) {
  return str
    .replace(/ğ/g, 'g')
    .replace(/Ğ/g, 'G')
    .replace(/ı/g, 'i')
    .replace(/İ/g, 'I')
    .replace(/ş/g, 's')
    .replace(/Ş/g, 'S')
    .replace(/ç/g, 'c')
    .replace(/Ç/g, 'C')
    .replace(/ö/g, 'o')
    .replace(/Ö/g, 'O')
    .replace(/ü/g, 'u')
    .replace(/Ü/g, 'U');
}

Örnek Sonuç:

Fişte K¿¿arl¿ Pide gibi çirkin semboller yerine Kasarli Pide yazması, müşteri gözünde çok daha temiz ve okunabilir bir sonuç sunar.


6. Sıkça Sorulan Sorular (SSS)

Termal yazıcıda Türkçe karakterler neden soru işareti (?) olarak çıkıyor?

Yazıcıya gönderdiğiniz verinin bayt kodları, yazıcının o an aktif olan karakter tablosunda (Code Page) tanımlı bir glife karşılık gelmediğinde yazıcı güvenlik mekanizması olarak soru işareti basar. Çözüm için yazdırma işleminden hemen önce 0x1B 0x74 18 komutu gönderilerek yazıcının CP857 (Turkish) moduna geçirilmesi ve gönderilen string’in CP857 bayt dizisine dönüştürülmesi gerekir.

ESC/POS kod sayfası komutu gönderdiğim halde yazıcı neden Türkçe basmıyor?

Bunun en yaygın nedeni, yazıcının marka ve modeline göre Türkçe kod sayfası indeks numarasının farklı olmasıdır. Örneğin Epson yazıcılarda CP857 için 18 veya 50 değeri kullanılırken, bazı Xprinter veya Posiflex modellerinde 38 veya 70 numarası atanmış olabilir. Yazıcının FEED tuşuna basılı tutarak açıp Self-Test fişi yazdırarak “Page List” altındaki doğru Türkçe tablo numarasını teyit etmelisiniz.

Termal yazıcılar UTF-8’i doğrudan desteklemez mi?

Yeni nesil bazı kurumsal Epson modelleri (örneğin TM-T88VI veya TM-T20III) UTF-8 modunu (FS ( C komutuyla) desteklese de, piyasadaki POS ve fiş yazıcılarının %90’ı 8-bit tek baytlık genişletilmiş ASCII kullanır. Dolayısıyla güvenilir ve tüm yazıcılarda çalışan bir sistem kurmak için metinlerin yazıcıya gönderilmeden önce CP857 veya Windows-1254 formatına dönüştürülmesi endüstri standardıdır.

Fiş yazıcıda Türkçe karakter sorununu tamamen çözmek için Printzen ne sunar?

Printzen mobil ve bulut servisleri; bağlı yazıcının donanım modelini, ROM sürümünü ve kod sayfası yeteneğini otomatik olarak algılar. Gönderdiğiniz UTF-8 metinleri yazıcının desteklediği en uygun kod sayfasına (CP857, Windows-1254) şeffaf şekilde dönüştürür; yazıcıda Türkçe ROM desteği yoksa akıllı transliterasyon uygulayarak fişlerin hiçbir zaman bozulmadan, kusursuz basılmasını sağlar.