add gettext lookups for addons api ValidationErrors (#19115)

This commit is contained in:
Andrew Williamson 2022-04-19 10:14:24 +01:00 коммит произвёл GitHub
Родитель ee02eed9c8
Коммит 9a11501da4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 73 добавлений и 37 удалений

Просмотреть файл

@ -7,6 +7,7 @@ from urllib.parse import urlsplit, urlunsplit
from django.conf import settings
from django.http.request import QueryDict
from django.utils.translation import gettext
from django.urls import reverse
from rest_framework import fields, exceptions, serializers
@ -39,12 +40,17 @@ class CategoriesSerializerField(serializers.Field):
for app_name, category_names in data.items():
if len(category_names) > amo.MAX_CATEGORIES:
raise exceptions.ValidationError(
'Maximum number of categories per application '
f'({amo.MAX_CATEGORIES}) exceeded'
gettext(
'Maximum number of categories per application '
'({MAX_CATEGORIES}) exceeded'
).format(MAX_CATEGORIES=amo.MAX_CATEGORIES)
)
if len(category_names) > 1 and 'other' in category_names:
raise exceptions.ValidationError(
'The "other" category cannot be combined with another category'
gettext(
'The "other" category cannot be combined with another '
'category'
)
)
app_cats = CATEGORIES[APPS[app_name].id]
# We don't know the addon_type at this point, so try them all and we'll
@ -57,10 +63,10 @@ class CategoriesSerializerField(serializers.Field):
all_cat_slugs.update(type_cats.keys())
# Now double-check all the category names were found
if not all_cat_slugs.issuperset(category_names):
raise exceptions.ValidationError('Invalid category name.')
raise exceptions.ValidationError(gettext('Invalid category name.'))
return categories
except KeyError:
raise exceptions.ValidationError('Invalid app name.')
raise exceptions.ValidationError(gettext('Invalid app name.'))
def to_representation(self, value):
grouped = sorted_groupby(
@ -100,16 +106,19 @@ class ContributionSerializerField(OutgoingURLField):
if parsed_url.hostname not in amo.VALID_CONTRIBUTION_DOMAINS:
errors.append(
'URL domain must be one of '
f'[{", ".join(amo.VALID_CONTRIBUTION_DOMAINS)}].'
gettext('URL domain must be one of [{domains}].').format(
domains=', '.join(amo.VALID_CONTRIBUTION_DOMAINS)
)
)
elif parsed_url.hostname == 'github.com' and not parsed_url.path.startswith(
'/sponsors/'
):
# Issue 15497, validate path for GitHub Sponsors
errors.append('URL path for GitHub Sponsors must contain /sponsors/.')
errors.append(
gettext('URL path for GitHub Sponsors must contain /sponsors/.')
)
if parsed_url.scheme != 'https':
errors.append('URLs must start with https://.')
errors.append(gettext('URLs must start with https://.'))
if errors:
raise exceptions.ValidationError(errors)
@ -195,7 +204,7 @@ class SourceFileField(serializers.FileField):
# Ensure the file type is one we support.
if not data.name.endswith(VALID_SOURCE_EXTENSIONS):
error_msg = (
error_msg = gettext(
'Unsupported file type, please upload an archive file ({extensions}).'
)
raise exceptions.ValidationError(
@ -216,7 +225,7 @@ class SourceFileField(serializers.FileField):
for member in archive.getmembers():
archive_member_validator(archive, member)
except (zipfile.BadZipFile, tarfile.ReadError, OSError, EOFError):
raise exceptions.ValidationError('Invalid or broken archive.')
raise exceptions.ValidationError(gettext('Invalid or broken archive.'))
return data
@ -240,7 +249,7 @@ class VersionCompatabilityField(serializers.Field):
data = {key: {} for key in data}
if not isinstance(data, dict) or data == {}:
# if it's neither it's not a valid input
raise exceptions.ValidationError('Invalid value')
raise exceptions.ValidationError(gettext('Invalid value'))
version = self.parent.instance
existing = version.compatible_apps if version else {}
@ -270,9 +279,9 @@ class VersionCompatabilityField(serializers.Field):
internal[app] = apps_versions
except KeyError:
raise exceptions.ValidationError('Invalid app specified')
raise exceptions.ValidationError(gettext('Invalid app specified'))
except AppVersion.DoesNotExist:
raise exceptions.ValidationError('Unknown app version specified')
raise exceptions.ValidationError(gettext('Unknown app version specified'))
return internal
@ -306,15 +315,18 @@ class ImageField(serializers.ImageField):
image_check = ImageCheck(data)
if data.content_type not in amo.IMG_TYPES or not image_check.is_image():
raise serializers.ValidationError('Images must be either PNG or JPG.')
raise exceptions.ValidationError(
gettext('Images must be either PNG or JPG.')
)
errors = []
if image_check.is_animated():
errors.append('Images cannot be animated.')
errors.append(gettext('Images cannot be animated.'))
if data.size > self.max_size:
errors.append(
'Images must be smaller than %dMB' % (self.max_size / 1024 / 1024)
gettext('Images must be smaller than %dMB')
% (self.max_size / 1024 / 1024)
)
icon_size = image_check.size
@ -322,6 +334,6 @@ class ImageField(serializers.ImageField):
errors.append('Images must be square (same width and height).')
if errors:
raise serializers.ValidationError(errors)
raise exceptions.ValidationError(errors)
return data

Просмотреть файл

@ -1,6 +1,7 @@
import os
import re
from django.utils.translation import gettext
from django.urls import reverse
from django_statsd.clients import statsd
@ -254,7 +255,9 @@ class LicenseSerializer(serializers.ModelSerializer):
def validate(self, data):
if self.instance and not self.get_is_custom(self.instance):
raise exceptions.ValidationError('Built in licenses can not be updated.')
raise exceptions.ValidationError(
gettext('Built in licenses can not be updated.')
)
return data
@ -410,7 +413,7 @@ class DeveloperVersionSerializer(VersionSerializer):
request = self.context.get('request')
own_upload = request and request.user == value.user
if not own_upload or not value.valid or value.validation_timeout:
raise exceptions.ValidationError('Upload is not valid.')
raise exceptions.ValidationError(gettext('Upload is not valid.'))
# Parse the file to get and validate package data with the addon.
self.parsed_data = parse_addon(value, addon=self.addon, user=request.user)
return value
@ -419,7 +422,7 @@ class DeveloperVersionSerializer(VersionSerializer):
# check the guid/version isn't in the addon blocklist
block_qs = Block.objects.filter(guid=guid) if guid else ()
if block_qs and block_qs.first().is_version_blocked(version_string):
msg = (
msg = gettext(
'Version {version} matches {block_link} for this add-on. '
'You can contact {amo_admins} for additional information.'
)
@ -438,10 +441,14 @@ class DeveloperVersionSerializer(VersionSerializer):
)
if existing_versions.exists():
if existing_versions[0].deleted:
msg = f'Version {version_string} was uploaded before and deleted.'
msg = gettext(
'Version {version_string} was uploaded before and deleted.'
)
else:
msg = f'Version {version_string} already exists.'
raise exceptions.ValidationError({'version': msg})
msg = gettext('Version {version_string} already exists.')
raise exceptions.ValidationError(
{'version': msg.format(version_string=version_string)}
)
def validate(self, data):
if not self.instance:
@ -457,7 +464,10 @@ class DeveloperVersionSerializer(VersionSerializer):
if channel == amo.RELEASE_CHANNEL_LISTED and self.addon:
if self.addon.disabled_by_user:
raise exceptions.ValidationError(
'Listed versions cannot be submitted while add-on is disabled.'
gettext(
'Listed versions cannot be submitted while add-on is '
'disabled.'
)
)
# This is replicating what Addon.get_required_metadata does
missing_addon_metadata = [
@ -471,8 +481,10 @@ class DeveloperVersionSerializer(VersionSerializer):
]
if missing_addon_metadata:
raise exceptions.ValidationError(
'Addon metadata is required to be set to create a listed '
f'version: {missing_addon_metadata}.',
gettext(
'Addon metadata is required to be set to create a listed '
'version: {missing_addon_metadata}.'
).format(missing_addon_metadata=missing_addon_metadata),
code='required',
)
else:
@ -893,7 +905,7 @@ class AddonSerializer(serializers.ModelSerializer):
# DeniedSlug.blocked checks for all numeric slugs as well as being denied.
if DeniedSlug.blocked(value):
raise exceptions.ValidationError(
'This slug cannot be used. Please choose another.'
gettext('This slug cannot be used. Please choose another.')
)
return value
@ -908,7 +920,9 @@ class AddonSerializer(serializers.ModelSerializer):
# We test for new versions in VersionSerailizer.validate instead
if channel == amo.RELEASE_CHANNEL_LISTED:
# This is replicating what Addon.get_required_metadata does
required_msg = 'This field is required for addons with listed versions.'
required_msg = gettext(
'This field is required for addons with listed versions.'
)
missing_metadata = {
field: required_msg
for field, value in (
@ -932,7 +946,7 @@ class AddonSerializer(serializers.ModelSerializer):
# double check we didn't lose any
if slugs != {cat.slug for cat in data['all_categories']}:
raise exceptions.ValidationError(
{'categories': 'Invalid category name.'}
{'categories': gettext('Invalid category name.')}
)
return data

Просмотреть файл

@ -1,4 +1,5 @@
from django import forms
from django.utils.translation import gettext
from rest_framework import exceptions
@ -33,7 +34,9 @@ class ValidateVersionLicense:
and 'custom_license' in request.data
):
raise exceptions.ValidationError(
'Both `license` and `custom_license` cannot be provided together.'
gettext(
'Both `license` and `custom_license` cannot be provided together.'
)
)
license_ = data.get('license')
@ -54,8 +57,10 @@ class ValidateVersionLicense:
raise exceptions.ValidationError(
{
'license': (
'This field, or custom_license, is required for listed '
'versions.'
gettext(
'This field, or custom_license, is required for '
'listed versions.'
)
)
},
code='required',
@ -82,10 +87,14 @@ class ValidateVersionLicense:
is_theme = addon_type == amo.ADDON_STATICTHEME
if isinstance(license_, License) and license_.creative_commons != is_theme:
raise exceptions.ValidationError(
{'license': 'Wrong addon type for this license.'},
{'license': gettext('Wrong addon type for this license.')},
code='required',
)
if is_custom and is_theme:
raise exceptions.ValidationError(
{'custom_license': 'Custom licenses are not supported for themes.'},
{
'custom_license': gettext(
'Custom licenses are not supported for themes.'
)
},
)

Просмотреть файл

@ -1,6 +1,7 @@
from django.core.exceptions import PermissionDenied
from django import http, shortcuts
from django.utils.crypto import constant_time_compare
from django.utils.translation import gettext
from rest_framework import exceptions, status
from rest_framework.mixins import CreateModelMixin
@ -77,13 +78,13 @@ class FileUploadViewSet(CreateModelMixin, ReadOnlyModelViewSet):
filedata = request.FILES['upload']
else:
raise exceptions.ValidationError(
'Missing "upload" key in multipart file data.',
gettext('Missing "upload" key in multipart file data.'),
status.HTTP_400_BAD_REQUEST,
)
channel = amo.CHANNEL_CHOICES_LOOKUP.get(request.POST.get('channel'))
if not channel:
raise exceptions.ValidationError(
'Missing "channel" arg.',
gettext('Missing "channel" arg.'),
status.HTTP_400_BAD_REQUEST,
)