Source: horizon
Version: 3:26.0.0-1
Severity: important
Tags: patch
User: [email protected]
Usertags: timestamps
X-Debbugs-Cc: [email protected]

The build timestamp is getting embedded in various shipped .pot files:

  
https://reproduce.debian.net/all/api/v1/builds/234931/artifacts/514050/diffoscope

  │ │ ├── ./usr/lib/python3/dist-packages/horizon/locale/django.pot
  ...
  │ │ │ -"POT-Creation-Date: 2026-09-21 07:22+0000\n"
  │ │ │ +"POT-Creation-Date: 2026-09-26 10:01+0000\n"

This issue is currently blocking migration to testing:

  https://reproduce.debian.net/excuses.html?source_name=horizon

This appears to have been introduced in upstream version 26.0.0 and is
present in newer versions as well:

  https://tests.reproducible-builds.org/debian/history/amd64/horizon.html

Reverting an upstream commit appears to resolve the issue:

  63ed6a1d6b1fe3f153b80ed580c7a49eaf2f1d12
  Avoid calling setup.py in the extract_messages command

Although it is hopefully possible to fix this in some better way than
reverting the upstream commit, offering the attached patch as a
workaround until a better solution that can be merged upstream can be
found.


live well,
  vagrant
From: Vagrant Cascadian <[email protected]>
Date: Thu, 1 Oct 2026 12:13:02 -0700
X-Dgit-Generated: 3:27.0.0-1.1~0 002f142d2f5d7c6163bad9147ac59ceb6e37cc36
Subject: Revert "Avoid calling setup.py in the extract_messages command"

This reverts commit 63ed6a1d6b1fe3f153b80ed580c7a49eaf2f1d12.

---

diff --git a/babel-django.cfg b/babel-django.cfg
index 6590355fa..f5e77263f 100644
--- a/babel-django.cfg
+++ b/babel-django.cfg
@@ -1,5 +1,3 @@
 [python: **.py]
 [django: **/templates/**.html]
 [django: **/templates/**.csv]
-[extractors]
-django = horizon.utils.babel_extract_django:extract_django
diff --git a/babel-djangojs.cfg b/babel-djangojs.cfg
index 03f75ac7d..f51212ad7 100644
--- a/babel-djangojs.cfg
+++ b/babel-djangojs.cfg
@@ -5,5 +5,3 @@
 # /openstack_dashboard/dashboards/XYZ/static which will ensure
 # that plugins are also translated.
 [angular: **/static/**.html]
-[extractors]
-angular = horizon.utils.babel_extract_angular:extract_angular
diff --git a/openstack_dashboard/management/commands/extract_messages.py b/openstack_dashboard/management/commands/extract_messages.py
index 60877840b..4def2971b 100644
--- a/openstack_dashboard/management/commands/extract_messages.py
+++ b/openstack_dashboard/management/commands/extract_messages.py
@@ -13,9 +13,10 @@
 # limitations under the License.
 
 import os
+from subprocess import call
 
-from babel.messages.frontend import CommandLineInterface
 from django.core.management.base import BaseCommand
+from setuptools.dist import Distribution
 
 
 DOMAINS = ['django', 'djangojs']
@@ -43,6 +44,17 @@ class Command(BaseCommand):
                                   "polluting the source code"))
 
     def handle(self, *args, **options):
+        cmd = ('python setup.py {quiet} extract_messages '
+               '-F babel-{domain}.cfg '
+               '--input-dirs {module} '
+               '-o {potfile}')
+        distribution = Distribution()
+        distribution.parse_config_files(distribution.find_config_files())
+
+        quiet = '-q' if int(options['verbosity']) == 0 else ''
+        if options['check_only']:
+            cmd += " ; rm {potfile}"
+
         for module in options['module']:
             for domain in options['domain']:
                 potfile = '{module}/locale/{domain}.pot'.format(module=module,
@@ -50,14 +62,6 @@ class Command(BaseCommand):
                 if not os.path.exists(potfile):
                     with open(potfile, 'wb') as f:
                         f.write(b'')
-                command = [
-                    'pybabel', 'extract',
-                    '-F', f'babel-{domain}.cfg',
-                    '--input-dirs', module,
-                    '-o', potfile,
-                ]
-                if int(options['verbosity']) == 0:
-                    command.insert(1, '-q')
-                CommandLineInterface().run(command)
-                if options['check_only']:
-                    os.remove(potfile)
+
+                call(cmd.format(module=module, domain=domain, potfile=potfile,
+                                quiet=quiet), shell=True)
diff --git a/pyproject.toml b/pyproject.toml
index 8bb559c99..aea237593 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -35,6 +35,13 @@ classifiers = [
 openstack_dashboard = "openstack_dashboard.utils.config:list_options"
 openstack_dashboard_integration_tests = "openstack_dashboard.test.integration_tests.config:list_opts"
 
+[project.entry-points."babel.extractors"]
+# We use a custom extractor to find translatable strings in AngularJS templates.
+# See https://babel.pocoo.org/en/latest/messages.html#referencing-extraction-methods
+# for details on how this works.
+angular = "horizon.utils.babel_extract_angular:extract_angular"
+django = "horizon.utils.babel_extract_django:extract_django"
+
 [project.urls]
 Homepage = "https://docs.openstack.org/horizon";
 Repository = "https://opendev.org/openstack/horizon/";

Attachment: signature.asc
Description: PGP signature

Reply via email to