Skip to content

Commit

Permalink
i18n: Fix untranslated strings in facet
Browse files Browse the repository at this point in the history
  • Loading branch information
mesemus committed Feb 18, 2025
1 parent 713c1ce commit 82c9ba8
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

"""Systemfield for managing referenced entities in request."""

from functools import partial

from invenio_i18n import gettext as _
from invenio_records.systemfields import SystemField

from ...references.entity_resolvers import EntityProxy
Expand Down Expand Up @@ -43,7 +42,9 @@ def set_obj(self, instance, obj):

# check if the reference is allowed
if not self._check_reference(instance, obj):
raise ValueError(f"Invalid reference for '{self.key}': {obj}")
raise ValueError(
_("Invalid reference for '%(key)s': %(obj)s", key=self.key, obj=obj)
)

# set dictionary key and reset the cache
self.set_dictkey(instance, obj)
Expand Down
35 changes: 21 additions & 14 deletions invenio_records_resources/resources/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
# details.

"""Common Errors handling for Resources."""

from json import JSONDecodeError

import marshmallow as ma
from flask import jsonify, make_response, request, url_for
from flask_resources import HTTPJSONException, create_error_handler
from invenio_i18n import gettext
from invenio_i18n import lazy_gettext as _
from invenio_pidstore.errors import (
PIDAlreadyExists,
Expand Down Expand Up @@ -116,56 +118,59 @@ class ErrorHandlersMixin:
QuerystringValidationError: create_error_handler(
HTTPJSONException(
code=400,
description="Invalid querystring parameters.",
description=_("Invalid querystring parameters."),
)
),
PermissionDeniedError: create_error_handler(
HTTPJSONException(
code=403,
description="Permission denied.",
description=_("Permission denied."),
)
),
RecordPermissionDeniedError: create_error_handler(
HTTPJSONException(
code=403,
description="Permission denied.",
description=_("Permission denied."),
)
),
PIDDeletedError: create_error_handler(
HTTPJSONException(
code=410,
description="The record has been deleted.",
description=_("The record has been deleted."),
)
),
PIDAlreadyExists: create_error_handler(
HTTPJSONException(
code=400,
description="The persistent identifier is already registered.",
description=_("The persistent identifier is already registered."),
)
),
PIDDoesNotExistError: create_error_handler(
HTTPJSONException(
code=404,
description="The persistent identifier does not exist.",
description=_("The persistent identifier does not exist."),
)
),
PIDUnregistered: create_error_handler(
HTTPJSONException(
code=404,
description="The persistent identifier is not registered.",
description=_("The persistent identifier is not registered."),
)
),
PIDRedirectedError: create_pid_redirected_error_handler(),
NoResultFound: create_error_handler(
HTTPJSONException(
code=404,
description="Not found.",
description=_("Not found."),
)
),
FacetNotFoundError: create_error_handler(
lambda e: HTTPJSONException(
code=404,
description=f"Facet {e.vocabulary_id} not found.",
# using gettext here in order to be able to call the format method
description=gettext(
"Facet %(vocabulary_id)s not found.", vocabulary_id=e.vocabulary_id
),
)
),
FileKeyNotFoundError: create_error_handler(
Expand All @@ -177,19 +182,19 @@ class ErrorHandlersMixin:
JSONDecodeError: create_error_handler(
HTTPJSONException(
code=400,
description="Unable to decode JSON data in request body.",
description=_("Unable to decode JSON data in request body."),
)
),
InvalidRelationValue: create_error_handler(
HTTPJSONException(
code=400,
description="Not a valid value.",
description=_("Not a valid value."),
)
),
InvalidCheckValue: create_error_handler(
HTTPJSONException(
code=400,
description="Not a valid value.",
description=_("Not a valid value."),
)
),
search.exceptions.RequestError: create_error_handler(
Expand All @@ -198,13 +203,15 @@ class ErrorHandlersMixin:
FailedFileUploadException: create_error_handler(
HTTPJSONException(
code=400,
description="The file upload transfer failed, please try again.",
description=_("The file upload transfer failed, please try again."),
)
),
FilesCountExceededException: create_error_handler(
HTTPJSONException(
code=400,
description="Uploading selected files will result in exceeding the max amount per record.",
description=_(
"Uploading selected files will result in exceeding the max amount per record."
),
)
),
}
20 changes: 13 additions & 7 deletions invenio_records_resources/services/custom_fields/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@

"""Custom Fields for InvenioRDM."""


from abc import abstractmethod

from invenio_i18n import gettext as _


class CustomFieldsException(Exception):
"""Base class for custom fields exceptions."""
Expand All @@ -32,9 +33,10 @@ def __init__(self, field_name, given_namespace):
@property
def description(self):
"""Exception's description."""
return (
f"Namespace {self.given_namespace} is not valid for custom field "
f"{self.field_name}."
return _(
"Namespace %(given_namespace)s is not valid for custom field %(field_name)s.",
given_namespace=self.given_namespace,
field_name=self.field_name,
)


Expand All @@ -48,7 +50,10 @@ def __init__(self, field_names):
@property
def description(self):
"""Exception's description."""
return f"Custom fields {self.field_names} are not configured."
return _(
"Custom fields %(field_names)s are not configured.",
field_names=self.field_names,
)


class CustomFieldsInvalidArgument(CustomFieldsException):
Expand All @@ -61,6 +66,7 @@ def __init__(self, arg_name):
@property
def description(self):
"""Exception's description."""
return (
f"Invalid argument {self.arg_name} passed when initializing custom field."
return _(
"Invalid argument %(arg_name)s passed when initializing custom field.",
arg_name=self.arg_name,
)
26 changes: 17 additions & 9 deletions invenio_records_resources/services/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ def __init__(self, action_name=None, record=None, *args, **kwargs):
class PermissionDeniedError(PermissionDenied):
"""Permission denied error."""

description = "Permission denied."
@property
def description(self):
"""Description."""
return _("Permission denied.")


class RevisionIdMismatchError(Exception):
Expand All @@ -44,9 +47,10 @@ def __init__(self, record_revision_id, expected_revision_id):
@property
def description(self):
"""Exception's description."""
return (
f"Revision id provided({self.expected_revision_id}) doesn't match "
f"record's one({self.record_revision_id})"
return _(
"Revision id provided(%(expected_revision_id)s) doesn't match record's one(%(record_revision_id)s)",
expected_revision_id=self.expected_revision_id,
record_revision_id=self.record_revision_id,
)


Expand All @@ -66,7 +70,7 @@ class FacetNotFoundError(Exception):
def __init__(self, vocabulary_id):
"""Initialise error."""
self.vocabulary_id = vocabulary_id
super().__init__(_("Facet {vocab} not found.").format(vocab=vocabulary_id))
super().__init__(_("Facet %(vocab)s not found.", vocab=vocabulary_id))


class FileKeyNotFoundError(Exception):
Expand All @@ -75,8 +79,10 @@ class FileKeyNotFoundError(Exception):
def __init__(self, recid, file_key):
"""Constructor."""
super().__init__(
_("Record '{recid}' has no file '{file_key}'.").format(
recid=recid, file_key=file_key
_(
"Record '%(recid)s' has no file '%(file_key)s'.",
recid=recid,
file_key=file_key,
)
)
self.recid = recid
Expand All @@ -89,8 +95,10 @@ class FailedFileUploadException(Exception):
def __init__(self, recid, file, file_key):
"""Constructor."""
super().__init__(
_("Record '{recid}' failed to upload file '{file_key}'.").format(
recid=recid, file_key=file_key
_(
"Record '%(recid)s' failed to upload file '%(file_key)s'.",
recid=recid,
file_key=file_key,
)
)
self.recid = recid
Expand Down
5 changes: 3 additions & 2 deletions invenio_records_resources/services/files/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"""File Service API."""

from flask import current_app
from invenio_i18n import gettext as _

from ..base import LinksTemplate, Service
from ..errors import FailedFileUploadException, FileKeyNotFoundError
Expand Down Expand Up @@ -257,10 +258,10 @@ def set_file_content(

except FailedFileUploadException as e:
file = e.file
current_app.logger.exception(f"File upload transfer failed.")
current_app.logger.exception("File upload transfer failed.")
# we gracefully fail so that uow can commit the cleanup operation in
# FileContentComponent
errors = "File upload transfer failed."
errors = _("File upload transfer failed.")

return self.file_result_item(
self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

from copy import deepcopy

from invenio_i18n import gettext as _

from ....pagination import Pagination
from ...errors import QuerystringValidationError
from .base import ParamInterpreter
Expand All @@ -34,6 +36,6 @@ def apply(self, identity, search, params):
)

if not p.valid():
raise QuerystringValidationError("Invalid pagination parameters.")
raise QuerystringValidationError(_("Invalid pagination parameters."))

return search[p.from_idx : p.to_idx]
13 changes: 8 additions & 5 deletions invenio_records_resources/services/records/params/querystr.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

"""Query parameter interpreter API."""

from ...errors import QuerystringValidationError

# Here for backward compatibility
from invenio_i18n import gettext as _

from ...errors import QuerystringValidationError
from ..queryparser import QueryParser, SuggestQueryParser # noqa
from .base import ParamInterpreter

Expand All @@ -25,8 +26,10 @@ def apply(self, identity, search, params):

if q_str and suggest_str:
raise QuerystringValidationError(
"You cannot specify both 'q' and 'suggest' parameters at the "
"same time."
_(
"You cannot specify both 'q' and 'suggest' parameters at the "
"same time."
)
)

query_str = q_str
Expand All @@ -35,7 +38,7 @@ def apply(self, identity, search, params):
query_str = suggest_str
parser_cls = self.config.suggest_parser_cls
if parser_cls is None:
raise QuerystringValidationError("Invalid 'suggest' parameter.")
raise QuerystringValidationError(_("Invalid 'suggest' parameter."))

if query_str:
query = parser_cls(identity).parse(query_str)
Expand Down
5 changes: 4 additions & 1 deletion invenio_records_resources/services/records/params/sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from copy import deepcopy

from invenio_i18n import gettext as _
from marshmallow import ValidationError

from .base import ParamInterpreter
Expand Down Expand Up @@ -57,5 +58,7 @@ def _compute_sort_fields(self, params):

sort = options.get(params["sort"])
if sort is None:
raise ValidationError(f"Invalid sort option '{params['sort']}'.")
raise ValidationError(
_("Invalid sort option '%(sort_option)s'.", sort_option=params["sort"])
)
return sort["fields"]
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,12 @@ def visit_search_field(self, node, context):
# allows, we don't map any query, we allow it "as is"
if not allows:
raise QuerystringValidationError(
_("Invalid search field: {field_name}.").format(
field_name=node.name
)
_("Invalid search field: %(field_name)s.", field_name=node.name)
)
# If a allow list exists, the term must be allowed to be queried.
if self._allow_list and not term_name in self._allow_list:
if self._allow_list and term_name not in self._allow_list:
raise QuerystringValidationError(
_("Invalid search field: {field_name}.").format(field_name=node.name)
_("Invalid search field: %(field_name)s.", field_name=node.name)
)

if field_value_mapper:
Expand Down

0 comments on commit 82c9ba8

Please sign in to comment.