Skip to content

Developer Guide

Alp Yalay edited this page Jan 3, 2026 · 2 revisions

Developer Guide

This document provides accurate, in-depth technical documentation for contributors and developers working on LocalizerAppMain.


Table of Contents

  1. Architecture Overview
  2. Dependency Injection
  3. State Management (BLoC)
  4. Core Services
  5. AI Integration
  6. Database Schema (Hive)
  7. Testing
  8. Build Instructions

Architecture Overview

The application follows a Clean Architecture approach, separating concerns into distinct layers.

Directory Structure

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

Dependency Injection

The application uses GetIt as a service locator for dependency injection. All services, repositories, and BLoCs are registered on app startup.

Key File: lib/core/di/service_locator.dart

The setupServiceLocator() function is called once at app startup (before runApp()). It performs the following:

  1. Registers Lazy Singletons: Most services (e.g., ComparisonEngine, FileWatcherService, SecureStorageService) are registered as LazySingleton, meaning they are created only when first accessed.
  2. Async Repository Initialization: SettingsRepository and LocalHistoryRepository require async init() calls (to open Hive boxes), so they are awaited and then registered as Singleton.

Accessing Services:

import 'package:localizer_app_main/core/di/service_locator.dart';

// In any file:
final comparisonEngine = sl<ComparisonEngine>();

State Management (BLoC)

The app uses flutter_bloc with Freezed for immutable events and states.

Main BLoCs

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.

Event/State Definition (with Freezed)

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;
}

Core Services

ComparisonEngine

  • Location: lib/core/services/comparison_engine.dart
  • Purpose: The main orchestrator for file comparisons.
  • How it Works:
    1. Parsing Phase (0-50%): Calls the appropriate parser (via LocalizationFileService) for each file. Parsing is run using compute() to offload work to a background isolate, preventing UI freezes.
    2. Diffing Phase (50-95%): Calls DiffCalculator.calculateDiff(). This is also run in a separate Isolate using Isolate.spawn with SendPort/ReceivePort to report granular progress back to the main thread.
    3. Finalization (95-100%): Wraps the results into a ComparisonResult object.
  • Data Structure: The diff result uses IMap from fast_immutable_collections for O(log n) operations, improving performance on large files (50k+ keys).

DiffCalculator

  • Location: lib/core/services/diff_calculator.dart
  • Purpose: Performs the actual diff logic between two Map<String, String> data sets.
  • Comparison Modes:
    1. Key-based (Default): Matches entries by key name. Standard for most localization files.
    2. Order-based: Matches entries by their index/position in the file. Useful for .txt or list-of-phrases files.
    3. 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_similarity package is used to calculate how similar two modified values are, populating the similarity field in ComparisonStatusDetail.

LocalizationFileService

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

AI Integration

The app supports multiple AI providers for translation assistance.

Adapter Pattern: AdaptiveAiAssistanceService

  • 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's translationStrategy setting and delegates requests to the appropriate provider.
  • Supported Providers:
    Provider Service Class Notes
    Google Gemini GeminiAiAssistanceService Uses google_generative_ai package. Supports translation, rephrasing, suggestions.
    OpenAI OpenAiAiAssistanceService Uses Dio for API calls.
    DeepL DeepLTranslationService Uses Dio. Translation only.
    Google Translate GoogleTranslationService Basic translation via Cloud API.

API Key Storage

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

Database Schema (Hive)

The app uses Hive for local NoSQL persistence. Hive adapters are generated by build_runner.

ComparisonSession (typeId: 0)

  • 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

AppSettings (typeId: 2)

  • 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, diffFontFamily
    Comparison Engine ignoreCase, ignoreWhitespace, ignorePatterns, comparisonMode, similarityThreshold
    File Handling defaultSourceEncoding, csvDelimiter, autoReloadOnChange
    AI Services aiTranslationService, translationStrategy, aiTemperature, maxTokens
    Git Integration enableGitIntegration, defaultBranch, commitMessageTemplate

Testing

The project uses flutter_test for unit and widget tests.

  • Unit Tests: Located in test/ mirroring the lib/ 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

Build Instructions

Prerequisites

  • Flutter SDK 3.19+
  • Windows 10/11 SDK (for Windows builds)

Steps

  1. Get Dependencies:
    flutter pub get
  2. Generate Code (Hive Adapters, Freezed classes):
    dart run build_runner build --delete-conflicting-outputs
  3. Run in Debug Mode:
    flutter run -d windows
  4. Build Release:
    flutter build windows --release
    The output will be in build/windows/x64/runner/Release/.