VIEW THIS AS

Auto mode follows the Route Engine until you choose a viewpoint.

YOU ARE HERE

ROUTE CHECK

CONNECTED TO

WHAT NEXT

Use the canonical route for this room, or HELP if you are unsure.

How People Translate Quickly | Odoo Module Translation QA: Export, Edit and Reimport PO Files Without Breaking Business Screens

Odoo module translation moves quickly when you know exactly which text belongs to a custom addon and which text belongs to the data that addon handles. People searching how to translate an Odoo module, Odoo PO translation files, Odoo export translation, or Odoo i18n import are usually trying to solve one concrete problem: make a modified business module display naturally in another language without corrupting its views, dynamic messages or upgrade path. The work starts with extracting the right source strings, not with typing into every screen that looks English.

A custom Odoo module may supply field labels, help text, selection choices, menu captions, QWeb templates, Python exceptions and JavaScript interface text. Some terms can be exported because Odoo recognises them in defined structures; others must be explicitly marked as translatable in source code. When a developer changes a label later, the translation file must be compared against the new source. A multilingual business screen can look mostly finished while a single untranslated confirmation sentence still causes a costly user mistake.

This guide owns one narrow reader job: take a custom Odoo addon from an approved source-language release through translation extraction, PO editing, importing and screen-level regression testing. It is not a primer on GNU gettext syntax in every product, not an article about translating commercial invoices as legal documents, and not a website-builder tutorial. We use Odoo’s own extraction rules and module lifecycle to explain why some translations appear, others do not, and how to verify the output after source changes.

Quick answer: translate a module as a versioned package

Identify the exact addon and Odoo version. Confirm that the target language is installed or available in the test database. Export the addon’s translatable terms using the supported Odoo translation export process. Keep the template in the module’s i18n/ directory and create or update an appropriately named target .po file. Translate message values while protecting source identities, formatting variables and technical references. Validate the PO file, load or update translations through the supported module workflow, and test the target-language interface using accounts and sample records that exercise the changed text.

Do not equate a successful PO import with a successful translation release. Odoo can accept a well-formed file while a target phrase misrepresents the action on a confirmation dialog. Conversely, an accurate message might never display because the source string was not extracted, the module was not reloaded, the installed language is different from the target, or frontend translation resources were not made available to the JavaScript component that needs them. Each failure has a distinct place in the pipeline.

Write an acceptance contract before starting: “After installing addon version V, users with locale L see accurate labels for the reservation flow, including the field, confirmation and cancellation steps; technical IDs and business decisions remain unchanged.” A tester can observe this. “Translate the app into French” gives no boundary and encourages changes in unrelated base modules. The smallest package and clearest job produce the quickest review.

The mechanism: Odoo extracts messages from some structures automatically

An Odoo addon is not one document. Its code and data definitions can contain strings of different kinds. In ordinary views, display text in supported nodes and attributes can be detected for translation. Model field descriptions such as string and help, eligible selection labels, and explicitly marked text can also enter the extraction process. In QWeb templates, designated text and attributes can be picked up unless the developer has intentionally excluded a region from translation. The precise extraction rules depend on the installed Odoo version and the type of component; consult the relevant version’s developer documentation.

What matters to a translator is the difference between visible text and extractable text. A literal written in a supported view is discoverable by Odoo’s extraction workflow. A phrase assembled at runtime from arbitrary variables may not be discoverable as a stable message. A string written into a record’s ordinary field can be business data rather than addon interface language. Editing a module’s PO file cannot substitute for a record-translation plan when the user’s actual request concerns product descriptions, CRM notes or customer-specific content.

The translation pipeline therefore has three gates. Extraction determines whether the source becomes a translation unit. Lookup determines whether the running application selects a target value. Rendering determines whether that value fits the context and means the right thing. Teams that focus only on editing msgstr values skip two gates. Teams that treat all text as database content make the opposite mistake and attempt to translate software labels in the wrong place.

Build an inventory around a single addon, not a whole database

For a useful example, imagine a custom addon named academy_visit that lets families request a campus tour. Its source interface contains “Request a visit”, “Preferred date”, “Number of visitors”, “Request received”, and “Cancel request”. A school wants French support. The addon integrates with standard Odoo scheduling and contacts, but its new labels belong to the addon. The team’s job is not to localise every menu in Odoo or rewrite a parent’s free-text remarks; it is to translate the labels and messages the addon itself introduces.

Begin by listing addon version, supported locales, visible workflows and strings that have a business consequence. Rank “Cancel request” above an informational heading because one can be mistaken for an irreversible action. Identify labels coming from views, model fields, templates and code. Where screenshots are needed, use synthetic records with fictional names and dates. Identify whether this addon is used in the backend, on a public website or both, because translation loading and frontend delivery can differ.

Draw a small state path: a user opens the form, chooses a date, saves a request, receives confirmation, revises the request, then cancels it. For each state, note the user-visible words and source location. This path gives the translation reviewer context and gives the tester a finite route to execute. A flat PO list cannot show that “Request received” is a confirmation rather than a label for the inbox that receives requests. The state map turns isolated words back into meaning.

Export a reliable template and preserve its history

Odoo’s developer documentation describes exporting translatable terms from a module and keeping the resulting PO template, usually a .pot file, within the addon’s i18n/ directory. A PO template contains source messages for translators to work from; target .po files contain translations for particular languages. The administrative menu path and development tooling can evolve, so follow the supported method in the version you deploy. A development team may use command-line export or a UI workflow according to its deployment practices.

Use a clean source checkout and a controlled test database for extraction. Record the git commit or release identifier used to produce the template. If you extract from a different addon version than the one you test, some entries may be stale or missing. A translation file that appears complete against a six-week-old template can be incomplete against yesterday’s code change. Keep the template as a source inventory, not as a translator’s creative rewrite of the source identifiers.

Do not hand-edit source strings inside the template to make them sound better. If the English interface itself is inaccurate, file a source-copy correction and regenerate the template after the developer changes the addon. Otherwise the PO entry may no longer match the lookup used at runtime. This separation can feel fussy, but it is the reason translations continue to resolve after more than one release. The source text has an owner; the target translation has an owner; the two must remain synchronised.

Read a PO entry as a source contract, not two unrelated sentences

A PO entry commonly contains source text in msgid and target text in msgstr, with comments and references that may reveal the originating module and context. The translator edits the target and pays attention to references rather than treating the file as a two-column vocabulary worksheet. Comments that appear technical may be the only available clue to whether “Draft” is a document state or a rough version, and whether “Done” means a workflow completed or a task was merely acknowledged.

An abbreviated illustrative entry could look like this:

#. module: academy_visit
msgid "Cancel request"
msgstr "Annuler la demande"

The translated French phrase is useful only if it represents the intended action. In a cancellation dialog, “Annuler la demande” may be suitable; as a navigation heading, another form could be better. The PO structure does not know that distinction. Extracted locations or addon comments help, but the translator should still request a screenshot or reachable test route for ambiguous labels. Treat the file as the transport mechanism for decisions made with real context.

When updating a target PO file, keep its original encoding, required header fields and structural conventions intact. Do not use an ordinary spreadsheet export that silently damages multiline entries, escape sequences or comments. A suitable PO editor or a controlled text workflow should preserve syntax. Parse and validate before import. A syntactically damaged catalog can prevent messages from loading, and a catalog with intact syntax can still contain the wrong business instruction. These are different reasons to reject an artifact.

Which strings need explicit marking in Python and JavaScript?

Odoo documents explicit marking for translatable literals in imperative code, including Python and JavaScript. Modern Odoo versions commonly use the environment translation method in model code, with appropriate translation helpers elsewhere. The essential rule for extraction is that the literal message template must be discoverable. A phrase built only after joining fragments or interpolating runtime values may not be extracted as one stable unit. The exporter cannot reliably harvest arbitrary program output by guessing every possible value.

Suppose a Python method builds the error message by concatenating “Visitor ”, a name and “ has no appointment”. Translators then receive two fragments that may not support natural word order in French, Arabic or Japanese. The developer should expose the whole sentence as a message with a named value, using the supported translation API and formatting approach for that Odoo release. Translators can then move the name to a grammatically appropriate position. The application inserts the value after translation. The point is not to teach one magic function name that never changes; it is to preserve a complete unit of meaning.

Front-end JavaScript has another boundary. The module’s messages must be made available to the client environment that requests them. Odoo’s translation documentation notes that front-end module translations are not automatically exposed under every circumstance and describes conventions and registration for modules that need website-side translations. If the backend shows French correctly but a public booking widget remains English, do not endlessly alter the PO values. Check whether the browser has access to that addon’s target strings under the deployed version’s mechanism.

Worked example: one action, several English source forms

Our visit addon contains a card with the heading “Request a visit”, a button labelled “Send request”, and a status after saving: “Request received”. A translator sees three uses of “request” and decides to use one target equivalent throughout. That is a good instinct for conceptual consistency, but not a command to preserve identical grammatical form. One is a noun phrase naming a screen, one is a verb phrase instructing an action, and one describes a completed event.

The team draws the sequence and records the actual state changes. On the card, the learner is invited to open a booking workflow. On the button, the user transmits information. After saving, the system acknowledges receipt but does not necessarily confirm that a visit has been approved. If the final target instead says “Your visit is confirmed”, it invents a promise that the business process has not made. That difference is more consequential than a slightly imperfect choice of article or preposition.

Translate each message against its function. Test from start to finish with a dummy request. After pressing the button, check whether the system created a draft booking, an awaiting-review item, or a confirmed appointment. Use that result to verify the target status phrase. Ask a business owner to sign off when wording conveys availability or obligation. The software may be technically perfect while the message makes the wrong commitment. Product localisation must not create liabilities through an enthusiastic synonym.

Worked example: a dynamic error message that must remain whole

The addon needs to tell a user, “The requested date {date} is unavailable.” The bracketed name here represents an illustrative formatting variable rather than exact Odoo code for every release. If a developer splits the sentence into translatable fragments around the date, the translator may be forced into unnatural syntax. Keep the entire source sentence extractable as one translation unit, and let the runtime pass the date separately through the supported formatting contract.

A good test uses dates with a day number, month name and time zone appropriate to the feature. Is the value already formatted for the user’s language before insertion? If so, the translator must not append another format. If the code produces an ISO date without local formatting, the problem is a date-presentation responsibility, not a reason to encode manual month substitutions inside translated prose. Confirm whether the business uses one operational time zone or a user’s selected time zone. The target must not imply local time when the displayed value is something else.

The reviewer checks that the dynamic value is present exactly once, that surrounding grammar remains natural, and that the message still describes unavailability rather than a hard rejection of the person’s application. A placeholder check protects structure; an end-to-end booking test protects business meaning. If a target string makes the appointment sound cancelled when it was merely unavailable to select, revise the prose. If the date is wrong, investigate the code that supplied it.

Field labels, selection values and the hidden data distinction

Odoo model fields can have display labels, help text and selection choices that are eligible for translation through defined mechanisms. Their human-readable names are not the same as database field names, model names, option keys or business rules. Suppose a selection field has technical value pending_review and visible label “Pending review”. The label can become an appropriate target-language phrase while the stored value remains the technical identifier. Translating the stored identifier as if it were prose risks breaking filters, imports, reports or automation that depend on stable values.

A help string may need more space than a label because it explains a decision. Preserve information about what a field does, especially when a user must choose whether a date is tentative, confirmed or cancelled. Never shorten the text to “Date” merely because it fits a narrow form. If layout is the problem, record a rendering defect. On the other hand, avoid adding obligations not present in the feature, such as “required by law”, unless the source and policy owner establish that claim.

Some values appearing in records are ordinary user-entered or business content; their translation requires different ownership. A parent may type a note explaining accessibility needs. That note is not a model field label and must not be silently translated or exposed through a PO export. Respect the line between module interface text and data values. It protects user privacy, prevents inaccurate mass replacement and keeps the deliverable limited to what was approved.

QWeb and templates: translation must survive structure

Odoo templates can mix static human-readable text with directives that determine layout, conditions and data insertion. A translator may see XML-like markup around a phrase and believe the easiest route is to copy the whole fragment into a new language. The safe boundary is narrower. Translate text and supported human-facing attributes while preserving directive names, structural markup and business logic. A change to a conditional expression is a programming change, not a linguistic improvement.

Imagine a confirmation view with a heading and an invoice link. The visible heading can be translated. The URL the link opens, the record identifier and the template condition controlling visibility should remain under their respective technical ownership. If the translation process works through extracted PO messages, it should not require editors to modify the QWeb source tree merely to change copy. If a string is not exported because a region is intentionally excluded, ask the developer whether that exclusion is correct rather than modifying the code without review.

Test templates in the browser with the target locale, including empty states and different screen widths. A long phrase may wrap into two lines or hide a button. The right fix could be a CSS or template layout adjustment; arbitrarily truncating the translation may change meaning. If the same snippet is included in several pages, test at least two representative placements. Successful extraction and import only show that the translated value reached the application; they do not prove that the layout is usable.

The install-and-update boundary: why old translations persist

Odoo loads language data in relation to installed modules and languages. The developer documentation explains that translation files in an addon’s i18n/ directory are associated with the module and that module installation or update can load translations for applicable installed languages. However, deployed databases also have their own language data and import state. After changing a PO file in source control, simply reloading a browser tab may not refresh every translated value. Confirm the supported update or import mechanism for your Odoo version and environment.

Do not immediately overwrite a production language database because a new file exists. Check the chosen import mode and whether existing user-maintained translations should be preserved or replaced. Determine which locale code the file and target database are using. If you imported French for France while your test user is configured for another French regional locale, your assumption about the lookup path may be wrong. Observe the actual installed language configuration instead of relying on the filename you expected to use.

Keep a deployment log with source addon version, PO file revision, database used for validation, load/import action and test account language. If a customer reports that one screen reverted to English, this record makes it possible to distinguish a missing entry from an import that never reached the environment. Speed comes from reproducibility. Without a release baseline, teams waste time comparing screenshots from different code, database and language versions as though they were one product.

Source changes: how to update a translation without losing intent

After version 1, the addon developer changes “Request received” to “Request submitted for review”. This is not cosmetic: the new source makes clear that submission is not confirmation. If the target translation remains associated with the old message, translators may not see the changed meaning without an extraction update. Regenerate the template from the current source and compare new, changed and obsolete entries. Review the previous target as a suggestion, not automatic proof of equivalence.

A safe workflow begins by reviewing the source change log: Was a button renamed for clarity? Did its action change? Was a new approval state introduced? Then update translation catalogs using a PO-aware method that preserves legitimate work while exposing changed and missing source entries. A former translation for “Request received” may be reusable after adjustment, but the reviewer must restore the explicit “for review” concept. Blindly copying old msgstr values into new keys can create an attractive yet false target.

When an old message disappears from the template, do not invent a new page where it might appear. It may have been removed, split, replaced or relocated. Confirm with the addon owner and test the current build. After reconciling the catalog, import or update translations in the test database and revisit the precise screens affected by the source change. This targeted regression is quicker than rereading every unchanged menu and more reliable than assuming updated PO counts equal completed coverage.

Translation memory helps only after you prove two strings are equivalent

Teams with a large portfolio of addons often have translation memory or a glossary from previous projects. These resources can reduce typing and maintain product vocabulary. They cannot tell you whether a source string has changed operational meaning. The English “Post” in an accounting screen is not the same as “Post” in a social feed. “Reconcile” in finance is not merely “make friends again”. “Draft” in an order workflow is a status, not a writing exercise.

Use a previous target as a candidate only after checking its object, function and state. If two labels share a source phrase but refer to different businesses processes, create contextual notes instead of forcing one translation across them. A glossary should define concepts, not just prescribe a replacement for every word. It should say, for example, that “confirm” means committing a workflow state at this step, while “validate” may mean checking an input without confirming the entire transaction.

For repeated messages inside the same addon, maintain consistency where it helps users recognise the same action. When UI text requires different grammatical form, preserve meaning over exact lexical repetition. A button can use an imperative while a status uses a past participle. That is not inconsistency; it is functional grammar. The quickest translation is not the one with fewest distinct target phrases, but the one reviewers can verify without reinterpretation.

High-risk business terms need a consequence check

Odoo is used for real business processes. An interface translation can influence actions related to orders, invoices, stock, appointments and approvals. Those verbs may indicate a state change that is not obvious from the word alone. Translate “Post”, “Validate”, “Confirm”, “Cancel”, “Refund” and similar actions only after the module owner explains their actual effect in the configured workflow. The same term can have different consequences in different apps or customisations.

Consider a confirmation dialog that offers “Cancel” beside “Confirm”. The word “Cancel” may dismiss the dialog without cancelling the underlying order, or it may be the action that cancels the order itself. The translator needs to see the surrounding heading and control outcome. If the UI uses identical English words for both functions, a source-copy improvement may be needed. Inventing two target strings while leaving their keys unresolved can confuse users and break consistency during the next update.

Maintain a consequence column for high-risk keys: no data change, reversible state change, externally visible action, or potentially irreversible action. This classification informs review depth. A decorative icon label needs visual checking; a payment-affecting action may require business sign-off and automated tests. The article does not offer legal or financial advice. It gives a way for language editors to know when a wording choice requires an operational expert.

Diagnosing “the translation imported but nothing changed”

Use a decision tree. First, does the PO file contain a target entry for the exact source message generated by the current addon version? If no, fix extraction or translation before investigating the runtime. Second, is the target language actually installed and selected for the test user? If no, correct that configuration. Third, was the file loaded into the database or module lifecycle you are viewing? A browser pointed at staging cannot prove a production import happened, and a source repository change cannot prove a database refresh.

Fourth, is the text rendered by the expected layer? A backend form and a website widget can use different translation paths. Fifth, is the phrase part of a custom addon or the Odoo base application? Sixth, is it sourced from a field, template, code message or business record value? Seventh, did another customisation or manual database translation take precedence? Each question narrows the search. Repeatedly changing accents or synonyms in msgstr will not fix a string that never resolves to that entry.

If the target partly appears, check whether only some variants or screens were covered by the extracted template. For example, a success message may be marked correctly while an error branch is assembled without translation markers. Reproduce both branches with synthetic records. When a problem only occurs in production, compare addon version, installed language, translated artifact and relevant view updates before assuming a mysterious caching failure. Observed differences are better evidence than guesses.

A release test matrix for the sample visit addon

Make a short table of states and expectations. Open a new request: the form title and date field should be natural in the target language. Submit a valid request: the button and response should distinguish submission from approval. Leave a required value empty: the error message should describe the missing input and display any dynamic field reference correctly. Request an unavailable slot: the date and explanation should be clear. Cancel the request: the dialog should say whether the request is being cancelled or merely the dialog is closing.

Now add variation: a long visitor name, a record with accented characters, a small mobile screen, a user with another locale, and a role that cannot approve bookings. Confirm that language does not affect permissions. The current user may see a translated button, but the underlying security and state transitions must remain those configured for that role. If an error branch appears only when a rule denies access, test with a permitted dummy account as well as an appropriately restricted one.

A translated screen passes only when text, data and outcome agree. Record each observation with the addon version and target language. If you discover a system bug, separate it from a translation mistake. One test case can reveal both, but remediation owners differ. A release should not be marked “language complete” solely because the PO file has no blank msgstr values: that statistic says little about unreachable messages, runtime formatting or terminology under real decisions.

Useful automated checks, and their limits

A PO-aware parser can detect malformed headers, unbalanced quoting and certain syntax problems. A placeholder comparison can flag target entries that have lost required formatting parameters. A diff against the current template can identify missing and stale messages. A CI job can report unexpected changes in the addon language directory and require the generated files to be committed together. These are valuable guards because they detect mechanical faults faster than a person reading thousands of entries.

Automation cannot reliably infer whether a target sentence overpromises an appointment, mislabels a financial state, or addresses a learner too formally for the setting. It may also misclassify legitimate grammatical differences across languages. Use checks as gates and clues, not as a substitute for reviewing the displayed screen. Prioritise messages by consequence and ambiguity, and reserve specialist time for those that cannot be judged from the PO text alone.

Avoid building a custom checker whose assumptions contradict Odoo’s current file format or extraction rules. Start with official tools and a known-good package. If a third-party CAT tool is part of the workflow, test a small round trip first: export a file, translate representative entries, import it and exercise the screen. A large project should never discover on release day that its translation platform silently altered comments or line formatting needed by the import process.

Managing several locales without drowning in parallel copies

Translate one stable source release into multiple target locales rather than asking each language team to extract its own source snapshot. Share source context and reference screenshots so “Request received” is understood consistently across languages. Let each target language use natural grammar; do not use the first finished translation as the meaning source for the next language unless the project has explicitly designed a relay-translation workflow with expert checks.

Use an issue register keyed by addon version and message identity. A French reviewer may report that the confirmation state is ambiguous; that report can reveal a source-copy problem affecting every language. The developer should clarify the English source and regenerate the template, after which all affected targets are reviewed. Do not bury product problems inside one country’s translation. The system should let a semantic discovery travel back to source ownership.

Schedule imports and test routes so that different target-language artifacts can be verified against the same code and database baseline. Do not compare French in staging with German in an older production module and conclude that their translation quality differs. Record the actual configurations. A repeatable fixture with fake visits and scripted workflow states can save hours of manual setup while keeping real customer records out of localisation tests.

What a responsible handoff includes

The translator should receive the exact PO or template files, the addon version, source notes, target locale, protected-formatting guidance, screenshots or an accessible test environment, and a list of consequential actions. The developer should receive the completed target files, list of unresolved source questions and any code-level defects preventing extraction. The QA reviewer should receive the acceptance contract, state path and reproducible fixture data. The release owner should receive validation results and a rollback route.

Keep an explicit unresolved-questions field. If nobody can explain whether “Cancel request” revokes an approved visit, mark it as blocked rather than confidently choosing a target and hoping the button’s behaviour agrees. The answer may require inspecting the actual custom business logic. A translator should not decide business policy through the back door of interface copy. That caution is particularly important when a custom addon has modified standard Odoo actions or reused standard-looking terms for a different outcome.

A clean handoff is short enough to act on. It does not need a hundred-page specification for five labels, but it must contain enough context that the next person can reproduce the task. A file with msgstr lines and no source release is not a complete deliverable. A translated screen with no retained target catalog is not maintainable. Reproducibility is the practical form of speed over successive module upgrades.

A small revision drill for a development team

Choose a harmless label in a test addon and export the current template. Translate it for one installed language, load the target and confirm the displayed value. Then change the English source label in the addon code or view, regenerate the template, and inspect what changed in the catalog. Do not jump straight to renaming the target entry. Ask whether the new source is semantically equivalent or reflects a changed process. Write down the evidence that supports your decision.

Next, add a message with a dynamic value and ensure the template extracts the whole meaningful sentence. Test two different values in the target language. Add one error branch that is rarely reached in the normal flow and make it reachable with synthetic data. Finally, move the same code to a staging database with a different installed locale and check whether translations actually load there. These small exercises expose the main handoff failures before they reach a large project.

The point is not to memorise every detail of Odoo’s APIs. It is to understand the invariant workflow: stable source, extractable units, protected variables, target files, controlled import, real business-state test, and recorded result. Once the team knows where language stops and executable business logic begins, translation becomes faster without becoming reckless.

Transfer: the difference between interface translation and business truth

The same distinction appears in ERP, CRM and learning software: translation can change how a user understands a control, but it must not silently change what the control does. A status phrase is a claim about the system’s state. A button is a promise about an action. A field label is a contract between a stored value and a human interpretation. Software localisation must preserve those relationships, even when a shorter or smoother word seems tempting.

Odoo adds its own practical details: implicit extraction from views and fields, explicit marking for code messages, PO catalogs in addon directories, versioned module updates, and frontend delivery boundaries. These are not generic tips pasted onto a new product name. They define the exact places where a correct target value can be lost or misapplied. A reliable release method tests those places rather than counting translated words in isolation.

Related eduKateSG guides cover broader checks: gettext PO and POT translation QA owns general catalog syntax, localization build validation covers resource compilation and release gates, and ICU MessageFormat plurals and selects handles that specialised pattern system. This article does not repeat those jobs. It owns the source-to-addon-to-business-screen translation lifecycle in Odoo.

Frequently asked questions

How do I translate my own Odoo module rather than all of Odoo?

Identify the addon, extract its translatable strings using the supported workflow for your installed Odoo version, create or update a target PO file in the module’s language directory, load that translation into a test database, and verify the addon’s screens. Do not expand the scope to other apps unless they own part of your workflow and the project includes them.

What is the difference between .pot and .po in an Odoo addon?

A POT file is a source-message template for translators; a PO file carries translations for a target language. Keep both aligned with the code release. Editing source message identities in a target file without regenerating extraction can prevent the application from resolving the intended translation.

Why did an Odoo label not appear in my export?

Check where it originates. Some view and field text is implicitly extractable, while messages assembled in imperative code need explicit marking. The label might instead be a database record value or originate from another addon. Investigate the source before hand-adding an entry that Odoo may never request.

Can I translate a technical field name or selection key?

Not as a normal localisation edit. Human-facing labels can be translated where supported; technical identifiers and stored values have programming and data responsibilities. Changing those may break integrations, reports or rules. A code or schema change requires separate engineering review.

Why is the backend in French but a website widget still in English?

Confirm that the widget’s messages belong to the expected addon and that its frontend translation resources are available under your deployed Odoo version. The official documentation distinguishes frontend exposure from ordinary backend translation behaviour. Do not assume that a backend PO import automatically populates every JavaScript client.

Will changing the PO file immediately change production?

Not necessarily. The deployed environment may need a supported import or module translation update. Check source checkout, file revision, database, installed language and user locale. Test the delivered artifact, not merely the edited file on a workstation.

Should translators keep placeholder syntax in dynamic messages?

Yes. Protect argument identities and formatting syntax while translating the complete message around them. Ask the developer what values are inserted and test several representative values. Whole-message translation is usually safer than concatenating separately translated fragments.

Can translation memory handle all repeated Odoo labels automatically?

No. Reuse approved terms where the business action and context match, but do not treat identical English words as identical workflow meanings. In finance, inventory and approvals, a small semantic shift can change what users believe will happen when they click.

How do we update translations after a module release changes source text?

Regenerate a template from the new code, compare changed or obsolete messages, review existing targets against current behaviour, update the PO catalogs and test affected routes after importing. Copying an old translation into a changed source entry without review can preserve yesterday’s wrong promise.

What is the minimum useful acceptance test?

One complete workflow in the target language, including a normal success state, one error state, a dynamic value and the most consequential action. Record the addon and database versions, the test user’s language and the resulting screen. Expand coverage for financial, contractual or irreversible actions.

Summary: the PO file is a bridge, not the finished business interface

Fast Odoo module translation begins with a stable addon release, complete extraction and clear ownership. Translate messages as context-aware units, protect technical variables and identifiers, keep PO catalogs aligned with their source, load them through the supported environment, and verify business-screen outcomes. Review high-risk actions with someone who understands the workflow. A correctly parsed file is necessary but not sufficient; the translated application must still tell users the truth about what their actions will do.

Official technical references

Use the Odoo 19.0 Translating Modules developer guide, the official 18.0 Translating Modules guide, and the Odoo 19.0 website theme translations guide when frontend resources are involved. Documentation paths and interfaces change by version, so follow the version that matches your environment. The academy_visit example is an invented teaching case and does not represent a real Odoo addon.

Discover more from eduKate Singapore

Subscribe now to keep reading and get access to the full archive.

Continue reading