Introduction
Some POS printers that support Arabic require sending the text "1001" encoded, the codepage doesn't exist in windows machines for Arabic languages and there doesn't seem to be a standard way to do the translation.
Background
POS printers don't typically support Unicode characters, and a good number of them doesn't support Arabic at all, the ones I've personally dealt with seems to support Irregular codepage characters for Arabic.
The most common codepage supported for Arabic is "1001", while trying to find out how to do the conversion I've found mutiple threads with the same question and no real answer till I found out that I should handle the translation from my code.
Using the code
- The code is in VB.net, can be easily converted to C# or Java if needed.
- The code can be optimized and extended to cover more characters.
- The code handles certain special cases, for example "لا" and "لأ".
Using the existing class can be as simple as adding the attached class to the project then calling:
var toPrint = Codepage1001.convert("{ARABIC UNICDOE TEXT HERE}")
How it works
First we have a list of Unicode characters assigned to variables:
Dim chars128 As String = "ﺀء"
Dim chars129 As String = "ﺁﺂآ"
Dim chars130 As String = "ﺃﺄأ"
In the above code we notice that each letter appears with all the possible shapes, that's to make the code more robust on different machines, the checks later would decide if a letter is connected to the pervious/next character or not and place the correct value.
The next step is to check every character in the input string and determine if it needs to be translated AND is Arabic or not, if it needs to be translated, is Arabic we prepend the replacement "number" to the buffer for "RTL" effect, else we append the "number" to a separate "LTR" buffer that'd get prepended when we start getting Arabic letters again and if the character is not ASCII we replace it with "?" character.
If chars128.Contains(Mid(unicodestring, i + 1, 1)) Then
en = False
append("128")
ElseIf chars129.Contains(Mid(unicodestring, i + 1, 1)) Then
If isConneted(prev) Then
en = False
append("189")
Else
en = False
append("129")
End If
ElseIf chars130.Contains(Mid(unicodestring, i + 1, 1)) Then
....
We also need to have a special check for the "Lam Alef" character so that it appears normal.
This is how we check for the "Lam Alef" once we find "Lam":
Private Shared Function isLamAlef(ByVal pos, ByVal len, ByVal full)
If pos = len Then
Return False
End If
If "أإا".Contains(Mid(full.ToString, pos + 1, 1)) Then
Return True
End If
Return False
End Function
And this is how we do the replacement:
Private Shared Function getLamAlefCode(ByVal pos, ByVal len, ByVal full)
If Mid(full.ToString, pos + 1, 1).Equals("ا") Then
Return "173"
End If
If Mid(full.ToString, pos + 1, 1).Equals("إ") Then
Return "172"
End If
If Mid(full.ToString, pos + 1, 1).Equals("أ") Then
Return "171"
End If
Return ""
End Function
Points of Interest
- It's much easier to use POS printers as normal printers with special paper sizes.
- If needed due to requirements or specific needs the conversion between Unicode and codepage-1001 has to be done manually.
- The code can be adapted to other languages/character sets facing similar problems.
- Publicly available codepage tables don't have the needed translations and I had to print the letters to a paper to see what they translate to.
History
The code was first written for a project i was working on around October 2012.
The code was published on a public bitbucket repository by the end of October 2012.