Skip to content
This repository has been archived by the owner on Mar 15, 2018. It is now read-only.

Commit

Permalink
Merge pull request #3460 from diox/iarc-v2-translations
Browse files Browse the repository at this point in the history
Add texts for IARC mappings (bug 1228364)
  • Loading branch information
diox committed Dec 3, 2015
2 parents 38b7c6e + eb9c0b7 commit 52dbc89
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 43 deletions.
34 changes: 24 additions & 10 deletions mkt/constants/iarc_mappings.py
Expand Up @@ -191,6 +191,13 @@
},
}

# Change {body: {'key': 'val'}} to {'val': 'key'}. Used to deserialize our
# data back to IARC.
REVERSE_DESCS = {}
for mapping in [{unicode(v): unicode(k) for k, v in body_mapping.items() if v}
for body, body_mapping in DESCS.items()]:
REVERSE_DESCS.update(mapping)

# WARNING: When adding a new rating descriptor here also include a migration.
# All descriptor keys must be prefixed by the rating body (e.g. USK_).
#
Expand Down Expand Up @@ -327,16 +334,15 @@
'USK_ShopStreamingService': '',
'USK_Tabakkonsum': 'has_usk_tobacco',
}

}

# Change {body: {'key': 'val'}} to {'val': 'key'}, combining v1 and v2 dicts.
_REVERSE_DESCS_BY_BODY = [
{unicode(v): unicode(k) for k, v in body_mapping.items() if v}
for body, body_mapping in DESCS_V2.items() + DESCS.items()]
REVERSE_DESCS = {}
for mapping in _REVERSE_DESCS_BY_BODY:
REVERSE_DESCS.update(mapping)
# Change {body: {'key': 'val'}} to {'val': 'key'}. Used to deserialize our
# data back to IARC.
REVERSE_DESCS_V2 = {}
for mapping in [{unicode(v): unicode(k) for k, v in body_mapping.items() if v}
for body, body_mapping in DESCS_V2.items()]:
REVERSE_DESCS_V2.update(mapping)


# WARNING: When adding a new interactive element here also include a migration.
#
Expand All @@ -349,12 +355,20 @@
'Digital Purchases': 'has_digital_purchases',
}

REVERSE_INTERACTIVES = {v: k for k, v in INTERACTIVES.items()}

INTERACTIVES_V2 = {
'IE_UsersInteract': 'has_users_interact',
'IE_SharesInfo': 'has_shares_info',
'IE_SharesLocation': 'has_shares_location',
'IE_DigitalPurchases': 'has_digital_purchases',
}

REVERSE_INTERACTIVES = {v: k for k, v
in INTERACTIVES_V2.items() + INTERACTIVES.items()}
REVERSE_INTERACTIVES_V2 = {v: k for k, v in INTERACTIVES_V2.items()}

# Human readable text for descriptors and interactives should not be translated
# by us, the rating bodies are very specific about the texts. Instead, we use
# the V1 descriptors and interactives, since V1 used text instead of constants.
# When we phase out v1, we'll just add a dict of strings here instead.
HUMAN_READABLE_DESCS_AND_INTERACTIVES = dict(
REVERSE_DESCS.items() + REVERSE_INTERACTIVES.items())
22 changes: 22 additions & 0 deletions mkt/constants/tests/test_iarc_mappings.py
@@ -0,0 +1,22 @@
from nose.tools import ok_

import mkt.site.tests

from mkt.constants.iarc_mappings import (
HUMAN_READABLE_DESCS_AND_INTERACTIVES, REVERSE_DESCS, REVERSE_DESCS_V2,
REVERSE_INTERACTIVES, REVERSE_INTERACTIVES_V2)


class TestIARCMappings(mkt.site.tests.TestCase):

def test_all_human_readable_strings_are_present(self):
for key in REVERSE_DESCS:
ok_(key in HUMAN_READABLE_DESCS_AND_INTERACTIVES)
for key in REVERSE_DESCS_V2:
ok_(key in HUMAN_READABLE_DESCS_AND_INTERACTIVES)
for key in REVERSE_INTERACTIVES:
ok_(key in HUMAN_READABLE_DESCS_AND_INTERACTIVES)
for key in REVERSE_INTERACTIVES_V2:
ok_(key in HUMAN_READABLE_DESCS_AND_INTERACTIVES)
for value in HUMAN_READABLE_DESCS_AND_INTERACTIVES.values():
ok_('__proxy__' not in unicode(value))
Expand Up @@ -40,10 +40,10 @@ <h3>{{ _('Content Ratings') }}</h3>
{% set desc_icon = body.label in desc_icons and desc_icons[body.label][descriptor] %}
{% if desc_icon %}
<img src="{{ media(desc_icon) }}" class="icon"
title="{{ mkt.iarc_mappings.REVERSE_DESCS[descriptor] }}">
title="{{ mkt.iarc_mappings.HUMAN_READABLE_DESCS_AND_INTERACTIVES[descriptor] }}">
{% else %}
<span class="dot-sep descriptor">
{{ mkt.iarc_mappings.REVERSE_DESCS[descriptor] }}
{{ mkt.iarc_mappings.HUMAN_READABLE_DESCS_AND_INTERACTIVES[descriptor] }}
</span>
{% endif %}
{% else %}
Expand All @@ -62,15 +62,15 @@ <h3>{{ _('Interactive Elements') }}</h3>
<div class="names">
{% for interactive in interactives %}
<span class="dot-sep interactive">
{{ mkt.iarc_mappings.REVERSE_INTERACTIVES[interactive] }}
{{ mkt.iarc_mappings.HUMAN_READABLE_DESCS_AND_INTERACTIVES[interactive] }}
</span>
{% endfor %}
</div>
{% set inter_icons = mkt.ratingsbodies.IARC_ICONS.interactive_elements %}
{% for interactive in interactives %}
{% if inter_icons[interactive] %}
<img src="{{ media(inter_icons[interactive]) }}" class="icon"
title="{{ mkt.iarc_mappings.REVERSE_INTERACTIVES[interactive] }}">
title="{{ mkt.iarc_mappings.HUMAN_READABLE_DESCS_AND_INTERACTIVES[interactive] }}">
{% endif %}
{% endfor %}
</div>
Expand Down
43 changes: 30 additions & 13 deletions mkt/webapps/models.py
Expand Up @@ -19,6 +19,7 @@
from django.utils.translation import trans_real as translation

import commonware.log
import waffle
from cache_nuggets.lib import memoize, memoize_key
from django_extensions.db.fields.json import JSONField
from jingo.helpers import urlparams
Expand All @@ -32,8 +33,12 @@
from lib.iarc.utils import get_iarc_app_title, render_xml
from lib.utils import static_url
from mkt.access import acl
from mkt.constants import APP_FEATURES, apps, iarc_mappings
from mkt.constants import APP_FEATURES, apps
from mkt.constants.applications import DEVICE_TYPES
from mkt.constants.iarc_mappings import (HUMAN_READABLE_DESCS_AND_INTERACTIVES,
REVERSE_DESCS, REVERSE_DESCS_V2,
REVERSE_INTERACTIVES,
REVERSE_INTERACTIVES_V2)
from mkt.constants.payments import PROVIDER_CHOICES
from mkt.constants.regions import RESTOFWORLD
from mkt.files.models import File, nfd_str
Expand Down Expand Up @@ -2061,7 +2066,7 @@ def set_descriptors(self, data):
data -- list of database flags ('has_usk_lang')
"""
create_kwargs = {}
for db_flag in mkt.constants.iarc_mappings.REVERSE_DESCS.keys():
for db_flag in set(REVERSE_DESCS.keys() + REVERSE_DESCS_V2.keys()):
create_kwargs[db_flag] = db_flag in data

instance, created = RatingDescriptors.objects.get_or_create(
Expand All @@ -2078,13 +2083,14 @@ def set_interactives(self, data):
data -- list of database flags ('has_users_interact')
"""
create_kwargs = {}
for db_flag in mkt.constants.iarc_mappings.REVERSE_INTERACTIVES.keys():
for db_flag in set(REVERSE_INTERACTIVES.keys() +
REVERSE_INTERACTIVES_V2.keys()):
create_kwargs[db_flag] = db_flag in data

ri, created = RatingInteractives.objects.get_or_create(
instance, created = RatingInteractives.objects.get_or_create(
addon=self, defaults=create_kwargs)
if not created:
ri.update(**create_kwargs)
instance.update(**create_kwargs)

def set_iarc_storefront_data(self, disable=False):
"""Send app data to IARC for them to verify."""
Expand Down Expand Up @@ -2512,15 +2518,20 @@ def to_keys_by_body(self, body):
def iarc_deserialize(self, body=None):
"""Map our descriptor strings back to the IARC ones (comma-sep.)."""
keys = self.to_keys()
# FIXME: convert IARC v2 constants to text.
if waffle.switch_is_active('iarc-upgrade-v2'):
reverse_descriptors = REVERSE_DESCS_V2
else:
reverse_descriptors = REVERSE_DESCS
if body:
keys = [key for key in keys if body.iarc_name.lower() in key]
return ', '.join(iarc_mappings.REVERSE_DESCS.get(desc) for desc
return ', '.join(reverse_descriptors.get(desc) for desc
in keys)

# Add a dynamic field to `RatingDescriptors` model for each rating descriptor.
for db_flag, desc in mkt.iarc_mappings.REVERSE_DESCS.items():
field = models.BooleanField(default=False, help_text=desc)
for db_flag in set(REVERSE_DESCS.keys() + REVERSE_DESCS_V2.keys()):
field = models.BooleanField(
default=False,
help_text=HUMAN_READABLE_DESCS_AND_INTERACTIVES[db_flag])
field.contribute_to_class(RatingDescriptors, db_flag)


Expand All @@ -2540,15 +2551,21 @@ def __unicode__(self):
return u'%s: %s' % (self.id, self.addon.name)

def iarc_deserialize(self):
# FIXME: convert IARC v2 constants to text.
"""Map our descriptor strings back to the IARC ones (comma-sep.)."""
return ', '.join(iarc_mappings.REVERSE_INTERACTIVES.get(inter)
if waffle.switch_is_active('iarc-upgrade-v2'):
reverse_interactives = REVERSE_INTERACTIVES_V2
else:
reverse_interactives = REVERSE_INTERACTIVES
return ', '.join(reverse_interactives.get(inter)
for inter in self.to_keys())


# Add a dynamic field to `RatingInteractives` model for each rating descriptor.
for interactive, db_flag in mkt.iarc_mappings.INTERACTIVES.items():
field = models.BooleanField(default=False, help_text=interactive)
for db_flag in set(REVERSE_INTERACTIVES.keys() +
REVERSE_INTERACTIVES_V2.keys()):
field = models.BooleanField(
default=False,
help_text=HUMAN_READABLE_DESCS_AND_INTERACTIVES[db_flag])
field.contribute_to_class(RatingInteractives, db_flag)


Expand Down
16 changes: 9 additions & 7 deletions mkt/webapps/serializers.py
Expand Up @@ -15,6 +15,7 @@
TranslationSerializerField)
from mkt.constants.applications import DEVICE_TYPES
from mkt.constants.categories import CATEGORY_CHOICES
from mkt.constants.iarc_mappings import HUMAN_READABLE_DESCS_AND_INTERACTIVES
from mkt.constants.payments import PROVIDER_BANGO
from mkt.features.utils import load_feature_profile
from mkt.prices.models import AddonPremium, Price
Expand Down Expand Up @@ -159,14 +160,14 @@ def get_content_ratings(self, app):
app.rating_descriptors.to_keys_by_body(body)
if hasattr(app, 'rating_descriptors') else []),
'descriptors_text': (
[mkt.iarc_mappings.REVERSE_DESCS[key] for key in
app.rating_descriptors.to_keys_by_body(body)]
[HUMAN_READABLE_DESCS_AND_INTERACTIVES[key]
for key in app.rating_descriptors.to_keys_by_body(body)]
if hasattr(app, 'rating_descriptors') else []),
'interactives': (
app.rating_interactives.to_keys()
if hasattr(app, 'rating_interactives') else []),
'interactives_text': (
[mkt.iarc_mappings.REVERSE_INTERACTIVES[key] for key in
[HUMAN_READABLE_DESCS_AND_INTERACTIVES[key] for key in
app.rating_interactives.to_keys()]
if hasattr(app, 'rating_interactives') else []),
}
Expand Down Expand Up @@ -504,13 +505,14 @@ def get_content_ratings(self, obj):
'descriptors': [key for key in
obj.es_data.get('content_descriptors', [])
if prefix in key],
'descriptors_text': [mkt.iarc_mappings.REVERSE_DESCS[key] for key
'descriptors_text': [HUMAN_READABLE_DESCS_AND_INTERACTIVES[key]
for key
in obj.es_data.get('content_descriptors')
if prefix in key],
'interactives': obj.es_data.get('interactive_elements', []),
'interactives_text': [mkt.iarc_mappings.REVERSE_INTERACTIVES[key]
for key in
obj.es_data.get('interactive_elements')]
'interactives_text': [HUMAN_READABLE_DESCS_AND_INTERACTIVES[key]
for key
in obj.es_data.get('interactive_elements')]
}

def get_feature_compatibility(self, app):
Expand Down
41 changes: 32 additions & 9 deletions mkt/webapps/tests/test_models.py
Expand Up @@ -29,8 +29,8 @@
from lib.utils import static_url
from mkt.constants import apps, MANIFEST_CONTENT_TYPE
from mkt.constants.applications import DEVICE_TYPES
from mkt.constants.iarc_mappings import (DESCS, INTERACTIVES, REVERSE_DESCS,
REVERSE_INTERACTIVES)
from mkt.constants.iarc_mappings import (DESCS, INTERACTIVES,
REVERSE_DESCS, REVERSE_INTERACTIVES)
from mkt.constants.payments import PROVIDER_BANGO, PROVIDER_REFERENCE
from mkt.constants.regions import RESTOFWORLD
from mkt.developers.models import (AddonPaymentAccount, PaymentAccount,
Expand Down Expand Up @@ -2281,15 +2281,30 @@ def test_desc_mapping(self):

def test_reverse_desc_mapping(self):
descs = RatingDescriptors.objects.create(addon=app_factory())
for desc in descs._fields():
eq_(type(REVERSE_DESCS.get(desc)), unicode, desc)
for field in descs._fields():
ok_(isinstance(REVERSE_DESCS.get(field), basestring))

def test_iarc_deserialize(self):
descs = RatingDescriptors.objects.create(
addon=app_factory(), has_esrb_blood=True, has_pegi_scary=True)
addon=app_factory(), has_esrb_blood=True, has_pegi_scary=True,
has_classind_drugs_legal=True)
self.assertSetEqual(descs.iarc_deserialize().split(', '),
['Blood', 'Fear'])
eq_(descs.iarc_deserialize(body=mkt.ratingsbodies.ESRB), 'Blood')
[u'Blood', u'Drogas L\xedcitas', u'Fear'])
eq_(descs.iarc_deserialize(body=mkt.ratingsbodies.ESRB), u'Blood')
eq_(descs.iarc_deserialize(
body=mkt.ratingsbodies.CLASSIND), u'Drogas L\xedcitas')

def test_iarc_deserialize_v2(self):
self.create_switch('iarc-upgrade-v2')
descs = RatingDescriptors.objects.create(
addon=app_factory(), has_esrb_blood=True, has_pegi_scary=True,
has_classind_drugs_legal=True)
self.assertSetEqual(descs.iarc_deserialize().split(', '),
[u'ClassInd_DrogasLicitas', u'PEGI_Fear',
u'ESRB_Blood'])
eq_(descs.iarc_deserialize(body=mkt.ratingsbodies.ESRB), u'ESRB_Blood')
eq_(descs.iarc_deserialize(
body=mkt.ratingsbodies.CLASSIND), u'ClassInd_DrogasLicitas')


class TestRatingInteractives(mkt.site.tests.TestCase):
Expand All @@ -2304,8 +2319,8 @@ def test_interactives_mapping(self):

def test_reverse_interactives_mapping(self):
interactives = RatingInteractives.objects.create(addon=app_factory())
for interactive_field in interactives._fields():
assert REVERSE_INTERACTIVES.get(interactive_field)
for field in interactives._fields():
ok_(isinstance(REVERSE_INTERACTIVES.get(field), basestring), field)

def test_iarc_deserialize(self):
interactives = RatingInteractives.objects.create(
Expand All @@ -2314,6 +2329,14 @@ def test_iarc_deserialize(self):
interactives.iarc_deserialize().split(', '),
['Shares Info', 'Users Interact'])

def test_iarc_deserialize_v2(self):
self.create_switch('iarc-upgrade-v2')
interactives = RatingInteractives.objects.create(
addon=app_factory(), has_users_interact=True, has_shares_info=True)
self.assertSetEqual(
interactives.iarc_deserialize().split(', '),
['IE_SharesInfo', 'IE_UsersInteract'])


class TestManifestUpload(BaseUploadTest, mkt.site.tests.TestCase):
fixtures = fixture('webapp_337141')
Expand Down

0 comments on commit 52dbc89

Please sign in to comment.