Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using lazy_gettext in boot-time translations #37

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ recursive-include docs Makefile
recursive-include invenio_banners *.html
recursive-include invenio_banners *.py
recursive-include invenio_banners *.po
recursive-include invenio_banners *.mo
recursive-include invenio_banners *.pot
recursive-include tests *.py
2 changes: 1 addition & 1 deletion invenio_banners/services/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

"""Banners Service configuration."""

from invenio_i18n import gettext as _
from invenio_i18n import lazy_gettext as _
from invenio_records_resources.services import Link, RecordServiceConfig
from invenio_records_resources.services.records.links import pagination_links
from sqlalchemy import asc, desc
Expand Down
1 change: 1 addition & 0 deletions run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ trap cleanup EXIT
python -m check_manifest --ignore ".*-requirements.txt"
python -m sphinx.cmd.build -qnNW docs docs/_build/html
eval "$(docker-services-cli up --db ${DB:-postgresql} --search ${SEARCH:-opensearch} --env)"
python setup.py compile_catalog
python -m pytest
tests_exit_code=$?
python -m sphinx.cmd.build -qnNW -b doctest docs docs/_build/doctest
Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ invenio_administration.views =
invenio_banners_details = invenio_banners.administration.banners:BannerDetailView
invenio_banners_edit = invenio_banners.administration.banners:BannerEditView
invenio_banners_create = invenio_banners.administration.banners:BannerCreateView
invenio_i18n.translations =
invenio_banners = invenio_banners


[build_sphinx]
Expand Down
103 changes: 103 additions & 0 deletions tests/ui/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 CESNET z.s.p.o.
#
# Invenio-Banners is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

"""UI tests configuration.

Note: need to call python setup.py compile_catalog to compile the translations before
running the tests.
"""
import json
from pathlib import Path

import pytest
from flask_security import login_user
from invenio_accounts.testutils import login_user_via_session
from invenio_app.factory import create_app as _create_app
from invenio_i18n import lazy_gettext as _


@pytest.fixture(scope="module")
def create_app(instance_path):
"""Application factory fixture."""
return _create_app


@pytest.fixture(scope="module")
def app_config(app_config):
"""Override pytest-invenio app_config fixture.

Set languages for the app.
"""
app_config["I18N_LANGUAGES"] = [
("cs", _("Czech")),
]
return app_config


@pytest.fixture()
def admin_identity(admin):
"""Identity of the admin user."""
return admin.identity


@pytest.fixture()
def admin_client(db, client, admin):
"""Log in a user to the client."""

login_user(admin.user, remember=True)
login_user_via_session(client, email=admin.user.email)

return client


def add_to_manifest(manifest, filename):
manifest.setdefault("assets", {})[filename] = {"publicPath": filename}
filename_without_ext = filename.rsplit(".", 1)[0]
manifest.setdefault("chunks", {}).setdefault(filename_without_ext, []).append(
filename
)


@pytest.fixture()
def fake_manifest(app, instance_path):
app.static_folder = str(Path(instance_path) / "static")

manifest_path = Path(instance_path) / "static" / "dist" / "manifest.json"
manifest_path.parent.mkdir(parents=True, exist_ok=True)

manifest = {
"status": "done",
"publicPath": "/static/dist/",
}
add_to_manifest(manifest, "base.js")
add_to_manifest(manifest, "base-admin-theme.js")

add_to_manifest(manifest, "i18n_app.js")
add_to_manifest(manifest, "invenio-administration-details.js")
add_to_manifest(manifest, "invenio-administration-search.js")

add_to_manifest(manifest, "theme.css")
add_to_manifest(manifest, "theme.js")

manifest_path.write_text(json.dumps(manifest))
return manifest_path


@pytest.fixture()
def clear_babel_context():

# force babel reinitialization when language is switched
def _clear_babel_context():
try:
from flask import g
from flask_babel import SimpleNamespace

g._flask_babel = SimpleNamespace()
except ImportError:
return

return _clear_babel_context
73 changes: 73 additions & 0 deletions tests/ui/test_i18n_administration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 CESNET z.s.p.o.
#
# Invenio-Banners is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

"""Test the i18n of the administration interface.

Note: this does not test the actual translation of the messages, but rather that the
translation kicks in and that some of the labels are localized - so that we know that
the lazy_gettext is working.
"""

from datetime import datetime, timedelta

from invenio_banners.proxies import current_banners_service as service


def test_list_is_localized(app, admin_client, fake_manifest, clear_babel_context):
"""Test that the administration page is localized and that the labels are translated."""

clear_babel_context()
resp = admin_client.get("/administration/banners")
assert resp.status_code == 200
assert resp.content_type == "text/html; charset=utf-8"
# check that the string "Active" is in the response twice (sort order, column number)
assert len(resp.text.split('"Active"')) == 3

clear_babel_context()
resp = admin_client.get(
"/administration/banners", headers=[("Accept-Language", "cs")]
)
assert resp.status_code == 200
assert resp.content_type == "text/html; charset=utf-8"
assert '<html lang="cs"' in resp.text

# checks both sort order and table column name
assert "Active" not in resp.text


def test_detail_is_localized(
app, admin, admin_client, fake_manifest, clear_babel_context
):
"""Test that the administration detail page is localized and that the labels are translated."""

active_banner = {
"message": "active",
"url_path": "/active",
"category": "info",
"start_datetime": (datetime.now() - timedelta(days=1)).isoformat(),
"end_datetime": (datetime.now() + timedelta(days=1)).isoformat(),
"active": True,
}

banner_id = service.create(admin.identity, active_banner)["id"]

clear_babel_context()
resp = admin_client.get(f"/administration/banners/{banner_id}")
assert resp.status_code == 200
assert resp.content_type == "text/html; charset=utf-8"
assert '"Active"' in resp.text

clear_babel_context()
resp = admin_client.get(
f"/administration/banners/{banner_id}", headers=[("Accept-Language", "cs")]
)
assert resp.status_code == 200
assert resp.content_type == "text/html; charset=utf-8"
assert '<html lang="cs"' in resp.text

# checks both sort order and table column name
assert "Active" not in resp.text