Skip to content

Commit

Permalink
Enable translation (rebased) (#69)
Browse files Browse the repository at this point in the history
* Make footnote model translatable
* Make package strings translatable
* Add Romanian translation
* Add i18n notes in README

---------

Co-authored-by: Jhonatan Lopes <jhonatan.dapontelopes@gmail.com>
  • Loading branch information
zerolab and jhonatan-lopes committed May 17, 2024
1 parent 7bf8b16 commit 44d49f2
Show file tree
Hide file tree
Showing 17 changed files with 435 additions and 26 deletions.
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 <LL@li.org>\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

0 comments on commit 44d49f2

Please sign in to comment.