Skip to content

fix: improve locale handling and tree-shaking#8

Merged
Guria merged 2 commits into
mainfrom
paraglide-tree-shake
Feb 23, 2026
Merged

fix: improve locale handling and tree-shaking#8
Guria merged 2 commits into
mainfrom
paraglide-tree-shake

Conversation

@Guria
Copy link
Copy Markdown
Owner

@Guria Guria commented Feb 23, 2026

Summary by CodeRabbit

  • New Features

    • Added automated validation to detect and prevent unused translations in production bundles.
    • Exposed a locale label helper used by the language selector for clearer locale names.
  • Documentation

    • Updated localization docs with new usage patterns and tree-shaking guidance.
  • Refactor

    • Simplified localization callback patterns to improve static message handling and enable better tree-shaking.

Copilot AI review requested due to automatic review settings February 23, 2026 10:55
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 23, 2026

Warning

Rate limit exceeded

@Guria has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 12 minutes and 37 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between c8917ac and 57f774b.

📒 Files selected for processing (3)
  • docs/localization.md
  • scripts/check-tree-shaking.ts
  • src/shared/model/locale.ts

Walkthrough

Adds a tree-shaking validation task and Bun checker script for ParaglideJS translations, refactors reatomLoc to accept parameterless factories, introduces localeAtom.label() for locale labels, updates localization messages with a sentinel key, and migrates consumer code to the new API.

Changes

Cohort / File(s) Summary
Task + CI integration
​.config/mise/conf.d/tasks-quality.toml
Adds lint:paraglide-tree-shaking task and registers it in tasks.validate and tasks.ci.
Tree-shake checker script
scripts/check-tree-shaking.ts
New Bun script scanning .var/dist/webapp/assets JS files for sentinel localization strings; exits non‑zero on findings and prints guidance.
Localization API & data
src/shared/model/locale.ts, docs/localization.md, messages/en.json, messages/es.json
Adds localeAtom.label() computed helper; changes reatomLoc signature to accept () => T; adds reatomloc_tree_shake_canary messages (en/es); updates docs.
Consumer updates
src/pages/items/ui/ItemsPage.tsx, src/pages/settings/ui/SettingsPage.tsx, src/widgets/layout/ui/AppShell.tsx
Migrates reatomLoc callbacks from (m) => ... to () => ...; replaces m[\language_${locale}`]()withlocaleAtom.label(locale)()` in language UI; updates language collection generation.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Mise as "Task runner (Mise)"
  participant Build as "Webapp build (.var/dist/webapp)"
  participant Checker as "Bun script\nscripts/check-tree-shaking.ts"
  Mise->>Build: run `build:webapp` (depends for task)
  Mise->>Checker: run `bun scripts/check-tree-shaking.ts`
  Checker->>Build: glob and read `assets/*.js`
  Checker->>Checker: scan files for sentinel strings
  alt sentinel found
    Checker->>Mise: exit non-zero (fail CI/validation)
  else no sentinel
    Checker->>Mise: report success (tree-shaking OK)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I hopped through messages, labels in paw,

I pruned the bundle without a flaw,
Zero-arg whispers keep translations lean,
A sentinel guards what mustn't be seen,
Hooray — the locales dance, neat and keen! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses both main changes: refactoring locale handling (localeAtom API updates, reatomLoc signature changes) and implementing tree-shaking validation (new check-tree-shaking.ts script and canary messages).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch paraglide-tree-shake

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves ParaglideJS tree-shaking by eliminating dynamic message access patterns and refining the reatomLoc API. The changes ensure that unused translations are properly removed from the production bundle, reducing bundle size.

Changes:

  • Introduced localeAtom.label() method with static locale label mapping to replace dynamic m[language_${locale}]() access
  • Updated reatomLoc API signature to remove the m parameter, requiring direct static calls to m.*() inside callbacks
  • Added automated tree-shaking verification script with canary messages and CI integration

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/shared/model/locale.ts Added localeLabels static mapping and label() method; updated reatomLoc signature to take zero-argument callback; updated documentation
src/widgets/layout/ui/AppShell.tsx Replaced dynamic m[language_${locale}]() with localeAtom.label(locale)()
src/pages/settings/ui/SettingsPage.tsx Updated all reatomLoc callbacks to remove m parameter; refactored language collection to use localeAtom.label()
src/pages/items/ui/ItemsPage.tsx Updated all reatomLoc callbacks to remove m parameter
scripts/check-tree-shaking.ts New script that verifies canary messages are not present in production bundle
messages/en.json Added reatomloc_tree_shake_canary message for verification
messages/es.json Added reatomloc_tree_shake_canary message for verification
docs/localization.md Updated documentation to reflect new API patterns and tree-shaking best practices
.config/mise/conf.d/tasks-quality.toml Added lint:paraglide-tree-shaking task to validation and CI pipelines

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/localization.md`:
- Around line 78-80: Replace the problematic inline code span that currently
uses escaped backticks (the segment referencing message lookup like m[`...`])
with a quoting style that avoids backticks inside code spans (for example use
m['...'] or m["..."]) and ensure there are no leading/trailing spaces inside the
code span; update the text around reatomLoc / localeAtom / m.* to use that new
inline form so the MD038 lint error is resolved.

In `@scripts/check-tree-shaking.ts`:
- Around line 34-44: Add a guard that verifies the dist directory exists and
that the Glob('*.js').scan({ cwd: distDir }) yields at least one file before
declaring success: check the filesystem for distDir (use the same distDir
identifier) and count the results of new Glob('*.js').scan(...) (or collect
files into an array) and if the directory is missing or the file count is zero,
print a descriptive error message referencing distDir and set failed = true (and
exit non-zero) so the check cannot silently pass when no JS files are present;
integrate this check near the top of the current scan loop that uses Glob,
sentinels, and failed.

In `@src/shared/model/locale.ts`:
- Around line 66-70: The computed returned by the label property doesn't
subscribe to locale changes when localeName is passed because target() is only
invoked conditionally; to fix it, always read target() inside the computed to
establish the dependency (e.g. call const current = target(); then const name =
localeName ?? current) before resolving localeLabels[name as keyof typeof
localeLabels](), keeping the computed('localeLabel') and existing lookup logic
intact so the computed tracks localeAtom via target().

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b66a008 and 7a8a39c.

📒 Files selected for processing (9)
  • .config/mise/conf.d/tasks-quality.toml
  • docs/localization.md
  • messages/en.json
  • messages/es.json
  • scripts/check-tree-shaking.ts
  • src/pages/items/ui/ItemsPage.tsx
  • src/pages/settings/ui/SettingsPage.tsx
  • src/shared/model/locale.ts
  • src/widgets/layout/ui/AppShell.tsx

Comment thread docs/localization.md
Comment thread scripts/check-tree-shaking.ts
Comment thread src/shared/model/locale.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a8a39c429

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shared/model/locale.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/localization.md (1)

160-160: Document the failure mode for partial locale registration.

The two-step requirement (message file + localeLabels map) creates a dual-maintenance surface. The doc doesn't state what silently breaks when only one step is done — e.g., does localeAtom.label(locale)() return undefined, an empty string, or throw? Adding a note on the observable symptom (and whether the Bun checker script in this PR validates localeLabels completeness, not just message-key existence) would help developers diagnose missing registrations quickly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/localization.md` at line 160, Update the docs to explicitly state the
failure mode when only the message file is added but the locale is not
registered in the localeLabels map: call out that localeAtom.label(locale)()
will not return the expected localized label (it will resolve to a
missing/undefined label or fallback value used by the app) and that UI text will
appear blank or fallback rather than throwing; also document whether the Bun
validation script in this PR checks both message keys and localeLabels
completeness — if it doesn't, update the script to verify that every locale_xx
message has a corresponding entry in localeLabels (referencing localeLabels and
localeAtom.label) and mention this check in the docs so developers can quickly
diagnose missing registrations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/localization.md`:
- Line 13: Update the table description for localeAtom.label(locale) to
accurately state that it returns a thunk (a zero-argument function) that yields
the display label rather than the label itself; reference the existing usage
pattern localeAtom.label(locale)() and change the text to something like
"Returns a zero-argument function () => string that produces the display label
for a locale code" so readers know to call the returned function.

---

Nitpick comments:
In `@docs/localization.md`:
- Line 160: Update the docs to explicitly state the failure mode when only the
message file is added but the locale is not registered in the localeLabels map:
call out that localeAtom.label(locale)() will not return the expected localized
label (it will resolve to a missing/undefined label or fallback value used by
the app) and that UI text will appear blank or fallback rather than throwing;
also document whether the Bun validation script in this PR checks both message
keys and localeLabels completeness — if it doesn't, update the script to verify
that every locale_xx message has a corresponding entry in localeLabels
(referencing localeLabels and localeAtom.label) and mention this check in the
docs so developers can quickly diagnose missing registrations.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a8a39c and c8917ac.

📒 Files selected for processing (1)
  • docs/localization.md

Comment thread docs/localization.md Outdated
@Guria Guria force-pushed the paraglide-tree-shake branch from c8917ac to 57f774b Compare February 23, 2026 11:12
@sonarqubecloud
Copy link
Copy Markdown

@Guria Guria merged commit d28f25d into main Feb 23, 2026
2 of 3 checks passed
@Guria Guria deleted the paraglide-tree-shake branch February 23, 2026 11:14
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.

2 participants