Skip to content
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

I18N has undefined message prop when rendering server side #3

Closed
zbyte64 opened this issue Sep 15, 2015 · 5 comments
Closed

I18N has undefined message prop when rendering server side #3

zbyte64 opened this issue Sep 15, 2015 · 5 comments

Comments

@zbyte64
Copy link

zbyte64 commented Sep 15, 2015

I do not understand how/where props.children gets converted to props.message. When I try rendering from nodejs the I18N component only gets props.children.

maker_1     | TypeError: Cannot read property 'call' of undefined
maker_1     |     at I18N.render (/opt/app/node_modules/jsxlate/lib/components.jsx:70:39)
maker_1     |     at [object Object].ReactCompositeComponentMixin._renderValidatedComponentWithoutOwnerOrContext (/opt/app/node_modules/react/lib/ReactCompositeComponent.js:789:34)
maker_1     |     at [object Object].ReactCompositeComponentMixin._renderValidatedComponent (/opt/app/node_modules/react/lib/ReactCompositeComponent.js:816:14)
maker_1     |     at [object Object].wrapper [as _renderValidatedComponent] (/opt/app/node_modules/react/lib/ReactPerf.js:70:21)
maker_1     |     at [object Object].ReactCompositeComponentMixin.mountComponent (/opt/app/node_modules/react/lib/ReactCompositeComponent.js:237:30)
maker_1     |     at [object Object].wrapper [as mountComponent] (/opt/app/node_modules/react/lib/ReactPerf.js:70:21)
maker_1     |     at Object.ReactReconciler.mountComponent (/opt/app/node_modules/react/lib/ReactReconciler.js:38:35)
maker_1     |     at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (/opt/app/node_modules/react/lib/ReactMultiChild.js:192:44)
maker_1     |     at ReactDOMComponent.Mixin._createContentMarkup (/opt/app/node_modules/react/lib/ReactDOMComponent.js:289:32)
maker_1     |     at ReactDOMComponent.Mixin.mountComponent (/opt/app/node_modules/react/lib/ReactDOMComponent.js:199:12)
maker_1     |     at Object.ReactReconciler.mountComponent (/opt/app/node_modules/react/lib/ReactReconciler.js:38:35)
maker_1     |     at [object Object].ReactCompositeComponentMixin.mountComponent (/opt/app/node_modules/react/lib/ReactCompositeComponent.js:247:34)
maker_1     |     at [object Object].wrapper [as mountComponent] (/opt/app/node_modules/react/lib/ReactPerf.js:70:21)
maker_1     |     at Object.ReactReconciler.mountComponent (/opt/app/node_modules/react/lib/ReactReconciler.js:38:35)
maker_1     |     at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (/opt/app/node_modules/react/lib/ReactMultiChild.js:192:44)
maker_1     |     at ReactDOMComponent.Mixin._createContentMarkup (/opt/app/node_modules/react/lib/ReactDOMComponent.js:289:32)
@zbyte64
Copy link
Author

zbyte64 commented Sep 16, 2015

I wrote up a unit test that reproduces the failure: zbyte64@1773be8

@zbyte64
Copy link
Author

zbyte64 commented Sep 16, 2015

I didn't understand what/why was happening until I saw:
https://github.com/drd/jsxlate/blob/master/jsxlate.js#L326

So jsxlate wants to rewrite the I18N tag before it gets interpreted. Currently I have a server running with the babel polyfill which can load up JSX directly - that method does not work with jsxlate. Seems I have three options:

  • run server code through webpack then run
  • write a require extension that chains through transformMessageNodes
  • modify I18N tag to look for props.children

@drd
Copy link
Owner

drd commented Sep 16, 2015

You are correct. What we do in development mode (generally) is option 3. Here's how we do that:

var components = require('jsxlate/lib/components');

if (__DEV__) {
    // Simple mock for i18n to avoid parsing i18n stuff
    components.i18n = (x) => x;
    components.I18N = React.createClass({
        render() {
            if (React.Children.count(this.props.children) === 1
                    && (typeof this.props.children !== 'string')) {
                return this.props.children;
            } else {
                return <span>{this.props.children}</span>;
            }
        }
    });
}

When I need to test translations locally, I do modify my require.extensions to preprocess files with jsxlate.

@drd
Copy link
Owner

drd commented Sep 16, 2015

To use jsxlate with node, I modified the babel/register compiler to allow for an optional preprocessor. Here is the modified compiler: https://gist.github.com/drd/d5a2e225065f525e57d9

And here is how I use it:

var compiler = require('./compiler');
var translator = require('jsxlate').translator;
var fs = require('fs');

require.extensions['.js'] = require.extensions['.jsx'] = function(module, filename) {
    var src = fs.readFileSync(filename, 'utf-8');
    // pass all .jsx files and all .js files not in node_modules through babel
    if (filename.match(/jsx$/) || !filename.match(/node_modules/)) {
        src = compiler.compile(filename, src, translator.transformMessageNodes);
    }
    module._compile(src, filename);
}

@zbyte64
Copy link
Author

zbyte64 commented Sep 16, 2015

TY, That last bit worked for me :)

@zbyte64 zbyte64 closed this as completed Sep 16, 2015
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

No branches or pull requests

2 participants