Skip to content

Expand Fluent localization to 34 locales (#466) - #500

Merged
leynos merged 47 commits into
mainfrom
issue-466-expand-localization-support
Aug 5, 2026
Merged

Expand Fluent localization to 34 locales (#466)#500
leynos merged 47 commits into
mainfrom
issue-466-expand-localization-support

Conversation

@leynos

@leynos leynos commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Closes #466

Expands Netsuke's Fluent localization from two catalogues to 35: the 34
requested locale tags plus en-US, which remains the source and fallback
locale.

The registry

The locale list used to live in four places — the embedded resources in
cli_localization, hard-coded paths in the build audit, the
rerun-if-changed directives, and the ortho_config metadata — so adding a
locale meant editing all four and hoping.

src/localization/locales.rs is now the single source of truth. A
define_locales! macro declares the tags and embeds
locales/<tag>/messages.ftl for each, so a registry entry without a catalogue
fails to compile. The embedding, the audit, the rerun directives, the
packaging smoke test and the tests all read it.

Cargo.toml's package.metadata.ortho_config.locales is the one necessary
duplicate, because Cargo metadata cannot call into Rust. The build audit
compares the two and fails on drift, so adding a locale means editing exactly
two lists.

Selection and fallback

Dispatch matched on the language subtag alone, so every Spanish tag collapsed
onto es-ES. Selection now matches the exact BCP 47 tag first, then consults
deliberate per-language rules, then the sole catalogue for that language, then
en-US. The rules keep variants that differ in substance apart: es-419 and
es-ES, pt-BR and pt-PT, zh-Hans and zh-Hant. English outside the
United States prefers en-GB, and no resolves to nb.

Audit

The build-time audit now walks every declared locale rather than two
hard-coded paths, and checks interpolation variables per message as well as
key presence — a translation that drops a { $path } or invents a { $name }
fails the build. It outgrew the 400-line file limit, so it moved into
build_l10n_audit/ split by concern: keys.rs parses the define_keys!
macro, ftl.rs parses catalogues into message and variable sets, mod.rs
orchestrates and reports.

Translations

Each of the 33 new catalogues carries all 328 messages, translated rather than
transliterated. Some things worth a reviewer's attention:

  • zh-Hans and zh-Hant are separate translations, not a character
    conversion: the Traditional catalogue uses Taiwanese computing terminology
    throughout (檔案, 快取, 預設, 巨集, 範本, 相依性, 建置).
  • pt-BR and pt-PT differ in vocabulary (arquivo/ficheiro,
    diretório/pasta, detectada/detetada) and in the progress labels, where
    European Portuguese uses the "a + infinitive" continuous form.
  • Plural examples carry each language's real CLDR categories: six for Arabic
    and Welsh, four for Czech, Polish, Russian, Ukrainian, Hebrew and Scottish
    Gaelic, three for Romanian, one for Hungarian and the CJK locales. Where a
    category changes the noun's case or mutation, each variant spells it out.
  • Netsuke identifiers users type (foreach, when, vars, cwd_mode,
    with_suffix, group_by, the netsuke::jinja::* tags, the literal option
    values) are untranslated throughout.

Right-to-left

ar, fa and he are the first RTL locales. Fluent already isolates
interpolated values, so the remaining hazard is the first character of a
message: a value opening with a Latin word, a bracket or a placeable lets that
token decide the paragraph direction. Those values carry a leading U+200F, and
a test enforces the rule.

Tests

  • tests/locale_catalogue_tests.rs (new): CLDR plural categories per
    language, the RTL direction policy, untranslated identifiers, and the rule
    that a translation is not a copy of the English source.
  • tests/locale_registry_tests.rs: every documented fallback rule case by
    case, plus registry structure.
  • tests/localization_tests.rs: every registered locale renders and
    interpolates; non-Latin scripts and direction marks survive to the rendered
    string.
  • tests/packaging_smoke_tests.rs: every registry catalogue ships in the
    package.

1265 tests pass. make check-fmt, make lint, make test,
make markdownlint and make nixie are all green.

Documentation

The translator guide gains sections on the registry and on right-to-left
handling, a plural table covering every shipped locale, and an
"adding a locale" workflow that matches the registry. The users' guide gains a
--locale section listing every tag with its language and the resolution
order. The design document describes the registry and the widened audit, and
its audit flowchart now shows the loop over every locale.

Note on the release-help policy

Release manual pages and PowerShell help remain en-US only: the binary embeds
every catalogue and translates at run time, so per-locale release assets would
add weight without adding reach. That decision is now stated in
scripts/generate-release-help.sh and in the users' guide rather than being
implicit in a bare assignment.

🤖 Generated with Claude Code

Summary by Sourcery

Expand Fluent-based localization from two locales to a registry-driven set of 35, enforce catalogue and metadata consistency at build time, and document and test the expanded locale selection and localization behaviour.

New Features:

  • Add Fluent catalogues for 33 additional locales plus en-GB, covering Latin, Cyrillic, Greek, Indic, Thai, CJK and right-to-left scripts, with language-specific plural rules.
  • Introduce a locale registry in src/localization/locales.rs that embeds each catalogue and drives CLI localization, build-time audits, rerun directives and packaging tests.
  • Allow CLI localization to select catalogues by exact BCP 47 tag with language-aware fallback rules, including script and region handling for English, Spanish, Portuguese, Chinese and Norwegian.
  • Add a resolve_catalogue_tag helper to expose the effective catalogue for a requested locale tag.

Enhancements:

  • Refactor the build-time localization audit into a dedicated build_l10n_audit module that walks all registered locales and validates keys and interpolation variables against the English source.
  • Extend documentation for translators, users and developers to describe the locale registry, fallback policy, right-to-left handling, plural categories per shipped locale, and Polonius toolchain constraints.
  • Tighten packaging checks so that all build_l10n_audit sources and every catalogue named by the registry are included in release artefacts.
  • Clarify and expand ADR-006, README and developer guidance around the pinned Polonius nightly toolchain and RUSTFLAGS propagation in local and CI workflows.

Documentation:

  • Update the translators' guide with the locale registry as source of truth, shipped locales, per-language CLDR plural categories, RTL guidance, and a revised workflow for adding new locales.
  • Extend the users' guide with a --locale section that lists all shipped tags, their languages, and explains locale resolution and fallback behaviour.
  • Clarify repository layout docs to point localization work at the locale registry, and adjust various guides to reflect nextest usage and environment handling.
  • Document in scripts and guides that release manual pages and PowerShell help are shipped in en-US only while runtime localization handles all other locales.

Tests:

  • Add locale_catalogue_tests to assert CLDR plural category sets, enforce RTL direction-mark rules, ensure Netsuke identifiers remain untranslated, and reject translations that copy the English source.
  • Add locale_registry_tests to verify the registry structure, catalogue selection and all documented fallback rules, including handling of unsupported or unparsable tags.
  • Extend localization tests to exercise message rendering and interpolation for every registered locale, and to ensure non-Latin scripts and direction marks survive in rendered output.
  • Broaden packaging_smoke_tests to verify build_l10n_audit sources are included and that every catalogue referenced by the locale registry ships in the crate.

Chores:

  • Remove the old build_l10n_audit.rs entry point in favour of a structured module layout and update Cargo.toml to include the new directory.
  • Adjust existing Polonius migration, design, developers' and agents' guides to reflect the audit and localization changes while keeping prior content in sync.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Summary

  • Expand Fluent localization from two catalogs to 35 supported locales, including en-US as the source and fallback locale.
  • Add the central locale_catalogues registry with exact BCP 47 matching and deliberate language, region, and script fallback.
  • Embed all catalogs and audit keys, interpolation variables, locale metadata, and package contents.
  • Refactor the build audit into focused parser, scanner, metadata, comparison, and orchestration modules.
  • Add runtime rendering, pluralization, interpolation, Unicode, RTL, registry, tracing, packaging, and audit tests.
  • Buffer startup diagnostics so human-mode fallback warnings remain visible and JSON output remains clean.
  • Document locale configuration, fallback behaviour, catalogue structure, translator requirements, and English-only release help.
  • Update the translator tooling execution plan and design documentation for the registry-based model and interpolation auditing.
  • Address the requirements in Issue #466.

Walkthrough

The PR adds a shared locale registry, exact-tag fallback resolution, modular build-time localisation auditing, 33 locale catalogues, startup diagnostic buffering, and validation, packaging, and documentation updates.

Changes

Localisation registry and runtime flow

Layer / File(s) Summary
Registry and runtime resolution
src/locale_catalogues.rs, src/localization/mod.rs, src/lib.rs, build.rs, src/cli_localization.rs
Add exact-tag lookup, language-specific fallback rules, registry-backed catalogue loading, and public registry exports.
Startup diagnostics and localiser guards
src/main.rs, src/startup_tracing.rs, test_support/src/localizer.rs, test_support/src/localizer_tests.rs
Buffer startup diagnostics until output mode resolution. Restore the previous localiser before releasing the shared test lock.
Runtime validation
tests/locale_registry_tests.rs, tests/localization_tests.rs, tests/startup_diagnostics_tests.rs, src/cli_localization_tracing_tests.rs, src/main_tests.rs
Validate locale resolution, fallback warnings, catalogue construction, startup output settlement, and concurrent localiser access.

Build-time localisation audit

Layer / File(s) Summary
Audit implementation
build_l10n_audit/*, build.rs
Split the audit into byte scanning, Rust-key extraction, Fluent parsing, metadata parsing, comparison, and orchestration modules. Audit every registered catalogue and interpolation variable.
Audit and packaging validation
tests/build_l10n_*, tests/packaging_smoke_tests.rs, Cargo.toml, dylint.toml, .codescene/code-health-rules.json
Test parser errors, metadata drift, key and variable mismatches, staged repositories, package contents, lint exclusions, and CodeScene rules.

Locale catalogues and documentation

Layer / File(s) Summary
Locale catalogues
locales/*/messages.ftl
Add the requested locale catalogues and update the Spanish completion message.
Catalogue, plural, script, and direction checks
tests/locale_catalogue_tests.rs, tests/localization_plural_tests.rs, tests/locale_direction_tests.rs
Validate catalogue coverage, CLDR plural categories, interpolation, script preservation, numeric selection, and RTL rendering.
Documentation and release guidance
docs/*.md, docs/sample-netsuke.toml, scripts/generate-release-help.sh, CHANGELOG.md
Document registry ownership, fallback rules, locale layout, audit behaviour, user locale selection, translation workflow, and source-locale release help.

Possibly related issues

Possibly related PRs

Suggested labels: Issue

Suggested reviewers: codescene-access

Poem

Register each locale.
Match exact tags first.
Audit keys and variables.
Buffer startup warnings.
Keep scripts and plurals aligned.


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (2 errors, 5 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Testing (Overall) ❌ Error Fail: tests cover registry, audits, plural/RTL output, and startup paths, but none covers build.rs emit_rerun_directives or LayeredLocalizer fallback for a missing valid message. Add hermetic tests that capture emit_rerun_directives output for every SUPPORTED_LOCALES path and build a partial consumer catalogue to assert missing keys use the English layer.
Unit Architecture ❌ Error localization::localizer() lazily mutates global state and calls build_localizer; Fluent parsing can warn and fall back to NoOpLocalizer without a Result. Make localizer construction return an explicit error and perform fallback/logging at the startup boundary; keep localizer() as a read-only accessor after explicit installation.
Out of Scope Changes check ⚠️ Warning Startup tracing buffering and localizer restoration changes are unrelated to issue #466's locale-expansion scope. Move the startup tracing and localizer restoration changes to a separate linked issue, or add explicit scope and acceptance criteria for them.
Testing (Property / Proof) ⚠️ Warning The PR adds parser, metadata, bounded-buffer, and lock-ordering invariants, but proptest coverage only exercises locale resolution; other tests use fixed cases. Add substantive proptest or model-based tests for parser inputs, ByteIndex laws, audit set rules, writer operation sequences, and localizer state transitions.
Testing (Compile-Time / Ui) ⚠️ Warning The registry has compile-time include_str! behaviour, but the PR has no trybuild or equivalent compile-fail test; existing tests only inspect runtime data or call audit functions directly. Add a compile-fail/UI fixture that removes or invalidates a registered catalogue and assert the compiler diagnostic with a focused .stderr snapshot.
Performance And Resource Use ⚠️ Warning build_localizer runs at src/main.rs:177 and :267, reparsing Fluent bundles even when the effective locale is unchanged; StartupWriter also locks a mutex for every write after settlement. Reuse the startup localizer when the effective catalogue is unchanged, and provide a lock-free steady-state writer path after buffering ends.
Architectural Complexity And Maintainability ⚠️ Warning Reject the bespoke 322-line TOML scanner in build_l10n_audit/metadata.rs; Cargo.toml already provides the approved toml = "0.8" dependency. Use the existing toml crate in build dependencies to read package.metadata.ortho_config.locales, delete the manual scanner, and retain focused audit tests.
Developer Documentation ❓ Inconclusive Investigation has not started. Inspect the changed APIs, developer guide, design documents, roadmap, and execplan before deciding.
✅ Passed checks (12 passed)
Check name Status Explanation
Title check ✅ Passed The title describes the Fluent locale expansion and links issue #466, matching the main change.
Description check ✅ Passed The description clearly explains the locale expansion, registry, fallback rules, audit, tests, packaging, and documentation changes.
Linked Issues check ✅ Passed The PR adds the requested locales, registry-driven selection, audits, tests, packaging checks, and documentation required by issue #466.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
User-Facing Documentation ✅ Passed docs/users-guide.md documents --locale precedence, runtime/configuration timing, normalization, all 35 shipped tags, fallback rules, English message fallback, and en-US-only release help.
Module-Level Documentation ✅ Passed All 24 Rust files changed by the PR have module-level //! documentation; the docs describe purpose, use, and relationships, including nested audit and test modules.
Testing (Unit And Behavioural) ✅ Passed PASS: Cover parser errors, audit drift, registry invariants, all 35 catalogues, interpolation, plural and RTL behaviour; BDD and binary tests cover CLI output and startup JSON/human paths.
Domain Architecture ✅ Passed Keep the check green: filesystem and build concerns stay in build.rs and build_l10n_audit/mod.rs, while catalogue embedding and Fluent construction remain behind locale and CLI localisation modules.
Observability ✅ Passed Retain the decision-point logs: fallback warnings include requested/effective locale and reason, catalogue failures include locale/error, and startup buffering preserves human diagnostics without c...
Security And Privacy ✅ Passed No secrets or credential-like values were added; locale inputs are parsed, registry paths are static, HTML output escapes values, and startup diagnostics use a bounded buffer with JSON discard.
Concurrency And State ✅ Passed Accept: protect StartupWriter with Arc and the global localizer with RwLock; deterministic contention, drop-order, poisoning, and joined-thread tests cover the risky interleavings.
Rust Compiler Lint Integrity ✅ Passed This PR introduces no inappropriate lint suppressions, artificial appeasement, or dead code. All pub(super)/pub(crate) items are used. Cloning is justified (Arc sharing, signature assertions docume...
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-466-expand-localization-support

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

codescene-access[bot]

This comment was marked as outdated.

@sourcery-ai

sourcery-ai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

This PR expands Netsuke’s Fluent-based localization from two catalogues to a full registry-driven set of 35 locales, introduces a locale registry as single source of truth wired into build/test/packaging, tightens the build-time localization audit (including variable checking), updates CLI localization to select catalogues by tag/fallback rules, adds broad test coverage and documentation for translators/users, and restructures build/audit plumbing accordingly.

Sequence diagram for catalogue selection and CLI localizer construction

sequenceDiagram
    actor User
    participant CLI as cli_localization
    participant Locales as localization.locales
    participant Ortho as ortho_config::FluentLocalizer

    User->>CLI: build_localizer(Some(preferred_locale))
    CLI->>CLI: parse_locale_identifier(preferred_locale)
    alt parse succeeds
        CLI->>Locales: resolve_catalogue(&LanguageIdentifier)
        Locales->>Locales: catalogue(locale.to_string())
        alt exact tag found
            Locales-->>CLI: &LocaleCatalogue
        else fallback needed
            Locales->>Locales: resolve_via_fallback(LanguageFallback)
            Locales-->>CLI: &LocaleCatalogue
        end
    else parse fails
        CLI->>Locales: source_catalogue()
        Locales-->>CLI: &LocaleCatalogue (en-US)
    end

    CLI->>Locales: source_catalogue()
    Locales-->>CLI: &LocaleCatalogue (en-US)

    CLI->>Ortho: FluentLocalizer::builder(locale)
    CLI->>Ortho: FluentLocalizer::with_en_us_defaults([source.resource()])
    CLI->>Ortho: builder.with_resources([catalogue.resource()])
    Ortho-->>CLI: primary localizer

    CLI->>CLI: LayeredLocalizer::new(primary, fallback)
    CLI-->>User: Box<dyn Localizer> (layered over en-US)
Loading

File-Level Changes

Change Details Files
Introduce a centralized locale registry that owns the catalogue list and is consumed by build, tooling, and runtime selection.
  • Add src/localization/locales.rs with define_locales! macro and LocaleCatalogue/SUPPORTED_LOCALES registry entries
  • Make build.rs rerun-if-changed directives derive from the registry and include every messages.ftl file
  • Update Cargo.toml package.metadata.ortho_config.locales to mirror the registry and treat it as the only necessary duplicate
  • Have tests and packaging_smoke_tests.rs read SUPPORTED_LOCALES and assert that all referenced catalogues ship in the crate
src/localization/mod.rs
src/localization/locales.rs
build.rs
Cargo.toml
tests/packaging_smoke_tests.rs
docs/repository-layout.md
docs/translators-guide.md
docs/contents.md
docs/sample-netsuke.toml
Extend CLI localization to work across the registry, selecting catalogues by BCP 47 tag with language-specific fallback rules.
  • Replace hard-coded en-US/es-ES include_str! in cli_localization.rs with registry-driven locale resolution
  • Add resolve_catalogue_tag helper to expose effective catalogue tag for a requested locale
  • Implement layered localizer creation using LocaleCatalogue resources and language fallbacks (en vs en-GB, es-ES vs es-419, pt-BR vs pt-PT, zh-Hans vs zh-Hant, no -> nb)
  • Update locale resolution feature tests to cover unsupported locale fallback and new resolution behaviour
src/cli_localization.rs
src/localization/locales.rs
tests/localization_tests.rs
tests/features/locale_resolution.feature
docs/users-guide.md
docs/translators-guide.md
docs/netsuke-design.md
Refactor and strengthen the build-time localization audit to walk all locales and validate both key sets and interpolation variables against the English source.
  • Split previous build_l10n_audit.rs into build_l10n_audit/keys.rs (define_keys! parser) and build_l10n_audit/ftl.rs (Fluent catalogue parser), with mod.rs orchestrating locale iteration and error reporting
  • Remove the old two-catalogue (en-US/es-ES) AuditDifferences structure and replace it with per-locale LocaleFindings (missing, orphaned, variable_mismatches)
  • Extend the audit to compare per-message variable sets to those in the English source catalogue and fail on mismatch
  • Add cargo metadata drift check so Cargo.toml’s ortho_config.locales array must match the registry
  • Wire build.rs to call the new audit module and add rerun-if-changed on locales.rs and Cargo.toml
build_l10n_audit/mod.rs
build_l10n_audit/keys.rs
build_l10n_audit/ftl.rs
build.rs
Cargo.toml
docs/netsuke-design.md
docs/developers-guide.md
Ship 33 new Fluent catalogues (plus en-GB) and enforce catalogue quality via tests for plural rules, RTL handling, and untranslated identifiers.
  • Add messages.ftl files under locales/ for a wide set of languages/scripts, including Latin, Cyrillic, Greek, RTL (ar, fa, he), Indic, Thai, CJK, and regional variants (es-419, pt-BR, pt-PT, zh-Hans, zh-Hant)
  • Document shipped locales, fallback rules, and plural categories per locale in translators-guide.md and users-guide.md
  • Add tests/locale_catalogue_tests.rs to assert CLDR plural category sets, ensure non-copy translations, check that Netsuke identifiers and literal option values remain untranslated, and enforce RTL direction mark rules
  • Extend tests/localization_tests.rs to iterate SUPPORTED_LOCALES, ensuring each renders and interpolates, non-Latin scripts survive, and RTL marks remain on Latin-initial labels
  • Update packaging_smoke_tests.rs to require all locale messages.ftl files in the packaged crate
locales/ar/messages.ftl
locales/cs/messages.ftl
locales/cy/messages.ftl
locales/da/messages.ftl
locales/de/messages.ftl
locales/el/messages.ftl
locales/en-GB/messages.ftl
locales/es-419/messages.ftl
locales/fa/messages.ftl
locales/fi/messages.ftl
locales/fr/messages.ftl
locales/gd/messages.ftl
locales/he/messages.ftl
locales/hi/messages.ftl
locales/hu/messages.ftl
locales/id/messages.ftl
locales/it/messages.ftl
locales/ja/messages.ftl
locales/ko/messages.ftl
locales/nb/messages.ftl
locales/nl/messages.ftl
locales/pl/messages.ftl
locales/pt-BR/messages.ftl
locales/pt-PT/messages.ftl
locales/ro/messages.ftl
locales/ru/messages.ftl
locales/sv/messages.ftl
locales/th/messages.ftl
locales/tr/messages.ftl
locales/uk/messages.ftl
locales/vi/messages.ftl
locales/zh-Hans/messages.ftl
locales/zh-Hant/messages.ftl
tests/locale_catalogue_tests.rs
tests/localization_tests.rs
tests/packaging_smoke_tests.rs
docs/translators-guide.md
docs/users-guide.md
CHANGELOG.md
Clarify and document the localization design, translator workflow, and Polonius/tooling constraints to keep docs aligned with the new locale system.
  • Rewrite translators-guide.md to describe the locale registry, shipped locales, fallback policy, file layout, plural categories per locale, RTL handling, and updated "adding a locale" workflow
  • Update users-guide.md with a --locale section listing tags, languages, resolution order, and the decision to keep release help en-US-only
  • Extend docs/netsuke-design.md to describe the registry, the widened audit (including per-locale loop and variable checks), and include a Mermaid flowchart covering the new audit process
  • Tighten Polonius-related docs (polonius.md, adr-006) and developer guidance around toolchain flags and test execution; align AGENTS.md and README.md wording
  • Adjust sample-netsuke.toml to mention BCP 47 tags and the fallback behaviour
docs/translators-guide.md
docs/users-guide.md
docs/netsuke-design.md
docs/polonius.md
docs/adr-006-adopt-polonius-nightly-toolchain.md
docs/developers-guide.md
AGENTS.md
README.md
docs/sample-netsuke.toml

Assessment against linked issues

Issue Objective Addressed Explanation
#466 Add complete Fluent catalogues for all 33 new locales (plus auditing es-ES against en-US) and implement exact-tag locale selection with distinct fallback rules for variants such as es-419/es-ES, pt-BR/pt-PT, zh-Hans/zh-Hant.
#466 Make build-time localization audit and build tooling consume a single locale registry, validate every declared locale for missing/orphaned keys and variable mismatches, and ensure packaging includes all catalogues.
#466 Update tests and documentation to cover all supported locales, fallback behaviour, plural categories, Unicode/RTL rendering, and state the locale policy; keep the quality gates (make check-fmt, make lint, make test, make markdownlint, make nixie) passing.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

codescene-access[bot]

This comment was marked as outdated.

@leynos

leynos commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

build_l10n_audit/ftl.rs

Comment on file

//! Minimal Fluent parser used by the build-time localization audit.

❌ New issue: String Heavy Function Arguments
In this module, 58.3% of all arguments to its 7 functions are strings. The threshold for string arguments is 39.0%

@leynos

leynos commented Aug 1, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

build_l10n_audit/keys.rs

Comment on file

//! Localization audit helpers for the build script.
//! Extraction of Fluent message identifiers declared in Rust source.

❌ New issue: Primitive Obsession
In this module, 30.6% of all function arguments are primitive types, threshold = 30.0%

@coderabbitai

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

@leynos
leynos marked this pull request as ready for review August 1, 2026 20:19

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sorry @leynos, your pull request is larger than the review limit of 150000 diff characters

@coderabbitai coderabbitai Bot added the Issue label Aug 1, 2026
chatgpt-codex-connector[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

@leynos

leynos commented Aug 2, 2026

Copy link
Copy Markdown
Owner Author

Pre-merge checks, addressed as of e3238f7.

❌ Rust Compiler Lint Integrity — fixed. The module-wide #[expect(dead_code)] on the build script's cli_localization was forced by one symbol: a pub fn resolve_catalogue_tag that existed only so tests could name a resolution result. It is gone, and so is the expectation — build.rs now compiles that module under ordinary dead-code analysis. The behaviour it encoded is covered where it actually lives: tests/locale_registry_tests.rs resolves through locales::resolve_catalogue directly, and tests/localization_tests.rs drives build_localizer with an unparseable tag, an empty tag, a region with no catalogue of its own, and both script variants.

❌ Testing (Overall) — fixed. The comparison rules moved out of the file-reading and registry-walking code into build_l10n_audit/compare.rs so they can be exercised directly. tests/build_l10n_parser_tests.rs now includes ftl.rs, metadata.rs, and compare.rs by path and asserts that a missing declared key, an orphaned key, a dropped variable, an invented variable, and a renamed variable each fail the audit, and that one catalogue breaking several rules reports all of them rather than the first. 30 tests in that file; 1309 in the suite.

⚠️ Testing (Unit And Behavioural) — fixed by the same change: ftl::parse_catalogue now has direct coverage, and every_locale_renders_and_interpolates walks the registry rather than sampling en-US/es-ES.

⚠️ Testing (Property / Proof) — fixed. Two proptests over generated tags: resolution is total (every input lands on a catalogue that is in the registry), and a tag whose language ships a catalogue never resolves to a different language. The second generates its language list from the registry, so a new locale is covered without touching the test.

⚠️ Observability — fixed. A catalogue that fails to parse was silent, which is indistinguishable from a locale simply having no translations; it now warns with the tag and the error. Resolution emits a debug event carrying both requested and effective tags, so a "why is this rendering in English" report can be answered from a log. The point about tracing starting only after configure_runtime is correct and is inherent: --help must render before Netsuke knows which configuration file to read.

⚠️ User-Facing Documentation — fixed, and thank you. This was a real error in the docs, not a presentation quibble. startup_localizer (src/main.rs:86) resolves before the configuration merge; configure_runtime (src/main.rs:157) resolves after. The configuration file therefore cannot affect --help or clap parse errors. Both docs/users-guide.md and docs/translators-guide.md now give the two precedence lists separately and name the function that performs each.

⚠️ Developer Documentation — fixed. docs/developers-guide.md gains a Localization section: the registry as sole source of truth, the API surface, the fallback contract and why the region and script variants need explicit rules, the two-phase resolution, and what adding a message requires.

⚠️ Out of Scope Changes — already fixed, in a53ea67. A make fmt run had swept unrelated documentation (polonius.md, adr-006, snapshot-testing, and most of developers-guide.md and users-guide.md) into the diff. Those files were reverted to origin/main and only this PR's own edits re-applied. The current diff against main touches no documentation outside the localization work.

⚠️ Testing (Compile-Time / Ui) — dismissed as disproportionate. The guarantee is already unconditional: define_locales! expands to include_str!("../../locales/<tag>/messages.ftl") for every declared tag, so a tag without a catalogue is a hard compile error in the crate itself — there is no path by which it reaches a test. A trybuild fixture would need its own crate, its own copy of the macro, and a pinned stderr snapshot that breaks on rustc diagnostic churn, to re-assert a property the primary build already enforces on every compile. Happy to open a follow-up issue if a UI-test harness is wanted repo-wide, but as a condition of this PR it is machinery without a new guarantee.

❓ Unit Architecture — validated here. Scoped to this PR's changes: src/localization/locales.rs is the sole locale list, and the four other consumers derive from it rather than repeating it — build.rs generates its rerun-if-changed directives from SUPPORTED_LOCALES, build_l10n_audit/mod.rs walks it, tests/packaging_smoke_tests.rs checks the shipped files against it, and the catalogue tests iterate it. The one unavoidable duplicate is Cargo.toml's package.metadata.ortho_config.locales, because Cargo metadata cannot call into Rust; the audit compares the two and fails the build on drift, so it cannot silently diverge. Module boundaries: the audit is split by input kind — keys.rs (the define_keys! macro), ftl.rs (catalogues), metadata.rs (Cargo metadata), compare.rs (the rules) — with mod.rs holding only I/O and orchestration. That split is what made the audit rules testable at all, since build scripts are not test targets. No module exceeds 341 lines; the largest is the byte-level define_keys! scanner.

❓ Architectural Complexity And Maintainability — validated here. cs review on every file this PR adds or substantially changes returns 10.0: locales.rs, cli_localization.rs, and all five build_l10n_audit modules. cs delta main HEAD reports no new code-health issues. The one CodeScene finding this PR carries is a documented rule-set suppression in .codescene/code-health-rules.json for String Heavy Function Arguments over build_l10n_audit/**, with the reasoning recorded in matching_content_path_doc and a stated condition for reassessment: those are hand-rolled scanners over borrowed source text, so their private helpers necessarily take &str views into a caller-owned buffer, and both proposed remedies — a context struct, or owned String — add indirection or per-line allocation across 35 catalogues without improving the design. The maintenance cost of adding a locale is bounded and mechanical: one registry line, one Cargo.toml line, one catalogue file, with the build failing on any inconsistency between them.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

@buzzybee-df12

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]

This comment was marked as resolved.

codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

Comment thread locales/fa/messages.ftl Outdated
Repository owner deleted a comment from coderabbitai Bot Aug 3, 2026
codescene-access[bot]

This comment was marked as outdated.

The tracing_capture introduction still described the retired OFF-filter
design, in which early events could not be written at all. The filter now
starts at WARN and writes through StartupWriter, so the paragraph states
the buffered design and defers the detail to the startup diagnostics
buffering subsection. The design document's locale precedence folded
configuration into one chain, implying a config file could steer CLI help
and clap errors; it now describes the two phases — startup_localizer
before the merge, configure_runtime after it — and which sources each one
can consult.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
codescene-access[bot]

This comment was marked as outdated.

codescene-access[bot]

This comment was marked as outdated.

@leynos

leynos commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

docs/translators-guide.md (4)

449-450: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Separate catalogue findings from metadata drift.
Change the final sentence. Metadata drift reports differences between Cargo.toml

and the registry; it does not name a locale or keys. State that catalogue

findings name the locale and affected keys, while metadata drift reports the two

lists. Match the wording to build_l10n_audit/mod.rs.

🤖 Detailed instructions

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs/translators-guide.md around lines 449 - 450, Update the final sentence
in the translation audit documentation to distinguish catalogue findings from
metadata drift: state that catalogue findings identify the locale and affected
keys, while metadata drift reports the two differing lists. Align the wording
with the behavior implemented in build_l10n_audit.

68-72: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Describe fallback coverage for all variants.
Replace the two variants on Line 72 with all variants. State that an existing

LANGUAGE_FALLBACKS rule must be extended when the language already has multiple

catalogues. Adding a third variant requires deterministic coverage for every

relevant region and script.

🤖 Detailed instructions

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs/translators-guide.md around lines 68 - 72, Update the locale-variant
guidance in the translator documentation to refer to all variants, not “the two
variants.” Clarify that existing LANGUAGE_FALLBACKS rules must be extended when
a language already has multiple catalogues, with deterministic coverage for
every relevant region and script when adding another variant.

52-66: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Correct the number of independent locale lists.
Change with one deliberate exception on Line 57 to with two deliberate exceptions, or explain why one list is excluded. Lines 59-66 identify both

Cargo.toml and EXPECTED_SHIPPED_TAGS as independent lists. Keep this

description aligned with the registration checklist.

🤖 Detailed instructions

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs/translators-guide.md around lines 52 - 66, Update the locale registry
description to state “with two deliberate exceptions,” matching the
independently maintained lists in Cargo.toml and EXPECTED_SHIPPED_TAGS. Keep the
surrounding explanation and registration checklist references consistent with
both exceptions.

90-90: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Document the bare zh fallback.
State that bare zh resolves to zh-Hans; the registry rule and test already define this behaviour.

🤖 Detailed instructions

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs/translators-guide.md at line 90, Update the zh entry in the
translator guide’s locale-resolution table to explicitly state that bare zh
falls back to zh-Hans, while preserving the existing script and regional
resolution rules.

@leynos

leynos commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== revision =='
git rev-parse --short HEAD

printf '%s\n' '== translators guide: reported sections =='
nl -ba docs/translators-guide.md | sed -n '48,96p;438,458p'

printf '%s\n' '== implementation: metadata drift and audit reporting =='
rg -n -C 8 --glob '*.rs' \
  'metadata.*drift|Cargo\.toml|SUPPORTED_LOCALES|metadata_locales|build_error_message|LocaleFindings|missing|orphaned' \
  build_l10n_audit

printf '%s\n' '== implementation: language fallbacks and Chinese resolution =='
rg -n -C 8 --glob '*.rs' \
  'LANGUAGE_FALLBACKS|zh-Hans|zh-Hant|resolve_catalogue|LanguageIdentifier' \
  src/locale_catalogues.rs tests/locale_registry_tests.rs

Length of output: 1132


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== revision =='
git rev-parse --short HEAD

printf '%s\n' '== translators guide: reported sections =='
awk 'NR >= 48 && NR <= 96 { printf "%4d  %s\n", NR, $0 } NR >= 438 && NR <= 458 { printf "%4d  %s\n", NR, $0 }' \
  docs/translators-guide.md

printf '%s\n' '== audit implementation =='
rg -n -C 6 --glob '*.rs' \
  'metadata.*drift|Cargo\.toml|SUPPORTED_LOCALES|parse_metadata_locales|build_error_message|LocaleFindings|missing|orphaned' \
  build_l10n_audit

printf '%s\n' '== fallback implementation and tests =='
rg -n -C 6 --glob '*.rs' \
  'LANGUAGE_FALLBACKS|zh-Hans|zh-Hant|resolve_catalogue|LanguageIdentifier' \
  src/locale_catalogues.rs tests/locale_registry_tests.rs

Length of output: 47299


@leynos Mark all four findings as resolved at revision 5a25d23.

  • Independent locale lists: docs/translators-guide.md Lines 57-66 correctly state that Cargo.toml metadata and EXPECTED_SHIPPED_TAGS are two deliberate exceptions to the registry-owned list.
  • Variant fallback coverage: Lines 70-75 require updates to LANGUAGE_FALLBACKS when a language has multiple catalogues. The text requires deterministic resolution for every relevant region and script.
  • Bare zh fallback: Line 93 states that bare zh resolves to zh-Hans. This matches src/locale_catalogues.rs::LANGUAGE_FALLBACKS and tests/locale_registry_tests.rs.
  • Audit reporting: Lines 452-456 distinguish catalogue findings from metadata drift. Catalogue findings name the locale and affected keys. Metadata drift prints the Cargo.toml and registry lists. This matches build_l10n_audit/mod.rs::audit_cargo_metadata and build_l10n_audit/mod.rs::audit_localization_keys_in.

You are interacting with an AI system.

@leynos

leynos commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

locales/fa/messages.ftl (1)

109-109: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Restore the natural Persian mapping-entry wording.
Replace the current text with wording that clearly states that the input resembles a mapping entry and that the colon is missing.

-manifest.yaml.hint.expected_colon = این به مدخل نگاشت می‌ماند؛ پس از کلید «:» کم است.
+manifest.yaml.hint.expected_colon = این شبیه یک مدخل نگاشت است؛ «:» بعد از کلید جا افتاده است.

Based on learnings from the previous review, restore the correction recorded for this exact locale line.

🤖 Detailed instructions

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @locales/fa/messages.ftl at line 109, Update the
manifest.yaml.hint.expected_colon translation in the Persian messages resource
to clearly state that the input resembles a mapping entry and that the colon is
missing after the key, restoring the reviewed natural Persian wording.

@coderabbitai

This comment was marked as resolved.

en-GB's write_zero now reads "zero bytes written" rather than the bare
io::ErrorKind name. Hindi's files_processed gains an exact [0] variant —
Fluent selects an exact match ahead of any CLDR category, and Hindi's
`one` covers zero, so the catalogue otherwise rendered "0 फ़ाइल" where
"no files were processed" is the natural sentence; the translator
comment documents the override. The Persian expected-colon hint takes
its reviewed wording. The plural oracles keep exact numeric variants as
declared branches and list ("hi", 0) among the idiomatically
numeral-free renderings, so both sweeps still verify the branch that is
actually selected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
codescene-access[bot]

This comment was marked as outdated.

coderabbitai[bot]

This comment was marked as resolved.

codescene-access[bot]

This comment was marked as outdated.

A quoted key names a table as legally as a bare one, and rejecting
quotes made table_end read straight past ["release metadata"] into the
next table — whose locales key it would then return as if it were ours.
Header content is now validated as a dotted TOML key whose segments may
be bare or quoted.

Quotes therefore no longer discriminate array values from headers, so
the scanner earns its keep: scan_prefix tracks array bracket depth
outside strings and comments, and a candidate bracket only ends the
table at depth zero. Headers self-balance on their own line, so a
non-zero depth means a nested value inside a multiline array, however
header-like its content — which also retires the lone-element ambiguity
the previous commit documented. Comments are now skipped during the
scan, so a delimiter or bracket inside one toggles nothing.

Also two translators' guide wording repairs: the exceptions sentence no
longer ends a preposition with a colon, and the plural-rules sentence
names intl_pluralrules as the engine Fluent consults.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@leynos

leynos commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Responding to the two failed pre-merge checks.

Rust Compiler Lint Integrity (error) — declined: the underscore fields are not a suppression of pending work, so an issue-linked #[expect(dead_code)] is the wrong instrument. Each of these fields is held for its Drop — the localizer guard restores the process-global localizer, the mutex guard serializes the window in which that happens, and their declaration order is the invariant under test. The leading underscore is the permanent Rust idiom for a field that is never read but is alive for its destructor, and the code documents this decision explicitly: the comment on RestoreProbe::_guard states that the underscore "is what exempts it from dead_code, rather than an expectation that would outlive any work it could be linked to." An #[expect(dead_code)] tied to an issue would require an issue that can never be closed, because there is no future change that makes these fields readable — reading them is not what they are for. The drop-order tests themselves are implemented and passing (the_lock_is_held_until_the_localizer_is_restored, the_lock_is_still_held_when_the_restore_begins, dropping_the_guard_restores_the_previous_localizer), so there is no "tracking the drop-order test implementation" left to link.

Testing (Compile-Time / Ui) (warning) — declined, as in the previous round, and the grounds have not changed: a trybuild or direct-rustc UI harness is a new dependency or bespoke harness under this PR's standing no-new-dependencies constraint, and the failure it would pin — include_str! on a missing file refusing to compile — is a guarantee of the language, not of this code. The property that is this repository's to verify is that every registered tag has a readable catalogue at the path the build script watches, and every_registry_tag_has_a_readable_catalogue covers it at test time, alongside the audit's own staged-tree mutation cases. If a compile-fail harness is wanted as an enhancement, it belongs in a follow-up issue rather than this PR.

codescene-access[bot]

This comment was marked as outdated.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== revision =='
git rev-parse --short HEAD

printf '%s\n' '== localizer guard structure, documentation, and tests =='
ast-grep outline test_support/src/localizer.rs --items all --view expanded || true
rg -n -C 10 --glob '*.rs' \
  'struct (RestoreProbe|LocaleLocalizer)|_guard|_localizer|impl Drop for|LOCALIZER_TEST_LOCK|the_lock_is_held_until_the_localizer_is_restored|the_lock_is_still_held_when_the_restore_begins|dropping_the_guard_restores_the_previous_localizer' \
  test_support src tests

printf '%s\n' '== locale inclusion mechanism and coverage =='
rg -n -C 10 --glob '*.rs' \
  'macro_rules! define_locales|define_locales!|include_str!\(|every_registry_tag_has_a_readable_catalogue|catalogue_path\(' \
  src build.rs build_l10n_audit tests

Length of output: 182793


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== current revision =='
git rev-parse --short HEAD

printf '%s\n' '== localizer source outline =='
ast-grep outline test_support/src/localizer.rs --items all --view expanded || true

printf '%s\n' '== localizer source =='
cat -n test_support/src/localizer.rs

printf '%s\n' '== localizer drop-order tests =='
if [ -f test_support/src/localizer_tests.rs ]; then
  cat -n test_support/src/localizer_tests.rs
fi

printf '%s\n' '== test module wiring =='
rg -n -C 3 --glob '*.rs' 'mod localizer_tests|localizer_tests' test_support/src

Length of output: 21883


@leynos Both declined findings are valid at revision e1e8fad. Withdraw them.

  • Rust Compiler Lint Integrity: test_support/src/localizer.rs::RestoreProbe::_guard exists for LocalizerGuard::drop. The source documents this purpose and the use of the underscore prefix. EnLocalizer and LocaleLocalizer declare _guard before _lock to restore the process-global localizer before lock release. The three named tests verify the restoration and field-drop-order invariant. Do not add #[expect(dead_code)] or a tracking issue.

  • Testing (Compile-Time / UI): src/locale_catalogues.rs::define_locales! embeds every registered catalogue with include_str!. Rust rejects a missing input during compilation. tests/build_l10n_audit_tests.rs::every_registry_tag_has_a_readable_catalogue verifies the separate repository-owned contract: every registry tag has the on-disk locales/<tag>/messages.ftl path that the audit reads. Do not add a compile-fail harness for this PR.


✏️ Learnings added
Learnt from: leynos
URL: https://github.com/leynos/netsuke/pull/500

Timestamp: 2026-08-05T13:47:06.246Z
Learning: In leynos/netsuke, `test_support/src/localizer.rs::RestoreProbe::_guard`, `EnLocalizer::_guard`, `EnLocalizer::_lock`, `LocaleLocalizer::_guard`, and `LocaleLocalizer::_lock` are intentional RAII fields. Their underscore names express that they exist only for `Drop`. Field declaration order is required: the localizer guard restores the process-global localizer before the mutex guard releases `LOCALIZER_TEST_LOCK`. Do not request an issue-linked `#[expect(dead_code)]` for these fields.

Learnt from: leynos
URL: https://github.com/leynos/netsuke/pull/500

Timestamp: 2026-08-05T13:47:06.246Z
Learning: In leynos/netsuke, `src/locale_catalogues.rs::define_locales!` uses `include_str!` for every registered catalogue, so a missing catalogue is a Rust compilation failure. `tests/build_l10n_audit_tests.rs::every_registry_tag_has_a_readable_catalogue` covers the repository-owned contract that each registry tag has the on-disk catalogue path used by the localization audit. Do not require a separate compile-fail harness for missing `include_str!` catalogue inputs in localization changes.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

codescene-access[bot]

This comment was marked as outdated.

@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@build_l10n_audit/metadata.rs`:
- Around line 102-117: The quoted-header parsing in split_header_name must
recognize escaped quotes instead of treating them as closing delimiters. Track
escape state while scanning quoted content, and apply the same logic in
key_segment_after so table_end stops at the target header and does not consume a
following table’s locales value. Add a regression case where the target table
lacks locales and a subsequent escaped-quote header defines it.
🪄 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: 6e2a9f1b-f54b-4870-899e-c40522519c13

📥 Commits

Reviewing files that changed from the base of the PR and between 5a25d23 and e1e8fad.

📒 Files selected for processing (7)
  • build_l10n_audit/metadata.rs
  • docs/translators-guide.md
  • locales/en-GB/messages.ftl
  • locales/fa/messages.ftl
  • locales/hi/messages.ftl
  • tests/build_l10n_parser_tests.rs
  • tests/localization_plural_tests.rs
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • leynos/rstest-bdd (auto-detected)
  • leynos/ortho-config (auto-detected)
  • leynos/whitaker (auto-detected)
  • leynos/shared-actions (auto-detected)

Comment thread build_l10n_audit/metadata.rs Outdated
@leynos

leynos commented Aug 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

docs/translators-guide.md (1)

286-287: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Complete the plural-rule sentence.
Replace “which is what Fluent selects with” with a complete statement. Name the

plural-rule implementation or API that Fluent uses.
Triage: [type:grammar]

🤖 Detailed instructions

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs/translators-guide.md around lines 286 - 287, Complete the plural-rule
sentence in the translator guide by replacing the fragment “which is what Fluent
selects with” with grammatically complete wording that explicitly names the
plural-rule implementation or API Fluent uses, while preserving the existing
CLDR version caveat.

Sources: Coding guidelines, Path instructions

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== current revision =='
git rev-parse --short HEAD

printf '%s\n' '== reported translator-guide section =='
nl -ba docs/translators-guide.md | sed -n '278,294p'

printf '%s\n' '== Fluent and plural-rule dependencies =='
rg -n -C 3 '^(fluent-bundle|intl_pluralrules|unic-langid)\s*=|fluent_bundle|intl_pluralrules' \
  Cargo.toml Cargo.lock src tests || true

printf '%s\n' '== plural-selection API usage =='
rg -n -C 5 --glob '*.rs' \
  'FluentBundle|FluentResource|format_pattern|plural|PluralRules|intl_pluralrules' \
  src tests test_support || true

Length of output: 1042


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '== current revision =='
git rev-parse --short HEAD

printf '%s\n' '== reported translator-guide section =='
awk 'NR >= 278 && NR <= 294 { printf "%d  %s\n", NR, $0 }' docs/translators-guide.md

printf '%s\n' '== Fluent and plural-rule dependencies =='
rg -n -C 3 '^(fluent-bundle|intl_pluralrules|unic-langid)\s*=|fluent_bundle|intl_pluralrules' \
  Cargo.toml Cargo.lock src tests 2>/dev/null || true

printf '%s\n' '== plural-selection API usage =='
rg -n -C 5 --glob '*.rs' \
  'FluentBundle|FluentResource|format_pattern|plural|PluralRules|intl_pluralrules' \
  src tests test_support 2>/dev/null || true

Length of output: 30666


@leynos docs/translators-guide.md — Lines 286-288

Mark this finding as resolved at revision e1e8fad.

The text now states:

“The categories are the ones the intl_pluralrules crate implements — the plural-rules engine Fluent consults when selecting a variant — and they can lag a newer CLDR release.”

This is a complete sentence. It names intl_pluralrules as the plural-rule implementation. It also preserves the CLDR-version caveat. tests/locale_catalogue_tests.rs confirms the same implementation relationship and records the locked intl_pluralrules version.

You are interacting with an AI system.

split_header_name read the escaped quote in a key like ["a\"b"] as the
close, re-opened on the true close, swallowed the bracket as string
content, and rejected the line — so table_end read past a legal header
and could return the next table's locales as this table's. Quoted
segments are now scanned by closing_quote_at, which treats a backslash
in a basic string as escaping the next character and takes a literal
string verbatim, mirroring step_single_line; key_segment_after shares
it. A regression case pins the escaped-quote header ending the table.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
codescene-access[bot]

This comment was marked as outdated.

@codescene-access codescene-access Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No quality gates enabled for this code.

@leynos
leynos merged commit 1d9894f into main Aug 5, 2026
17 checks passed
@leynos
leynos deleted the issue-466-expand-localization-support branch August 5, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expand localization support to the requested locale set

3 participants