Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Enable translation (rebased) #69

Merged
merged 11 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ coverage.xml
cover/

# Translations
*.mo
*.pot

# Django stuff:
Expand Down
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,36 @@ WAGTAILADMIN_RICH_TEXT_EDITORS = {
- Default: `["bold", "italic", "link"]`
- Use this to update a list of Rich Text features allowed in the footnote text.

## 🌍 Internationalisation

Wagtail Footnotes can be translated. Note that in a multi-lingual setup, the URL setup for footnotes
needs to be in a `i18n_patterns()` call with `prefix_default_language=False`:

```python
# urls.py

urlpatterns += i18n_patterns(
path("footnotes/", include(footnotes_urls)),
# ...
path("", include(wagtail_urls)),
prefix_default_language=False,
)
```

or outside `i18n_patterns()`:

```python
# urls.py

urlpattherns += [
path("footnotes/", include(footnotes_urls)),
]
urlpatterns += i18n_patterns(
# ...
path("", include(wagtail_urls)),
)
```

## 💡 Common issues

- I click on the `Fn` button in the editor and it stops working
Expand Down
8 changes: 8 additions & 0 deletions tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
"wagtail.search",
"wagtail.admin",
"wagtail_modeladmin",
"wagtail.contrib.simple_translation",
"wagtail.contrib.redirects",
"wagtail.sites",
"wagtail",
"taggit",
Expand All @@ -53,6 +55,7 @@
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
Expand Down Expand Up @@ -110,6 +113,11 @@

USE_TZ = True

USE_I18N = True
WAGTAIL_I18N_ENABLED = True
LANGUAGE_CODE = "en"


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/stable/howto/static-files/

Expand Down
7 changes: 5 additions & 2 deletions tests/templates/base.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{% load wagtailuserbar %}
{% load wagtailuserbar i18n %}

{% get_current_language as LANGUAGE_CODE %}

<!DOCTYPE html>
<html lang="en">
<html lang="{{ LANGUAGE_CODE }}">

<head>
<meta charset="UTF-8">
Expand Down
155 changes: 155 additions & 0 deletions tests/test/test_translation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import json

from bs4 import BeautifulSoup as bs4
from django.test import override_settings
from django.urls import reverse
from django.utils import translation
from wagtail.models import Locale, Page
from wagtail.test.utils import TestCase, WagtailTestUtils

from wagtail_footnotes.models import Footnote

from ..models import TestPageStreamField


@override_settings(
LANGUAGES=[
("en", "English"),
("fr", "French"),
("de", "German"),
],
WAGTAIL_CONTENT_LANGUAGES=[
("en", "English"),
("fr", "French"),
("de", "German"),
],
)
class TestSubmitPageTranslationView(WagtailTestUtils, TestCase):
@classmethod
def setUpTestData(cls):
cls.en_locale = Locale.objects.first()
cls.fr_locale = Locale.objects.create(language_code="fr")
cls.de_locale = Locale.objects.create(language_code="de")

cls.en_homepage = Page.objects.get(title="Welcome to your new Wagtail site!")
cls.fr_homepage = cls.en_homepage.copy_for_translation(cls.fr_locale)
cls.fr_homepage.save_revision().publish()
cls.de_homepage = cls.en_homepage.copy_for_translation(cls.de_locale)
cls.de_homepage.save_revision().publish()

cls.uuid = "f291a4b7-5ac5-4030-b341-b1993efb2ad2"
cls.en_test_page = TestPageStreamField(
title="Test Page With Footnote",
slug="test-page-with-footnote",
body=json.dumps(
[
{
"type": "paragraph",
"value": f'<p>This is a paragraph with a footnote. <footnote id="{cls.uuid}">1</footnote></p>',
},
]
),
)
cls.en_homepage.add_child(instance=cls.en_test_page)
cls.en_test_page.save_revision().publish()
cls.en_footnote = Footnote.objects.create(
page=cls.en_test_page,
uuid=cls.uuid,
text="This is a footnote",
)
cls.url = reverse(
"simple_translation:submit_page_translation", args=(cls.en_test_page.id,)
)

def setUp(self):
super().setUp()
self.login()

def test_translating_page_translates_footnote(self):
de = self.de_locale.id
fr = self.fr_locale.id
data = {"locales": [de, fr], "include_subtree": True}
self.client.post(self.url, data, follow=True)

de_footnote = self.en_footnote.get_translation(de)
self.assertEqual(de_footnote.text, self.en_footnote.text)
self.assertEqual(de_footnote.uuid, self.en_footnote.uuid)
de_test_page = self.en_test_page.get_translation(de)
self.assertCountEqual(de_test_page.footnotes.all(), [de_footnote])

fr_footnote = self.en_footnote.get_translation(fr)
self.assertEqual(fr_footnote.text, self.en_footnote.text)
self.assertEqual(fr_footnote.uuid, self.en_footnote.uuid)
fr_test_page = self.en_test_page.get_translation(fr)
self.assertCountEqual(fr_test_page.footnotes.all(), [fr_footnote])

# Can also change the text:
fr_footnote.text = "This is a French translated footnote"
fr_footnote.save(update_fields=["text"])
fr_footnote.refresh_from_db()
en_footnote = self.en_footnote
en_footnote.refresh_from_db()
self.assertEqual(fr_footnote.text, "This is a French translated footnote")
self.assertNotEqual(fr_footnote.text, en_footnote.text)

def test_translated_page_shows_translated_footnote(self):
fr = self.fr_locale.id
data = {"locales": [fr], "include_subtree": True}
response = self.client.post(self.url, data, follow=True)

fr_test_page = self.en_test_page.get_translation(fr)

self.assertRedirects(
response, reverse("wagtailadmin_pages:edit", args=[fr_test_page.pk])
)

self.assertIn(
"The page 'Test Page With Footnote' was successfully created in French",
[msg.message for msg in response.context["messages"]],
)

fr_footnote = self.en_footnote.get_translation(fr)
self.assertEqual(fr_footnote.text, self.en_footnote.text)
self.assertEqual(fr_footnote.uuid, self.en_footnote.uuid)
self.assertCountEqual(fr_test_page.footnotes.all(), [fr_footnote])

fr_test_page.title = ("[FR] Test Page With Footnote",)
fr_test_page.body = json.dumps(
[
{
"type": "paragraph",
"value": f'<p>This is a French paragraph with a footnote. <footnote id="{self.uuid}">1</footnote></p>',
},
]
)
fr_test_page.save_revision().publish()
fr_test_page.refresh_from_db()

# Can also change the text:
fr_footnote.text = "This is a French translated footnote"
fr_footnote.save()

translation.activate("fr")

response = self.client.get(fr_test_page.get_full_url())
self.assertEqual(response.status_code, 200)

soup = bs4(response.content, "html.parser")

# Test that required html tags are present with correct
# attrs that enable the footnotes to respond to clicks
source_anchor = soup.find("a", {"id": "footnote-source-1"})
self.assertTrue(source_anchor)

source_anchor_string = str(source_anchor)
self.assertIn("<sup>[1]</sup>", source_anchor_string)
self.assertIn('href="#footnote-1"', source_anchor_string)
self.assertIn('id="footnote-source-1"', source_anchor_string)

footnotes = soup.find("div", {"class": "footnotes"})
self.assertTrue(footnotes)

footnotes_string = str(footnotes)
self.assertIn('id="footnote-1"', footnotes_string)
self.assertIn('href="#footnote-source-1"', footnotes_string)
self.assertIn("[1] This is a French translated footnote", footnotes_string)
7 changes: 6 additions & 1 deletion tests/urls.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin
from django.urls import include, path
from wagtail import urls as wagtail_urls
Expand All @@ -11,6 +12,10 @@
path("django-admin/", admin.site.urls),
path("admin/", include(wagtailadmin_urls)),
path("documents/", include(wagtaildocs_urls)),
]

urlpatterns += i18n_patterns(
path("footnotes/", include(footnotes_urls)),
path("", include(wagtail_urls)),
]
prefix_default_language=False,
)
Binary file added wagtail_footnotes/locale/en/LC_MESSAGES/django.mo
Binary file not shown.
55 changes: 55 additions & 0 deletions wagtail_footnotes/locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 2024 Torchbox
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-05-17 09:04-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/wagtail_footnotes/admin/footnotes_modal.html:14
msgid "Choose a footnote"
msgstr ""

#: templates/wagtail_footnotes/admin/footnotes_modal.html:26
msgid "Footnotes"
msgstr ""

#: templates/wagtail_footnotes/admin/footnotes_modal.html:28
msgid ""
"To add a new footnote, close this window and scroll to the \"Footnotes\" "
"section at bottom of the page."
msgstr ""

#: templates/wagtail_footnotes/admin/footnotes_modal.html:36
msgid "Text"
msgstr ""

#: templates/wagtail_footnotes/admin/footnotes_modal.html:37
msgid "ID"
msgstr ""

#: templates/wagtail_footnotes/admin/footnotes_modal.html:45
msgid ""
"Footnotes will appear with arbitrary numbers here in the editor. On the "
"published page, and in previews, their numbering will be numerical and "
"ordered."
msgstr ""

#: templates/wagtail_footnotes/includes/footnotes.html:6
msgid "Foonotes"
msgstr ""

#: templates/wagtail_footnotes/includes/footnotes.html:12
msgid "Back to content"
msgstr ""
Binary file added wagtail_footnotes/locale/ro/LC_MESSAGES/django.mo
Binary file not shown.
63 changes: 63 additions & 0 deletions wagtail_footnotes/locale/ro/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-05-17 09:06-0500\n"
"PO-Revision-Date: 2024-05-17 15:23+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: ro\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n==0 || (n!=1 && n%100>=1 && "
"n%100<=19) ? 1 : 2);\n"
"X-Generator: Poedit 3.4.4\n"

#: templates/wagtail_footnotes/admin/footnotes_modal.html:14
msgid "Choose a footnote"
msgstr "Alegeți o notă de subsol"

#: templates/wagtail_footnotes/admin/footnotes_modal.html:26
msgid "Footnotes"
msgstr "Note de subsol"

#: templates/wagtail_footnotes/admin/footnotes_modal.html:28
msgid ""
"To add a new footnote, close this window and scroll to the \"Footnotes\" "
"section at bottom of the page."
msgstr ""
"Pentru a adăuga o notă nouă de subsol, închideți această fereastră și "
"derulați la secțiunea „Note de subsol”."

#: templates/wagtail_footnotes/admin/footnotes_modal.html:36
msgid "Text"
msgstr "Text"

#: templates/wagtail_footnotes/admin/footnotes_modal.html:37
msgid "ID"
msgstr "ID"

#: templates/wagtail_footnotes/admin/footnotes_modal.html:45
msgid ""
"Footnotes will appear with arbitrary numbers here in the editor. On the "
"published page, and in previews, their numbering will be numerical and "
"ordered."
msgstr ""
"Notele de subsol vor apărea ca un set de numere și cifre aleatorii în "
"editorul de text. Pe pagina publicată și în previzualizări, numerotarea va "
"fi numerică și ordonată."

#: templates/wagtail_footnotes/includes/footnotes.html:6
msgid "Foonotes"
msgstr "Note de subsol"

#: templates/wagtail_footnotes/includes/footnotes.html:12
msgid "Back to content"
msgstr "Înapoi la conținut"
Loading
Loading