Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

collective.translators

This package extends plone.app.multilingual with pluggable external translation utilities for automatic content translation in Plone. It integrates several translation providers, so you can configure DeepL, AWS Translate, LibreTranslate, DeepSeek, Ollama, or ChatGPT and use them to translate your content.

This add-on requires plone.app.multilingual PR #468. No released version of plone.app.multilingual provides the IExternalTranslationService interface yet.

Translation services

Each service registers a named utility that provides IExternalTranslationService. The utilities share the same interface for translating content and for reporting the languages they support, so you can switch between providers without changing anything else.

Configure each service from its own control panel.

Google Translate is not part of this package. plone.app.multilingual already ships it, and you configure it with the Google API key in the Languages site setup.

Service Utility name Factory
AWS Translate aws_translate AWSTranslatorFactory
ChatGPT chatgpt_translate ChatGPTFactory
DeepL deepl_translate DeeplTranslatorFactory
DeepSeek deepseek DeepSeekFactory
LibreTranslate libretranslate_translate LibreTranslateTranslatorFactory
Ollama ollama OllamaFactory

AWS Translate

Uses Amazon AWS Translate. Reads the credentials and the region from the Plone registry. Falls back to language autodetection when the source language is unknown.

ChatGPT

Uses the OpenAI API. Reads the credentials from the Plone registry.

DeepL

Uses the DeepL API, on either the Free or the Pro endpoint. Reads the API key from the Plone registry. Detects the source language on request, and translates both text and HTML.

DeepSeek

Uses DeepSeek, a translation API backed by a large language model. Reads the API key from the Plone registry. Translates through chat completions.

LibreTranslate

Uses an open source LibreTranslate server. You set the server URL and the API key. Detects the source language on request, and translates both text and HTML.

Ollama

Uses an Ollama server, so the models run on your own hardware. You set the server URL and the model. Use this service for private or offline translation.

Installation

Add collective.translators to the dependencies of your project.

LibreTranslate works out of the box, because it only needs HTTP requests. The other services need a client library, which you pull in through an extra:

collective.translators[deepl]
collective.translators[deepl,aws]

Add-ons control panel

Every translation service ships its own install and uninstall profile, and appears as a separate entry in the add-ons control panel.

Add-on Extra it needs
Collective Translators: AWS Translate collective.translators[aws]
Collective Translators: ChatGPT collective.translators[chatgpt]
Collective Translators: DeepL collective.translators[deepl]
Collective Translators: DeepSeek collective.translators[deepseek]
Collective Translators: LibreTranslate none
Collective Translators: Ollama collective.translators[ollama]

An entry appears only when the library it needs is importable. A control panel therefore never points at a service that your site cannot use.

Installing any service also installs the shared collective.translators:default profile as a dependency. That profile holds no configuration of its own, so it stays out of the list while it has nothing to offer. It appears as Collective Translators: shared base only while an upgrade of the add-on is waiting to run, because the control panel reaches the upgrade steps of a product only through a profile it lists.

Upgrade from 1.0.0a2 or older

Older versions installed every service from a single profile. To migrate a site, open /prefs_install_products_form and run the upgrade that Collective Translators offers there. The same step is also available from /portal_setup/manage_upgrades, under the collective.translators:default profile.

The upgrade keeps the settings of the services whose library you installed, API keys included. It removes the leftover registry records and configlets of the other services. Install those services again from the add-ons control panel once you add their library.

Add a new service

Contribute a new translation service in either of two ways:

  • Open a pull request against this package, following the structure below.
  • Publish a separate Plone add-on that provides an external translation utility with the same interface and the same registration pattern.

Read the code of an existing service, such as DeepL or LibreTranslate, for a concrete example of every file below.

1. Implement and register the utility

Your utility class must implement IExternalTranslationService from plone.app.multilingual.interfaces, with at least these methods:

  • is_available() returns True when the service is enabled and ready.
  • available_languages() returns the supported language codes, or the supported source and target pairs.
  • translate_content(content, source_language, target_language) translates the content and returns the translated text.

Register a module level instance of the class in mytool/configure.zcml:

<utility
    provides="plone.app.multilingual.interfaces.IExternalTranslationService"
    name="your_tool_name"
    component=".utility.YourTranslator"
    />

2. Include the package

Add the include to src/collective/translators/configure.zcml. Guard it with a zcml:condition when your service needs a client library:

<include
    package=".mytool"
    zcml:condition="installed yourlibrary"
    />

3. Add a control panel

This step is optional. Skip it when your service needs no configuration.

Write the registry schema and the control panel form in mytool/controlpanel.py, then register the browser page and the plone.restapi adapter in mytool/configure.zcml. Give the adapter a configlet_id that matches the action_id of the configlet, otherwise plone.restapi leaves your panel out of @controlpanels.

Declare a browser layer that extends collective.translators.interfaces.IBrowserLayer in mytool/interfaces.py, and bind the browser page to that layer.

4. Ship an install and an uninstall profile

Register both profiles in mytool/profiles.zcml, and include that file from mytool/configure.zcml. The profiles then exist only when the ZCML of your service loads, which is what hides the add-on when the library is missing.

<genericsetup:registerProfile
    name="default"
    title="Collective Translators: My Tool"
    provides="Products.GenericSetup.interfaces.EXTENSION"
    directory="profiles/default"
    />

Put metadata.xml, browserlayer.xml, registry.xml, and controlpanel.xml in mytool/profiles/default/. Make metadata.xml depend on profile-collective.translators:default.

Put browserlayer.xml, registry.xml, and controlpanel.xml in mytool/profiles/uninstall/, each one with remove="true".

Add the name of your service to collective.translators.setuphandlers.SERVICES, so that its uninstall profile stays hidden from the add-ons control panel.

5. Test the service

Restart your site. Install your add-on from the add-ons control panel. Open the control panel of your service, enter your API key or your settings, and translate a page.

Contribute

License

GPL version 2.

Changelog

1.0.0a2 (2026-10-01)

Breaking changes

  • Remove the Google Translate service, with its profile and control panel. The 1002 upgrade step cleans its registry records and configlet from existing sites.
  • Split the single GenericSetup profile into one install and one uninstall profile per translation service. Each service is now a separate entry in the add-ons control panel, shown only when the library it needs is importable. The shared collective.translators:default profile is hidden and installed as a dependency, and it no longer registers a browser layer of its own: every service registers a layer extending collective.translators.interfaces.IBrowserLayer. Existing sites are migrated by the upgrade step to profile version 1001, which keeps the settings of the available services and removes the leftovers of the others. [mamico]

Bug fixes

  • Align configlet_id with the action_id of the configlet for AWS Translate, ChatGPT, DeepL, DeepSeek, LibreTranslate and Ollama, so the panels are listed by the @controlpanels endpoint of plone.restapi. [mamico]
  • Register the missing control panel configlet for Ollama. [mamico]
  • Show the collective.translators:default profile in the add-ons control panel while it has upgrade steps to run, and hide it the rest of the time. The control panel drops a hidden profile before it builds the entry of its product, so a permanently hidden base profile kept its upgrade steps out of /prefs_install_products_form, and those steps are the migration path of the sites installed with the single profile of 1.0.0a2 and older. Keying the decision on pending upgrades rather than on one version number keeps later migrations reachable as well. The uninstall profiles stay hidden at all times. [mamico]

Internal

  • Move package metadata from setup.py to pyproject.toml @plone
  • Require Manage portal for every control panel view. DeepSeek, Google Translate and LibreTranslate used to require plone.app.controlpanel.Language, while their configlet already required Manage portal. [mamico]

Tests

  • Run the test suite with pytest instead of zope-testrunner, and declare pytest, pytest-cov and pytest-plone in the test extra. Add coverage of the per service profiles and of the upgrade step. [mamico]
  • Run the tests in CI against the plone.app.multilingual branch that provides IExternalTranslationService, checked out by mxdev from tox -e init, and move the constraints to the Plone 6.2 set the test matrix already names. Without it the ZCML of the add-on cannot be loaded at all against a released plone.app.multilingual. [mamico]

1.0.0a1 (2026-08-24)

Bug fixes:

  • Fixed the issue related to not yet installed package. [mamico]

1.0.0a0 (2026-08-17)

Internal:

  • Update configuration files @plone

100.0.0 (2025-05-11)

No significant changes.

1.0.0 (2025-05-11)

No significant changes.

Metadata

Release files for collective.translators 1.0.0a2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for collective.translators 1.0.0a2
File Size Uploaded
collective_translators-1.0.0a2.tar.gz 53.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for collective.translators 1.0.0a2
File Interpreter ABI Platform
collective_translators-1.0.0a2-py3-none-any.whl Python 3 none any Details

Total release size: 125.3 kB

Release files / collective_translators-1.0.0a2.tar.gz

Download URL collective_translators-1.0.0a2.tar.gz
Size 53.2 kB
Tags Source
SHA-256 checksum
How to use checksums
8c78ec765075cb68a8ccf45e83a8760f38e7f754c9378d4e494889ef69879317
BLAKE2b-256 checksum
How to use checksums
ac33dc52f10fb85c466a24018234781957cc52aeeb9be5612f33372f508affc3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.14

Release files / collective_translators-1.0.0a2-py3-none-any.whl

Download URL collective_translators-1.0.0a2-py3-none-any.whl
Size 72.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0dbea4edb5e1b5666a25fc628d45a459e62193cb72824a797a8a08696dfda4f6
BLAKE2b-256 checksum
How to use checksums
4c3f6791c42f1cb37c63126c056f3ba93e58acced1483ef6aee0dbf8f698024e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.14
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page