Compiling the catalog at runtime
See original GitHub issueFirst off, thanks for the awesome library. The day-to-day dev experience seems a lot nicer than react-intl
- where I’ve migrated from 😃.
The problem
We’re fetching translations from a translation platform at runtime - we want our translators to be able to see their changes in (near) real time on our staging environment. I could be wrong, but AFAIK the lingui compile
workflow is optimized for compile time. What I mean by this, is that it outputs a JS file, which can then be imported by Node (in case of SSR) or Webpack (for the frontend).
Given this background I haven’t found a straightforward way to set this up. My current solution works like this:
- For the frontend we expose an endpoint like
/api/lang/nl.js
. This endpoint uses@lingui/cli/api#createCompiledCatalog
to build a JS file which exposes the catalog on the window. This is actually the least painful step. - For the backend we use
createCompiledCatalog
to compile a CJS bundle, which we are then force to run throughrequire-from-string
. I mean, I guess it works pretty well. It just feels kinda weird to start from a plain JSON catalog, then run this through a compiler that turns the plain JSON into valid JS, which we then compile to get a working catalog at runtime. I feel like it should be possible to goJSON
➡️runtime catalog
without the transpilation/compilation steps.
The solution I’d like
I’d like an API which generates a runtime catalog - meaning an in-process Object which I can pass directly into the <I18nProvider>
.
Alternatives I’ve considered
Not sure if this is helpful, but I’ve considered writing the CJS catalog to disk, and then require
ing it in Node. This has an obvious problem: Node’s module caching. Given that we want to be able to update the translations at runtime, we would have to clear the cache for the module, either by explicitly doing something like delete require.cache[require.resolve('./catalog.js')]
, or by hashing the catalog’s content, and writing to ./{hash}-catalog.js
, which would bust the cache every time the contents change.
Additional context
If this is something that you’d consider adding, I think this might be a good candidate for v3 #334.
@tricoder42 mentioned something related here: https://github.com/lingui/js-lingui/issues/293#issuecomment-416272667
I’m trying to say that my original proposal isn’t about loading locales, but only message definitions. No matter if messages are extracted from source files or remote API, first you always need just message definitions and then you create locale files by merging with existing catalogs. Yes, we could also add loading translations from API, but that’s another step.
I’m not sure if what you’re thinking would solve my problem, or whether “loading translations from API” would remain at compile time.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:7
- Comments:8 (7 by maintainers)
Top GitHub Comments
Thanks for detailed description of your usecase.
Does your staging environment runs with
NODE_ENV=development
? If so, the core library loads required localeData (plurals) and compiles messages at runtime:https://github.com/lingui/js-lingui/blob/d33f9b3fc19197d916fb42254bbdb78ac664a819/packages/core/src/i18n.js#L204-L208
All you need to do is to load catalog as a plain JSON:
Now, the only problem is that you need to run it in React component and save catalogs to state so you can pass it to
I18nProvider
. This will be changed in #334 wheni18n
core object is the single source of truth for locales and catalogs.If you don’t run staging with
NODE_ENV=development
then it might be a bit tricky, because we need to exposedev/compile.js
in the compiled source and then you need to add it toi18n._dev
…Anyway, this will definitely become easier in v3. The core API is more flexible and I was thinking about exposing runtime compiler.
lingui compile
does more than compile messages to JS functions:I want to create a detailed benchmark about using compiled message catalog and compile them at runtime, but first I want to finish refactoring in #334 before adding more features.
Most likely it would be something like this:
I want to keep door open for Fluent syntax.
This could be actually done in minor release. We just need to rename
_dev
property and export runtime parser as a separate package. Unfortunately I want to focus on #334 to start testing it asap.