re-write localization service and add translation extension
This commit is contained in:
@@ -6,7 +6,6 @@ import 'dart:ui' show DartPluginRegistrant, IsolateNameServer, PluginUtilities;
|
||||
|
||||
import 'package:cancellation_token_http/http.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
@@ -34,6 +33,7 @@ import 'package:immich_mobile/utils/bootstrap.dart';
|
||||
import 'package:immich_mobile/utils/diff.dart';
|
||||
import 'package:immich_mobile/utils/http_ssl_options.dart';
|
||||
import 'package:path_provider_foundation/path_provider_foundation.dart';
|
||||
import 'package:immich_mobile/extensions/translation_extensions.dart';
|
||||
import 'package:photo_manager/photo_manager.dart' show PMProgressHandler;
|
||||
|
||||
final backgroundServiceProvider = Provider((ref) => BackgroundService());
|
||||
@@ -76,8 +76,7 @@ class BackgroundService {
|
||||
Future<bool> enableService({bool immediate = false}) async {
|
||||
try {
|
||||
final callback = PluginUtilities.getCallbackHandle(_nativeEntry)!;
|
||||
final String title =
|
||||
"backup_background_service_default_notification".tr();
|
||||
final String title = 'backup_background_service_default_notification'.t();
|
||||
final bool ok = await _foregroundChannel
|
||||
.invokeMethod('enable', [callback.toRawHandle(), title, immediate]);
|
||||
return ok;
|
||||
@@ -325,7 +324,8 @@ class BackgroundService {
|
||||
return false;
|
||||
}
|
||||
|
||||
final translationsOk = await loadTranslations();
|
||||
final translationsOk =
|
||||
await EasyLocalizationService().loadTranslations();
|
||||
if (!translationsOk) {
|
||||
debugPrint("[_callHandler] could not load translations");
|
||||
}
|
||||
@@ -452,8 +452,8 @@ class BackgroundService {
|
||||
toUpload = await backupService.removeAlreadyUploadedAssets(toUpload);
|
||||
} catch (e) {
|
||||
_showErrorNotification(
|
||||
title: "backup_background_service_error_title".tr(),
|
||||
content: "backup_background_service_connection_failed_message".tr(),
|
||||
title: 'backup_background_service_error_title'.t(),
|
||||
content: 'backup_background_service_connection_failed_message'.t(),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@@ -468,7 +468,7 @@ class BackgroundService {
|
||||
_assetsToUploadCount = toUpload.length;
|
||||
_uploadedAssetsCount = 0;
|
||||
_updateNotification(
|
||||
title: "backup_background_service_in_progress_notification".tr(),
|
||||
title: 'backup_background_service_in_progress_notification'.t(),
|
||||
content: notifyTotalProgress
|
||||
? formatAssetBackupProgress(
|
||||
_uploadedAssetsCount,
|
||||
@@ -502,8 +502,8 @@ class BackgroundService {
|
||||
|
||||
if (!ok && !_cancellationToken!.isCancelled) {
|
||||
_showErrorNotification(
|
||||
title: "backup_background_service_error_title".tr(),
|
||||
content: "backup_background_service_backup_failed_message".tr(),
|
||||
title: 'backup_background_service_error_title'.t(),
|
||||
content: 'backup_background_service_backup_failed_message'.t(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -561,8 +561,8 @@ class BackgroundService {
|
||||
|
||||
void _onBackupError(ErrorUploadAsset errorAssetInfo) {
|
||||
_showErrorNotification(
|
||||
title: "backup_background_service_upload_failure_notification"
|
||||
.tr(namedArgs: {'filename': errorAssetInfo.fileName}),
|
||||
title: 'backup_background_service_upload_failure_notification'
|
||||
.t({'filename': errorAssetInfo.fileName}),
|
||||
individualTag: errorAssetInfo.id,
|
||||
);
|
||||
}
|
||||
@@ -576,8 +576,8 @@ class BackgroundService {
|
||||
}
|
||||
|
||||
_throttledDetailNotify.title =
|
||||
"backup_background_service_current_upload_notification"
|
||||
.tr(namedArgs: {'filename': currentUploadAsset.fileName});
|
||||
'backup_background_service_current_upload_notification'
|
||||
.t({'filename': currentUploadAsset.fileName});
|
||||
_throttledDetailNotify.progress = 0;
|
||||
_throttledDetailNotify.total = 0;
|
||||
}
|
||||
|
||||
@@ -1,31 +1,128 @@
|
||||
// ignore_for_file: implementation_imports
|
||||
|
||||
import 'package:easy_localization/src/easy_localization_controller.dart';
|
||||
import 'package:easy_localization/src/localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:immich_mobile/constants/locales.dart';
|
||||
import 'package:immich_mobile/generated/codegen_loader.g.dart';
|
||||
|
||||
/// Workaround to manually load translations in another Isolate
|
||||
Future<bool> loadTranslations() async {
|
||||
await EasyLocalizationController.initEasyLocation();
|
||||
|
||||
final controller = EasyLocalizationController(
|
||||
supportedLocales: locales.values.toList(),
|
||||
useFallbackTranslations: true,
|
||||
saveLocale: true,
|
||||
assetLoader: const CodegenLoader(),
|
||||
path: translationsPath,
|
||||
useOnlyLangCode: false,
|
||||
onLoadError: (e) => debugPrint(e.toString()),
|
||||
fallbackLocale: locales.values.first,
|
||||
);
|
||||
|
||||
await controller.loadTranslations();
|
||||
|
||||
return Localization.load(
|
||||
controller.locale,
|
||||
translations: controller.translations,
|
||||
fallbackTranslations: controller.fallbackTranslations,
|
||||
);
|
||||
}
|
||||
// ignore_for_file: implementation_imports
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:easy_localization/src/easy_localization_controller.dart';
|
||||
import 'package:easy_localization/src/localization.dart';
|
||||
|
||||
import 'package:intl/message_format.dart';
|
||||
import 'package:immich_mobile/constants/locales.dart';
|
||||
import 'package:immich_mobile/generated/codegen_loader.g.dart';
|
||||
|
||||
abstract class ILocalizationService {
|
||||
String translate(String key, [Map<String, Object>? args]);
|
||||
|
||||
Locale get currentLocale;
|
||||
|
||||
bool get isInitialized;
|
||||
|
||||
Future<bool> loadTranslations();
|
||||
|
||||
Future<void> changeLocale(Locale localeCode);
|
||||
}
|
||||
|
||||
class EasyLocalizationService implements ILocalizationService {
|
||||
EasyLocalizationService._internal();
|
||||
|
||||
static EasyLocalizationService? _instance;
|
||||
static EasyLocalizationService get instance {
|
||||
_instance ??= EasyLocalizationService._internal();
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
factory EasyLocalizationService() => instance;
|
||||
|
||||
static BuildContext? _context;
|
||||
static EasyLocalizationController? _controller;
|
||||
static bool _isInitialized = false;
|
||||
|
||||
static void setContext(BuildContext context) {
|
||||
if (_context != context) {
|
||||
debugPrint('🔄 Updating EasyLocalization context');
|
||||
_context = context;
|
||||
}
|
||||
}
|
||||
|
||||
static BuildContext? get context => _context;
|
||||
|
||||
@override
|
||||
String translate(String key, [Map<String, Object>? args]) {
|
||||
if (_context != null) {
|
||||
try {
|
||||
String message = _context!.tr(key);
|
||||
if (args != null) {
|
||||
return MessageFormat(message, locale: Intl.defaultLocale ?? 'en')
|
||||
.format(args);
|
||||
}
|
||||
return message;
|
||||
} catch (e) {
|
||||
debugPrint('❌ Translation error for key "$key": $e');
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
@override
|
||||
Locale get currentLocale {
|
||||
if (_controller != null) {
|
||||
return _controller!.locale;
|
||||
}
|
||||
if (_context != null) {
|
||||
return _context!.locale;
|
||||
}
|
||||
return Intl.defaultLocale != null
|
||||
? Locale(Intl.defaultLocale!)
|
||||
: locales.values.first;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isInitialized => _isInitialized;
|
||||
|
||||
@override
|
||||
Future<void> changeLocale(Locale localeCode) async {
|
||||
try {
|
||||
if (_context != null) {
|
||||
await _context!.setLocale(localeCode);
|
||||
}
|
||||
if (_controller != null) {
|
||||
await _controller!.setLocale(localeCode);
|
||||
}
|
||||
debugPrint('✅ Locale changed to: $localeCode');
|
||||
} catch (e) {
|
||||
debugPrint('❌ Failed to change locale to $localeCode: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> loadTranslations() async {
|
||||
if (_isInitialized) {
|
||||
debugPrint('✅ Translations already loaded');
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
await EasyLocalizationController.initEasyLocation();
|
||||
_controller = EasyLocalizationController(
|
||||
supportedLocales: locales.values.toList(),
|
||||
useFallbackTranslations: true,
|
||||
saveLocale: true,
|
||||
assetLoader: const CodegenLoader(),
|
||||
path: translationsPath,
|
||||
useOnlyLangCode: false,
|
||||
onLoadError: (e) => debugPrint(e.toString()),
|
||||
fallbackLocale: locales.values.first,
|
||||
);
|
||||
await _controller!.loadTranslations();
|
||||
final bool result = Localization.load(
|
||||
_controller!.locale,
|
||||
translations: _controller!.translations,
|
||||
fallbackTranslations: _controller!.fallbackTranslations,
|
||||
);
|
||||
_isInitialized = result;
|
||||
debugPrint('✅ Translations loaded: $result');
|
||||
return result;
|
||||
} catch (e) {
|
||||
debugPrint('❌ Error loading translations: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user