155 lines
4.9 KiB
Python
155 lines
4.9 KiB
Python
|
|
from typing import TYPE_CHECKING, Any, Optional
|
||
|
|
|
||
|
|
from django.core.exceptions import PermissionDenied
|
||
|
|
from django.utils.translation import gettext_lazy, ngettext_lazy
|
||
|
|
|
||
|
|
from wagtail.admin import messages
|
||
|
|
from wagtail.admin.ui.tables import Column, TitleColumn
|
||
|
|
from wagtail.admin.views import generic
|
||
|
|
from wagtail.admin.viewsets.model import ModelViewSet
|
||
|
|
from wagtail.coreutils import get_content_languages
|
||
|
|
from wagtail.models import Locale
|
||
|
|
from wagtail.permissions import locale_permission_policy
|
||
|
|
|
||
|
|
from .forms import LocaleForm
|
||
|
|
from .utils import get_locale_usage
|
||
|
|
|
||
|
|
if TYPE_CHECKING:
|
||
|
|
from django.http import HttpRequest, HttpResponseBase
|
||
|
|
|
||
|
|
|
||
|
|
class LanguageTitleColumn(TitleColumn):
|
||
|
|
cell_template_name = "wagtaillocales/_language_title_cell.html"
|
||
|
|
|
||
|
|
def get_value(self, locale):
|
||
|
|
return locale
|
||
|
|
|
||
|
|
|
||
|
|
def _can_add_locale() -> bool:
|
||
|
|
content_languages = get_content_languages().keys()
|
||
|
|
created_locales = Locale.objects.filter(language_code__in=content_languages)
|
||
|
|
return created_locales.count() < len(content_languages)
|
||
|
|
|
||
|
|
|
||
|
|
class LocaleUsageColumn(Column):
|
||
|
|
def get_value(self, locale):
|
||
|
|
num_pages, num_others = get_locale_usage(locale)
|
||
|
|
if num_others:
|
||
|
|
return gettext_lazy("%(num_pages)d pages and %(num_others)d others") % {
|
||
|
|
"num_pages": num_pages,
|
||
|
|
"num_others": num_others,
|
||
|
|
}
|
||
|
|
|
||
|
|
return ngettext_lazy("%(num_pages)d page", "%(num_pages)d pages", num_pages) % {
|
||
|
|
"num_pages": num_pages
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
class IndexView(generic.IndexView):
|
||
|
|
page_title = gettext_lazy("Locales")
|
||
|
|
add_item_label = gettext_lazy("Add a locale")
|
||
|
|
context_object_name = "locales"
|
||
|
|
queryset = Locale.all_objects.all()
|
||
|
|
default_ordering = "language_code"
|
||
|
|
|
||
|
|
columns = [
|
||
|
|
LanguageTitleColumn(
|
||
|
|
"language",
|
||
|
|
label=gettext_lazy("Language"),
|
||
|
|
sort_key="language_code",
|
||
|
|
url_name="wagtaillocales:edit",
|
||
|
|
),
|
||
|
|
LocaleUsageColumn("usage", label=gettext_lazy("Usage")),
|
||
|
|
]
|
||
|
|
|
||
|
|
def get_add_url(self) -> Optional[str]:
|
||
|
|
# Removes the "Add" button from the index view.
|
||
|
|
if not _can_add_locale():
|
||
|
|
return None
|
||
|
|
return super().get_add_url()
|
||
|
|
|
||
|
|
|
||
|
|
class CreateView(generic.CreateView):
|
||
|
|
page_title = gettext_lazy("Add locale")
|
||
|
|
success_message = gettext_lazy("Locale '%(object)s' created.")
|
||
|
|
|
||
|
|
def dispatch(
|
||
|
|
self, request: "HttpRequest", *args: Any, **kwargs: Any
|
||
|
|
) -> "HttpResponseBase":
|
||
|
|
# Only allow access to the add view if there are locales to be added.
|
||
|
|
if not _can_add_locale():
|
||
|
|
raise PermissionDenied
|
||
|
|
|
||
|
|
return super().dispatch(request, *args, **kwargs)
|
||
|
|
|
||
|
|
|
||
|
|
class EditView(generic.EditView):
|
||
|
|
success_message = gettext_lazy("Locale '%(object)s' updated.")
|
||
|
|
error_message = gettext_lazy("The locale could not be saved due to errors.")
|
||
|
|
context_object_name = "locale"
|
||
|
|
queryset = Locale.all_objects.all()
|
||
|
|
|
||
|
|
|
||
|
|
class DeleteView(generic.DeleteView):
|
||
|
|
success_message = gettext_lazy("Locale '%(object)s' deleted.")
|
||
|
|
page_title = gettext_lazy("Delete locale")
|
||
|
|
confirmation_message = gettext_lazy("Are you sure you want to delete this locale?")
|
||
|
|
queryset = Locale.all_objects.all()
|
||
|
|
|
||
|
|
def can_delete(self, locale):
|
||
|
|
if not self.queryset.exclude(pk=locale.pk).exists():
|
||
|
|
self.cannot_delete_message = gettext_lazy(
|
||
|
|
"This locale cannot be deleted because there are no other locales."
|
||
|
|
)
|
||
|
|
return False
|
||
|
|
|
||
|
|
if get_locale_usage(locale) != (0, 0):
|
||
|
|
self.cannot_delete_message = gettext_lazy(
|
||
|
|
"This locale cannot be deleted because there are pages and/or other objects using it."
|
||
|
|
)
|
||
|
|
return False
|
||
|
|
|
||
|
|
return True
|
||
|
|
|
||
|
|
def get_context_data(self, object=None):
|
||
|
|
context = super().get_context_data()
|
||
|
|
context["can_delete"] = self.can_delete(object)
|
||
|
|
return context
|
||
|
|
|
||
|
|
def form_valid(self, form):
|
||
|
|
if self.can_delete(self.get_object()):
|
||
|
|
return super().form_valid(form)
|
||
|
|
else:
|
||
|
|
messages.error(self.request, self.cannot_delete_message)
|
||
|
|
return super().get(self.request)
|
||
|
|
|
||
|
|
|
||
|
|
class LocaleViewSet(ModelViewSet):
|
||
|
|
icon = "site"
|
||
|
|
model = Locale
|
||
|
|
permission_policy = locale_permission_policy
|
||
|
|
add_to_reference_index = False
|
||
|
|
|
||
|
|
index_view_class = IndexView
|
||
|
|
add_view_class = CreateView
|
||
|
|
edit_view_class = EditView
|
||
|
|
delete_view_class = DeleteView
|
||
|
|
|
||
|
|
# It does not make sense to copy Locale objects as they only contain the
|
||
|
|
# language code and are meant to be unique.
|
||
|
|
copy_view_enabled = False
|
||
|
|
|
||
|
|
template_prefix = "wagtaillocales/"
|
||
|
|
|
||
|
|
def get_common_view_kwargs(self, **kwargs):
|
||
|
|
return super().get_common_view_kwargs(
|
||
|
|
**{
|
||
|
|
"history_url_name": None,
|
||
|
|
"usage_url_name": None,
|
||
|
|
**kwargs,
|
||
|
|
}
|
||
|
|
)
|
||
|
|
|
||
|
|
def get_form_class(self, for_update=False):
|
||
|
|
return LocaleForm
|