-
-
Notifications
You must be signed in to change notification settings - Fork 1
Developer Guide
This document provides accurate, in-depth technical documentation for contributors and developers working on LocalizerAppMain.
- Architecture Overview
- Dependency Injection
- State Management (BLoC)
- Core Services
- AI Integration
- Database Schema (Hive)
- Testing
- Build Instructions
The application follows a Clean Architecture approach, separating concerns into distinct layers.
lib/
├── business_logic/
│ └── blocs/ # BLoC state management classes
│ ├── comparison_bloc.dart
│ ├── directory_comparison_bloc.dart
│ ├── history_bloc.dart
│ ├── progress_bloc.dart
│ ├── settings_bloc/
│ ├── theme_bloc.dart
│ └── translation_bloc.dart
├── core/
│ ├── di/
│ │ └── service_locator.dart # GetIt dependency injection setup
│ └── services/ # Core business logic services
│ ├── comparison_engine.dart
│ ├── diff_calculator.dart
│ ├── file_watcher_service.dart
│ ├── localization_file_service.dart
│ ├── quality_metrics_service.dart
│ ├── toast_service.dart
│ └── ...
├── data/
│ ├── cache/
│ │ └── translation_cache.dart
│ ├── models/ # Hive-persisted data models
│ │ ├── app_settings.dart
│ │ ├── comparison_history.dart
│ │ └── ...
│ ├── parsers/ # 13 file format parsers
│ │ ├── json_parser.dart
│ │ ├── xml_parser.dart
│ │ └── ...
│ ├── repositories/ # Data access layer
│ │ ├── history_repository.dart
│ │ ├── settings_repository.dart
│ │ └── project_repository.dart
│ └── services/ # External API services
│ ├── gemini_translation_service.dart
│ ├── openai_ai_assistance_service.dart
│ ├── deepl_translation_service.dart
│ └── adaptive_ai_assistance_service.dart
└── presentation/
├── views/ # Main screens
│ ├── basic_comparison_view.dart
│ ├── advanced_diff/
│ ├── settings_view.dart
│ └── ...
└── widgets/ # Reusable UI components
The application uses GetIt as a service locator for dependency injection. All services, repositories, and BLoCs are registered on app startup.
The setupServiceLocator() function is called once at app startup (before runApp()). It performs the following:
-
Registers Lazy Singletons: Most services (e.g.,
ComparisonEngine,FileWatcherService,SecureStorageService) are registered asLazySingleton, meaning they are created only when first accessed. -
Async Repository Initialization:
SettingsRepositoryandLocalHistoryRepositoryrequire asyncinit()calls (to open Hive boxes), so they areawaited and then registered asSingleton.
Accessing Services:
import 'package:localizer_app_main/core/di/service_locator.dart';
// In any file:
final comparisonEngine = sl<ComparisonEngine>();The app uses flutter_bloc with Freezed for immutable events and states.
| BLoC | Responsibility |
|---|---|
ComparisonBloc |
Manages the lifecycle of a file comparison (loading, comparing, results). Receives settings via event parameters to avoid direct coupling with SettingsBloc. |
DirectoryComparisonBloc |
Handles batch comparison of multiple file pairs from directories. |
HistoryBloc |
Manages loading, clearing, and filtering the comparison history. |
SettingsBloc |
Persists and provides access to all AppSettings. |
ThemeBloc |
Manages the UI theme (Light, Dark, Amoled) and accent color. |
ProgressBloc |
Provides a central stream for progress updates during long-running operations (parsing, diffing). |
TranslationBloc |
Coordinates AI translation requests and results. |
Events and states are defined within the same .dart file using Freezed annotations. The .freezed.dart file is auto-generated by build_runner.
Example (comparison_bloc.dart):
// Events
@freezed
class ComparisonEvent with _$ComparisonEvent {
const factory ComparisonEvent.compareFilesRequested(...) = CompareFilesRequested;
const factory ComparisonEvent.proceedWithComparison(...) = ProceedWithComparison;
}
// States
@freezed
class ComparisonState with _$ComparisonState {
const factory ComparisonState.initial() = _Initial;
const factory ComparisonState.loading() = _Loading;
const factory ComparisonState.success(...) = _Success;
const factory ComparisonState.failure(...) = _Failure;
}-
Location:
lib/core/services/comparison_engine.dart - Purpose: The main orchestrator for file comparisons.
-
How it Works:
-
Parsing Phase (0-50%): Calls the appropriate parser (via
LocalizationFileService) for each file. Parsing is run usingcompute()to offload work to a background isolate, preventing UI freezes. -
Diffing Phase (50-95%): Calls
DiffCalculator.calculateDiff(). This is also run in a separate Isolate usingIsolate.spawnwithSendPort/ReceivePortto report granular progress back to the main thread. -
Finalization (95-100%): Wraps the results into a
ComparisonResultobject.
-
Parsing Phase (0-50%): Calls the appropriate parser (via
-
Data Structure: The diff result uses
IMapfromfast_immutable_collectionsfor O(log n) operations, improving performance on large files (50k+ keys).
-
Location:
lib/core/services/diff_calculator.dart -
Purpose: Performs the actual diff logic between two
Map<String, String>data sets. -
Comparison Modes:
- Key-based (Default): Matches entries by key name. Standard for most localization files.
-
Order-based: Matches entries by their index/position in the file. Useful for
.txtor list-of-phrases files. - Smart Match: Starts with key-based matching, then attempts to detect renamed keys by finding orphan source values that closely match orphan target values (using string similarity).
-
String Similarity: The
string_similaritypackage is used to calculate how similar two modified values are, populating thesimilarityfield inComparisonStatusDetail.
-
Location:
lib/core/services/localization_file_service.dart - Purpose: Acts as a factory to select the correct parser for a given file extension and orchestrate parsing/exporting.
The app supports multiple AI providers for translation assistance.
-
Location:
lib/data/services/adaptive_ai_assistance_service.dart -
Purpose: This is the main entry point used by the rest of the app (registered as
AiAssistanceService). It reads the user'stranslationStrategysetting and delegates requests to the appropriate provider. -
Supported Providers:
Provider Service Class Notes Google Gemini GeminiAiAssistanceServiceUses google_generative_aipackage. Supports translation, rephrasing, suggestions.OpenAI OpenAiAiAssistanceServiceUses Dio for API calls. DeepL DeepLTranslationServiceUses Dio. Translation only. Google Translate GoogleTranslationServiceBasic translation via Cloud API.
- API keys are stored securely using
flutter_secure_storage(SecureStorageService). - The keys are retrieved from secure storage when a service is called, not stored in plain text in
AppSettings.
The app uses Hive for local NoSQL persistence. Hive adapters are generated by build_runner.
-
Box Name:
comparison_history_box - Purpose: Stores a record of each comparison made.
| Hive Field | Type | Description |
|---|---|---|
| 0 | String id |
UUID v4 |
| 1 | DateTime timestamp |
Execution time |
| 2 | String file1Path |
Source file path |
| 3 | String file2Path |
Target file path |
| 4 | int stringsAdded |
Count of added keys |
| 5 | int stringsRemoved |
Count of removed keys |
| 6 | int stringsModified |
Count of modified values |
| 7 | int stringsIdentical |
Count of identical values |
| 8 | int? sourceKeyCount |
Total keys in source |
| 9 | int? translatedKeyCount |
Total keys in target |
| 10 | int? sourceWordCount |
Word count in source |
| 11 | int? translatedWordCount |
Word count in target |
| 12 | String? projectId |
ID of the associated project |
-
Box Name:
app_settings_box - Purpose: Stores all user preferences. Contains 80+ fields covering appearance, comparison engine behavior, AI settings, file handling, Git integration, and more.
-
Notable Fields:
Group Example Fields Appearance appThemeMode,accentColorValue,diffAddedColor,diffRemovedColor,diffModifiedColor,diffFontSize,diffFontFamilyComparison Engine ignoreCase,ignoreWhitespace,ignorePatterns,comparisonMode,similarityThresholdFile Handling defaultSourceEncoding,csvDelimiter,autoReloadOnChangeAI Services aiTranslationService,translationStrategy,aiTemperature,maxTokensGit Integration enableGitIntegration,defaultBranch,commitMessageTemplate
The project uses flutter_test for unit and widget tests.
-
Unit Tests: Located in
test/mirroring thelib/structure. -
Key Test Files:
-
test/core/services/diff_calculator_test.dart: Validates the core diffing logic. -
test/data/parsers/*_test.dart: Tests for individual file parsers.
-
Run all tests:
flutter test- Flutter SDK 3.19+
- Windows 10/11 SDK (for Windows builds)
-
Get Dependencies:
flutter pub get
-
Generate Code (Hive Adapters, Freezed classes):
dart run build_runner build --delete-conflicting-outputs
-
Run in Debug Mode:
flutter run -d windows
-
Build Release:
The output will be in
flutter build windows --release
build/windows/x64/runner/Release/.