Back to Blog

October 19, 2026

Odoo Strips React and Immutable.js From Its Accounting Cheat Sheets to Finally Make Them Translatable

Odoo removes React and Immutable.js from its interactive accounting and inventory cheat sheets, migrating all example content to reStructuredText so Sphinx can extract strings for translation, consolidating interactions into a single vanilla JavaScript file, and adding regression tests to prevent future translation bypasses.

Odoo’s accounting documentation has long included interactive cheat sheets — reference pages where users can click through example journal entries, see how debits and credits flow, and understand the mechanics of double-entry bookkeeping without leaving the browser. They’re genuinely useful tools, the kind of documentation that teaches by doing rather than by describing. But they’ve carried a quiet problem since the day they shipped: every label, every example value, and every explanatory string was hard-coded in JavaScript. If you read the documentation in French, German, Spanish, or any of the dozens of languages Odoo supports, you’d see perfectly translated page text surrounding stubbornly English interactive examples.

The latest update fixes this by doing something counterintuitive: it removes the React framework entirely and replaces it with plain markup and a single vanilla JavaScript file.

Before and after diagram showing the migration from React and Immutable.js with untranslatable JS-rendered labels to vanilla JavaScript with RST content that flows through the Sphinx translation pipeline

The Hidden Language Barrier in Interactive Documentation

The accounting cheat sheet and its inventory counterpart were built using React components backed by Immutable.js for state management. The architecture made sense at the time: React handled the interactive toggle behavior, Immutable.js kept the example data structures clean, and the whole thing rendered dynamically in the browser. The problem was that “rendered dynamically in the browser” meant “invisible to Sphinx.”

Odoo’s documentation runs on Sphinx, the Python-based documentation generator that powers projects from the Linux kernel to Django. Sphinx’s translation workflow is straightforward: it parses reStructuredText source files, extracts every human-readable string, and generates gettext-compatible .pot files that translators can work with. The system is mature, well-tooled, and handles thousands of pages across Odoo’s documentation without issue.

But Sphinx can only extract strings from content it can see at build time. When React renders example tables, column headers like “Debit” and “Credit,” account names like “Cash” and “Revenue,” and explanatory labels like “This entry records the sale” — all of that content exists only inside JavaScript files that Sphinx never parses. The translation pipeline sees nothing. The result: a page that looks fully translated until the user reaches the interactive section, where everything suddenly switches to English.

Why It Took This Long

The cheat sheets weren’t broken in the conventional sense. They worked perfectly for English-speaking users, which meant the translation gap only surfaced as complaints from the international community — complaints that were easy to misclassify as incomplete translation work rather than a structural limitation of the documentation build system.

There’s also a practical factor: rebuilding interactive documentation is unglamorous work. It doesn’t add features, it doesn’t fix a customer-facing bug, and it requires someone to understand both the Sphinx build pipeline and the React rendering layer well enough to migrate content without losing functionality. That combination of low urgency and cross-domain expertise meant the fix kept getting deferred.

The Fix: Move Content Back to Where Sphinx Can See It

The solution is elegantly simple. Every example table, every label, every explanatory paragraph that was previously constructed in JavaScript has been moved to the page’s reStructuredText source. The RST markup defines the content. A stylesheet handles the visual presentation. And a single vanilla JavaScript file manages the interactive behavior — toggling visibility, highlighting active examples, handling click events.

This separation follows a principle that web developers rediscover every few years: content belongs in markup, styling belongs in stylesheets, and JavaScript should handle behavior, not generate the text users read. The React architecture had collapsed all three concerns into the JavaScript layer, which was fine for rendering but catastrophic for the translation pipeline.

With the content in RST, Sphinx picks it up automatically during the next build. The gettext extraction runs, the .pot files include every example string, and translators can localize the interactive examples through exactly the same workflow they use for every other page. No special tooling, no workarounds, no second pipeline.

Two Frameworks Out, Zero Dependencies In

The migration didn’t just restructure the content — it eliminated two JavaScript dependencies entirely. React and Immutable.js are no longer loaded on the cheat sheet pages. The replacement is a single vanilla JavaScript file, loaded through the existing custom-js metadata mechanism that Sphinx already supports.

The dependency reduction matters beyond just bundle size. React requires a build step, version management, and awareness of its component lifecycle. Immutable.js adds its own API surface that developers need to understand. Vanilla JavaScript, by contrast, runs everywhere, needs no transpilation, and can be maintained by anyone who reads the documentation codebase — not just developers with React experience.

The old architecture also included several inventory-specific JavaScript files that had accumulated over time but were no longer referenced by any page. These were cleaned out as part of the migration, trimming dead code that had been silently shipped with every documentation build.

The Regression Test That Prevents a Repeat

Here’s where the fix goes beyond a one-time cleanup. The update includes a new HTML and gettext regression test that verifies two things: first, that the example strings actually appear in the gettext extraction output, confirming Sphinx can see them; and second, that the page’s JavaScript asset is correctly copied by the Sphinx build process.

The test creates a guardrail against future contributors accidentally reintroducing the same pattern. If someone adds a new interactive example by putting the content in JavaScript instead of RST, the test catches it. If the vanilla JS file fails to load, the test catches that too. It’s a small addition, but it transforms a one-time fix into a permanent constraint on the codebase.

What Translators Actually See Now

For the community translators who maintain Odoo’s documentation in dozens of languages, the change is immediately visible. The cheat sheet strings now appear in their translation tool alongside every other page’s content. Terms like account names, transaction descriptions, and instructional labels are properly segmented for translation, meaning translators can localize them individually rather than dealing with monolithic JavaScript blobs.

The accounting vocabulary is particularly important to get right in translation. “Accounts Receivable” in English becomes “Créances clients” in French, and the distinction matters for anyone learning bookkeeping through the cheat sheet. The interactive examples are supposed to bridge the gap between theory and practice, and that bridge only works when the examples speak the reader’s language.

A Pattern Worth Noticing

This change is small in scope but instructive in principle. Frameworks are tools for solving complexity, but they also introduce it. React was originally chosen for the cheat sheets because interactive content felt like a React-shaped problem — state management, dynamic rendering, component composition. The reality turned out to be simpler: the interactivity amounted to show-and-hide behavior, which vanilla JavaScript handles in a few dozen lines.

The framework didn’t just add unnecessary weight; it actively prevented a basic feature (translation) from working. The content was held hostage inside a rendering pipeline that was invisible to the rest of the documentation infrastructure. Removing the framework didn’t just simplify the code — it reconnected the content to a localization system that serves millions of users in non-English markets.

For documentation teams working with Sphinx, Docusaurus, or any other static site generator that relies on build-time string extraction, the lesson is pointed: if your interactive content renders at runtime, your translation pipeline cannot see it. The fancier the rendering, the wider the gap.

Less Framework, More Reach

The accounting cheat sheet will look the same tomorrow as it did yesterday — for English users. The difference is that it will now also look right for every other language. The interactive examples will carry translated account names, translated labels, and translated explanations, because the content finally lives where the documentation system expects to find it: in the markup.

Sometimes the best technical decision is removing the technology that’s in the way.

Ready to experience Odoo AI?

Join hundreds of teams using DearERP to customize Odoo in minutes, not weeks. Plans start at $29/month.