Add language support per field in export data

Closes #13266
This commit is contained in:
Cédric Krier
2024-05-19 19:58:16 +02:00
parent e98b1f2559
commit 822e716070
10 changed files with 89 additions and 17 deletions
+1
View File
@@ -1,3 +1,4 @@
* Support language suffix in CSV export
* Close tab with mouse middle click
* Support language suffix in CSV import
+28 -10
View File
@@ -1196,6 +1196,15 @@
Sao.Window.CSV = Sao.class_(Object, {
init: function(title) {
this.languages = Sao.rpc({
'method': 'model.ir.lang.search_read',
'params': [
[['translatable', '=', true]],
0, null, null, ['code', 'name'],
{},
],
}, this.session, false);
this.dialog = new Sao.Dialog(title, 'csv', 'lg');
this.el = this.dialog.modal;
@@ -1398,14 +1407,6 @@
this.session = Sao.Session.current_session;
this.fields_data = {}; // Ask before Removing this.
this.fields_invert = {};
this.languages = Sao.rpc({
'method': 'model.ir.lang.search_read',
'params': [
[['translatable', '=', true]],
0, null, null, ['code', 'name'],
{},
],
}, this.session, false);
Sao.Window.Import._super.init.call(this,
Sao.i18n.gettext('CSV Import: %1', name));
@@ -1983,8 +1984,25 @@
this.fields[path] = node;
// Insert relation only to real field
if (item.name.indexOf('.') == -1 && item.field.relation) {
node.children = {};
if (item.name.indexOf('.') == -1) {
if (item.field.relation) {
node.children = {};
} else if (item.field.translate) {
node.children = {};
for (const language of this.languages) {
const l_path = `${path}:lang=${language.code}`;
const l_string = (
`${long_string} (${language.name})`);
const l_node = {
path: l_path,
string: language.name,
long_string: l_string,
relation: null,
};
node.children[language.code] = l_node;
this.fields[l_path] = l_node;
}
}
}
}
}
+1
View File
@@ -1,3 +1,4 @@
* Support language suffix in CSV export
* Close tab with mouse middle click
* Support language suffix in CSV import
+6 -1
View File
@@ -7,7 +7,7 @@ import sys
from gi.repository import Gdk, GObject, Gtk
from tryton.common import IconFactory
from tryton.common import IconFactory, RPCExecute
from tryton.common.underline import set_underline
from tryton.config import TRYTON_ICON
from tryton.gui import Main
@@ -36,6 +36,11 @@ class WinCSV(NoModal):
def __init__(self, *args, **kwargs):
super(WinCSV, self).__init__(*args, **kwargs)
self.languages = RPCExecute(
'model', 'ir.lang', 'search_read', [
('translatable', '=', True),
], 0, None, [('name', 'DESC')], ['code', 'name'])
self.dialog = Gtk.Dialog(
transient_for=self.parent, destroy_with_parent=True)
Main().add_window(self.dialog)
+7
View File
@@ -176,6 +176,13 @@ class WinExport(WinCSV):
if '.' not in name:
if field.get('relation'):
self.model1.insert(node, 0, [None, ''])
elif field.get('translate', False):
for language in self.languages:
l_path = f"{path}:lang={language['code']}"
l_string = f"{string_} ({language['name']})"
self.model1.insert(
node, 0, [language['name'], l_path])
self.fields[l_path] = (l_string, None)
def _get_fields(self, model):
try:
-4
View File
@@ -26,10 +26,6 @@ class WinImport(WinCSV):
self.fields_data = {}
self.fields = {}
self.fields_invert = {}
self.languages = RPCExecute(
'model', 'ir.lang', 'search_read', [
('translatable', '=', True),
], 0, None, None, ['code', 'name'])
super(WinImport, self).__init__()
self.dialog.set_title(_('CSV Import: %s') % name)
+1
View File
@@ -1,3 +1,4 @@
* Add language support per field in export data
* Add translated descriptor for Char and Text fields
* Include row and column in error message when importing data
* Remove support for ``:id`` suffix in import data
+12
View File
@@ -742,8 +742,11 @@ class ModelStorage(Model):
break
field_name = fields_tree[i]
descriptor = None
language = None
if '.' in field_name:
field_name, descriptor = field_name.split('.')
elif ':lang=' in field_name:
field_name, language = field_name.split(':lang=')
eModel = pool.get(value.__name__)
field = eModel._fields[field_name]
if field.states and 'invisible' in field.states:
@@ -754,6 +757,8 @@ class ModelStorage(Model):
break
if descriptor:
value = getattr(field, descriptor)().__get__(value, eModel)
elif language:
value = field.translated().__get__(value, eModel)(language)
else:
value = getattr(value, field_name)
if isinstance(value, (list, tuple)):
@@ -790,6 +795,7 @@ class ModelStorage(Model):
def _convert_field_names(cls, fields_names):
pool = Pool()
ModelField = pool.get('ir.model.field')
Lang = pool.get('ir.lang')
result = []
for names in fields_names:
descriptions = []
@@ -798,6 +804,9 @@ class ModelStorage(Model):
translated = name.endswith('.translated')
if translated:
name = name[:-len('.translated')]
language = None
if ':lang=' in name:
name, language = name.split(':lang=')
field = class_._fields[name]
field_name = ModelField.get_name(class_.__name__, name)
if translated:
@@ -807,6 +816,9 @@ class ModelStorage(Model):
elif isinstance(field, fields.Reference):
field_name = gettext(
'ir.msg_field_model_name', field=field_name)
if language:
lang = Lang.get(language)
field_name += f' ({lang.name})'
descriptions.append(field_name)
if hasattr(field, 'get_target'):
class_ = field.get_target()
+1
View File
@@ -20,6 +20,7 @@ class ExportData(ModelSQL):
float = fields.Float('Float')
numeric = fields.Numeric('Numeric')
char = fields.Char('Char')
char_translated = fields.Char("Char", translate=True)
text = fields.Text('Text')
date = fields.Date('Date')
datetime = fields.DateTime('DateTime')
+32 -2
View File
@@ -7,6 +7,7 @@ from decimal import Decimal
from trytond.pool import Pool
from trytond.tests.test_tryton import activate_module, with_transaction
from trytond.transaction import Transaction
class ExportDataTestCase(unittest.TestCase):
@@ -130,6 +131,32 @@ class ExportDataTestCase(unittest.TestCase):
ExportData.export_data([export1, export2], ['char']),
[['test'], ['']])
@with_transaction()
def test_char_translated(self):
"Test export_data char translated"
pool = Pool()
ExportData = pool.get('test.export_data')
Language = pool.get('ir.lang')
english, = Language.search([('code', '=', 'en')])
english.translatable = True
english.save()
french, = Language.search([('code', '=', 'fr')])
french.translatable = True
french.save()
with Transaction().set_context(language='en'):
record, = ExportData.create([{'char_translated': 'foo'}])
with Transaction().set_context(language='fr'):
ExportData.write([record], {'char_translated': 'bar'})
self.assertEqual(
ExportData.export_data(
[record],
['char_translated:lang=en', 'char_translated:lang=fr']),
[['foo', 'bar']])
@with_transaction()
def test_text(self):
'Test export_data text'
@@ -433,11 +460,14 @@ class ExportDataTestCase(unittest.TestCase):
export1, = ExportData.create([{
'char': "Test",
"char_translated": "Test 2",
'integer': 2,
}])
self.assertEqual(
ExportData.export_data([export1], ['char', 'integer'], True),
[["Char", "Integer"], ["Test", 2]])
ExportData.export_data(
[export1],
['char', 'char_translated:lang=en', 'integer'], True),
[["Char", "Char (English)", "Integer"], ["Test", "Test 2", 2]])
@with_transaction()
def test_nested_header(self):