文章目录
- 一、问题由来
- 二、排查经过
- 1. 问 deepseek
- 2. 验证
- 3. 新问题
- 三、 总结
- 四、补充(翻译模型 `ir.translation` 中 `src` 和 `value` 字段详解)
一、问题由来
客户有多个公司,使用多个数据库。他们有时需要同步不同数据库之间的数据的需求。在实现的时候,会判断产品名称是否一样。
前提:他们习惯使用中文环境。
发现问题:明明form视图上显示的产品名称一样,同步的时候总是提示,产品名称不一样。(视图上已经排除中英文翻译不一致的问题)
二、排查经过
追根溯源: 查询数据库,发现数据库中存储的name跟视图上显示的name不一样。
视图上显示:7439-95-4/镁块(xie)
数据中存储:7439-95-4/镁屑
数据查询:
如下图:form视图上显示都是:7439-95-4/镁块(xie)
我把左边的叫 A 数据库的;右边叫做 B 数据库的。
该产品在 A 数据库中的产品id是5585,在 B 数据库中的产品id是13。
如下图:B 数据库中显示的存储值是:7439-95-4/镁屑
修改思路: 是从A同步到B,所以后续修改都是看怎么把B中的产品名称改成跟A一样的。
1. 问 deepseek
根据上面建议查询如下:
两个数据库中的翻译值不一样,form视图显示的都是翻译模型中value的值,所以看到的结果是一样的。继续查询产品的name看看:
上面是A数据库的翻译值,下面是B数据库的翻译值。
解释说明:这里提前说下后面的经验成果,利于后续的理解。
ir.translation
模型中我们用到的两个比较重要的字段:src,value。
src: 是视图上根据当前语言输入的原始值 。
value: 是视图上显示的翻译的值
sql 查询B数据库中产品的name,发现跟译文中的 src 一样
总结: 数据库中存储的产品name值跟翻译中src的值一样,但form视图上显示的是 value的值。
通过deepseek提供的方法,修改了译文中的 src 的值后,修改代码如下:
# 如果翻译中存储的源跟显示的产品名不一样,就修改所有翻译中源值和翻译的值def fix_name(self):self.ensure_one()# 获取当前翻译记录translations = self.env['ir.translation'].search([('name', '=', 'product.template,name'),('res_id', '=', self.id)])if translations:# 如果数据库name与翻译src不同,统一为数据库namefor t in translations:if self.name != t.src:t.write({'src': self.name, 'value': self.name})
修改后效果如下:
(这种解决了,视图上显示名和数据库不一致的问题)
ps:解决所有有问题的数据同理。
2. 验证
在英文语言环境下,修改B数据库中该产品的name,发现,英文译文下的 src, value都同步更新后面加了22,其中zh_CN语言下的 src 值也跟着改变了,但是zh_CN状态下的value值没有改变。
如图,只修改B数据库中form视图上中文翻译的值,发现只有zh_CN语言下的value值变了。数据库结果如下:
3. 新问题
通过上述修正后,发现B数据中的产品name还是没有修改过来,通过 ilike 找到这个产品,id是11。
后来查了创建时间发现,产品11和13原来是同名的,后来11归档了,但是13中的name总是跟着11来的,最后在英文环境下修改了11的产品名称,再修改产品11的翻译,这样同步不会出问题了。
完成同步后,把产品11的name又改回去了。
三、 总结
- 如果遇到已有数据存在产品现实名称跟数据库查询名称不一样的问题,多半是多语言翻译的问题;
- ir.translation 模型中src 是在当前语言状态下输入的源值;value是翻译的值,是当前语言环境下显示在form视图上的值;
- 英文状态下修改name值,会同步修改英文状态下翻译中的src和value的值,以及中文状态下的src值,但是不会修改中文下的翻译的值,也就是中文下form视图下显示的值,需要手动修改;
- 如果遇到复制的产品,通过上述还是不一样,则需要修改源头产品的name(原因不知道为啥)
四、补充(翻译模型 ir.translation
中 src
和 value
字段详解)
(以下为deepseek回答,供参考)
在 Odoo 的多语言系统中,
ir.translation
模型负责存储所有可翻译内容的翻译记录,其中src
和value
是两个核心字段:一、字段定义
src
字段:
- 含义:源文本(Source Text)
- 作用:存储原始语言的文本内容
- 特点:
- 这是需要被翻译的原始字符串
- 通常是创建记录时最初使用的语言文本(如英文)
- 作为查找翻译的"键"(与
name
、res_id
等字段组合形成唯一键)
value
字段:
- 含义:翻译值(Translated Value)
- 作用:存储目标语言的翻译文本
- 特点:
- 当此字段有值时,系统会优先显示这个翻译内容
- 如果此字段为空,系统会回退显示
src
的内容- 可以存储不同语言对同一
src
的不同翻译二、工作流程示例
假设原始产品用英文创建,然后翻译为中文:
创建产品时:
python product = env['product.template'].create({'name': 'Magnesium block'})
- 数据库
product.template
表中的name
: “Magnesium block”- 此时
ir.translation
尚无记录添加中文翻译后:
ir.translation
记录:
src
: “Magnesium block” (原始文本)value
: “镁块” (中文翻译)lang
: “zh_CN” (目标语言)三、重要行为特点
显示优先级:
- 系统会优先显示
value
字段的内容(如果存在且当前语言匹配)- 如果
value
为空或语言不匹配,则显示src
内容- 如果都为空,则显示数据库字段的原始值
数据一致性:
- 理想情况下,
src
应该与数据库中原始记录的字段值保持一致- 但实践中可能出现不一致(如直接更新数据库字段未同步翻译表)
导入/导出影响:
- 通过 Odoo 界面导出翻译时,导出的是
src
→value
的映射- 直接数据库操作可能绕过翻译机制
四、 典型问题场景
您遇到的场景解释:
- 数据库
product.template.name
= “7439-95-4/镁屑”(当前值)- 翻译表中
src
= “7439-95-4/镁块(xie)”(旧值) 这表明:
- 产品名称曾被修改过(从"镁块(xie)“改为"镁屑”)
- 但修改操作没有同步更新翻译表中的
src
字段- 系统可能仍在使用旧的翻译记录
五、 最佳实践建议
修改数据时:
- 始终通过标准API(如
write()
方法)修改可翻译字段- 避免直接SQL更新
数据同步:
python # 当修改可翻译字段时,同步更新翻译记录 product.write({'name': '新名称'}) translations = env['ir.translation'].search([ ('name', '=', 'product.template,name'), ('res_id', '=', product.id) ]) translations.write({'src': '新名称'})
查询数据时:
- 如需获取原始值,直接查询模型字段
- 如需获取翻译值,使用
with_context(lang=lang)
或display_name
字段理解
src
和value
的区别对于解决Odoo多语言系统中的显示问题至关重要,特别是在处理数据迁移或自定义模块开发时。