Skip to content

[chores] Improve i18n coverage for user-facing strings #519#539

Open
CodingWithSaksham wants to merge 3 commits into
openwisp:masterfrom
CodingWithSaksham:issues/519-improve-i18n-coverage
Open

[chores] Improve i18n coverage for user-facing strings #519#539
CodingWithSaksham wants to merge 3 commits into
openwisp:masterfrom
CodingWithSaksham:issues/519-improve-i18n-coverage

Conversation

@CodingWithSaksham

@CodingWithSaksham CodingWithSaksham commented Jul 2, 2026

Copy link
Copy Markdown

Checklist

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • I have updated the documentation.

Reference to Existing Issue

Closes #519 .

Description of Changes

Fixed missing/broken translation coverage across openwisp_users (admin labels, login template, several admin messages and a model validation error that were silently untranslatable) and filled in the German ,Italian, Russian, and Slovenian translations for every newly extracted string.

NOTE

I used AI primarily to translate the text into different languages. Most of the translations were verified using Google Translate. However, some translations could not be verified because the strings contained variables and placeholders, and translating them directly with Google Translate produced incorrect or broken translations by altering those variables. In those cases, I relied on the AI generated translations.

Fixed missing/broken translation coverage across openwisp_users (admin labels, login template a model validation error that were silently untranslatable) and filled in the German ,Italian, Russian, and Slovenian translations for every newly extracted string.
Closes openwisp#519
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@CodingWithSaksham, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e62efaf0-ea79-48e7-8497-fed286122267

📥 Commits

Reviewing files that changed from the base of the PR and between a935c94 and 793c443.

📒 Files selected for processing (2)
  • openwisp_users/admin.py
  • openwisp_users/base/models.py
📝 Walkthrough

Walkthrough

This PR improves i18n coverage across openwisp-users. Hardcoded strings in admin.py, base/models.py, mixins.py, and the login template are wrapped with Django translation utilities (gettext_lazy, ngettext, ngettext_lazy, {% trans %}, {% blocktrans %}), replacing f-string interpolation with placeholder-based formatting. Locale catalogs (django.po) for German, Italian, Russian, and Slovenian, under both the core app and accounts app, are refreshed with updated POT-Creation-Date, updated source references, and new/reflowed translation entries, including quoted %(username)s placeholders.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • openwisp/openwisp-users#517: Updates the same accounts email/UI translation strings around %(username)s quoting and account expiration/reminder/deactivation messages.

Poem
A rabbit hops through catalogs anew,
Wrapping words in _() and ngettext too,
German, Italian, Russian, Slovene in tow,
Every string now knows which way to go,
Translated burrows, ready to glow! 🐰🌍


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Bug Fixes ❌ Error The PR changes user-facing pluralized/i18n messages, but adds no regression test; existing tests only assert errors/HTML and would still pass if the patch were removed. Add a deterministic regression test for the changed validation/email strings, and Selenium coverage for UI translation behavior if that UI is in scope.
Changes ⚠️ Warning UI/template changes lack screenshots in the PR description, and no tests/docs were updated for the translated validation/admin messages. Add screenshots or screen recordings, and add/update tests (plus docs if behavior is documented) for the new i18n/UI messages.
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the PR’s i18n-focused changes and references the linked issue.
Description check ✅ Passed The description includes the checklist, linked issue, and a clear summary of the localization changes.
Linked Issues check ✅ Passed The changes wrap user-facing strings for translation and update the supported locale catalogs as required by #519.
Out of Scope Changes check ✅ Passed The diff appears confined to i18n wrapper fixes, translation catalogs, and related localization message updates.
Features ✅ Passed Not a feature PR: it only updates i18n strings/catalogs and one permission message, with no new feature/docs/test work required.
General Rules ✅ Passed All edited UI strings are translatable, locale catalogs include the corresponding entries, and I found no security, performance, or naming issues.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coveralls

coveralls commented Jul 2, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 98.128% (-0.003%) from 98.131% — CodingWithSaksham:issues/519-improve-i18n-coverage into openwisp:master

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openwisp_users/mixins.py`:
- Around line 63-75: The validation message in the organization-change check is
still built by splicing a translated verb fragment into a sentence, which should
be replaced with full plural-aware translations. Update the message construction
in the mixin method that raises ValidationError to use ngettext with complete
singular and plural sentence templates, and format only the named placeholders
such as count, object_label, and related_object_label. Remove the standalone
verb translation so the entire sentence is translated in context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e50f2788-5d0a-49eb-a22b-9991fed86065

📥 Commits

Reviewing files that changed from the base of the PR and between f7bc7b1 and 0a8ca98.

📒 Files selected for processing (13)
  • openwisp_users/accounts/locale/de/LC_MESSAGES/django.po
  • openwisp_users/accounts/locale/it/LC_MESSAGES/django.po
  • openwisp_users/accounts/locale/ru/LC_MESSAGES/django.po
  • openwisp_users/accounts/locale/sl/LC_MESSAGES/django.po
  • openwisp_users/admin.py
  • openwisp_users/api/permissions.py
  • openwisp_users/base/models.py
  • openwisp_users/locale/de/LC_MESSAGES/django.po
  • openwisp_users/locale/it/LC_MESSAGES/django.po
  • openwisp_users/locale/ru/LC_MESSAGES/django.po
  • openwisp_users/locale/sl/LC_MESSAGES/django.po
  • openwisp_users/mixins.py
  • openwisp_users/templates/admin/openwisp_users/login.html
📜 Review details
⏰ Context from checks skipped due to timeout. (14)
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=5.0.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=5.0.0
  • GitHub Check: Python==3.10 | django~=5.0.0
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests, ensure all user-facing strings are marked as translatable using the Django i18n framework (django.utils.translation.gettext, gettext_lazy, or ugettext aliases)

**/*.py: Mark user-facing strings for translation with Django i18n helpers in Django code
Place imports at the top of the file; only defer imports when necessary (e.g., Django model imports inside functions or methods where the app registry is not yet ready)
Avoid unnecessary blank lines inside function and method bodies
Write comments and docstrings only when they explain why code is shaped a certain way; place comments before the relevant code block instead of scattering them inside it

Files:

  • openwisp_users/api/permissions.py
  • openwisp_users/mixins.py
  • openwisp_users/base/models.py
  • openwisp_users/admin.py
🪛 HTMLHint (1.9.2)
openwisp_users/templates/admin/openwisp_users/login.html

[warning] 47-47: No matching [ label ] tag found.

(input-requires-label)

🔇 Additional comments (18)
openwisp_users/locale/de/LC_MESSAGES/django.po (1)

140-148: 📐 Maintainability & Code Quality | ⚡ Quick win

Fix the plural agreement in this translation.

permission_classes reads as plural here, so wurde is incorrect. Use wurden or rephrase the sentence so the admin error reads naturally.

Suggested fix
- "permission_classes der View wurde nicht korrekt implementiert. Bitte "
+ "permission_classes der View wurden nicht korrekt implementiert. Bitte "
openwisp_users/locale/it/LC_MESSAGES/django.po (1)

142-150: 📐 Maintainability & Code Quality | ⚡ Quick win

Fix the verb agreement in this translation.

permission_classes is plural in context, so non implementata should be non implementate.

Suggested fix
- "permission_classes della view non implementata correttamente. Utilizza una "
+ "permission_classes della view non implementate correttamente. Utilizza una "
openwisp_users/locale/ru/LC_MESSAGES/django.po (1)

141-149: 📐 Maintainability & Code Quality | ⚡ Quick win

Rephrase this error message for grammar.

permission_classes представления реализовано некорректно is not natural Russian. Please rewrite the sentence so the technical term stays intact but the message reads correctly.

Suggested fix
- "permission_classes представления реализовано некорректно. Используйте один "
+ "Свойство permission_classes у представления реализовано некорректно. Используйте один "
openwisp_users/locale/sl/LC_MESSAGES/django.po (1)

134-142: 📐 Maintainability & Code Quality | ⚡ Quick win

Fix the broken grammar in this translation.

permission_classes poglede ni pravilno implementiran is not grammatical Slovenian. Please rewrite the full sentence before shipping.

Suggested fix
- "permission_classes poglede ni pravilno implementiran. Uporabite enega od "
+ "permission_classes pogleda niso pravilno implementirane. Uporabite enega od "
openwisp_users/accounts/locale/de/LC_MESSAGES/django.po (1)

9-18: LGTM!

Also applies to: 45-56, 57-73, 74-213

openwisp_users/accounts/locale/it/LC_MESSAGES/django.po (1)

9-16: LGTM!

Also applies to: 44-63, 72-80, 122-144, 154-207

openwisp_users/accounts/locale/ru/LC_MESSAGES/django.po (1)

8-19: LGTM!

Also applies to: 30-37, 49-102, 112-220

openwisp_users/accounts/locale/sl/LC_MESSAGES/django.po (1)

9-19: LGTM!

Also applies to: 51-76, 86-222

openwisp_users/templates/admin/openwisp_users/login.html (3)

44-48: HTMLHint "missing label" warning on the submit input is a pre-existing false positive, not introduced by this change.

Submit inputs get their accessible name from the value attribute; no <label> association is required here. No action needed for this i18n change.

Source: Linters/SAST tools


7-7: LGTM! This mirrors Django's own admin idiom for singular/plural error banners.


23-26: LGTM! blocktrans trimmed correctly wraps the full sentence with the {{ username }} variable inline.

openwisp_users/admin.py (5)

183-197: LGTM!


266-282: LGTM! This mirrors Django's own admin pattern of using gettext with model_ngettext for the pluralized noun while keeping a single sentence template.


399-422: LGTM!


489-509: LGTM!


642-675: LGTM!

openwisp_users/base/models.py (1)

492-504: LGTM! Named-placeholder formatting is applied correctly and matches the test expectation for the owner-downgrade error.

openwisp_users/api/permissions.py (1)

46-53: LGTM!

Comment thread openwisp_users/mixins.py Outdated
Comment thread openwisp_users/api/permissions.py Outdated
@coderabbitai coderabbitai Bot removed the enhancement label Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[chores] Improve i18n coverage for user-facing strings

3 participants