From 32c316ac674371c4be9591ea8a0cbf2870290d86 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 27 Nov 2025 13:10:42 -0800 Subject: [PATCH 1/4] Modernize i18n workflow --- docs/glossary.md | 4 ++++ docs/i18n-l10n/translating-text-strings.md | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/glossary.md b/docs/glossary.md index a6c762350..65391effa 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -25,6 +25,10 @@ Buildout [Buildout](https://github.com/buildout/buildout/) is a Python-based tool for building and assembling applications from multiple parts, based on a configuration file. It was the most common way of installing Plone 3, 4, and 5, and can still be used with Plone 6. + Usage of Buildout in Plone appears in various places in this documentation. + For a history and extended usage of Buildout, you can refer to the Plone 4 Documentation's section on [Buildout](https://4.docs.plone.org/old-reference-manuals/buildout/). + The Plone community authored this reference manual, as Buildout's own documentation is suboptimal. + CMS Content Management System diff --git a/docs/i18n-l10n/translating-text-strings.md b/docs/i18n-l10n/translating-text-strings.md index 22d307e88..dae336c29 100644 --- a/docs/i18n-l10n/translating-text-strings.md +++ b/docs/i18n-l10n/translating-text-strings.md @@ -56,7 +56,7 @@ Information in the PO file headers is ignored. [`i18ndude`](https://pypi.org/project/i18ndude/) should be used to create a script which searches particular packages for translation strings. -If you have created your add-on using [bobtemplates.plone](https://pypi.org/project/bobtemplates.plone/), then you will already have a script `update.sh` inside your package and a script `update_locale` in your buildout to extract the messages from your code. +If you have created your add-on using [bobtemplates.plone](https://pypi.org/project/bobtemplates.plone/), then you will already have a script {file}`update.sh` inside your package and a script {file}`update_locale` in your {term}`buildout` to extract the messages from your code. After running that script, a new `domain.pot` file will be created in your `locales` directory where all the messages will be saved. @@ -273,7 +273,7 @@ This script hooks into the release process and builds the MO files for you. ### Installing i18ndude -The recommended method is to have {term}`i18ndude` installed via your [buildout](https://www.buildout.org/en/latest/). +The recommended method is to have {term}`i18ndude` installed via your buildout. Add the following to your `buildout.cfg`: From 3c368e5db5baab229460fba80e7652cc236e50f9 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 30 Nov 2025 21:34:42 -0800 Subject: [PATCH 2/4] Apply suggestions from code review Co-authored-by: Mikel Larreategi --- docs/i18n-l10n/translating-text-strings.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/i18n-l10n/translating-text-strings.md b/docs/i18n-l10n/translating-text-strings.md index dae336c29..b09eb942a 100644 --- a/docs/i18n-l10n/translating-text-strings.md +++ b/docs/i18n-l10n/translating-text-strings.md @@ -56,7 +56,11 @@ Information in the PO file headers is ignored. [`i18ndude`](https://pypi.org/project/i18ndude/) should be used to create a script which searches particular packages for translation strings. -If you have created your add-on using [bobtemplates.plone](https://pypi.org/project/bobtemplates.plone/), then you will already have a script {file}`update.sh` inside your package and a script {file}`update_locale` in your {term}`buildout` to extract the messages from your code. +If you have created your add-on using [`bobtemplates.plone`](https://pypi.org/project/bobtemplates.plone/), then you will already have a script {file}`update.sh` inside your package and a script {file}`update_locale` in your {term}`buildout` to extract the messages from your code. + +If you have created your add-on or projects using [Cookieplone](https://github.com/plone/cookieplone), then you will already have a `make i18n` command in the {file}`backend` folder that extracts the messages from your code. + +This command will call `i18ndude` under the hood using `uvx`, without you needing to install it separately. After running that script, a new `domain.pot` file will be created in your `locales` directory where all the messages will be saved. From b6957a8d6df8ceef139f9f06bc251bdf5f1bbafd Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 30 Nov 2025 21:38:51 -0800 Subject: [PATCH 3/4] Remove obsolete buildout section --- docs/i18n-l10n/translating-text-strings.md | 34 ---------------------- 1 file changed, 34 deletions(-) diff --git a/docs/i18n-l10n/translating-text-strings.md b/docs/i18n-l10n/translating-text-strings.md index b09eb942a..0898c5c9f 100644 --- a/docs/i18n-l10n/translating-text-strings.md +++ b/docs/i18n-l10n/translating-text-strings.md @@ -273,40 +273,6 @@ To make this easier, and if you use [zest.releaser](https://pypi.org/project/zes This script hooks into the release process and builds the MO files for you. -(translating-text-strings-installing-i18ndude-label)= - -### Installing i18ndude - -The recommended method is to have {term}`i18ndude` installed via your buildout. - -Add the following to your `buildout.cfg`: - -```cfg -parts = - ... - i18ndude - -[i18ndude] -unzip = true -recipe = zc.recipe.egg -eggs = i18ndude -``` - -After running buildout, `i18ndude` will be available in your `buildout/bin` folder. - -```console -bin/i18ndude -h -Usage: i18ndude command [options] [path | file1 file2 ...]] -``` - -You can also call it relative to your current package source folder. - -```console -server:home moo$ cd src/mfabrik.plonezohointegration/ -server:mfabrik.plonezohointegration moo$ ../../bin/i18ndude -``` - - (translating-text-strings-setting-up-folder-structure-for-finnish-and-english-label)= ### Setting up folder structure for Finnish and English From 2788a3ec1b6e2827ddfa428e6a9d2e2d5b37aabf Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 30 Nov 2025 21:45:15 -0800 Subject: [PATCH 4/4] Add some MyST markup --- docs/i18n-l10n/translating-text-strings.md | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/i18n-l10n/translating-text-strings.md b/docs/i18n-l10n/translating-text-strings.md index 0898c5c9f..6314ff3a2 100644 --- a/docs/i18n-l10n/translating-text-strings.md +++ b/docs/i18n-l10n/translating-text-strings.md @@ -34,7 +34,7 @@ Plone internally uses the UNIX standard {term}`gettext` tool to perform {term}`i The package `zope.i18n` implements several APIs related to internationalization and localization. - Follows {term}`gettext` best practices. -- Translations are stored in the `locales` folder of your application, such as `locales/fi/LC_MESSAGES/your.app.po`. +- Translations are stored in the `locales` folder of your application, such as {file}`locales/fi/LC_MESSAGES/your.app.po`. - Uses the package [`zope.i18nmessageid`](https://pypi.org/project/zope.i18nmessageid/). This provides a string-like class which allows storing the translation domain with translatable text strings. - {term}`PO file`s must usually be manually converted to binary {term}`MO file`s every time the translations are updated. @@ -62,9 +62,9 @@ If you have created your add-on or projects using [Cookieplone](https://github.c This command will call `i18ndude` under the hood using `uvx`, without you needing to install it separately. -After running that script, a new `domain.pot` file will be created in your `locales` directory where all the messages will be saved. +After running that script, a new {file}`domain.pot` file will be created in your {file}`locales` directory where all the messages will be saved. -To have those messages translated into some languages, you will need to create a language directory inside the `locales` directory, and a `LC_MESSAGES` directory inside it. +To have those messages translated into some languages, you will need to create a language directory inside the {file}`locales` directory, and a {file}`LC_MESSAGES` directory inside it. This follows the gettext standard. After doing that, the directory structure will be as follows. @@ -74,11 +74,11 @@ After doing that, the directory structure will be as follows. ./locales/ga/LC_MESSAGES/domain.po ``` -You will need to provide your translations in those `domain.po` files. +You will need to provide your translations in those {file}`domain.po` files. -If you add, update, or remove strings in your package, you will need to run only the `update.sh` script to update all language files. +If you add, update, or remove strings in your package, you will need to run only the {file}`update.sh` script to update all language files. -You also need to have the following ZCML entry to signal Plone that the files stored in the `locales` folder follow the gettext standard and that it needs to use them when requesting translated strings. +You also need to have the following ZCML entry to signal Plone that the files stored in the {file}`locales` folder follow the gettext standard and that it needs to use them when requesting translated strings. ```xml @@ -93,7 +93,7 @@ You also need to have the following ZCML entry to signal Plone that the files st You will need to declare you own `MessageFactory`. This is a callable that marks strings with a translation domain. -`MessageFactory` is usually declared in the main `__init__.py` file of your package. +`MessageFactory` is usually declared in the main {file}`__init__.py` file of your package. It is imported from wherever it is needed in your package. `_` is the standard name that is used in gettext to identify the translation function, and the previous scripts will use that assumption to identify translatable strings. @@ -159,7 +159,7 @@ It will use the text content of the element as `msgid`. Use attributes `i18n:translate`, `i18n:attributes`, and so on. For examples, look at any core Plone `.pt` files. -The `i18n:translate` attribute will {term}`hook` into the translation machinery, and will look up the corresponding translated string to the one stated there, while looking in the relevant `domain.po` file corresponding to the `i18n:domain` stated in the file and the language negotiated by Plone. +The `i18n:translate` attribute will {term}`hook` into the translation machinery, and will look up the corresponding translated string to the one stated there, while looking in the relevant {file}`domain.po` file corresponding to the `i18n:domain` stated in the file and the language negotiated by Plone. (translating-text-strings-automatically-translated-message-ids-label)= @@ -306,9 +306,9 @@ i18ndude rebuild-pot --pot locales/mydomain.pot --create your.app.package . `i18ndude` scans source `.py` and `.pt` files for translatable text strings. On some occasions this is not enough, for example, when you dynamically generate message IDs in your code. Entries which cannot be detected by an automatic code scan are called {term}`manual .po entries`. -They are managed in `locales/manual.pot`, which is merged into the generated `locales/yournamespace.app.pot` file. +They are managed in {file}`locales/manual.pot`, which is merged into the generated {file}`locales/yournamespace.app.pot` file. -Here is a sample `manual.pot` file. +Here is a sample {file}`manual.pot` file. ```po msgstr "" @@ -374,11 +374,11 @@ https://web.archive.org/web/20131018150303/http://permalink.gmane.org/gmane.comp If you need to change a translation from a PO file, you could create a new Python package and register your own PO files. -To do this, create the package and add a `locales` directory in there, along the lines of what [plone.app.locales](https://pypi.org/project/plone.app.locales/) does. +To do this, create the package and add a {file}`locales` directory in there, along the lines of what [`plone.app.locales`](https://pypi.org/project/plone.app.locales/) does. Then you can add your own translations in the language that you need. -For example, `locales/fr/LC_MESSAGES/plone.po` overrides French messages in the `plone` domain. +For example, {file}`locales/fr/LC_MESSAGES/plone.po` overrides French messages in the `plone` domain. -Reference the translation in `configure.zcml` of your package: +Reference the translation in {file}`configure.zcml` of your package: ```xml ``` -Your ZCML needs to be included *before* the one from [plone.app.locales](https://pypi.org/project/plone.app.locales/). +Your ZCML needs to be included *before* the one from [`plone.app.locales`](https://pypi.org/project/plone.app.locales/). The first translation of a `msgid` wins. To manage this, you can include the ZCML in the buildout: