1. Odoo18泰文打印乱码问题深度解析
最近在实施一个泰国市场的Odoo18项目时,遇到了一个颇为棘手的问题:系统生成的PDF报告中泰文显示为乱码。这个问题看似简单,实则涉及字符编码、字体配置、PDF生成引擎等多个技术环节的协同工作。经过一周的排查和测试,终于找到了完整的解决方案,这里把整个处理过程和经验总结分享给大家。
相关服务:泰国服务器
重要提示:Odoo的PDF打印功能依赖于wkhtmltopdf工具,而泰文乱码问题90%以上都与字体配置有关,但剩下的10%可能是更隐蔽的系统级问题。
2. 问题现象与初步诊断
2.1 典型乱码表现
在Odoo18中,当尝试打印包含泰文的销售订单或发票时,生成的PDF中泰文字符会呈现以下几种异常情况:
- 完全无法显示(显示为空白)
- 显示为方框"□□□"
- 显示为乱码字符(如"à¸à¸±à¸à¸à¸µà¹à¸à¸°")
- 部分字符正确但音调符号错位
2.2 诊断步骤
首先通过以下命令检查系统基础环境:
# 检查系统支持的泰文字体
fc-list | grep Thai
# 检查wkhtmltopdf版本
wkhtmltopdf --version
# 检查locale设置
locale
常见问题根源包括:
- 服务器缺少泰文字体支持
- wkhtmltopdf编译时未包含字体配置选项
- Odoo模板未正确声明字符编码
- 系统locale设置不正确
3. 完整解决方案
3.1 系统级字体安装
对于Ubuntu/Debian系统:
# 安装泰文字体包
sudo apt-get install fonts-thai-tlwg fonts-sipa-arundina
# 刷新字体缓存
fc-cache -fv
对于CentOS/RHEL系统:
sudo yum install cjkuni-ukai-fonts thai-scalable-fonts
验证字体安装:
fc-list | grep -i "thai"
应能看到类似输出:
/usr/share/fonts/truetype/thai/TlwgTypo.ttf: Tlwg Typo:style=Regular
/usr/share/fonts/truetype/thai/TlwgTypo-Bold.ttf: Tlwg Typo:style=Bold
3.2 wkhtmltopdf专项配置
推荐使用特定版本的wkhtmltopdf:
wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
sudo dpkg -i wkhtmltox_0.12.6-1.focal_amd64.deb
sudo apt-get install -f
创建自定义配置文件:
<!-- /etc/xml/unicode.xml -->
<!DOCTYPE unicode [
<!ENTITY thai-font "Tlwg Typo">
]>
3.3 Odoo模板调整
在报表模板的
<style>
部分添加:
<style>
@page {
size: A4;
margin: 0mm;
}
body {
font-family: 'Tlwg Typo', 'SIPA Arundina', sans-serif;
encoding: 'UTF-8';
}
</style>
对于QWeb报表,需要在
<t>
标签中指定:
<t t-call="web.external_layout">
<t t-set="encoding" t-value="'UTF-8'"/>
...
</t>
4. 进阶问题排查
4.1 音调符号错位问题
泰语的音调符号需要特殊处理,在CSS中添加:
thai-text {
text-rendering: optimizeLegibility;
font-feature-settings: "kern" 1, "liga" 1, "clig" 1, "dlig" 1;
}
4.2 字体回退机制
创建字体回退配置文件:
sudo nano /etc/fonts/local.conf
内容为:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<alias>
<family>serif</family>
<prefer>
<family>Tlwg Typo</family>
<family>SIPA Arundina</family>
</prefer>
</alias>
</fontconfig>
4.3 Docker环境特殊处理
如果使用Docker部署,需要在Dockerfile中添加:
RUN apt-get update && \
apt-get install -y fonts-thai-tlwg fonts-sipa-arundina && \
fc-cache -fv
5. 验证与测试方案
5.1 测试模板
创建一个专门的测试报表:
<odoo>
<template id="report_thai_test">
<t t-call="web.html_container">
<div class="page">
<h1>泰文测试</h1>
<p>正常文本: Hello World</p>
<p>泰文测试: ภาษาไทย</p>
<p>混合文本: 订单 Order123 ภาษาไทย</p>
</div>
</t>
</template>
</odoo>
5.2 自动化测试脚本
创建测试Python脚本:
import os
from odoo.tests.common import TransactionCase
class TestThaiPrinting(TransactionCase):
def test_thai_pdf_generation(self):
report = self.env.ref('your_module.report_thai_test')
pdf_content = report._render_qweb_pdf(report.id, [])[0]
with open('/tmp/thai_test.pdf', 'wb') as f:
f.write(pdf_content)
# 检查PDF是否包含泰文字符
self.assertIn(b'ภาษาไทย', pdf_content)
6. 性能优化建议
- 字体子集化 :使用pyftsubset工具只嵌入使用的字符
pyftsubset TlwgTypo.ttf --text="ภาษาไทย" --output-file=TlwgTypo-subset.ttf
- 缓存机制 :对频繁打印的报表启用缓存
@api.model
def render_qweb_pdf(self, docids, data=None):
cache_key = f"report_{self.id}_{hash(tuple(docids))}"
cached = self.env.cr.cache.get(cache_key)
if cached:
return cached
result = super().render_qweb_pdf(docids, data)
self.env.cr.cache.set(cache_key, result, timeout=3600)
return result
- 异步生成 :对于大批量打印使用队列
@api.model
def generate_reports_async(self, docids):
self.env['queue.job'].create({
'name': 'Generate Thai Reports',
'model_name': 'ir.actions.report',
'method': 'render_qweb_pdf',
'args': (self.id, docids),
})
7. 常见问题速查表
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 全部显示为方框 | 字体未正确安装 | 执行`fc-list |
| 部分字符乱码 | 编码声明错误 |
检查模板中的
<meta charset="UTF-8">
|
| 音调位置错误 | 字体渲染问题 |
添加CSS
text-rendering: optimizeLegibility
|
| 打印速度慢 | 字体文件过大 | 使用字体子集化工具精简字体 |
| Docker中无效 | 字体未装入容器 | 在Dockerfile中添加字体安装指令 |
8. 扩展知识:多语言打印最佳实践
-
字体选择原则 :
- 泰文推荐:Tlwg Typo, SIPA Arundina
- 中文推荐:Noto Sans CJK, Source Han Sans
- 日文推荐:IPAexGothic, Noto Sans JP
-
混合语言处理 :
.multilang {
font-family: 'Tlwg Typo', 'Noto Sans CJK SC', sans-serif;
unicode-range: U+0E00-0E7F, U+4E00-9FFF;
}
- PDF/A合规性 :
# 在报表动作中设置
'report_type': 'pdfa',
'pdfa_metadata': {
'Producer': 'Odoo',
'Creator': 'Your Company',
},
经过这次问题的解决,我深刻体会到国际化系统中小语种支持的重要性。特别是在东南亚市场,泰文、越南文等带有复杂音调符号的文字处理需要格外注意。建议在项目初期就建立多语言测试用例,避免后期大规模返工。





