wagtail 7.2.1__py3-none-any.whl → 7.3rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. wagtail/__init__.py +1 -1
  2. wagtail/actions/copy_for_translation.py +4 -2
  3. wagtail/admin/action_menu.py +4 -1
  4. wagtail/admin/api/actions/convert_alias.py +2 -2
  5. wagtail/admin/api/actions/copy.py +2 -2
  6. wagtail/admin/api/actions/copy_for_translation.py +2 -2
  7. wagtail/admin/api/actions/create_alias.py +2 -2
  8. wagtail/admin/api/actions/delete.py +1 -1
  9. wagtail/admin/api/actions/move.py +1 -1
  10. wagtail/admin/api/actions/publish.py +2 -2
  11. wagtail/admin/api/actions/revert_to_page_revision.py +2 -2
  12. wagtail/admin/api/actions/unpublish.py +1 -1
  13. wagtail/admin/api/filters.py +2 -2
  14. wagtail/admin/compare.py +22 -0
  15. wagtail/admin/forms/account.py +52 -1
  16. wagtail/admin/forms/comments.py +53 -0
  17. wagtail/admin/forms/models.py +36 -0
  18. wagtail/admin/forms/pages.py +7 -0
  19. wagtail/admin/forms/workflows.py +5 -2
  20. wagtail/admin/icons.py +4 -3
  21. wagtail/admin/locale/ar/LC_MESSAGES/django.mo +0 -0
  22. wagtail/admin/locale/ar/LC_MESSAGES/django.po +35 -0
  23. wagtail/admin/locale/en/LC_MESSAGES/django.po +262 -234
  24. wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +72 -43
  25. wagtail/admin/locale/it/LC_MESSAGES/django.mo +0 -0
  26. wagtail/admin/locale/it/LC_MESSAGES/django.po +566 -6
  27. wagtail/admin/locale/it/LC_MESSAGES/djangojs.mo +0 -0
  28. wagtail/admin/locale/it/LC_MESSAGES/djangojs.po +40 -2
  29. wagtail/admin/locale/nl/LC_MESSAGES/django.mo +0 -0
  30. wagtail/admin/locale/nl/LC_MESSAGES/django.po +2 -2
  31. wagtail/admin/locale/sv/LC_MESSAGES/django.mo +0 -0
  32. wagtail/admin/locale/sv/LC_MESSAGES/django.po +330 -15
  33. wagtail/admin/locale/sv/LC_MESSAGES/djangojs.mo +0 -0
  34. wagtail/admin/locale/sv/LC_MESSAGES/djangojs.po +3 -2
  35. wagtail/admin/panels/comment_panel.py +1 -51
  36. wagtail/admin/panels/title_field_panel.py +3 -1
  37. wagtail/admin/static/wagtailadmin/css/core.css +1 -1
  38. wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
  39. wagtail/admin/static/wagtailadmin/js/comments.js +1 -1
  40. wagtail/admin/static/wagtailadmin/js/core.js +1 -1
  41. wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +1 -1
  42. wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
  43. wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
  44. wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
  45. wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
  46. wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
  47. wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +1 -1
  48. wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
  49. wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
  50. wagtail/admin/templates/wagtailadmin/base.html +1 -1
  51. wagtail/admin/templates/wagtailadmin/generic/edit_partials.html +100 -0
  52. wagtail/admin/templates/wagtailadmin/generic/form.html +26 -5
  53. wagtail/admin/templates/wagtailadmin/generic/includes/_loaded_revision_inputs.html +3 -0
  54. wagtail/admin/templates/wagtailadmin/generic/listing_results.html +1 -17
  55. wagtail/admin/templates/wagtailadmin/pages/create.html +14 -4
  56. wagtail/admin/templates/wagtailadmin/pages/edit.html +16 -3
  57. wagtail/admin/templates/wagtailadmin/pages/edit_partials.html +31 -0
  58. wagtail/admin/templates/wagtailadmin/pages/index_results.html +1 -9
  59. wagtail/admin/templates/wagtailadmin/shared/autosave/indicator.html +36 -0
  60. wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html +1 -1
  61. wagtail/admin/templates/wagtailadmin/shared/editing_sessions/list.html +2 -2
  62. wagtail/admin/templates/wagtailadmin/shared/editing_sessions/module.html +19 -3
  63. wagtail/admin/templates/wagtailadmin/shared/headers/_actions.html +5 -0
  64. wagtail/admin/templates/wagtailadmin/shared/headers/_history_icon_link.html +2 -2
  65. wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +8 -9
  66. wagtail/admin/templates/wagtailadmin/shared/listing/filter_partials.html +19 -0
  67. wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +3 -3
  68. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/side_panel.html +3 -0
  69. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/privacy.html +18 -6
  70. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/usage.html +11 -4
  71. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/workflow.html +22 -1
  72. wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +1 -0
  73. wagtail/admin/templates/wagtailadmin/shared/side_panels.html +1 -2
  74. wagtail/admin/templates/wagtailadmin/shared/unsaved_changes_warning.html +20 -20
  75. wagtail/admin/templates/wagtailadmin/userbar/base.html +2 -0
  76. wagtail/admin/templates/wagtailadmin/userbar/item_accessibility.html +1 -1
  77. wagtail/admin/templatetags/wagtailadmin_tags.py +6 -14
  78. wagtail/admin/tests/pages/test_create_page.py +298 -1
  79. wagtail/admin/tests/pages/test_custom_listing.py +48 -2
  80. wagtail/admin/tests/pages/test_edit_page.py +721 -7
  81. wagtail/admin/tests/pages/test_explorer_view.py +9 -5
  82. wagtail/admin/tests/pages/test_page_search.py +15 -0
  83. wagtail/admin/tests/pages/test_revisions.py +4 -0
  84. wagtail/admin/tests/test_account_management.py +88 -2
  85. wagtail/admin/tests/test_collections_views.py +15 -15
  86. wagtail/admin/tests/test_compare.py +34 -0
  87. wagtail/admin/tests/test_editing_sessions.py +230 -8
  88. wagtail/admin/tests/test_forms.py +192 -1
  89. wagtail/admin/tests/test_icon_sprite.py +22 -2
  90. wagtail/admin/tests/test_page_chooser.py +13 -13
  91. wagtail/admin/tests/test_reports_views.py +4 -1
  92. wagtail/admin/tests/test_userbar.py +69 -5
  93. wagtail/admin/tests/test_views_generic.py +5 -5
  94. wagtail/admin/tests/test_workflows.py +14 -12
  95. wagtail/admin/tests/viewsets/test_model_viewset.py +13 -0
  96. wagtail/admin/ui/autosave.py +5 -0
  97. wagtail/admin/ui/editing_sessions.py +3 -0
  98. wagtail/admin/ui/side_panels.py +19 -20
  99. wagtail/admin/userbar.py +48 -27
  100. wagtail/admin/views/bulk_action/dispatcher.py +2 -2
  101. wagtail/admin/views/chooser.py +6 -6
  102. wagtail/admin/views/editing_sessions.py +20 -7
  103. wagtail/admin/views/generic/__init__.py +1 -0
  104. wagtail/admin/views/generic/chooser.py +5 -5
  105. wagtail/admin/views/generic/mixins.py +143 -26
  106. wagtail/admin/views/generic/models.py +157 -27
  107. wagtail/admin/views/generic/ordering.py +1 -1
  108. wagtail/admin/views/generic/preview.py +4 -4
  109. wagtail/admin/views/home.py +3 -1
  110. wagtail/admin/views/pages/create.py +77 -29
  111. wagtail/admin/views/pages/edit.py +160 -34
  112. wagtail/admin/views/pages/preview.py +4 -4
  113. wagtail/admin/views/pages/revisions.py +3 -0
  114. wagtail/admin/views/pages/search.py +4 -4
  115. wagtail/admin/views/pages/usage.py +2 -2
  116. wagtail/admin/views/tags.py +2 -2
  117. wagtail/admin/views/workflows.py +73 -54
  118. wagtail/admin/viewsets/model.py +34 -8
  119. wagtail/admin/widgets/button.py +11 -4
  120. wagtail/admin/widgets/chooser.py +6 -4
  121. wagtail/admin/widgets/slug.py +1 -1
  122. wagtail/api/v2/filters.py +27 -21
  123. wagtail/api/v2/pagination.py +4 -4
  124. wagtail/api/v2/views.py +7 -7
  125. wagtail/blocks/list_block.py +0 -8
  126. wagtail/blocks/migrations/migrate_operation.py +8 -1
  127. wagtail/blocks/stream_block.py +2 -10
  128. wagtail/blocks/struct_block.py +192 -12
  129. wagtail/compat.py +2 -2
  130. wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +1 -1
  131. wagtail/contrib/forms/locale/it/LC_MESSAGES/django.mo +0 -0
  132. wagtail/contrib/forms/locale/it/LC_MESSAGES/django.po +40 -2
  133. wagtail/contrib/frontend_cache/backends/azure.py +6 -6
  134. wagtail/contrib/frontend_cache/backends/cloudfront.py +2 -2
  135. wagtail/contrib/frontend_cache/utils.py +1 -1
  136. wagtail/contrib/redirects/forms.py +1 -1
  137. wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +14 -14
  138. wagtail/contrib/redirects/locale/it/LC_MESSAGES/django.mo +0 -0
  139. wagtail/contrib/redirects/locale/it/LC_MESSAGES/django.po +15 -2
  140. wagtail/contrib/redirects/locale/sv/LC_MESSAGES/django.mo +0 -0
  141. wagtail/contrib/redirects/locale/sv/LC_MESSAGES/django.po +16 -3
  142. wagtail/contrib/redirects/middleware.py +11 -7
  143. wagtail/contrib/redirects/models.py +17 -1
  144. wagtail/contrib/redirects/tests/test_import_admin_views.py +3 -3
  145. wagtail/contrib/redirects/tests/test_redirects.py +56 -8
  146. wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +6 -6
  147. wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.mo +0 -0
  148. wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.po +43 -2
  149. wagtail/contrib/search_promotions/tests.py +1 -1
  150. wagtail/contrib/search_promotions/views/settings.py +24 -25
  151. wagtail/contrib/settings/jinja2tags.py +2 -2
  152. wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +2 -2
  153. wagtail/contrib/settings/locale/it/LC_MESSAGES/django.mo +0 -0
  154. wagtail/contrib/settings/locale/it/LC_MESSAGES/django.po +6 -2
  155. wagtail/contrib/settings/locale/sv/LC_MESSAGES/django.mo +0 -0
  156. wagtail/contrib/settings/locale/sv/LC_MESSAGES/django.po +3 -2
  157. wagtail/contrib/settings/tests/generic/test_admin.py +118 -2
  158. wagtail/contrib/settings/tests/site_specific/test_admin.py +78 -15
  159. wagtail/contrib/settings/tests/site_specific/test_model.py +2 -2
  160. wagtail/contrib/settings/views.py +7 -0
  161. wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +1 -1
  162. wagtail/contrib/simple_translation/locale/it/LC_MESSAGES/django.mo +0 -0
  163. wagtail/contrib/simple_translation/locale/it/LC_MESSAGES/django.po +5 -2
  164. wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +7 -7
  165. wagtail/contrib/styleguide/tests.py +2 -0
  166. wagtail/contrib/styleguide/views.py +4 -5
  167. wagtail/contrib/table_block/locale/ar/LC_MESSAGES/django.mo +0 -0
  168. wagtail/contrib/table_block/locale/ar/LC_MESSAGES/django.po +5 -1
  169. wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
  170. wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.mo +0 -0
  171. wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.po +5 -2
  172. wagtail/contrib/typed_table_block/blocks.py +37 -0
  173. wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
  174. wagtail/contrib/typed_table_block/locale/sv/LC_MESSAGES/django.mo +0 -0
  175. wagtail/contrib/typed_table_block/locale/sv/LC_MESSAGES/django.po +4 -3
  176. wagtail/contrib/typed_table_block/tests.py +108 -0
  177. wagtail/coreutils.py +4 -4
  178. wagtail/documents/__init__.py +4 -4
  179. wagtail/documents/locale/en/LC_MESSAGES/django.po +15 -15
  180. wagtail/documents/locale/it/LC_MESSAGES/django.mo +0 -0
  181. wagtail/documents/locale/it/LC_MESSAGES/django.po +32 -2
  182. wagtail/documents/locale/sv/LC_MESSAGES/django.mo +0 -0
  183. wagtail/documents/locale/sv/LC_MESSAGES/django.po +32 -4
  184. wagtail/documents/models.py +1 -1
  185. wagtail/documents/tests/test_admin_views.py +19 -4
  186. wagtail/documents/tests/test_search.py +0 -2
  187. wagtail/documents/tests/test_views.py +6 -4
  188. wagtail/documents/views/bulk_actions/add_tags.py +1 -1
  189. wagtail/embeds/finders/facebook.py +3 -3
  190. wagtail/embeds/finders/instagram.py +3 -3
  191. wagtail/embeds/finders/oembed.py +7 -2
  192. wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
  193. wagtail/embeds/oembed_providers.py +8 -0
  194. wagtail/embeds/tests/test_embeds.py +35 -0
  195. wagtail/images/__init__.py +4 -4
  196. wagtail/images/admin_urls.py +3 -3
  197. wagtail/images/blocks.py +1 -1
  198. wagtail/images/formats.py +2 -2
  199. wagtail/images/image_operations.py +2 -2
  200. wagtail/images/locale/en/LC_MESSAGES/django.po +44 -40
  201. wagtail/images/locale/it/LC_MESSAGES/django.mo +0 -0
  202. wagtail/images/locale/it/LC_MESSAGES/django.po +50 -4
  203. wagtail/images/locale/nl/LC_MESSAGES/django.mo +0 -0
  204. wagtail/images/locale/nl/LC_MESSAGES/django.po +3 -3
  205. wagtail/images/locale/sv/LC_MESSAGES/django.mo +0 -0
  206. wagtail/images/locale/sv/LC_MESSAGES/django.po +49 -6
  207. wagtail/images/models.py +11 -10
  208. wagtail/images/templates/wagtailimages/images/index_results.html +1 -1
  209. wagtail/images/templates/wagtailimages/images/url_generator.html +17 -38
  210. wagtail/images/templates/wagtailimages/images/url_generator_output.html +28 -0
  211. wagtail/images/templatetags/wagtailimages_tags.py +4 -4
  212. wagtail/images/tests/test_admin_views.py +432 -59
  213. wagtail/images/tests/test_image_operations.py +2 -2
  214. wagtail/images/tests/test_models.py +0 -2
  215. wagtail/images/views/bulk_actions/add_tags.py +1 -1
  216. wagtail/images/views/images.py +72 -39
  217. wagtail/locale/en/LC_MESSAGES/django.po +103 -105
  218. wagtail/locale/it/LC_MESSAGES/django.mo +0 -0
  219. wagtail/locale/it/LC_MESSAGES/django.po +105 -2
  220. wagtail/locale/sv/LC_MESSAGES/django.mo +0 -0
  221. wagtail/locale/sv/LC_MESSAGES/django.po +95 -12
  222. wagtail/locales/locale/en/LC_MESSAGES/django.po +1 -1
  223. wagtail/locales/locale/it/LC_MESSAGES/django.mo +0 -0
  224. wagtail/locales/locale/it/LC_MESSAGES/django.po +13 -2
  225. wagtail/locales/locale/sv/LC_MESSAGES/django.mo +0 -0
  226. wagtail/locales/locale/sv/LC_MESSAGES/django.po +4 -3
  227. wagtail/locales/tests.py +5 -5
  228. wagtail/models/i18n.py +4 -6
  229. wagtail/models/media.py +18 -0
  230. wagtail/models/pages.py +65 -11
  231. wagtail/models/reference_index.py +15 -0
  232. wagtail/models/revisions.py +40 -12
  233. wagtail/models/workflows.py +0 -3
  234. wagtail/permission_policies/base.py +2 -2
  235. wagtail/permission_policies/collections.py +2 -2
  236. wagtail/project_template/requirements.txt +2 -2
  237. wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
  238. wagtail/signal_handlers.py +1 -0
  239. wagtail/sites/locale/en/LC_MESSAGES/django.po +1 -1
  240. wagtail/sites/locale/sv/LC_MESSAGES/django.mo +0 -0
  241. wagtail/sites/locale/sv/LC_MESSAGES/django.po +3 -2
  242. wagtail/sites/tests.py +7 -7
  243. wagtail/snippets/action_menu.py +2 -1
  244. wagtail/snippets/locale/en/LC_MESSAGES/django.po +23 -13
  245. wagtail/snippets/locale/sv/LC_MESSAGES/django.mo +0 -0
  246. wagtail/snippets/locale/sv/LC_MESSAGES/django.po +12 -1
  247. wagtail/snippets/tests/test_chooser_block.py +197 -0
  248. wagtail/snippets/tests/test_chooser_panel.py +149 -0
  249. wagtail/snippets/tests/test_chooser_views.py +375 -0
  250. wagtail/snippets/tests/test_chooser_widget.py +22 -0
  251. wagtail/snippets/tests/test_compare_revisions_view.py +167 -0
  252. wagtail/snippets/tests/test_copy_view.py +38 -0
  253. wagtail/snippets/tests/test_create_view.py +1159 -0
  254. wagtail/snippets/tests/test_delete_view.py +225 -0
  255. wagtail/snippets/tests/test_edit_view.py +2882 -0
  256. wagtail/snippets/tests/test_history_view.py +182 -0
  257. wagtail/snippets/tests/test_index_view.py +105 -0
  258. wagtail/snippets/tests/test_list_view.py +786 -0
  259. wagtail/snippets/tests/test_locking.py +28 -0
  260. wagtail/snippets/tests/test_permissions.py +167 -0
  261. wagtail/snippets/tests/test_preview.py +3 -3
  262. wagtail/snippets/tests/test_revert_view.py +343 -0
  263. wagtail/snippets/tests/test_snippet_models.py +112 -0
  264. wagtail/snippets/tests/test_unpublish_view.py +228 -0
  265. wagtail/snippets/tests/test_unschedule_view.py +151 -0
  266. wagtail/snippets/tests/test_viewset.py +38 -5
  267. wagtail/snippets/views/snippets.py +78 -30
  268. wagtail/snippets/widgets.py +2 -2
  269. wagtail/templatetags/wagtailcore_tags.py +2 -2
  270. wagtail/test/dummy_external_storage.py +1 -1
  271. wagtail/test/testapp/fixtures/test.json +22 -0
  272. wagtail/test/testapp/fixtures/test_empty.json +2 -0
  273. wagtail/test/testapp/fixtures/test_explorable_pages.json +10 -0
  274. wagtail/test/testapp/fixtures/test_specific.json +9 -0
  275. wagtail/test/testapp/migrations/0059_nopromotepage.py +25 -0
  276. wagtail/test/testapp/models.py +7 -0
  277. wagtail/test/testapp/views.py +5 -0
  278. wagtail/test/utils/page_tests.py +7 -7
  279. wagtail/test/utils/wagtail_factories/builder.py +2 -2
  280. wagtail/tests/streamfield_migrations/test_migrations.py +35 -0
  281. wagtail/tests/test_blocks.py +321 -61
  282. wagtail/tests/test_collection_model.py +12 -0
  283. wagtail/tests/test_page_model.py +190 -1
  284. wagtail/tests/test_page_privacy.py +5 -0
  285. wagtail/tests/test_reference_index.py +42 -0
  286. wagtail/tests/test_revision_model.py +118 -1
  287. wagtail/tests/test_utils.py +2 -2
  288. wagtail/users/locale/en/LC_MESSAGES/django.po +14 -14
  289. wagtail/users/locale/id_ID/LC_MESSAGES/django.mo +0 -0
  290. wagtail/users/locale/id_ID/LC_MESSAGES/django.po +6 -2
  291. wagtail/users/locale/it/LC_MESSAGES/django.mo +0 -0
  292. wagtail/users/locale/it/LC_MESSAGES/django.po +14 -2
  293. wagtail/users/locale/sv/LC_MESSAGES/django.mo +0 -0
  294. wagtail/users/locale/sv/LC_MESSAGES/django.po +48 -17
  295. wagtail/users/tests/test_admin_views.py +39 -25
  296. wagtail/users/utils.py +4 -1
  297. wagtail/users/views/groups.py +19 -5
  298. wagtail/users/wagtail_hooks.py +1 -1
  299. wagtail/utils/loading.py +2 -2
  300. wagtail-7.3rc1.data/data/AGENTS.md +21 -0
  301. wagtail-7.3rc1.data/data/CHANGELOG.txt +4941 -0
  302. wagtail-7.3rc1.data/data/CODE_OF_CONDUCT.md +71 -0
  303. wagtail-7.3rc1.data/data/CONTRIBUTORS.md +999 -0
  304. wagtail-7.3rc1.data/data/SPONSORS.md +55 -0
  305. {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/METADATA +6 -6
  306. {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/RECORD +310 -280
  307. {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/WHEEL +1 -1
  308. wagtail/images/static/wagtailimages/js/image-url-generator.js +0 -1
  309. wagtail/snippets/tests/test_snippets.py +0 -6377
  310. {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/entry_points.txt +0 -0
  311. {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/licenses/LICENSE +0 -0
  312. {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@ from django.conf import settings
8
8
  from django.contrib.auth import get_user_model
9
9
  from django.contrib.auth.models import AnonymousUser, Group
10
10
  from django.contrib.contenttypes.models import ContentType
11
- from django.core.exceptions import ValidationError
11
+ from django.core.exceptions import PermissionDenied, ValidationError
12
12
  from django.http import Http404
13
13
  from django.test import Client, TestCase, override_settings
14
14
  from django.test.client import RequestFactory
@@ -1013,6 +1013,141 @@ class TestSaveRevision(TestCase):
1013
1013
  approved_go_live_at=timezone.now() + datetime.timedelta(days=1)
1014
1014
  )
1015
1015
 
1016
+ def test_overwrite_revision(self):
1017
+ christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
1018
+ christmas_event.title = "A partridge in a pear tree"
1019
+ revision1 = christmas_event.save_revision()
1020
+ self.assertEqual(christmas_event.revisions.count(), 1)
1021
+ christmas_event.title = "Two turtle doves"
1022
+ revision2 = christmas_event.save_revision(overwrite_revision=revision1)
1023
+ self.assertEqual(christmas_event.revisions.count(), 1)
1024
+ self.assertEqual(revision1.id, revision2.id)
1025
+ revision1.refresh_from_db()
1026
+ self.assertEqual(revision1.content["title"], "Two turtle doves")
1027
+
1028
+ def test_cannot_overwrite_revision_that_is_not_latest(self):
1029
+ christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
1030
+ christmas_event.title = "A partridge in a pear tree"
1031
+ revision1 = christmas_event.save_revision()
1032
+ self.assertEqual(christmas_event.revisions.count(), 1)
1033
+ christmas_event.title = "Two turtle doves"
1034
+ christmas_event.save_revision()
1035
+ self.assertEqual(christmas_event.revisions.count(), 2)
1036
+ christmas_event.title = "Three French hens"
1037
+ with self.assertRaisesMessage(
1038
+ PermissionDenied,
1039
+ "Cannot overwrite a revision that is not the latest for this page.",
1040
+ ):
1041
+ christmas_event.save_revision(overwrite_revision=revision1)
1042
+ self.assertEqual(christmas_event.revisions.count(), 2)
1043
+ latest_revision = christmas_event.get_latest_revision()
1044
+ self.assertEqual(latest_revision.content["title"], "Two turtle doves")
1045
+
1046
+ def test_cannot_overwrite_revision_from_other_instance(self):
1047
+ christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
1048
+ christmas_event.title = "A partridge in a pear tree"
1049
+ christmas_event.save_revision()
1050
+ self.assertEqual(christmas_event.revisions.count(), 1)
1051
+
1052
+ other_event = EventPage.objects.get(
1053
+ url_path="/home/events/tentative-unpublished-event/"
1054
+ )
1055
+ other_event.title = "The final event"
1056
+ revision2 = other_event.save_revision()
1057
+ self.assertEqual(other_event.revisions.count(), 1)
1058
+
1059
+ christmas_event.title = "Two turtle doves"
1060
+ with self.assertRaisesMessage(
1061
+ PermissionDenied,
1062
+ "Cannot overwrite a revision that is not the latest for this page.",
1063
+ ):
1064
+ christmas_event.save_revision(overwrite_revision=revision2)
1065
+
1066
+ self.assertEqual(christmas_event.revisions.count(), 1)
1067
+ latest_revision = christmas_event.get_latest_revision()
1068
+ self.assertEqual(latest_revision.content["title"], "A partridge in a pear tree")
1069
+
1070
+ self.assertEqual(other_event.revisions.count(), 1)
1071
+ latest_revision = other_event.get_latest_revision()
1072
+ self.assertEqual(latest_revision.content["title"], "The final event")
1073
+
1074
+ def test_overwrite_revision_with_user_id(self):
1075
+ event_moderator = get_user_model().objects.get(
1076
+ email="eventmoderator@example.com"
1077
+ )
1078
+ christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
1079
+ christmas_event.title = "A partridge in a pear tree"
1080
+ revision1 = christmas_event.save_revision(user=event_moderator)
1081
+ self.assertEqual(christmas_event.revisions.count(), 1)
1082
+ christmas_event.title = "Two turtle doves"
1083
+ revision2 = christmas_event.save_revision(
1084
+ user=event_moderator, overwrite_revision=revision1
1085
+ )
1086
+ self.assertEqual(christmas_event.revisions.count(), 1)
1087
+ self.assertEqual(revision1.id, revision2.id)
1088
+ revision1.refresh_from_db()
1089
+ self.assertEqual(revision1.content["title"], "Two turtle doves")
1090
+
1091
+ def test_cannot_overwrite_revision_with_wrong_user_id(self):
1092
+ event_moderator = get_user_model().objects.get(
1093
+ email="eventmoderator@example.com"
1094
+ )
1095
+ event_editor = get_user_model().objects.get(email="eventeditor@example.com")
1096
+
1097
+ christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
1098
+ christmas_event.title = "A partridge in a pear tree"
1099
+ revision1 = christmas_event.save_revision(user=event_editor)
1100
+ self.assertEqual(christmas_event.revisions.count(), 1)
1101
+ christmas_event.title = "Two turtle doves"
1102
+ with self.assertRaisesMessage(
1103
+ PermissionDenied,
1104
+ "Cannot overwrite a revision that was not created by the current user.",
1105
+ ):
1106
+ christmas_event.save_revision(
1107
+ user=event_moderator, overwrite_revision=revision1
1108
+ )
1109
+ self.assertEqual(christmas_event.revisions.count(), 1)
1110
+ revision1.refresh_from_db()
1111
+ self.assertEqual(revision1.content["title"], "A partridge in a pear tree")
1112
+
1113
+ def test_cannot_overwrite_revision_with_omitted_user_id(self):
1114
+ event_editor = get_user_model().objects.get(email="eventeditor@example.com")
1115
+
1116
+ christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
1117
+ christmas_event.title = "A partridge in a pear tree"
1118
+ revision1 = christmas_event.save_revision(user=event_editor)
1119
+ self.assertEqual(christmas_event.revisions.count(), 1)
1120
+ christmas_event.title = "Two turtle doves"
1121
+ with self.assertRaisesMessage(
1122
+ PermissionDenied,
1123
+ "Cannot overwrite a revision that was not created by the current user.",
1124
+ ):
1125
+ christmas_event.save_revision(overwrite_revision=revision1)
1126
+ self.assertEqual(christmas_event.revisions.count(), 1)
1127
+ revision1.refresh_from_db()
1128
+ self.assertEqual(revision1.content["title"], "A partridge in a pear tree")
1129
+
1130
+ def test_cannot_overwrite_anonymous_revision_with_user_id(self):
1131
+ event_moderator = get_user_model().objects.get(
1132
+ email="eventmoderator@example.com"
1133
+ )
1134
+
1135
+ christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
1136
+ christmas_event.title = "A partridge in a pear tree"
1137
+ revision1 = christmas_event.save_revision()
1138
+ self.assertEqual(christmas_event.revisions.count(), 1)
1139
+ christmas_event.title = "Two turtle doves"
1140
+ with self.assertRaisesMessage(
1141
+ PermissionDenied,
1142
+ "Cannot overwrite a revision that was not created by the current user.",
1143
+ ):
1144
+ christmas_event.save_revision(
1145
+ user=event_moderator, overwrite_revision=revision1
1146
+ )
1147
+ self.assertEqual(christmas_event.revisions.count(), 1)
1148
+ revision1.refresh_from_db()
1149
+ self.assertEqual(revision1.content["title"], "A partridge in a pear tree")
1150
+
1016
1151
 
1017
1152
  class TestLiveRevision(TestCase):
1018
1153
  fixtures = ["test.json"]
@@ -4147,3 +4282,57 @@ class TestPageServeWithPasswordRestriction(TestCase, WagtailTestUtils):
4147
4282
 
4148
4283
  self.assertFalse("Cache-Control" in response)
4149
4284
  self.assertFalse("Expires" in response)
4285
+
4286
+
4287
+ class TestPageNaturalKey(TestCase):
4288
+ def setUp(self):
4289
+ self.home_page = Page.objects.get(slug="home")
4290
+
4291
+ def test_page_natural_key(self):
4292
+ natural_key = self.home_page.natural_key()
4293
+ self.assertEqual(natural_key, ("/home/",))
4294
+
4295
+ retrieved_page = Page.objects.get_by_natural_key("/home/")
4296
+ self.assertEqual(retrieved_page, self.home_page)
4297
+
4298
+
4299
+ class TestPageCreationWithoutPromotePanels(WagtailTestUtils, TestCase):
4300
+ def setUp(self):
4301
+ self.user = self.login()
4302
+ self.root_page = Page.objects.get(url_path="/home/")
4303
+
4304
+ def _submit_page_form(self, model_name, title):
4305
+ url = reverse(
4306
+ "wagtailadmin_pages:add", args=("tests", model_name, self.root_page.id)
4307
+ )
4308
+
4309
+ get_response = self.client.get(url)
4310
+ self.assertEqual(get_response.status_code, 200)
4311
+
4312
+ form = get_response.context["form"]
4313
+ post_data = form.data.copy()
4314
+
4315
+ for key, value in list(post_data.items()):
4316
+ if value is None:
4317
+ post_data[key] = ""
4318
+
4319
+ post_data.update(
4320
+ {
4321
+ "title": title,
4322
+ "action-save": "Save draft",
4323
+ }
4324
+ )
4325
+
4326
+ post_response = self.client.post(url, post_data)
4327
+ return post_response
4328
+
4329
+ def test_create_simple_page_with_auto_slug(self):
4330
+ response_1 = self._submit_page_form("nopromotepage", "New York")
4331
+ self.assertEqual(response_1.status_code, 302)
4332
+ self.assertTrue(Page.objects.filter(title="New York", slug="new-york").exists())
4333
+
4334
+ response_2 = self._submit_page_form("nopromotepage", "New York")
4335
+ self.assertEqual(response_2.status_code, 302)
4336
+ self.assertTrue(
4337
+ Page.objects.filter(title="New York", slug="new-york-2").exists()
4338
+ )
@@ -28,6 +28,11 @@ class TestPagePrivacy(WagtailTestUtils, TestCase):
28
28
  response.templates[0].name, "wagtailcore/password_required.html"
29
29
  )
30
30
 
31
+ # test that preview attributes are set on the request
32
+ request = response.context["request"]
33
+ self.assertFalse(request.is_preview)
34
+ self.assertIsNone(request.preview_mode)
35
+
31
36
  submit_url = "/_util/authenticate_with_password/%d/%d/" % (
32
37
  self.view_restriction.id,
33
38
  self.secret_plans_page.id,
@@ -878,3 +878,45 @@ class TestBulkFetch(TestCase):
878
878
  },
879
879
  expected_refs,
880
880
  )
881
+
882
+
883
+ class TestReferenceIndex(TestCase):
884
+ def test_target_deletion_leaves_orphan(self):
885
+ """
886
+ Regression test for #13632:
887
+ Deleting the TARGET (referenced) object should remove the inbound link from ReferenceIndex.
888
+ """
889
+ root_page = Page.objects.get(id=2)
890
+ target_page = Page(title="Target2", slug="target2")
891
+ root_page.add_child(instance=target_page)
892
+ source_page = Page(title="Source2", slug="source2")
893
+ root_page.add_child(instance=source_page)
894
+
895
+ ReferenceIndex.objects.create(
896
+ base_content_type=ReferenceIndex._get_base_content_type(source_page),
897
+ content_type=ContentType.objects.get_for_model(source_page),
898
+ object_id=source_page.pk,
899
+ to_content_type=ReferenceIndex._get_base_content_type(target_page),
900
+ to_object_id=target_page.pk,
901
+ model_path="body",
902
+ content_path="body.0.value",
903
+ content_path_hash=ReferenceIndex._get_content_path_hash("body.0.value"),
904
+ )
905
+
906
+ # Verify ref exists
907
+ self.assertEqual(ReferenceIndex.get_references_to(target_page).count(), 1)
908
+
909
+ # Delete TARGET
910
+ target_page.delete()
911
+
912
+ # Check if reference remains (pointing to dead target)
913
+ refs = ReferenceIndex.objects.filter(
914
+ to_object_id=target_page.pk,
915
+ to_content_type=ReferenceIndex._get_base_content_type(target_page),
916
+ )
917
+
918
+ self.assertEqual(
919
+ refs.count(),
920
+ 0,
921
+ "ReferenceIndex should be cleared of inbound references when target is deleted",
922
+ )
@@ -1,6 +1,7 @@
1
1
  import datetime
2
2
 
3
3
  from django.contrib.contenttypes.models import ContentType
4
+ from django.core.exceptions import PermissionDenied
4
5
  from django.test import TestCase
5
6
  from freezegun import freeze_time
6
7
 
@@ -12,9 +13,10 @@ from wagtail.test.testapp.models import (
12
13
  RevisableModel,
13
14
  SimplePage,
14
15
  )
16
+ from wagtail.test.utils import WagtailTestUtils
15
17
 
16
18
 
17
- class TestRevisableModel(TestCase):
19
+ class TestRevisableModel(WagtailTestUtils, TestCase):
18
20
  @classmethod
19
21
  def setUpTestData(cls):
20
22
  cls.instance = RevisableModel.objects.create(text="foo")
@@ -237,3 +239,118 @@ class TestRevisableModel(TestCase):
237
239
  self.assertEqual(Revision.objects.filter(**query).first(), revision)
238
240
  instance.delete()
239
241
  self.assertIs(Revision.objects.filter(**query).exists(), False)
242
+
243
+ def test_overwrite_revision(self):
244
+ self.instance.text = "Existing revision"
245
+ revision1 = self.instance.save_revision()
246
+ self.assertEqual(self.instance.revisions.count(), 1)
247
+ self.instance.text = "Updated revision"
248
+ revision2 = self.instance.save_revision(overwrite_revision=revision1)
249
+ self.assertEqual(self.instance.revisions.count(), 1)
250
+ self.assertEqual(revision1.id, revision2.id)
251
+ revision1.refresh_from_db()
252
+ self.assertEqual(revision1.content["text"], "Updated revision")
253
+
254
+ def test_cannot_overwrite_revision_that_is_not_latest(self):
255
+ self.instance.text = "Existing revision"
256
+ revision1 = self.instance.save_revision()
257
+ self.assertEqual(self.instance.revisions.count(), 1)
258
+ self.instance.text = "Second revision"
259
+ self.instance.save_revision()
260
+ self.assertEqual(self.instance.revisions.count(), 2)
261
+ self.instance.text = "Updated revision"
262
+ with self.assertRaisesMessage(
263
+ PermissionDenied,
264
+ "Cannot overwrite a revision that is not the latest for this "
265
+ "revisable model.",
266
+ ):
267
+ self.instance.save_revision(overwrite_revision=revision1)
268
+
269
+ self.assertEqual(self.instance.revisions.count(), 2)
270
+ latest_revision = self.instance.get_latest_revision()
271
+ self.assertEqual(latest_revision.content["text"], "Second revision")
272
+
273
+ def test_cannot_overwrite_revision_from_other_instance(self):
274
+ self.instance.text = "Existing revision"
275
+ self.instance.save_revision()
276
+
277
+ other_instance = RevisableModel.objects.create(text="other")
278
+ other_instance.text = "Existing other revision"
279
+ revision1 = other_instance.save_revision()
280
+
281
+ self.instance.text = "Updated revision"
282
+ with self.assertRaisesMessage(
283
+ PermissionDenied,
284
+ "Cannot overwrite a revision that is not the latest for this "
285
+ "revisable model.",
286
+ ):
287
+ self.instance.save_revision(overwrite_revision=revision1)
288
+
289
+ self.assertEqual(self.instance.revisions.count(), 1)
290
+ latest_revision = self.instance.get_latest_revision()
291
+ self.assertEqual(latest_revision.content["text"], "Existing revision")
292
+
293
+ self.assertEqual(other_instance.revisions.count(), 1)
294
+ latest_revision = other_instance.get_latest_revision()
295
+ self.assertEqual(latest_revision.content["text"], "Existing other revision")
296
+
297
+ def test_overwrite_revision_with_user_id(self):
298
+ user = self.create_user("user1")
299
+ self.instance.text = "Existing revision"
300
+ revision1 = self.instance.save_revision(user=user)
301
+ self.assertEqual(self.instance.revisions.count(), 1)
302
+ self.instance.text = "Updated revision"
303
+ revision2 = self.instance.save_revision(overwrite_revision=revision1, user=user)
304
+ self.assertEqual(self.instance.revisions.count(), 1)
305
+ self.assertEqual(revision1.id, revision2.id)
306
+ revision1.refresh_from_db()
307
+ self.assertEqual(revision1.content["text"], "Updated revision")
308
+
309
+ def test_cannot_overwrite_revision_with_wrong_user_id(self):
310
+ user1 = self.create_user("user1")
311
+ user2 = self.create_user("user2")
312
+ self.instance.text = "Existing revision"
313
+ revision1 = self.instance.save_revision(user=user1)
314
+ self.assertEqual(self.instance.revisions.count(), 1)
315
+ self.instance.text = "Updated revision"
316
+ with self.assertRaisesMessage(
317
+ PermissionDenied,
318
+ "Cannot overwrite a revision that was not created by the current user.",
319
+ ):
320
+ self.instance.save_revision(overwrite_revision=revision1, user=user2)
321
+
322
+ self.assertEqual(self.instance.revisions.count(), 1)
323
+ latest_revision = self.instance.get_latest_revision()
324
+ self.assertEqual(latest_revision.content["text"], "Existing revision")
325
+
326
+ def test_cannot_overwrite_revision_with_omitted_user_id(self):
327
+ user1 = self.create_user("user1")
328
+ self.instance.text = "Existing revision"
329
+ revision1 = self.instance.save_revision(user=user1)
330
+ self.assertEqual(self.instance.revisions.count(), 1)
331
+ self.instance.text = "Updated revision"
332
+ with self.assertRaisesMessage(
333
+ PermissionDenied,
334
+ "Cannot overwrite a revision that was not created by the current user.",
335
+ ):
336
+ self.instance.save_revision(overwrite_revision=revision1)
337
+
338
+ self.assertEqual(self.instance.revisions.count(), 1)
339
+ latest_revision = self.instance.get_latest_revision()
340
+ self.assertEqual(latest_revision.content["text"], "Existing revision")
341
+
342
+ def test_cannot_overwrite_anonymous_revision_with_user_id(self):
343
+ user1 = self.create_user("user1")
344
+ self.instance.text = "Existing revision"
345
+ revision1 = self.instance.save_revision()
346
+ self.assertEqual(self.instance.revisions.count(), 1)
347
+ self.instance.text = "Updated revision"
348
+ with self.assertRaisesMessage(
349
+ PermissionDenied,
350
+ "Cannot overwrite a revision that was not created by the current user.",
351
+ ):
352
+ self.instance.save_revision(overwrite_revision=revision1, user=user1)
353
+
354
+ self.assertEqual(self.instance.revisions.count(), 1)
355
+ latest_revision = self.instance.get_latest_revision()
356
+ self.assertEqual(latest_revision.content["text"], "Existing revision")
@@ -185,14 +185,14 @@ class TestInvokeViaAttributeShortcut(SimpleTestCase):
185
185
  raise AssertionError(
186
186
  "An error occurred when attempting to pickle %r: %s"
187
187
  % (self.test_object, e)
188
- )
188
+ ) from e
189
189
  try:
190
190
  self.test_object = pickle.loads(pickled)
191
191
  except Exception as e: # noqa: BLE001
192
192
  raise AssertionError(
193
193
  "An error occurred when attempting to unpickle %r: %s"
194
194
  % (self.test_object, e)
195
- )
195
+ ) from e
196
196
 
197
197
  # Confirm unpickled object works the same
198
198
  self.target_object = self.test_object.obj
@@ -8,7 +8,7 @@ msgid ""
8
8
  msgstr ""
9
9
  "Project-Id-Version: PACKAGE VERSION\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2025-10-23 16:45+0100\n"
11
+ "POT-Creation-Date: 2026-01-21 18:00+0000\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -296,7 +296,7 @@ msgid ""
296
296
  "users."
297
297
  msgstr ""
298
298
 
299
- #: templates/wagtailusers/groups/confirm_delete.html:18 views/groups.py:139
299
+ #: templates/wagtailusers/groups/confirm_delete.html:18 views/groups.py:153
300
300
  msgid "Are you sure you want to delete this group?"
301
301
  msgstr ""
302
302
 
@@ -307,7 +307,7 @@ msgstr ""
307
307
 
308
308
  #: templates/wagtailusers/groups/includes/formatted_permissions.html:20
309
309
  #: templates/wagtailusers/groups/includes/formatted_permissions.html:107
310
- #: views/groups.py:88 views/users.py:125
310
+ #: views/groups.py:102 views/users.py:125
311
311
  msgid "Name"
312
312
  msgstr ""
313
313
 
@@ -403,7 +403,7 @@ msgstr ""
403
403
  msgid "Can view"
404
404
  msgstr ""
405
405
 
406
- #: utils.py:85
406
+ #: utils.py:88
407
407
  #, python-format
408
408
  msgid "user %(id)s (deleted)"
409
409
  msgstr ""
@@ -461,46 +461,46 @@ msgid_plural "%(num_parent_objects)d users have been marked as inactive"
461
461
  msgstr[0] ""
462
462
  msgstr[1] ""
463
463
 
464
- #: views/groups.py:78 views/groups.py:148
464
+ #: views/groups.py:92 views/groups.py:162
465
465
  msgid "Groups"
466
466
  msgstr ""
467
467
 
468
- #: views/groups.py:79
468
+ #: views/groups.py:93
469
469
  msgid "Add a group"
470
470
  msgstr ""
471
471
 
472
- #: views/groups.py:80
472
+ #: views/groups.py:94
473
473
  msgid "Search groups"
474
474
  msgstr ""
475
475
 
476
- #: views/groups.py:96
476
+ #: views/groups.py:110
477
477
  msgid "Add group"
478
478
  msgstr ""
479
479
 
480
- #: views/groups.py:97
480
+ #: views/groups.py:111
481
481
  #, python-format
482
482
  msgid "Group '%(object)s' created."
483
483
  msgstr ""
484
484
 
485
- #: views/groups.py:110
485
+ #: views/groups.py:124
486
486
  #, python-format
487
487
  msgid "Group '%(object)s' updated."
488
488
  msgstr ""
489
489
 
490
- #: views/groups.py:111
490
+ #: views/groups.py:125
491
491
  msgid "The group could not be saved due to errors."
492
492
  msgstr ""
493
493
 
494
- #: views/groups.py:118
494
+ #: views/groups.py:132
495
495
  msgid "View users in this group"
496
496
  msgstr ""
497
497
 
498
- #: views/groups.py:137
498
+ #: views/groups.py:151
499
499
  #, python-format
500
500
  msgid "Group '%(object)s' deleted."
501
501
  msgstr ""
502
502
 
503
- #: views/groups.py:138
503
+ #: views/groups.py:152
504
504
  msgid "Delete group"
505
505
  msgstr ""
506
506
 
@@ -4,6 +4,7 @@
4
4
  #
5
5
  # Translators:
6
6
  # atmosuwiryo <suwiryo.atmo@gmail.com>, 2019
7
+ # Imanu Wardi, 2025
7
8
  # M. Febrian Ramadhana <febrian@ramadhana.me>, 2018
8
9
  # atmosuwiryo <suwiryo.atmo@gmail.com>, 2019
9
10
  msgid ""
@@ -12,7 +13,7 @@ msgstr ""
12
13
  "Report-Msgid-Bugs-To: \n"
13
14
  "POT-Creation-Date: 2025-10-23 16:45+0100\n"
14
15
  "PO-Revision-Date: 2014-02-19 11:54+0000\n"
15
- "Last-Translator: atmosuwiryo <suwiryo.atmo@gmail.com>, 2019\n"
16
+ "Last-Translator: Imanu Wardi, 2025\n"
16
17
  "Language-Team: Indonesian (Indonesia) (http://app.transifex.com/torchbox/"
17
18
  "wagtail/language/id_ID/)\n"
18
19
  "MIME-Version: 1.0\n"
@@ -22,7 +23,10 @@ msgstr ""
22
23
  "Plural-Forms: nplurals=1; plural=0;\n"
23
24
 
24
25
  msgid "Wagtail users"
25
- msgstr "Wagtail pengguna"
26
+ msgstr "Pengguna Wagtail"
27
+
28
+ msgid "Required. Letters, digits and @/./+/-/_ only."
29
+ msgstr "Harus diisi. Gunakan hanya huruf, angka, dan simbol @/./+/-/."
26
30
 
27
31
  msgid "This value may contain only letters, numbers and @/./+/-/_ characters."
28
32
  msgstr "Hanya dapat berisi karakter huruf, angka dan @/./+/-/_ saja."
@@ -6,7 +6,7 @@
6
6
  # Giacomo Ghizzani <giacomo.ghz@gmail.com>, 2015-2018
7
7
  # giammi <gian-maria.daffre@giammi.org>, 2018
8
8
  # giammi <gian-maria.daffre@giammi.org>, 2018
9
- # Marco Badan <marco.badan@gmail.com>, 2021-2024
9
+ # Marco Badan <marco.badan@gmail.com>, 2021-2026
10
10
  # Sandro Badalamenti <sandro@mailinator.com>, 2019
11
11
  msgid ""
12
12
  msgstr ""
@@ -14,7 +14,7 @@ msgstr ""
14
14
  "Report-Msgid-Bugs-To: \n"
15
15
  "POT-Creation-Date: 2025-10-23 16:45+0100\n"
16
16
  "PO-Revision-Date: 2014-02-19 11:54+0000\n"
17
- "Last-Translator: Sandro Badalamenti <sandro@mailinator.com>, 2019\n"
17
+ "Last-Translator: Marco Badan <marco.badan@gmail.com>, 2021-2026\n"
18
18
  "Language-Team: Italian (http://app.transifex.com/torchbox/wagtail/language/"
19
19
  "it/)\n"
20
20
  "MIME-Version: 1.0\n"
@@ -129,6 +129,12 @@ msgstr "Scuro"
129
129
  msgid "admin theme"
130
130
  msgstr "tema admin"
131
131
 
132
+ msgid "More contrast"
133
+ msgstr "Più contrasto"
134
+
135
+ msgid "contrast"
136
+ msgstr "contrasto"
137
+
132
138
  msgid "Default"
133
139
  msgstr "Default"
134
140
 
@@ -143,6 +149,9 @@ msgstr "densità"
143
149
  msgid "Keyboard shortcuts"
144
150
  msgstr "Scorciatoie da tastiera"
145
151
 
152
+ msgid "Enable custom keyboard shortcuts specific to Wagtail."
153
+ msgstr "Abilita le scorciatoie da tastiera personalizzate per Wagtail."
154
+
146
155
  msgid "user profile"
147
156
  msgstr "profilo utente"
148
157
 
@@ -317,6 +326,9 @@ msgstr ""
317
326
  "Non ci sono utenti configurati. Perché non <a "
318
327
  "href=\"%(wagtailusers_add_url)s\">ne aggiungi qualcuno</a>?"
319
328
 
329
+ msgid "Can view"
330
+ msgstr "Può vedere"
331
+
320
332
  #, python-format
321
333
  msgid "user %(id)s (deleted)"
322
334
  msgstr "utente %(id)s (eliminato)"