diff --git a/securedrop/requirements/python3/securedrop-app-code-requirements.in b/securedrop/requirements/python3/securedrop-app-code-requirements.in index addfd3dee6..579653c64a 100644 --- a/securedrop/requirements/python3/securedrop-app-code-requirements.in +++ b/securedrop/requirements/python3/securedrop-app-code-requirements.in @@ -1,5 +1,6 @@ alembic argon2_cffi>=20.1.0 +babel>=2.9.1 cffi>=1.14.2 # This version needs Rust for compilation. diff --git a/securedrop/requirements/python3/securedrop-app-code-requirements.txt b/securedrop/requirements/python3/securedrop-app-code-requirements.txt index c9d1c9de35..a5a33f816b 100644 --- a/securedrop/requirements/python3/securedrop-app-code-requirements.txt +++ b/securedrop/requirements/python3/securedrop-app-code-requirements.txt @@ -25,10 +25,12 @@ argon2-cffi==20.1.0 \ --hash=sha256:d8029b2d3e4b4cea770e9e5a0104dd8fa185c1724a0f01528ae4826a6d25f97d \ --hash=sha256:da7f0445b71db6d3a72462e04f36544b0de871289b0bc8a7cc87c0f5ec7079fa # via -r requirements/python3/securedrop-app-code-requirements.in -babel==2.5.1 \ - --hash=sha256:6007daf714d0cd5524bbe436e2d42b3c20e68da66289559341e48d2cd6d25811 \ - --hash=sha256:f20b2acd44f587988ff185d8949c3e208b4b3d5d20fcab7d91fe481ffa435528 - # via flask-babel +babel==2.9.1 \ + --hash=sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9 \ + --hash=sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0 + # via + # -r requirements/python3/securedrop-app-code-requirements.in + # flask-babel cffi==1.14.2 \ --hash=sha256:0da50dcbccd7cb7e6c741ab7912b2eff48e85af217d72b57f80ebc616257125e \ --hash=sha256:12a453e03124069b6896107ee133ae3ab04c624bb10683e1ed1c1663df17c13c \ diff --git a/securedrop/tests/test_i18n_tool.py b/securedrop/tests/test_i18n_tool.py index a1228692b8..f221fedde3 100644 --- a/securedrop/tests/test_i18n_tool.py +++ b/securedrop/tests/test_i18n_tool.py @@ -14,6 +14,24 @@ from sh import sed, msginit, pybabel, git, touch +def dummy_translate(po): + buf = None + with io.open(po, "r") as in_file: + buf = in_file.readlines() + + with io.open(po, "w") as out_file: + for line in buf: + if line.startswith("msgid "): + out_file.write(line) + idstr = line.split("msgid ", 1) + out_file.write("msgstr {}".format(idstr[1])) + + elif line.startswith("msgstr "): + pass + else: + out_file.write(line) + + class TestI18NTool(object): def setup(self): @@ -145,6 +163,10 @@ def test_translate_messages_l10n(self, tmpdir): locale = 'en_US' locale_dir = join(str(tmpdir), locale) pybabel('init', '-i', messages_file, '-d', str(tmpdir), '-l', locale) + + po_file = join(locale_dir, 'LC_MESSAGES/messages.po') + dummy_translate(po_file) + mo_file = join(locale_dir, 'LC_MESSAGES/messages.mo') assert not exists(mo_file) i18n_tool.I18NTool().main(args) @@ -195,6 +217,10 @@ def test_translate_messages_compile_arg(self, tmpdir): current_po_mtime = getmtime(po_file) assert old_po_mtime < current_po_mtime + # + # Translation would occur here - let's fake it + dummy_translate(po_file) + # # Compile but do not extract+update # @@ -202,12 +228,12 @@ def test_translate_messages_compile_arg(self, tmpdir): join(self.dir, 'i18n/code.py'), join(self.dir, 'i18n/template.html'), ] - old_po_mtime = current_po_mtime + current_po_mtime = getmtime(po_file) i18n_tool.I18NTool().main(args + [ '--sources', ",".join(source), '--compile', ]) - assert old_po_mtime == getmtime(po_file) + assert current_po_mtime == getmtime(po_file) with io.open(mo_file, mode='rb') as fobj: mo = fobj.read() assert b'code hello i18n' in mo diff --git a/securedrop/tests/test_template_filters.py b/securedrop/tests/test_template_filters.py index 7c73466fba..ca4a56c87a 100644 --- a/securedrop/tests/test_template_filters.py +++ b/securedrop/tests/test_template_filters.py @@ -47,7 +47,7 @@ def verify_rel_datetime_format(app): test_time = datetime.utcnow() - timedelta(hours=2) result = template_filters.rel_datetime_format(test_time, relative=True) - assert "2 heures" in result + assert u"2\xa0heures" in result def verify_filesizeformat(app): @@ -69,18 +69,18 @@ def verify_filesizeformat(app): c.get('/?l=fr_FR') assert session.get('locale') == 'fr_FR' - assert "1 octet" == template_filters.filesizeformat(1) - assert "2 octets" == template_filters.filesizeformat(2) + assert u'1\xa0octet' == template_filters.filesizeformat(1) + assert u"2\xa0octets" == template_filters.filesizeformat(2) value = 1024 * 3 - assert "3 ko" == template_filters.filesizeformat(value) + assert u"3\u202fko" == template_filters.filesizeformat(value) value *= 1024 - assert "3 Mo" == template_filters.filesizeformat(value) + assert u"3\u202fMo" == template_filters.filesizeformat(value) value *= 1024 - assert "3 Go" == template_filters.filesizeformat(value) + assert u"3\u202fGo" == template_filters.filesizeformat(value) value *= 1024 - assert "3 To" == template_filters.filesizeformat(value) + assert u"3\u202fTo" == template_filters.filesizeformat(value) value *= 1024 - assert "072 To" in template_filters.filesizeformat(value) + assert u"072\u202fTo" in template_filters.filesizeformat(value) # We can't use fixtures because these options are set at app init time, and we