feat: runtime core macro#2618
Draft
timofei-iatsenko wants to merge 6 commits into
Draft
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
size-limit report 📦
|
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.
PoC: Runtime JS Macro
Motivation
Currently, Lingui requires a compilation step (babel/swc plugin) to transform macros like
t,plural,select, andselectOrdinalinto runtime code. This creates a barrier for use cases where a build pipeline is either unavailable or undesirable — most notably on the backend (Node.js scripts, serverless functions, CLI tools) where bundle size is not a concern but DX simplicity is.This PR introduces a runtime macro — a set of functions with the same signature/contract as the compile-time macro, but executed entirely at runtime without any compiler plugin. This allows using Lingui's familiar API without any compilation step.
Trade-offs
messagefield in production, leaving only theid— this significantly reduces the i18n overhead in the bundle. The runtime macro cannot do this.${variable}is not supported and will throw with a helpful error message. Users must always use the labeled placeholder syntax:${{name: value}}. This is intentionally strict — it ensures the runtime macro produces the same ICU messages regardless of variable naming, and keeps code portable between runtime and compile-time macros. We should add a configuration flag to the compile-time macro to enforce the same restriction, so that code written for one works identically with the other.plural/selectoptions (e.g.,`She is ${gender}`) are already evaluated by the time they reach the function. However, the full functionality is preserved — instead of a plain template literal, users wrap it withtto produce a macro marker:t`She is ${{gender}}`instead of`She is ${gender}`. Nested macro markers (plural,select,selectOrdinal) work as option values as well.Compatibility with existing infrastructure
The runtime macro is a subset of the compile-time macro API. It produces the same
MessageDescriptorshape ({id, message, values}) with the same ID generation algorithm. This means:What's left
This is PoC, not fully working feature. I wanted to check what features could be implemented without a compile time macro and what's not. The current implementation is doing just macro expansion but not actually connected to i18n.
This is still should be in done. Also JSX macro is not supported (i have another branch with PoC for that as well)
Key questions:
@lingui/coreor distributed as a standalone package?tbound to global i18n, or learn from experience and re-design this, to something likei18n.t`Message`How to try this in your app
Copy the file to your repository. Say you have setup an alias for this file
@mycomp/native-core-macro, then add configuration to lingui config:Then use in your code:
Usage example
For myself