Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): Extract - Flatten ICU messages #1431

Closed
wants to merge 2 commits into from

Conversation

Martin005
Copy link
Contributor

@Martin005 Martin005 commented Feb 12, 2023

Description

Fixes #1186

Based on suggestion from #1186, this PR adds flattening of ICU messages for the extract and extract-template CLI commands.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

Checklist

  • I have read the CONTRIBUTING and CODE_OF_CONDUCT docs
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

@vercel
Copy link

vercel bot commented Feb 12, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated
js-lingui ✅ Ready (Inspect) Visit Preview 💬 Add your feedback Feb 12, 2023 at 0:10AM (UTC)

@Martin005 Martin005 changed the title Merge pull request #1399 from lingui/main feat(cli): Extract - Flatten ICU messages Feb 12, 2023
@github-actions
Copy link

github-actions bot commented Feb 12, 2023

size-limit report 📦

Path Size
./packages/core/build/esm/index.js 1.76 KB (0%)
./packages/detect-locale/build/esm/index.js 812 B (0%)
./packages/react/build/esm/index.js 1.79 KB (0%)
./packages/remote-loader/build/esm/index.js 7.29 KB (0%)

@codecov
Copy link

codecov bot commented Feb 12, 2023

Codecov Report

Base: 69.24% // Head: 70.01% // Increases project coverage by +0.77% 🎉

Coverage data is based on head (4e4a4ce) compared to base (d4a423d).
Patch coverage: 95.52% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##             next    #1431      +/-   ##
==========================================
+ Coverage   69.24%   70.01%   +0.77%     
==========================================
  Files          71       73       +2     
  Lines        2019     2081      +62     
  Branches      542      561      +19     
==========================================
+ Hits         1398     1457      +59     
- Misses        499      501       +2     
- Partials      122      123       +1     
Impacted Files Coverage Δ
packages/cli/src/lingui-extract-template.ts 0.00% <0.00%> (ø)
packages/cli/src/lingui-extract.ts 0.00% <0.00%> (ø)
packages/cli/src/tests.ts 92.30% <ø> (ø)
packages/core/src/flatten/printICU.ts 97.05% <97.05%> (ø)
packages/cli/src/api/catalog.ts 88.07% <100.00%> (+0.11%) ⬆️
packages/core/src/flatten/flattenMessage.ts 100.00% <100.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

Copy link
Collaborator

@timofei-iatsenko timofei-iatsenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this supposed to work in general? When the message would be flattened, it would be a different string. And it would not match to id string from runtime.

Comment on lines -11 to -12
// Redirect imports to the compiled bundles
moduleNameMapper: {},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this, integration test become absolutely the same to the "regular" tests. The idea was to check that code works from ./build instead of ./src

What was wrong with that?

@@ -20,6 +20,7 @@ import extract, { ExtractedMessage } from "./extractors"
import { CliExtractOptions } from "../lingui-extract"
import { CliExtractTemplateOptions } from "../lingui-extract-template"
import { CompiledCatalogNamespace } from "./compile"
import { flattenMessage } from "@lingui/core/flatten"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it's in @lingui/core? Is it supposed to be used on runtime?

Comment on lines +38 to +50
function cloneDeep<T>(obj: T): T {
if (Array.isArray(obj)) {
// @ts-expect-error
return [...obj.map(cloneDeep)]
}
if (obj !== null && typeof obj === "object") {
// @ts-expect-error
return Object.keys(obj).reduce((cloned, k) => {
cloned[k] = cloneDeep(obj[k])
return cloned
}, {})
}
return obj
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, avoid @ts-expect-error

For clone deep you can use simpler JSON.parse(JSON.stringify()) but, better is avoiding mutating data in flattenTokens

Comment on lines +17 to +35
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i]
if (isPluralOrSelect(token)) {
const cloned = cloneDeep(token)
const { cases } = cloned
cloned.cases = cases.reduce((all, k, index) => {
const newValue = flattenTokens([
...tokens.slice(0, i),
...cases[index].tokens,
...tokens.slice(i + 1),
])
all[index] = { ...k, tokens: newValue }
return all
}, [])

return [cloned]
}
}
return tokens
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not a usual forEach()?

tokens.forEach((token, index) => { /* … */ })

Comment on lines +20 to +32
const cloned = cloneDeep(token)
const { cases } = cloned
cloned.cases = cases.reduce((all, k, index) => {
const newValue = flattenTokens([
...tokens.slice(0, i),
...cases[index].tokens,
...tokens.slice(i + 1),
])
all[index] = { ...k, tokens: newValue }
return all
}, [])

return [cloned]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without reduce, mutating data and cloneDeep:

return [{
  ...token,
  cases: token.cases.map((k, index) => {
    const newValue = flattenTokens([
      ...tokens.slice(0, i),
      ...cases[index].tokens,
      ...tokens.slice(i + 1)
    ])

    return {...k, tokens: newValue}
  })
}]

@andrii-bodnar andrii-bodnar modified the milestone: v4 Feb 13, 2023
@timofei-iatsenko
Copy link
Collaborator

@Martin005

How this supposed to work in general? When the message would be flattened, it would be a different string. And it would not match to id string from runtime.

I see here a couple ways how this could be done:

  1. This logic should be applied in the macro and not in extractor. This way macro will generate flatten messages, left them in the bundle where extractor would pick them up. But we should consider SWC version of macro, and porting these changes to the SWC would be hard (because it depends on @message-parser). So i would not recommend this option.

  2. Implement it together with hash based id proposal. This way a hash would be generated by macro from the original, untouched message. And extractor with --flat would process only "messages" not ids. The only one problem here - this will not work for users who not used macro and not use explicit ids. Actually, for v4 we can force explicit ids to be used for non-macro usage.

@Martin005
Copy link
Contributor Author

Martin005 commented Feb 14, 2023

@thekip I have been thinking about this and I believe that the second option would be the best way to go.
Looking at formatjs, if you don't specify id, it will throw an Error. But in their babel config, you can specify that an id can be generated with a specified pattern.
This makes a lot of sense for me. What do you think?

@timofei-iatsenko
Copy link
Collaborator

Yes, this is exactly how i'm see implementation of hash-based ids with macro.

Two cases:

  1. Without macro, i18n._() call, id is required. Message would not be used as substitution.
  2. Macro t calls will generate hash based ids from message if explicit ids is not specified, and this behavior would be enabled as default.

@Martin005 Martin005 marked this pull request as draft February 14, 2023 14:14
@timofei-iatsenko timofei-iatsenko mentioned this pull request Feb 17, 2023
14 tasks
@andrii-bodnar andrii-bodnar force-pushed the next branch 2 times, most recently from 1b9469e to 4aa80de Compare February 20, 2023 12:33
@andrii-bodnar andrii-bodnar removed the v4 label Feb 24, 2023
@andrii-bodnar andrii-bodnar deleted the feat/cli-extract-flatten-icu branch April 26, 2023 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Suggestion: option to flatten ICU Messages
3 participants