fix(i18n): respect implicit and zero Accept-Language quality values in preferredLocale - #17743
Conversation
…n preferredLocale sortAndFilterLocales only ranked entries when both quality values were truthy, so an entry with no explicit q= (which means 1.0 per RFC 7231) or with q=0 was left in raw header order instead of being sorted. Default a missing q to 1.0 (0 for a bare `*` so it never wins) so Astro.preferredLocale and Astro.preferredLocaleList return the highest-quality match regardless of order.
🦋 Changeset detectedLatest commit: 845940f The changes in this PR will be included in the next version bump. This PR includes changesets to release 420 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Merging this PR will improve performance by 16.19%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | Simulation | Build: hybrid site (static + server) |
1.6 s | 1.4 s | +16.19% |
Tip
Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.
Comparing contactjawad:fix-preferred-locale-quality-sort (845940f) with main (771b0a9)
|
@contactjawad please create an issue first with a valid reproduction |
|
Thanks @ematipico — opened #17780 with a minimal reproduction (an Accept-Language header like |
There was a problem hiding this comment.
Merge Requirement Assessment
Status: satisfied
- Fix
Astro.preferredLocale/Astro.preferredLocaleListto honor absentAccept-Languagequality values asq=1.0andq=0as a valid, low-ranking value — Implemented inpackages/astro/src/i18n/utils.tsby defaultingundefinedto1for real locales and*to0, replacing the old truthiness guard that treated both cases as equal and left entries in raw header order. - Add regression tests that fail on
mainand pass with the fix — Two new unit tests inpackages/astro/test/units/i18n/i18n-utils.test.tscover: an implicitq=1entry beating a lower explicit quality entry regardless of header order, and aq=0entry not winning over a higher-quality alternative. - Include a changeset for the user-facing fix —
.changeset/fix-preferred-locale-quality-sort.mdis present and describes the behavior change under theastropackage.
Findings
No findings.
Review Status
Verdict: ready to merge based on static review
Context: PR #17743 (closes #17780)
Scope: PR base/head verified (771b0a9a..845940fb); full PR diff reviewed
Changeset: present and covers astro
Limitations: none
Validation: Static review only; no project code, tests, builds, or checks were run.
This review was made by an LLM. The analysis may be wrong, and reports might be incorrect.
|
Thank you @contactjawad :) |
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [astro](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/astro)) | [`7.2.4` → `7.2.6`](https://renovatebot.com/diffs/npm/astro/7.2.4/7.2.6) |  |  | --- >⚠️ **Warning** > > Some dependencies could not be looked up. Check the [Dependency Dashboard](issues/273) for more information. --- ### Release Notes <details> <summary>withastro/astro (astro)</summary> ### [`v7.2.6`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#726) [Compare Source](https://github.com/withastro/astro/compare/astro@7.2.5...astro@7.2.6) ##### Patch Changes - [#​17812](withastro/astro#17812) [`29af6da`](withastro/astro@29af6da) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes a bug where `new FetchState(request)` could fail in development when server dependencies were optimized ### [`v7.2.5`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#725) [Compare Source](https://github.com/withastro/astro/compare/astro@7.2.4...astro@7.2.5) ##### Patch Changes - [#​17758](withastro/astro#17758) [`5f419e2`](withastro/astro@5f419e2) Thanks [@​astro-factory](https://github.com/apps/astro-factory)! - Fixes a bug where `experimental_getFontFileURL()` rejected valid font URLs when using the Cloudflare adapter - [#​17416](withastro/astro#17416) [`493796b`](withastro/astro@493796b) Thanks [@​iseraph-dev](https://github.com/iseraph-dev)! - Skips no-op pathname writes when normalizing SSR request URLs - [#​17712](withastro/astro#17712) [`bd374b7`](withastro/astro@bd374b7) Thanks [@​fkatsuhiro](https://github.com/fkatsuhiro)! - Updates deprecation messages target from Astro 7 to 8 - [#​17719](withastro/astro#17719) [`dac1768`](withastro/astro@dac1768) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes session ID validation to reject non-UUID cookie values before using them as storage keys - [#​17770](withastro/astro#17770) [`84eb7e7`](withastro/astro@84eb7e7) Thanks [@​astro-factory](https://github.com/apps/astro-factory)! - Fixes `--mode`, `--site`, `--base`, `--out-dir`, `--verbose`, `--silent`, and `--open` flags being silently dropped when using `astro dev --background` or `astro preview --background` - [#​17713](withastro/astro#17713) [`d035290`](withastro/astro@d035290) Thanks [@​wakqasahmed](https://github.com/wakqasahmed)! - Fixes `content-modules.mjs` not removing entries for deleted or renamed content files, which could cause Vite to attempt to resolve non-existent modules As part of this fix, `#moduleImports` is now fully rebuilt from `deferredRender` entries before every write, so a module import added only through the public `addModuleImport()` API without a corresponding `deferredRender` entry in the store will no longer be preserved across writes. - [#​17743](withastro/astro#17743) [`adc750f`](withastro/astro@adc750f) Thanks [@​contactjawad](https://github.com/contactjawad)! - Fixes `Astro.preferredLocale` and `Astro.preferredLocaleList` ignoring `Accept-Language` quality values when they are absent or `0`. An entry without an explicit `q=` now correctly counts as quality `1.0` (per RFC 7231) and an entry with `q=0` is treated as not acceptable, so the highest-quality locale is selected regardless of header order. - [#​17757](withastro/astro#17757) [`660991c`](withastro/astro@660991c) Thanks [@​astro-factory](https://github.com/apps/astro-factory)! - Fixes build errors showing wrong file location, missing line:col, and misleading hints when a plugin error (e.g. from MDX) is wrapped by Vite's build error - [#​17783](withastro/astro#17783) [`60b14ff`](withastro/astro@60b14ff) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes a type error when passing an image from a content collection `image()` schema to a component or `<Image />`. The schema returned by `image()` was missing the `apng` format, so it no longer matched the type of an imported image. - [#​17664](withastro/astro#17664) [`d483125`](withastro/astro@d483125) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes an issue where Astro CSP support didn't correctly handle cases `"unsafe-inline"` resource. Now when `"unsafe-inline"`, Astro won't emit hashes for the directive specified. - [#​17810](withastro/astro#17810) [`0fc5f65`](withastro/astro@0fc5f65) Thanks [@​florian-lefebvre](https://github.com/florian-lefebvre)! - Fixes a regression in the content collections that could cause images to not be resolved - [#​17781](withastro/astro#17781) [`aa33b44`](withastro/astro@aa33b44) Thanks [@​matthewp](https://github.com/matthewp)! - Fixes `memoryCache()` storing responses that set cookies through `Astro.cookies` or `Astro.session` - [#​17787](withastro/astro#17787) [`6661fbe`](withastro/astro@6661fbe) Thanks [@​astro-factory](https://github.com/apps/astro-factory)! - Fixes `server:defer` crashing the dev server with "undefined is not a function" when a deferred component imports from `astro:i18n` - [#​17750](withastro/astro#17750) [`dd0e3ac`](withastro/astro@dd0e3ac) Thanks [@​dobrodob](https://github.com/dobrodob)! - Fixes a regression where `transition:persist` stopped working for `<audio>` and `<video>` elements. - [#​17774](withastro/astro#17774) [`fe1d16d`](withastro/astro@fe1d16d) Thanks [@​astro-factory](https://github.com/apps/astro-factory)! - Adds support for importing `.apng` files as image metadata for use with standard `<img>` elements. Astro's image components reject APNG files to avoid removing their animation - [#​17799](withastro/astro#17799) [`8797754`](withastro/astro@8797754) Thanks [@​astro-factory](https://github.com/apps/astro-factory)! - Fixes i18n `fallbackType: "rewrite"` returning 500 instead of 404 when the fallback locale also has no matching static path for a prerendered dynamic route - [#​17741](withastro/astro#17741) [`99d3d3d`](withastro/astro@99d3d3d) Thanks [@​ericswpark](https://github.com/ericswpark)! - Bumps the Astro compiler to the latest version. [Changelog](https://github.com/withastro/compiler-rs/releases/tag/%40astrojs%2Fcompiler-rs%400.4.0). - [#​17782](withastro/astro#17782) [`3578d45`](withastro/astro@3578d45) Thanks [@​Princesseuh](https://github.com/Princesseuh)! - Improves the performance of the Astro CLI in local by enabling Node's module compilation cache. - [#​17705](withastro/astro#17705) [`2043e4f`](withastro/astro@2043e4f) Thanks [@​astrobot-houston](https://github.com/astrobot-houston)! - Fixes incremental builds serving cached HTML that references stale CSS filenames after a stylesheet-only edit - [#​17754](withastro/astro#17754) [`3d50dfd`](withastro/astro@3d50dfd) Thanks [@​astro-factory](https://github.com/apps/astro-factory)! - Fixes the dev server refusing to start in Docker containers after a restart due to PID reuse in the lock file check - [#​17769](withastro/astro#17769) [`bbda94d`](withastro/astro@bbda94d) Thanks [@​astro-factory](https://github.com/apps/astro-factory)! - Fixes a build failure when defining `vite.environments.ssr` in the Astro config. User-provided environment config for `ssr`, `prerender`, or `client` is now properly deep-merged with Astro's internal environment settings instead of silently breaking the server entry naming. - [#​17776](withastro/astro#17776) [`0874da8`](withastro/astro@0874da8) Thanks [@​astro-factory](https://github.com/apps/astro-factory)! - Fixes the `glob()` content loader failing to load files with colons in their names (e.g., `Guide: Architecture.md`) - Updated dependencies \[[`0762a83`](withastro/astro@0762a83), [`0c99615`](withastro/astro@0c99615)]: - [@​astrojs/markdown-satteri](https://github.com/astrojs/markdown-satteri)@​0.3.8 </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC40OC4xIiwidXBkYXRlZEluVmVyIjoiNDQuNDguMSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: Davide Zarantonello <davide@zarantonello.dev>
Closes #17780
Summary
Astro.preferredLocale/Astro.preferredLocaleListcan return the wrong locale becausesortAndFilterLocalesignoresAccept-Languagequality values that are absent or0.parseLocalestoresqualityValue = undefinedwhen an entry has no explicitq=, and0forq=0. The comparator only ran when both values were truthy:Per RFC 7231 §5.3.1 an absent
q=means quality 1.0 (the highest), andq=0means "not acceptable". Because both are falsy, the guard failed,sortreturned0, and the entries were left in raw header order — so a lower-quality locale earlier in the header could win.For
Accept-Language: en;q=0.7, de(locales['en','fr','de']),dehas implicit quality1.0and should win, but the old code returneden.Fix
Default a missing
qto1.0, and keep a bare*at0so it is never ranked above a real locale (the existingfirstResult.locale !== '*'guard relies on that):Test
Two cases added to the existing
computePreferredLocaleunit block: an implicit-q=1entry beating a lower explicitq, and aq=0entry being excluded. Both fail onmainand pass with this change. A changeset is included.