-
Notifications
You must be signed in to change notification settings - Fork 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
Framework: Add i18n-translate codemod #13597
Conversation
@ockham This PR needs a rebase |
I think I found out why Facebook is migrating all projects to use prettier.) It's something that can significantly simplify reviewing changes introduced by codemods :) We should also revisit split between internal and external dependencies which doesn't play well with automated code refactoring. I tested it with It has 2 issues to fix: import i18n, { localize, localize, localize } from 'i18n-calypso'; import { localize } from 'i18n-calypso';
import { localize } from 'i18n-calypso'; We can fix missing or broken whitespaces with |
By the way. I think it wouldn't be that bad idea to merge it as soon as 2 issues I mentioned are fixed. It can only help people to migrate their code to use Another idea. Can we have interactive pre-commit hook? We could detect missing localize and ask if it should be added to the PR. |
68f6f08
to
b449c64
Compare
Thanks for the review @gziolo!
Should be fixed now.
Last I checked I don't think the whitespace rule that we'd need here was available for the
We do have an ESLint rule to guard against |
6c76078
to
fe6690b
Compare
Instead of wrapping the const Search = React.createClass({ ... });
export default localize( Search ); This pattern makes HOC composition easier, and also doesn't break static methods and properties: const Search = localize(React.createClass({
statics: { instances: 0 },
componentWillMount() { Search.instances++ }, // !!! Search is a different class
}); @ockham What do you think? Would you mind if I pushed a fix to this branch? |
@jsnajdr I don't mind, as long as it doesn't break other stuff. As discussed over at #13759 (comment):
So we need to keep those other cases in mind, which I think makes things quite a bit harder. |
I'll check how often there special cases with non-default export actually occur. It would be great if we could wrap the export instead of the |
If the result of 'React.createClass' is assigned to a variable and that variable is later exported with 'export default' or 'module.exports =', wrap the exported variable with 'localize': export default localize( TheComponent );
I added code that detects the special case where the component is assigned to a variable and then exported as default. In such case, the In the remaining cases (and there are plenty of variants), the There's one more case worth handling:
Codemods are fun! |
Detect if a class is wrapped with connect() in the export statement and add the 'localize' wrapper at the right place: export default connect( ... )( localize( TheComponent ) );
Added a special case for |
Nice! Seems to work well. The code is a bit less easy to grok now, but that's almost inevitable. I was originally thinking we might optimistically wrap the first use of whatever variable I plan on merging tomorrow so the codemod is available in time for the Calypso Framework Hangout on Thursday. |
Next thing I plan to do is to codemod the |
Great job on this one! I was wondering if we should pipe codemodes and transform all module.exports to ES6 exports first and then use one codemod to wrap them with localize :) |
I was thinking it'd be preferable to do different transforms in separate steps (and PRs)... |
It has landed 🎉 |
This codemod:
createClass
-created React components that usethis.translate
(provided by the auto-injected i18n mixin)import { localize } from 'i18n-calypso'
before the firstimport
it finds. If there's already something else beingimport
ed fromi18n-calypso
, the codemod is smart enough to add the{ localize }
import to that statement.createClass
instance inlocalize()
(thus providing atranslate
prop to the component)this.translate
withthis.props.translate
To test:
make build
bin/codemods/i18n-mixin client/my-sites/ads/
. Or any directory. Try stuff that doesn't have unit tests (see below).localize
's parens, dos/localize\((\S*)\)/localize( $1 )/g
.)\t
(one tab, four spaces -- not properly displayed here on GitHub!) with\t\t
(two tabs) -- required since that's another thing that codemods tend to mess up.Limitations:
import
statement at the top of each file you want to change. I'd recommend running @jsnmoon's./bin/codemods/commonjs-imports path-to-transform/
first -- this will convertrequire
s toimport
s.identity
there astranslate
prop.localize
can also break yourrefs
.jscodeshift
based codemods tend to screw up some of our whitespace -- in particular, the spaces inside parens (notably forlocalize
).FYI @jsnmoon @ehg @stephanethomas @gziolo @mtias