Published: · Updated:
Paste code or load the sample — the result appears below, with the line and severity of each finding.
Ö becomes Ö, ü becomes ü, a Turkish ş turns into two junk symbols. The data is right in your system, right in the file — and wrong on the label. This is not corruption; it is two sides decoding the same bytes with different tables.
Modern systems write text as UTF-8, where Ö is two bytes. A Zebra
printer without instructions decodes ^FD data with its default
legacy code page, where every byte is one character — so those two bytes
print as two wrong characters. The signature is exact: each accented letter
becomes a two-character pair, and plain ASCII around it stays perfect.
Put ^CI28 once near the top of the format, before the first
^FD. It tells the printer to decode field data as UTF-8 — the
same assumption your system already makes. Any other numeric
^CI value selects a single-byte legacy table and only remaps a
handful of positions; for real multilingual text, 28 is the value that
matches what you send.
^XA
^CI28
^FO50,50^A0N,40,40^FDGüteschließung — Ölçüm^FS
^XZOpen this label in the ZPL viewer →
An honest detail about testing this on screen: a browser preview (ours
included) assumes UTF-8 throughout, so a file without
^CI28 can render perfectly in the preview and still garble on a
printer whose default is a legacy page. The structural check therefore warns
when a numeric ^CI other than 28 is present; the absence of
^CI28 is the thing to check by eye before sending multilingual
text to hardware.
Encoding delivers the right character code; the font must then
contain the character's shape. Built-in printer fonts cover Latin
scripts well but not everything. When a correctly encoded character prints as
a blank or a box, load a TTF that contains the glyph (~DU) and
call it with ^A@ — the label then carries its own font instead
of hoping the printer has one.
For bytes you cannot type — or when an integration mangles raw high-bit
bytes in transit — ^FH switches the field to hex escapes:
^FH^FD_C3_96^FS prints Ö by value. It is the robust path for
generated files where an intermediate system cannot be trusted to preserve
UTF-8 bytes.
When ^CI28 is in the file and the font has the glyph, the
character can still die between your program and the head. Three places to
look, in the order they are usually found:
^CI
through and is not UTF-8 safe; question marks after ^CI28 on a
driver-printed job are this. Send the ZPL raw instead — to port 9100
(how to send ZPL to a
network printer), through Zebra Setup Utilities, or via the ZPL driver
in pass-through mode — or fall back to
^FH hex escapes, which survive any
driver because every byte is plain ASCII.^CW assigns the TTF a letter (^CWR,E:ARIAL.TTF);
if the fields still say ^A0N, the printer draws with font 0 and
its missing glyphs, not with the font you loaded. The field must call the
same identifier (^ARN,40,40) — the
custom fonts guide walks through
loading and calling, and the
font inspector lists which font each
field actually resolves to.^CI28 then decodes
them as broken multi-byte sequences. Save as UTF-8 without BOM and check the
bytes (ö must be C3 B6) before blaming the printer.The preview assumes UTF-8, so the screen can look right while the paper is wrong. Our linter flags non-ASCII text in a label that has no ^CI command at all: rule ZPL5004 shows an example and the fix.
Your system sends UTF-8, where an accented letter is two bytes; a printer without instructions decodes them with a one-byte legacy code page and prints two wrong characters. Add ^CI28 near the top of the format, before the first ^FD.
A browser preview assumes UTF-8 throughout, so a file without ^CI28 can render perfectly on screen and still garble on hardware whose default is a legacy code page. Check for ^CI28 before sending multilingual text to a printer.
Encoding delivers the character code; the font must contain its shape. Load a TTF with the glyph via ~DU and call it with ^A@, so the label carries its own font instead of relying on the printer's built-ins.
Three usual reasons: the job goes through a generic Windows driver that does not pass ^CI through (send the ZPL raw or use ^FH hex escapes); the text still calls font 0 while the downloaded font was assigned another letter with ^CW; or the file was saved as ANSI/Windows-1254 instead of UTF-8.
Raw text and control characters instead of a label point to dump mode; truly scrambled glyphs point to a language mismatch. Telling them apart takes a minute.
Only the last graphic printsA format with several ^GB boxes prints only the final one on a mobile printer. The file is usually innocent: check the active printer language first.
Every label in the job prints the same time (^FC, ^SL)A multi-label ZPL job stamps every label with the same clock value. That is ^SL's documented default, not a bug — and ^SLT changes it.
Zebra prints an extra blank labelA blank label after every print, a skipped or half-printed label: two causes in the ZPL (^LL, ^PQ), two in the printer, one in the driver. Check in that order.