From f0155674a5112fc730e01b10d6893c10d9331f1f Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:34:14 +0100 Subject: [PATCH] refactor!: remove redundant sending of translations (#22962) * chore!: remove redundant translation * refactor!: remove "get_translated_dict" hook Instead, include the results from `frappe.geo.country_info.get_translated_dict` in `get_all_translations`. * test: money_in_words uses translated currency ... and now we have translations. * Revert "test: money_in_words uses translated currency" This reverts commit e07d594ac1ce4b120c0fceb5d23377cb981fe820. * refactor!: stop translating timezone and currency * refactor: rename `get_translated_dict` ... to `get_translated_countries` --- frappe/__init__.py | 10 --- frappe/core/doctype/page/page.py | 5 -- frappe/desk/form/meta.py | 16 ---- frappe/geo/country_info.py | 19 ++-- frappe/hooks.py | 5 -- frappe/public/js/frappe/model/meta.js | 8 +- frappe/translate.py | 98 ++------------------- frappe/website/doctype/web_form/web_form.py | 27 +++++- 8 files changed, 39 insertions(+), 149 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 651b52eaec..0f2b822ee3 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -132,16 +132,6 @@ def as_unicode(text: str, encoding: str = "utf-8") -> str: return str(text) -def get_lang_dict(fortype: str, name: str | None = None) -> dict[str, str]: - """Returns the translated language dict for the given type and name. - - :param fortype: must be one of `doctype`, `page`, `report`, `include`, `jsfile`, `boot` - :param name: name of the document for which assets are to be returned.""" - from frappe.translate import get_dict - - return get_dict(fortype, name) - - def set_user_lang(user: str, user_language: str | None = None) -> None: """Guess and set user language for the session. `frappe.local.lang`""" from frappe.translate import get_user_lang diff --git a/frappe/core/doctype/page/page.py b/frappe/core/doctype/page/page.py index 77029b8c67..2f4d48c4a9 100644 --- a/frappe/core/doctype/page/page.py +++ b/frappe/core/doctype/page/page.py @@ -173,11 +173,6 @@ class Page(Document): # flag for not caching this page self._dynamic_page = True - if frappe.lang != "en": - from frappe.translate import get_lang_js - - self.script += get_lang_js("page", self.name) - for path in get_code_files_via_hooks("page_js", self.name): js = get_js(path) if js: diff --git a/frappe/desk/form/meta.py b/frappe/desk/form/meta.py index d0a6b2501c..40497030a9 100644 --- a/frappe/desk/form/meta.py +++ b/frappe/desk/form/meta.py @@ -1,6 +1,5 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE -import io import os import frappe @@ -45,9 +44,6 @@ def get_meta(doctype, cached=True) -> "FormMeta": else: meta = FormMeta(doctype) - if frappe.local.lang != "en": - meta.set_translations(frappe.local.lang) - return meta @@ -256,18 +252,6 @@ class FormMeta(Meta): self.set("__form_grid_templates", templates) - def set_translations(self, lang): - from frappe.translate import extract_messages_from_code, make_dict_from_messages - - self.set("__messages", frappe.get_lang_dict("doctype", self.name)) - - # set translations for grid templates - if self.get("__form_grid_templates"): - for content in self.get("__form_grid_templates").values(): - messages = extract_messages_from_code(content) - messages = make_dict_from_messages(messages) - self.get("__messages").update(messages) - def load_dashboard(self): self.set("__dashboard", self.get_dashboard_data()) diff --git a/frappe/geo/country_info.py b/frappe/geo/country_info.py index 3267149d4c..e07581c056 100644 --- a/frappe/geo/country_info.py +++ b/frappe/geo/country_info.py @@ -8,6 +8,7 @@ import os from functools import lru_cache import frappe +from frappe.utils.deprecations import deprecated from frappe.utils.momentjs import get_all_timezones @@ -38,29 +39,23 @@ def _get_country_timezone_info(): return {"country_info": get_all(), "all_timezones": get_all_timezones()} +@deprecated def get_translated_dict(): - from babel.dates import Locale, get_timezone, get_timezone_name + return get_translated_countries() + + +def get_translated_countries(): + from babel.dates import Locale translated_dict = {} locale = Locale.parse(frappe.local.lang, sep="-") - # timezones - for tz in get_all_timezones(): - timezone_name = get_timezone_name(get_timezone(tz), locale=locale, width="short") - if timezone_name: - translated_dict[tz] = timezone_name + " - " + tz - # country names && currencies for country, info in get_all().items(): country_name = locale.territories.get((info.get("code") or "").upper()) if country_name: translated_dict[country] = country_name - currency = info.get("currency") - currency_name = locale.currencies.get(currency) - if currency_name: - translated_dict[currency] = currency_name - return translated_dict diff --git a/frappe/hooks.py b/frappe/hooks.py index 00efa993ca..e134a2a660 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -269,11 +269,6 @@ scheduler_events = { ], } -get_translated_dict = { - ("doctype", "System Settings"): "frappe.geo.country_info.get_translated_dict", - ("page", "setup-wizard"): "frappe.geo.country_info.get_translated_dict", -} - sounds = [ {"name": "email", "src": "/assets/frappe/sounds/email.mp3", "volume": 0.1}, {"name": "submit", "src": "/assets/frappe/sounds/submit.mp3", "volume": 0.1}, diff --git a/frappe/public/js/frappe/model/meta.js b/frappe/public/js/frappe/model/meta.js index d596d6300b..a27060512f 100644 --- a/frappe/public/js/frappe/model/meta.js +++ b/frappe/public/js/frappe/model/meta.js @@ -16,7 +16,7 @@ $.extend(frappe.meta, { $.each(doc.fields, function (i, df) { frappe.meta.add_field(df); }); - frappe.meta.sync_messages(doc); + if (doc.__print_formats) frappe.model.sync(doc.__print_formats); if (doc.__workflow_docs) frappe.model.sync(doc.__workflow_docs); }, @@ -281,12 +281,6 @@ $.extend(frappe.meta, { return print_format_list; }, - sync_messages: function (doc) { - if (doc.__messages) { - $.extend(frappe._messages, doc.__messages); - } - }, - get_field_currency: function (df, doc) { var currency = frappe.boot.sysdefaults.currency; if (!doc && cur_frm) doc = cur_frm.doc; diff --git a/frappe/translate.py b/frappe/translate.py index a16ad5d823..764e642abe 100644 --- a/frappe/translate.py +++ b/frappe/translate.py @@ -7,6 +7,7 @@ Translation tools for frappe """ + import functools import io import itertools @@ -14,11 +15,9 @@ import json import operator import os import re -from contextlib import contextmanager +from contextlib import contextmanager, suppress from csv import reader, writer -from pypika.terms import PseudoColumn - import frappe from frappe.model.utils import InvalidIncludePath, render_include from frappe.query_builder import DocType, Field @@ -159,81 +158,10 @@ def get_lang_dict(): ) -def get_dict(fortype: str, name: str | None = None) -> dict[str, str]: - """Returns translation dict for a type of object. - - :param fortype: must be one of `doctype`, `page`, `report`, `include`, `jsfile`, `boot` - :param name: name of the document for which assets are to be returned. - """ - fortype = fortype.lower() - asset_key = fortype + ":" + (name or "-") - translation_assets = frappe.cache.hget("translation_assets", frappe.local.lang) or {} - - if asset_key not in translation_assets: - messages = [] - if fortype == "doctype": - messages = get_messages_from_doctype(name) - elif fortype == "page": - messages = get_messages_from_page(name) - elif fortype == "report": - messages = get_messages_from_report(name) - elif fortype == "include": - messages = get_messages_from_include_files() - elif fortype == "jsfile": - messages = get_messages_from_file(name) - elif fortype == "boot": - apps = frappe.get_all_apps(True) - for app in apps: - messages.extend(get_server_messages(app)) - - messages += get_messages_from_navbar() - messages += get_messages_from_include_files() - messages += ( - frappe.qb.from_("Print Format").select(PseudoColumn("'Print Format:'"), "name") - ).run() - messages += (frappe.qb.from_("DocType").select(PseudoColumn("'DocType:'"), "name")).run() - messages += frappe.qb.from_("Role").select(PseudoColumn("'Role:'"), "name").run() - messages += (frappe.qb.from_("Module Def").select(PseudoColumn("'Module:'"), "name")).run() - messages += ( - frappe.qb.from_("Workspace Shortcut") - .where(Field("format").isnotnull()) - .select(PseudoColumn("''"), "format") - ).run() - messages += (frappe.qb.from_("Onboarding Step").select(PseudoColumn("''"), "title")).run() - - messages = deduplicate_messages(messages) - message_dict = make_dict_from_messages(messages, load_user_translation=False) - message_dict.update(get_dict_from_hooks(fortype, name)) - # remove untranslated - message_dict = {k: v for k, v in message_dict.items() if k != v} - translation_assets[asset_key] = message_dict - frappe.cache.hset("translation_assets", frappe.local.lang, translation_assets) - - translation_map: dict = translation_assets[asset_key] - - translation_map.update(get_user_translations(frappe.local.lang)) - - return translation_map - - def get_messages_for_boot(): """Return all message translations that are required on boot.""" - messages = get_all_translations(frappe.local.lang) - messages.update(get_dict_from_hooks("boot", None)) - return messages - - -def get_dict_from_hooks(fortype, name): - translated_dict = {} - - hooks = frappe.get_hooks("get_translated_dict") - for (hook_fortype, fortype_name) in hooks: - if hook_fortype == fortype and fortype_name == name: - for method in hooks[(hook_fortype, fortype_name)]: - translated_dict.update(frappe.get_attr(method)()) - - return translated_dict + return get_all_translations(frappe.local.lang) def make_dict_from_messages(messages, full_dict=None, load_user_translation=True): @@ -260,15 +188,6 @@ def make_dict_from_messages(messages, full_dict=None, load_user_translation=True return out -def get_lang_js(fortype: str, name: str) -> str: - """Returns code snippet to be appended at the end of a JS script. - - :param fortype: Type of object, e.g. `DocType` - :param name: Document name - """ - return f"\n\n$.extend(frappe._messages, {json.dumps(get_dict(fortype, name))})" - - def get_all_translations(lang: str) -> dict[str, str]: """Load and return the entire translations dictionary for a language from apps + user translations. @@ -278,13 +197,12 @@ def get_all_translations(lang: str) -> dict[str, str]: return {} def _merge_translations(): + from frappe.geo.country_info import get_translated_countries + all_translations = get_translations_from_apps(lang).copy() - try: - # get user specific translation data - user_translations = get_user_translations(lang) - all_translations.update(user_translations) - except Exception: - pass + with suppress(Exception): + all_translations.update(get_user_translations(lang)) + all_translations.update(get_translated_countries()) return all_translations diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index 6c47ebd5fa..cde5db54dc 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -258,10 +258,29 @@ def get_context(context): } def load_translations(self, context): - translated_messages = frappe.translate.get_dict("doctype", self.doc_type) - # Sr is not added by default, had to be added manually - translated_messages["Sr"] = _("Sr") - context.translated_messages = frappe.as_json(translated_messages) + messages = [ + "Sr", + "Attach", + self.title, + self.introduction_text, + self.success_title, + self.success_message, + self.list_title, + self.button_label, + self.meta_title, + self.meta_description, + ] + + for field in self.web_form_fields: + messages.extend([field.label, field.description]) + if field.fieldtype == "Select" and field.options: + messages.extend(field.options.split("\n")) + + messages.extend(col.label for col in self.list_columns) + + context.translated_messages = frappe.as_json( + {message: _(message) for message in messages if message} + ) def load_list_data(self, context): if not self.list_columns: