-
Notifications
You must be signed in to change notification settings - Fork 17
feat(localization): Core localization infrastructure with reactive culture switching #161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat(localization): Core localization infrastructure with reactive culture switching #161
Conversation
|
Great start and thank you for your contribution, although I have a number of questions/remarks:
|
|
@Skyaero42 this is WIP pr, the implementation will be added based on these changes in future pr |
|
Yes, unit tests are required. If you review one of Undead's PR, you get an idea of how he does it. |
|
what can i add next is, if this pr scope allow it:
@Skyaero42 asked why i used System.Reactive?
things to consider:Both Simple interface Using |
|
If this is a WIP PR, then it would be helpfull to mark it as a draft. I tried to see if I could do it from my side, but I don't think I can. |
Done |
046665d to
2dc75bc
Compare
|
implemenled Phase 2 of the comprehensive localization system for GenHub, building on the infrastructure established in Phase 1. This phase creates the complete What's NewResource File Structure (10 files, 278 strings)Created organized
Key Features✅ Hierarchical Organization - Resources organized by functional area Files ChangedNew Files (13 files, 3,428 lines)Resource Files (10 files, 2,780 lines)
Helper Classes (1 file, 64 lines)
Tests (1 file, 384 lines)
Documentation (1 file, 200 lines)
Modified Files (4 files)Project Configuration
Service Updates
Test Updates
Architecture & DesignResource OrganizationResource Key Naming ConventionUses hierarchical dot notation for clarity: Project ConfigurationAdded to <PropertyGroup>
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Strings\*.resx">
<Generator>ResXFileCodeGenerator</Generator>
<CustomToolNamespace>GenHub.Core.Resources.Strings</CustomToolNamespace>
</EmbeddedResource>
</ItemGroup>This configures:
TestingTest CoverageAdded 15 integration tests, all passing ✅ Tests validate:
📖 Usage ExamplesBasic String Retrievalpublic class MyViewModel : ViewModelBase
{
private readonly ILocalizationService _localization;
public MyViewModel(ILocalizationService localization)
{
_localization = localization;
}
public void SaveProfile()
{
// Get a simple string
var saveText = _localization.GetString(
StringResources.UiCommon,
"Button.Save"
);
// Returns: "Save"
}
}Format Strings with Parameters// String in Errors.Validation.resx: "RequiredField" = "{0} is required."
var errorMessage = _localization.GetString(
StringResources.ErrorsValidation,
"RequiredField",
"Profile Name"
);
// Returns: "Profile Name is required."Using StringResources Constants// Strongly-typed resource set names prevent typos
var confirmDelete = _localization.GetString(
StringResources.MessagesConfirmations, // Compile-time checked!
"DeleteProfile",
profileName
);
// Returns: "Are you sure you want to delete {profileName}?"Real-World ViewModel Examplepublic class SettingsViewModel : ViewModelBase
{
private readonly ILocalizationService _localization;
public SettingsViewModel(ILocalizationService localization)
{
_localization = localization;
// Subscribe to culture changes for reactive updates
_localization.CultureChanged
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => UpdateLocalizedProperties());
}
// Property bound to UI
public string ThemeLabel => _localization.GetString(
StringResources.UiSettings,
"Theme.Label"
);
// Property bound to UI
public string LanguageLabel => _localization.GetString(
StringResources.UiSettings,
"Language.Label"
);
private void UpdateLocalizedProperties()
{
// Notify UI that all localized properties have changed
this.RaisePropertyChanged(nameof(ThemeLabel));
this.RaisePropertyChanged(nameof(LanguageLabel));
// ... more properties
}
}📚 Resource File StructureSample: UI.Common.resx<data name="Button.Save" xml:space="preserve">
<value>Save</value>
<comment>Button text for saving changes</comment>
</data>
<data name="Status.Loading" xml:space="preserve">
<value>Loading...</value>
<comment>Displayed while content is loading</comment>
</data>
<data name="Action.Delete" xml:space="preserve">
<value>Delete</value>
<comment>Action to delete an item</comment>
</data>Sample: Errors.Validation.resx<data name="RequiredField" xml:space="preserve">
<value>{0} is required.</value>
<comment>Generic validation error for required fields. {0} = field name</comment>
</data>
<data name="InvalidPath" xml:space="preserve">
<value>The path '{0}' is not valid.</value>
<comment>Path validation error. {0} = the invalid path</comment>
</data>
<data name="ProfileNameTooLong" xml:space="preserve">
<value>Profile name must be {0} characters or less.</value>
<comment>Profile name length validation. {0} = maximum length</comment>
</data>🔍 String Extraction CoverageStrings were systematically extracted from: ViewModels ✅
Services ✅
Constants ✅
What Was NOT ExtractedThe following remain in English as per best practices:
Translator-Friendly Features1. Contextual CommentsEvery string includes a comment explaining:
2. Logical GroupingRelated strings are grouped together: 3. Clear NamingKey names are self-documenting:
4. Format PlaceholdersNumbered placeholders are documented: <comment>
{0} = profile name
{1} = game name
Example: "Profile 'MyProfile' created for The Sims 4"
</comment>5. Translation Tool Support
🚀 Satellite Assembly GenerationHow It WorksWhen culture-specific translations are added (Phase 8-9): Build output structure: Current Status
Metrics
Additional Resources Or Docs
Translation Workflow (For Future)When adding new languages:
|
|
request Review From @Skyaero42 and @undead2146 and @ViTeXFTW |
undead2146
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good so far, I don't have much experience with localisation hence I cannot give a deeper review than just the surface level comments
GenHub/GenHub.Core/Services/Localization/LocalizationService.cs
Outdated
Show resolved
Hide resolved
GenHub/GenHub.Core/Services/Localization/LocalizationService.cs
Outdated
Show resolved
Hide resolved
GenHub/GenHub.Core/Services/Localization/LocalizationService.cs
Outdated
Show resolved
Hide resolved
GenHub/GenHub.Core/Services/Localization/LocalizationService.cs
Outdated
Show resolved
Hide resolved
GenHub/GenHub.Core/Services/Localization/LocalizationService.cs
Outdated
Show resolved
Hide resolved
|
Is this still being worked on @OmarAglan? |
|
@OmarAglan I will be putting this in draft considering no new updates have been made |
770653b to
9bda372
Compare
|
Added 159 missing user-facing strings across 12 resource files comprehensive string extraction audit for GenHub's localization system. The initial resource file had 278 strings, i scanned the entire codebase to identify and add all remaining user-facing strings, bringing the total to 437 localized strings across 12 resource files. New Resource Files
|
|
@OmarAglan is this PR ready for review? |
Yes |
Introduces ILanguageProvider and ILocalizationService interfaces to support resource management and runtime language switching. Also adds System.Reactive package to enable reactive culture change notifications.
Introduces LocalizationOptions for configuring localization behavior and LanguageProvider for discovering available languages, managing resource managers, and validating cultures. These additions support improved localization management and extensibility in the application.
Introduces LocalizationService for runtime language switching, resource management, and reactive culture updates. Adds LocalizationExtensions with culture-aware formatting and utility methods for dates, numbers, currency, percentages, file sizes, pluralization, and culture info.
Introduces LocalizationServicesModule for registering localization-related services and options via dependency injection. Provides extension methods for IServiceCollection to add localization services with optional configuration, Added System.Reactive to Directory.Packages.props and removed explicit version from GenHub.Core.csproj to centralize package version management.
Introduces LanguageProviderTests and LocalizationServiceTests to verify the behavior of language discovery, culture validation, resource management, and localization service features including culture changes, string retrieval, and error handling.
Introduced new .resx resource files for error messages, validation, confirmations, success messages, tooltips, and UI labels to support application localization. Also added documentation describing the localization system design.
Added GenerateSatelliteAssembliesForCore property to support satellite assemblies. Configured .resx files in Resources/Strings as embedded resources with code generation and a custom namespace.
Introduces the StringResources static class to provide strongly-typed access to resource file base names used in the localization system. This improves maintainability and reduces errors when referencing string resources throughout the application.
Extended LocalizationService to allow specifying a resource set when retrieving localized strings. This adds overloads for GetString that accept a resource set parameter, improving flexibility and enabling localization from multiple resource sets. Enhanced logging now includes the resource set for better traceability.
Added comprehensive integration tests for string resource loading and localization infrastructure in StringResourcesTests.cs. Updated localization system architecture documentation with formatting and clarity improvements. Introduced a new localization resources guide detailing resource file structure, naming conventions, usage, and best practices for developers and translators.
Introduces new GetString overloads in ILocalizationService to support retrieving localized strings from specific resource sets, with and without formatting arguments. Updates related test to use explicit object array casting for null arguments.
Reduced the required minimum number of strings in each resource file from 10 to 5 in StringResourcesTests. This change accounts for resource sets that naturally have fewer entries, such as UI.Navigation.
Introduces UI.Tools.resx containing localized strings for the Tools tab, including labels, buttons, status messages, error messages, tooltips, and dialog titles to support tool plugin management in GenHub.
Introduces UI.Downloads.resx containing localized strings for the Downloads tab, including page titles, section headers, download categories, and status messages to support UI text management and localization.
Expanded resource files with additional UI strings for buttons, status messages, section headers, labels, placeholders, and error messages. These changes improve localization and provide more descriptive text for game profiles, navigation, and settings sections.
Introduced several new resource strings for the update dialog, including messages for update availability, release notes, default update notes, up-to-date status, version readiness, and progress percentage. These additions support improved user communication during the update process.
Added service availability, file system, and tool-related error messages to Errors.Operations.resx. Introduced profile validation messages to Errors.Validation.resx. Updated StringResources.cs with new resource base names for tools and downloads UI.
Escaped ampersands as & in UI.Downloads.resx, UI.GameProfiles.resx, and UI.Navigation.resx to ensure correct XML and UI rendering. Updated localization-resources-guide.md to document new resource files, string counts, and recent changes to resource management.
ecf94f5 to
8367163
Compare
There was a problem hiding this 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 implements a comprehensive core localization infrastructure for GenHub, establishing the foundation for multi-language support with reactive culture switching. The implementation uses .NET resource files (.resx) with satellite assemblies following Avalonia's recommended approach.
Key Changes:
- Introduces
ILocalizationServiceandLocalizationServicefor runtime language switching with reactive notifications - Implements
ILanguageProviderandLanguageProviderfor satellite assembly discovery and resource management - Creates 12 resource files with 437 English strings organized by functional area
- Provides comprehensive test coverage with 44 unit tests
- Includes detailed architecture and usage documentation
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
GenHub.Core/Interfaces/Localization/ILocalizationService.cs |
Core service interface for localization with culture management and reactive updates |
GenHub.Core/Interfaces/Localization/ILanguageProvider.cs |
Interface for language discovery and ResourceManager provisioning |
GenHub.Core/Services/Localization/LocalizationService.cs |
Singleton service implementation with thread-safe operations |
GenHub.Core/Services/Localization/LanguageProvider.cs |
Implementation for satellite assembly discovery and caching |
GenHub.Core/Models/Localization/LocalizationOptions.cs |
Configuration model with fallback and logging options |
GenHub.Core/Extensions/Localization/LocalizationExtensions.cs |
Helper methods for culture-aware formatting |
GenHub.Core/Resources/Strings/*.resx |
12 resource files with organized English strings |
GenHub.Core/Resources/Strings/StringResources.cs |
Constants for type-safe resource set access |
GenHub/Infrastructure/DependencyInjection/LocalizationServicesModule.cs |
DI registration with configuration support |
GenHub.Tests.Core/Services/Localization/*.cs |
Comprehensive unit tests (28 + 16 tests) |
GenHub.Tests.Core/Resources/StringResourcesTests.cs |
Integration tests for resource loading |
docs/architecture/localization-system-design.md |
Detailed architecture design document |
docs/localization/localization-resources-guide.md |
Resource organization and usage guide |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Moved and deduplicated Dispose pattern in LocalizationService. Minor formatting and ordering fixes in LanguageProvider and LocalizationExtensions. Cleaned up and condensed localization system architecture documentation.
Eliminated GetString overloads that did not require a resource set from ILocalizationService and LocalizationService. Updated all usages and related tests to explicitly specify the resource set, improving clarity and reducing ambiguity in localization calls.
|
Rebased And Updated, Can You Take Another Look @undead2146 |
This PR implements Core localization infrastructure of the comprehensive localization system for GenHub, establishing the foundational infrastructure for multi-language support. This phase introduces the core services, interfaces, and architecture that will enable seamless translation of the application into multiple languages with runtime language switching.
Core Services & Interfaces
ILocalizationService- Primary service interface for accessing localized strings and managing cultureLocalizationService- Singleton service implementation with reactive culture change notificationsILanguageProvider- Interface for language discovery and resource managementLanguageProvider- Implementation that discovers available languages via satellite assembliesLocalizationOptions- Configuration model for localization behaviorLocalizationExtensions- Helper methods for common localization scenariosKey Features
Reactive Culture Switching - Uses
System.Reactivefor UI-friendly culture change notificationsThread-Safe Operations - All culture switching and resource access is thread-safe
Graceful Fallback - Automatically falls back to English for missing translations
Dynamic Language Discovery - Scans for available languages from satellite assemblies
Culture-Aware Formatting - Extensions for dates, numbers, currency, file sizes, etc.
Comprehensive Testing - 44 unit tests with 100% pass rate
🏗️ Architecture & Design
Service Layer
Reactive Pattern
The service implements reactive culture switching using
System.Reactive:This ensures all UI elements update automatically when the user changes languages.
Thread Safety
lockstatements for culture switching operationsResourceManagerinstancesTest Coverage
28 LocalizationService tests covering:
16 LanguageProvider tests covering:
Basic Setup (Dependency Injection)
In ViewModels
Changing Languages at Runtime
Using Extension Methods