Odoo18泰文打印乱码解决方案与多语言PDF生成实践

2026-08-04 16:57:5620 阅读量

1. Odoo18泰文打印乱码问题深度解析

最近在实施一个泰国市场的Odoo18项目时,遇到了一个颇为棘手的问题:系统生成的PDF报告中泰文显示为乱码。这个问题看似简单,实则涉及字符编码、字体配置、PDF生成引擎等多个技术环节的协同工作。经过一周的排查和测试,终于找到了完整的解决方案,这里把整个处理过程和经验总结分享给大家。

相关服务:泰国服务器

重要提示:Odoo的PDF打印功能依赖于wkhtmltopdf工具,而泰文乱码问题90%以上都与字体配置有关,但剩下的10%可能是更隐蔽的系统级问题。

2. 问题现象与初步诊断

2.1 典型乱码表现

在Odoo18中,当尝试打印包含泰文的销售订单或发票时,生成的PDF中泰文字符会呈现以下几种异常情况:

  1. 完全无法显示(显示为空白)
  2. 显示为方框"□□□"
  3. 显示为乱码字符(如"à¸à¸±à¸à¸à¸µà¹à¸à¸°")
  4. 部分字符正确但音调符号错位

2.2 诊断步骤

首先通过以下命令检查系统基础环境:

# 检查系统支持的泰文字体
fc-list | grep Thai

# 检查wkhtmltopdf版本
wkhtmltopdf --version

# 检查locale设置
locale

常见问题根源包括:

  1. 服务器缺少泰文字体支持
  2. wkhtmltopdf编译时未包含字体配置选项
  3. Odoo模板未正确声明字符编码
  4. 系统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

内容为:

Odoo18泰文打印乱码解决方案与多语言PDF生成实践

<?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. 性能优化建议

  1. 字体子集化 :使用pyftsubset工具只嵌入使用的字符
pyftsubset TlwgTypo.ttf --text="ภาษาไทย" --output-file=TlwgTypo-subset.ttf
  1. 缓存机制 :对频繁打印的报表启用缓存
@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
  1. 异步生成 :对于大批量打印使用队列
@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. 扩展知识:多语言打印最佳实践

  1. 字体选择原则

    • 泰文推荐:Tlwg Typo, SIPA Arundina
    • 中文推荐:Noto Sans CJK, Source Han Sans
    • 日文推荐:IPAexGothic, Noto Sans JP
  2. 混合语言处理

.multilang {
    font-family: 'Tlwg Typo', 'Noto Sans CJK SC', sans-serif;
    unicode-range: U+0E00-0E7F, U+4E00-9FFF;
}
  1. PDF/A合规性
# 在报表动作中设置
'report_type': 'pdfa',
'pdfa_metadata': {
    'Producer': 'Odoo',
    'Creator': 'Your Company',
},

经过这次问题的解决,我深刻体会到国际化系统中小语种支持的重要性。特别是在东南亚市场,泰文、越南文等带有复杂音调符号的文字处理需要格外注意。建议在项目初期就建立多语言测试用例,避免后期大规模返工。

本文地址:https://www.idc504.com/news/9_211078.html