diff --git a/odoo/addons/test_new_api/demo_data.xml b/odoo/addons/test_new_api/demo_data.xml
index 9edab779fcc..ff048467183 100644
--- a/odoo/addons/test_new_api/demo_data.xml
+++ b/odoo/addons/test_new_api/demo_data.xml
@@ -16,6 +16,7 @@
Hey dude!
+ hello
@@ -27,6 +28,11 @@
This is a much longer message
+
+
+ first@example.localhost
+
+
diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py
index eec467cd7b4..4f5fbb5ea5e 100644
--- a/odoo/addons/test_new_api/models.py
+++ b/odoo/addons/test_new_api/models.py
@@ -72,7 +72,7 @@ class Discussion(models.Model):
categories = fields.Many2many('test_new_api.category',
'test_new_api_discussion_category', 'discussion', 'category')
participants = fields.Many2many('res.users')
- messages = fields.One2many('test_new_api.message', 'discussion')
+ messages = fields.One2many('test_new_api.message', 'discussion', copy=True)
message_concat = fields.Text(string='Message concatenate')
important_messages = fields.One2many('test_new_api.message', 'discussion',
domain=[('important', '=', True)])
@@ -125,6 +125,7 @@ class Message(models.Model):
'res.partner', compute='_compute_author_partner',
search='_search_author_partner')
important = fields.Boolean()
+ label = fields.Char(translate=True)
@api.one
@api.constrains('author', 'discussion')
diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py
index 45815c6f031..05e736c7361 100644
--- a/odoo/addons/test_new_api/tests/test_new_fields.py
+++ b/odoo/addons/test_new_api/tests/test_new_fields.py
@@ -862,6 +862,40 @@ class TestFields(common.TransactionCase):
self.assertEqual(len(discussion.important_messages), 2)
self.assertEqual(len(discussion.very_important_messages), 2)
+ def test_80_copy(self):
+ Translations = self.env['ir.translation']
+ discussion = self.env.ref('test_new_api.discussion_0')
+ message = self.env.ref('test_new_api.message_0_0')
+ message1 = self.env.ref('test_new_api.message_0_1')
+
+ email = self.env.ref('test_new_api.emailmessage_0_0')
+ self.assertEqual(email.message, message)
+
+ french = self.env['res.lang']._lang_get('fr_FR')
+ french.active = True
+
+ def count(msg):
+ # return the number of translations of msg.label
+ return Translations.search_count([
+ ('name', '=', 'test_new_api.message,label'),
+ ('res_id', '=', msg.id),
+ ])
+
+ # set a translation for message.label
+ email.with_context(lang='fr_FR').label = "bonjour"
+ self.assertEqual(count(message), 1)
+ self.assertEqual(count(message1), 0)
+
+ # setting the parent record should not copy its translations
+ email.copy({'message': message1.id})
+ self.assertEqual(count(message), 1)
+ self.assertEqual(count(message1), 0)
+
+ # setting a one2many should not copy translations on the lines
+ discussion.copy({'messages': [(6, 0, message1.ids)]})
+ self.assertEqual(count(message), 1)
+ self.assertEqual(count(message1), 0)
+
class TestX2many(common.TransactionCase):
def test_search_many2many(self):
diff --git a/odoo/models.py b/odoo/models.py
index e32b35a5870..79997061504 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -3824,7 +3824,13 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
return [default]
@api.multi
- def copy_translations(old, new):
+ def copy_translations(old, new, excluded=()):
+ """ Recursively copy the translations from original to new record
+
+ :param old: the original record
+ :param new: the new record (copy of the original one)
+ :param excluded: a container of user-provided field names
+ """
# avoid recursion through already copied records in case of circular relationship
if '__copy_translations_seen' not in old._context:
old = old.with_context(__copy_translations_seen=defaultdict(set))
@@ -3850,13 +3856,20 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
if not field.copy:
continue
- if field.type == 'one2many':
+ if field.inherited and field.related[0] in excluded:
+ # inherited fields that come from a user-provided parent record
+ # must not copy translations, as the parent record is not a copy
+ # of the old parent record
+ continue
+
+ if field.type == 'one2many' and field.name not in excluded:
# we must recursively copy the translations for o2m; here we
# rely on the order of the ids to match the translations as
# foreseen in copy_data()
old_lines = old[name].sorted(key='id')
new_lines = new[name].sorted(key='id')
for (old_line, new_line) in pycompat.izip(old_lines, new_lines):
+ # don't pass excluded as it is not about those lines
old_line.copy_translations(new_line)
elif field.translate:
@@ -3896,7 +3909,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
vals = self.copy_data(default)[0]
# To avoid to create a translation in the lang of the user, copy_translation will do it
new = self.with_context(lang=None).create(vals)
- self.with_context(from_copy_translation=True).copy_translations(new)
+ self.with_context(from_copy_translation=True).copy_translations(new, excluded=default or ())
return new
@api.multi