question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

help wanted: strings not interpolated (displaying {var}) in "production" builds

See original GitHub issue

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

  1. Bootstrap a React app via create-react-app with Redux+Typescript:
    • npx create-react-app linguiv2 --template redux-typescript
  2. Add lingui components to project:
    • npm install @lingui/react @lingui/cli @lingui/macro
  3. Modify project tsconfig.json, change:
  4. Add minimal lingui to the project:
    • 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 (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Counter />
        <p>
          <Trans>Displaying {item} of {total}</Trans>
        </p>
  1. View in “developer mode”
    • npm build and viewing page displays: Displaying 1 of 5 (expected behavior)
  2. 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.

Additional context Please note that I followed the guidance for configuration of my tsconfig.json file here: https://lingui.js.org/guides/typescript.html

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 more ts-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 my package.json file, but this also yielded the same results:

  "babel": {
    "plugins": [
      "macros"
    ]
  }

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

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
davakoscommented, Oct 15, 2020

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:

const enMessages = require("locale/en/messages");
i18n.load(locale, enMessages.messages);

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,

0reactions
davakoscommented, Oct 15, 2020

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Using variable interpolation in .gitlab-ci.yml doesn't work ...
Running with gitlab-runner 11.11.0 (6c154264) on My Docker Runner srMa1eEy Using Docker executor with image docker:stable .
Read more >
c# - String Interpolation with format variable - Stack Overflow
I have a format defined somewhere else and use the format variable, not inline string. In C# 6, this is seems impossible: var...
Read more >
Restrict template literal interpolation expressions to strings
When using string literals, any variables are coerced to strings, which can lead to undesirable behavior. As far as I can tell there's...
Read more >
Improved interpolated strings - C# 10.0 draft specifications
It has to allocate an array for the arguments in most cases. There is no opportunity to avoid instantiating the instance if it's...
Read more >
Template literals (Template strings) - JavaScript | MDN
Template literals are literals delimited with backtick (`) characters, allowing for multi-line strings, string interpolation with embedded ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found