Commit 6cb65101 by Tom Christie

Use translatable error strings. Refs #2063.

parent 3eaf92e8
...@@ -5,7 +5,11 @@ In addition Django's built in 403 and 404 exceptions are handled. ...@@ -5,7 +5,11 @@ In addition Django's built in 403 and 404 exceptions are handled.
(`django.http.Http404` and `django.core.exceptions.PermissionDenied`) (`django.http.Http404` and `django.core.exceptions.PermissionDenied`)
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from rest_framework import status from rest_framework import status
from rest_framework.compat import force_text
import math import math
...@@ -15,10 +19,13 @@ class APIException(Exception): ...@@ -15,10 +19,13 @@ class APIException(Exception):
Subclasses should provide `.status_code` and `.default_detail` properties. Subclasses should provide `.status_code` and `.default_detail` properties.
""" """
status_code = status.HTTP_500_INTERNAL_SERVER_ERROR status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
default_detail = 'A server error occured' default_detail = _('A server error occured')
def __init__(self, detail=None): def __init__(self, detail=None):
self.detail = detail or self.default_detail if detail is not None:
self.detail = force_text(detail)
else:
self.detail = force_text(self.default_detail)
def __str__(self): def __str__(self):
return self.detail return self.detail
...@@ -31,6 +38,19 @@ class APIException(Exception): ...@@ -31,6 +38,19 @@ class APIException(Exception):
# from rest_framework import serializers # from rest_framework import serializers
# raise serializers.ValidationError('Value was invalid') # raise serializers.ValidationError('Value was invalid')
def force_text_recursive(data):
if isinstance(data, list):
return [
force_text_recursive(item) for item in data
]
elif isinstance(data, dict):
return dict([
(key, force_text_recursive(value))
for key, value in data.items()
])
return force_text(data)
class ValidationError(APIException): class ValidationError(APIException):
status_code = status.HTTP_400_BAD_REQUEST status_code = status.HTTP_400_BAD_REQUEST
...@@ -39,7 +59,7 @@ class ValidationError(APIException): ...@@ -39,7 +59,7 @@ class ValidationError(APIException):
# The details should always be coerced to a list if not already. # The details should always be coerced to a list if not already.
if not isinstance(detail, dict) and not isinstance(detail, list): if not isinstance(detail, dict) and not isinstance(detail, list):
detail = [detail] detail = [detail]
self.detail = detail self.detail = force_text_recursive(detail)
def __str__(self): def __str__(self):
return str(self.detail) return str(self.detail)
...@@ -47,59 +67,77 @@ class ValidationError(APIException): ...@@ -47,59 +67,77 @@ class ValidationError(APIException):
class ParseError(APIException): class ParseError(APIException):
status_code = status.HTTP_400_BAD_REQUEST status_code = status.HTTP_400_BAD_REQUEST
default_detail = 'Malformed request.' default_detail = _('Malformed request.')
class AuthenticationFailed(APIException): class AuthenticationFailed(APIException):
status_code = status.HTTP_401_UNAUTHORIZED status_code = status.HTTP_401_UNAUTHORIZED
default_detail = 'Incorrect authentication credentials.' default_detail = _('Incorrect authentication credentials.')
class NotAuthenticated(APIException): class NotAuthenticated(APIException):
status_code = status.HTTP_401_UNAUTHORIZED status_code = status.HTTP_401_UNAUTHORIZED
default_detail = 'Authentication credentials were not provided.' default_detail = _('Authentication credentials were not provided.')
class PermissionDenied(APIException): class PermissionDenied(APIException):
status_code = status.HTTP_403_FORBIDDEN status_code = status.HTTP_403_FORBIDDEN
default_detail = 'You do not have permission to perform this action.' default_detail = _('You do not have permission to perform this action.')
class MethodNotAllowed(APIException): class MethodNotAllowed(APIException):
status_code = status.HTTP_405_METHOD_NOT_ALLOWED status_code = status.HTTP_405_METHOD_NOT_ALLOWED
default_detail = "Method '%s' not allowed." default_detail = _("Method '%s' not allowed.")
def __init__(self, method, detail=None): def __init__(self, method, detail=None):
self.detail = detail or (self.default_detail % method) if detail is not None:
self.detail = force_text(detail)
else:
self.detail = force_text(self.default_detail) % method
class NotAcceptable(APIException): class NotAcceptable(APIException):
status_code = status.HTTP_406_NOT_ACCEPTABLE status_code = status.HTTP_406_NOT_ACCEPTABLE
default_detail = "Could not satisfy the request Accept header" default_detail = _('Could not satisfy the request Accept header')
def __init__(self, detail=None, available_renderers=None): def __init__(self, detail=None, available_renderers=None):
self.detail = detail or self.default_detail if detail is not None:
self.detail = force_text(detail)
else:
self.detail = force_text(self.default_detail)
self.available_renderers = available_renderers self.available_renderers = available_renderers
class UnsupportedMediaType(APIException): class UnsupportedMediaType(APIException):
status_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE status_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
default_detail = "Unsupported media type '%s' in request." default_detail = _("Unsupported media type '%s' in request.")
def __init__(self, media_type, detail=None): def __init__(self, media_type, detail=None):
self.detail = detail or (self.default_detail % media_type) if detail is not None:
self.detail = force_text(detail)
else:
self.detail = force_text(self.default_detail) % media_type
class Throttled(APIException): class Throttled(APIException):
status_code = status.HTTP_429_TOO_MANY_REQUESTS status_code = status.HTTP_429_TOO_MANY_REQUESTS
default_detail = 'Request was throttled.' default_detail = _('Request was throttled.')
extra_detail = " Expected available in %d second%s." extra_detail = ungettext_lazy(
'Expected available in %(wait)d second.',
'Expected available in %(wait)d seconds.',
'wait'
)
def __init__(self, wait=None, detail=None): def __init__(self, wait=None, detail=None):
if detail is not None:
self.detail = force_text(detail)
else:
self.detail = force_text(self.default_detail)
if wait is None: if wait is None:
self.detail = detail or self.default_detail
self.wait = None self.wait = None
else: else:
format = (detail or self.default_detail) + self.extra_detail
self.detail = format % (wait, wait != 1 and 's' or '')
self.wait = math.ceil(wait) self.wait = math.ceil(wait)
self.detail += ' ' + force_text(
self.extra_detail % {'wait': self.wait}
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment