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

i18n: Fix untranslated strings in facets #605

Open
wants to merge 1 commit 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
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
Loading