Describe the bug
I am experiencing an issue in my TypeScript application (bootstrapped by Create-React-App) where translation strings aren't properly interpolated when built for "production" (minified, etc.).
For example:
if I run the app in "development" mode with npm start results: Displaying 1 of 5 (expected)
if I run the app in "production" mode" with npm run build and serve -s build, results: Displaying {item} of {total} (not expected)
(see screenshots below)
I also see this same interpolation behavior in the following cases:
In the use of plurals, results: {thing, plural, one {# thing} other {# things}}, expected: 1 thing or 2 things
In both lingui versions 2.9.2 and 3.0.0-13
After running a message catalog extract/compile and importing message catalogs in app before npm run build
I haven't seen a duplicate bug to this in existing issues (open or closed).
To Reproduce
Bootstrap a React app via create-react-app with Redux+Typescript:
In index.tsx, add import { I18nProvider } from '@lingui/react' and wrap <Provider store={store}> with <Provider store={store}> in ReactDOM.render(
In App.tsx, add import { Trans } from "@lingui/macro"; and in App functional component, add some variables to be interpolated and a translation element, such as:
function App() {
const item = 1;
const total = 5;
return (
Displaying {item} of {total}
```
View in "developer mode"
npm build and viewing page displays: Displaying 1 of 5 (expected behavior)
Build+view in "production mode"
npm run build and serve -s build and viewing page displays: Displaying {item} of {total} (not expected behavior)
Expected behavior
Expected that variables would be interpolated in messages in production builds.
But I am unsure how to complete the additional steps to configure babel and webpack as I am using a project bootstrapped by create-react-app that I have not ejected (and I would prefer not to eject unless it's necessary to make this work).
As such, I do not have separate .babelrc or webpack.config.js files and when I create these for the project they do not appear to do anything (because this config is "owned" by cra). Note that I did also try ejecting my app and following this documentation, but it seems like it may be out-of-date at this point because it appears babel-preset-env and babel-preset-react have been replaced by @babel/preset-env and @babel/preset-react for a while now and the preferred way way use TS and Babel is to run TS through Babel (via @babel/preset-typescript), so there is no morets-loader in webpack.
I'm sure there's a step I'm missing here for how (or in what order) the code is getting transpiled + minified, but I can't figure out how to fix this.
Dev screenshot (see highlighted text)
Production screenshot (see highlighted text)
Versions
jsLingui version: seeing this behavior in both 2.9.2 and 3.0.0-13
Babel version: 7.9.0
Your Babel config (e.g. .babelrc) or framework you use (Create React App, Meteor, etc.)
I don't have a .babelrc, I am using create-react-app, react-scripts version 3.4.3
In case it helps, this is my full tsconfig.json.
This was all created by create-react-app and I only changed target from es5 => es2016 and jsx from react => preserve
For me the problem is that babel config is not getting applied. If you're using cra you could use https://github.com/gsoft-inc/craco, to override babel with that macro
Also probably you're issue was not loading the catalogs correctly on v2 you need to require the messages.js (compiled catalogs) and load them in i18nProvider, on v3 you can do it directly with i18n.load
Thank you very much for the quick response and sample!
I am adjusting my project now to see if I can resolve the issue.
I probably should have noted that I first saw this in an application I am creating using TypeScript and Lingui v3.0.0-13 and in this app I am importing the message catalog. I just didn't import the message catalogs in the create-react-app sample app I created to reproduce the issue.
In my app I am bootstrapping my message catalog as:
import { setupI18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
import { en } from "make-plural/plurals";
...
const locale = "en";
const i18n = setupI18n();
// locales must be loaded AND loaded before load() to prevent the exception: "plurals is not a function"
// see:
// https://github.com/lingui/js-lingui/issues/683#issuecomment-620424893
// note: using cmj "require" instead of es6 "import" here because despite setting "compileNamespace": "es" in .linguirc
// I am getting a typescript "messages has no default export" warning using "import lang from 'catalogPath'"
i18n.loadLocaleData(locale, { plurals: en });
i18n.load(locale, require("locale/en/messages"));
i18n.activate(locale);
I haven't tried adjusting this yet, but perhaps it has something to do with me using CJS vs ES6 imports here.
I also note that our .linguirc files differ. The notable differences seem to be:
yours uses compileNamespace: "cjs", while mine is using "es"
yours includes "runtimeConfigModule": ["@lingui/core", "i18n"], I do not have this line at all
Will update once I adjust my project and test, I just wanted to make note of these updates.
Fixed.
The issue was my import of the message catalogs, specifically this line:
i18n.load(locale, require("locale/en/messages"));
I was loading the messages, but not loading the actual exported messages object, so I adjusted to an es6 import:
import {messages as enMessages} from 'locale/en/messages'
...
// @ts-ignore
i18n.load(locale, enMessages);
and this resolved it.
Or I supposed if I wanted to continue to use CJS require in order to conditionally load catalogs based on supported language(s), I could use:
The main thing is that I missed importing the actual .messages object.
Thank you very much for your help, please feel free to close/resolve this issue.
Best regards,
Describe the bug I am experiencing an issue in my TypeScript application (bootstrapped by Create-React-App) where translation strings aren't properly interpolated when built for "production" (minified, etc.).
For example:
npm start
results:Displaying 1 of 5
(expected)npm run build
andserve -s build
, results:Displaying {item} of {total}
(not expected) (see screenshots below)I also see this same interpolation behavior in the following cases:
{thing, plural, one {# thing} other {# things}}
, expected:1 thing
or2 things
npm run build
I haven't seen a duplicate bug to this in existing issues (open or closed).
To Reproduce
npx create-react-app linguiv2 --template redux-typescript
npm install @lingui/react @lingui/cli @lingui/macro
tsconfig.json
, change:"target": "es2016"
"jsx": "preserve"
Add minimal lingui to the project:
index.tsx
, addimport { I18nProvider } from '@lingui/react'
and wrap<Provider store={store}>
with<Provider store={store}>
inReactDOM.render(
import { Trans } from "@lingui/macro";
and inApp
functional component, add some variables to be interpolated and a translation element, such as:return (
npm build
and viewing page displays:Displaying 1 of 5
(expected behavior)npm run build
andserve -s build
and viewing page displays:Displaying {item} of {total}
(not expected behavior)Expected behavior Expected that variables would be interpolated in messages in production builds.
Additional context Please note that I followed the guidance for configuration of my
tsconfig.json
file here: https://lingui.js.org/guides/typescript.htmlBut I am unsure how to complete the additional steps to configure babel and webpack as I am using a project bootstrapped by create-react-app that I have not ejected (and I would prefer not to eject unless it's necessary to make this work). As such, I do not have separate
.babelrc
orwebpack.config.js
files and when I create these for the project they do not appear to do anything (because this config is "owned" by cra). Note that I did also try ejecting my app and following this documentation, but it seems like it may be out-of-date at this point because it appearsbabel-preset-env
andbabel-preset-react
have been replaced by@babel/preset-env
and@babel/preset-react
for a while now and the preferred way way use TS and Babel is to run TS through Babel (via@babel/preset-typescript
), so there is no morets-loader
in webpack.I also tried following these 2.x to 3.x migration directions: https://github.com/lingui/js-lingui/blob/81937f9c05368459d201c6b5069ed06307b988f0/docs/releases/migration-3.rst#pluginspresets by installing
babel-plugin-macros
and adding the following macro to mypackage.json
file, but this also yielded the same results:I'm sure there's a step I'm missing here for how (or in what order) the code is getting transpiled + minified, but I can't figure out how to fix this.
Dev screenshot (see highlighted text)
Production screenshot (see highlighted text)
Versions
2.9.2
and3.0.0-13
7.9.0
.babelrc
) or framework you use (Create React App, Meteor, etc.) I don't have a.babelrc
, I am using create-react-app, react-scripts version3.4.3
In case it helps, this is my full
tsconfig.json
. This was all created by create-react-app and I only changed target from es5 => es2016 and jsx from react => preserveAlright, i saw you executed extract and compile.
For me the problem is that babel config is not getting applied. If you're using cra you could use https://github.com/gsoft-inc/craco, to override babel with that macro
I've created a sample repo for you https://github.com/semoal/lingui-v3-ts-redux
Also probably you're issue was not loading the catalogs correctly on v2 you need to require the messages.js (compiled catalogs) and load them in i18nProvider, on v3 you can do it directly with i18n.load
Also i saw create-react-app alreadyy contains babel-plugin-macros, so probably you don't need to use craco.
https://github.com/facebook/create-react-app/blob/master/packages/babel-preset-react-app/create.js#L121
Thank you very much for the quick response and sample! I am adjusting my project now to see if I can resolve the issue. I probably should have noted that I first saw this in an application I am creating using TypeScript and Lingui v3.0.0-13 and in this app I am importing the message catalog. I just didn't import the message catalogs in the create-react-app sample app I created to reproduce the issue.
In my app I am bootstrapping my message catalog as:
I haven't tried adjusting this yet, but perhaps it has something to do with me using CJS vs ES6 imports here. I also note that our .linguirc files differ. The notable differences seem to be:
compileNamespace: "cjs"
, while mine is using"es"
"runtimeConfigModule": ["@lingui/core", "i18n"]
, I do not have this line at allWill update once I adjust my project and test, I just wanted to make note of these updates.
Fixed. The issue was my import of the message catalogs, specifically this line:
i18n.load(locale, require("locale/en/messages"));
I was loading the messages, but not loading the actual exported
messages
object, so I adjusted to an es6 import:and this resolved it. Or I supposed if I wanted to continue to use CJS require in order to conditionally load catalogs based on supported language(s), I could use:
The main thing is that I missed importing the actual
.messages
object. Thank you very much for your help, please feel free to close/resolve this issue. Best regards,