Skip to content

Add support for localization file splitting#25227

Merged
maliming merged 8 commits intoabpframework:devfrom
antonGritsenko:dev
Apr 9, 2026
Merged

Add support for localization file splitting#25227
maliming merged 8 commits intoabpframework:devfrom
antonGritsenko:dev

Conversation

@antonGritsenko
Copy link
Copy Markdown
Contributor

Description

See discussion #25217
The goal of this change is to bring support for multiple JSON files for the same culture. This can be really helpful in case if you have big module and do not want to split it to different resources.

There are few changes in the code, it just removes exception if same culture found.

It can handle duplicate key in same way as it before: last value will win. Order of the files will be handled by the VirtualFileProvider (default: alphabetically). This mean that if same key defined in the different files, then value from the last file will be used (see unit tests)

Checklist

  • I fully tested it as developer / designer and created unit / integration tests
  • I documented it (or no need to document or I will create a separate documentation issue)

How to test it?

  • Create several JSON file with same culture (see unit tests)
  • Values from all files must be added to localization dictionary

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 9, 2026

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
2 out of 3 committers have signed the CLA.

✅ antonGritsenko
✅ maliming
❌ Anton Gritsenko


Anton Gritsenko seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@maliming maliming self-requested a review April 9, 2026 09:26
@maliming maliming added this to the 10.4-preview milestone Apr 9, 2026
@maliming maliming requested a review from Copilot April 9, 2026 09:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for splitting a single culture’s localization texts across multiple JSON files and merging them at load time (with “last value wins” semantics), along with tests and documentation updates.

Changes:

  • Merge multiple localization dictionaries that share the same culture instead of throwing when duplicates are found.
  • Allow duplicate localization keys within JSON input by overwriting previous values.
  • Add new test resources/tests and update localization documentation to describe file-splitting behavior.

Reviewed changes

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

Show a summary per file
File Description
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/VirtualFiles/VirtualFileLocalizationResourceContributorBase.cs Merges dictionaries for the same culture instead of throwing.
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/StaticLocalizationDictionary.cs Adds dictionary merge support for static dictionaries.
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs Removes duplicate-key exception; last value overwrites.
framework/src/Volo.Abp.Localization/Volo/Abp/Localization/ILocalizationDictionary.cs Adds a new Merge member to the public interface.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalizationTestModule.cs Registers a new test resource using split virtual JSON files.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpStringLocalizerFactory_Tests.cs Adds a test asserting merged values from split files.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/AbpLocalization_Tests.cs Adds a test asserting de texts are loaded from multiple files.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/JsonLocalizationDictionaryBuilder_Tests.cs Adds tests for duplicate keys and deep-key collisions.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/de.json Moves some de texts out to a separate file to test merging.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/de_Book.json New de split file containing book-related texts.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/FilesSplit/!en_First.json New split-file fixture to test ordering/overrides.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/FilesSplit/en_Base.json New split-file fixture with base texts.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/FilesSplit/en_Book.json New split-file fixture with book texts.
framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/FilesSplit/zen_Last.json New split-file fixture intended to override earlier values.
docs/en/framework/fundamentals/localization.md Documents multi-file-per-culture merging and override behavior.

Comment thread docs/en/framework/fundamentals/localization.md Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 9, 2026

Codecov Report

❌ Patch coverage is 64.70588% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 50.05%. Comparing base (ebb4f11) to head (9c76057).
⚠️ Report is 112 commits behind head on dev.

Files with missing lines Patch % Lines
...o/Abp/Localization/StaticLocalizationDictionary.cs 50.00% 4 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev   #25227      +/-   ##
==========================================
- Coverage   50.69%   50.05%   -0.64%     
==========================================
  Files        3472     3557      +85     
  Lines      117030   119392    +2362     
  Branches     8826     9014     +188     
==========================================
+ Hits        59327    59766     +439     
- Misses      55894    57824    +1930     
+ Partials     1809     1802       -7     

☔ 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.

Copy link
Copy Markdown
Contributor

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

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

Copy link
Copy Markdown
Contributor

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

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

@maliming
Copy link
Copy Markdown
Member

maliming commented Apr 9, 2026

Hi @antonGritsenko, thanks for this contribution! We've reviewed the PR and made some adjustments on top of your implementation. Here's a summary of the changes:

Core implementation (VirtualFileLocalizationResourceContributorBase)

  • Removed the Merge(ILocalizationDictionary) method from the ILocalizationDictionary interface — adding a new member to a public interface is a breaking change for any external implementations. The merge is now handled entirely inside the contributor using Fill(...).
  • Added explicit OrderBy(f.Name, StringComparer.Ordinal) sorting before iteration, so the "last file wins" behavior is deterministic regardless of the file provider's enumeration order.
  • Optimized the merge loop: the previous approach re-created a new Dictionary on every additional file for the same culture (O(entries × files)). The new approach accumulates all entries into a single raw Dictionary<string, LocalizedString> per culture during the scan and wraps it once at the end.
  • Removed the now-unused _resource field and its assignment in Initialize (it was only referenced in the removed duplicate-culture exception message).

Tests (JsonLocalizationDictionaryBuilder_Tests)

  • Replaced the Should_Handle_Duplicates test — it used duplicate JSON property names, but System.Text.Json already collapses those before our code runs, so the test didn't actually exercise the new behavior. The new test covers a flat key being overridden by a later nested object expansion (which does go through FlattenTexts).
  • Renamed Should_Create_Resource_By_Name_FromSplitFilesShould_Create_Resource_By_Name_From_Split_Files to match the underscore-separated naming convention used throughout the test class.
  • Changed localizer.GetAllStrings() to localizer.GetAllStrings(includeParentCultures: false) to make the intent explicit.

Documentation

  • Added an example file structure diagram and a merge order diagram to make the feature easier to understand for developers.

@antonGritsenko
Copy link
Copy Markdown
Contributor Author

@maliming thanks for improvement! Regarding the Should_Handle_Duplicates - this is more "behavior testing" rather than code testing. I used to such unit tests just to be sure that next update of the code\core\framework will not change the expected behavior.

@maliming
Copy link
Copy Markdown
Member

maliming commented Apr 9, 2026

@antonGritsenko You're right, that's a valid point. I've restored the test with a clearer name (Should_Use_Last_Value_When_Json_Contains_Duplicate_Keys) and added a comment explaining that it's intentionally locking the behavior of System.Text.Json for duplicate JSON property names — so it serves as a regression guard if STJ ever changes this behavior in a future version.

@maliming
Copy link
Copy Markdown
Member

maliming commented Apr 9, 2026

hi

Can you sign the CLA?

https://cla-assistant.io/abpframework/abp?pullRequest=25227

Thanks.

@antonGritsenko
Copy link
Copy Markdown
Contributor Author

@maliming I did, but my name listed twice, not sure why.

@maliming maliming merged commit b1f8cb4 into abpframework:dev Apr 9, 2026
1 of 2 checks passed
@maliming
Copy link
Copy Markdown
Member

maliming commented Apr 9, 2026

Merged! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants