From 9f2cd664e697382c8a786ecda4d22d3f2d9611f8 Mon Sep 17 00:00:00 2001 From: catborise Date: Mon, 2 Nov 2026 22:51:11 +0300 Subject: [PATCH] feat(locale): the panel offers only the languages it is translated into The language choice on the Settings page listed every language Django knows, 99 of them. Six catalogs (Czech under the wrong code, German, Spanish, French, Russian, Ukrainian) translated none of the panel's messages, so choosing one of them, like most of the others, showed English. The Turkish catalog lacked the four newest messages. The panel now offers English and Turkish (LANGUAGES). The empty catalogs and the English one, which has nothing to translate, are removed. Turkish translates every message again. CI checks that the offered catalogs translate every message and that their compiled files are up to date; the README says how to update them. --- .github/workflows/test.yml | 16 +- README.md | 10 + appsettings/tests/test_appsettings.py | 8 + locale/cz/LC_MESSAGES/django.mo | Bin 388 -> 0 bytes locale/cz/LC_MESSAGES/django.po | 4008 ------------------------ locale/de/LC_MESSAGES/django.mo | Bin 380 -> 0 bytes locale/de/LC_MESSAGES/django.po | 4008 ------------------------ locale/en/LC_MESSAGES/django.mo | Bin 380 -> 0 bytes locale/en/LC_MESSAGES/django.po | 4008 ------------------------ locale/es/LC_MESSAGES/django.mo | Bin 380 -> 0 bytes locale/es/LC_MESSAGES/django.po | 4008 ------------------------ locale/fr/LC_MESSAGES/django.mo | Bin 379 -> 0 bytes locale/fr/LC_MESSAGES/django.po | 4008 ------------------------ locale/ru/LC_MESSAGES/django.mo | Bin 518 -> 0 bytes locale/ru/LC_MESSAGES/django.po | 4010 ------------------------ locale/tr/LC_MESSAGES/django.mo | Bin 157982 -> 158523 bytes locale/tr/LC_MESSAGES/django.po | 1482 ++++----- locale/uk/LC_MESSAGES/django.mo | Bin 602 -> 0 bytes locale/uk/LC_MESSAGES/django.po | 4011 ------------------------- webvirtcloud/settings.py.template | 5 + 20 files changed, 791 insertions(+), 28791 deletions(-) delete mode 100644 locale/cz/LC_MESSAGES/django.mo delete mode 100644 locale/cz/LC_MESSAGES/django.po delete mode 100644 locale/de/LC_MESSAGES/django.mo delete mode 100644 locale/de/LC_MESSAGES/django.po delete mode 100644 locale/en/LC_MESSAGES/django.mo delete mode 100644 locale/en/LC_MESSAGES/django.po delete mode 100644 locale/es/LC_MESSAGES/django.mo delete mode 100644 locale/es/LC_MESSAGES/django.po delete mode 100644 locale/fr/LC_MESSAGES/django.mo delete mode 100644 locale/fr/LC_MESSAGES/django.po delete mode 100644 locale/ru/LC_MESSAGES/django.mo delete mode 100644 locale/ru/LC_MESSAGES/django.po delete mode 100644 locale/uk/LC_MESSAGES/django.mo delete mode 100644 locale/uk/LC_MESSAGES/django.po diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e65e22ac..7561dfbd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,7 +71,8 @@ jobs: libldap2-dev \ libsasl2-dev \ pkg-config \ - gcc + gcc \ + gettext - name: Install Python Dependencies run: | @@ -90,6 +91,19 @@ jobs: - name: Run Django Migrations run: python manage.py migrate --noinput + # Each catalog of LANGUAGES translates every message, and its compiled + # .mo is the .po's: a changed text needs its translations + - name: Check Translation Catalogs + if: matrix.python-version == '3.12' && matrix.database == 'sqlite' + run: | + python manage.py makemessages -l tr --no-obsolete --ignore=staticfiles -v0 + for dir in locale/tr/LC_MESSAGES; do + msgfmt --check -o /tmp/django.mo "$dir/django.po" + missing=$(msgattrib --untranslated "$dir/django.po"; msgattrib --only-fuzzy "$dir/django.po") + if [ -n "$missing" ]; then echo "$missing"; echo "::error file=$dir/django.po::untranslated or fuzzy messages"; exit 1; fi + cmp <(msgunfmt "$dir/django.mo") <(msgunfmt /tmp/django.mo) || { echo "::error file=$dir/django.mo::not compiled from django.po (compilemessages)"; exit 1; } + done + # Includes the vrtManager tests; fails below the coverage floor in pyproject.toml - name: Run Test Suite run: | diff --git a/README.md b/README.md index 82100e77..1d56269f 100644 --- a/README.md +++ b/README.md @@ -736,6 +736,16 @@ python3 dev/console_layout.py us "English (US)" --model pc104 # a keyboard with It lists the dead keys it leaves out: a character only a dead key types cannot be typed. Type a sample with every character group of the layout into a VM set to that layout before committing the file. +### Translations + +The panel is translated into the languages of `LANGUAGES` in `settings.py`, each with a full catalog in `locale/`. A new or changed text needs its translation in each before CI passes (needs `gettext`): + +```bash +python manage.py makemessages -l tr --no-obsolete --ignore=staticfiles --ignore=.venv +# translate the new and fuzzy entries of locale/tr/LC_MESSAGES/django.po +python manage.py compilemessages -l tr +``` + ### Running tests ```bash diff --git a/appsettings/tests/test_appsettings.py b/appsettings/tests/test_appsettings.py index 9ce00f8b..61b7cae4 100644 --- a/appsettings/tests/test_appsettings.py +++ b/appsettings/tests/test_appsettings.py @@ -1,3 +1,5 @@ +import re + from django.contrib.messages import get_messages from django.test import RequestFactory, TestCase from django.urls import reverse @@ -22,6 +24,12 @@ class AppSettingsTestCase(TestCase): response = self.client.get(reverse("appsettings")) self.assertEqual(response.status_code, 200) + def test_the_language_choice_offers_the_translated_languages(self): + page = self.client.get(reverse("appsettings")).content.decode() + choice = page[page.index('