-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Babel macro: Add new Babel macro which handles block.json file transformation #16088
Conversation
6de5d19
to
dc4afea
Compare
Hi @gziolo - something I noticed recently is that changes to the block.json files aren't built during watch. I haven't looked into how the build for json files works. Is that something that this PR will fix or should it be tackled separately? |
I noticed it as well. This PR doesn’t address it in the current shape but there are some existing solutions in creste-react-app showing how to enforce re-building files which use macros. I think the same issue applies to Jest. We can look into it separately. |
👍 I've created an issue - #16104 |
dc4afea
to
464b0bd
Compare
498d730
to
2054fb5
Compare
I updated PR to allow the following usage in the block's file: import getBlockData from '@wordpress/blocks/macro';
const metadata = getBlockData( './fixtures/block-i18n.json' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As to whether we should go down the route of this being a macro: From some of the readings, it doesn't seem to me that the plugin should really need to be overly opinionated one way or the other. Would it not be too much trouble to just make a normal babel transform plugin, whose logic is reused by a bundled macro, then the user could choose which to use based on their own preferences?
I see some advantages in macros, certainly (as highlighted in the Babel blog post). It's a bit funny to me one of the promoted advantages is the lack of configuration necessary, when in-fact you do need to configure at least the babel-plugin-macros
plugin. Maybe in the future this could become a built-in feature of Babel. The "Babel cache" caveat seems concerning, though the messaging on it is mixed. If it can have the potential to impact consumers in how they use the macro, that seems really non-ideal. It also doesn't seem to have had much visible movement for solutions since evenchange4/graphql.macro#6 was opened almost two years ago.
It really got me pushing to consider what would be necessary to avoid any of these transforms at all. Of course, we could force someone to wrap the translatable strings themselves when registering the block. There's a lot less magic here, which can be a good thing, but it's also very inconvenient.
I wonder also about whether we can do it at the framework based on the namespace provided when a block is registered.
i.e. Would something like this be feasible?
import settings from './block.json';
registerBlockType( 'my-plugin/map', settings )
function registerBlockType( name, settings ) {
const [ namespace ] = name.split( '/' );
settings = {
...settings,
title: _x( settings.title, namespace ),
// ...
};
}
const { mapKeys, pick } = require( 'lodash' ); | ||
const { dirname, join, relative } = require( 'path' ); | ||
|
||
const i18nVariable = '_x'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't imagine there's much value in making this configurable, since _x
specifically assumes to be used with an additional argument for the context, which in this implementation is hard-coded and not-configurable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree I don't remember why I introduced it :)
throw new Error( `Invalid file name provided: ${ filename }.` ); | ||
} | ||
|
||
const metadataRaw = readFileSync( filename, 'utf8' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any way to make this non-blocking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at 2 or 3 plugins that read JSON files and they use a blocking approach. I'm happy to use the async version but I would need some guidelines or any working example. Do you know anything that would be useful?
} ); | ||
} | ||
} else { | ||
throw new Error( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could do some early returns to avoid the nesting
if ( referencePath.parentPath.type !== 'CallExpression' ) {
throw new Error();
}
// ...
if ( ! textDomain ) {
return;
}
// ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed one of the most popular macros when writing the proof of the concept. You are absolutely right, we should refactor 👍
2054fb5
to
78592e1
Compare
I'm happy to provide both. It feels like it shouldn't be too much work to add support for the regular plugin and perform the transform when
The truth is that the issue with cache exists for both macros and regular plugins in case when you introduce a dependency on non-JS asset. It's also something that isn't resolved in Babel core until today.
In fact, this is what PHP does for the plugin registration. So maybe we could do the same.
It makes me wonder how exactly the translations system works. I assumed that you need to ship code which has to wrap all translations with i18n function so they could be detected. That's why I opted for the Babel approach where it explicitly includes the string wrapped with i18n functions so it can be detected. @swissspidy - can you provide more details? Which approach would you pick? Maybe it doesn't need to be as magical as I wanted it to be :) |
@aduth, I see you filed #19006 where you discovered that translator comments get removed when JS code is bundled in the plugin code. It only assures me that this is why this whole Babel story has been started. Those translations are read from JS code. The same issue will exist for PHP code when we opt for dynamically applied translations. It means we have two options:
|
@gziolo The string extraction system (WP-CLI) would ideally extract the strings directly from |
In fact, this is what @aduth proposed as an alternative solution. If we want to start using Do you know who could help with implementation efforts on WP-CLI side? I'll open an issue there as soon as I confirm this with @aduth and @youknowriad. |
Feel free to open an issue at https://github.com/wp-cli/i18n-command/ I can potentially help with implementation as I built large parts of that tool and am familiar with it. Then, I suppose @ocean90 could help update it on dotorg.
Just like WP-CLI scans all JS and PHP files for translation functions, it would then also scan all |
Let's close this PR based on the feedback received. Thank you for all comments that helped to figure out the next steps 🙇 |
@swissspidy - it turned out you already filed an issue a few months back, I left a comment there: wp-cli/i18n-command#163 (comment). |
I also updated the development roadmap in #16209 to reflect comments from @swissspidy and @aduth: |
Description
Input
Output
TODO
block.json
file, accept only whitelist properties and wrap those translatable withi18n
callsRelated resources:
Examples: