martinandert / react-translate-component

A component for React that utilizes the Counterpart module to provide multi-lingual/localized text content.
MIT License
322 stars 31 forks source link

translate returns an object instead of a string #1

Closed ppet closed 10 years ago

ppet commented 10 years ago

when used outside the return statement of the React class render function, the react-translate-component's translate function returns an object where a string should be returned. code snippet within a React.creatClass: render:function() { var menusLns = this.getFooterMenu(); //getting a json file that describes my menus var i, j; var menus = []; var content;

    for (i = 0; i < menusLns.length; ++i) {
        var Menu = {};
        Menu.title = menusLns[i].id;
       Menu.items = "";
        for (j = 0; j < menusLns[i].menuitem.length; ++j) {
            var tagTitle = menusLns[i].menuitem[j].value;
            console.log("item tagTitle = " + tagTitle); // Ok
            var text = this._e("gui", tagTitle); // we are not within the return statement...

// this._e comes from a mixin lib in which we have _e: require('react-translate-component').translate, // this syntax works nicely in another react component, but within its return statement console.log("item text = " + text); // KO: object Object var link = menusLns[i].menuitem[j].link; var item = '\u003cli\u003e\u003ca title="' + tagTitle + '" href="' + link + '"\u003e' + text + '\u003c/a\u003e\u003c/li\u003e\n'; console.log("menu item: " + item); Menu.items += item; } menus.push(Menu); }

    return (
        <  ....  >
    );
}
martinandert commented 10 years ago

You are using it wrong. React-Translate-Component's translate function is just a convenience function that mimics the invocation of Counterpart's exported method. translate returns an "instance" of the React component. So instead of this

var Translate = require('react-translate-component');

// in render function
return React.DOM.li(null, Translate(null, 'my.translation.key'));

you can do it a bit shorter this way

var t = require('react-translate-component').translate;

// in render function
return React.DOM.li(null, t('my.translation.key'));

If you need a translated string to be returned, use Counterpart's method. Counterpart is a peer dependency of React-Translate-Component und used internally in its render function.

var _t = require('counterpart');
_t('my.translation.keys') // => 'a string'
andresgutgon commented 10 years ago

Hi, in my case I need transtation to be a string to use as a HTML attribute. Look at i18n_placeholder

This is my component:

  render: function () {
    var i18n_placeholder = counterpart.translate('foo.email.placeholder');
    return (
      <div>
          <input type="email" placeholder={i18n_placeholder} />
      </div>
    );
  },

The problem

If I implement a locale swicher this way image

When locale is changed by the user, Counterpart translations are not changed because are not React Components.

Question

How can I update counterpart translations when user select locale in switcher component?

Note

Switcher component is the same you use in your example

martinandert commented 10 years ago

How can I update counterpart translations when user select locale in switcher component?

You could listen to Counterpart's locale change event in your component's componentDidMount lifecycle method. Example (untestet):

var MyComponent = React.createClass({
  /* ... */

  componentDidMount: function() {
    counterpart.onLocaleChange(this.localeChanged);
  },

  componentWillUnmount: function() {
    counterpart.offLocaleChange(this.localeChanged);
  },

  localeChanged: function(newLocale) {
    this.setState({ 
      placeholder: counterpart.translate('foo.email.placeholder')
    });
  },

  render: function () {
    var i18n_placeholder = this.state.placeholder;

    return (
      <div>
        <input type="email" placeholder={i18n_placeholder} />
      </div>
    );
  },
});
andresgutgon commented 10 years ago

Thank you @martinandert that worked great

neemzy commented 8 years ago

Thanks for the tip! Might be useful to put that somewhere in the README (FAQ or so), as it is a quite common use case.

In my case, I built on top of your tip to have Counterpart.onLocaleChange set the current locale in the state of my root component. When the locale changes, it rerenders itself and all its children, thus triggering Counterpart's native translate function again with the current locale. Any thoughts? Would you fear a performance pitfall with such a global solution?