From 6c65e59a516efb246250b0d356d72101966ea1f6 Mon Sep 17 00:00:00 2001 From: Mudiwa Matanda Date: Thu, 22 Feb 2024 08:05:19 +0200 Subject: [PATCH 1/6] added homepaage locale setting --- README.md | 3 +++ contentrepo/settings/base.py | 3 ++- home/import_content_pages.py | 24 +++++++++++++++++++++--- requirements-dev.txt | 1 + 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c4802273..4396d4a5 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,9 @@ Authentication is required to access the API. Session, basic, and token authenti To create an authentication token, you can do so via the Django Admin (available at the `/django-admin` endpoint), or by `POST`ing the username and password of the user you want to generate a token for to the `/api/v2/token/` endpoint. +### Internationalisation +To create or import pages in other languages, the user must first create the locale in the specified language. To create a new locale, go to "Settings" => "Locales" in the admin interface, and click "Add a new locale". Set the "Sync from" field to "English". This keeps the the specified language tree in sync with any existing and new English content as it's authored. After you press "Save", there should be two "Home" pages in the page explorer. + ## Running in Production There is a [docker image](https://github.com/praekeltfoundation/contentrepo/pkgs/container/contentrepo) that can be used to easily run this service. It uses the following environment variables for configuration: diff --git a/contentrepo/settings/base.py b/contentrepo/settings/base.py index 2313f5cd..b50c5981 100644 --- a/contentrepo/settings/base.py +++ b/contentrepo/settings/base.py @@ -32,7 +32,8 @@ "wagtail_content_import.pickers.local", "wagtail.admin", "wagtail", - "wagtail.locales", + "wagtail_localize", + "wagtail_localize.locales", "wagtail.api.v2", "wagtailmedia", "wagtail.contrib.simple_translation", diff --git a/home/import_content_pages.py b/home/import_content_pages.py index 6f8ece78..e678c0ec 100644 --- a/home/import_content_pages.py +++ b/home/import_content_pages.py @@ -9,7 +9,7 @@ from typing import Any from uuid import uuid4 -from django.core.exceptions import ValidationError # type: ignore +from django.core.exceptions import ObjectDoesNotExist, ValidationError # type: ignore from openpyxl import load_workbook from taggit.models import Tag # type: ignore from treebeard.exceptions import NodeAlreadySaved # type: ignore @@ -74,13 +74,26 @@ def locale_from_display_name(self, langname: str) -> Locale: for lang_code, lang_dn in get_content_languages().items(): if lang_dn == langname: codes.append(lang_code) + print(f"Debug: langname={langname}, codes={codes}") if not codes: raise ImportException(f"Language not found: {langname}") if len(codes) > 1: raise ImportException( f"Multiple codes for language: {langname} -> {codes}" ) - self.locale_map[langname] = Locale.objects.get(language_code=codes[0]) + # print(f"Debug: lanuage code 0 = {codes[0]}") + # self.locale_map[langname] = Locale.objects.get(language_code=codes[0]) + + for code in codes: + try: + # Retrieve the Locale object for each language code in the codes list + self.locale_map[langname] = Locale.objects.get( + language_code=code, language_code__iexact=code + ) + except Locale.DoesNotExist: + print(f"Debug: Locale not found for language code: {code}") + raise ImportException(f"Locale not found for language code: {code}") + return self.locale_map[langname] def perform_import(self) -> None: @@ -214,7 +227,12 @@ def delete_existing_content(self) -> None: ContentPageIndex.objects.all().delete() def home_page(self, locale: Locale) -> HomePage: - return HomePage.objects.get(locale=locale) + try: + return HomePage.objects.get(locale=locale) + except ObjectDoesNotExist: + raise ImportException( + f"You are trying to add a child page to a '{locale}' HomePage that does not exist. Please create the '{locale}' HomePage first" + ) def default_locale(self) -> Locale: site = Site.objects.get(is_default_site=True) diff --git a/requirements-dev.txt b/requirements-dev.txt index aa631277..f5ba7927 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,7 @@ black==24.1.1 ruff==0.1.14 responses +wagtail-localize pytest==8.0.0 pytest-django pytest-cov From 5ae8a0fe3d2f53c0c32a5a7f55ece09c8f7c9329 Mon Sep 17 00:00:00 2001 From: Mudiwa Matanda Date: Thu, 22 Feb 2024 08:38:13 +0200 Subject: [PATCH 2/6] removed not needed lines --- home/import_content_pages.py | 15 +-------------- requirements-dev.txt | 1 - requirements.txt | 1 + 3 files changed, 2 insertions(+), 15 deletions(-) diff --git a/home/import_content_pages.py b/home/import_content_pages.py index e678c0ec..c6203b72 100644 --- a/home/import_content_pages.py +++ b/home/import_content_pages.py @@ -74,26 +74,13 @@ def locale_from_display_name(self, langname: str) -> Locale: for lang_code, lang_dn in get_content_languages().items(): if lang_dn == langname: codes.append(lang_code) - print(f"Debug: langname={langname}, codes={codes}") if not codes: raise ImportException(f"Language not found: {langname}") if len(codes) > 1: raise ImportException( f"Multiple codes for language: {langname} -> {codes}" ) - # print(f"Debug: lanuage code 0 = {codes[0]}") - # self.locale_map[langname] = Locale.objects.get(language_code=codes[0]) - - for code in codes: - try: - # Retrieve the Locale object for each language code in the codes list - self.locale_map[langname] = Locale.objects.get( - language_code=code, language_code__iexact=code - ) - except Locale.DoesNotExist: - print(f"Debug: Locale not found for language code: {code}") - raise ImportException(f"Locale not found for language code: {code}") - + self.locale_map[langname] = Locale.objects.get(language_code=codes[0]) return self.locale_map[langname] def perform_import(self) -> None: diff --git a/requirements-dev.txt b/requirements-dev.txt index f5ba7927..aa631277 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,7 +1,6 @@ black==24.1.1 ruff==0.1.14 responses -wagtail-localize pytest==8.0.0 pytest-django pytest-cov diff --git a/requirements.txt b/requirements.txt index 0729f84d..25329ffd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ wagtail==5.0.5 wagtailmedia psycopg2-binary wagtail-content-import +wagtail-localize drf-spectacular dj-database-url django-environ==0.4.5 From f8057498618c2e2f9fa6d5f2d1d4c346de08ed4c Mon Sep 17 00:00:00 2001 From: Mudiwa Matanda Date: Thu, 22 Feb 2024 09:53:10 +0200 Subject: [PATCH 3/6] added test for missing locale homepage --- contentrepo/settings/base.py | 3 +-- home/tests/content_without_locale_homepage.csv | 15 +++++++++++++++ home/tests/test_content_import_export.py | 16 ++++++++++++++++ requirements.txt | 1 - 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 home/tests/content_without_locale_homepage.csv diff --git a/contentrepo/settings/base.py b/contentrepo/settings/base.py index b50c5981..2313f5cd 100644 --- a/contentrepo/settings/base.py +++ b/contentrepo/settings/base.py @@ -32,8 +32,7 @@ "wagtail_content_import.pickers.local", "wagtail.admin", "wagtail", - "wagtail_localize", - "wagtail_localize.locales", + "wagtail.locales", "wagtail.api.v2", "wagtailmedia", "wagtail.contrib.simple_translation", diff --git a/home/tests/content_without_locale_homepage.csv b/home/tests/content_without_locale_homepage.csv new file mode 100644 index 00000000..112eccaa --- /dev/null +++ b/home/tests/content_without_locale_homepage.csv @@ -0,0 +1,15 @@ +structure,message,page_id,slug,parent,web_title,web_subtitle,web_body,whatsapp_title,whatsapp_body,whatsapp_template_name,whatsapp_template_category,example_values,variation_title,variation_body,list_items,sms_title,sms_body,ussd_title,ussd_body,messenger_title,messenger_body,viber_title,viber_body,translation_tag,tags,quick_replies,triggers,locale,next_prompt,buttons,image_link,doc_link,media_link,related_pages,footer +Menu 1,0,1914,mnch-content-please-dont-include-tests-here,,MNCH CONTENT - please don't include tests here,,,,,,,,,,,,,,,,,,,a4192a58-04fe-4766-9d00-9ec4769ce3d8,,,,English,,,,,,, +Sub 1.1.1,0,1306,stage-based-messages,MNCH CONTENT - please don't include tests here,Push messages,,,,,,,,,,,,,,,,,,,35628191-624e-4a13-93bf-499f4e7de017,,,,English,,,,,,, +Sub 1.1.2,0,1303,appointment-reminders,Push messages,Appointment reminders,,,,,,,,,,,,,,,,,,,8cff04aa-cf08-4120-88b4-e2269b7d5d80,,,,English,,,,,,, +Sub 1.3.1,0,1305,onboarding,Appointment reminders,Onboarding,,,,,,,,,,,,,,,,,,,33cbdea8-4f8e-4461-a8c5-e81c218eb2cc,,,,English,,,,,,, +Menu 2,0,1918,qa-test-content,Onboarding,QA TEST CONTENT,,,,,,,,,,,,,,,,,,,3c34e866-bf12-417b-ba2c-2ff691981339,,,,English,,,,,,, +Sub 2.1.1,0,1787,ma_test,QA TEST CONTENT,MA_TEST,,,,,,,,,,,,,,,,,,,e08351cd-7495-40aa-9c99-b9b731e3ef14,,,,English,,,,,,, +Sub 2.1.1.1,1,1788,ma_export,MA_TEST,MA_EXPORT,,,related pages,this is my content page with related pages. Import,,UTILITY,,,,,,,,,,,,,3e641799-df48-42d5-bdf0-33e332eb3993,,,,English,,[],,,,, +Sub 2.1.2,0,1898,simone_test,QA TEST CONTENT,Simone_Test,,,,,,,,,,,,,,,,,,,abeec5a4-eb18-4551-9291-239d537ab448,,,,English,,,,,,, +Sub 2.1.3,0,1307,functional-copy,QA TEST CONTENT,Multi-media test content,,,,,,,,,,,,,,,,,,,219c1d0c-9b83-4a06-b59f-aa7897a969c9,,,,English,,,,,,, +Menu 3,0,1922,faqs,,FAQs,,,,,,,,,,,,,,,,,,,34f2ee6d-0e17-4b59-899d-e184af5e4863,,,,English,,,,,,, +Menu 4,0,1923,dev-test,,Dev Test,,,,,,,,,,,,,,,,,,,058b1a58-34f7-4589-bc79-a0372860ee17,,,,English,,,,,,, +Menu 1,0,1611,stage-based-messages-por,,Stage-based messages Por,,,,,,,,,,,,,,,,,,,35628191-624e-4a13-93bf-499f4e7de017,,,,Portuguese,,,,,,, +Menu 2,0,1704,helen_test,,Helen test por,,,,,,,,,,,,,,,,,,,51cdf6dc-fb64-4197-bda0-f913b6a72811,,,,Portuguese,,,,,,, +Menu 3,0,1768,hlumi-por-test,,Hlumi por test,,,,,,,,,,,,,,,,,,,743fef92-7384-493e-bcb2-3a7f47ac644f,,,,Portuguese,,,,,,, \ No newline at end of file diff --git a/home/tests/test_content_import_export.py b/home/tests/test_content_import_export.py index 5d80decf..8d65c39a 100644 --- a/home/tests/test_content_import_export.py +++ b/home/tests/test_content_import_export.py @@ -730,6 +730,22 @@ def test_multiple_locales_for_name( == "Multiple codes for language: NotEnglish -> ['en1', 'en2']" ) + + def test_locale_HomePage_DNE(self, csv_impexp: ImportExport) -> None: + """ + Importing files with non default locale HomePages that do not exist in the db should raise + an error that results in an error message that gets sent back to the user + """ + pt, _created = Locale.objects.get_or_create(language_code="pt") + with pytest.raises(ImportException) as e: + csv_impexp.import_file("content_without_locale_homepage.csv") + assert e.value.row_num == 13 + assert ( + e.value.message + =="You are trying to add a child page to a 'Portuguese' HomePage that does not exist. Please create the 'Portuguese' HomePage first" + + ) + def test_missing_parent(self, csv_impexp: ImportExport) -> None: """ If the import file specifies a parent title, but there are no pages with that diff --git a/requirements.txt b/requirements.txt index 25329ffd..0729f84d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,6 @@ wagtail==5.0.5 wagtailmedia psycopg2-binary wagtail-content-import -wagtail-localize drf-spectacular dj-database-url django-environ==0.4.5 From 854efdf44e689e18b9309e73ca9dd5df8f00fa26 Mon Sep 17 00:00:00 2001 From: Mudiwa Matanda Date: Thu, 22 Feb 2024 09:54:55 +0200 Subject: [PATCH 4/6] fixed formating --- home/tests/test_content_import_export.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/home/tests/test_content_import_export.py b/home/tests/test_content_import_export.py index 8d65c39a..96c8e6ae 100644 --- a/home/tests/test_content_import_export.py +++ b/home/tests/test_content_import_export.py @@ -730,10 +730,9 @@ def test_multiple_locales_for_name( == "Multiple codes for language: NotEnglish -> ['en1', 'en2']" ) - def test_locale_HomePage_DNE(self, csv_impexp: ImportExport) -> None: """ - Importing files with non default locale HomePages that do not exist in the db should raise + Importing files with non default locale HomePages that do not exist in the db should raise an error that results in an error message that gets sent back to the user """ pt, _created = Locale.objects.get_or_create(language_code="pt") @@ -742,8 +741,7 @@ def test_locale_HomePage_DNE(self, csv_impexp: ImportExport) -> None: assert e.value.row_num == 13 assert ( e.value.message - =="You are trying to add a child page to a 'Portuguese' HomePage that does not exist. Please create the 'Portuguese' HomePage first" - + == "You are trying to add a child page to a 'Portuguese' HomePage that does not exist. Please create the 'Portuguese' HomePage first" ) def test_missing_parent(self, csv_impexp: ImportExport) -> None: From b0b657fa08366e2709ce9697ff40489570094fc2 Mon Sep 17 00:00:00 2001 From: Mudiwa Matanda Date: Mon, 26 Feb 2024 06:32:26 +0200 Subject: [PATCH 5/6] fiixed readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4396d4a5..73d37ae1 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ Authentication is required to access the API. Session, basic, and token authenti To create an authentication token, you can do so via the Django Admin (available at the `/django-admin` endpoint), or by `POST`ing the username and password of the user you want to generate a token for to the `/api/v2/token/` endpoint. ### Internationalisation -To create or import pages in other languages, the user must first create the locale in the specified language. To create a new locale, go to "Settings" => "Locales" in the admin interface, and click "Add a new locale". Set the "Sync from" field to "English". This keeps the the specified language tree in sync with any existing and new English content as it's authored. After you press "Save", there should be two "Home" pages in the page explorer. +To create or import pages in other languages, the user must first create the locale and HomePage in the specified language. To create a new locale, go to "Settings" => "Locales" in the admin interface, and click "Add a new locale". Then go to the default(most likely English) homepage, click the kebab menu and select translate. This will copies the whole default tree into the new locale, creating the new homepage with all the required pages. After you press "Save", there should be two "Home" pages in the page explorer. ## Running in Production There is a [docker image](https://github.com/praekeltfoundation/contentrepo/pkgs/container/contentrepo) that can be used to easily run this service. It uses the following environment variables for configuration: From 3d5b5ec4f7536afba6ade8bb726053f73299f201 Mon Sep 17 00:00:00 2001 From: Mudiwa Matanda Date: Mon, 26 Feb 2024 06:40:28 +0200 Subject: [PATCH 6/6] fixed grammmar --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 73d37ae1..dc6d7e69 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ Authentication is required to access the API. Session, basic, and token authenti To create an authentication token, you can do so via the Django Admin (available at the `/django-admin` endpoint), or by `POST`ing the username and password of the user you want to generate a token for to the `/api/v2/token/` endpoint. ### Internationalisation -To create or import pages in other languages, the user must first create the locale and HomePage in the specified language. To create a new locale, go to "Settings" => "Locales" in the admin interface, and click "Add a new locale". Then go to the default(most likely English) homepage, click the kebab menu and select translate. This will copies the whole default tree into the new locale, creating the new homepage with all the required pages. After you press "Save", there should be two "Home" pages in the page explorer. +To create or import pages in other languages, the user must first create the locale and HomePage in the specified language. To create a new locale, go to "Settings" => "Locales" in the admin interface, and click "Add a new locale". Then go to the default(most likely English) homepage, click the kebab menu and select translate. This will copy the whole default tree into the new locale, creating the new homepage with all the required pages. After you press "Save", there should be two "Home" pages in the page explorer. ## Running in Production There is a [docker image](https://github.com/praekeltfoundation/contentrepo/pkgs/container/contentrepo) that can be used to easily run this service. It uses the following environment variables for configuration: