Skip to content

Conversation

@Samk13
Copy link
Member

@Samk13 Samk13 commented Aug 28, 2025

❤️ Thank you for your contribution!

Description

This PR introduces backward-compatible multilingual support for rule configurations in invenio-checks. Rule titles, messages, and descriptions can now be specified in multiple languages using dictionary format while maintaining full backward compatibility with existing string-based configurations.

Changes

Core Features

  • Multilingual rule fields: title, message, and description now support multilingual dictionaries
  • Translation function: New translate_field() function with intelligent fallback chain
  • Backward compatibility: Existing string-based configurations continue to work unchanged
  • Jinja2 filter: Registered translate_field filter for dynamic language change "macro didn't work"

Translation Fallback Chain

  1. Current user locale (from current_i18n.locale)
  2. English ("en") as universal fallback
  3. First available language in the dictionary
  4. Empty string for truly empty configurations

API Changes

  • New translate_field() function in invenio_checks/utils.py: Handles translation of multilingual fields with fallback
  • Jinja2 filter registration: Template filter available as {{ field | translate_field }} in templates
  • Error handling: Graceful fallbacks for unsupported field types with descriptive ValueError

Configuration Examples

New Multilingual Format

{
  "id": "access:open/publication",
  "title": {
    "en": "Open Access Publication",
    "sv": "Öppen tillgång publikation", 
    "de": "Open-Access-Publikation"
  },
  "message": {
    "en": "Publication articles must be Open Access",
    "sv": "Publikationsartiklar måste vara öppen tillgång",
    "de": "Publikationsartikel müssen Open Access sein"
  },
  "description": {
    "en": "This rule ensures that all publication articles are Open Access.",
    "sv": "Denna regel säkerställer att alla publikationer är öppet tillgängliga.",
    "de": "Diese Regel stellt sicher, dass alle Publikationen Open Access sind."
  },
  "level": "error"
}

Backward Compatible (still works)

{
  "id": "simple-rule",
  "title": "Simple Rule Title",
  "message": "Simple string message",
  "level": "warning"
}

Mixed Format (also supported)

{
  "id": "mixed-rule", 
  "title": "String Title",
  "message": {
    "en": "English message",
    "sv": "Swedish message"
  },
  "description": "String description"
}

Breaking Changes

None - This is backward compatible. Existing configurations work unchanged.

  1. Replace string fields with language dictionaries:

    // Before
    "title": "My Rule"
    
    // After  
    "title": {
      "en": "My Rule",
      "sv": "Min regel"
    }
  2. Use the filter for custom templates:

    {{ rule.title | translate_field }}
Screenshot 2025-08-29 at 18 05 23 Screenshot 2025-08-29 at 18 08 15 Screenshot 2025-08-29 at 18 08 09
  • The first check in the screenshot shows a case where the rule has no translations and still appears in English without errors.
  • The last check displays a case where the rule contains a mix of English strings and translations.

Checklist

Ticks in all boxes and 🟢 on all GitHub actions status checks are required to merge:

Frontend

Reminder

By using GitHub, you have already agreed to the GitHub’s Terms of Service including that:

  1. You license your contribution under the same terms as the current repository’s license.
  2. You agree that you have the right to license your contribution under the current repository’s license.

Samk13 added 6 commits August 29, 2025 10:07
* Added missing translation entry for invenio_checks.
* Updated mapping and output file keys to use underscores.
* add keywords to catch aliases on extract msgs
* Wrap class-level attributes strings with lazy_gettext
   as stored values will be used later
* Introduces the English translation files structure for the project
* Run extract_msgs command
* Change command prefix from 'python' to 'uv run' for consistency.
* Update Transifex host URL to the correct endpoint.
* Adjust section header for clarity in configuration.
@Samk13 Samk13 force-pushed the i18n-add-translation-support branch from 1a5bb90 to 9bced7d Compare August 29, 2025 08:08
@Samk13 Samk13 marked this pull request as ready for review August 29, 2025 09:51
@Samk13 Samk13 requested a review from utnapischtim August 29, 2025 09:51
* its backward compatible with existing config
* implement _translate_field function for i18n
* update RuleResult to handle multilingual dict
* add translation macro in metadata template
* include translation tests
@Samk13 Samk13 force-pushed the i18n-add-translation-support branch from 9f2e453 to c8276df Compare August 29, 2025 19:05
Samk13 added a commit to Samk13/invenio-rdm-records that referenced this pull request Aug 29, 2025
* Implemented _getLocalizedMessage to handle string, object, and array
  inputs for localization.
* Updated error handling to utilize the new method for better
  localization of error messages.
* require inveniosoftware/invenio-checks#49
@Samk13 Samk13 force-pushed the i18n-add-translation-support branch from 523102b to a6e2b9f Compare August 30, 2025 23:17
* Fix display-time translation for dynamic language switching
* Move translate_field from rules.py to utils.py for better separation
* Update all test imports to use utils.translate_field
* Maintain backward compatibility with string and dict fields
* Store raw multilingual dictionaries instead of translated strings
@Samk13 Samk13 force-pushed the i18n-add-translation-support branch from a6e2b9f to 8a8d759 Compare September 1, 2025 12:06
try:
# Lazy imports to keep utils usable even when deps/context aren't ready
# pylint: disable=import-outside-toplevel
from flask import current_app
Copy link
Contributor

Choose a reason for hiding this comment

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

in which situation is it necessary to place the imports here?

Copy link
Member Author

@Samk13 Samk13 Sep 1, 2025

Choose a reason for hiding this comment

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

The lazy imports are necessary to prevent application context errors. This utils module might be imported during Docker builds, CLI scripts, or testing, all before Flask's application context exists. Without lazy imports, you'd get RuntimeError: Working outside of application context or import failures when the module is loaded outside a running Flask app. So I am trying to avoid that.

* Changed Dict to dict for consistency in type hints
as suggested as dict works too since python3.9
* update copyrights
@Samk13 Samk13 force-pushed the i18n-add-translation-support branch from 7dd6a15 to d56fd79 Compare September 1, 2025 13:35
@Samk13 Samk13 moved this to 👀 In review in vNext Sep 3, 2025
@Samk13 Samk13 added this to vNext Sep 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 👀 In review

Development

Successfully merging this pull request may close these issues.

2 participants