예제 #1
0
    def fetch_all_translations(self, obj, source, field):
        # TODO: get all locales or KEY_LOCALES_FOR_EDITORIAL_CONTENT at least?
        base_locale = to_language(settings.LANGUAGE_CODE)
        current_locale = to_language(get_language())
        default_locale = obj.default_locale

        return self._fetch_some_translations(
            field, {base_locale, current_locale, default_locale})
예제 #2
0
    def fetch_single_translation(self, obj, source, field, requested_language):
        value = gettext(field) if field else field
        default_language = to_language(settings.LANGUAGE_CODE)
        requested_language = to_language(requested_language)
        if not value or requested_language == default_language or value != field:
            actual_language = requested_language
        else:
            # we've fallen back to the default locale
            actual_language = default_language

        return self._format_single_translation_response(
            value,
            actual_language,
            requested_language,
        )
예제 #3
0
 def get_context_data(self):
     addon_url = self.addon.get_url_path(add_prefix=False)
     # We need to display the name in some language that is relevant to the
     # recipient(s) instead of using the reviewer's. addon.default_locale
     # should work.
     if self.addon.name.locale != self.addon.default_locale:
         lang = to_language(self.addon.default_locale)
         with translation.override(lang):
             addon = Addon.unfiltered.get(pk=self.addon.pk)
     else:
         addon = self.addon
     review_url_kw = {'addon_id': self.addon.pk}
     if (self.version and
             self.version.channel == amo.RELEASE_CHANNEL_UNLISTED):
         review_url_kw['channel'] = 'unlisted'
         dev_ver_url = reverse(
             'devhub.addons.versions',
             args=[self.addon.id])
     else:
         dev_ver_url = self.addon.get_dev_url('versions')
     return {'name': addon.name,
             'number': self.version.version if self.version else '',
             'reviewer': self.user.display_name,
             'addon_url': absolutify(addon_url),
             'dev_versions_url': absolutify(dev_ver_url),
             'review_url': absolutify(reverse('reviewers.review',
                                              kwargs=review_url_kw,
                                              add_prefix=False)),
             'comments': self.data.get('comments'),
             'SITE_URL': settings.SITE_URL}
예제 #4
0
 def get_context_data(self):
     addon_url = self.addon.get_url_path(add_prefix=False)
     # We need to display the name in some language that is relevant to the
     # recipient(s) instead of using the reviewer's. addon.default_locale
     # should work.
     if self.addon.name.locale != self.addon.default_locale:
         lang = to_language(self.addon.default_locale)
         with translation.override(lang):
             addon = Addon.unfiltered.get(pk=self.addon.pk)
     else:
         addon = self.addon
     review_url_kw = {'addon_id': self.addon.pk}
     if (self.version and
             self.version.channel == amo.RELEASE_CHANNEL_UNLISTED):
         review_url_kw['channel'] = 'unlisted'
         dev_ver_url = reverse(
             'devhub.addons.versions',
             args=[self.addon.id])
     else:
         dev_ver_url = self.addon.get_dev_url('versions')
     return {'name': addon.name,
             'number': self.version.version if self.version else '',
             'reviewer': self.user.display_name,
             'addon_url': absolutify(addon_url),
             'dev_versions_url': absolutify(dev_ver_url),
             'review_url': absolutify(reverse('reviewers.review',
                                              kwargs=review_url_kw,
                                              add_prefix=False)),
             'comments': self.data.get('comments'),
             'SITE_URL': settings.SITE_URL}
예제 #5
0
 def fetch_all_translations(self, obj, source, field):
     translations = field.__class__.objects.filter(
         id=field.id, localized_string__isnull=False)
     return {
         to_language(trans.locale): unicode(trans)
         for trans in translations
     } if translations else None
예제 #6
0
 def get_context_data(self):
     addon_url = self.addon.get_url_path(add_prefix=False)
     dev_ver_url = self.addon.get_dev_url('versions')
     # We need to display the name in some language that is relevant to the
     # recipient(s) instead of using the reviewer's. addon.default_locale
     # should work.
     if self.addon.name.locale != self.addon.default_locale:
         lang = to_language(self.addon.default_locale)
         with translation.override(lang):
             addon = Addon.unfiltered.get(pk=self.addon.pk)
     else:
         addon = self.addon
     return {
         'name':
         addon.name,
         'number':
         self.version.version if self.version else '',
         'reviewer':
         self.user.display_name,
         'addon_url':
         absolutify(addon_url),
         'dev_versions_url':
         absolutify(dev_ver_url),
         'review_url':
         absolutify(
             reverse('editors.review',
                     args=[self.addon.pk],
                     add_prefix=False)),
         'comments':
         self.data.get('comments'),
         'SITE_URL':
         settings.SITE_URL
     }
예제 #7
0
 def fetch_all_translations(self, obj, source, field):
     # this property is set by amo.utils.attach_trans_dict
     if trans_dict := getattr(obj, 'translations', None):
         translations = trans_dict.get(field.id, [])
         return {
             to_language(locale): value
             for (locale, value) in translations
         }
예제 #8
0
 def _fetch_some_translations(self, field, langs):
     if not field:
         return {}
     base_locale = to_language(settings.LANGUAGE_CODE)
     translations = {}
     if base_locale in langs:
         # we get the base_locale for free - it's just the field text
         translations[base_locale] = str(field)
         langs = (lang for lang in langs if lang != base_locale)
     for lang in langs:
         with override(lang):
             value = gettext(field)
             if value not in translations.values():
                 translations[lang] = value
     return translations
예제 #9
0
    def fetch_single_translation(self, obj, source, field, requested_language):
        base_locale = to_language(settings.LANGUAGE_CODE)
        default_locale = obj.default_locale

        translations = self._fetch_some_translations(
            field, {base_locale, requested_language, default_locale})
        actual_language = (
            requested_language if requested_language in translations else
            default_locale if default_locale in translations else base_locale)

        value = translations.get(actual_language)

        return self._format_single_translation_response(
            value,
            actual_language,
            requested_language,
        )
예제 #10
0
 def get_context_data(self):
     addon_url = self.addon.get_url_path(add_prefix=False)
     dev_ver_url = self.addon.get_dev_url('versions')
     # We need to display the name in some language that is relevant to the
     # recipient(s) instead of using the reviewer's. addon.default_locale
     # should work.
     if self.addon.name.locale != self.addon.default_locale:
         lang = to_language(self.addon.default_locale)
         with translation.override(lang):
             addon = Addon.unfiltered.get(pk=self.addon.pk)
     else:
         addon = self.addon
     return {'name': addon.name,
             'number': self.version.version if self.version else '',
             'reviewer': self.user.display_name,
             'addon_url': absolutify(addon_url),
             'dev_versions_url': absolutify(dev_ver_url),
             'review_url': absolutify(reverse('editors.review',
                                              args=[self.addon.pk],
                                              add_prefix=False)),
             'comments': self.data.get('comments'),
             'SITE_URL': settings.SITE_URL}
예제 #11
0
 def fetch_all_translations(self, obj, source, field):
     translations = field.__class__.objects.filter(id=field.id, localized_string__isnull=False)
     return dict((to_language(trans.locale), unicode(trans)) for trans in translations) if translations else None
예제 #12
0
def build_webext_dictionary_from_legacy(addon, destination):
    """Create a webext package of a legacy dictionary `addon`, and put it in
    `destination` path."""
    from olympia.files.utils import SafeZip  # Avoid circular import.
    old_path = addon.current_version.all_files[0].file_path
    old_zip = SafeZip(old_path)
    if not old_zip.is_valid:
        raise ValidationError('Current dictionary xpi is not valid')

    dictionary_path = ''

    with zipfile.ZipFile(destination, 'w', zipfile.ZIP_DEFLATED) as new_zip:
        for obj in old_zip.filelist:
            splitted = obj.filename.split('/')
            # Ignore useless directories and files.
            if splitted[0] in ('META-INF', '__MACOSX', 'chrome',
                               'chrome.manifest', 'install.rdf'):
                continue

            # Also ignore javascript (regardless of where they are, not just at
            # the root), since dictionaries should not contain any code.
            if splitted[-1].endswith('.js'):
                continue

            # Store the path of the last .dic file we find. It can be inside a
            # directory.
            if (splitted[-1].endswith('.dic')):
                dictionary_path = obj.filename

            new_zip.writestr(obj.filename, old_zip.read(obj.filename))

        # Now that all files we want from the old zip are copied, build and
        # add manifest.json.
        if not dictionary_path:
            # This should not happen... It likely means it's an invalid
            # dictionary to begin with, or one that has its .dic file in a
            # chrome/ directory for some reason. Abort!
            raise ValidationError('Current dictionary xpi has no .dic file')

        if addon.target_locale:
            target_language = addon.target_locale
        else:
            # Guess target_locale since we don't have one already. Note that
            # for extra confusion, target_locale is a language, not a locale.
            target_language = to_language(
                os.path.splitext(os.path.basename(dictionary_path))[0])
            if target_language not in settings.AMO_LANGUAGES:
                # We couldn't find that language in the list we support. Let's
                # try with just the prefix.
                target_language = target_language.split('-')[0]
                if target_language not in settings.AMO_LANGUAGES:
                    # We tried our best.
                    raise ValidationError(u'Addon has no target_locale and we'
                                          u' could not guess one from the xpi')

        # Dumb version number increment. This will be invalid in some cases,
        # but some of the dictionaries we have currently already have wild
        # version numbers anyway.
        version_number = addon.current_version.version
        if version_number.endswith('.1-typefix'):
            version_number = version_number.replace('.1-typefix', '.2webext')
        else:
            version_number = '%s.1webext' % version_number

        manifest = {
            'manifest_version': 2,
            'name': unicode(addon.name),
            'browser_specific_settings': {
                'gecko': {
                    'id': addon.guid,
                },
            },
            'version': version_number,
            'dictionaries': {
                target_language: dictionary_path
            },
        }

        # Write manifest.json we just build.
        new_zip.writestr('manifest.json', json.dumps(manifest))
예제 #13
0
def test_to_language(test_input, expected):
    assert to_language(test_input) == expected
예제 #14
0
def test_to_language(test_input, expected):
    assert to_language(test_input) == expected
예제 #15
0
 def check(a, b):
     eq_(to_language(a), b)
예제 #16
0
        request = self.context.get('request', None)
        if request and request.method == 'GET' and 'lang' in request.GET:
            return request.GET['lang']
        else:
            return None

    def fetch_all_translations(self, obj, source, field):
        # this property is set by amo.utils.attach_trans_dict
        if trans_dict := getattr(obj, 'translations', None):
            translations = trans_dict.get(field.id, [])
            return {to_language(locale): value for (locale, value) in translations}
        else:
            translations = field.__class__.objects.filter(
                id=field.id, localized_string__isnull=False
            )
            return {to_language(trans.locale): str(trans) for trans in translations}

    def _format_single_translation_response(self, value, lang, requested_lang):
        if not value or not lang:
            return None
        if lang == requested_lang:
            return {lang: value}
        else:
            return {lang: value, requested_lang: None, '_default': lang}

    def fetch_single_translation(self, obj, source, field, requested_language):
        return self._format_single_translation_response(
            str(field) if field else field,
            to_language(field.locale),
            to_language(requested_language),
        )
예제 #17
0
 def fetch_single_translation(self, obj, source, field, requested_language):
     return self._format_single_translation_response(
         str(field) if field else field,
         to_language(field.locale),
         to_language(requested_language),
     )
예제 #18
0
        request = self.context.get('request', None)
        return is_gate_active(request, 'l10n_flat_input_output')

    def fetch_all_translations(self, obj, source, field):
        # this property is set by amo.utils.attach_trans_dict
        if trans_dict := getattr(obj, 'translations', None):
            translations = trans_dict.get(field.id, [])
            return {
                to_language(locale): value
                for (locale, value) in translations
            }
        else:
            translations = field.__class__.objects.filter(
                id=field.id, localized_string__isnull=False)
            return {
                to_language(trans.locale): str(trans)
                for trans in translations
            }

    def _format_single_translation_response(self, value, lang, requested_lang):
        if not value or not lang:
            return None
        if lang == requested_lang:
            return {lang: value}
        else:
            return {lang: value, requested_lang: None, '_default': lang}

    def fetch_single_translation(self, obj, source, field, requested_language):
        return self._format_single_translation_response(
            str(field) if field else field,
            to_language(field.locale),
예제 #19
0
def extract(addon):
    """Extract indexable attributes from an add-on."""
    attrs = ('id', 'slug', 'created', 'default_locale', 'last_updated',
             'weekly_downloads', 'bayesian_rating', 'average_daily_users',
             'status', 'type', 'hotness', 'is_disabled', 'is_listed')
    d = {attr: getattr(addon, attr) for attr in attrs}
    # Coerce the Translation into a string.
    d['name_sort'] = unicode(addon.name).lower()
    translations = addon.translations
    d['name'] = list(set(string for _, string in translations[addon.name_id]))
    d['name_translations'] = [
        {'lang': to_language(lang), 'string': string}
        for lang, string in addon.translations[addon.name_id] if string]
    d['description'] = list(set(string for _, string
                                in translations[addon.description_id]))
    d['description_translations'] = [
        {'lang': to_language(lang), 'string': string}
        for lang, string in addon.translations[addon.description_id] if string]
    d['summary'] = list(set(string for _, string
                            in translations[addon.summary_id]))
    d['authors'] = [a.name for a in addon.listed_authors]
    d['device'] = getattr(addon, 'device_ids', [])
    # This is an extra query, not good for perf.
    d['category'] = getattr(addon, 'category_ids', [])
    d['tags'] = getattr(addon, 'tag_list', [])
    d['price'] = getattr(addon, 'price', 0.0)
    if addon.current_version:
        d['platforms'] = [p.id for p in
                          addon.current_version.supported_platforms]
    d['appversion'] = {}
    for app, appver in addon.compatible_apps.items():
        if appver:
            min_, max_ = appver.min.version_int, appver.max.version_int
        else:
            # Fake wide compatibility for search tools and personas.
            min_, max_ = 0, version_int('9999')
        d['appversion'][app.id] = dict(min=min_, max=max_)
    try:
        d['has_version'] = addon._current_version is not None
    except ObjectDoesNotExist:
        d['has_version'] = None
    d['app'] = [app.id for app in addon.compatible_apps.keys()]

    if addon.type == amo.ADDON_PERSONA:
        try:
            # This would otherwise get attached when by the transformer.
            d['weekly_downloads'] = addon.persona.popularity
            # Boost on popularity.
            d['boost'] = addon.persona.popularity ** .2
            d['has_theme_rereview'] = (
                addon.persona.rereviewqueuetheme_set.exists())
        except Persona.DoesNotExist:
            # The addon won't have a persona while it's being created.
            pass
    else:
        # Boost by the number of users on a logarithmic scale. The maximum
        # boost (11,000,000 users for adblock) is about 5x.
        d['boost'] = addon.average_daily_users ** .2
    # Double the boost if the add-on is public.
    if addon.status == amo.STATUS_PUBLIC and 'boost' in d:
        d['boost'] = max(d['boost'], 1) * 4

    # Indices for each language. languages is a list of locales we want to
    # index with analyzer if the string's locale matches.
    for analyzer, languages in amo.SEARCH_ANALYZER_MAP.iteritems():
        if (not settings.ES_USE_PLUGINS and
                analyzer in amo.SEARCH_ANALYZER_PLUGINS):
            continue

        d['name_' + analyzer] = list(
            set(string for locale, string in translations[addon.name_id]
                if locale.lower() in languages))
        d['summary_' + analyzer] = list(
            set(string for locale, string in translations[addon.summary_id]
                if locale.lower() in languages))
        d['description_' + analyzer] = list(
            set(string for locale, string in translations[addon.description_id]
                if locale.lower() in languages))

    return d
예제 #20
0
 def check(a, b):
     eq_(to_language(a), b)
예제 #21
0
파일: fields.py 프로젝트: diox/olympia
 def fetch_single_translation(self, obj, source, field, requested_language):
     return (
         {to_language(field.locale): six.text_type(field)} if field
         else None)
예제 #22
0
파일: fields.py 프로젝트: diox/olympia
 def fetch_all_translations(self, obj, source, field):
     translations = field.__class__.objects.filter(
         id=field.id, localized_string__isnull=False)
     return {to_language(trans.locale): six.text_type(trans)
             for trans in translations} if translations else None
예제 #23
0
 def check(a, b):
     assert to_language(a) == b
예제 #24
0
 def fetch_single_translation(self, obj, source, field, requested_language):
     return {to_language(field.locale): str(field)} if field else None
예제 #25
0
 def check(a, b):
     assert to_language(a) == b
예제 #26
0
 def fetch_single_translation(self, obj, source, field, requested_language):
     return {to_language(field.locale): unicode(field)} if field else None
예제 #27
0
def build_webext_dictionary_from_legacy(addon, destination):
    """Create a webext package of a legacy dictionary `addon`, and put it in
    `destination` path."""
    from olympia.files.utils import SafeZip  # Avoid circular import.
    old_path = addon.current_version.all_files[0].file_path
    old_zip = SafeZip(old_path)
    if not old_zip.is_valid:
        raise ValidationError('Current dictionary xpi is not valid')

    dictionary_path = ''

    with zipfile.ZipFile(destination, 'w', zipfile.ZIP_DEFLATED) as new_zip:
        for obj in old_zip.filelist:
            splitted = obj.filename.split('/')
            # Ignore useless directories and files.
            if splitted[0] in ('META-INF', '__MACOSX', 'chrome',
                               'chrome.manifest', 'install.rdf'):
                continue

            # Also ignore javascript (regardless of where they are, not just at
            # the root), since dictionaries should not contain any code.
            if splitted[-1].endswith('.js'):
                continue

            # Store the path of the last .dic file we find. It can be inside a
            # directory.
            if (splitted[-1].endswith('.dic')):
                dictionary_path = obj.filename

            new_zip.writestr(obj.filename, old_zip.read(obj.filename))

        # Now that all files we want from the old zip are copied, build and
        # add manifest.json.
        if not dictionary_path:
            # This should not happen... It likely means it's an invalid
            # dictionary to begin with, or one that has its .dic file in a
            # chrome/ directory for some reason. Abort!
            raise ValidationError('Current dictionary xpi has no .dic file')

        if addon.target_locale:
            target_language = addon.target_locale
        else:
            # Guess target_locale since we don't have one already. Note that
            # for extra confusion, target_locale is a language, not a locale.
            target_language = to_language(os.path.splitext(
                os.path.basename(dictionary_path))[0])
            if target_language not in settings.AMO_LANGUAGES:
                # We couldn't find that language in the list we support. Let's
                # try with just the prefix.
                target_language = target_language.split('-')[0]
                if target_language not in settings.AMO_LANGUAGES:
                    # We tried our best.
                    raise ValidationError(u'Addon has no target_locale and we'
                                          u' could not guess one from the xpi')

        # Dumb version number increment. This will be invalid in some cases,
        # but some of the dictionaries we have currently already have wild
        # version numbers anyway.
        version_number = addon.current_version.version
        if version_number.endswith('.1-typefix'):
            version_number = version_number.replace('.1-typefix', '.2webext')
        else:
            version_number = '%s.1webext' % version_number

        manifest = {
            'manifest_version': 2,
            'name': unicode(addon.name),
            'applications': {
                'gecko': {
                    'id': addon.guid,
                },
            },
            'version': version_number,
            'dictionaries': {target_language: dictionary_path},
        }

        # Write manifest.json we just build.
        new_zip.writestr('manifest.json', json.dumps(manifest))
예제 #28
0
 def fetch_all_translations(self, obj, source, field):
     # skip gettext in the default locale
     # TODO: iterate through all/subset of locales to actually get all translations?
     return {to_language(settings.LANGUAGE_CODE): str(field)}