From 5df970013ebd2eaad2d9b88299938ecc3e8cb722 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 15 Dec 2021 18:16:51 +0530 Subject: [PATCH 1/5] feat: translations in Data Import --- frappe/core/doctype/data_export/exporter.py | 2 +- frappe/core/doctype/data_import/exporter.py | 10 +- frappe/core/doctype/data_import/importer.py | 135 +++++++++++------- frappe/handler.py | 2 +- .../js/frappe/data_import/import_preview.js | 4 +- 5 files changed, 95 insertions(+), 58 deletions(-) diff --git a/frappe/core/doctype/data_export/exporter.py b/frappe/core/doctype/data_export/exporter.py index c5cf67ba57..88c469ce71 100644 --- a/frappe/core/doctype/data_export/exporter.py +++ b/frappe/core/doctype/data_export/exporter.py @@ -369,7 +369,7 @@ class DataExporter: self.append_field_column(frappe._dict({ "fieldname": "name" if dt else self.name_field, "parent": dt or "", - "label": "ID", + "label": _("ID"), "fieldtype": "Data", "reqd": 1, }), True) diff --git a/frappe/core/doctype/data_import/exporter.py b/frappe/core/doctype/data_import/exporter.py index 21faf98e49..c09bd58c25 100644 --- a/frappe/core/doctype/data_import/exporter.py +++ b/frappe/core/doctype/data_import/exporter.py @@ -5,6 +5,7 @@ import typing import frappe +from frappe import _ from frappe.model import ( display_fieldtypes, no_value_fields, @@ -215,9 +216,9 @@ class Exporter: for df in self.fields: is_parent = not df.is_child_table_field if is_parent: - label = df.label + label = _(df.label) else: - label = "{0} ({1})".format(df.label, df.child_table_df.label) + label = "{0} ({1})".format(_(df.label), _(df.child_table_df.label)) if label in header: # this label is already in the header, @@ -227,6 +228,7 @@ class Exporter: label = "{0}".format(df.fieldname) else: label = "{0}.{1}".format(df.child_table_df.fieldname, df.fieldname) + header.append(label) self.csv_array.append(header) @@ -253,10 +255,10 @@ class Exporter: self.build_xlsx_response() def build_csv_response(self): - build_csv_response(self.get_csv_array_for_export(), self.doctype) + build_csv_response(self.get_csv_array_for_export(), _(self.doctype)) def build_xlsx_response(self): - build_xlsx_response(self.get_csv_array_for_export(), self.doctype) + build_xlsx_response(self.get_csv_array_for_export(), _(self.doctype)) def group_children_data_by_parent(self, children_data: typing.Dict[str, list]): return groupby_metric(children_data, key='parent') diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index 28880e7e38..b98a307d87 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -262,7 +262,7 @@ class Importer: rows = [header_row] rows += [row.data for row in self.import_file.data if row.row_number in row_indexes] - build_csv_response(rows, self.doctype) + build_csv_response(rows, _(self.doctype)) def print_import_log(self, import_log): failed_records = [log for log in import_log if not log.success] @@ -1009,18 +1009,12 @@ def build_fields_dict_for_column_matching(parent_doctype): out = {} # doctypes and fieldname if it is a child doctype - doctypes = [[parent_doctype, None]] + [ - [df.options, df] for df in parent_meta.get_table_fields() + doctypes = [(parent_doctype, None)] + [ + (df.options, df) for df in parent_meta.get_table_fields() ] for doctype, table_df in doctypes: # name field - name_by_label = ( - "ID" if doctype == parent_doctype else "ID ({0})".format(table_df.label) - ) - name_by_fieldname = ( - "name" if doctype == parent_doctype else "{0}.name".format(table_df.fieldname) - ) name_df = frappe._dict( { "fieldtype": "Data", @@ -1031,63 +1025,104 @@ def build_fields_dict_for_column_matching(parent_doctype): } ) - if doctype != parent_doctype: + if doctype == parent_doctype: + name_headers = ( + "name", # fieldname + "ID", # label + _("ID"), # translated label + ) + else: + name_headers = ( + "{0}.name".format(table_df.fieldname), # fieldname + "ID ({0})".format(table_df.label), # label + "{0} ({1})".format(_("ID"), _(table_df.label)), # translated label + ) + name_df.is_child_table_field = True name_df.child_table_df = table_df - out[name_by_label] = name_df - out[name_by_fieldname] = name_df + for header in name_headers: + out[header] = name_df # other fields + table_fields = parent_meta.get( + "fields", {"fieldtype": ["in", table_fieldtypes]} + ) + + for table_field in table_fields: + table_field.translated_label = _(table_field.label) + fields = get_standard_fields(doctype) + frappe.get_meta(doctype).fields for df in fields: - label = (df.label or "").strip() fieldtype = df.fieldtype or "Data" + if fieldtype in no_value_fields: + continue + + label = (df.label or "").strip() + translated_label = _(label) parent = df.parent or parent_doctype - if fieldtype not in no_value_fields: - if parent_doctype == doctype: - # for parent doctypes keys will be - # Label - # label - # Label (label) - if not out.get(label): - # if Label is already set, don't set it again - # in case of duplicate column headers - out[label] = df - out[df.fieldname] = df - label_with_fieldname = "{0} ({1})".format(label, df.fieldname) - out[label_with_fieldname] = df - else: - # in case there are multiple table fields with the same doctype - # for child doctypes keys will be - # Label (Table Field Label) - # table_field.fieldname - table_fields = parent_meta.get( - "fields", {"fieldtype": ["in", table_fieldtypes], "options": parent} - ) - for table_field in table_fields: - by_label = "{0} ({1})".format(label, table_field.label) - by_fieldname = "{0}.{1}".format(table_field.fieldname, df.fieldname) - # create a new df object to avoid mutation problems - if isinstance(df, dict): - new_df = frappe._dict(df.copy()) - else: - new_df = df.as_dict() + if parent_doctype == doctype: + # for parent doctypes keys will be + # Label, fielname, Label (fieldname) - new_df.is_child_table_field = True - new_df.child_table_df = table_field - out[by_label] = new_df - out[by_fieldname] = new_df + for header in (label, translated_label): + # if Label is already set, don't set it again + # in case of duplicate column headers + if header not in out: + out[header] = df + + for header in ( + df.fieldname, + f"{label} ({df.fieldname})", + f"{translated_label} ({df.fieldname})" + ): + out[header] = df + + else: + # in case there are multiple table fields with the same doctype + # for child doctypes keys will be + # Label (Table Field Label) + # table_field.fieldname + + + for table_field in table_fields: + if table_field.options != parent: + continue + + # create a new df object to avoid mutation problems + if isinstance(df, dict): + new_df = frappe._dict(df.copy()) + else: + new_df = df.as_dict() + + new_df.is_child_table_field = True + new_df.child_table_df = table_field + + for header in ( + # fieldname + "{0}.{1}".format(table_field.fieldname, df.fieldname), + # label + "{0} ({1})".format(label, table_field.label), + # translated label + "{0} ({1})".format(translated_label, table_field.translated_label), + ): + out[header] = new_df # if autoname is based on field # add an entry for "ID (Autoname Field)" autoname_field = get_autoname_field(parent_doctype) if autoname_field: - out["ID ({})".format(autoname_field.label)] = autoname_field - # ID field should also map to the autoname field - out["ID"] = autoname_field - out["name"] = autoname_field + for header in ( + "ID ({})".format(autoname_field.label), # label + "{0} ({1})".format(_("ID"), _(autoname_field.label)), # translated label + + # ID field should also map to the autoname field + "ID", + _("ID"), + "name", + ): + out[header] = autoname_field return out diff --git a/frappe/handler.py b/frappe/handler.py index 35063ee9d6..2c2b5723fa 100755 --- a/frappe/handler.py +++ b/frappe/handler.py @@ -260,7 +260,7 @@ def run_doc_method(method, docs=None, dt=None, dn=None, arg=None, args=None): # build output as csv if cint(frappe.form_dict.get('as_csv')): - build_csv_response(response, doc.doctype.replace(' ', '')) + build_csv_response(response, _(doc.doctype).replace(' ', '')) return frappe.response['message'] = response diff --git a/frappe/public/js/frappe/data_import/import_preview.js b/frappe/public/js/frappe/data_import/import_preview.js index 786692e552..75bfb90bde 100644 --- a/frappe/public/js/frappe/data_import/import_preview.js +++ b/frappe/public/js/frappe/data_import/import_preview.js @@ -343,11 +343,11 @@ function get_fields_as_options(doctype, column_map) { return [].concat( ...keys.map(key => { return column_map[key].map(df => { - let label = df.label; + let label = __(df.label); let value = df.fieldname; if (doctype !== key) { let table_field = frappe.meta.get_docfield(doctype, key); - label = `${df.label} (${table_field.label})`; + label = `${__(df.label)} (${__(table_field.label)})`; value = `${table_field.fieldname}.${df.fieldname}`; } return { From a952c8994d2f9665a05b96eab03e1e8f025bf331 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 15 Dec 2021 18:55:23 +0530 Subject: [PATCH 2/5] fix: remove unnecessary loop --- frappe/core/doctype/data_import/importer.py | 49 ++++++++------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index b98a307d87..c72c67c4c7 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -1014,6 +1014,8 @@ def build_fields_dict_for_column_matching(parent_doctype): ] for doctype, table_df in doctypes: + translated_table_label = _(table_df.label) if table_df else None + # name field name_df = frappe._dict( { @@ -1035,7 +1037,7 @@ def build_fields_dict_for_column_matching(parent_doctype): name_headers = ( "{0}.name".format(table_df.fieldname), # fieldname "ID ({0})".format(table_df.label), # label - "{0} ({1})".format(_("ID"), _(table_df.label)), # translated label + "{0} ({1})".format(_("ID"), translated_table_label), # translated label ) name_df.is_child_table_field = True @@ -1044,14 +1046,6 @@ def build_fields_dict_for_column_matching(parent_doctype): for header in name_headers: out[header] = name_df - # other fields - table_fields = parent_meta.get( - "fields", {"fieldtype": ["in", table_fieldtypes]} - ) - - for table_field in table_fields: - table_field.translated_label = _(table_field.label) - fields = get_standard_fields(doctype) + frappe.get_meta(doctype).fields for df in fields: fieldtype = df.fieldtype or "Data" @@ -1085,29 +1079,24 @@ def build_fields_dict_for_column_matching(parent_doctype): # Label (Table Field Label) # table_field.fieldname + # create a new df object to avoid mutation problems + if isinstance(df, dict): + new_df = frappe._dict(df.copy()) + else: + new_df = df.as_dict() - for table_field in table_fields: - if table_field.options != parent: - continue + new_df.is_child_table_field = True + new_df.child_table_df = table_df - # create a new df object to avoid mutation problems - if isinstance(df, dict): - new_df = frappe._dict(df.copy()) - else: - new_df = df.as_dict() - - new_df.is_child_table_field = True - new_df.child_table_df = table_field - - for header in ( - # fieldname - "{0}.{1}".format(table_field.fieldname, df.fieldname), - # label - "{0} ({1})".format(label, table_field.label), - # translated label - "{0} ({1})".format(translated_label, table_field.translated_label), - ): - out[header] = new_df + for header in ( + # fieldname + "{0}.{1}".format(table_df.fieldname, df.fieldname), + # label + "{0} ({1})".format(label, table_df.label), + # translated label + "{0} ({1})".format(translated_label, translated_table_label), + ): + out[header] = new_df # if autoname is based on field # add an entry for "ID (Autoname Field)" From e6d550b45199a576c613eae9f6a801f9ccdb3089 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 15 Dec 2021 19:11:43 +0530 Subject: [PATCH 3/5] fix: remove unnecessary translation --- frappe/core/doctype/data_export/exporter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/data_export/exporter.py b/frappe/core/doctype/data_export/exporter.py index 88c469ce71..c5cf67ba57 100644 --- a/frappe/core/doctype/data_export/exporter.py +++ b/frappe/core/doctype/data_export/exporter.py @@ -369,7 +369,7 @@ class DataExporter: self.append_field_column(frappe._dict({ "fieldname": "name" if dt else self.name_field, "parent": dt or "", - "label": _("ID"), + "label": "ID", "fieldtype": "Data", "reqd": 1, }), True) From 8b8f03f2d1f5b3c5cac38c93d45db2184ebe8634 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Thu, 16 Dec 2021 10:54:57 +0530 Subject: [PATCH 4/5] fix: remove irrelevant comment --- frappe/core/doctype/data_import/importer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index c72c67c4c7..2ed75f869d 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -1074,7 +1074,6 @@ def build_fields_dict_for_column_matching(parent_doctype): out[header] = df else: - # in case there are multiple table fields with the same doctype # for child doctypes keys will be # Label (Table Field Label) # table_field.fieldname From 6dc67835c5eb3497498432181590c55865934aaa Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Mon, 20 Dec 2021 19:01:31 +0530 Subject: [PATCH 5/5] fix: typo in comment Co-authored-by: Faris Ansari --- frappe/core/doctype/data_import/importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/core/doctype/data_import/importer.py b/frappe/core/doctype/data_import/importer.py index 2ed75f869d..b9b2050763 100644 --- a/frappe/core/doctype/data_import/importer.py +++ b/frappe/core/doctype/data_import/importer.py @@ -1058,7 +1058,7 @@ def build_fields_dict_for_column_matching(parent_doctype): if parent_doctype == doctype: # for parent doctypes keys will be - # Label, fielname, Label (fieldname) + # Label, fieldname, Label (fieldname) for header in (label, translated_label): # if Label is already set, don't set it again