Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add translation coverage row to dashboard #3129

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@
{% include "dashboard/todo_dashboard_rows/_automatically_saved_pages_row.html" %}
{% include "dashboard/todo_dashboard_rows/_drafted_pages_row.html" %}
{% endif %}
{% if perms.cms.change_page %}
{% include "dashboard/todo_dashboard_rows/number_of_missing_or_outdated_translations_row.html" %}
{% endif %}
</div>
{% endblock collapsible_box_content %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% extends "../_todo_dashboard_row.html" %}
{% load i18n %}
{% block todo_dashboard_icon %}
languages
{% endblock todo_dashboard_icon %}
{% block todo_dashboard_title_link %}
{% url 'translation_coverage' region_slug=request.region.slug %}
{% endblock todo_dashboard_title_link %}
{% block todo_dashboard_title %}
{% translate "Outdated and missing translations" %}
{% endblock todo_dashboard_title %}
{% block todo_dashboard_number %}
{% with total=number_of_missing_translations %}
{{ block.super }}
{% endwith %}
{% endblock todo_dashboard_number %}
{% block todo_dashboard_description %}
{% if number_of_missing_translations > 0 %}
{% blocktranslate trimmed %}
Your pages currently have <b>{{ number_of_missing_translations }} pages </b>that have an outdated or no translation.
In order for the users to benefit from your content you should translate them or have them translated.
{% endblocktranslate %}
{% else %}
{% blocktranslate trimmed %}
At the moment all pages have up-to-date translations. Good job!
{% endblocktranslate %}
{% endif %}
{% endblock todo_dashboard_description %}
{% block todo_dashboard_button_link %}
{% if outdated_pages %}
<a class="btn !rounded-full"
href="{% url 'translation_coverage' region_slug=request.region.slug %}">
{% translate "Go to <br> translation coverage" %}
</a>
{% else %}
<i class="w-8 h-8 text-green-500" icon-name="check-circle-2"></i>
{% endif %}
{% endblock todo_dashboard_button_link %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{% extends "../_todo_dashboard_row.html" %}
{% load i18n %}
{% block todo_dashboard_ajax_url %}
{{ translation_coverage_ajax }}
{% endblock todo_dashboard_ajax_url %}
{% block todo_dashboard_id %}
translation-coverage
{% endblock todo_dashboard_id %}
{% block todo_dashboard_icon %}
languages
{% endblock todo_dashboard_icon %}
{% block todo_dashboard_title_link %}
{% url 'translation_coverage' region_slug=request.region.slug %}
{% endblock todo_dashboard_title_link %}
{% block todo_dashboard_title %}
{% translate "Outdated and missing translations" %}
{% endblock todo_dashboard_title %}
{% block todo_dashboard_number %}
{% with total=number_of_missing_or_outdated_translations %}
{{ block.super }}
{% endwith %}
{% endblock todo_dashboard_number %}
{% block todo_dashboard_description %}
<div class="hidden todo-message">
{# djlint:off #}
{% blocktranslate trimmed %}
Your pages currently have <b></b> <b>pages</b> that have an outdated or no translation.
In order for the users to benefit from your content you should translate them or have them translated.
{% endblocktranslate %}
{# djlint:on #}
</div>
<div class="hidden success-message">
{% blocktranslate trimmed %}
At the moment all pages have up-to-date translations. Good job!
{% endblocktranslate %}
</div>
<div class="waiting-message">
{% blocktranslate trimmed %}
We are loading your outdated and missing translations in the background. Please be patient.
{% endblocktranslate %}
</div>
{% endblock todo_dashboard_description %}
{% block todo_dashboard_button_link %}
<div class="hidden todo-button">
<a class="btn !rounded-full"
href="{% url 'translation_coverage' region_slug=request.region.slug %}">
{% translate "Go to <br> translation coverage" %}
</a>
</div>
<div class="hidden success-icon">
<i class="w-8 h-8 text-green-500" icon-name="check-circle-2"></i>
</div>
{% endblock todo_dashboard_button_link %}
7 changes: 6 additions & 1 deletion integreat_cms/cms/urls/protected.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,12 @@
"broken-links/",
dashboard.DashboardView.get_broken_links_context,
name="get_broken_links_ajax",
)
),
path(
"translation-coverage/",
dashboard.DashboardView.get_translation_coverage_context,
name="get_translation_coverage_ajax",
),
]
),
),
Expand Down
32 changes: 32 additions & 0 deletions integreat_cms/cms/views/dashboard/dashboard_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
"get_broken_links_ajax",
kwargs={"region_slug": self.request.region.slug},
),
"translation_coverage_ajax": reverse(
"get_translation_coverage_ajax",
kwargs={"region_slug": self.request.region.slug},
),
}
)

Expand Down Expand Up @@ -242,3 +246,31 @@ def get_drafted_pages(
"drafted_pages": drafted_pages,
"single_drafted_page": single_drafted_page,
}

@json_response
# pylint: disable=unused-argument, disable=no-self-argument
def get_translation_coverage_context(
request: HttpRequest, region_slug: str
) -> JsonResponse:
r"""
Extend context by info on translation coverage of pages

:return: Dictionary containing the context for translation coverage of pages in a region
"""
non_archived_pages = request.region.non_archived_pages
language_count = len(request.region.languages)
possible_translations = non_archived_pages.count() * language_count

all_translations = PageTranslation.objects.filter(
page__in=non_archived_pages
).only("pk")
non_outdated_translations = sum(
1 for translation in all_translations if not translation.is_outdated
)

return JsonResponse(
data={
"number_of_missing_or_outdated_translations": possible_translations
- non_outdated_translations
}
)
66 changes: 63 additions & 3 deletions integreat_cms/locale/de/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -5718,6 +5718,32 @@ msgid "At the moment all pages are ready for machine translation. Good job!"
msgstr ""
"Aktuell sind alle Seiten bereit zur maschinellen Übersetzung. Gute Arbeit!"

#: cms/templates/dashboard/todo_dashboard_rows/_missing_translations_row.html
#: cms/templates/dashboard/todo_dashboard_rows/number_of_missing_or_outdated_translations_row.html
msgid "Outdated and missing translations"
msgstr "Veraltete und fehlende Übersetzungen"

#: cms/templates/dashboard/todo_dashboard_rows/_missing_translations_row.html
#, python-format
msgid ""
"Your pages currently have <b>%(number_of_missing_translations)s pages </"
"b>that have an outdated or no translation. In order for the users to benefit "
"from your content you should translate them or have them translated."
msgstr ""
"Ihre Inhalte haben momentan <b>%(number_of_missing_translations)s Seiten</b> "
"mit fehlender oder veralteter Übersetzung. Damit die Nutzer:innen von Ihren "
"Inhalten profitieren können, sollten Sie diese übersetzen (lassen)."

#: cms/templates/dashboard/todo_dashboard_rows/_missing_translations_row.html
#: cms/templates/dashboard/todo_dashboard_rows/number_of_missing_or_outdated_translations_row.html
msgid "At the moment all pages have up-to-date translations. Good job!"
msgstr "Aktuell haben alle Ihre Seiten aktuelle Übersetzungen. Gute Arbeit!"

#: cms/templates/dashboard/todo_dashboard_rows/_missing_translations_row.html
#: cms/templates/dashboard/todo_dashboard_rows/number_of_missing_or_outdated_translations_row.html
msgid "Go to <br> translation coverage"
msgstr "Zum Bericht"

#: cms/templates/dashboard/todo_dashboard_rows/_outdated_pages_row.html
msgid "Outdated pages"
msgstr "Veraltete Seiten"
Expand Down Expand Up @@ -5778,6 +5804,24 @@ msgstr ""
msgid "At the moment there is no page waiting for approval. Good job!"
msgstr "Aktuell liegen keine Seiten zur Freigabe vor. Gute Arbeit!"

#: cms/templates/dashboard/todo_dashboard_rows/number_of_missing_or_outdated_translations_row.html
msgid ""
"Your pages currently have <b></b> <b>pages</b> that have an outdated or no "
"translation. In order for the users to benefit from your content you should "
"translate them or have them translated."
msgstr ""
"Ihre Inhalte haben momentan <b></b> <b>Seiten</b> mit fehlender oder "
"veralteter Übersetzung. Damit die Nutzer:innen von Ihren Inhalten "
"profitieren können, sollten Sie diese übersetzen (lassen)."

#: cms/templates/dashboard/todo_dashboard_rows/number_of_missing_or_outdated_translations_row.html
msgid ""
"We are loading your outdated and missing translations in the background. "
"Please be patient."
msgstr ""
"Wir laden im Hintergrund gerade Ihre kaputten Links. Bitte haben Sie noch "
"ein wenig Geduld."

#: cms/templates/emails/_base_email.html
#: cms/templates/emails/password_reset_email.txt
#: cms/templates/emails/welcome_email.txt
Expand Down Expand Up @@ -11285,6 +11329,25 @@ msgstr ""
#~ msgid "Contents"
#~ msgstr "Inhalte"

#~ msgid ""
#~ "We are loading your translation coverage in the background. Please be "
#~ "patient."
#~ msgstr ""
#~ "Wir laden im Hintergrund gerade Ihre veralteten und fehlenden "
#~ "Übersetzungen. Bitte haben Sie noch ein wenig Geduld."

#, python-format
#~ msgid ""
#~ "Your pages currently have "
#~ "<b>%(number_of_missing_or_outdated_translations)s pages </b>that have an "
#~ "outdated or no translation. In order for the users to benefit from your "
#~ "content you should translate them or have them translated."
#~ msgstr ""
#~ "Ihre Inhalten haben aktuell "
#~ "<b>%(number_of_missing_or_outdated_translations)s Seiten </b> mit "
#~ "fehlender oder veralteter Übersetzung. Damit die Nutzer:innen von Ihren "
#~ "Inhalten profitieren können, sollten Sie diese übersetzen (lassen)."

#~ msgid "View location"
#~ msgstr "Ort ansehen"

Expand Down Expand Up @@ -12568,9 +12631,6 @@ msgstr ""
#~ msgid "Translations missing"
#~ msgstr "Fehlende Übersetzungen"

#~ msgid "Translation Coverage"
#~ msgstr "Abdeckung der Übersetzungen"

#~ msgid "Settings for"
#~ msgstr "Einstellungen für"

Expand Down
1 change: 1 addition & 0 deletions integreat_cms/static/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import "./js/menu";

import "./js/poi-categories/poicategory-colors-icons";
import "./js/dashboard/broken-links";
import "./js/dashboard/translation-coverage";

// IE11: fetch
/* eslint-disable-next-line @typescript-eslint/no-var-requires */
Expand Down
84 changes: 84 additions & 0 deletions integreat_cms/static/src/js/dashboard/translation-coverage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { getCsrfToken } from "../utils/csrf-token";

type Content = {
number_of_missing_or_outdated_translations: number;
};

const getContent = async (url: string): Promise<Content> => {
const response = await fetch(url, {
method: "POST",
headers: {
"X-CSRFToken": getCsrfToken(),
},
});
return response.json();
};

const showAllTotalNumbers = () => {
const elements = document.querySelectorAll<HTMLElement>(".total-results");

elements.forEach((element) => {
if (!element.closest("#translation-coverage")) {
const el = element;
el.classList.remove("hidden");
}
});
};

window.addEventListener("load", async () => {
showAllTotalNumbers();

const translationCoverageElement = document.getElementById("translation-coverage");

if (!translationCoverageElement) {
return;
}

const url = translationCoverageElement.dataset.url;
const hideWaitingMessage = () => {
translationCoverageElement.querySelector(".waiting-message").classList.add("hidden");
};

const showSuccessMessage = () => {
translationCoverageElement.querySelector(".success-message").classList.remove("hidden");
};

const showSuccessIcon = () => {
translationCoverageElement.querySelector(".success-icon").classList.remove("hidden");
};

const showDescription = (affectedPageTitle: string) => {
translationCoverageElement.querySelector(".todo-message").classList.remove("hidden");
(translationCoverageElement.querySelector(".todo-message b") as HTMLElement).innerText = affectedPageTitle;
};

const showNumberOfPagesElement = () => {
translationCoverageElement.querySelector(".total-results").classList.remove("hidden");
};

const updateNumberOfPages = (numberOfPages: number) => {
(translationCoverageElement.querySelector(".total-results span") as HTMLElement).innerText =
numberOfPages.toString();
};

const showButton = () => {
translationCoverageElement.querySelector(".todo-button").classList.remove("hidden");
};

if (url) {
console.log(url);
const json = await getContent(url);
console.log(json);
hideWaitingMessage();
showNumberOfPagesElement();
if (json.number_of_missing_or_outdated_translations > 0) {
showDescription(String(json.number_of_missing_or_outdated_translations));
updateNumberOfPages(json.number_of_missing_or_outdated_translations);
showButton();
} else {
showSuccessMessage();
showSuccessIcon();
updateNumberOfPages(0);
}
}
});
Loading