diff --git a/superset-frontend/src/preamble.ts b/superset-frontend/src/preamble.ts index 32010d6c0cc..136856db328 100644 --- a/superset-frontend/src/preamble.ts +++ b/superset-frontend/src/preamble.ts @@ -32,6 +32,7 @@ import setupFormatters from './setup/setupFormatters'; import setupDashboardComponents from './setup/setupDashboardComponents'; import { User } from './types/bootstrapTypes'; import getBootstrapData, { applicationRoot } from './utils/getBootstrapData'; +import './hooks/useLocale'; configure(); diff --git a/superset/models/helpers.py b/superset/models/helpers.py index 82b62b6f778..07944c25eff 100644 --- a/superset/models/helpers.py +++ b/superset/models/helpers.py @@ -49,7 +49,7 @@ from flask_appbuilder import Model from flask_appbuilder.models.decorators import renders from flask_appbuilder.models.mixins import AuditMixin from flask_appbuilder.security.sqla.models import User -from flask_babel import lazy_gettext as _ +from flask_babel import get_locale, lazy_gettext as _ from jinja2.exceptions import TemplateError from markupsafe import escape, Markup from sqlalchemy import and_, Column, or_, UniqueConstraint @@ -559,13 +559,28 @@ class AuditMixinNullable(AuditMixin): # Convert naive datetime to UTC return self.changed_on.astimezone(pytz.utc).strftime("%Y-%m-%dT%H:%M:%S.%f%z") + def _format_time_humanized(self, timestamp: datetime) -> str: + locale = str(get_locale()) + time_diff = datetime.now() - timestamp + # Skip activation for 'en' locale as it's humanize's default locale + if locale == "en": + return humanize.naturaltime(time_diff) + try: + humanize.i18n.activate(locale) + result = humanize.naturaltime(time_diff) + humanize.i18n.deactivate() + return result + except Exception as e: + logger.warning(f"Locale '{locale}' is not supported in humanize: {e}") + return humanize.naturaltime(time_diff) + @property def changed_on_humanized(self) -> str: - return humanize.naturaltime(datetime.now() - self.changed_on) + return self._format_time_humanized(self.changed_on) @property def created_on_humanized(self) -> str: - return humanize.naturaltime(datetime.now() - self.created_on) + return self._format_time_humanized(self.created_on) @renders("changed_on") def modified(self) -> Markup: