Ejemplo n.º 1
0
def firefox_all(request):
    ftl_files = 'firefox/all'
    product_android = firefox_android
    product_desktop = firefox_desktop

    # Human-readable product labels
    products = OrderedDict([
        ('desktop_release',
         ftl('firefox-all-product-firefox', ftl_files=ftl_files)),
        ('desktop_beta',
         ftl('firefox-all-product-firefox-beta', ftl_files=ftl_files)),
        ('desktop_developer',
         ftl('firefox-all-product-firefox-developer', ftl_files=ftl_files)),
        ('desktop_nightly',
         ftl('firefox-all-product-firefox-nightly', ftl_files=ftl_files)),
        ('desktop_esr',
         ftl('firefox-all-product-firefox-esr', ftl_files=ftl_files)),
        ('android_release',
         ftl('firefox-all-product-firefox-android', ftl_files=ftl_files)),
        ('android_beta',
         ftl('firefox-all-product-firefox-android-beta', ftl_files=ftl_files)),
        ('android_nightly',
         ftl('firefox-all-product-firefox-android-nightly',
             ftl_files=ftl_files)),
    ])

    channel_release = 'release'
    channel_beta = 'beta'
    channel_dev = 'devedition'
    channel_nightly = 'nightly'
    channel_esr = 'esr'
    channel_esr_next = 'esr_next'

    latest_release_version_desktop = product_desktop.latest_version(
        channel_release)
    latest_beta_version_desktop = product_desktop.latest_version(channel_beta)
    latest_developer_version_desktop = product_desktop.latest_version(
        channel_dev)
    latest_nightly_version_desktop = product_desktop.latest_version(
        channel_nightly)
    latest_esr_version_desktop = product_desktop.latest_version(channel_esr)
    latest_esr_next_version_desktop = product_desktop.latest_version(
        channel_esr_next)

    latest_release_version_android = product_android.latest_version(
        channel_release)
    latest_beta_version_android = product_android.latest_version(channel_beta)
    latest_nightly_version_android = product_android.latest_version(
        channel_nightly)

    context = {
        'products':
        products.items(),
        'desktop_release_platforms':
        product_desktop.platforms(channel_release),
        'desktop_release_full_builds':
        product_desktop.get_filtered_full_builds(
            channel_release, latest_release_version_desktop),
        'desktop_release_channel_label':
        product_desktop.channel_labels.get(channel_release, 'Firefox'),
        'desktop_release_latest_version':
        latest_release_version_desktop,
        'desktop_beta_platforms':
        product_desktop.platforms(channel_beta),
        'desktop_beta_full_builds':
        product_desktop.get_filtered_full_builds(channel_beta,
                                                 latest_beta_version_desktop),
        'desktop_beta_channel_label':
        product_desktop.channel_labels.get(channel_beta, 'Firefox'),
        'desktop_beta_latest_version':
        latest_beta_version_desktop,
        'desktop_developer_platforms':
        product_desktop.platforms(channel_dev),
        'desktop_developer_full_builds':
        product_desktop.get_filtered_full_builds(
            channel_dev, latest_developer_version_desktop),
        'desktop_developer_channel_label':
        product_desktop.channel_labels.get(channel_dev, 'Firefox'),
        'desktop_developer_latest_version':
        latest_developer_version_desktop,
        'desktop_nightly_platforms':
        product_desktop.platforms(channel_nightly),
        'desktop_nightly_full_builds':
        product_desktop.get_filtered_full_builds(
            channel_nightly, latest_nightly_version_desktop),
        'desktop_nightly_channel_label':
        product_desktop.channel_labels.get(channel_nightly, 'Firefox'),
        'desktop_nightly_latest_version':
        latest_nightly_version_desktop,
        'desktop_esr_platforms':
        product_desktop.platforms(channel_esr),
        'desktop_esr_full_builds':
        product_desktop.get_filtered_full_builds(channel_esr,
                                                 latest_esr_version_desktop),
        'desktop_esr_channel_label':
        product_desktop.channel_labels.get(channel_esr, 'Firefox'),
        'desktop_esr_latest_version':
        latest_esr_version_desktop,
        'android_release_platforms':
        product_android.platforms(channel_release),
        'android_release_full_builds':
        product_android.get_filtered_full_builds(
            channel_release, latest_release_version_android),
        'android_release_channel_label':
        product_android.channel_labels.get(channel_release, 'Firefox'),
        'android_release_latest_version':
        latest_release_version_android,
        'android_beta_platforms':
        product_android.platforms(channel_beta),
        'android_beta_full_builds':
        product_android.get_filtered_full_builds(channel_beta,
                                                 latest_beta_version_android),
        'android_beta_channel_label':
        product_android.channel_labels.get(channel_beta, 'Firefox'),
        'android_beta_latest_version':
        latest_beta_version_android,
        'android_nightly_platforms':
        product_android.platforms(channel_nightly),
        'android_nightly_full_builds':
        product_android.get_filtered_full_builds(
            channel_nightly, latest_nightly_version_android),
        'android_nightly_channel_label':
        product_android.channel_labels.get(channel_nightly, 'Firefox'),
        'android_nightly_latest_version':
        latest_nightly_version_android,
    }

    if latest_esr_next_version_desktop:
        context['desktop_esr_platforms_next'] = product_desktop.platforms(
            channel_esr_next, True)
        context[
            'desktop_esr_full_builds_next'] = product_desktop.get_filtered_full_builds(
                channel_esr_next, latest_esr_next_version_desktop)
        context['desktop_esr_channel_label_next'] = (
            product_desktop.channel_labels.get(channel_esr_next, 'Firefox'), )
        context['desktop_esr_next_version'] = latest_esr_next_version_desktop

    return l10n_utils.render(request,
                             'firefox/all-unified.html',
                             context,
                             ftl_files=ftl_files)
Ejemplo n.º 2
0
 def test_ftl_view_util(self):
     assert fluent.ftl("fluent-title", locale="de", ftl_files="mozorg/fluent") == "Title in German"
Ejemplo n.º 3
0
class NewsletterFooterForm(forms.Form):
    """
    Form used to subscribe to a single newsletter, typically in the
    footer of a page (see newsletters/middleware.py) but sometimes
    on a dedicated page.
    """

    choice_labels = {
        "mozilla-foundation":
        ftl("multi-newsletter-form-checkboxes-label-mozilla"),
        "mozilla-and-you":
        ftl("multi-newsletter-form-checkboxes-label-firefox"),
    }

    email = forms.EmailField(widget=EmailInput(attrs={"required": "required"}))
    # first/last_name not yet included in email_newsletter_form helper
    # currently used on /contribute/friends/ (custom markup)
    first_name = forms.CharField(widget=forms.TextInput, required=False)
    last_name = forms.CharField(widget=forms.TextInput, required=False)
    fmt = forms.ChoiceField(widget=SimpleRadioSelect,
                            choices=FORMATS,
                            initial="H")
    privacy = forms.BooleanField(widget=PrivacyWidget)
    source_url = forms.CharField(required=False)
    newsletters = forms.MultipleChoiceField(
        widget=forms.CheckboxSelectMultiple())

    # has to take a newsletters argument so it can figure
    # out which languages to list in the form.
    def __init__(self, newsletters, locale, data=None, *args, **kwargs):
        regions = product_details.get_regions(locale)
        regions = sorted(iter(regions.items()), key=itemgetter(1))

        try:
            if isinstance(newsletters, str):
                newsletters = newsletters.split(",")
            newsletters = validate_newsletters(newsletters)
        except ValidationError:
            # replace with most common good newsletter
            # form validation will work with submitted data
            newsletters = ["mozilla-and-you"]

        lang = locale.lower()
        if "-" in lang:
            lang, country = lang.split("-", 1)
        else:
            country = ""
            regions.insert(
                0, ("",
                    ftl_lazy("newsletter-form-select-country-or-region",
                             fallback="newsletter-form-select-country")))
        lang_choices = get_lang_choices(newsletters)
        languages = [x[0] for x in lang_choices]
        if lang not in languages:
            # The lang from their locale is not one that our newsletters
            # are translated into. Initialize the language field to no
            # choice, to force the user to pick one of the languages that
            # we do support.
            lang = ""
            lang_choices.insert(
                0, ("", ftl_lazy("newsletter-form-available-languages")))

        super().__init__(data, *args, **kwargs)

        required_args = {
            "required": "required",
            "aria-required": "true",
        }
        country_widget = widgets.Select(attrs=required_args)
        country_label = ftl_lazy("newsletter-form-select-country-or-region",
                                 fallback="newsletter-form-select-country")
        self.fields["country"] = forms.ChoiceField(widget=country_widget,
                                                   choices=regions,
                                                   initial=country,
                                                   required=False,
                                                   label=country_label)
        lang_widget = widgets.Select(attrs=required_args)
        lang_label = ftl_lazy("newsletter-form-select-language",
                              fallback="newsletter-form-available-languages")
        self.fields["lang"] = forms.TypedChoiceField(widget=lang_widget,
                                                     choices=lang_choices,
                                                     initial=lang,
                                                     required=False,
                                                     label=lang_label)
        self.fields["newsletters"].choices = [(n, self.choice_labels.get(n, n))
                                              for n in newsletters]
        self.fields["newsletters"].initial = newsletters

    def clean_newsletters(self):
        return validate_newsletters(self.cleaned_data["newsletters"])

    def clean_source_url(self):
        su = self.cleaned_data["source_url"].strip()
        if su:
            # limit to 255 characters by truncation
            return su[:255]

        return su
Ejemplo n.º 4
0
 def __init__(self, attrs=None):
     choices = (
         ("true", ftl("newsletter-form-yes")),
         ("false", ftl("newsletter-form-no")),
     )
     super().__init__(attrs, choices)
Ejemplo n.º 5
0
 def test_ftl_view_util_default_files(self):
     """Should use default FTL files"""
     assert fluent.ftl('fluent-title', locale='de') == 'Title in German'
Ejemplo n.º 6
0
 def test_ftl_view_util_active_locale(self):
     """Should use activated locale if not provided"""
     translation.activate('fr')
     assert fluent.ftl('fluent-title') == 'Title in French'
Ejemplo n.º 7
0
 def test_ftl_view_util_no_mutate_list(self):
     """Should not mutate the ftl_files list"""
     ftl_files = ['mozorg/fluent']
     assert fluent.ftl('fluent-title', locale='de',
                       ftl_files=ftl_files) == 'Title in German'
     assert ftl_files == ['mozorg/fluent']
Ejemplo n.º 8
0
 def test_ftl_view_util_tuple(self):
     """Should be able to pass in a tuple of ftl files"""
     ftl_files = ('mozorg/fluent', )
     assert fluent.ftl('fluent-title', locale='de',
                       ftl_files=ftl_files) == 'Title in German'
Ejemplo n.º 9
0
 def test_ftl_view_util(self):
     assert fluent.ftl('fluent-title',
                       locale='de',
                       ftl_files='mozorg/fluent') == 'Title in German'
Ejemplo n.º 10
0
def firefox_all(request):
    ftl_files = 'firefox/all'
    product_android = firefox_android
    product_desktop = firefox_desktop
    product_ios = firefox_ios

    # Human-readable product labels
    products = OrderedDict(
        [
            ('desktop_release', ftl('firefox-all-product-firefox', ftl_files=ftl_files)),
            ('desktop_beta', ftl('firefox-all-product-firefox-beta', ftl_files=ftl_files)),
            ('desktop_developer', ftl('firefox-all-product-firefox-developer', ftl_files=ftl_files)),
            ('desktop_nightly', ftl('firefox-all-product-firefox-nightly', ftl_files=ftl_files)),
            ('desktop_esr', ftl('firefox-all-product-firefox-esr', ftl_files=ftl_files)),
            ('android_release', ftl('firefox-all-product-firefox-android', ftl_files=ftl_files)),
            ('android_beta', ftl('firefox-all-product-firefox-android-beta', ftl_files=ftl_files)),
            ('android_nightly', ftl('firefox-all-product-firefox-android-nightly', ftl_files=ftl_files)),
            ('ios_release', ftl('firefox-all-product-firefox-ios', ftl_files=ftl_files)),
        ]
    )

    channel_release = 'release'
    channel_beta = 'beta'
    channel_dev = 'devedition'
    channel_nightly = 'nightly'
    channel_esr = 'esr'
    channel_esr_next = 'esr_next'

    latest_release_version_desktop = product_desktop.latest_version(channel_release)
    latest_beta_version_desktop = product_desktop.latest_version(channel_beta)
    latest_developer_version_desktop = product_desktop.latest_version(channel_dev)
    latest_nightly_version_desktop = product_desktop.latest_version(channel_nightly)
    latest_esr_version_desktop = product_desktop.latest_version(channel_esr)
    latest_esr_next_version_desktop = product_desktop.latest_version(channel_esr_next)

    latest_release_version_android = product_android.latest_version(channel_release)
    latest_beta_version_android = product_android.latest_version(channel_beta)
    latest_nightly_version_android = product_android.latest_version(channel_nightly)
    latest_release_version_ios = product_ios.latest_version(channel_release)

    lang_multi = ftl('firefox-all-lang-multi', ftl_files=ftl_files)

    context = {
        'products': products.items(),
        'desktop_release_platforms': product_desktop.platforms(channel_release),
        'desktop_release_full_builds': product_desktop.get_filtered_full_builds(
            channel_release, latest_release_version_desktop
        ),
        'desktop_release_channel_label': product_desktop.channel_labels.get(
            channel_release, 'Firefox'
        ),
        'desktop_release_latest_version': latest_release_version_desktop,
        'desktop_beta_platforms': product_desktop.platforms(channel_beta),
        'desktop_beta_full_builds': product_desktop.get_filtered_full_builds(
            channel_beta, latest_beta_version_desktop
        ),
        'desktop_beta_channel_label': product_desktop.channel_labels.get(
            channel_beta, 'Firefox'
        ),
        'desktop_beta_latest_version': latest_beta_version_desktop,
        'desktop_developer_platforms': product_desktop.platforms(channel_dev),
        'desktop_developer_full_builds': product_desktop.get_filtered_full_builds(
            channel_dev, latest_developer_version_desktop
        ),
        'desktop_developer_channel_label': product_desktop.channel_labels.get(
            channel_dev, 'Firefox'
        ),
        'desktop_developer_latest_version': latest_developer_version_desktop,
        'desktop_nightly_platforms': product_desktop.platforms(channel_nightly),
        'desktop_nightly_full_builds': product_desktop.get_filtered_full_builds(
            channel_nightly, latest_nightly_version_desktop
        ),
        'desktop_nightly_channel_label': product_desktop.channel_labels.get(
            channel_nightly, 'Firefox'
        ),
        'desktop_nightly_latest_version': latest_nightly_version_desktop,
        'desktop_esr_platforms': product_desktop.platforms(channel_esr),
        'desktop_esr_full_builds': product_desktop.get_filtered_full_builds(
            channel_esr, latest_esr_version_desktop
        ),
        'desktop_esr_channel_label': product_desktop.channel_labels.get(
            channel_esr, 'Firefox'
        ),
        'desktop_esr_latest_version': latest_esr_version_desktop,
        'android_release_platforms': [('android', 'Android')],
        'android_release_full_builds': [{
                                            'locale': 'multi',
                                            'name_en': lang_multi, 'name_native': lang_multi,
                                            'platforms': {'android': {'download_url': settings.GOOGLE_PLAY_FIREFOX_LINK_UTMS}}
                                        }],
        'android_release_channel_label': product_android.channel_labels.get(
            channel_release, 'Firefox'
        ),
        'android_release_latest_version': latest_release_version_android,
        'android_beta_platforms': [('android', 'Android')],
        'android_beta_full_builds': [{
                                        'locale': 'multi',
                                        'name_en': lang_multi, 'name_native': lang_multi,
                                        'platforms': {'android': {'download_url': settings.GOOGLE_PLAY_FIREFOX_BETA_LINK}}
                                    }],
        'android_beta_channel_label': product_android.channel_labels.get(
            channel_beta, 'Firefox'
        ),
        'android_beta_latest_version': latest_beta_version_android,
        'android_nightly_platforms': [('android', 'Android')],
        'android_nightly_full_builds': [{
                                            'locale': 'multi',
                                            'name_en': lang_multi, 'name_native': lang_multi,
                                            'platforms': {'android': {'download_url': settings.GOOGLE_PLAY_FIREFOX_NIGHTLY_LINK}}
                                        }],
        'android_nightly_channel_label': product_android.channel_labels.get(
            channel_nightly, 'Firefox'
        ),
        'android_nightly_latest_version': latest_nightly_version_android,
        'ios_release_platforms': [('ios', 'iOS')],
        'ios_release_full_builds': [{
                                        'locale': 'multi',
                                        'name_en': lang_multi, 'name_native': lang_multi,
                                        'platforms': {'ios': {'download_url': settings.APPLE_APPSTORE_FIREFOX_LINK.replace('/{country}/', '/')}}
                                    }],
        'ios_release_channel_label': product_ios.channel_labels.get(
            channel_release, 'Firefox'
        ),
        'ios_release_latest_version': latest_release_version_ios,
    }

    if latest_esr_next_version_desktop:
        context['desktop_esr_platforms_next'] = product_desktop.platforms(
            channel_esr_next, True
        )
        context[
            'desktop_esr_full_builds_next'
        ] = product_desktop.get_filtered_full_builds(
            channel_esr_next, latest_esr_next_version_desktop
        )
        context['desktop_esr_channel_label_next'] = (
            product_desktop.channel_labels.get(channel_esr_next, 'Firefox'),
        )
        context['desktop_esr_next_version'] = latest_esr_next_version_desktop

    return l10n_utils.render(request, 'firefox/all-unified.html',
                             context, ftl_files=ftl_files)
Ejemplo n.º 11
0
def newsletter_subscribe(request):
    if request.method == "POST":
        newsletters = request.POST.getlist("newsletters")
        form = NewsletterFooterForm(newsletters,
                                    l10n_utils.get_locale(request),
                                    request.POST)
        errors = []
        if form.is_valid():
            data = form.cleaned_data

            kwargs = {"format": data["fmt"]}
            # add optional data
            kwargs.update({
                k: data[k]
                for k in [
                    "country",
                    "lang",
                    "source_url",
                    "first_name",
                    "last_name",
                ] if data[k]
            })

            # NOTE this is not a typo; Referrer is misspelled in the HTTP spec
            # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36
            if not kwargs.get("source_url") and request.headers.get("Referer"):
                kwargs["source_url"] = request.headers["Referer"]

            # Convert data["newsletters"] to a comma separated string.
            newsletters = data["newsletters"]
            if isinstance(newsletters, list):
                newsletters = ",".join(newsletters)

            try:
                basket.subscribe(data["email"], newsletters, **kwargs)
            except basket.BasketException as e:
                if e.code == basket.errors.BASKET_INVALID_EMAIL:
                    errors.append(str(invalid_email_address))
                else:
                    log.exception(
                        f"Error subscribing {data['email']} to newsletter(s) {newsletters}"
                    )
                    errors.append(str(general_error))

        else:
            if "email" in form.errors:
                errors.append(ftl("newsletter-form-please-enter-a-valid"))
            if "privacy" in form.errors:
                errors.append(ftl("newsletter-form-you-must-agree-to"))
            for fieldname in ("newsletters", "fmt", "lang", "country"):
                if fieldname in form.errors:
                    errors.extend(form.errors[fieldname])

        # form error messages may contain unsanitized user input
        errors = [escape(e) for e in errors]

        if request.headers.get("x-requested-with") == "XMLHttpRequest":
            # return JSON
            if errors:
                resp = {
                    "success": False,
                    "errors": errors,
                }
            else:
                resp = {"success": True}

            return JsonResponse(resp)
        else:
            ctx = {"newsletter_form": form}
            if not errors:
                ctx["success"] = True

            return l10n_utils.render(request,
                                     "newsletter/index.html",
                                     ctx,
                                     ftl_files=FTL_FILES)

    return l10n_utils.render(request,
                             "newsletter/index.html",
                             ftl_files=FTL_FILES)
Ejemplo n.º 12
0
def newsletter_subscribe(request):
    if request.method == 'POST':
        newsletters = request.POST.get('newsletters', None)
        form = NewsletterFooterForm(newsletters,
                                    l10n_utils.get_locale(request),
                                    request.POST)
        errors = []
        if form.is_valid():
            data = form.cleaned_data

            kwargs = {'format': data['fmt']}
            # add optional data
            kwargs.update(
                dict((k, data[k]) for k in [
                    'country',
                    'lang',
                    'source_url',
                    'first_name',
                    'last_name',
                ] if data[k]))

            # NOTE this is not a typo; Referrer is misspelled in the HTTP spec
            # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36
            if not kwargs.get('source_url') and request.META.get(
                    'HTTP_REFERER'):
                kwargs['source_url'] = request.META['HTTP_REFERER']

            try:
                basket.subscribe(data['email'], data['newsletters'], **kwargs)
            except basket.BasketException as e:
                if e.code == basket.errors.BASKET_INVALID_EMAIL:
                    errors.append(str(invalid_email_address))
                else:
                    log.exception("Error subscribing %s to newsletter %s" %
                                  (data['email'], data['newsletters']))
                    errors.append(str(general_error))

        else:
            if 'email' in form.errors:
                errors.append(ftl('newsletter-form-please-enter-a-valid'))
            if 'privacy' in form.errors:
                errors.append(ftl('newsletter-form-you-must-agree-to'))
            for fieldname in ('fmt', 'lang', 'country'):
                if fieldname in form.errors:
                    errors.extend(form.errors[fieldname])

        # form error messages may contain unsanitized user input
        errors = list(map(escape, errors))

        if request.is_ajax():
            # return JSON
            if errors:
                resp = {
                    'success': False,
                    'errors': errors,
                }
            else:
                resp = {'success': True}

            return JsonResponse(resp)
        else:
            ctx = {'newsletter_form': form}
            if not errors:
                ctx['success'] = True

            return l10n_utils.render(request,
                                     'newsletter/index.html',
                                     ctx,
                                     ftl_files=FTL_FILES)

    return l10n_utils.render(request,
                             'newsletter/index.html',
                             ftl_files=FTL_FILES)
Ejemplo n.º 13
0
def firefox_all(request):
    ftl_files = "firefox/all"
    product_android = firefox_android
    product_desktop = firefox_desktop
    product_ios = firefox_ios

    # Human-readable product labels
    products = OrderedDict(
        [
            ("desktop_release", ftl("firefox-all-product-firefox", ftl_files=ftl_files)),
            ("desktop_beta", ftl("firefox-all-product-firefox-beta", ftl_files=ftl_files)),
            ("desktop_developer", ftl("firefox-all-product-firefox-developer", ftl_files=ftl_files)),
            ("desktop_nightly", ftl("firefox-all-product-firefox-nightly", ftl_files=ftl_files)),
            ("desktop_esr", ftl("firefox-all-product-firefox-esr", ftl_files=ftl_files)),
            ("android_release", ftl("firefox-all-product-firefox-android", ftl_files=ftl_files)),
            ("android_beta", ftl("firefox-all-product-firefox-android-beta", ftl_files=ftl_files)),
            ("android_nightly", ftl("firefox-all-product-firefox-android-nightly", ftl_files=ftl_files)),
            ("ios_release", ftl("firefox-all-product-firefox-ios", ftl_files=ftl_files)),
        ]
    )

    channel_release = "release"
    channel_beta = "beta"
    channel_dev = "devedition"
    channel_nightly = "nightly"
    channel_esr = "esr"
    channel_esr_next = "esr_next"

    latest_release_version_desktop = product_desktop.latest_version(channel_release)
    latest_beta_version_desktop = product_desktop.latest_version(channel_beta)
    latest_developer_version_desktop = product_desktop.latest_version(channel_dev)
    latest_nightly_version_desktop = product_desktop.latest_version(channel_nightly)
    latest_esr_version_desktop = product_desktop.latest_version(channel_esr)
    latest_esr_next_version_desktop = product_desktop.latest_version(channel_esr_next)

    latest_release_version_android = product_android.latest_version(channel_release)
    latest_beta_version_android = product_android.latest_version(channel_beta)
    latest_nightly_version_android = product_android.latest_version(channel_nightly)
    latest_release_version_ios = product_ios.latest_version(channel_release)

    lang_multi = ftl("firefox-all-lang-multi", ftl_files=ftl_files)

    context = {
        "products": products.items(),
        "desktop_release_platforms": product_desktop.platforms(channel_release),
        "desktop_release_full_builds": product_desktop.get_filtered_full_builds(channel_release, latest_release_version_desktop),
        "desktop_release_channel_label": product_desktop.channel_labels.get(channel_release, "Firefox"),
        "desktop_release_latest_version": latest_release_version_desktop,
        "desktop_beta_platforms": product_desktop.platforms(channel_beta),
        "desktop_beta_full_builds": product_desktop.get_filtered_full_builds(channel_beta, latest_beta_version_desktop),
        "desktop_beta_channel_label": product_desktop.channel_labels.get(channel_beta, "Firefox"),
        "desktop_beta_latest_version": latest_beta_version_desktop,
        "desktop_developer_platforms": product_desktop.platforms(channel_dev),
        "desktop_developer_full_builds": product_desktop.get_filtered_full_builds(channel_dev, latest_developer_version_desktop),
        "desktop_developer_channel_label": product_desktop.channel_labels.get(channel_dev, "Firefox"),
        "desktop_developer_latest_version": latest_developer_version_desktop,
        "desktop_nightly_platforms": product_desktop.platforms(channel_nightly),
        "desktop_nightly_full_builds": product_desktop.get_filtered_full_builds(channel_nightly, latest_nightly_version_desktop),
        "desktop_nightly_channel_label": product_desktop.channel_labels.get(channel_nightly, "Firefox"),
        "desktop_nightly_latest_version": latest_nightly_version_desktop,
        "desktop_esr_platforms": product_desktop.platforms(channel_esr),
        "desktop_esr_full_builds": product_desktop.get_filtered_full_builds(channel_esr, latest_esr_version_desktop),
        "desktop_esr_channel_label": product_desktop.channel_labels.get(channel_esr, "Firefox"),
        "desktop_esr_latest_version": latest_esr_version_desktop,
        "android_release_platforms": [("android", "Android")],
        "android_release_full_builds": [
            {
                "locale": "multi",
                "name_en": lang_multi,
                "name_native": lang_multi,
                "platforms": {"android": {"download_url": settings.GOOGLE_PLAY_FIREFOX_LINK_UTMS}},
            }
        ],
        "android_release_channel_label": product_android.channel_labels.get(channel_release, "Firefox"),
        "android_release_latest_version": latest_release_version_android,
        "android_beta_platforms": [("android", "Android")],
        "android_beta_full_builds": [
            {
                "locale": "multi",
                "name_en": lang_multi,
                "name_native": lang_multi,
                "platforms": {"android": {"download_url": settings.GOOGLE_PLAY_FIREFOX_BETA_LINK}},
            }
        ],
        "android_beta_channel_label": product_android.channel_labels.get(channel_beta, "Firefox"),
        "android_beta_latest_version": latest_beta_version_android,
        "android_nightly_platforms": [("android", "Android")],
        "android_nightly_full_builds": [
            {
                "locale": "multi",
                "name_en": lang_multi,
                "name_native": lang_multi,
                "platforms": {"android": {"download_url": settings.GOOGLE_PLAY_FIREFOX_NIGHTLY_LINK}},
            }
        ],
        "android_nightly_channel_label": product_android.channel_labels.get(channel_nightly, "Firefox"),
        "android_nightly_latest_version": latest_nightly_version_android,
        "ios_release_platforms": [("ios", "iOS")],
        "ios_release_full_builds": [
            {
                "locale": "multi",
                "name_en": lang_multi,
                "name_native": lang_multi,
                "platforms": {"ios": {"download_url": settings.APPLE_APPSTORE_FIREFOX_LINK.replace("/{country}/", "/")}},
            }
        ],
        "ios_release_channel_label": product_ios.channel_labels.get(channel_release, "Firefox"),
        "ios_release_latest_version": latest_release_version_ios,
    }

    if latest_esr_next_version_desktop:
        context["desktop_esr_platforms_next"] = product_desktop.platforms(channel_esr_next, True)
        context["desktop_esr_full_builds_next"] = product_desktop.get_filtered_full_builds(channel_esr_next, latest_esr_next_version_desktop)
        context["desktop_esr_channel_label_next"] = (product_desktop.channel_labels.get(channel_esr_next, "Firefox"),)
        context["desktop_esr_next_version"] = latest_esr_next_version_desktop

    return l10n_utils.render(request, "firefox/all-unified.html", context, ftl_files=ftl_files)