在柬埔寨、老挝、缅甸开店:小票上的当地文字怎么才印得对

这三个国家的华人店铺不少,收银系统却是这份资料里最容易踩坑的一类。

先把结论放前面,方便你直接拿去问供应商:

本文核对状态

文字本身的部分,是照 Unicode 标准字符数据库(UCD 13.0.0) 一个字符一个字符核对过的:每个元音符号的属性、柬文叠字符号的属性、 各国数字的编号范围、有没有货币符号,字符数和字节数都是实际数出来的。 断行规则读的是 Unicode 官方文档 UAX #14(第 55 版,2025-09-05)。 "没有编码"这一条,查的是微软官方公布的编码页清单。这部分比较硬。

打印机怎么表现、当地小票习惯、税务规定,全部没核实。

待核实清单 —— TODO: verify

  1. 你要买的那台打印机,字库里到底有没有这三种文字。大概率没有, 但要自己确认,别信参数表上写的"支持多国语言"。
  2. 打印机印图片的能力:最大宽度多少点、印一张全图片小票要多久。 接受了第一节的结论之后,这条就是最关键的一条。
  3. 店里真正要用的那台收银机上有没有对应字体和断词词库。 不是供应商演示用的电脑。这条是最常见的翻车点。
  4. 你手上现有的缅甸文商品资料,到底是哪一套写法,会不会两套混在一起。
  5. 当地小票上是印本地数字还是印阿拉伯数字(09),是习惯还是规定。
  6. 缅甸的货币在小票上怎么写 —— Unicode 里根本没有缅元的货币符号。
  7. 税务、发票、小票必印字段,这份资料一个字都没有。 柬埔寨、老挝、缅甸三个国家篇一篇都没写过,必须另外找当地会计。见第八节。

一、为什么"换个编码"这条路走不通

热敏打印机自带字库的工作方式是:一个字节对应一个图形。要用这条路, 前提是这门文字有一套现成的"编码表",把字符和字节对应起来。

泰文有。微软公布的编码页清单里,泰文有三条(windows-874x-mac-thai、 还有一条 IBM 的),越南文有一条(windows-1258),印度那边九种文字有九条。

高棉文、老挝文、缅甸文,一条都没有。 不是少,是零。 Windows 没有、苹果没有、IBM 没有,国际标准 ISO/IEC 8859 里也没有相应的部分。

这件事对三种文字的意义不太一样,值得分开说:

柬埔寨文和缅甸文没有编码,是正常的。 这两种文字里,一个字母印成什么样 取决于它前后跟着什么,好几个字符会合并成一个图形, "一个字节对一个图形"这套机制根本表达不了。就算给它分配编码也没用。

老挝文没有编码,才是真正要注意的地方。 老挝文的结构和泰文非常接近 —— 一个辅音,上面下面挂符号,前置元音按看到的顺序存,不合并成新图形。 泰文能用 windows-874,老挝文本来完全可以有一套一样的编码。 但从来没人做过这套标准。

所以老挝这个市场的情况是:技术上最简单,可省事的路照样没有。 供应商说"泰国我们做过,老挝一样",前半句是真的,后半句会让你多花一笔钱。

对你的实际影响: 这三个国家的小票,必须是收银机先把字排好、 渲染成一张图片,再整张发给打印机。这个决定要在买打印机之前定下来, 因为要看的是打印机印图片的能力和速度,不是它的字库列表。 等到验收时才发现,打印机已经买了。

还有一个副作用值得记住:别的国家小票印出乱码,多半是编码选错了; 这三个国家不可能是编码选错,因为压根没有编码可选。 同样的症状在这里只可能是别的原因 —— 缺字体、收银机上没装排版引擎, 或者第二节说的那个。

二、缅甸文最大的坑:两套写法,同一批字符编号

缅甸有一套流通很广的旧写法,叫 Zawgyi。它用的是和标准写法完全相同的 那批字符编号,只是每个编号代表的意思不一样。

为什么这件事对开店的人是个实际问题:

存进系统不报错,导出来也不报错。 两套写法都是合法的 UTF-8, 数据库不会拒绝,Excel 不会提示,导入工具不会报警。 存进去是什么,取出来还是什么,一个字节都不差 —— 只是印出来是另一串字。

数据里没有任何地方写着"这是哪一套"。 编码标注两边都是 UTF-8, 数据库字段类型也一样。区别只存在于看的人装的是哪套字体, 而字体不在数据里。

自动识别只能算概率,不能算确定。 谷歌开源的 Zawgyi 识别工具 (myanmar-tools)用的是训练出来的模型,不是写死的规则, 项目自己给的理由是:写死规则的识别器会把掸语、孟语的正常文字误判成 Zawgyi。 掸语孟语用的字符编号确实和 Zawgyi 占用的那批重叠(这一点照 UCD 核对过)。 如果你店里有掸族员工、卖掸语标注的商品,这正是最容易被误伤的情况。

转换规则是有标准出处的。 Zawgyi 和标准写法之间的转换规则收在 CLDR 里, CLDR 是 Unicode 官方的数据库。myanmar-tools 这个工具本身,项目页面上 明确写着不是谷歌的官方产品 —— 两者的可信程度不一样,别混为一谈。

两个方向都是"看起来正常"。 旧写法的数据用新字体看, 或者新写法的数据用旧字体看,出来的都还是一段像模像样的缅甸文, 不是方框也不是问号,只是字不对。不认识缅甸文的人看不出任何异常。

它一般不是从软件进来的,是从商品资料进来的: 供应商发的表格、 店员用自己手机打的商品名、上一套系统里导出来的菜单。

该怎么办:导入商品资料的时候就处理掉 —— 识别、转换、 记下这批资料原来是哪一套。不要留到打印的时候再处理, 因为那时候同一个字段里两套都有,没有统一的答案。

三、老挝像泰国,柬埔寨和缅甸不像

这三种文字都有一类"前置元音"—— 读音在辅音后面,写出来却在辅音左边。 泰文也有。但存的方式不一样,这决定了很多事情。

照 Unicode 字符数据库核对,区别一眼能看出来:

文字 前置元音编号 字符类别 数据里怎么存 打印时要不要调顺序
泰文 U+0E40U+0E44 Lo 按看到的顺序,存在辅音前面 不用
老挝文 U+0EC0U+0EC4 Lo 按看到的顺序,存在辅音前面 不用
高棉文 U+17C1U+17C3 Mc 存在辅音后面
缅甸文 U+1031 Mc 存在辅音后面

Lo 是"字母",能独立存在;Mc 是"要挂在别的字上的符号",单独没有意义。

老挝文和泰文,存的顺序就是印的顺序。 排版时不需要调换。

柬埔寨文和缅甸文,存的顺序和印的顺序是两个顺序。 和印度那一类文字一样。实测:缅甸文 U+1000 U+1031 是两个字符、六个字节, 印出来第二个字符在第一个的左边

这件事在店里表现成四个具体问题:

四、柬埔寨文是往下叠的

高棉文有一种叠字:第二个辅音叠在第一个下面。 负责叠的那个字符是 U+17D2它本身不印出任何东西, 只是一条"把下一个字叠到下面去"的指令。

实测几个例子:

一个字里有 字符数 字节数 印出来
U+179F U+17D2 U+178F 3 9 一个字母,下面叠一个
U+179F U+17D2 U+178F U+17D2 U+179A 5 15 一个字母,下面叠两个
U+1781 U+17D2 U+1789 U+17BB U+17C6 5 15 一整摞,只占一格宽

对你意味着三件事:

五个字符只占一格宽。 系统如果按字符个数去算对齐, 柬文商品名那一列一定会歪 —— 而且用英文测试数据测的时候一切正常。

行距不够会把下面叠的部分切掉。 泰文是上面的声调符号容易被切, 柬文是下面叠的辅音容易被切。切掉之后不是缺一块,是变成另一个词。

千万别让系统"清理"商品名里的不可见字符。 U+17D2 看起来像垃圾字符, 其实是关键指令;柬文还会用 U+200B(零宽空格)标词的边界, 清掉之后断行位置也跟着乱。这两个字符在屏幕上都看不见, 肉眼检查商品资料是查不出来的。

柬文还有一种元音(U+17C4U+17C5),印出来一半在字母左边、 一半在右边。这类元音在数据里是一个字符,没有办法拆开处理。

五、数字和货币符号

三种文字各有自己的一套数字,缅甸文那套还有两份:

文字 数字 编号范围
高棉文 ០១២៣៤៥៦៧៨៩ U+17E0U+17E9
老挝文 ໐໑໒໓໔໕໖໗໘໙ U+0ED0U+0ED9
缅甸文 ၀၁၂၃၄၅၆၇၈၉ U+1040U+1049
掸文 ႐႑႒႓႔႕႖႗႘႙ U+1090U+1099

小票上到底印本地数字还是印 09,是当地习惯问题, 这份资料没核实过(TODO: verify)。但有两条不管在哪都成立: 这件事要做成模板里的一个开关,不能写死在程序里; 同一张小票上绝对不能两种数字混着印。

缅甸有一对特别容易混的字符: U+1040(缅甸数字零)和 U+101D(缅甸字母 wa)是两个不同的字符(这一点核对过), 但长得很像,打字时经常拿字母当零用。 后果是:数量、电话号码这类字段里存进去一个字母, 系统搜不到、对不上、算不了 —— 而且看上去完全正常。

货币符号:柬埔寨和老挝有,缅甸没有。 把 Unicode 里所有货币符号翻了一遍:柬埔寨瑞尔有(U+17DB,៛), 老挝基普有(U+20AD,₭),缅元一个都没有。 所以缅甸的价格该怎么印 —— 用拉丁字母缩写、用缅文写、还是用国际货币代码 —— 这是当地习惯,本文没核实,你要自己确认后再定模板

另外,柬埔寨在零售场合常被描述成美元和瑞尔一起流通。 如果属实,对收银的影响很直接:一个柜台两种货币、 标价一种货币找零另一种、汇率要有人维护。 但这属于国家篇的内容,而本资料没有柬埔寨国家篇, 所以这里只把它列成待核实项,不给答案。

六、断行:这三种文字词和词之间不空格

和泰文一样,这三种文字写起来是连续的,词和词之间不留空格。 Unicode 官方文档 UAX #14 把泰文、老挝文、高棉文、缅甸文归成同一类 (SA),意思是:光看字符本身判断不出哪里可以断行,必须查词库。

没有词库会怎样:系统只能在排不下的地方硬断, 结果是每一个长商品名都从中间断开。 中文断在哪里都还读得懂,这几种文字断错了就是另一串字。

好消息是标准库里有现成的词库。ICU 的官方文档明确写着, 中文、日文、泰文、老挝文、高棉文、缅甸文都有词库支持,而且是自动生效的。 这三种文字全在名单上。

两件事要提醒:

渲染成图片解决不了断行。 断行发生在渲染之前。 先断错了再渲染,只是把错的结果印得很清楚。

要确认词库在店里那台收银机上。 词库是随程序打包的数据, 便宜的安卓收银机为了省空间经常裁掉。开发用的电脑上有,不代表收银机上有。

七、验收清单

每一条都要找一个真正认识这门语言的人来看,不是"认得这是柬埔寨字"就行。

# 测什么 什么算通过
1 印一个带两层叠字的柬文词 两个都叠在下面,底下没被切掉
2 印一个带前置元音的缅文词(U+1031 元音印在辅音左边
3 印一个带 U+17C4 的柬文词 元音一半在左一半在右
4 印一个多层符号的缅文字 是一个整体,没有空心圆圈
5 把商品名截断后打印 整个字一起消失,不留半截符号
6 印一个长到要换行的商品名 断在词和词之间,不是从词中间断开
7 印三行长短不一的商品 金额小数点对齐
8 印一整行满纸宽的当地文字 印到纸边,右边没被切掉
9 印一个带 ៛ 或 ₭ 的价格 符号印得出来,不是方框
10 印一个缅甸的价格 和第五节确认的当地写法一致
11 导入一批已知是旧写法的缅甸文商品资料 被识别并转换,或者被拒绝,不能不声不响存进去
12 在数量字段里输入 U+101D 被当成非数字拒绝,不能存成零
13 商品列表按当地文字排序 顺序和当地人预期一致
14 印一个掸语商品名 没有被误判成旧写法然后"改正"
15 把一笔已完成的交易重新打印一次 和原来那张完全一样
16 以上全部在店里那台真机上再做一遍 和演示时结果一致

第 2、5、11、12、14 条,出问题的时候看起来都是正常的。 第 14 条之所以要单独测,是因为"修复旧写法"这个功能本身也会把好数据改坏。

第 16 条最容易被跳过。演示用的笔记本电脑和店里的收银机不是一台机器。

八、这份资料没覆盖的部分

柬埔寨、老挝、缅甸,这三个国家的国家篇一篇都没写。

也就是说:税率多少、价格要不要含税展示、小票上必须印哪些字段、 税号什么格式、收银机要不要向哪个部门登记、现金抹零合不合法、 柬埔寨双币怎么处理 —— 本资料一条都没查过,一条都不敢写。

这些必须找当地会计或者报税代理确认。系统供应商不是这方面的责任人, 也别指望他们替你把关

九、双语怎么配

这三个市场的华人店铺,常见的配法是:后台管理用中文, 小票和顾客看到的部分用当地文字。 员工是本地人,老板看中文报表。

这个配法本身没问题,但有一件事要提前问清楚: 后台和小票是不是两套独立的语言设置。 有些系统只有一个"语言"开关,一改全改, 结果是老板把界面切成中文之后,小票也跟着变成中文了。

另外,屏幕上缺字体和小票上缺字体,暴露的速度完全不一样: 屏幕上显示成方框,员工当天就会来说; 小票上印错了,是顾客拿走扔掉,你可能几个月都不知道。 所以验收一定要以打印出来的小票为准,不能只看屏幕。

十、挑系统时该问清楚的问题

可以直接拿去问供应商:

  1. 你们印高棉文/缅甸文小票,是靠打印机字库,还是软件渲染成图片? —— 回答"靠字库"或者"加个编码就行"的,基本可以判断没做过。
  2. 能不能现在就打一张当地文字的样票给我看? —— 要求当场打,不接受截图。
  3. 能不能用你们实际会卖给我的那台收银机和打印机打? —— 不是用笔记本电脑打。这条最关键。
  4. 你们怎么处理缅甸文的两套写法?导入商品资料时会不会识别? —— 反问"什么两套写法"的,说明没做过缅甸。
  5. 商品名太长要截断时,你们按什么单位截? —— 应该回答"按用户看到的一个字",回答"按字符"或"按字节"的有问题。
  6. 导入商品资料时你们会不会清理不可见字符? —— 会的话,要确认不会把柬文的叠字符号和零宽空格一起清掉。
  7. 收银机上装了哪些字体?有没有断词词库?能不能列出来? —— 要具体名字,不接受"支持多国语言"这种回答。
  8. 后台语言和小票语言是不是分开设置的?
  9. 打印机印图片的最大宽度是多少?印一张全图片的小票要多久?
  10. 你们在柬埔寨/老挝/缅甸做过几家店?能不能给我看一张真实的小票?
  11. 税务这块,你们做过当地的实施吗? —— 这份资料完全没覆盖税务,无论对方怎么回答, 你都要另外找当地会计确认一遍。

由秘奥软件(MISAll)团队维护。最后更新:2026-08