Translating a website into ten, twenty or forty languages is quickly done with a single AI. The harder question is whether you can trust the result. A single language model occasionally invents words, translates product names or changes a number, and does not notice it itself. We have therefore written a module for Odoo 19 in which several AIs and translation services work on the same text, rate each other's results anonymously and agree on the wording that sounds both accurate and natural. Anything that is not clear-cut is left to a human to decide.
The module is called ai_translation_consensus and is available as free software under the AGPL-3 licence on GitHub:
github.com/Alex0176/odoo-ai-translation-consensus
Contents of this article
The idea: cross-checking instead of trust
The module can do two things:
- Translating: add missing (or outdated) translations of every translatable field in Odoo, that is, blog posts, web pages, menus, products and everything else that Odoo stores in several languages. The AIs see not only the individual sentence but the neighbouring blocks and an excerpt of the whole page. This way individual words are understood in the right context.
- Proofreading: check the text in its own language and suggest better wording or corrections. The original is always one of the candidates. If the original wins, nothing is changed.
The core is mutual checking. Every AI is good at judging other people's texts, even if it occasionally gets things wrong itself. The module makes use of this: several providers each write a version, and the same providers then rate all versions without knowing who they come from. A provider does not rate its own version.
How a suggestion comes about
- Translating. Each translator writes a version in parallel.
- Fixed checks. Without AI, it is checked whether HTML tags, entities, placeholders such as
%sor{}, numbers and links have remained unchanged. A version that violates this can never win, however fluent it sounds. - Rating. The remaining versions are shuffled and anonymised. Each reviewer gives each one a score for accuracy and for naturalness (1 to 10), names a favourite and can suggest an improvement.
- Agreeing. The rank of a version is 0.5 × average score + 5 × share of favourite votes. Agreement is reached if the best version has at least 60 % of the favourite votes and an average score of at least 7.0.
- Second round. Without agreement, the best versions, together with the reviewers' improvement suggestions, go into the rating once more.
- Human. If it is still not clear-cut even then, the suggestion waits for a decision.
If there are only pure translation services without a review function (for example DeepL), a result counts as agreed only if at least two services have delivered exactly the same text. For proofreading, the results must remain recognisably similar to the original (similarity of at least 0.6, same numbers). Small free models occasionally answer a batch with shifted or foreign texts. Such answers are discarded rather than voted on. A glossary records brand names and fixed terms.
Providers: with and without a key
Free and paid services can sit in the same vote. The module comes with presets for many providers; all are switched off after installation.
| Type | Translates | Reviews / corrects | Examples |
|---|---|---|---|
| OpenAI-compatible interface | yes | yes | OpenAI, Mistral, DeepSeek, xAI, Groq, Together, OpenRouter, Cerebras, Qwen, Moonshot, GitHub Models, Hugging Face, Ollama, LM Studio, vLLM, llama.cpp |
| OpenAI-compatible without key | yes | yes | Ollama on your own server, Pollinations |
| Anthropic | yes | yes | Claude |
| Google Gemini, Cohere | yes | yes | |
| Local command | yes | yes | claude -p or any program that reads from stdin and outputs the answer |
| Translation services | yes | no | DeepL, Google Translate, Azure Translator, LibreTranslate, MyMemory, Lingva |
You enter the key (or the name of an environment variable that contains it), press Test connection and switch the provider on. The model names in the presets are starting points; if you use them, you should compare them with the provider's current list. With two or more providers there is a genuine cross-check; with only one, nobody checks its work. The wizard points this out.
An entire website at once
A start wizard (menu AI translation → Start here) explains the steps and creates the first rule. If the module website is installed, the bridge module ai_translation_consensus_website comes along automatically. It adds the scope “An entire website with everything on it”: you choose the website and have the content suggested. The module looks at all models with translatable fields that belong to the website (pages, menus, blogs, products, events, forums, courses and more) and proposes one rule per content type, with the website's languages as the target.
- What is not installed (forums, courses, galleries) does not appear and will be included later as soon as it is installed.
- Shop models are only suggested if the website has a shop. Only published records are captured.
- Contacts, companies, payment providers, pricelists, delivery methods, loyalty programmes and snippet filters are deliberately not offered by the module.
- The address names of the pages (
seo_name) are not translated. - Types you do not want can be removed before creating.
Creating and searching cost nothing: the rule only lists which texts need work. Only when processing are providers called and costs incurred.
Dashboard, costs and automatic start
For each rule, the dashboard shows how many texts are finished, waiting for confirmation or a human, queued or failed. In addition there is the breakdown by language and provider, the costs so far and those still to be expected, the estimated remaining time and the switch for scheduled processing.
The numbers in this figure are sample data and say nothing about real costs.
- Costs are calculated from what the providers actually report: tokens (OpenAI, Anthropic, Gemini, Cohere) or characters (DeepL, Google, Azure). Tokens are always shown, money only if you have entered the price per million tokens (or characters) for the provider. The presets contain no prices, because these change. Services that do not report tokens are estimated from the text length and marked as an estimate.
- Forecast: average cost and working time per text multiplied by the number of queued texts. This is an estimate that improves with the first batches.
- Automatic start: rules with the option Start by itself when a record changes search, on each run of the scheduled action, only for records changed since the last search run. With the scheduled action switched on, an edited website is therefore translated again without any manual steps.
- Completion message: When the last open text of a rule is done, the message “All languages translated” (“All texts checked” during proofreading) appears once in the AI Translation channel.
Approval by humans
By default, the module writes nothing to your records without your consent. Each suggestion shows the versions, who wrote them, the scores and the reviewers’ comments. You can accept the suggestion, choose a different version, type in your own wording or reject it.
The text and the provider names in this image are entirely fictitious and serve only to illustrate the view.
If you trust a rule, you can switch on Apply agreement automatically. Suggestions without agreement still wait for a human, even then. When applying, the module checks once more whether the source text has changed in the meantime, re-runs the markup checks and writes without tracking and without notifying followers.
Security and data protection
- Everything is off after installation. Providers and the scheduled action are deactivated. Nothing is sent without your action.
- Texts leave your server as soon as a hosted service is involved. A rule can be marked Confidential; in that case only providers flagged as running on your own infrastructure see the text.
- Keys are stored in a field that only administrators can see, or in an environment variable that is referenced by name only. In error messages they are masked, and they are sent in headers. Exception: the optional MyMemory key can only be passed there as a query parameter.
- Local command runs a program and is therefore blocked until the system parameter
ai_translation_consensus.allow_commandis set toTrue. The command is called without a shell and runs in an empty temporary directory. - Prompt injection: The requests mark the text as data. Instructions within the translated text are not followed, and a result that violates tags or placeholders is discarded.
- Free services have limits. Pollinations allows one response per 45 seconds anonymously. The provider option
min_intervalkeeps to that interval, and “Please try again later” responses are respected.
Installation
git clone https://github.com/Alex0176/odoo-ai-translation-consensus.git
ln -s /pfad/odoo-ai-translation-consensus/ai_translation_consensus /pfad/addons/
ln -s /pfad/odoo-ai-translation-consensus/ai_translation_consensus_website /pfad/addons/
odoo-bin -c odoo.conf -d <datenbank> -i ai_translation_consensus --stop-after-init
Odoo 19 and the Python package requests are required. A German translation is included. The bridge module ai_translation_consensus_website is installed automatically if website is present. After installation, the Odoo service must be restarted because the module contains Python code. If you run a production system, install the module on a copy of the database first.
The first steps: open the menu AI Translation → Providers, test and switch on the services, then Start here and create the first rule. Search for texts generates the suggestions, and Process a batch calls the providers. Start with a small rule, such as a single blog post and two languages, and look at the result and the costs before you queue an entire website.
Limits
- Quality depends on the models you switch on. Cross-checking reduces the errors of individual models, but it is no guarantee. For legally or safety-critical texts, the module is no substitute for a native speaker.
- Costs grow quickly. One text costs one call per translator, one review call per reviewer and, with a split vote, a second round. Page context increases the input of every call. A rule with 45 target languages multiplies the number of texts. Limit the runs with Records per search run, New suggestions per search run and Suggestions per cron run, and add inexpensive or local models as reviewers.
- Only fields with
translate=True. Formatted text is processed block by block (Odoo’s term mechanism). - Prices and model names change. The default settings are not a maintained price list.
- Built for Odoo 19.0 Community. Other versions are not supported.
Frequently asked questions
Is anything translated or overwritten without my consent?
No, as long as you do not switch on Apply agreement automatically. Even then, only suggestions with agreement are written. The providers and the scheduled action are off after installation.
Do I need keys for paid providers?
Only for the providers that require one. With Pollinations, MyMemory or a locally operated model (for example Ollama) you can do without. Free services are often limited and slow; for an entire website they are usually only suitable as a supplement.
What does a translation cost?
That depends on the provider, model, text length and number of languages, so the module does not specify fixed figures. The dashboard shows usage and costs once you have entered the prices, and estimates the remaining costs of the queued texts.
Can I keep texts confidential?
Yes, with the rule option Confidential. Then only providers that are marked as running on your own infrastructure work on them, such as a local Ollama.
Does this replace Odoo’s own translation?
No. The module uses Odoo’s multilingual capability and writes to the same translations that you would otherwise maintain by hand.
Under which licence is it released?
Under the AGPL-3. Bug reports and improvements are welcome as an issue in the GitHub repository .
Support from Biricon IT Services
We support Odoo installations for small and medium-sized businesses: from implementation through customisations and migrations to ongoing operation. If you run your Odoo website in several languages, want to safeguard translations with AI or want to bring a module safely into your production instance, we will be happy to help. Further in-house developments: Archive a company together with portal users, Document numbers from prefix, year and counter and Firmenbuch and address validation for Austrian customers.
As of 3 November 2026. Module version 19.0.1.0.0. The images show fictitious sample data.