kopia lustrzana https://github.com/wagtail/wagtail
Enforce the use of a single string formatting mechanism for translation source strings
Close #9377pull/9723/head
rodzic
713636a00e
commit
5c1c2c8f53
|
@ -22,6 +22,7 @@ jobs:
|
|||
- run: pipenv run flake8
|
||||
- run: pipenv run isort --check-only --diff .
|
||||
- run: pipenv run black --target-version py37 --check --diff .
|
||||
- run: pipenv run semgrep --config .semgrep.yml --error .
|
||||
- run: git ls-files '*.html' | xargs pipenv run djhtml --check
|
||||
- run: pipenv run curlylint --parse-only wagtail
|
||||
- run: pipenv run doc8 docs
|
||||
|
|
|
@ -50,3 +50,8 @@ repos:
|
|||
rev: v1.4.13
|
||||
hooks:
|
||||
- id: djhtml
|
||||
- repo: https://github.com/returntocorp/semgrep
|
||||
rev: v0.117.0
|
||||
hooks:
|
||||
- id: semgrep
|
||||
args: ['--config', '.semgrep.yml', '--error']
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
rules:
|
||||
- id: translation-no-new-style-formatting
|
||||
patterns:
|
||||
- pattern: $FUNC("$STRING_ID", ...)
|
||||
- metavariable-regex:
|
||||
metavariable: $FUNC
|
||||
regex: '_|gettext|gettext_lazy|ngettext|ngettext_lazy'
|
||||
- metavariable-regex:
|
||||
metavariable: $STRING_ID
|
||||
regex: ".*({(\\d*|[\\w_]*)}).*"
|
||||
message: |
|
||||
Do not use str.format style formatting for translations.
|
||||
Use printf style formatting with named placeholders instead.
|
||||
For example, do `_("Hello %(name)s") % {"name": "Wagtail"}`
|
||||
instead of `_("Hello {name}").format(name="Wagtail")`.
|
||||
See https://docs.wagtail.org/en/latest/contributing/translations.html#marking-strings-for-translation for more information.
|
||||
languages: [python, javascript, typescript]
|
||||
severity: ERROR
|
||||
- id: translation-no-f-strings
|
||||
patterns:
|
||||
- pattern: $FUNC(f"...", ...)
|
||||
- metavariable-regex:
|
||||
metavariable: $FUNC
|
||||
regex: '_|gettext|gettext_lazy|ngettext|ngettext_lazy'
|
||||
message: >
|
||||
Do not use formatted string literals for translations.
|
||||
Use printf style formatting with named placeholders instead.
|
||||
For example, do `_("Hello %(name)s") % {"name": "Wagtail"}`
|
||||
instead of `_(f"Hello {name}")`.
|
||||
See https://docs.wagtail.org/en/latest/contributing/translations.html#marking-strings-for-translation for more information.
|
||||
languages: [python]
|
||||
severity: ERROR
|
||||
- id: translation-no-anonymous-arguments
|
||||
patterns:
|
||||
- pattern: $FUNC("$STRING_ID", ...)
|
||||
- metavariable-regex:
|
||||
metavariable: $FUNC
|
||||
regex: '_|gettext|gettext_lazy|ngettext|ngettext_lazy'
|
||||
- metavariable-regex:
|
||||
metavariable: $STRING_ID
|
||||
regex: ".*%\\w.*"
|
||||
message: >
|
||||
Do not use anonymous placeholders for translations.
|
||||
Use printf style formatting with named placeholders instead.
|
||||
For example, do `_("Hello %(name)s") % {"name": "Wagtail"}`
|
||||
instead of `_("Hello %s") % "Wagtail"`.
|
||||
See https://docs.wagtail.org/en/latest/contributing/translations.html#marking-strings-for-translation for more information.
|
||||
languages: [python, javascript, typescript]
|
||||
severity: ERROR
|
||||
- id: translation-no-format-within-gettext-python
|
||||
patterns:
|
||||
- pattern: $FUNC("..." % ..., ...)
|
||||
- metavariable-regex:
|
||||
metavariable: $FUNC
|
||||
regex: '_|gettext|gettext_lazy|ngettext|ngettext_lazy'
|
||||
message: >
|
||||
Do not format string before translations
|
||||
or the interpolated value will be part of the key.
|
||||
Instead, interpolate after the call to gettext.
|
||||
For example, do `_("Hello %(name)s") % {"name": "Wagtail"}`
|
||||
instead of `_("Hello %(name)s" % {"name": "Wagtail"} )`.
|
||||
See https://docs.wagtail.org/en/latest/contributing/translations.html#marking-strings-for-translation for more information.
|
||||
languages: [python]
|
||||
severity: ERROR
|
||||
- id: translation-no-format-within-gettext-javascript
|
||||
patterns:
|
||||
- pattern: $FUNC("...".replace(...), ...)
|
||||
- metavariable-regex:
|
||||
metavariable: $FUNC
|
||||
regex: '_|gettext|gettext_lazy|ngettext|ngettext_lazy'
|
||||
message: >
|
||||
Do not format string before translations
|
||||
or the interpolated value will be part of the key.
|
||||
Instead, interpolate after the call to gettext.
|
||||
For example, do `_("Hello %(name)s") % {"name": "Wagtail"}`
|
||||
instead of `_("Hello %(name)s" % {"name": "Wagtail"} )`.
|
||||
See https://docs.wagtail.org/en/latest/contributing/translations.html#marking-strings-for-translation for more information.
|
||||
languages: [javascript, typescript]
|
||||
severity: ERROR
|
1
Makefile
1
Makefile
|
@ -21,6 +21,7 @@ lint-server:
|
|||
black --target-version py37 --check --diff .
|
||||
flake8
|
||||
isort --check-only --diff .
|
||||
semgrep --config .semgrep.yml --error .
|
||||
curlylint --parse-only wagtail
|
||||
git ls-files '*.html' | xargs djhtml --check
|
||||
|
||||
|
|
|
@ -36,10 +36,10 @@ const MinimapItem: React.FunctionComponent<MinimapItemProps> = ({
|
|||
const { href, label, icon, required, errorCount, level } = item;
|
||||
const hasError = errorCount > 0;
|
||||
const errorsLabel = ngettext(
|
||||
'{num} error',
|
||||
'{num} errors',
|
||||
'%(num)s error',
|
||||
'%(num)s errors',
|
||||
errorCount,
|
||||
).replace('{num}', `${errorCount}`);
|
||||
).replace('%(num)s', `${errorCount}`);
|
||||
const text = label.length > 26 ? `${label.substring(0, 26)}…` : label;
|
||||
return (
|
||||
<a
|
||||
|
|
|
@ -59,7 +59,7 @@ const PageExplorerItem: React.FunctionComponent<PageExplorerItemProps> = ({
|
|||
>
|
||||
<Icon
|
||||
name="edit"
|
||||
title={gettext("Edit '{title}'").replace('{title}', title || '')}
|
||||
title={gettext("Edit '%(title)s'").replace('%(title)s', title || '')}
|
||||
className="icon--item-action"
|
||||
/>
|
||||
</Button>
|
||||
|
@ -72,8 +72,8 @@ const PageExplorerItem: React.FunctionComponent<PageExplorerItemProps> = ({
|
|||
>
|
||||
<Icon
|
||||
name="arrow-right"
|
||||
title={gettext("View child pages of '{title}'").replace(
|
||||
'{title}',
|
||||
title={gettext("View child pages of '%(title)s'").replace(
|
||||
'%(title)s',
|
||||
title || '',
|
||||
)}
|
||||
className="icon--item-action"
|
||||
|
|
|
@ -97,8 +97,8 @@ export const SubMenuItem: React.FunctionComponent<SubMenuItemProps> = ({
|
|||
<span className="w-sr-only">
|
||||
{dismissibleCount === 1
|
||||
? gettext('(1 new item in this menu)')
|
||||
: gettext('({number} new items in this menu)').replace(
|
||||
'{number}',
|
||||
: gettext('(%(number)s new items in this menu)').replace(
|
||||
'%(number)s',
|
||||
`${dismissibleCount}`,
|
||||
)}
|
||||
</span>
|
||||
|
|
|
@ -70,10 +70,10 @@ function initErrorDetection() {
|
|||
.find('[data-tabs-errors-statement]')
|
||||
.text(
|
||||
ngettext(
|
||||
'({errorCount} error)',
|
||||
'({errorCount} errors)',
|
||||
'(%(errorCount)s error)',
|
||||
'(%(errorCount)s errors)',
|
||||
errorCount,
|
||||
).replace('{errorCount}', errorCount),
|
||||
).replace('%(errorCount)s', errorCount),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -166,12 +166,12 @@ function onSelectIndividualCheckbox(e) {
|
|||
numObjectsSelected = getStringForListing('SINGULAR');
|
||||
} else if (numCheckedObjects === checkedState.numObjects) {
|
||||
numObjectsSelected = getStringForListing('ALL').replace(
|
||||
'{0}',
|
||||
'%(objects)s',
|
||||
numCheckedObjects,
|
||||
);
|
||||
} else {
|
||||
numObjectsSelected = getStringForListing('PLURAL').replace(
|
||||
'{0}',
|
||||
'%(objects)s',
|
||||
numCheckedObjects,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -133,10 +133,11 @@ export default function initSidePanel() {
|
|||
parseInt(Math.max(minWidth, Math.min(targetWidth, maxWidth)), 10) ||
|
||||
width;
|
||||
|
||||
const valueText = ngettext('{num} pixel', '{num} pixels', newWidth).replace(
|
||||
'{num}',
|
||||
const valueText = ngettext(
|
||||
'%(num)s pixel',
|
||||
'%(num)s pixels',
|
||||
newWidth,
|
||||
);
|
||||
).replace('%(num)s', newWidth);
|
||||
|
||||
sidePanelWrapper.style.width = `${newWidth}px`;
|
||||
widthInput.value = 100 - ((newWidth - minWidth) / range) * 100;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Language
|
||||
|
||||
British English is preferred for user-facing text; this text should also be marked for translation (using the `django.utils.translation.gettext` function and `{% trans %}` template tag, for example). However, identifiers within code should use American English if the British or international spelling would conflict with built-in language keywords; for example, CSS code should consistently use the spelling `color` to avoid inconsistencies like `background-color: $colour-red`.
|
||||
British English is preferred for user-facing text; this text should also be marked for translation (using the `django.utils.translation.gettext` function and `{% translate %}` template tag, for example). However, identifiers within code should use American English if the British or international spelling would conflict with built-in language keywords; for example, CSS code should consistently use the spelling `color` to avoid inconsistencies like `background-color: $colour-red`.
|
||||
|
||||
### Latin phrases and abbreviations
|
||||
|
||||
|
|
|
@ -36,6 +36,38 @@ These new translations are imported into Wagtail for any subsequent RC and the f
|
|||
- To translate a project, select it and enter your translation in the translation panel
|
||||
- Save the translation using the translation button on the panel
|
||||
|
||||
## Marking strings for translation
|
||||
|
||||
In code, strings can be marked for translation with using Django's [translation system](django:topics/i18n/translation), using `gettext` or `gettext_lazy` in Python and `blocktranslate` and `translate` in templates.
|
||||
|
||||
In both Python and templates, make sure to always use named placeholder. In addition, in Python, only use the printf style formatting. This is to ensure compatibility with Transifex and help translators in their work.
|
||||
|
||||
For example:
|
||||
|
||||
```python
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
# Do this: printf style + named placeholders
|
||||
_("Page %(page_title)s with status %(status)s") % {"page_title": page.title, "status": page.status_string}
|
||||
|
||||
# Do not use anonymous placeholders
|
||||
_("Page %s with status %s") % (page.title, page.status_string)
|
||||
_("Page {} with status {}").format(page.title, page.status_string)
|
||||
|
||||
# Do not use positional placeholders
|
||||
_("Page {0} with status {1}").format(page.title, page.status_string)
|
||||
|
||||
# Do not use new style
|
||||
_("Page {page_title} with status {status}").format(page_title=page.title, status=page.status_string)
|
||||
|
||||
# Do not interpolate within the gettext call
|
||||
_("Page %(page_title)s with status %(status)s" % {"page_title": page.title, "status": page.status_string})
|
||||
_("Page {page_title} with status {status}".format(page_title=page.title, status=page.status_string))
|
||||
|
||||
# Do not use f-string
|
||||
_(f"Page {page.title} with status {page.status_string}")
|
||||
```
|
||||
|
||||
## Additional resources
|
||||
|
||||
- [](django:topics/i18n/translation)
|
||||
|
|
|
@ -46,4 +46,4 @@ We use [Prettier](https://prettier.io/) for formatting and [ESLint](https://esli
|
|||
|
||||
This is an area of active improvement for Wagtail, with [ongoing discussions](https://github.com/wagtail/wagtail/discussions/8017).
|
||||
|
||||
- Always use the `trimmed` attribute on `blocktrans` tags to prevent unnecessary whitespace from being added to the translation strings.
|
||||
- Always use the `trimmed` attribute on `blocktranslate` tags to prevent unnecessary whitespace from being added to the translation strings.
|
||||
|
|
|
@ -44,7 +44,7 @@ An example of a confirmation template is as follows:
|
|||
{% extends 'wagtailadmin/bulk_actions/confirmation/base.html' %}
|
||||
{% load i18n wagtailadmin_tags %}
|
||||
|
||||
{% block titletag %}{% blocktrans trimmed count counter=items|length %}Delete 1 item{% plural %}Delete {{ counter }} items{% endblocktrans %}{% endblock %}
|
||||
{% block titletag %}{% blocktranslate trimmed count counter=items|length %}Delete 1 item{% plural %}Delete {{ counter }} items{% endblocktranslate %}{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
{% trans "Delete" as del_str %}
|
||||
|
@ -66,7 +66,7 @@ An example of a confirmation template is as follows:
|
|||
|
||||
{% block items_with_no_access %}
|
||||
|
||||
{% blocktrans trimmed asvar no_access_msg count counter=items_with_no_access|length %}You don't have permission to delete this item{% plural %}You don't have permission to delete these items{% endblocktrans %}
|
||||
{% blocktranslate trimmed asvar no_access_msg count counter=items_with_no_access|length %}You don't have permission to delete this item{% plural %}You don't have permission to delete these items{% endblocktranslate %}
|
||||
{% include './list_items_with_no_access.html' with items=items_with_no_access no_access_msg=no_access_msg %}
|
||||
|
||||
{% endblock items_with_no_access %}
|
||||
|
|
1
setup.py
1
setup.py
|
@ -60,6 +60,7 @@ testing_extras = [
|
|||
"flake8-print==5.0.0",
|
||||
"doc8==0.8.1",
|
||||
"flake8-assertive==2.0.0",
|
||||
"semgrep",
|
||||
# For templates linting
|
||||
"curlylint==0.13.1",
|
||||
# For template indenting
|
||||
|
|
|
@ -122,13 +122,15 @@ class SubmitForModerationMenuItem(ActionMenuItem):
|
|||
workflow_state
|
||||
and workflow_state.status == workflow_state.STATUS_NEEDS_CHANGES
|
||||
):
|
||||
context["label"] = _("Resubmit to {}").format(
|
||||
workflow_state.current_task_state.task.name
|
||||
)
|
||||
context["label"] = _("Resubmit to %(task_name)s") % {
|
||||
"task_name": workflow_state.current_task_state.task.name
|
||||
}
|
||||
elif page:
|
||||
workflow = page.get_workflow()
|
||||
if workflow:
|
||||
context["label"] = _("Submit to {}").format(workflow.name)
|
||||
context["label"] = _("Submit to %(workflow_name)s") % {
|
||||
"workflow_name": workflow.name
|
||||
}
|
||||
return context
|
||||
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ class LoginForm(AuthenticationForm):
|
|||
|
||||
def __init__(self, request=None, *args, **kwargs):
|
||||
super().__init__(request=request, *args, **kwargs)
|
||||
self.fields["username"].widget.attrs["placeholder"] = (
|
||||
gettext_lazy("Enter your %s") % self.username_field.verbose_name
|
||||
)
|
||||
self.fields["username"].widget.attrs["placeholder"] = gettext_lazy(
|
||||
"Enter your %(username_field_name)s"
|
||||
) % {"username_field_name": self.username_field.verbose_name}
|
||||
self.fields["username"].widget.attrs["autofocus"] = ""
|
||||
|
||||
@property
|
||||
|
|
|
@ -101,9 +101,9 @@ class CopyForm(forms.Form):
|
|||
self._errors["new_slug"] = self.error_class(
|
||||
[
|
||||
_(
|
||||
'This slug is already in use within the context of its parent page "%s"'
|
||||
'This slug is already in use within the context of its parent page "%(parent_page_title)s"'
|
||||
)
|
||||
% parent_page
|
||||
% {"parent_page_title": parent_page}
|
||||
]
|
||||
)
|
||||
# The slug is no longer valid, hence remove it from cleaned_data
|
||||
|
|
|
@ -45,13 +45,11 @@ class TagField(TaggitTagField):
|
|||
value_too_long += val
|
||||
if value_too_long:
|
||||
raise ValidationError(
|
||||
_(
|
||||
"Tag(s) %(value_too_long)s are over %(max_tag_length)d characters"
|
||||
% {
|
||||
"value_too_long": value_too_long,
|
||||
"max_tag_length": max_tag_length,
|
||||
}
|
||||
)
|
||||
_("Tag(s) %(value_too_long)s are over %(max_tag_length)d characters")
|
||||
% {
|
||||
"value_too_long": value_too_long,
|
||||
"max_tag_length": max_tag_length,
|
||||
}
|
||||
)
|
||||
|
||||
if not self.free_tagging:
|
||||
|
|
|
@ -96,9 +96,10 @@ class WorkflowPageForm(forms.ModelForm):
|
|||
self.add_error(
|
||||
"page",
|
||||
ValidationError(
|
||||
_("This page already has workflow '{0}' assigned.").format(
|
||||
existing_workflow
|
||||
),
|
||||
_(
|
||||
"This page already has workflow '%(workflow_name)s' assigned."
|
||||
)
|
||||
% {"workflow_name": existing_workflow},
|
||||
code="existing_workflow",
|
||||
),
|
||||
)
|
||||
|
|
|
@ -57,38 +57,38 @@ def get_js_translation_strings():
|
|||
"BULK_ACTIONS": {
|
||||
"PAGE": {
|
||||
"SINGULAR": _("1 page selected"),
|
||||
"PLURAL": _("{0} pages selected"),
|
||||
"ALL": _("All {0} pages on this screen selected"),
|
||||
"PLURAL": _("%(objects)s pages selected"),
|
||||
"ALL": _("All %(objects)s pages on this screen selected"),
|
||||
"ALL_IN_LISTING": _("All pages in listing selected"),
|
||||
},
|
||||
"DOCUMENT": {
|
||||
"SINGULAR": _("1 document selected"),
|
||||
"PLURAL": _("{0} documents selected"),
|
||||
"ALL": _("All {0} documents on this screen selected"),
|
||||
"PLURAL": _("%(objects)s documents selected"),
|
||||
"ALL": _("All %(objects)s documents on this screen selected"),
|
||||
"ALL_IN_LISTING": _("All documents in listing selected"),
|
||||
},
|
||||
"IMAGE": {
|
||||
"SINGULAR": _("1 image selected"),
|
||||
"PLURAL": _("{0} images selected"),
|
||||
"ALL": _("All {0} images on this screen selected"),
|
||||
"PLURAL": _("%(objects)s images selected"),
|
||||
"ALL": _("All %(objects)s images on this screen selected"),
|
||||
"ALL_IN_LISTING": _("All images in listing selected"),
|
||||
},
|
||||
"USER": {
|
||||
"SINGULAR": _("1 user selected"),
|
||||
"PLURAL": _("{0} users selected"),
|
||||
"ALL": _("All {0} users on this screen selected"),
|
||||
"PLURAL": _("%(objects)s users selected"),
|
||||
"ALL": _("All %(objects)s users on this screen selected"),
|
||||
"ALL_IN_LISTING": _("All users in listing selected"),
|
||||
},
|
||||
"SNIPPET": {
|
||||
"SINGULAR": _("1 snippet selected"),
|
||||
"PLURAL": _("{0} snippets selected"),
|
||||
"ALL": _("All {0} snippets on this screen selected"),
|
||||
"PLURAL": _("%(objects)s snippets selected"),
|
||||
"ALL": _("All %(objects)s snippets on this screen selected"),
|
||||
"ALL_IN_LISTING": _("All snippets in listing selected"),
|
||||
},
|
||||
"ITEM": {
|
||||
"SINGULAR": _("1 item selected"),
|
||||
"PLURAL": _("{0} items selected"),
|
||||
"ALL": _("All {0} items on this screen selected"),
|
||||
"PLURAL": _("%(objects)s items selected"),
|
||||
"ALL": _("All %(objects)s items on this screen selected"),
|
||||
"ALL_IN_LISTING": _("All items in listing selected"),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -737,7 +737,7 @@ def timesince_last_update(
|
|||
"user_display_name": user_display_name,
|
||||
}
|
||||
else:
|
||||
return _("%(time)s") % {"time": time_str}
|
||||
return time_str
|
||||
else:
|
||||
if use_shorthand:
|
||||
# Note: Duplicate code in timesince_simple()
|
||||
|
|
|
@ -31,7 +31,7 @@ class Create(CreateView):
|
|||
permission_policy = collection_permission_policy
|
||||
form_class = CollectionForm
|
||||
page_title = gettext_lazy("Add collection")
|
||||
success_message = gettext_lazy("Collection '{0}' created.")
|
||||
success_message = gettext_lazy("Collection '%(object)s' created.")
|
||||
add_url_name = "wagtailadmin_collections:add"
|
||||
edit_url_name = "wagtailadmin_collections:edit"
|
||||
index_url_name = "wagtailadmin_collections:index"
|
||||
|
@ -58,7 +58,7 @@ class Edit(EditView):
|
|||
model = Collection
|
||||
form_class = CollectionForm
|
||||
template_name = "wagtailadmin/collections/edit.html"
|
||||
success_message = gettext_lazy("Collection '{0}' updated.")
|
||||
success_message = gettext_lazy("Collection '%(object)s' updated.")
|
||||
error_message = gettext_lazy("The collection could not be saved due to errors.")
|
||||
delete_item_label = gettext_lazy("Delete collection")
|
||||
edit_url_name = "wagtailadmin_collections:edit"
|
||||
|
@ -134,7 +134,7 @@ class Edit(EditView):
|
|||
class Delete(DeleteView):
|
||||
permission_policy = collection_permission_policy
|
||||
model = Collection
|
||||
success_message = gettext_lazy("Collection '{0}' deleted.")
|
||||
success_message = gettext_lazy("Collection '%(object)s' deleted.")
|
||||
index_url_name = "wagtailadmin_collections:index"
|
||||
delete_url_name = "wagtailadmin_collections:delete"
|
||||
page_title = gettext_lazy("Delete collection")
|
||||
|
|
|
@ -208,23 +208,23 @@ class RevisionsRevertMixin:
|
|||
|
||||
def get_success_message(self):
|
||||
message = _(
|
||||
"{model_name} '{instance}' has been replaced with version from {timestamp}."
|
||||
"%(model_name)s '%(object)s' has been replaced with version from %(timestamp)s."
|
||||
)
|
||||
if self.draftstate_enabled and self.action == "publish":
|
||||
message = _(
|
||||
"Version from {timestamp} of {model_name} '{instance}' has been published."
|
||||
"Version from %(timestamp)s of %(model_name)s '%(object)s' has been published."
|
||||
)
|
||||
|
||||
if self.object.go_live_at and self.object.go_live_at > timezone.now():
|
||||
message = _(
|
||||
"Version from {timestamp} of {model_name} '{instance}' has been scheduled for publishing."
|
||||
"Version from %(timestamp)s of %(model_name)s '%(object)s' has been scheduled for publishing."
|
||||
)
|
||||
|
||||
return message.format(
|
||||
model_name=capfirst(self.model._meta.verbose_name),
|
||||
instance=self.object,
|
||||
timestamp=self.revision.created_at.strftime("%d %b %Y %H:%M"),
|
||||
)
|
||||
return message % {
|
||||
"model_name": capfirst(self.model._meta.verbose_name),
|
||||
"object": self.object,
|
||||
"timestamp": self.revision.created_at.strftime("%d %b %Y %H:%M"),
|
||||
}
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
|
|
@ -403,12 +403,14 @@ class CreateView(
|
|||
def get_success_message(self, instance):
|
||||
if isinstance(instance, DraftStateMixin) and self.action == "publish":
|
||||
if instance.go_live_at and instance.go_live_at > timezone.now():
|
||||
return _("'{0}' created and scheduled for publishing.").format(instance)
|
||||
return _("'{0}' created and published.").format(instance)
|
||||
return _("'%(object)s' created and scheduled for publishing.") % {
|
||||
"object": instance
|
||||
}
|
||||
return _("'%(object)s' created and published.") % {"object": instance}
|
||||
|
||||
if self.success_message is None:
|
||||
return None
|
||||
return self.success_message.format(instance)
|
||||
return self.success_message % {"object": instance}
|
||||
|
||||
def get_success_buttons(self):
|
||||
return [
|
||||
|
@ -630,14 +632,14 @@ class EditView(
|
|||
def get_success_message(self):
|
||||
if self.draftstate_enabled and self.action == "publish":
|
||||
if self.object.go_live_at and self.object.go_live_at > timezone.now():
|
||||
return _("'{0}' updated and scheduled for publishing.").format(
|
||||
self.object
|
||||
)
|
||||
return _("'{0}' updated and published.").format(self.object)
|
||||
return _("'%(object)s' updated and scheduled for publishing.") % {
|
||||
"object": self.object
|
||||
}
|
||||
return _("'%(object)s' updated and published.") % {"object": self.object}
|
||||
|
||||
if self.success_message is None:
|
||||
return None
|
||||
return self.success_message.format(self.object)
|
||||
return self.success_message % {"object": self.object}
|
||||
|
||||
def get_success_buttons(self):
|
||||
return [
|
||||
|
@ -761,7 +763,7 @@ class DeleteView(
|
|||
def get_success_message(self):
|
||||
if self.success_message is None:
|
||||
return None
|
||||
return self.success_message.format(self.object)
|
||||
return self.success_message % {"object": self.object}
|
||||
|
||||
def delete_action(self):
|
||||
with transaction.atomic():
|
||||
|
@ -883,7 +885,7 @@ class UnpublishView(HookResponseMixin, TemplateView):
|
|||
index_url_name = None
|
||||
edit_url_name = None
|
||||
unpublish_url_name = None
|
||||
success_message = _("'{object_name}' unpublished.")
|
||||
success_message = _("'%(object)s' unpublished.")
|
||||
template_name = "wagtailadmin/shared/confirm_unpublish.html"
|
||||
|
||||
def setup(self, request, pk, *args, **kwargs):
|
||||
|
@ -910,7 +912,7 @@ class UnpublishView(HookResponseMixin, TemplateView):
|
|||
def get_success_message(self):
|
||||
if self.success_message is None:
|
||||
return None
|
||||
return self.success_message.format(object_name=str(self.object))
|
||||
return self.success_message % {"object": str(self.object)}
|
||||
|
||||
def get_success_buttons(self):
|
||||
if self.edit_url_name:
|
||||
|
@ -977,7 +979,9 @@ class RevisionsUnscheduleView(TemplateView):
|
|||
edit_url_name = None
|
||||
history_url_name = None
|
||||
revisions_unschedule_url_name = None
|
||||
success_message = gettext_lazy('Version {revision_id} of "{object}" unscheduled.')
|
||||
success_message = gettext_lazy(
|
||||
'Version %(revision_id)s of "%(object)s" unscheduled.'
|
||||
)
|
||||
template_name = "wagtailadmin/shared/revisions/confirm_unschedule.html"
|
||||
|
||||
def setup(self, request, pk, revision_id, *args, **kwargs):
|
||||
|
@ -1007,9 +1011,10 @@ class RevisionsUnscheduleView(TemplateView):
|
|||
def get_success_message(self):
|
||||
if self.success_message is None:
|
||||
return None
|
||||
return self.success_message.format(
|
||||
revision_id=self.revision.id, object=self.get_object_display_title()
|
||||
)
|
||||
return self.success_message % {
|
||||
"revision_id": self.revision.id,
|
||||
"object": self.get_object_display_title(),
|
||||
}
|
||||
|
||||
def get_success_buttons(self):
|
||||
return [
|
||||
|
@ -1031,9 +1036,10 @@ class RevisionsUnscheduleView(TemplateView):
|
|||
return reverse(self.history_url_name, args=(quote(self.object.pk),))
|
||||
|
||||
def get_page_subtitle(self):
|
||||
return _('revision {revision_id} of "{object}"').format(
|
||||
revision_id=self.revision.id, object=self.get_object_display_title()
|
||||
)
|
||||
return _('revision %(revision_id)s of "%(object)s"') % {
|
||||
"revision_id": self.revision.id,
|
||||
"object": self.get_object_display_title(),
|
||||
}
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
|
|
@ -30,9 +30,8 @@ def convert_alias(request, page_id):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Page '{0}' has been converted into an ordinary page.").format(
|
||||
page.get_admin_display_title()
|
||||
),
|
||||
_("Page '%(page_title)s' has been converted into an ordinary page.")
|
||||
% {"page_title": page.get_admin_display_title()},
|
||||
)
|
||||
|
||||
for fn in hooks.get_hooks("after_convert_alias_page"):
|
||||
|
|
|
@ -81,17 +81,17 @@ def copy(request, page_id):
|
|||
if form.cleaned_data.get("copy_subpages"):
|
||||
messages.success(
|
||||
request,
|
||||
_("Page '{0}' and {1} subpages copied.").format(
|
||||
page.specific_deferred.get_admin_display_title(),
|
||||
new_page.get_descendants().count(),
|
||||
),
|
||||
_("Page '%(page_title)s' and %(subpages_count)s subpages copied.")
|
||||
% {
|
||||
"page_title": page.specific_deferred.get_admin_display_title(),
|
||||
"subpages_count": new_page.get_descendants().count(),
|
||||
},
|
||||
)
|
||||
else:
|
||||
messages.success(
|
||||
request,
|
||||
_("Page '{0}' copied.").format(
|
||||
page.specific_deferred.get_admin_display_title()
|
||||
),
|
||||
_("Page '%(page_title)s' copied.")
|
||||
% {"page_title": page.specific_deferred.get_admin_display_title()},
|
||||
)
|
||||
|
||||
for fn in hooks.get_hooks("after_copy_page"):
|
||||
|
|
|
@ -179,7 +179,8 @@ class CreateView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
# Notification
|
||||
messages.success(
|
||||
self.request,
|
||||
_("Page '{0}' created.").format(self.page.get_admin_display_title()),
|
||||
_("Page '%(page_title)s' created.")
|
||||
% {"page_title": self.page.get_admin_display_title()},
|
||||
)
|
||||
|
||||
response = self.run_hook("after_create_page", self.request, self.page)
|
||||
|
@ -220,9 +221,8 @@ class CreateView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
if self.page.go_live_at and self.page.go_live_at > timezone.now():
|
||||
messages.success(
|
||||
self.request,
|
||||
_("Page '{0}' created and scheduled for publishing.").format(
|
||||
self.page.get_admin_display_title()
|
||||
),
|
||||
_("Page '%(page_title)s' created and scheduled for publishing.")
|
||||
% {"page_title": self.page.get_admin_display_title()},
|
||||
buttons=[self.get_edit_message_button()],
|
||||
)
|
||||
else:
|
||||
|
@ -232,9 +232,8 @@ class CreateView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
buttons.append(self.get_edit_message_button())
|
||||
messages.success(
|
||||
self.request,
|
||||
_("Page '{0}' created and published.").format(
|
||||
self.page.get_admin_display_title()
|
||||
),
|
||||
_("Page '%(page_title)s' created and published.")
|
||||
% {"page_title": self.page.get_admin_display_title()},
|
||||
buttons=buttons,
|
||||
)
|
||||
|
||||
|
@ -271,9 +270,8 @@ class CreateView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
|
||||
messages.success(
|
||||
self.request,
|
||||
_("Page '{0}' created and submitted for moderation.").format(
|
||||
self.page.get_admin_display_title()
|
||||
),
|
||||
_("Page '%(page_title)s' created and submitted for moderation.")
|
||||
% {"page_title": self.page.get_admin_display_title()},
|
||||
buttons=buttons,
|
||||
)
|
||||
|
||||
|
|
|
@ -67,7 +67,8 @@ def delete(request, page_id):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Page '{0}' deleted.").format(page.get_admin_display_title()),
|
||||
_("Page '%(page_title)s' deleted.")
|
||||
% {"page_title": page.get_admin_display_title()},
|
||||
)
|
||||
|
||||
for fn in hooks.get_hooks("after_delete_page"):
|
||||
|
|
|
@ -57,14 +57,19 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
|
||||
def add_save_confirmation_message(self):
|
||||
if self.is_reverting:
|
||||
message = _("Page '{0}' has been replaced with version from {1}.").format(
|
||||
self.page.get_admin_display_title(),
|
||||
self.previous_revision.created_at.strftime("%d %b %Y %H:%M"),
|
||||
)
|
||||
message = _(
|
||||
"Page '%(page_title)s' has been replaced "
|
||||
"with version from %(previous_revision_datetime)s."
|
||||
) % {
|
||||
"page_title": self.page.get_admin_display_title(),
|
||||
"previous_revision_datetime": self.previous_revision.created_at.strftime(
|
||||
"%d %b %Y %H:%M"
|
||||
),
|
||||
}
|
||||
else:
|
||||
message = _("Page '{0}' has been updated.").format(
|
||||
self.page.get_admin_display_title()
|
||||
)
|
||||
message = _("Page '%(page_title)s' has been updated.") % {
|
||||
"page_title": self.page.get_admin_display_title()
|
||||
}
|
||||
|
||||
messages.success(self.request, message)
|
||||
|
||||
|
@ -424,9 +429,9 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
return self.render_to_response(self.get_context_data())
|
||||
|
||||
def add_cancel_workflow_confirmation_message(self):
|
||||
message = _("Workflow on page '{0}' has been cancelled.").format(
|
||||
self.page.get_admin_display_title()
|
||||
)
|
||||
message = _("Workflow on page '%(page_title)s' has been cancelled.") % {
|
||||
"page_title": self.page.get_admin_display_title()
|
||||
}
|
||||
|
||||
messages.success(
|
||||
self.request,
|
||||
|
@ -578,21 +583,24 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
|
||||
if self.is_reverting:
|
||||
message = _(
|
||||
"Version from {0} of page '{1}' has been scheduled for publishing."
|
||||
).format(
|
||||
self.previous_revision.created_at.strftime("%d %b %Y %H:%M"),
|
||||
self.page.get_admin_display_title(),
|
||||
)
|
||||
"Version from %(previous_revision_datetime)s "
|
||||
"of page '%(page_title)s' has been scheduled for publishing."
|
||||
) % {
|
||||
"previous_revision_datetime": self.previous_revision.created_at.strftime(
|
||||
"%d %b %Y %H:%M"
|
||||
),
|
||||
"page_title": self.page.get_admin_display_title(),
|
||||
}
|
||||
else:
|
||||
if self.page.live:
|
||||
message = _(
|
||||
"Page '{0}' is live and this version has been scheduled for publishing."
|
||||
).format(self.page.get_admin_display_title())
|
||||
"Page '%(page_title)s' is live and this version has been scheduled for publishing."
|
||||
) % {"page_title": self.page.get_admin_display_title()}
|
||||
|
||||
else:
|
||||
message = _("Page '{0}' has been scheduled for publishing.").format(
|
||||
self.page.get_admin_display_title()
|
||||
)
|
||||
message = _(
|
||||
"Page '%(page_title)s' has been scheduled for publishing."
|
||||
) % {"page_title": self.page.get_admin_display_title()}
|
||||
|
||||
messages.success(
|
||||
self.request, message, buttons=[self.get_edit_message_button()]
|
||||
|
@ -603,15 +611,17 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
|
||||
if self.is_reverting:
|
||||
message = _(
|
||||
"Version from {0} of page '{1}' has been published."
|
||||
).format(
|
||||
self.previous_revision.created_at.strftime("%d %b %Y %H:%M"),
|
||||
self.page.get_admin_display_title(),
|
||||
)
|
||||
"Version from %(datetime)s of page '%(page_title)s' has been published."
|
||||
) % {
|
||||
"datetime": self.previous_revision.created_at.strftime(
|
||||
"%d %b %Y %H:%M"
|
||||
),
|
||||
"page_title": self.page.get_admin_display_title(),
|
||||
}
|
||||
else:
|
||||
message = _("Page '{0}' has been published.").format(
|
||||
self.page.get_admin_display_title()
|
||||
)
|
||||
message = _("Page '%(page_title)s' has been published.") % {
|
||||
"page_title": self.page.get_admin_display_title()
|
||||
}
|
||||
|
||||
buttons = []
|
||||
if self.page.url is not None:
|
||||
|
@ -653,9 +663,9 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
workflow = self.page.get_workflow()
|
||||
workflow.start(self.page, self.request.user)
|
||||
|
||||
message = _("Page '{0}' has been submitted for moderation.").format(
|
||||
self.page.get_admin_display_title()
|
||||
)
|
||||
message = _("Page '%(page_title)s' has been submitted for moderation.") % {
|
||||
"page_title": self.page.get_admin_display_title()
|
||||
}
|
||||
|
||||
messages.success(
|
||||
self.request,
|
||||
|
@ -695,9 +705,9 @@ class EditView(TemplateResponseMixin, ContextMixin, HookResponseMixin, View):
|
|||
workflow = self.page.get_workflow()
|
||||
workflow.start(self.page, self.request.user)
|
||||
|
||||
message = _("Workflow on page '{0}' has been restarted.").format(
|
||||
self.page.get_admin_display_title()
|
||||
)
|
||||
message = _("Workflow on page '%(page_title)s' has been restarted.") % {
|
||||
"page_title": self.page.get_admin_display_title()
|
||||
}
|
||||
|
||||
messages.success(
|
||||
self.request,
|
||||
|
|
|
@ -52,7 +52,8 @@ def unlock(request, page_id):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Page '{0}' is now unlocked.").format(page.get_admin_display_title()),
|
||||
_("Page '%(page_title)s' is now unlocked.")
|
||||
% {"page_title": page.get_admin_display_title()},
|
||||
extra_tags="unlock",
|
||||
)
|
||||
|
||||
|
|
|
@ -17,18 +17,19 @@ def approve_moderation(request, revision_id):
|
|||
if not revision.submitted_for_moderation:
|
||||
messages.error(
|
||||
request,
|
||||
_("The page '{0}' is not currently awaiting moderation.").format(
|
||||
revision.content_object.specific_deferred.get_admin_display_title()
|
||||
),
|
||||
_("The page '%(page_title)s' is not currently awaiting moderation.")
|
||||
% {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
},
|
||||
)
|
||||
return redirect("wagtailadmin_home")
|
||||
|
||||
if request.method == "POST":
|
||||
revision.approve_moderation(user=request.user)
|
||||
|
||||
message = _("Page '{0}' published.").format(
|
||||
revision.content_object.specific_deferred.get_admin_display_title()
|
||||
)
|
||||
message = _("Page '%(page_title)s' published.") % {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
}
|
||||
buttons = []
|
||||
if revision.content_object.url is not None:
|
||||
buttons.append(
|
||||
|
@ -58,9 +59,10 @@ def reject_moderation(request, revision_id):
|
|||
if not revision.submitted_for_moderation:
|
||||
messages.error(
|
||||
request,
|
||||
_("The page '{0}' is not currently awaiting moderation.").format(
|
||||
revision.content_object.specific_deferred.get_admin_display_title()
|
||||
),
|
||||
_("The page '%(page_title)s' is not currently awaiting moderation.")
|
||||
% {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
},
|
||||
)
|
||||
return redirect("wagtailadmin_home")
|
||||
|
||||
|
@ -69,9 +71,10 @@ def reject_moderation(request, revision_id):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Page '{0}' rejected for publication.").format(
|
||||
revision.content_object.specific_deferred.get_admin_display_title()
|
||||
),
|
||||
_("Page '%(page_title)s' rejected for publication.")
|
||||
% {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse(
|
||||
|
@ -97,9 +100,10 @@ def preview_for_moderation(request, revision_id):
|
|||
if not revision.submitted_for_moderation:
|
||||
messages.error(
|
||||
request,
|
||||
_("The page '{0}' is not currently awaiting moderation.").format(
|
||||
revision.content_object.specific_deferred.get_admin_display_title()
|
||||
),
|
||||
_("The page '%(page_title)s' is not currently awaiting moderation.")
|
||||
% {
|
||||
"page_title": revision.content_object.specific_deferred.get_admin_display_title()
|
||||
},
|
||||
)
|
||||
return redirect("wagtailadmin_home")
|
||||
|
||||
|
|
|
@ -56,8 +56,9 @@ def move_confirm(request, page_to_move_id, destination_id):
|
|||
messages.error(
|
||||
request,
|
||||
_(
|
||||
"The slug '{0}' is already in use at the selected parent page. Make sure the slug is unique and try again"
|
||||
).format(page_to_move.slug),
|
||||
"The slug '%(page_slug)s' is already in use at the selected parent page. Make sure the slug is unique and try again"
|
||||
)
|
||||
% {"page_slug": page_to_move.slug},
|
||||
)
|
||||
return redirect(
|
||||
"wagtailadmin_pages:move",
|
||||
|
@ -107,7 +108,8 @@ def move_confirm(request, page_to_move_id, destination_id):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Page '{0}' moved.").format(page_to_move.get_admin_display_title()),
|
||||
_("Page '%(page_title)s' moved.")
|
||||
% {"page_title": page_to_move.get_admin_display_title()},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse("wagtailadmin_pages:edit", args=(page_to_move.id,)),
|
||||
|
|
|
@ -16,7 +16,7 @@ class Unpublish(UnpublishView):
|
|||
index_url_name = "wagtailadmin_explore"
|
||||
edit_url_name = "wagtailadmin_pages:edit"
|
||||
unpublish_url_name = "wagtailadmin_pages:unpublish"
|
||||
success_message = _("Page '{0}' unpublished.")
|
||||
success_message = _("Page '%(page_title)s' unpublished.")
|
||||
template_name = "wagtailadmin/pages/confirm_unpublish.html"
|
||||
|
||||
def setup(self, request, page_id, *args, **kwargs):
|
||||
|
@ -36,7 +36,9 @@ class Unpublish(UnpublishView):
|
|||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_success_message(self):
|
||||
return self.success_message.format(self.object.get_admin_display_title())
|
||||
return self.success_message % {
|
||||
"page_title": self.object.get_admin_display_title()
|
||||
}
|
||||
|
||||
def get_next_url(self):
|
||||
next_url = get_valid_next_url_from_request(self.request)
|
||||
|
|
|
@ -38,9 +38,8 @@ class BaseWorkflowFormView(View):
|
|||
if not self.page.workflow_in_progress:
|
||||
messages.error(
|
||||
request,
|
||||
_("The page '{0}' is not currently awaiting moderation.").format(
|
||||
self.page.get_admin_display_title()
|
||||
),
|
||||
_("The page '%(page_title)s' is not currently awaiting moderation.")
|
||||
% {"page_title": self.page.get_admin_display_title()},
|
||||
)
|
||||
return redirect(self.redirect_to)
|
||||
|
||||
|
@ -250,8 +249,9 @@ def preview_revision_for_task(request, page_id, task_id):
|
|||
messages.error(
|
||||
request,
|
||||
_(
|
||||
"The page '{0}' is not currently awaiting moderation in task '{1}'."
|
||||
).format(page.get_admin_display_title(), task.name),
|
||||
"The page '%(page_title)s' is not currently awaiting moderation in task '%(task_name)s'."
|
||||
)
|
||||
% {"page_title": page.get_admin_display_title(), "task_name": task.name},
|
||||
)
|
||||
return redirect("wagtailadmin_home")
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ class Create(CreateView):
|
|||
model = Workflow
|
||||
page_title = _("New workflow")
|
||||
template_name = "wagtailadmin/workflows/create.html"
|
||||
success_message = _("Workflow '{0}' created.")
|
||||
success_message = _("Workflow '%(object)s' created.")
|
||||
add_url_name = "wagtailadmin_workflows:add"
|
||||
edit_url_name = "wagtailadmin_workflows:edit"
|
||||
index_url_name = "wagtailadmin_workflows:index"
|
||||
|
@ -142,7 +142,7 @@ class Edit(EditView):
|
|||
model = Workflow
|
||||
page_title = _("Editing workflow")
|
||||
template_name = "wagtailadmin/workflows/edit.html"
|
||||
success_message = _("Workflow '{0}' updated.")
|
||||
success_message = _("Workflow '%(object)s' updated.")
|
||||
add_url_name = "wagtailadmin_workflows:add"
|
||||
edit_url_name = "wagtailadmin_workflows:edit"
|
||||
delete_url_name = "wagtailadmin_workflows:disable"
|
||||
|
@ -244,7 +244,7 @@ class Disable(DeleteView):
|
|||
model = Workflow
|
||||
page_title = _("Disable workflow")
|
||||
template_name = "wagtailadmin/workflows/confirm_disable.html"
|
||||
success_message = _("Workflow '{0}' disabled.")
|
||||
success_message = _("Workflow '%(object)s' disabled.")
|
||||
add_url_name = "wagtailadmin_workflows:add"
|
||||
edit_url_name = "wagtailadmin_workflows:edit"
|
||||
delete_url_name = "wagtailadmin_workflows:disable"
|
||||
|
@ -305,7 +305,11 @@ def enable_workflow(request, pk):
|
|||
if not workflow.active:
|
||||
workflow.active = True
|
||||
workflow.save()
|
||||
messages.success(request, _("Workflow '{0}' enabled.").format(workflow.name))
|
||||
messages.success(
|
||||
request,
|
||||
_("Workflow '%(workflow_name)s' enabled.")
|
||||
% {"workflow_name": workflow.name},
|
||||
)
|
||||
|
||||
# Redirect
|
||||
redirect_to = request.POST.get("next", None)
|
||||
|
@ -334,9 +338,8 @@ def remove_workflow(request, page_pk, workflow_pk=None):
|
|||
page.workflowpage.delete()
|
||||
messages.success(
|
||||
request,
|
||||
_("Workflow removed from Page '{0}'.").format(
|
||||
page.get_admin_display_title()
|
||||
),
|
||||
_("Workflow removed from Page '%(page_title)s'.")
|
||||
% {"page_title": page.get_admin_display_title()},
|
||||
)
|
||||
|
||||
# Redirect
|
||||
|
@ -414,7 +417,7 @@ class CreateTask(CreateView):
|
|||
model = None
|
||||
page_title = _("New workflow task")
|
||||
template_name = "wagtailadmin/workflows/create_task.html"
|
||||
success_message = _("Task '{0}' created.")
|
||||
success_message = _("Task '%(object)s' created.")
|
||||
add_url_name = "wagtailadmin_workflows:add_task"
|
||||
edit_url_name = "wagtailadmin_workflows:edit_task"
|
||||
index_url_name = "wagtailadmin_workflows:task_index"
|
||||
|
@ -456,7 +459,7 @@ class EditTask(EditView):
|
|||
model = None
|
||||
page_title = _("Editing workflow task")
|
||||
template_name = "wagtailadmin/workflows/edit_task.html"
|
||||
success_message = _("Task '{0}' updated.")
|
||||
success_message = _("Task '%(object)s' updated.")
|
||||
add_url_name = "wagtailadmin_workflows:select_task_type"
|
||||
edit_url_name = "wagtailadmin_workflows:edit_task"
|
||||
delete_url_name = "wagtailadmin_workflows:disable_task"
|
||||
|
@ -510,7 +513,7 @@ class DisableTask(DeleteView):
|
|||
model = Task
|
||||
page_title = _("Disable task")
|
||||
template_name = "wagtailadmin/workflows/confirm_disable_task.html"
|
||||
success_message = _("Task '{0}' disabled.")
|
||||
success_message = _("Task '%(object)s' disabled.")
|
||||
add_url_name = "wagtailadmin_workflows:add_task"
|
||||
edit_url_name = "wagtailadmin_workflows:edit_task"
|
||||
delete_url_name = "wagtailadmin_workflows:disable_task"
|
||||
|
@ -552,7 +555,9 @@ def enable_task(request, pk):
|
|||
if not task.active:
|
||||
task.active = True
|
||||
task.save()
|
||||
messages.success(request, _("Task '{0}' enabled.").format(task.name))
|
||||
messages.success(
|
||||
request, _("Task '%(task_name)s' enabled.") % {"task_name": task.name}
|
||||
)
|
||||
|
||||
# Redirect
|
||||
redirect_to = request.POST.get("next", None)
|
||||
|
|
|
@ -976,7 +976,7 @@ def register_reports_menu():
|
|||
def register_whats_new_in_wagtail_version_menu_item():
|
||||
version = "4.1"
|
||||
return DismissibleMenuItem(
|
||||
_("What's new in Wagtail {version}").format(version=version),
|
||||
_("What's new in Wagtail %(version)s") % {"version": version},
|
||||
wagtail_feature_release_whats_new_link(),
|
||||
icon_name="help",
|
||||
order=1000,
|
||||
|
|
|
@ -175,14 +175,16 @@ class ListBlock(Block):
|
|||
if self.meta.min_num is not None and self.meta.min_num > len(value):
|
||||
non_block_errors.append(
|
||||
ValidationError(
|
||||
_("The minimum number of items is %d") % self.meta.min_num
|
||||
_("The minimum number of items is %(min_num)d")
|
||||
% {"min_num": self.meta.min_num}
|
||||
)
|
||||
)
|
||||
|
||||
if self.meta.max_num is not None and self.meta.max_num < len(value):
|
||||
non_block_errors.append(
|
||||
ValidationError(
|
||||
_("The maximum number of items is %d") % self.meta.max_num
|
||||
_("The maximum number of items is %(max_num)d")
|
||||
% {"max_num": self.meta.max_num}
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -159,7 +159,8 @@ class BaseStreamBlock(Block):
|
|||
if self.meta.min_num is not None and self.meta.min_num > len(value):
|
||||
non_block_errors.append(
|
||||
ValidationError(
|
||||
_("The minimum number of items is %d") % self.meta.min_num
|
||||
_("The minimum number of items is %(min_num)d")
|
||||
% {"min_num": self.meta.min_num}
|
||||
)
|
||||
)
|
||||
elif self.required and len(value) == 0:
|
||||
|
@ -168,7 +169,8 @@ class BaseStreamBlock(Block):
|
|||
if self.meta.max_num is not None and self.meta.max_num < len(value):
|
||||
non_block_errors.append(
|
||||
ValidationError(
|
||||
_("The maximum number of items is %d") % self.meta.max_num
|
||||
_("The maximum number of items is %(max_num)d")
|
||||
% {"max_num": self.meta.max_num}
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -187,7 +189,8 @@ class BaseStreamBlock(Block):
|
|||
ValidationError(
|
||||
"{}: {}".format(
|
||||
block.label,
|
||||
_("The minimum number of items is %d") % min_num,
|
||||
_("The minimum number of items is %(min_num)d")
|
||||
% {"min_num": min_num},
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -196,7 +199,8 @@ class BaseStreamBlock(Block):
|
|||
ValidationError(
|
||||
"{}: {}".format(
|
||||
block.label,
|
||||
_("The maximum number of items is %d") % max_num,
|
||||
_("The maximum number of items is %(max_num)d")
|
||||
% {"max_num": max_num},
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -102,15 +102,15 @@ class FormBuilder:
|
|||
"""
|
||||
|
||||
if "\n" in field.choices:
|
||||
choices = map(
|
||||
lambda x: (
|
||||
choices = (
|
||||
(
|
||||
x.strip().rstrip(",").strip(),
|
||||
x.strip().rstrip(",").strip(),
|
||||
),
|
||||
field.choices.split("\r\n"),
|
||||
)
|
||||
for x in field.choices.split("\r\n")
|
||||
)
|
||||
else:
|
||||
choices = map(lambda x: (x.strip(), x.strip()), field.choices.split(","))
|
||||
choices = ((x.strip(), x.strip()) for x in field.choices.split(","))
|
||||
|
||||
return choices
|
||||
|
||||
|
@ -201,8 +201,8 @@ class WagtailAdminFormPageForm(WagtailAdminPageForm):
|
|||
"label",
|
||||
django.forms.ValidationError(
|
||||
_(
|
||||
"There is another field with the label %s, please change one of them."
|
||||
% duplicate_form_field.instance.label
|
||||
"There is another field with the label %(label_name)s, please change one of them."
|
||||
)
|
||||
% {"label_name": duplicate_form_field.instance.label}
|
||||
),
|
||||
)
|
||||
|
|
|
@ -7,7 +7,9 @@ from wagtail.admin.panels import Panel
|
|||
class FormSubmissionsPanel(Panel):
|
||||
def on_model_bound(self):
|
||||
if not self.heading:
|
||||
self.heading = _("%s submissions") % self.model.get_verbose_name()
|
||||
self.heading = _("%(model_name)s submissions") % {
|
||||
"model_name": self.model.get_verbose_name()
|
||||
}
|
||||
|
||||
class BoundPanel(Panel.BoundPanel):
|
||||
template_name = "wagtailforms/panels/form_responses_panel.html"
|
||||
|
|
|
@ -39,9 +39,9 @@ class ButtonHelper:
|
|||
cn = self.finalise_classname(classnames, classnames_exclude)
|
||||
return {
|
||||
"url": self.url_helper.create_url,
|
||||
"label": _("Add %s") % self.verbose_name,
|
||||
"label": _("Add %(object)s") % {"object": self.verbose_name},
|
||||
"classname": cn,
|
||||
"title": _("Add a new %s") % self.verbose_name,
|
||||
"title": _("Add a new %(object)s") % {"object": self.verbose_name},
|
||||
}
|
||||
|
||||
def inspect_button(self, pk, classnames_add=None, classnames_exclude=None):
|
||||
|
@ -55,7 +55,7 @@ class ButtonHelper:
|
|||
"url": self.url_helper.get_action_url("inspect", quote(pk)),
|
||||
"label": _("Inspect"),
|
||||
"classname": cn,
|
||||
"title": _("Inspect this %s") % self.verbose_name,
|
||||
"title": _("Inspect this %(object)s") % {"object": self.verbose_name},
|
||||
}
|
||||
|
||||
def edit_button(self, pk, classnames_add=None, classnames_exclude=None):
|
||||
|
@ -69,7 +69,7 @@ class ButtonHelper:
|
|||
"url": self.url_helper.get_action_url("edit", quote(pk)),
|
||||
"label": _("Edit"),
|
||||
"classname": cn,
|
||||
"title": _("Edit this %s") % self.verbose_name,
|
||||
"title": _("Edit this %(object)s") % {"object": self.verbose_name},
|
||||
}
|
||||
|
||||
def delete_button(self, pk, classnames_add=None, classnames_exclude=None):
|
||||
|
@ -83,7 +83,7 @@ class ButtonHelper:
|
|||
"url": self.url_helper.get_action_url("delete", quote(pk)),
|
||||
"label": _("Delete"),
|
||||
"classname": cn,
|
||||
"title": _("Delete this %s") % self.verbose_name,
|
||||
"title": _("Delete this %(object)s") % {"object": self.verbose_name},
|
||||
}
|
||||
|
||||
def get_buttons_for_obj(
|
||||
|
@ -133,7 +133,7 @@ class PageButtonHelper(ButtonHelper):
|
|||
"url": self.url_helper.get_action_url("unpublish", quote(pk)),
|
||||
"label": _("Unpublish"),
|
||||
"classname": cn,
|
||||
"title": _("Unpublish this %s") % self.verbose_name,
|
||||
"title": _("Unpublish this %(object)s") % {"object": self.verbose_name},
|
||||
}
|
||||
|
||||
def copy_button(self, pk, classnames_add=None, classnames_exclude=None):
|
||||
|
@ -147,7 +147,7 @@ class PageButtonHelper(ButtonHelper):
|
|||
"url": self.url_helper.get_action_url("copy", quote(pk)),
|
||||
"label": _("Copy"),
|
||||
"classname": cn,
|
||||
"title": _("Copy this %s") % self.verbose_name,
|
||||
"title": _("Copy this %(object)s") % {"object": self.verbose_name},
|
||||
}
|
||||
|
||||
def get_buttons_for_obj(
|
||||
|
|
|
@ -246,9 +246,9 @@ class ModelFormView(WMABaseView, FormView):
|
|||
return fields
|
||||
|
||||
def get_success_message(self, instance):
|
||||
return _("%(model_name)s '%(instance)s' created.") % {
|
||||
return _("%(model_name)s '%(object)s' created.") % {
|
||||
"model_name": capfirst(self.opts.verbose_name),
|
||||
"instance": instance,
|
||||
"object": instance,
|
||||
}
|
||||
|
||||
def get_success_message_buttons(self, instance):
|
||||
|
@ -257,7 +257,9 @@ class ModelFormView(WMABaseView, FormView):
|
|||
|
||||
def get_error_message(self):
|
||||
model_name = self.verbose_name
|
||||
return _("The %s could not be created due to errors.") % model_name
|
||||
return _("The %(object)s could not be created due to errors.") % {
|
||||
"object": model_name
|
||||
}
|
||||
|
||||
def form_valid(self, form):
|
||||
self.instance = form.save()
|
||||
|
@ -799,7 +801,7 @@ class CreateView(ModelFormView):
|
|||
return response
|
||||
|
||||
def get_meta_title(self):
|
||||
return _("Create new %s") % self.verbose_name
|
||||
return _("Create new %(object)s") % {"object": self.verbose_name}
|
||||
|
||||
def get_page_subtitle(self):
|
||||
return capfirst(self.verbose_name)
|
||||
|
@ -859,12 +861,12 @@ class EditView(ModelFormView, InstanceSpecificView):
|
|||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_meta_title(self):
|
||||
return _("Editing %s") % self.verbose_name
|
||||
return _("Editing %(object)s") % {"object": self.verbose_name}
|
||||
|
||||
def get_success_message(self, instance):
|
||||
return _("%(model_name)s '%(instance)s' updated.") % {
|
||||
return _("%(model_name)s '%(object)s' updated.") % {
|
||||
"model_name": capfirst(self.verbose_name),
|
||||
"instance": instance,
|
||||
"object": instance,
|
||||
}
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
@ -889,7 +891,7 @@ class EditView(ModelFormView, InstanceSpecificView):
|
|||
|
||||
def get_error_message(self):
|
||||
name = self.verbose_name
|
||||
return _("The %s could not be saved due to errors.") % name
|
||||
return _("The %(object)s could not be saved due to errors.") % {"object": name}
|
||||
|
||||
def get_template_names(self):
|
||||
return self.model_admin.get_edit_template()
|
||||
|
@ -923,7 +925,7 @@ class ChooseParentView(WMABaseView):
|
|||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_page_title(self):
|
||||
return _("Add %s") % self.verbose_name
|
||||
return _("Add %(object)s") % {"object": self.verbose_name}
|
||||
|
||||
def get_form(self, request):
|
||||
parents = self.permission_helper.get_valid_parent_pages(request.user)
|
||||
|
@ -971,25 +973,22 @@ class DeleteView(InstanceSpecificView):
|
|||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_meta_title(self):
|
||||
return _("Confirm deletion of %s") % self.verbose_name
|
||||
return _("Confirm deletion of %(object)s") % {"object": self.verbose_name}
|
||||
|
||||
def confirmation_message(self):
|
||||
return (
|
||||
_(
|
||||
"Are you sure you want to delete this %s? If other things in your "
|
||||
"site are related to it, they may also be affected."
|
||||
)
|
||||
% self.verbose_name
|
||||
)
|
||||
return _(
|
||||
"Are you sure you want to delete this %(object)s? If other things in your "
|
||||
"site are related to it, they may also be affected."
|
||||
) % {"object": self.verbose_name}
|
||||
|
||||
def delete_instance(self):
|
||||
self.instance.delete()
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
try:
|
||||
msg = _("%(model_name)s '%(instance)s' deleted.") % {
|
||||
msg = _("%(model_name)s '%(object)s' deleted.") % {
|
||||
"model_name": self.verbose_name,
|
||||
"instance": self.instance,
|
||||
"object": self.instance,
|
||||
}
|
||||
with transaction.atomic():
|
||||
log(instance=self.instance, action="wagtail.delete")
|
||||
|
@ -1065,7 +1064,7 @@ class InspectView(InstanceSpecificView):
|
|||
)
|
||||
|
||||
def get_meta_title(self):
|
||||
return _("Inspecting %s") % self.verbose_name
|
||||
return _("Inspecting %(object)s") % {"object": self.verbose_name}
|
||||
|
||||
def get_field_label(self, field_name, field=None):
|
||||
"""Return a label to display for a field"""
|
||||
|
|
|
@ -111,7 +111,8 @@ def edit(request, redirect_id):
|
|||
log(instance=theredirect, action="wagtail.edit")
|
||||
messages.success(
|
||||
request,
|
||||
_("Redirect '{0}' updated.").format(theredirect.title),
|
||||
_("Redirect '%(redirect_title)s' updated.")
|
||||
% {"redirect_title": theredirect.title},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse("wagtailredirects:edit", args=(theredirect.id,)),
|
||||
|
@ -152,7 +153,9 @@ def delete(request, redirect_id):
|
|||
log(instance=theredirect, action="wagtail.delete")
|
||||
theredirect.delete()
|
||||
messages.success(
|
||||
request, _("Redirect '{0}' deleted.").format(theredirect.title)
|
||||
request,
|
||||
_("Redirect '%(redirect_title)s' deleted.")
|
||||
% {"redirect_title": theredirect.title},
|
||||
)
|
||||
return redirect("wagtailredirects:index")
|
||||
|
||||
|
@ -176,7 +179,8 @@ def add(request):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Redirect '{0}' added.").format(theredirect.title),
|
||||
_("Redirect '%(redirect_title)s' added.")
|
||||
% {"redirect_title": theredirect.title},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse("wagtailredirects:edit", args=(theredirect.id,)),
|
||||
|
@ -239,7 +243,9 @@ def start_import(request):
|
|||
|
||||
if extension not in supported_extensions:
|
||||
messages.error(
|
||||
request, _('File format of type "{}" is not supported').format(extension)
|
||||
request,
|
||||
_('File format of type "%(extension)s" is not supported')
|
||||
% {"extension": extension},
|
||||
)
|
||||
return redirect("wagtailredirects:start_import")
|
||||
|
||||
|
@ -253,7 +259,11 @@ def start_import(request):
|
|||
data = force_str(data, from_encoding)
|
||||
dataset = input_format.create_dataset(data)
|
||||
except UnicodeDecodeError as e:
|
||||
messages.error(request, _("Imported file has a wrong encoding: %s") % e)
|
||||
messages.error(
|
||||
request,
|
||||
_("Imported file has a wrong encoding: %(error_message)s")
|
||||
% {"error_message": e},
|
||||
)
|
||||
return redirect("wagtailredirects:start_import")
|
||||
except Exception as e: # pragma: no cover
|
||||
messages.error(
|
||||
|
|
|
@ -137,7 +137,7 @@ def add(request):
|
|||
log(search_pick, "wagtail.create")
|
||||
messages.success(
|
||||
request,
|
||||
_("Editor's picks for '{0}' created.").format(query),
|
||||
_("Editor's picks for '%(query)s' created.") % {"query": query},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse("wagtailsearchpromotions:edit", args=(query.id,)),
|
||||
|
@ -197,7 +197,7 @@ def edit(request, query_id):
|
|||
if save_searchpicks(query, new_query, searchpicks_formset):
|
||||
messages.success(
|
||||
request,
|
||||
_("Editor's picks for '{0}' updated.").format(new_query),
|
||||
_("Editor's picks for '%(query)s' updated.") % {"query": new_query},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse("wagtailsearchpromotions:edit", args=(query.id,)),
|
||||
|
|
|
@ -42,10 +42,10 @@ class SubmitTranslationForm(forms.Form):
|
|||
if descendant_count > 0:
|
||||
hide_include_subtree = False
|
||||
self.fields["include_subtree"].label = ngettext(
|
||||
"Include subtree ({} page)",
|
||||
"Include subtree ({} pages)",
|
||||
"Include subtree (%(descendant_count)s page)",
|
||||
"Include subtree (%(descendant_count)s pages)",
|
||||
descendant_count,
|
||||
).format(descendant_count)
|
||||
) % {"descendant_count": descendant_count}
|
||||
|
||||
if hide_include_subtree:
|
||||
self.fields["include_subtree"].widget = forms.HiddenInput()
|
||||
|
|
|
@ -74,8 +74,10 @@ class SubmitTranslationView(SingleObjectMixin, TemplateView):
|
|||
form.cleaned_data["locales"][0]
|
||||
)
|
||||
else:
|
||||
# Note: always plural
|
||||
locales = _("{} locales").format(len(form.cleaned_data["locales"]))
|
||||
# Translators: always plural
|
||||
locales = _("%(locales_count)s locales") % {
|
||||
"locales_count": len(form.cleaned_data["locales"])
|
||||
}
|
||||
|
||||
messages.success(self.request, self.get_success_message(locales))
|
||||
|
||||
|
@ -117,15 +119,15 @@ class SubmitPageTranslationView(SubmitTranslationView):
|
|||
|
||||
def get_success_message(self, locales):
|
||||
return _(
|
||||
"The page '{page_title}' was successfully created in {locales}"
|
||||
).format(page_title=self.object.get_admin_display_title(), locales=locales)
|
||||
"The page '%(page_title)s' was successfully created in %(locales)s"
|
||||
) % {"page_title": self.object.get_admin_display_title(), "locales": locales}
|
||||
|
||||
|
||||
class SubmitSnippetTranslationView(SubmitTranslationView):
|
||||
def get_title(self):
|
||||
return _("Translate {model_name}").format(
|
||||
model_name=self.object._meta.verbose_name
|
||||
)
|
||||
return _("Translate %(model_name)s") % {
|
||||
"model_name": self.object._meta.verbose_name
|
||||
}
|
||||
|
||||
def get_object(self):
|
||||
model = get_snippet_model_from_url_params(
|
||||
|
@ -153,8 +155,8 @@ class SubmitSnippetTranslationView(SubmitTranslationView):
|
|||
)
|
||||
|
||||
def get_success_message(self, locales):
|
||||
return _("Successfully created {locales} for {model_name} '{object}'").format(
|
||||
model_name=self.object._meta.verbose_name,
|
||||
object=str(self.object),
|
||||
locales=locales,
|
||||
)
|
||||
return _("Successfully created %(locales)s for %(model_name)s '%(object)s'") % {
|
||||
"model_name": self.object._meta.verbose_name,
|
||||
"object": str(self.object),
|
||||
"locales": locales,
|
||||
}
|
||||
|
|
|
@ -137,7 +137,8 @@ def add(request):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Document '{0}' added.").format(doc.title),
|
||||
_("Document '%(document_title)s' added.")
|
||||
% {"document_title": doc.title},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse("wagtaildocs:edit", args=(doc.id,)), _("Edit")
|
||||
|
@ -188,7 +189,8 @@ def edit(request, document_id):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Document '{0}' updated").format(doc.title),
|
||||
_("Document '%(document_title)s' updated")
|
||||
% {"document_title": doc.title},
|
||||
buttons=[messages.button(edit_url, _("Edit"))],
|
||||
)
|
||||
return redirect(redirect_url)
|
||||
|
@ -247,7 +249,10 @@ def delete(request, document_id):
|
|||
|
||||
if request.method == "POST":
|
||||
doc.delete()
|
||||
messages.success(request, _("Document '{0}' deleted.").format(doc.title))
|
||||
messages.success(
|
||||
request,
|
||||
_("Document '%(document_title)s' deleted.") % {"document_title": doc.title},
|
||||
)
|
||||
return redirect(next_url) if next_url else redirect("wagtaildocs:index")
|
||||
|
||||
return TemplateResponse(
|
||||
|
@ -279,11 +284,13 @@ def usage(request, document_id):
|
|||
for object, references in object_page:
|
||||
edit_url = url_finder.get_edit_url(object)
|
||||
if edit_url is None:
|
||||
label = _("(Private %s)") % object._meta.verbose_name
|
||||
label = _("(Private %(object)s)") % {"object": object._meta.verbose_name}
|
||||
edit_link_title = None
|
||||
else:
|
||||
label = str(object)
|
||||
edit_link_title = _("Edit this %s") % object._meta.verbose_name
|
||||
edit_link_title = _("Edit this %(object)s") % {
|
||||
"object": object._meta.verbose_name
|
||||
}
|
||||
results.append((label, edit_url, edit_link_title, references))
|
||||
|
||||
return TemplateResponse(
|
||||
|
|
|
@ -26,7 +26,7 @@ class WagtailImageField(ImageField):
|
|||
self.max_image_pixels = getattr(
|
||||
settings, "WAGTAILIMAGES_MAX_IMAGE_PIXELS", 128 * 1000000
|
||||
)
|
||||
max_upload_size_text = filesizeformat(self.max_upload_size)
|
||||
self.max_upload_size_text = filesizeformat(self.max_upload_size)
|
||||
|
||||
# Help text
|
||||
if self.max_upload_size is not None:
|
||||
|
@ -34,7 +34,7 @@ class WagtailImageField(ImageField):
|
|||
"Supported formats: %(supported_formats)s. Maximum filesize: %(max_upload_size)s."
|
||||
) % {
|
||||
"supported_formats": SUPPORTED_FORMATS_TEXT,
|
||||
"max_upload_size": max_upload_size_text,
|
||||
"max_upload_size": self.max_upload_size_text,
|
||||
}
|
||||
else:
|
||||
self.help_text = _("Supported formats: %(supported_formats)s.") % {
|
||||
|
@ -42,27 +42,27 @@ class WagtailImageField(ImageField):
|
|||
}
|
||||
|
||||
# Error messages
|
||||
self.error_messages["invalid_image_extension"] = (
|
||||
_("Not a supported image format. Supported formats: %s.")
|
||||
% SUPPORTED_FORMATS_TEXT
|
||||
)
|
||||
# Translation placeholders should all be interpolated at the same time to avoid escaping,
|
||||
# either right now if all values are known, otherwise when used.
|
||||
self.error_messages["invalid_image_extension"] = _(
|
||||
"Not a supported image format. Supported formats: %(supported_formats)s."
|
||||
) % {"supported_formats": SUPPORTED_FORMATS_TEXT}
|
||||
|
||||
self.error_messages["invalid_image_known_format"] = _(
|
||||
"Not a valid .%s image. The extension does not match the file format (%s)"
|
||||
"Not a valid .%(extension)s image. The extension does not match the file format (%(image_format)s)"
|
||||
)
|
||||
|
||||
self.error_messages["file_too_large"] = (
|
||||
_("This file is too big (%%s). Maximum filesize %s.") % max_upload_size_text
|
||||
self.error_messages["file_too_large"] = _(
|
||||
"This file is too big (%(file_size)s). Maximum filesize %(max_filesize)s."
|
||||
)
|
||||
|
||||
self.error_messages["file_too_many_pixels"] = (
|
||||
_("This file has too many pixels (%%s). Maximum pixels %s.")
|
||||
% self.max_image_pixels
|
||||
self.error_messages["file_too_many_pixels"] = _(
|
||||
"This file has too many pixels (%(num_pixels)s). Maximum pixels %(max_pixels_count)s."
|
||||
)
|
||||
|
||||
self.error_messages["file_too_large_unknown_size"] = (
|
||||
_("This file is too big. Maximum filesize %s.") % max_upload_size_text
|
||||
)
|
||||
self.error_messages["file_too_large_unknown_size"] = _(
|
||||
"This file is too big. Maximum filesize %(max_filesize)s."
|
||||
) % {"max_filesize": self.max_upload_size_text}
|
||||
|
||||
def check_image_file_format(self, f):
|
||||
# Check file extension
|
||||
|
@ -82,7 +82,7 @@ class WagtailImageField(ImageField):
|
|||
if extension != f.image.format_name:
|
||||
raise ValidationError(
|
||||
self.error_messages["invalid_image_known_format"]
|
||||
% (extension, f.image.format_name),
|
||||
% {"extension": extension, "image_format": f.image.format_name},
|
||||
code="invalid_image_known_format",
|
||||
)
|
||||
|
||||
|
@ -94,7 +94,11 @@ class WagtailImageField(ImageField):
|
|||
# Check the filesize
|
||||
if f.size > self.max_upload_size:
|
||||
raise ValidationError(
|
||||
self.error_messages["file_too_large"] % (filesizeformat(f.size),),
|
||||
self.error_messages["file_too_large"]
|
||||
% {
|
||||
"file_size": filesizeformat(f.size),
|
||||
"max_filesize": self.max_upload_size_text,
|
||||
},
|
||||
code="file_too_large",
|
||||
)
|
||||
|
||||
|
@ -110,7 +114,8 @@ class WagtailImageField(ImageField):
|
|||
|
||||
if num_pixels > self.max_image_pixels:
|
||||
raise ValidationError(
|
||||
self.error_messages["file_too_many_pixels"] % (num_pixels),
|
||||
self.error_messages["file_too_many_pixels"]
|
||||
% {"num_pixels": num_pixels, "max_pixels_count": self.max_image_pixels},
|
||||
code="file_too_many_pixels",
|
||||
)
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ def edit(request, image_id):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Image '{0}' updated.").format(image.title),
|
||||
_("Image '%(image_title)s' updated.") % {"image_title": image.title},
|
||||
buttons=[messages.button(edit_url, _("Edit again"))],
|
||||
)
|
||||
return redirect(redirect_url)
|
||||
|
@ -226,7 +226,8 @@ def edit(request, image_id):
|
|||
request,
|
||||
_(
|
||||
"The source image file could not be found. Please change the source or delete the image."
|
||||
).format(image.title),
|
||||
)
|
||||
% {"image_title": image.title},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse("wagtailimages:delete", args=(image.id,)), _("Delete")
|
||||
|
@ -349,7 +350,10 @@ def delete(request, image_id):
|
|||
|
||||
if request.method == "POST":
|
||||
image.delete()
|
||||
messages.success(request, _("Image '{0}' deleted.").format(image.title))
|
||||
messages.success(
|
||||
request,
|
||||
_("Image '%(image_title)s' deleted.") % {"image_title": image.title},
|
||||
)
|
||||
return redirect(next_url) if next_url else redirect("wagtailimages:index")
|
||||
|
||||
return TemplateResponse(
|
||||
|
@ -375,7 +379,7 @@ def add(request):
|
|||
|
||||
messages.success(
|
||||
request,
|
||||
_("Image '{0}' added.").format(image.title),
|
||||
_("Image '%(image_title)s' added.") % {"image_title": image.title},
|
||||
buttons=[
|
||||
messages.button(
|
||||
reverse("wagtailimages:edit", args=(image.id,)), _("Edit")
|
||||
|
@ -415,11 +419,13 @@ def usage(request, image_id):
|
|||
for object, references in object_page:
|
||||
edit_url = url_finder.get_edit_url(object)
|
||||
if edit_url is None:
|
||||
label = _("(Private %s)") % object._meta.verbose_name
|
||||
label = _("(Private %(object)s)") % {"object": object._meta.verbose_name}
|
||||
edit_link_title = None
|
||||
else:
|
||||
label = str(object)
|
||||
edit_link_title = _("Edit this %s") % object._meta.verbose_name
|
||||
edit_link_title = _("Edit this %(object)s") % {
|
||||
"object": object._meta.verbose_name
|
||||
}
|
||||
results.append((label, edit_url, edit_link_title, references))
|
||||
|
||||
return TemplateResponse(
|
||||
|
|
|
@ -48,12 +48,12 @@ class IndexView(generic.IndexView):
|
|||
|
||||
class CreateView(generic.CreateView):
|
||||
page_title = gettext_lazy("Add locale")
|
||||
success_message = gettext_lazy("Locale '{0}' created.")
|
||||
success_message = gettext_lazy("Locale '%(object)s' created.")
|
||||
template_name = "wagtaillocales/create.html"
|
||||
|
||||
|
||||
class EditView(generic.EditView):
|
||||
success_message = gettext_lazy("Locale '{0}' updated.")
|
||||
success_message = gettext_lazy("Locale '%(object)s' updated.")
|
||||
error_message = gettext_lazy("The locale could not be saved due to errors.")
|
||||
delete_item_label = gettext_lazy("Delete locale")
|
||||
context_object_name = "locale"
|
||||
|
@ -62,7 +62,7 @@ class EditView(generic.EditView):
|
|||
|
||||
|
||||
class DeleteView(generic.DeleteView):
|
||||
success_message = gettext_lazy("Locale '{0}' deleted.")
|
||||
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?")
|
||||
template_name = "wagtaillocales/confirm_delete.html"
|
||||
|
|
|
@ -45,29 +45,37 @@ class BasicLock(BaseLock):
|
|||
if self.page.locked_by_id == user.pk:
|
||||
if self.page.locked_at:
|
||||
return format_html(
|
||||
_("<b>Page '{}' was locked</b> by <b>you</b> on <b>{}</b>."),
|
||||
self.page.get_admin_display_title(),
|
||||
self.page.locked_at.strftime("%d %b %Y %H:%M"),
|
||||
# nosemgrep: translation-no-new-style-formatting (new-style only w/ format_html)
|
||||
_(
|
||||
"<b>Page '{page_title}' was locked</b> by <b>you</b> on <b>{datetime}</b>."
|
||||
),
|
||||
page_title=self.page.get_admin_display_title(),
|
||||
datetime=self.page.locked_at.strftime("%d %b %Y %H:%M"),
|
||||
)
|
||||
|
||||
else:
|
||||
return format_html(
|
||||
_("<b>Page '{}' is locked</b> by <b>you</b>."),
|
||||
self.page.get_admin_display_title(),
|
||||
# nosemgrep: translation-no-new-style-formatting (new-style only w/ format_html)
|
||||
_("<b>Page '{page_title}' is locked</b> by <b>you</b>."),
|
||||
page_title=self.page.get_admin_display_title(),
|
||||
)
|
||||
else:
|
||||
if self.page.locked_by and self.page.locked_at:
|
||||
return format_html(
|
||||
_("<b>Page '{}' was locked</b> by <b>{}</b> on <b>{}</b>."),
|
||||
self.page.get_admin_display_title(),
|
||||
str(self.page.locked_by),
|
||||
self.page.locked_at.strftime("%d %b %Y %H:%M"),
|
||||
# nosemgrep: translation-no-new-style-formatting (new-style only w/ format_html)
|
||||
_(
|
||||
"<b>Page '{page_title}' was locked</b> by <b>{user}</b> on <b>{datetime}</b>."
|
||||
),
|
||||
page_title=self.page.get_admin_display_title(),
|
||||
user=str(self.page.locked_by),
|
||||
datetime=self.page.locked_at.strftime("%d %b %Y %H:%M"),
|
||||
)
|
||||
else:
|
||||
# Page was probably locked with an old version of Wagtail, or a script
|
||||
return format_html(
|
||||
_("<b>Page '{}' is locked</b>."),
|
||||
self.page.get_admin_display_title(),
|
||||
# nosemgrep: translation-no-new-style-formatting (new-style only w/ format_html)
|
||||
_("<b>Page '{page_title}' is locked</b>."),
|
||||
page_title=self.page.get_admin_display_title(),
|
||||
)
|
||||
|
||||
|
||||
|
@ -92,9 +100,12 @@ class WorkflowLock(BaseLock):
|
|||
workflow_info = _("This page is currently awaiting moderation.")
|
||||
else:
|
||||
workflow_info = format_html(
|
||||
_("This page is awaiting <b>'{}'</b> in the <b>'{}'</b> workflow."),
|
||||
self.task.name,
|
||||
self.page.current_workflow_state.workflow.name,
|
||||
# nosemgrep: translation-no-new-style-formatting (new-style only w/ format_html)
|
||||
_(
|
||||
"This page is awaiting <b>'{task_name}'</b> in the <b>'{workflow_name}'</b> workflow."
|
||||
),
|
||||
task_name=self.task.name,
|
||||
workflow_name=self.page.current_workflow_state.workflow.name,
|
||||
)
|
||||
|
||||
return mark_safe(
|
||||
|
@ -122,7 +133,10 @@ class ScheduledForPublishLock(BaseLock):
|
|||
scheduled_revision = self.page.scheduled_revision
|
||||
|
||||
return format_html(
|
||||
_("Page '{}' is locked and has been scheduled to go live at {}"),
|
||||
self.page.get_admin_display_title(),
|
||||
scheduled_revision.approved_go_live_at.strftime("%d %b %Y %H:%M"),
|
||||
# nosemgrep: translation-no-new-style-formatting (new-style only w/ format_html)
|
||||
_(
|
||||
"Page '{page_title}' is locked and has been scheduled to go live at {datetime}"
|
||||
),
|
||||
page_title=self.page.get_admin_display_title(),
|
||||
datetime=scheduled_revision.approved_go_live_at.strftime("%d %b %Y %H:%M"),
|
||||
)
|
||||
|
|
|
@ -3871,9 +3871,13 @@ class WorkflowState(models.Model):
|
|||
return super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return _("Workflow '{0}' on Page '{1}': {2}").format(
|
||||
self.workflow, self.page, self.status
|
||||
)
|
||||
return _(
|
||||
"Workflow '%(workflow_name)s' on Page '%(page_title)s': %(status)s"
|
||||
) % {
|
||||
"workflow_name": self.workflow,
|
||||
"page_title": self.page,
|
||||
"status": self.status,
|
||||
}
|
||||
|
||||
def resume(self, user=None):
|
||||
"""Put a STATUS_NEEDS_CHANGES workflow state back into STATUS_IN_PROGRESS, and restart the current task"""
|
||||
|
@ -4231,9 +4235,13 @@ class TaskState(models.Model):
|
|||
self.content_type = ContentType.objects.get_for_model(self)
|
||||
|
||||
def __str__(self):
|
||||
return _("Task '{0}' on Page Revision '{1}': {2}").format(
|
||||
self.task, self.page_revision, self.status
|
||||
)
|
||||
return _(
|
||||
"Task '%(task_name)s' on Page Revision '%(revision_info)s': %(status)s"
|
||||
) % {
|
||||
"task_name": self.task,
|
||||
"revision_info": self.page_revision,
|
||||
"status": self.status,
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def specific(self):
|
||||
|
|
|
@ -201,9 +201,10 @@ class BaseLogEntry(models.Model):
|
|||
if not log_action_registry.action_exists(self.action):
|
||||
raise ValidationError(
|
||||
{
|
||||
"action": _("The log action '{}' has not been registered.").format(
|
||||
self.action
|
||||
"action": _(
|
||||
"The log action '%(action_name)s' has not been registered."
|
||||
)
|
||||
% {"action_name": self.action}
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -31,12 +31,12 @@ class IndexView(generic.IndexView):
|
|||
|
||||
class CreateView(generic.CreateView):
|
||||
page_title = _("Add site")
|
||||
success_message = _("Site '{0}' created.")
|
||||
success_message = _("Site '%(object)s' created.")
|
||||
template_name = "wagtailsites/create.html"
|
||||
|
||||
|
||||
class EditView(generic.EditView):
|
||||
success_message = _("Site '{0}' updated.")
|
||||
success_message = _("Site '%(object)s' updated.")
|
||||
error_message = _("The site could not be saved due to errors.")
|
||||
delete_item_label = _("Delete site")
|
||||
context_object_name = "site"
|
||||
|
@ -44,7 +44,7 @@ class EditView(generic.EditView):
|
|||
|
||||
|
||||
class DeleteView(generic.DeleteView):
|
||||
success_message = _("Site '{0}' deleted.")
|
||||
success_message = _("Site '%(object)s' deleted.")
|
||||
page_title = _("Delete site")
|
||||
confirmation_message = _("Are you sure you want to delete this site?")
|
||||
|
||||
|
|
|
@ -31,16 +31,16 @@ class DeleteBulkAction(SnippetBulkAction):
|
|||
|
||||
def get_success_message(self, num_parent_objects, num_child_objects):
|
||||
if num_parent_objects == 1:
|
||||
return _("%(snippet_type)s '%(instance)s' deleted.") % {
|
||||
"snippet_type": capfirst(self.model._meta.verbose_name),
|
||||
"instance": self.actionable_objects[0],
|
||||
return _("%(model_name)s '%(object)s' deleted.") % {
|
||||
"model_name": capfirst(self.model._meta.verbose_name),
|
||||
"object": self.actionable_objects[0],
|
||||
}
|
||||
else:
|
||||
return ngettext(
|
||||
"%(count)d %(snippet_type)s deleted.",
|
||||
"%(count)d %(snippet_type)s deleted.",
|
||||
"%(count)d %(model_name)s deleted.",
|
||||
"%(count)d %(model_name)s deleted.",
|
||||
num_parent_objects,
|
||||
) % {
|
||||
"snippet_type": capfirst(self.model._meta.verbose_name_plural),
|
||||
"model_name": capfirst(self.model._meta.verbose_name_plural),
|
||||
"count": num_parent_objects,
|
||||
}
|
||||
|
|
|
@ -243,17 +243,17 @@ class CreateView(generic.CreateView):
|
|||
return reverse(self.index_url_name) + urlquery
|
||||
|
||||
def get_success_message(self, instance):
|
||||
message = _("%(snippet_type)s '%(instance)s' created.")
|
||||
message = _("%(model_name)s '%(object)s' created.")
|
||||
if isinstance(instance, DraftStateMixin) and self.action == "publish":
|
||||
message = _("%(snippet_type)s '%(instance)s' created and published.")
|
||||
message = _("%(model_name)s '%(object)s' created and published.")
|
||||
if instance.go_live_at and instance.go_live_at > timezone.now():
|
||||
message = _(
|
||||
"%(snippet_type)s '%(instance)s' created and scheduled for publishing."
|
||||
"%(model_name)s '%(object)s' created and scheduled for publishing."
|
||||
)
|
||||
|
||||
return message % {
|
||||
"snippet_type": capfirst(self.model._meta.verbose_name),
|
||||
"instance": instance,
|
||||
"model_name": capfirst(self.model._meta.verbose_name),
|
||||
"object": instance,
|
||||
}
|
||||
|
||||
def get_success_buttons(self):
|
||||
|
@ -376,24 +376,24 @@ class EditView(generic.EditView):
|
|||
return reverse(self.index_url_name)
|
||||
|
||||
def get_success_message(self):
|
||||
message = _("%(snippet_type)s '%(instance)s' updated.")
|
||||
message = _("%(model_name)s '%(object)s' updated.")
|
||||
|
||||
if self.draftstate_enabled and self.action == "publish":
|
||||
message = _("%(snippet_type)s '%(instance)s' updated and published.")
|
||||
message = _("%(model_name)s '%(object)s' updated and published.")
|
||||
|
||||
if self.object.go_live_at and self.object.go_live_at > timezone.now():
|
||||
message = _(
|
||||
"%(snippet_type)s '%(instance)s' has been scheduled for publishing."
|
||||
"%(model_name)s '%(object)s' has been scheduled for publishing."
|
||||
)
|
||||
|
||||
if self.object.live:
|
||||
message = _(
|
||||
"%(snippet_type)s '%(instance)s' is live and this version has been scheduled for publishing."
|
||||
"%(model_name)s '%(object)s' is live and this version has been scheduled for publishing."
|
||||
)
|
||||
|
||||
return message % {
|
||||
"snippet_type": capfirst(self.model._meta.verbose_name),
|
||||
"instance": self.object,
|
||||
"model_name": capfirst(self.model._meta.verbose_name),
|
||||
"object": self.object,
|
||||
}
|
||||
|
||||
def get_success_buttons(self):
|
||||
|
@ -506,20 +506,20 @@ class DeleteView(generic.DeleteView):
|
|||
def get_success_message(self):
|
||||
count = len(self.objects)
|
||||
if count == 1:
|
||||
return _("%(snippet_type)s '%(instance)s' deleted.") % {
|
||||
"snippet_type": capfirst(self.model._meta.verbose_name),
|
||||
"instance": self.objects[0],
|
||||
return _("%(model_name)s '%(object)s' deleted.") % {
|
||||
"model_name": capfirst(self.model._meta.verbose_name),
|
||||
"object": self.objects[0],
|
||||
}
|
||||
|
||||
# This message is only used in plural form, but we'll define it with ngettext so that
|
||||
# languages with multiple plural forms can be handled correctly (or, at least, as
|
||||
# correctly as possible within the limitations of verbose_name_plural...)
|
||||
return ngettext(
|
||||
"%(count)d %(snippet_type)s deleted.",
|
||||
"%(count)d %(snippet_type)s deleted.",
|
||||
"%(count)d %(model_name)s deleted.",
|
||||
"%(count)d %(model_name)s deleted.",
|
||||
count,
|
||||
) % {
|
||||
"snippet_type": capfirst(self.model._meta.verbose_name_plural),
|
||||
"model_name": capfirst(self.model._meta.verbose_name_plural),
|
||||
"count": count,
|
||||
}
|
||||
|
||||
|
@ -590,11 +590,15 @@ class UsageView(generic.IndexView):
|
|||
for object, references in context.get("page_obj"):
|
||||
edit_url = url_finder.get_edit_url(object)
|
||||
if edit_url is None:
|
||||
label = _("(Private %s)") % object._meta.verbose_name
|
||||
label = _("(Private %(object)s)") % {
|
||||
"object": object._meta.verbose_name
|
||||
}
|
||||
edit_link_title = None
|
||||
else:
|
||||
label = str(object)
|
||||
edit_link_title = _("Edit this %s") % object._meta.verbose_name
|
||||
edit_link_title = _("Edit this %(object)s") % {
|
||||
"object": object._meta.verbose_name
|
||||
}
|
||||
results.append((label, edit_url, edit_link_title, references))
|
||||
|
||||
context.update(
|
||||
|
@ -729,15 +733,15 @@ class RevisionsCompareView(PermissionCheckedMixin, generic.RevisionsCompareView)
|
|||
|
||||
@property
|
||||
def edit_label(self):
|
||||
return _("Edit this {model_name}").format(
|
||||
model_name=self.model._meta.verbose_name
|
||||
)
|
||||
return _("Edit this %(model_name)s") % {
|
||||
"model_name": self.model._meta.verbose_name
|
||||
}
|
||||
|
||||
@property
|
||||
def history_label(self):
|
||||
return _("{model_name} history").format(
|
||||
model_name=self.model._meta.verbose_name
|
||||
)
|
||||
return _("%(model_name)s history") % {
|
||||
"model_name": self.model._meta.verbose_name
|
||||
}
|
||||
|
||||
|
||||
class UnpublishView(PermissionCheckedMixin, generic.UnpublishView):
|
||||
|
|
|
@ -21,9 +21,9 @@ class AdminSnippetChooser(BaseChooser):
|
|||
def __init__(self, model, **kwargs):
|
||||
self.model = model
|
||||
name = self.model._meta.verbose_name
|
||||
self.choose_one_text = _("Choose %s") % name
|
||||
self.choose_another_text = _("Choose another %s") % name
|
||||
self.link_to_chosen_text = _("Edit this %s") % name
|
||||
self.choose_one_text = _("Choose %(object)s") % {"object": name}
|
||||
self.choose_another_text = _("Choose another %(object)s") % {"object": name}
|
||||
self.link_to_chosen_text = _("Edit this %(object)s") % {"object": name}
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ class IndexView(generic.IndexView):
|
|||
|
||||
class CreateView(PermissionPanelFormsMixin, generic.CreateView):
|
||||
page_title = _("Add group")
|
||||
success_message = _("Group '{0}' created.")
|
||||
success_message = _("Group '%(object)s' created.")
|
||||
template_name = "wagtailusers/groups/create.html"
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
@ -116,7 +116,7 @@ class CreateView(PermissionPanelFormsMixin, generic.CreateView):
|
|||
|
||||
|
||||
class EditView(PermissionPanelFormsMixin, generic.EditView):
|
||||
success_message = _("Group '{0}' updated.")
|
||||
success_message = _("Group '%(object)s' updated.")
|
||||
error_message = _("The group could not be saved due to errors.")
|
||||
delete_item_label = _("Delete group")
|
||||
context_object_name = "group"
|
||||
|
@ -154,7 +154,7 @@ class EditView(PermissionPanelFormsMixin, generic.EditView):
|
|||
|
||||
|
||||
class DeleteView(generic.DeleteView):
|
||||
success_message = _("Group '{0}' deleted.")
|
||||
success_message = _("Group '%(object)s' deleted.")
|
||||
page_title = _("Delete group")
|
||||
confirmation_message = _("Are you sure you want to delete this group?")
|
||||
template_name = "wagtailusers/groups/confirm_delete.html"
|
||||
|
|
|
@ -178,12 +178,12 @@ class Edit(EditView):
|
|||
index_url_name = "wagtailusers_users:index"
|
||||
edit_url_name = "wagtailusers_users:edit"
|
||||
delete_url_name = "wagtailusers_users:delete"
|
||||
success_message = _("User '{0}' updated.")
|
||||
success_message = _("User '%(object)s' updated.")
|
||||
context_object_name = "user"
|
||||
error_message = gettext_lazy("The user could not be saved due to errors.")
|
||||
|
||||
def get_page_title(self):
|
||||
return _("Editing %s") % self.object.get_username()
|
||||
return _("Editing %(object)s") % {"object": self.object.get_username()}
|
||||
|
||||
def get_page_subtitle(self):
|
||||
return ""
|
||||
|
@ -250,7 +250,7 @@ class Delete(DeleteView):
|
|||
index_url_name = "wagtailusers_users:index"
|
||||
page_title = gettext_lazy("Delete user")
|
||||
context_object_name = "user"
|
||||
success_message = _("User '{0}' deleted.")
|
||||
success_message = _("User '%(object)s' deleted.")
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
|
|
Ładowanie…
Reference in New Issue