diff --git a/superset/constants.py b/superset/constants.py index f60b79a9615c..9dac073e704a 100644 --- a/superset/constants.py +++ b/superset/constants.py @@ -203,6 +203,25 @@ class RouteMethod: # pylint: disable=too-few-public-methods | EXTRA_FORM_DATA_OVERRIDE_EXTRA_KEYS ) +LOCALES_LANGUAGE_MAP = { + "en": "en_US", + "es": "es_ES", + "it": "it_IT", + "fr": "fr_FR", + "zh": "zh_CN", + "zh_TW": "zh_HK", + "ja": "ja_JP", + "de": "de_DE", + "pt": "pt_PT", + "pt_BR": "pt_BR", + "ru": "ru_RU", + "ko": "ko_KR", + "sk": "sk_SK", + "sl": "sl_SI", + "nl": "nl_NL", + "uk": "uk_UA", +} + class TimeGrain(StrEnum): SECOND = "PT1S" diff --git a/superset/models/helpers.py b/superset/models/helpers.py index 5dc97b602af2..f5d907b16f8f 100644 --- a/superset/models/helpers.py +++ b/superset/models/helpers.py @@ -92,6 +92,7 @@ is_adhoc_column, MediumText, remove_duplicates, + activate_humanize_locale, ) from superset.utils.dates import datetime_to_epoch @@ -556,10 +557,12 @@ def changed_on_utc(self) -> str: @property def changed_on_humanized(self) -> str: + activate_humanize_locale() return humanize.naturaltime(datetime.now() - self.changed_on) @property def created_on_humanized(self) -> str: + activate_humanize_locale() return humanize.naturaltime(datetime.now() - self.created_on) @renders("changed_on") diff --git a/superset/models/sql_lab.py b/superset/models/sql_lab.py index 4d443423d18d..124096a4f389 100644 --- a/superset/models/sql_lab.py +++ b/superset/models/sql_lab.py @@ -65,6 +65,7 @@ MediumText, QueryStatus, user_label, + activate_humanize_locale, ) if TYPE_CHECKING: @@ -463,10 +464,12 @@ def url(self) -> str: @property def last_run_humanized(self) -> str: + activate_humanize_locale() return naturaltime(datetime.now() - self.changed_on) @property def _last_run_delta_humanized(self) -> str: + activate_humanize_locale() return naturaltime(datetime.now() - self.changed_on) @renders("changed_on") diff --git a/superset/utils/core.py b/superset/utils/core.py index 2b80c89f6126..abcced37b50e 100644 --- a/superset/utils/core.py +++ b/superset/utils/core.py @@ -38,6 +38,7 @@ from collections.abc import Iterable, Iterator, Sequence from contextlib import closing, contextmanager from dataclasses import dataclass +import humanize.i18n from datetime import timedelta from email.mime.application import MIMEApplication from email.mime.image import MIMEImage @@ -58,7 +59,7 @@ import sqlalchemy as sa from cryptography.hazmat.backends import default_backend from cryptography.x509 import Certificate, load_pem_x509_certificate -from flask import current_app, g, request +from flask import current_app, g, request, session from flask_appbuilder import SQLA from flask_appbuilder.security.sqla.models import User from flask_babel import gettext as __ @@ -101,6 +102,7 @@ from superset.utils.database import get_example_database from superset.utils.date_parser import parse_human_timedelta from superset.utils.hashing import md5_sha_from_dict, md5_sha_from_str +from superset.constants import LOCALES_LANGUAGE_MAP if TYPE_CHECKING: from superset.connectors.sqla.models import BaseDatasource, TableColumn @@ -1831,3 +1833,10 @@ def get_user_agent(database: Database, source: QuerySource | None) -> str: return user_agent_func(database, source) return DEFAULT_USER_AGENT + + +def activate_humanize_locale() -> str: + locale = session.get("locale", "en") + if (locale != "en"): + locale = LOCALES_LANGUAGE_MAP.get(locale, "fa_IR") + humanize.i18n.activate(locale)