Skip to content

V10.3.1/service update#150

Merged
gimlichael merged 6 commits intomainfrom
v10.3.1/service-update
Feb 24, 2026
Merged

V10.3.1/service update#150
gimlichael merged 6 commits intomainfrom
v10.3.1/service-update

Conversation

@gimlichael
Copy link
Copy Markdown
Member

@gimlichael gimlichael commented Feb 22, 2026

This pull request makes improvements to the handling of cultures and regions in the World class, with a focus on filtering out invalid entries and ensuring backward compatibility with ISO region codes. It also adds a comprehensive test to verify that all expected ISO region codes are present. The main changes are grouped below by theme.

Enhancements to region and culture handling:

  • Updated the filtering logic in World.SpecificCultures to exclude cultures with LCID 127, which are incorrectly categorized as specific cultures on some Linux systems.
  • Improved the region collection in World.Regions by skipping statistical regions (numeric codes), using TryAdd for uniqueness, and ordering the results by region name.
  • Added a comment to clarify the exclusion of cultures with LCID 127 for cross-platform consistency.

Codebase improvements:

  • Refactored the addition of cultures and regions to use Decorator.Enclose(...).TryAdd(...) for safer and cleaner collection handling. [1] [2]
  • Added a new test Regions_ShouldContainAllExpectedIsoRegionCodes_ForBackwardCompatibility in WorldTest.cs to verify that all expected ISO region codes are present, ensuring backward compatibility and providing detailed output for missing or added codes.

Summary by CodeRabbit

  • Bug Fixes

    • Cleaner culture/region lists by excluding numeric/statistical entries and improving region ordering.
    • Safer mapping of country ISO Alpha‑2 codes to region data to avoid lookup errors.
  • Tests

    • Updated region tests to validate expected ISO codes across frameworks, renamed a test for backward compatibility, and added richer diagnostics and adjusted thresholds.

@gimlichael gimlichael self-assigned this Feb 22, 2026
Copilot AI review requested due to automatic review settings February 22, 2026 14:08
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 80b86a5 and e1d787c.

📒 Files selected for processing (1)
  • src/Cuemon.Core/Globalization/UnM49DataContainer.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Cuemon.Core/Globalization/UnM49DataContainer.cs

📝 Walkthrough

Walkthrough

World’s population logic now uses safe TryAdd decorators and filters edge-case cultures and numeric region names; Regions ordering changed. UnM49DataContainer now uses a Region lookup cache built from World.Regions. WorldTest replaced a removed test with a backward-compatibility ISO region codes test that emits richer diagnostics.

Changes

Cohort / File(s) Summary
World population and ordering
src/Cuemon.Core/Globalization/World.cs
Switches from direct Add to Decorator.Enclose(...).TryAdd(...), adds using Cuemon.Collections.Generic, filters out cultures with LCID == 127, skips numeric Region.Name entries, and orders Regions by RegionInfo.Name then RegionInfo.NativeName.
Region lookup in data container
src/Cuemon.Core/Globalization/UnM49DataContainer.cs
Introduces a regionsByIsoAlpha2 cache derived from World.Regions and replaces FirstOrDefault/try-catch resolution with a safe dictionary lookup keyed by ISO Alpha-2.
Tests — ISO region compatibility & diagnostics
test/Cuemon.Core.Tests/Globalization/WorldTest.cs
Removes Regions_ShouldReturnAllRegions; adds Regions_ShouldContainAllExpectedIsoRegionCodes_ForBackwardCompatibility that compares an expected ISO Alpha-2 set to World.Regions, emits missing/added code diagnostics, and adjusts assertion thresholds with conditional NET48 vs non-NET48 behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Test
    participant World
    participant UnM49
    participant RegionsCache

    Test->>World: Request Regions collection
    World-->>RegionsCache: Build ordered Regions list (TryAdd, filters)
    World-->>Test: Return Regions

    UnM49->>RegionsCache: Create regionsByIsoAlpha2 from World.Regions
    UnM49->>RegionsCache: Lookup RegionInfo by ISO Alpha-2
    RegionsCache-->>UnM49: RegionInfo or null
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped through cultures, neat and spry,

Skipping numbers that made me sigh.
I cached my regions, tidy and true,
Tests now whisper what I already knew.
A rabbit's nibble — order renewed. 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'V10.3.1/service update' is vague and generic, using non-descriptive terms that do not convey meaningful information about the specific changes (culture/region handling improvements, statistical region filtering, TryAdd refactoring, or test additions). Consider using a more descriptive title like 'Improve World class region/culture handling and add ISO region code coverage test' to clearly communicate the main changes to reviewers.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch v10.3.1/service-update

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

❤️ Share

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

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request aims to improve the World class's handling of cultures and regions for better cross-platform consistency and backward compatibility with ISO region codes. However, the implementation contains critical bugs that prevent it from achieving its goals.

Changes:

  • Added filtering of cultures with LCID 127 to prevent incorrectly categorized invariant cultures on Linux systems
  • Refactored dictionary operations to use Decorator.Enclose().TryAdd() for safer collection handling
  • Added filtering of statistical regions (numeric codes) from the regions collection
  • Added ordering of regions by ISO code name and a comprehensive backward compatibility test

Reviewed changes

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

File Description
src/Cuemon.Core/Globalization/World.cs Modified culture and region collection logic, added filtering for LCID 127 and statistical regions, changed dictionary keys and added ordering
test/Cuemon.Core.Tests/Globalization/WorldTest.cs Added comprehensive test to verify all expected ISO region codes are present for backward compatibility
Comments suppressed due to low confidence (2)

src/Cuemon.Core/Globalization/World.cs:18

  • The comment is excessively long and should be more concise. Additionally, it uses "should not happen" which is informal phrasing.

Consider shortening to:

// Filter out cultures with LCID 127 (invariant culture) that may be incorrectly categorized as specific cultures on some Linux systems.
            foreach (var c in specificCultures.Where(ci => ci.LCID != 127)) // *should* not happen for specific cultures, but on some linux based systems there are some cultures with LCID 127 (invariant culture) that are incorrectly categorized as specific cultures, so we need to filter those out.

src/Cuemon.Core/Globalization/World.cs:20

  • The key for the cultures dictionary has been changed from c.DisplayName to c.Name. While c.Name is a more appropriate key (it's the culture identifier like "en-US"), this change differs from the previous behavior.

The old code used c.DisplayName as the key, which could be non-unique across different locales (e.g., "English (United States)" could appear differently depending on the current culture). Using c.Name (the culture identifier) as the key is more correct and ensures uniqueness.

However, verify that this change doesn't break any existing code that might depend on the ordering or content of the collection. The SortedList will now sort by culture name (e.g., "ar-SA", "en-US", "zh-CN") instead of display name.

                Decorator.Enclose(cultures).TryAdd(c.Name, c);

Comment thread test/Cuemon.Core.Tests/Globalization/WorldTest.cs
Comment thread src/Cuemon.Core/Globalization/World.cs Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/Cuemon.Core/Globalization/World.cs (1)

34-34: Materialise the OrderBy result to avoid re-sorting on every enumeration.

regions.Values.OrderBy(...) returns a lazy IOrderedEnumerable<RegionInfo>. This lazy sequence is stored in the Lazy<> value and then directly in the Regions static property, meaning every caller that iterates World.Regions triggers a full sort pass over all entries. A single .ToList() (or .ToArray()) call inside the Lazy initializer would sort once and amortise the cost.

⚡ Proposed fix — materialise once
-            return regions.Values.OrderBy(info => info.Name);
+            return regions.Values.OrderBy(info => info.Name).ToList();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Cuemon.Core/Globalization/World.cs` at line 34, The current Lazy
initializer returns regions.Values.OrderBy(info => info.Name) which yields a
lazy IOrderedEnumerable and causes World.Regions to re-sort on each enumeration;
update the Lazy value produced by the initializer (the expression that builds
Regions) to materialize the ordered sequence (e.g., append .ToList() or
.ToArray() to regions.Values.OrderBy(info => info.Name)) so the sort is
performed once and subsequent enumerations use the cached materialized
collection.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Cuemon.Core/Globalization/World.cs`:
- Around line 31-34: World.Regions is adding duplicate RegionInfo entries
because TryAdd is using the culture key c.Name (e.g., "en-US") instead of the
region key; change the TryAdd call in the loop that iterates
SpecificCultures.Value so it keys the SortedList by the region identifier (use
region.Name, or better region.TwoLetterISORegionName) instead of c.Name,
ensuring Decorator.Enclose(regions).TryAdd(...) deduplicates actual regions and
preserves StringComparer.OrdinalIgnoreCase semantics.

In `@test/Cuemon.Core.Tests/Globalization/WorldTest.cs`:
- Around line 56-65: The test throws a NullReferenceException because missing
codes come from expectedTwoLetterIsoCodes but aren't present in World.Regions,
and the code calls .EnglishName on a null result while also re-enumerating
World.Regions; fix by reusing the materialized collection sut1 (the list derived
from World.Regions) for lookups and perform a null-safe lookup when writing
TestOutput.WriteLine for both missing and added: retrieve the matching
RegionInfo from sut1 (e.g., via FirstOrDefault/SingleOrDefault), check for null
and fall back to printing the code or a placeholder instead of accessing
.EnglishName on null, and avoid re-enumerating World.Regions inside the loops.

---

Nitpick comments:
In `@src/Cuemon.Core/Globalization/World.cs`:
- Line 34: The current Lazy initializer returns regions.Values.OrderBy(info =>
info.Name) which yields a lazy IOrderedEnumerable and causes World.Regions to
re-sort on each enumeration; update the Lazy value produced by the initializer
(the expression that builds Regions) to materialize the ordered sequence (e.g.,
append .ToList() or .ToArray() to regions.Values.OrderBy(info => info.Name)) so
the sort is performed once and subsequent enumerations use the cached
materialized collection.

Comment thread src/Cuemon.Core/Globalization/World.cs Outdated
Comment thread test/Cuemon.Core.Tests/Globalization/WorldTest.cs
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.68%. Comparing base (32af67f) to head (e1d787c).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #150      +/-   ##
==========================================
+ Coverage   80.66%   80.68%   +0.02%     
==========================================
  Files         600      600              
  Lines       18932    18937       +5     
  Branches     1949     1950       +1     
==========================================
+ Hits        15272    15280       +8     
+ Misses       3592     3589       -3     
  Partials       68       68              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/Cuemon.Core/Globalization/UnM49DataContainer.cs Fixed
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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

Duplicate comments:
In `@src/Cuemon.Core/Globalization/World.cs`:
- Line 32: The current dedupe key uses $"{region.Name}:{region.NativeName}"
which allows multiple RegionInfo entries per ISO code; change the uniqueness key
in the Decorator.Enclose(regions).TryAdd call to use the ISO code only (e.g.
region.TwoLetterISORegionName or region.Name) so entries are unique by ISO code,
or if multi-entry per ISO is intended update the World.Regions XML doc to
explicitly state that Regions may contain multiple RegionInfo objects per ISO
code and describe implications for consumers; locate the
Decorator.Enclose(regions).TryAdd invocation in World.cs and update either the
key expression to region.TwoLetterISORegionName (or region.Name) or the XML
comment for Regions accordingly.

In `@test/Cuemon.Core.Tests/Globalization/WorldTest.cs`:
- Around line 58-65: The test currently dereferences null when logging
missing/added entries and re-enumerates World.Regions; change the diagnostic
loops to use the already-materialized sut1 collection (instead of World.Regions)
and perform a null-safe lookup (e.g., FirstOrDefault/SingleOrDefault into a
local variable) before accessing EnglishName, writing a clear message that
handles null (e.g., "not found") via TestOutput.WriteLine for each code, and
ensure these logs run before Assert.Empty(missing) so the assertion failure is
visible.

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@sonarqubecloud
Copy link
Copy Markdown

@gimlichael gimlichael merged commit 5dc10dc into main Feb 24, 2026
605 of 606 checks passed
@gimlichael gimlichael deleted the v10.3.1/service-update branch February 24, 2026 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants