
在 PrestaShop 1.7 中,即使后台使用英文,也可通过重写 HTMLTemplateInvoice 和 Context 类,使每张发票按对应客户订单的语言(如立陶宛语、拉脱维亚语、爱沙尼亚语)正确渲染,关键在于同步更新上下文语言与翻译器。
在 prestashop 1.7 中,即使后台使用英文,也可通过重写 `htmltemplateinvoice` 和 `context` 类,使每张发票按对应客户订单的语言(如立陶宛语、拉脱维亚语、爱沙尼亚语)正确渲染,关键在于同步更新上下文语言与翻译器。
在 PrestaShop 1.7 的多语言场景中,仅修改 Context::getContext()->language 并不足以触发模板中翻译内容的本地化——因为 Symfony 的 Translator 组件独立维护其语言环境(locale),而 PrestaShop 默认未在 PDF 模板上下文中主动刷新翻译器实例。因此,即使 Context->language->id 已设为 2(立陶宛语),若 translator 仍绑定于后台当前 locale(如 en-US),所有 {l s='...'} 标签仍将输出英文。
✅ 正确解决方案:双管齐下更新语言与翻译器
你需要同时完成两件事:
-
设置正确的
Language实例(含locale属性); -
显式调用
setTranslatorFromLocale(),确保Translator加载对应语言的翻译目录(catalogue)。
以下是你应在主题或模块中覆盖的核心代码:
✅ 1. 重写 HTMLTemplateInvoice.php(位于 /override/classes/pdf/)
<?php class HTMLTemplateInvoice extends HTMLTemplateInvoiceCore
{
public $order;
public $order_invoice;
public $available_in_your_account = false;
public function __construct(OrderInvoice $order_invoice, $smarty, $bulk_mode = false)
{
$this->order_invoice = $order_invoice;
$this->order = new Order((int) $order_invoice->id_order);
$this->smarty = $smarty;
// 兼容旧订单地址为空的情况(官方逻辑保留)
if (!isset($this->order_invoice->shop_address) || !$this->order_invoice->shop_address) {
$this->order_invoice->shop_address = OrderInvoice::getCurrentFormattedShopAddress((int) $this->order->id_shop);
if (!$bulk_mode) {
OrderInvoice::fixAllShopAddresses();
}
}
$this->date = Tools::displayDate($order_invoice->date_add);
// ? 关键:仅当非前台(即后台生成PDF时)才切换上下文语言
// 避免干扰后台其他操作,且需确保员工登录态存在
if (Context::getContext()->employee && $this->order->id_lang) {
$lang = new Language((int) $this->order->id_lang);
Context::getContext()->language = $lang;
Context::getContext()->shop = new Shop((int) $this->order->id_shop);
// ? 强制刷新翻译器,传入 language->locale(如 'lt-LT')
Context::getContext()->setTranslatorFromLocale($lang->locale);
}
$id_lang = Context::getContext()->language->id;
$this->title = $order_invoice->getInvoiceNumberFormatted($id_lang);
$this->shop = new Shop((int) $this->order->id_shop);
}
}
✅ 2. 重写 Context.php(位于 /override/classes/)
<?php class Context extends ContextCore
{
/**
* 手动设置 Translator 实例,基于指定 locale 加载翻译目录
* @param string $locale 如 'lt-LT', 'lv-LV', 'et-EE'
*/
public function setTranslatorFromLocale($locale)
{
$translator = $this->getTranslatorFromLocale($locale);
// 安全检查:确保该 locale 至少有一个翻译条目,避免 fallback 到默认语言
if (count($translator->getCatalogue($locale)->all()) > 0) {
$this->translator = $translator;
} else {
// 可选:记录警告日志(生产环境建议启用)
PrestaShopLogger::addLog("Warning: No translations found for locale '{$locale}'", 3);
}
}
}
⚠️ 注意事项:
- 覆盖文件必须放在
/override/classes/和/override/classes/pdf/目录下,并清除缓存(删除/var/cache/prod/和/cache/class_index.php);- 确保目标语言(如立陶宛语)已在后台「国际 → 语言」中启用,且对应
.xlf翻译文件已部署(位于/translations/lt-LT/);- 若使用自定义 PDF 模板(如
invoice.tpl),请确认其中所有文本均使用{l s='...'}语法,而非硬编码字符串;bulk_mode场景(批量导出发票)下,上述逻辑仍生效,但需注意性能——getTranslatorFromLocale()是轻量级操作,无需担忧。
✅ 验证方式
- 创建一笔立陶宛客户订单(语言 ID=2,locale=
lt-LT); - 在后台「订单 → 查看 → 发票」生成 PDF;
- 检查 PDF 中标题、表头、按钮文字(如 "Invoice" → "Sąskaita faktūra")是否为立陶宛语;
- 同时验证另一笔拉脱维亚订单(ID=3,
lv-LV)是否输出对应语言。
通过此方案,你无需修改核心文件、不依赖钩子、不侵入订单流程,即可实现「后台英语 + 发票多语言」的精准分离,满足跨国电商合规与用户体验双重需求。











