Skip to content

add i18n support#6796

Open
benedikt-bartscher wants to merge 17 commits into
reflex-dev:mainfrom
benedikt-bartscher:add-i18n
Open

add i18n support#6796
benedikt-bartscher wants to merge 17 commits into
reflex-dev:mainfrom
benedikt-bartscher:add-i18n

Conversation

@benedikt-bartscher

@benedikt-bartscher benedikt-bartscher commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

closes #2339

@codspeed-hq

codspeed-hq Bot commented Jul 17, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 26 untouched benchmarks
⏩ 8 skipped benchmarks1


Comparing benedikt-bartscher:add-i18n (e8459f4) with main (f79d011)2

Open in CodSpeed

Footnotes

  1. 8 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (e54bc83) during the generation of this report, so f79d011 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a complete reflex-i18n package implementing internationalization for Reflex apps — covering static component translation (rx.t), server-side dynamic translation (gettext/ngettext/pgettext), locale-aware number/date formatting for both client and server, Accept-Language negotiation, a per-event locale scope mechanism in reflex-base, and a reflex i18n CLI for managing .po catalogs.

  • Adds reflex-i18n as a standalone installable package with I18nPlugin, I18nState (cookie-backed locale, server-side negotiation), rx.t (client-side via catalog JS modules), and format_* helpers using Babel/Intl.
  • Extends reflex-base with a generic EventScopeProvider protocol and implicit computed-var dependency tracking via bytecode introspection, both of which are broadly useful beyond i18n.
  • Patches reflex/state.py hot-reload logic to purge stale cross-state dependency edges when states are removed, fixing a crash triggered when a translated computed var depends on a reloaded state module.

Confidence Score: 5/5

Safe to merge — no correctness bugs in the core translation or event-scope paths; all previous review concerns have been addressed in this revision.

The event-scope cleanup, q=0 Accept-Language exclusion, conditional Secure cookie attribute, catalog load error handling, set_locale lazy-loader mapping, and CLI add_command guard are all correctly implemented. The remaining findings are a Decimal-to-float precision loss in the compact number format branch and the translation cache not being wired into hot reload — both are minor developer-experience limitations rather than correctness issues.

runtime.py — compact format branch converts Decimal to float and the translation cache has no hot-reload integration.

Important Files Changed

Filename Overview
packages/reflex-i18n/src/reflex_i18n/runtime.py Server-side translation and formatting runtime; locale contextvar, gettext helpers, Babel number/date formatting, and negotiate_locale. One minor inconsistency: the compact branch of format_number converts Decimal to float, silently losing precision.
packages/reflex-base/src/reflex_base/event/processor/scope.py New per-event ambient-context provider mechanism; _EventScope correctly cleans up with try/except in aenter, ExitStack for synchronous CMs, and nullcontext fast path when no providers registered.
packages/reflex-base/src/reflex_base/event/processor/base_state_processor.py Integrates event_scope around handler execution and delta resolution; event scope is correctly entered twice (before and after handler) so locale updates from set_locale are reflected in translated computed vars.
packages/reflex-base/src/reflex_base/vars/dep_tracking.py Adds implicit dependency tracking via LOAD_GLOBAL/LOAD_DEREF bytecode instructions; correctly handles unhashable objects and the no-providers fast path.
packages/reflex-i18n/src/reflex_i18n/state.py I18nState substate with locale cookie, computed locale var, and per-event locale scope provider; correctly guards against use without I18nPlugin and resolves locale from cookie then Accept-Language.
packages/reflex-i18n/src/reflex_i18n/_web/i18n.js Client-side i18n runtime; I18nProvider with SSR-safe hydration pattern, catalog lazy-loading with proper error handling, conditional Secure cookie attribute, and Intl-backed number/date formatting with capped formatter cache.
packages/reflex-i18n/src/reflex_i18n/catalog.py Compiles .po catalogs to per-locale JS modules with whitelist-validated plural expressions and tree-shaken messages; index module generates code-split dynamic imports.
packages/reflex-i18n/src/reflex_i18n/cli.py CLI commands for extract, init, and check; correctly separates dry-run check from persisting extract, and handles missing catalogs gracefully.
packages/reflex-i18n/src/reflex_i18n/vars.py rx.t() translation var; validates literal string requirement, registers messages in compile-time registry, and generates client-side JS calls via FunctionVar.
packages/reflex-i18n/src/reflex_i18n/plugin.py I18nPlugin dataclass wiring state registration, static asset shipping, and catalog compilation; clean separation of concerns and lazy state import.
reflex/init.py Adds i18n to the lazy-loader mapping including set_locale, I18nState, t, gettext, ngettext, pgettext, I18nPlugin, I18nConfig.
reflex/state.py Refactors reload_state_module to collect removed state names and purge stale dependency edges, fixing a potential crash in hot-reload when a translated computed var depends on a reloaded state.
reflex/reflex.py _add_plugin_cli_commands() loads reflex.cli entry points with proper exception handling and isinstance guard to prevent type errors from aborting CLI startup.
packages/reflex-i18n/src/reflex_i18n/format.py Client-side locale-aware formatting vars using Intl API via useFormat hook; clean separation from server-side runtime formatting functions.

Reviews (9): Last reviewed commit: "Merge remote-tracking branch 'upstream/m..." | Re-trigger Greptile

Comment thread packages/reflex-base/src/reflex_base/event/processor/scope.py
Comment thread packages/reflex-i18n/src/reflex_i18n/runtime.py
Comment thread packages/reflex-i18n/src/reflex_i18n/_web/i18n.js
Comment thread packages/reflex-i18n/src/reflex_i18n/_web/i18n.js
Comment thread reflex/__init__.py
@benedikt-bartscher
benedikt-bartscher marked this pull request as ready for review July 18, 2026 11:09
@benedikt-bartscher
benedikt-bartscher requested review from a team and Alek99 as code owners July 18, 2026 11:09
@benedikt-bartscher benedikt-bartscher changed the title first i18n wip add basic i18n support Jul 18, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6b9a5f5342

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +12 to +13
"reflex-base >= 0.9.7.dev0",
"reflex >= 0.9.7.dev0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove development pins before publishing reflex-i18n

With the new dispatch-release option, selecting reflex-i18n will create a release and trigger .github/workflows/publish.yml, whose publish job runs scripts/check_min_deps.py --check-dev-pins "$PACKAGE" and explicitly rejects published dependencies containing *.dev pins. Because these two requirements are part of reflex-i18n's published metadata, the publish workflow for any reflex-i18n release will fail at that gate until they are pinned to released versions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave this open for the maintainers

Comment thread reflex/reflex.py
@benedikt-bartscher benedikt-bartscher changed the title add basic i18n support add i18n support Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Internationalization (I18N) and localization (L10N) (Feature Request)

1 participant