文章目錄
- 一、問題由來
- 二、排查經過
- 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多語言系統中的顯示問題至關重要,特別是在處理數據遷移或自定義模塊開發時。