Why accented characters come out garbled on your label

An address with ç or ã prints as a box and a stray symbol. The cause is one missing line in the file, and the fix is five characters long.

The symptom

The label converts, the barcode is perfect, and the recipient name comes out like this:

endere□°o Jo□úo

Instead of "endereço João". The ç became a box followed by a symbol, the ã became something else. Every accented character turns into two wrong ones, always in the same places.

It is not the converter and not the printer. It is the file saying one thing and meaning another.

The cause: ZPL does not assume UTF-8

When the system that produced the label wrote "endereço", it stored the ç as two bytes, which is how UTF-8 represents that character. Nothing wrong so far.

The trouble is at the other end. With no instruction otherwise, ZPL reads each byte as one character from an old 256-slot table that is not UTF-8. The two bytes of the ç are read as two separate characters, and that is exactly what prints: two symbols where there should be one.

That is why the defect is always the same shape: every accented character becomes two, and text with no accents comes out perfectly. If your English labels work and your Portuguese or Spanish ones do not, this is why.

The fix: ^CI28 right after ^XA

The ^CI command chooses how the file should be interpreted, and ^CI28 is UTF-8. It goes once per label, right after ^XA:

^XA
^CI28
^FO50,50^A0N,30,30^FDendereço João^FS
^XZ

With that line, the same label prints "endereço João". We rendered both versions against the renderer EasyZPL uses, and that single line is the whole difference.

It has to be repeated in every ^XA … ^XZ block. In a file of fifty labels that is fifty lines, and that is normal: each label is independent of the others by design.

^CI13 does not fix it, whatever the forums say

Searching for this problem turns up people recommending ^CI13. It is a real command and a legitimate character table, and it does not fix this case: we tested it, and the label comes out identical to one with no ^CI at all.

The reason is simple. ^CI13 swaps one 256-slot table for another 256-slot table, and the problem is not which table: it is that UTF-8 does not fit in 256 slots. Only ^CI28 changes the reading rule itself.

When ^CI28 did not help

One case is left, and it starts upstream: ^CI28 says how to interpret the file's bytes, so it cannot repair a file that was saved in a different encoding. If the system that produced the label saved it as Latin-1 or Windows-1252, the accent was already wrong when it left, and no command inside the file undoes that.

How to tell which case you have: open the file in an editor that shows the encoding (VS Code shows it in the status bar). If the accents look right in the editor, the file is UTF-8 and only ^CI28 is missing. If they look wrong there too, the problem belongs to whoever generated it.

In that second case the fix is to ask the sender to correct it, or, if it is urgent, to generate the label without accents. An address with no accents gets delivered; an address full of boxes sometimes does not.

← All guides