Repository navigation
feat: add macro.jsxRuntime option to emit Solid components from <Trans> - #286
Merged
Merged
Conversation
Chudesnov
force-pushed
the
feat/jsx-runtime-solid
branch
from
October 16, 2026 15:27
3adde38 to
5ca423a
Compare
With `jsxRuntime: "solid"` every JSX element inside <Trans> is emitted as
`(_props) => <el {...attrs} {..._props}/>`, with the `_props` spread last so
runtime props such as `children` win. `@lingui/solid` renders components via
`createComponent`, so a bare element would not receive its children.
This matches wrapJsxElementAsComponent in the Babel macro. `t`, `msg`,
`defineMessage` and `useLingui` are unaffected. The default stays "react".
Closes lingui#276
Chudesnov
force-pushed
the
feat/jsx-runtime-solid
branch
from
October 16, 2026 15:33
5ca423a to
ce40927
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #286 +/- ##
==========================================
+ Coverage 94.42% 94.60% +0.17%
==========================================
Files 11 11
Lines 2530 2576 +46
==========================================
+ Hits 2389 2437 +48
+ Misses 141 139 -2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🟢 Approval recommended
Static review identified no blocking issues, and supplied regression coverage addresses option forwarding, component generation, and preserved default behavior.
No open issues 🎉
What changed in this PR
Adds Solid-compatible JSX output to Lingui’s macro tooling, addressing #276 while preserving React as the default.
Changes:
- Adds and forwards the
jsxRuntimeoption. - Wraps nested JSX elements as component functions in Solid mode.
- Adds documentation and regression coverage for configuration, output, and placeholder handling.
| File | Description |
|---|---|
| packages/native-tools/README.md | Documents Solid configuration. |
| packages/native-tools/__test__/transform.spec.ts | Tests React and Solid output. |
| packages/lingui-macro/src-js/map-options.ts | Types and forwards jsxRuntime. |
| packages/lingui-macro/README.md | Documents runtime behavior. |
| packages/lingui-macro/e2e/options.test.ts | Tests configuration forwarding. |
| packages/lingui-macro/e2e/fixtures/lingui-options/solid.config.js | Adds Solid configuration fixture. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_self_closing_element.snap | Covers self-closing elements. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_props_name_collision.snap | Covers generated parameter hygiene. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_plural_inside_trans.snap | Covers nested plural macros. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_nested_elements_and_values.snap | Covers nesting and interpolation. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_named_placeholder_reused.snap | Covers placeholder reuse. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_member_expression_tag.snap | Covers member-expression tags. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_existing_spread_attrs.snap | Covers attribute spread ordering. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_element_inside_icu_case.snap | Covers elements within plural cases. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_does_not_affect_t_and_use_lingui.snap | Confirms unchanged non-JSX macro output. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_distinct_elements_same_placeholder.snap | Covers conflicting placeholder errors. |
| crates/lingui_macro/tests/snapshots/jsx_solid__solid_basic_component_with_attrs.snap | Covers basic Solid component output. |
| crates/lingui_macro/tests/jsx_solid.rs | Adds Solid transformation regression tests. |
| crates/lingui_macro/src/options.rs | Defines, defaults, and tests runtime options. |
| crates/lingui_macro/src/lib.rs | Exports JsxRuntime. |
| crates/lingui_macro/src/builder.rs | Generates Solid component wrappers. |
Review effort: Balanced
timofei-iatsenko
approved these changes
Oct 19, 2026
2 of 8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
jsxRuntime: "react" | "solid"macro option (default"react").With
"solid", every JSX element inside<Trans>is emitted as a component function instead of a bare element:This ports the Babel macro's
wrapJsxElementAsComponentbehavior, and the idlqG909matches the Babel snapshotshould generate Solid components 1.Details:
{..._props}is appended last so runtime props such aschildrenwin. The tag name is cloned as-is (member expressions like<Foo.Bar>work), and the element is always self-closing._propsis a freshprivate_ident!, so hygiene renames it (_props1) if the user already has a_propsbinding in scope.<Trans>path is affected.t,msg,defineMessageanduseLinguiproduce identical output in both modes._t="link") and the "Multiple distinct JSX elements with the same placeholder name" check still compare the original elements, not the wrapped ones.Docs: new
jsxRuntimeentry in both the@lingui/swc-pluginand@lingui/native-toolsREADMEs, pointing todefineConfigfrom@lingui/solid/configand the Solid tutorial.Closes #276
Tests
crates/lingui_macro/tests/jsx_solid.rs(snapshots): basic attrs, self-closing, nested elements with values, member-expression tag, existing spread attrs, reused named placeholder,PluralinsideTrans, element inside an ICU case,_propsname collision, conflicting named placeholders (to_panic!), andt/useLinguiunaffected.jsxRuntimeinoptions.rs("solid","react", missing, invalid).native-toolsspec for solid vs. default output; e2e test thatmacro.jsxRuntimefrom a Lingui config reaches the plugin options.cargo test,cargo fmt --check,cargo clippy --all-targets --all-features -- -D warnings, and native-toolsyarn build && yarn test. No existing snapshots changed.AI disclosure
Heads up: this was written with Claude Code. I spot-checked it, but I haven't written Rust before, so I'd appreciate a close look at
component_valueinbuilder.rsand the option plumbing inoptions.rs.