js-lingui: @lingui/babel-preset-react is probably missing in babel config

Describe the bug

  • <Trans> elements don’t show in dev
  • Console prints: @lingui/babel-preset-react is probably missing in babel config, but you are using <Trans> component in a way which requires it. Either don't use children in <Trans> component or configure babel to load @lingui/babel-preset-react preset. See tutorial for more info: https://l.lingui.io/tutorial-i18n-react
  • The link in the console message doesn’t point to a tutorial
  • Production crashes

To Reproduce

  1. Fork https://github.com/facebook/create-react-app
  2. Make app
  3. Follow https://lingui.js.org/tutorials/react.html#installing-linguijs

Expected behavior

  • I’d expect it to work without @lingui/babel-preset-react since it’s not mentioned in the docs
  • The link to point to a tutorial

Additional context Add any other context about the problem here.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 18 (13 by maintainers)

Most upvoted comments

That means there should be all these functions/components exported from a package with prebaked i18n instance and you should be able to change its configuration instead of making a new one.

It used to be like that in early version of LinguiJS but I was afraid that having a global/default i18n instance would lead to errors.

Still, no way to get rid of two imports (runtime vs macro), because macros must be imported from specific module name. At least we could get i18n.t syntax back:


import i18n, { Trans } from `@lingui/macro`

<a title={i18n.t`Link title`}><Trans>Content</Trans></a>

this would be transformed to:

import i18n, { Trans } from `@lingui/react`

<a title={i18n._('Link title' )}><Trans id="Content" /></a>

This is trivial example to keep things simple. We could rename runtime/macro exports to make it clear what is what…

If you want to use a custom instance of i18n, then you need to create your own ./i18n.macro.js file as described above.

Oh my god, it’s so simple! 😊 Thanks, I’ll try it tonight but it makes total sense.

I have to mix imports from @lingui/macro and @lingui/react with @lingui/react even exporting the same things as @lingui/macro but it doesn’t actually work or do the same.

💡I agree that exporting Trans component from both packages might be confusing. This is something what could be changed in v3.

However I don’t mind extra import, because it clearly separates runtime code (@lingui/react) from build time macros (@lingui/macro). Anything imported from @lingui/react stays in the runtime code, but macros are processed at build time and replaced with runtime Trans component.

I don’t really like the <I18n> component with the function child as it seems to add a lot of clutter but I agree that it’s probably more convenient to use than withI18n(). Personally I’d probably use the approach shown in https://lingui.js.org/tutorials/react-patterns.html#translations-outside-react-components instead

It is possible to use i18n manager directly, but the problem is that when you change the language, the text won’t be updated. with18n HOC and I18n component read i18n manager from context and they both trigger re-render when language changes.

💡On the other hand, if you don’t mind to do a full page refresh on language change, then you can use i18n manager directly. We should definitely document both usages and their differences.

Finally internationalizing properties has turned into i18n._(tSome value). To me this seems less convenient and natural than i18n.tsomething. The new method looks like magic (unlike the old version which afaik is a standard template literal) that is again prone to programmer errors.

I actually think the opposite in this case. i18n.t'Hello ${name}' was transformed in plugin to i18n._('Hello {name}', { name }). Although it looks simpler, you weren’t aware of such transformation and you got confusing errors in production if you forgot to use Lingui plugins.

On the other hand, writing i18n._(t'Hello ${name}') is transformed into i18n._({ id: 'Hello {name}', values: { name }}) and you can clearly distinguish runtime vs build time code. Especially because you have to import t macro explicitly to make it work. You see a macro and you know instantly there’s something going on at build time.

I’m trying to further simplify it to i18n(t'Hello') but I think the issue isn’t with i18n._ method, but rather the whole syntax right? I’m curious what we could do here to make it easier to understand.

Is there a way to still use the old babel transformer?

Although I planned to support both macros and plugins, I don’t think if I’ll be able to do that given my limited resources. Ideally I would like to have one way how to do it. Let’s keep it open. Macro should be the recommended way, but standalone plugin might be the advanced usage.

Conclusion: Thank you for your feedback, it’s really valuable. Based on feedback from other people, there’s a lot of confusion around macros and I think it may have two reasons:

  1. Misleading documentation - it should be clear what the library does and how
  2. Unconventional approach - this library does sth new which isn’t common among i18n libs. I tried to hide complexity of message formats under JSX and template literals so developers aren’t forced to learn a new syntax. Using plugins, it was “too magical”, using macros it’s too explicit, but the pattern is the same: users don’t expect there’s an extra transformation at build time. I wonder if this is caused by poor documentation or maybe because this approach isn’t common yet? Macros were released a year ago, but only last week were added to CRA which will bring them to masses. I still struggle to figure out how to communicate what macros does so it’s as easy to understand as JSX.