details: https://code.tryton.org/tryton/commit/dba330085af9
branch: default
user: Cédric Krier <[email protected]>
date: Fri Oct 02 14:58:38 2026 +0200
description:
Support reading translated fields in any suffixed language
Closes #15132
diffstat:
trytond/CHANGELOG | 1 +
trytond/doc/ref/models.rst | 4 ++
trytond/trytond/model/modelsql.py | 14 +++++++++
trytond/trytond/tests/test_modelsql.py | 49 ++++++++++++++++++++++++++++++++++
4 files changed, 68 insertions(+), 0 deletions(-)
diffs (119 lines):
diff -r beb60346fb5d -r dba330085af9 trytond/CHANGELOG
--- a/trytond/CHANGELOG Fri Oct 16 10:52:57 2026 +0200
+++ b/trytond/CHANGELOG Fri Oct 02 14:58:38 2026 +0200
@@ -1,3 +1,4 @@
+* Support reading translated fields in any suffixed language
* Rename delete_many to deletemany in the FileStore
* Restrict the wizard session to the user who created it (issue15206)
* Only permit administrators to execute wizards without models or groups
(issue15205)
diff -r beb60346fb5d -r dba330085af9 trytond/doc/ref/models.rst
--- a/trytond/doc/ref/models.rst Fri Oct 16 10:52:57 2026 +0200
+++ b/trytond/doc/ref/models.rst Fri Oct 02 14:58:38 2026 +0200
@@ -403,6 +403,10 @@
:class:`~fields.Selection` or :class:`~fields.MultiSelection` fields.
Their human-readable value are returned.
+ ``fields_names`` can also contain ``<field>:<language>`` for translatable
+ fields.
+ Their translated values are returned.
+
The virtual fields ``_write`` and ``_delete`` can be used the read the
writeable and deleteable state of the records.
Regarding the ``_timestamp`` virtual fields it contains a timestamp that is
diff -r beb60346fb5d -r dba330085af9 trytond/trytond/model/modelsql.py
--- a/trytond/trytond/model/modelsql.py Fri Oct 16 10:52:57 2026 +0200
+++ b/trytond/trytond/model/modelsql.py Fri Oct 02 14:58:38 2026 +0200
@@ -1202,6 +1202,7 @@
extra_fields = set()
if 'write_date' not in fields_names:
extra_fields.add('write_date')
+ fields_translated = []
for field_name in fields_names:
if field_name in {'_timestamp', '_write', '_delete', '__name__'}:
continue
@@ -1211,6 +1212,10 @@
if field_name.endswith(':string'):
field_name = field_name[:-len(':string')]
fields_related[field_name]
+ elif ':' in field_name:
+ field_name, language = field_name.split(':', 1)
+ fields_translated.append((field_name, language))
+ extra_fields.add(field_name)
field = cls._fields[field_name]
if hasattr(field, 'datetime_field') and field.datetime_field:
extra_fields.add(field.datetime_field)
@@ -1312,6 +1317,15 @@
max_write_date = max(
(r['write_date'] for r in result if r.get('write_date')),
default=None)
+
+ for fname, language in fields_translated:
+ translations = Translation.get_ids(
+ f'{cls.__name__},{fname}', 'model', language, ids,
+ cached_after=max_write_date)
+ for row in result:
+ row[f'{fname}:{language}'] = (
+ translations.get(row['id']) or row[fname])
+
for fname, column in columns.items():
if fname.startswith('_'):
continue
diff -r beb60346fb5d -r dba330085af9 trytond/trytond/tests/test_modelsql.py
--- a/trytond/trytond/tests/test_modelsql.py Fri Oct 16 10:52:57 2026 +0200
+++ b/trytond/trytond/tests/test_modelsql.py Fri Oct 02 14:58:38 2026 +0200
@@ -1755,6 +1755,55 @@
self.assertEqual(other.name, "Bar")
@with_transaction()
+ def test_read_multiple_languages(self):
+ "Test read multiple languages"
+ pool = Pool()
+ Model = pool.get('test.modelsql.translation')
+ transaction = Transaction()
+
+ with transaction.set_context(language=self.default_language):
+ record, = Model.create([{'name': "Foo"}])
+ with transaction.set_context(language=self.other_language):
+ Model.write([record], {'name': "Bar"})
+
+ values = Model.read([record.id], [
+ 'name',
+ f'name:{self.default_language}',
+ f'name:{self.other_language}',
+ ])
+
+ self.assertEqual(values, [{
+ 'id': record.id,
+ 'name': "Foo",
+ f'name:{self.default_language}': "Foo",
+ f'name:{self.other_language}': "Bar",
+ }])
+
+ @with_transaction()
+ def test_read_multiple_languages_fallback(self):
+ "Test read multiple languages with fallback"
+ pool = Pool()
+ Model = pool.get('test.modelsql.translation')
+ transaction = Transaction()
+
+ with transaction.set_context(language=self.default_language):
+ record, = Model.create([{'name': "Foo"}])
+ with transaction.set_context(language=self.other_language):
+ Model.write([record], {'name': "Bar"})
+
+ with transaction.set_context(language=self.other_language):
+ values = Model.read([record.id], [
+ f'name:{self.other_language}',
+ 'name:unknown',
+ ])
+
+ self.assertEqual(values, [{
+ 'id': record.id,
+ f'name:{self.other_language}': "Bar",
+ 'name:unknown': "Foo",
+ }])
+
+ @with_transaction()
def test_read_last_translation(self):
"Test read last translation record"
pool = Pool()