Read the site on a phone - #504
Conversation
Starlight served the 146 API pages on /es/ under its own notice, "Esta página aún no está disponible en tu idioma", which promised a translation that is not coming. The reference is generated from the docstrings, so its text is the code's own; keeping a Spanish copy of it in step with every signature change would cost more than it teaches, and the guides carry the teaching in both languages already. So the notice now says what is true: the API reference is published in English in both languages because it is generated from the code. The Spanish reference index says the same where it sends the reader there, and the parity check, which exempts exactly this subtree and nothing else, records the reason rather than the mechanism.
Every guide opened with "By José Manuel Requena Plens · Published ..., updated ...", between the title and the first sentence, on 278 pages. Of the three things it said, two were already on the page: the name in the footer credit, which carries rel="author" and is the form a crawler reads, and the update date in the last-updated line at the foot of the article. Only the first publication date was unique to it. So the line is gone and that date moved to where its sibling already was. The last-updated line now reads "Published <date>, updated <date>", one date when the two are the same day, in both languages. Nothing machine-readable changes: Head.astro computes author, datePublished and dateModified from the same git history and the same route data whatever the body shows, so the JSON-LD, the sitemap, the markdown copies and the llms artifacts are untouched.
On a wide screen the sidebar answers "what is in this topic?" before the reader asks: /signals/ opens with its seven rows down the left. On a phone the same page opens with a title and prose, the sidebar folded behind the menu button, and nothing on the first screen names a single section. The list is further down every landing page, authored as headings, but measured against the built site it starts between one and nearly three screens below the fold. So the landing page now opens with it. TopicSections renders the topic's own sidebar tree as a short navigation block: one row per section, with the number of pages inside, the whole row a target. It renders on a topic's landing page and nowhere else, and `md:sl-hidden` retires it the moment the real sidebar appears, so a desktop reader is not shown the same seven labels twice. The tree it reads is the one the sidebar renders, not a second list to keep in step: the topics plugin has already narrowed `starlightRoute.sidebar` to the current topic by the time components render, which is the same data Pagination.astro walks.
The Spanish-regulation guide printed the snippet that renders an acoustic inspection fiche and then showed no fiche, unlike every other guide that ends in a report. It was not alone: sixty-seven fiches are generated, committed and shipped in the built site, and seven of them were embedded on no page in either language. One was the worked example of the very snippet its guide prints. The seven are in their guides now, in both languages: the RD 1367/2007 inspection fiche, the ISO 1999 NIPTS and HTLAN predictions, the machine enclosure and HVAC duct fiches, the reactive silencer, and the IEC 61400-11 tonality assessment. Three of those guides never mentioned `.report()` at all, so they gained the paragraph and the snippet as well as the preview; every number quoted in a description was read off the committed page. The gap was invisible to every gate, which is the part worth fixing. The fiche check closed the loop from the generator to the committed file and stopped there, and the EN/ES parity check compares the two trees with each other, so a fiche missing from both languages passed both. It now asks the remaining question, per language: is this fiche on a page a reader can reach, and does every embedded name exist?
The glossary was twelve five-column tables. A table is the right shape for numbers and the wrong one for a sentence: measured on a phone, the definition column rendered 135 px wide while the one-word guide link took 256, and the row needed 775 px of horizontal scroll inside a 358 px screen. The definition is the content of that page, so each term is a block now: the notation and its unit above, the sentence at the full width of the column, the standard and the guide underneath as metadata. The definition gets 324 px on the same phone and there is nothing to scroll sideways; on a wide screen the spare width goes to a second column instead of stretching the prose. The deeper problem was that the same 120 entries existed four times: a table in each language, and a hand-written JSON-LD block of 120 DefinedTerm nodes in the frontmatter of each. Nothing kept the four in step and they had drifted. They come from one array now, src/data/glossary.mjs, which the component renders and emits the structured data from. Each page went from 2030 lines to 39. What cannot differ between the two languages is stored once, which is what stops it drifting: the notation, the designation where it is only a catalogue number, the route of the guide. What genuinely translates is a pair: the definition, the unit where the unit is a word, the clause, the twenty-one designations carrying translated prose, and the two entries named rather than symbolised. The link to a guide now takes its text from that guide's own title, read at build time, so the nine Spanish rows still advertising a title their page had stopped using are gone by construction, and a term pointing at a page that does not exist fails the build instead of shipping a dangling link.
The page stopped being twelve markdown tables and became a component, so it is now the kind of page pa11y exists for. It was not on the list; the other two generated reference pages, conformance and errata, were.
Three result classes had a `.report()` section written in their guide and no example to show for it: the two detailed ISO 12354 predictions and the ISO 3745 precision sound power determination. The guide told the reader what the fiche contains and could not show one. The two prediction fiches are the Annex L / Annex G building, read from the fixture the tests and the conformance report already share rather than transcribed a third time: the same 220 mm separating floor, floating floor, AAC external walls and calcium-silicate internal walls, through the same eight Annex E junctions. They rate to the annexes' own R'w = 57 dB over thirteen paths and L'n,w = 41 dB over five. The two corrections the registry records against the printed inputs travel with the fixture, so the fiche cannot quietly disagree with the conformance rows. The precision fiche is the guide's own worked example, the forty-position hemisphere array whose spectrum the page already plots, so the fiche and the prose print the same LWA = 89.3 dB(A) and the same U = 4.1 dB. All three are embedded in their guides in both languages, which is what the per-language check added with the previous batch now requires of every committed fiche.
There was a problem hiding this comment.
Sorry @jmrplens, your pull request is larger than the review limit of 150000 diff characters
|
You've reached the fair usage limit for the Bito Code Review Agent trial. Upgrade to a paid plan or contact support@bito.in for assistance. Learn more |
|
Warning Review limit reached
Next review available in: 5 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe change adds three generated report examples, validates bilingual report embeds, documents report generation in English and Spanish, adds a bilingual glossary, and updates documentation navigation, dates, accessibility routes, and layout components. ChangesReport examples and embeds
Reference and page presentation
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant ReportGenerator
participant ReportFiles
participant DocumentationPages
participant ReportChecker
ReportGenerator->>ReportFiles: Generate registered report fiches
DocumentationPages->>ReportFiles: Embed report previews
ReportChecker->>DocumentationPages: Scan bilingual embeds
ReportChecker->>ReportFiles: Verify generated fiche coverage
Possibly related PRs
Suggested labels: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Reviewer's GuideAdds missing example PDF fiches and previews for several .report() APIs, ensures every generated fiche is embedded in at least one EN/ES guide, refactors the glossary into a single data source with a new responsive layout, and improves mobile navigation by showing topic sections and moving byline dates into a unified LastUpdated component while keeping API reference English-only by design. Sequence diagram for fiche generation and embedding validationsequenceDiagram
actor Dev
participant Make as make_reports
participant Gen as generate_reports.py
participant Reports as REPORT_DIR<br/>(.github/reports)
participant Site as docs .mdx<br/>ReportPreview
participant Check as check_reports.py
Dev->>Make: make reports
Make->>Gen: main()
Gen->>Gen: _detailed_airborne_example
Gen->>Gen: _detailed_impact_example
Gen->>Gen: _precision_sound_power_example
Gen->>Reports: write iso12354_detailed_airborne_example.pdf
Gen->>Reports: write iso12354_detailed_impact_example.pdf
Gen->>Reports: write iso3745_precision_power_example.pdf
Dev->>Check: python scripts/check_reports.py
Check->>Check: _problems()
Check->>Check: _unshown()
Check->>Site: _shown_in("en"/"es")
Site-->>Check: ReportPreview name="..."
Check->>Reports: glob("*.pdf")
Reports-->>Check: fiche names
Check->>Check: compare generated vs shown
Check-->>Dev: error if
Note over Check: fiche generated but shown on no page
Dev->>Site: add ReportPreview in guides
Dev->>Check: rerun scripts/check_reports.py
Check-->>Dev: All fiches match and are shown
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@site/src/components/Glossary.astro`:
- Around line 107-117: Update the DefinedTerm description construction in the
terms.map callback to normalize both term.definitionText and term.unitText with
the existing termCode helper before interpolating them. Preserve the current
unit-label and “Defined in” formatting while ensuring no raw TeX delimiters or
math syntax remain in the JSON-LD description.
- Around line 34-35: Update the Glossary JSON-LD URL construction to use the
configured siteUrl and BASE values instead of the hardcoded SITE URL. Build the
site URL with new URL(BASE, `${siteUrl}${lang === 'es' ? '/es' : ''}`).href and
trim its trailing slash, and construct guide URLs from `${BASE}${lang === 'es' ?
'/es' : ''}/${guide}/` rather than using term.href.replace(BASE, '').
In `@site/src/content/docs/devices/emission/sound-power-pressure.mdx`:
- Around line 481-488: Update the result.report metadata construction to use the
imported ReportMetadata symbol directly instead of emission.ReportMetadata,
while preserving all existing metadata fields and values.
In `@site/src/content/docs/es/devices/emission/sound-power-pressure.mdx`:
- Around line 493-503: Update the result.report call to construct metadata with
the imported top-level ReportMetadata symbol instead of emission.ReportMetadata,
preserving all existing metadata fields and report arguments.
In `@site/src/data/glossary.mjs`:
- Around line 1712-1716: Update the glossary entries identified by id "imd" and
"dim" so their standard field contains only "IEC 60268-3:2013" and their
existing "14.12.7" clause is moved into a separate clause field.
- Around line 1838-1846: Update the glossary entry identified by id "l-p-2" so
the underwater L_p notation is stored once and reused for both languages,
following the file-header rule for identical notation. Remove the separate
Spanish "Lp" value and ensure both name.en and name.es resolve to the same
"$L_p$" notation for Glossary.astro’s notation() handling.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 49e54770-f629-4a28-9baa-5fb716cf33ee
⛔ Files ignored due to path filters (3)
.github/reports/iso12354_detailed_airborne_example.pdfis excluded by!**/*.pdf.github/reports/iso12354_detailed_impact_example.pdfis excluded by!**/*.pdf.github/reports/iso3745_precision_power_example.pdfis excluded by!**/*.pdf
📒 Files selected for processing (34)
.github/reports/iso12354_detailed_airborne_example.webp.github/reports/iso12354_detailed_impact_example.webp.github/reports/iso3745_precision_power_example.webpscripts/check_reports.pyscripts/generate_reports.pysite/.pa11yci.jsonsite/astro.config.mjssite/scripts/check-i18n-parity.mjssite/src/components/Glossary.astrosite/src/components/LastUpdated.astrosite/src/components/MarkdownContent.astrosite/src/components/PageTitle.astrosite/src/components/TopicSections.astrosite/src/content/docs/buildings/design/detailed-prediction.mdxsite/src/content/docs/devices/emission/sound-power-pressure.mdxsite/src/content/docs/devices/noise-control/noise-control.mdxsite/src/content/docs/devices/noise-control/silencers.mdxsite/src/content/docs/environment/sources/wind-turbine-noise.mdxsite/src/content/docs/environment/spanish-noise-regulation.mdxsite/src/content/docs/es/buildings/design/detailed-prediction.mdxsite/src/content/docs/es/devices/emission/sound-power-pressure.mdxsite/src/content/docs/es/devices/noise-control/noise-control.mdxsite/src/content/docs/es/devices/noise-control/silencers.mdxsite/src/content/docs/es/environment/sources/wind-turbine-noise.mdxsite/src/content/docs/es/environment/spanish-noise-regulation.mdxsite/src/content/docs/es/perception/hearing/noise-induced-hearing-loss.mdxsite/src/content/docs/es/reference/glossary.mdsite/src/content/docs/es/reference/glossary.mdxsite/src/content/docs/es/reference/index.mdsite/src/content/docs/perception/hearing/noise-induced-hearing-loss.mdxsite/src/content/docs/reference/glossary.mdsite/src/content/docs/reference/glossary.mdxsite/src/content/i18n/es.jsonsite/src/data/glossary.mjs
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #504 +/- ##
=======================================
Coverage 96.99% 96.99%
=======================================
Files 272 272
Lines 38575 38575
=======================================
Hits 37416 37416
Misses 1159 1159 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Numerical conformance report✅ 533/533 conformance checks pass across 57 domains and 362 standards - filters class 1 - weightings within IEC 61672-1 class 1. Each row pins a standard clause to its expected normative value and the value the library computes. Every section below is collapsible and stays collapsed while all of its rows pass; a section with any failing row opens automatically. ✅ Numerical validation - filters & weightings: class showcase (IEC 61260-1 · IEC 61672-1 · ISO 7196)IEC 61260-1:2014 class per filter architecture (order 6, one-third-octave, 100 Hz-10 kHz, fs = 48 kHz). For each architecture the table shows, at its binding band, the measured relative attenuation and the class-1 limit it must clear, so the number and the range it must sit in are both visible. A positive margin means the acceptance limits are met with that much room.
Only Butterworth (the library default) and Chebyshev-II are class-compliant architectures. Chebyshev-I and elliptic trade the mask for passband ripple, and Bessel for a maximally-flat group delay (soft rolloff); they cannot satisfy the IEC 61260-1 Class 1/2 attenuation mask by construction, so they are labelled By design - this is expected, not a failure or regression. Frequency-weighting conformance (A/C: IEC 61672-1 Table 3; G: ISO 7196 A.3). The max deviation from nominal is informational (it falls at a frequency extreme where the tolerance is widest and asymmetric); compliance is judged at the binding frequency - the one with the least headroom - where the deviation, the applicable tolerance band and the headroom are shown together.
✅ Filters & weightings: 100% (10/10)
✅ Levels & dosimetry: 100% (9/9)
✅ Room & building acoustics: 100% (72/72)
✅ Room acoustics: 100% (16/16)
✅ Psychoacoustics: 100% (14/14)
✅ Speech transmission (IEC 60268-16): 100% (10/10)
✅ System measurement (Golay / Kirkeby / Mueller-Massarani): 100% (5/5)
✅ Intensity & sound power: 100% (10/10)
✅ Building prediction & uncertainty: 100% (15/15)
✅ Outdoor propagation & occupational exposure: 100% (10/10)
✅ Materials: absorption, airflow & impedance: 100% (6/6)
✅ Scattering & diffusion (ISO 17497): 100% (14/14)
✅ In-situ road absorption (ISO 13472): 100% (3/3)
✅ Precision sound power (ISO 3745 / 9614-3): 100% (4/4)
✅ Human vibration (ISO 8041 / 2631 / 5349): 100% (15/15)
✅ Speech intelligibility (ANSI S3.5-1997): 100% (24/24)
✅ Objective intelligibility (STOI / ESTOI): 100% (3/3)
✅ Impulsive-sound prominence (NT ACOU 112): 100% (2/2)
✅ Impulsive-sound prominence (ISO/PAS 1996-3): 100% (2/2)
✅ Room noise (ANSI S12.2-2019): 100% (3/3)
✅ Hearing threshold (ISO 7029 / ISO 389-7): 100% (3/3)
✅ Measurement uncertainty (GUM / Supplement 1): 100% (7/7)
✅ Noise-induced hearing loss (ISO 1999): 100% (6/6)
✅ Multiple-shock whole-body vibration (ISO 2631-5): 100% (6/6)
✅ Sound absorption in enclosed spaces (EN 12354-6): 100% (2/2)
✅ Prominent discrete tones (ECMA-418-1): 100% (2/2)
✅ Tonal audibility (ISO/PAS 20065): 100% (11/11)
✅ Psychoacoustic annoyance & fluctuation strength (Fastl & Zwicker): 100% (3/3)
✅ Electroacoustics: distortion & frequency response: 100% (20/20)
✅ Calibrated spectral analysis (Bendat & Piersol): 100% (12/12)
✅ Multiple-input coherence (Bendat & Piersol): 100% (5/5)
✅ Time-frequency analysis (Bendat & Piersol): 100% (3/3)
✅ Correlation, time delay and envelope (B&P / Knapp & Carter): 100% (7/7)
✅ Cepstrum, liftering and envelope spectrum (Havelock / B&P): 100% (3/3)
✅ Time synchronous averaging (McFadden 1987): 100% (5/5)
✅ Data qualification and Rice statistics (Bendat & Piersol): 100% (8/8)
✅ Underwater acoustics (ISO 18405/17208/18406): 100% (6/6)
✅ Underwater sound propagation (transmission loss): 100% (16/16)
✅ Underwater propagation regimes (Weston flux theory): 100% (3/3)
✅ Marine-mammal auditory weighting (NMFS / Southall): 100% (4/4)
✅ Underwater numerical propagation (modes / rays / PE): 100% (4/4)
✅ Aircraft noise (ICAO Annex 16 / IEC 61265): 100% (15/15)
✅ Rotorcraft noise (ECAC Doc 32 / NORAH2): 100% (12/12)
✅ CNOSSOS-EU road source (Directive 2002/49/EC Annex II): 100% (6/6)
✅ Wind-turbine noise (IEC 61400-11): 100% (3/3)
✅ Porous & multilayer absorbers (Mechel / Bies / Cox & D'Antonio): 100% (20/20)
✅ Slow-sound perfect absorbers (Jimenez et al. Appl. Sci. 2017): 100% (3/3)
✅ Program loudness (ITU-R BS.1770 / EBU R 128): 100% (8/8)
✅ 2D FDTD wave simulation (Attenborough & Van Renterghem 2021, Ch. 4): 100% (4/4)
✅ Swept-sine distortion & phase utilities (Farina / Novak): 100% (7/7)
✅ Spherical ground & barriers (Attenborough / Salomons / Bies): 100% (7/7)
✅ Panel & aperture sound insulation (Bies / Hopkins / Cremer): 100% (17/17)
✅ Bending-wave plate-junction transmission (Cremer / Craik / Hopkins): 100% (6/6)
✅ Atmospheric refraction (Salomons rays / GFPE): 100% (3/3)
✅ Electroacoustics: 100% (9/9)
✅ Industrial noise control: 100% (22/22)
✅ CNOSSOS-EU railway source (Directive 2002/49/EC Annex II): 100% (8/8)
Tests & coverage — 48198 tests, 0 failures (✅ all green)
Conformance harness: |
The new precision snippet wrote emission.ReportMetadata; the class is exported from the package root, as its sibling snippet on the same page already showed. The static pass does not import anything, so only CI, which runs every English block, could see it.
Six findings, four of them mine and two already fixed by the snippet commit. Three entries had their designation cut mid-parenthesis. The migration split a standard at the first comma when what followed looked like a clause, and in "ISO 717-2:2020 (measurement in ISO 16251-1:2014, Formulae (3) and (4))" what followed was the middle of a note: the opening bracket stayed in `standard` and the closing one moved to `clause`. The page read correctly because the component joins the two with a comma, and the structured data did not. Those three notes are one field again. Two entries kept their clause inside the designation, which every other entry separates and which the JSON-LD needs separated. The migration's rule required a word boundary after the first digit, so it matched "5" and missed "14.12.7". The underwater sound pressure level stored its notation twice, `$L_p$` in English and `Lp` in Spanish, so one card typeset it and the other printed the source. The notation is one value with a translated qualifier, which is what the module's own header says. In the component, the site and base strings come from src/data/site.mjs, where astro.config.mjs and the audit scripts read them, instead of a literal; the guide URL is built from the slug rather than by stripping the base back off a href, which a string replace would have removed wherever it first appeared; and the JSON-LD description, unit and clause go through the same maths stripping as the term code, so a consumer reads "THDF" and not the TeX.
|
|
You've reached the fair usage limit for the Bito Code Review Agent trial. Upgrade to a paid plan or contact support@bito.in for assistance. Learn more |
main carries the squash of #504, which is this branch's own glossary work under a different SHA, so most of it merged cleanly. Four files needed a decision, and in each one this branch is the later state: - `site/src/data/glossary.mjs` differed in three lines, the guide slug of the two assessment pages this branch moved into `environment/assessment/`. - The two `spanish-noise-regulation.mdx` pages differed in the depth of their component imports, which is what that same move corrected. - `scripts/generate_reports.py` is the fiche registry and command line here, and the builders it used to hold live in `scripts/reports/`. The three fiches #504 added are in that package and still registered.



Five things a reader meets before the content, fixed together because they are all the same complaint: the page is not shaped like what it holds.
The example report a guide described and never showed
The Spanish-regulation guide printed the snippet that renders an acoustic inspection fiche and then showed no fiche. It was not alone. Sixty-seven fiches were generated, committed and shipped in the built site, and seven were embedded on no page in either language — one of them the worked example of the very snippet its guide prints.
The seven are in their guides now, in both languages, and three guides that never mentioned
.report()at all gained the paragraph and the snippet as well as the preview. Three further classes had a.report()section written and no example to generate from; those fiches exist now too:R'w = 57 dBover thirteen paths andL'n,w = 41 dBover five;LWA = 89.3 dB(A).The gap was invisible to every gate, which is the part worth fixing. The fiche check closed the loop from the generator to the committed file and stopped there, and the EN/ES parity check compares the two trees with each other, so a fiche missing from both languages passed both. It now asks the remaining question, per language: is this fiche on a page a reader can reach, and does every embedded name exist? Seventy fiches, all shown.
A topic that would not say what it holds
On a wide screen the sidebar answers "what is in this topic?" before the reader asks. On a phone the same landing page opens with a title and prose, the sidebar folded behind the menu button, and nothing on the first screen naming a single section; the authored list is between one and nearly three screens below the fold.
The landing page now opens with it: one row per section with the number of pages inside, the whole row a target, retired by
md:sl-hiddenthe moment the real sidebar appears. It reads the tree the sidebar renders, not a second list to keep in step.The maintainer between the reader and the first sentence
Every guide opened with "By José Manuel Requena Plens · Published ..., updated ...", on 278 pages. Two of the three things it said were already on the page: the name in the footer credit, which carries
rel="author", and the update date in the last-updated line at the foot of the article. Only the first publication date was unique to it, and it moved to where its sibling already was. Nothing machine-readable changes:Head.astrocomputes author and both dates from the same git history whatever the body shows.A glossary shaped like a spreadsheet
Twelve five-column tables. Measured on a phone, the definition column rendered 135 px wide while the one-word guide link took 256, and the row needed 775 px of horizontal scroll inside a 358 px screen. Each term is a block now: notation and unit above, the sentence at the full width, standard and guide underneath as metadata. The definition gets 324 px on the same phone with nothing to scroll sideways, and a wide screen spends the spare width on a second column instead of stretching the prose.
The deeper problem was that the same 120 entries existed four times: a table in each language and a hand-written JSON-LD block of 120
DefinedTermnodes in the frontmatter of each. Nothing kept them in step and they had drifted. They come from one array now, and each page went from 2030 lines to 39. What cannot legitimately differ between languages is stored once; what translates is a pair. The link to a guide takes its text from that guide's own title, read at build time, so the nine Spanish rows still advertising a title their page had stopped using are gone by construction, and a term pointing at a page that does not exist fails the build.The API reference, in English on purpose
Starlight served the 146 API pages on
/es/under "Esta página aún no está disponible en tu idioma", promising a translation that is not coming. The reference is generated from the docstrings, so its text is the code's own, and keeping a Spanish copy of it in step with every signature change would cost more than it teaches. The notice now says that, the Spanish reference index says it where it sends the reader there, and the parity check records the reason rather than the mechanism.Verified locally: ruff, mypy, the site build, 3630 snippet blocks over 505 pages, EN/ES parity over 156 pages, the sidebar audit over 13 topics and 301 pages per locale, KaTeX with no parse errors, the visual and contrast checks, and pa11y over 66 URLs, the glossary among them for the first time.
Summary by Sourcery
Unify glossary content into a single data source, add glossary rendering and structured data, ensure all generated report fiches are embedded and validated per locale, add missing report examples and previews to guides, remove the page byline in favour of consolidated date display, and improve mobile navigation by surfacing topic sections on landing pages while clarifying API reference language policy.
New Features:
Bug Fixes:
Enhancements:
Tests:
Summary by CodeRabbit
New Features
Documentation