gilbsgilbs / babel-plugin-i18next-extract

Babel plugin that statically extracts i18next and react-i18next translation keys.
https://i18next-extract.netlify.com
MIT License
159 stars 37 forks source link

Decorators #28

Open kaareal opened 5 years ago

kaareal commented 5 years ago

I have been trying to make the babel-plugin-i18next-extract work on code thats using decorators.

I got the following .babelrc using @babel/plugin-proposal-decorators

   ["@babel/plugin-proposal-decorators", { "legacy": true }],
   ["@babel/plugin-proposal-class-properties", { "loose": true }],
   ["@babel/plugin-proposal-object-rest-spread"],
   [
      "i18next-extract",
      {
        "locales": ["en", "nl"],
        "keyAsDefaultValue": true,
        "discardOldKeys": true,
        "i18nextInstancesNames": ["i18next", "i18n", "props"],
        "outputPath": "src/i18n/{{locale}}/{{ns}}.json"
      }
   ]

The babel-plugin-i18next-extract fails to pick up anything that contains a @withTranslation it seems

import { withTranslation } from 'react-i18next';

@withTranslation()
export default class Login extends React.Component {

  render() {
     return <span>{this.props.t("string")}</span>
  }
}

Wanted to hear if anybody got any ideas, how to bring that to work?

gilbsgilbs commented 5 years ago

Hi,

It is true that decorators are not supported. I thought of decorators while implementing withTranslation HOC but I said to myself that since they aren't part of a final ES spec at the moment, I would consider adding support for them as soon as they get first-class support in Babel. To be quite honest, I didn't look into it any further and as far as I'm concerned, I'm patiently waiting for decorators to be part of a final ES spec before actually using them in any production code.

That being said, I'm opened to contributions adding support for decorators. If you want to make a PR, I'm unsure whether decorators are properly typed in Babel, but I think it is acceptable to type them as any if we don't have a better alternative. Secondly, if I remember correctly, decorators are known to cause problems regarding exports. In your example you use the legacy mode, but I think we should support both legacy mode and the mode that fixes the export problem. You may find useful to experiment with ASTExplorer which uses the non-legacy mode.

Note that this is not the only issue with withTranslation HoC. For example, if you wrap your component implementation directly in withTranslation, it won't work although being perfectly ES-compliant code.

Let me know if you need any further information or help.

gilbsgilbs commented 5 years ago

As a workaround, if your only goal is to get your translation keys to be extracted, you could very well go like this:

import { withTranslation } from 'react-i18next';

@withTranslation()
export default class Login extends React.Component {
  render() {
     const t = this.props.t;
     return <span>{t("string")}</span>
  }
}

You would loose namespace parsing from withTranslation, but it should at least find the keys. Another option (that I think is preferable) is to avoid using decorators:

class _Login extends React.Component {
  render() {
     return <span>{this.props.t("string")}</span>
  }
}

export default withTranslation()(_Login);
kaareal commented 5 years ago

@gilbsgilbs Thank you so much about the replies.

I think you right about decorators is a bit of a mess (but it will be great one day, will revisit when it hits stage 3). I am only using them because I am using mobx, otherwise I would stay far away. Was reading https://github.com/mobxjs/mobx/pull/1732 -> building on moving sand.

The above solution is great, thats the perfect shortcut for me. Thanks for an awesome tool.

gilbsgilbs commented 5 years ago

Thanks for replying. I'm reopening in order to keep track on improvements regarding decorators.