MozillaFoundation / foundation.mozilla.org

Mozilla Foundation website
https://foundation.mozilla.org
Mozilla Public License 2.0
389 stars 153 forks source link

Remove `.localized` from templates #9882

Open tbrlpld opened 1 year ago

tbrlpld commented 1 year ago

Description

We are calling the .localized property on translatable objects (provided by the TranslatableMixin) in template code quite a bit:

$ ag --html "\.localized"
network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/blog_index_feature.html
14:      <a href="{% relocalized_url blog_page.localized.url %}" class="tw-group tw-block hover:tw-no-underline">
15:        <h1 class="tw-h4-heading medium:tw-h1-heading medium:tw-text-[34px] tw-mt-1 tw-mb-2 group-hover:tw-underline">{{ blog_page.localized.title}}</h1>
16:        <p class="tw-body tw-line-clamp-3 medium:tw-line-clamp-none">{{ blog_page.localized.get_meta_description }}</p>
41:        <a href="{% relocalized_url blog_page.localized.url %}">
42:          {% image blog_page.localized.specific.get_meta_image fill-1200x628 class='tw-h-full tw-w-full tw-object-contain tw-object-top' %}

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/publication_hero.html
21:            {% with parent_page=entry.localized %}

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/blog_card.html
23:  <p class="tw-body tw-line-clamp-3">{{ page.specific.localized.get_meta_description }}</p>

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/custom_hero_guts.html
10:      {% with parent_page=entry.localized %}

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/focus_area.html
11:            <a href="{{ area.page.localized.url }}" aria-label="{% blocktrans with name=area.name %}Learn more about: {{ name }}{% endblocktrans %}">{% trans "Learn more →" %}</a>

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/take_action.html
12:            {% with target=item.internal_link.localized %}

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/partner.html
14:        <a href="{{ page.partner_page.localized.url }}" class="text-white tw-cta-link font-weight-bold" id="partner-cta">

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/spotlight_posts.html
16:    {% with localized=post.blog.localized %}

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/cause_statement.html
6:        <a href="{{page.cause_statement_link_page.localized.url}}" class="tw-cta-link" id="homepage-cause-statement-cta">{{page.cause_statement_link_text}}</a>

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/news_you_can_use.html
28:      {% with first=items.first.blog.localized %}
62:      {% with localized=item.blog.localized %}

network-api/networkapi/wagtailpages/templates/wagtailpages/blog_author_detail_page.html
36:        {{ author.localized.tagline }}
39:        {{ author.localized.introduction }}

network-api/networkapi/wagtailpages/templates/wagtailpages/bannered_campaign_page.html
64:            {% with localized_signup=page.signup.localized %}

network-api/networkapi/wagtailpages/templates/wagtailpages/research_author_detail_page.html
35:        {{ author_profile.localized.tagline }}
38:        {{ author_profile.localized.introduction }}

network-api/networkapi/wagtailpages/templates/wagtailpages/fragments/generic_card.html
20:    <a href="{% relocalized_url page.localized.url %}">
21:      {% image page.localized.specific.get_meta_image fill-1200x628 %}
31:    <a href="{% relocalized_url page.localized.url %}" class="tw-group tw-block hover:tw-no-underline">
32:      <p class="tw-h4-heading d-inline-block mt-1 mb-2 group-hover:tw-underline">{{ page.localized.title }}</p>

network-api/networkapi/mozfest/templates/partials/mozfest_footer.html
11:    {% with localized_footer_signup=mozfest_footer.localized %}

network-api/networkapi/mozfest/templates/partials/signup.html
10:        {% with localized_signup=page.signup.localized %}

network-api/networkapi/templates/fragments/buyersguide/article_card_body.html
10:    <a href="{% relocalized_url page.localized.url %}" class="tw-group tw-block hover:tw-no-underline">
11:      <p class="tw-h4-heading d-inline-block tw-mb-1 medium:tw-my-0 group-hover:tw-underline">{{ page.localized.title }}</p>
12:      <p class="tw-text-xs medium:tw-text-lg tw-body tw-line-clamp-3 tw-leading-3 medium:tw-leading-6 medium:tw-mt-2 tw-mb-0">{{ page.localized.get_meta_description }}</p>

network-api/networkapi/templates/fragments/buyersguide/most_voted_rating.html
6:    <span class="people-voted {{ vote_data.label|slugify }}">{{ vote_data.localized }}</span> 

network-api/networkapi/templates/fragments/buyersguide/editorial_content_list_product_update_card.html
4:  <p class="tw-h4-heading d-inline-block tw-mb-1 medium:tw-my-0 group-hover:tw-underline">{{ update.localized.title }}</p>

network-api/networkapi/templates/fragments/buyersguide/article_card_horizontal.html
4:  <a href="{% relocalized_url page.localized.url %}" class="tw-block tw-shrink-0 tw-max-w-[256px]">
5:    {% image page.localized.get_meta_image fill-512x288 class="tw-hidden medium:tw-block tw-w-[256px] tw-aspect-video tw-object-cover" %}
6:    {% image page.localized.get_meta_image fill-160x160 class="tw-block medium:tw-hidden tw-w-[80px] tw-aspect-square tw-rounded-2xl tw-object-cover" %}

network-api/networkapi/templates/fragments/buyersguide/pni_category_nav.html
7:            <a class="multipage-link tw-block {% if show_all_reviews_as_active_category %} active {% endif %}" data-name="None" data-mobile="{% trans "All Categories" %}" href="{% relocalized_url home_page.localized.url %}">{% trans "All Reviews" %}</a>

network-api/networkapi/templates/fragments/buyersguide/article_card_vertical.html
4:  <a href="{% relocalized_url page.localized.url %}" class="tw-block tw-w-full">
9:    {% image page.localized.get_meta_image fill-768x432 class="tw-object-cover tw-w-[384px] tw-aspect-video" %}

network-api/networkapi/templates/fragments/buyersguide/no_search_results.html
12:    {% relocalized_url home_page.localized.url as home_url %}

network-api/networkapi/templates/fragments/buyersguide/item.html
64:        <input type="hidden" class="product-categories" value="{{category.localized.name}}">

network-api/networkapi/templates/pages/buyersguide/catalog.html
10:  <input type="hidden" class="category-title" value="{% if current_category %}{{current_category.localized.name}}{% else %}None{% endif %}">
11:  <input type="hidden" class="parent-title" value="{{current_category.parent.localized.name}}">
34:          href="{% if current_category.parent %}{% localizedroutablepageurl home_page 'category-view' current_category.parent.slug  %}{% elif current_category %}{% localizedroutablepageurl home_page 'category-view' current_category.slug  %}{% else %}{% relocalized_url home_page.localized.url %}{% endif %}"
39:              {{current_category.parent.localized.name}}
41:              {{current_category.localized.name}}
95:                    data-parent="{{ cat.parent.localized.name }}"
128:              {% include "fragments/buyersguide/item.html" with product=product.localized matched=matched %}
135:            {% include "fragments/buyersguide/item.html" with product=product.localized matched=matched %}

network-api/networkapi/templates/fragments/buyersguide/pni_mobile_nav.html
15:                                            {{current_category.parent.localized.name}}
17:                                            {{current_category.localized.name}}
29:                            <a class="multipage-link active" data-name="None" href="{% relocalized_url home_page.localized.url %}">{% trans "All Categories" %}</a>
31:                            <a class="multipage-link {% if not category %} active{% endif %}" data-name="None" href="{% relocalized_url home_page.localized.url %}">{% trans "All Categories" %}</a>

network-api/networkapi/templates/pages/buyersguide/product_page.html
65:                    {{category.localized.name}}
182:                {% include "fragments/buyersguide/related_product.html" with related_product=related_product_page.related_product.localized %}

I recently noticed that .localized is not a cached property. That means, that each access might trigger another database query (considering that the locale needs to be retrieved, it might be even more).

Instead of relying on the template code to pull the localized versions of content, we should make sure that the pages and view code provides the properly localized items to the templates (e.g. via get_context or other methods).

Reducing the database queries that our template code causes should improve the pages performance. When this is done in widely used fragments, it might give a performance boost to the entire site.

See also:

Acceptance criteria

It is hard to specify at this point what we exactly expect, but we should be reducing the number of locations where .localized is used in templates.

┆Issue is synchronized with this Jira Epic

mtdenton commented 1 year ago

@tbrlpld let's break this down into logically smaller tickets to tackle this work

tbrlpld commented 1 year ago

@mtdenton I have turned this into an epic. I think best way to tackle this might be to go on a file by file basis, because I don't think there is a way to address them all at once and the solutions might need to be specific based on the use case in each template.

The basic strategy (move logic to Python get_context or other method) is outlined in the epic and in each issue.

tbrlpld commented 1 year ago

It may be valuable (but not necessarily required) to tackle #8813 before, or as part of, this epic.

tbrlpld commented 1 year ago

This also feels related to #9812

simont-cr commented 9 months ago

Per @jhonatan-lopes recommendation, this issue needs to be addressed soon as it is currently a major source of performance degradation. Updated priority from P2 to P1.