mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
chore: migrate mobile translations accessor (1) (#30667)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
parent
235daff561
commit
565fbe4917
30 changed files with 207 additions and 177 deletions
|
|
@ -97,6 +97,15 @@ const _kIntParamNames = [
|
|||
'quantity',
|
||||
];
|
||||
|
||||
const _kParamTypeOverrides = <String, String>{
|
||||
'advanced_settings_clear_image_cache_success.size': 'String',
|
||||
'backup_controller_page_storage_format.total': 'String',
|
||||
'backup_controller_page_storage_format.used': 'String',
|
||||
'cleanup_found_assets_with_size.size': 'String',
|
||||
};
|
||||
|
||||
final _usedParamTypeOverrides = <String>{};
|
||||
|
||||
void main() async {
|
||||
final sourceFile = File('../i18n/en.json');
|
||||
if (!await sourceFile.exists()) {
|
||||
|
|
@ -143,6 +152,11 @@ class TranslationParam {
|
|||
Future<void> _generateTranslations(Map<String, dynamic> translations, File output) async {
|
||||
final root = _buildTranslationTree('', translations);
|
||||
|
||||
final staleOverrides = _kParamTypeOverrides.keys.toSet().difference(_usedParamTypeOverrides);
|
||||
if (staleOverrides.isNotEmpty) {
|
||||
throw StateError('_kParamTypeOverrides has entries matching no plain {placeholder}: ${staleOverrides.join(', ')}');
|
||||
}
|
||||
|
||||
final buffer = StringBuffer('''
|
||||
// DO NOT EDIT. This is code generated via generate_keys.dart
|
||||
|
||||
|
|
@ -194,21 +208,22 @@ class Translations extends _BaseTranslations {
|
|||
await output.writeAsString(buffer.toString());
|
||||
}
|
||||
|
||||
TranslationNode _buildTranslationTree(String key, dynamic value) {
|
||||
TranslationNode _buildTranslationTree(String key, dynamic value, [String parentKey = '']) {
|
||||
final fullKey = parentKey.isEmpty ? key : '$parentKey.$key';
|
||||
if (value is Map<String, dynamic>) {
|
||||
final children = <String, TranslationNode>{};
|
||||
for (final entry in value.entries) {
|
||||
children[entry.key] = _buildTranslationTree(entry.key, entry.value);
|
||||
children[entry.key] = _buildTranslationTree(entry.key, entry.value, fullKey);
|
||||
}
|
||||
return TranslationNode(key: key, children: children);
|
||||
} else {
|
||||
final stringValue = value.toString();
|
||||
final params = _extractParams(stringValue);
|
||||
final params = _extractParams(stringValue, fullKey);
|
||||
return TranslationNode(key: key, value: stringValue, params: params);
|
||||
}
|
||||
}
|
||||
|
||||
List<TranslationParam> _extractParams(String value) {
|
||||
List<TranslationParam> _extractParams(String value, String fullKey) {
|
||||
final params = <String, TranslationParam>{};
|
||||
|
||||
final icuRegex = RegExp(r'\{(\w+),\s*(plural|select|number|date|time)([^}]*(?:\{[^}]*\}[^}]*)*)\}');
|
||||
|
|
@ -264,8 +279,11 @@ List<TranslationParam> _extractParams(String value) {
|
|||
continue;
|
||||
}
|
||||
|
||||
String type;
|
||||
if (_kIntParamNames.contains(name.toLowerCase())) {
|
||||
final String type;
|
||||
if (_kParamTypeOverrides['$fullKey.$name'] case final override?) {
|
||||
type = override;
|
||||
_usedParamTypeOverrides.add('$fullKey.$name');
|
||||
} else if (_kIntParamNames.contains(name.toLowerCase())) {
|
||||
type = 'int';
|
||||
} else {
|
||||
type = 'Object';
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import 'package:immich_mobile/constants/constants.dart';
|
|||
import 'package:immich_mobile/constants/locales.dart';
|
||||
import 'package:immich_mobile/domain/services/background_worker.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/codegen_loader.g.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
||||
|
|
@ -273,10 +272,7 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
|
|||
darkTheme: getThemeData(colorScheme: immichTheme.dark, locale: context.locale),
|
||||
theme: getThemeData(colorScheme: immichTheme.light, locale: context.locale),
|
||||
builder: (context, child) => ImmichTranslationProvider(
|
||||
translations: ImmichTranslations(
|
||||
submit: "submit".t(context: context),
|
||||
password: "password".t(context: context),
|
||||
),
|
||||
translations: ImmichTranslations(submit: context.t.submit, password: context.t.password),
|
||||
child: ImmichThemeProvider(colorScheme: context.colorScheme, child: child!),
|
||||
),
|
||||
routerConfig: router.config(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_config.model.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_disk_info.model.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_features.model.dart';
|
||||
|
|
@ -16,9 +16,9 @@ enum VersionStatus {
|
|||
|
||||
String get message => switch (this) {
|
||||
VersionStatus.upToDate => "",
|
||||
VersionStatus.clientOutOfDate => "app_update_available".tr(),
|
||||
VersionStatus.serverOutOfDate => "server_update_available".tr(),
|
||||
VersionStatus.error => "unable_to_check_version".tr(),
|
||||
VersionStatus.clientOutOfDate => StaticTranslations.instance.app_update_available,
|
||||
VersionStatus.serverOutOfDate => StaticTranslations.instance.server_update_available,
|
||||
VersionStatus.error => StaticTranslations.instance.unable_to_check_version,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/domain/models/log.model.dart';
|
||||
import 'package:immich_mobile/domain/services/log.service.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/services/immich_logger.service.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
@RoutePage()
|
||||
class AppLogPage extends HookWidget {
|
||||
|
|
@ -50,7 +51,7 @@ class AppLogPage extends HookWidget {
|
|||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('logs'.tr(), style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0)),
|
||||
title: Text(context.t.logs, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0)),
|
||||
scrolledUnderElevation: 1,
|
||||
elevation: 2,
|
||||
actions: [
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/domain/models/log.model.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
@RoutePage()
|
||||
class AppLogDetailPage extends HookWidget {
|
||||
|
|
@ -44,7 +44,7 @@ class AppLogDetailPage extends HookWidget {
|
|||
context.scaffoldMessenger.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
"copied_to_clipboard".tr(),
|
||||
context.t.copied_to_clipboard,
|
||||
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
|
||||
),
|
||||
),
|
||||
|
|
@ -106,7 +106,7 @@ class AppLogDetailPage extends HookWidget {
|
|||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text("log_detail_title".tr())),
|
||||
appBar: AppBar(title: Text(context.t.log_detail_title)),
|
||||
body: SafeArea(
|
||||
child: ListView(
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:background_downloader/background_downloader.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/download.provider.dart';
|
||||
|
||||
class DownloadPanel extends ConsumerWidget {
|
||||
|
|
@ -67,14 +67,14 @@ class DownloadTaskTile extends StatelessWidget {
|
|||
final progressPercent = (progress * 100).round();
|
||||
|
||||
String getStatusText() => switch (status) {
|
||||
TaskStatus.running => 'downloading'.tr(),
|
||||
TaskStatus.complete => 'download_complete'.tr(),
|
||||
TaskStatus.failed => 'download_failed'.tr(),
|
||||
TaskStatus.canceled => 'download_canceled'.tr(),
|
||||
TaskStatus.paused => 'download_paused'.tr(),
|
||||
TaskStatus.enqueued => 'download_enqueue'.tr(),
|
||||
TaskStatus.notFound => 'download_notfound'.tr(),
|
||||
TaskStatus.waitingToRetry => 'download_waiting_to_retry'.tr(),
|
||||
TaskStatus.running => context.t.downloading,
|
||||
TaskStatus.complete => context.t.download_complete,
|
||||
TaskStatus.failed => context.t.download_failed,
|
||||
TaskStatus.canceled => context.t.download_canceled,
|
||||
TaskStatus.paused => context.t.download_paused,
|
||||
TaskStatus.enqueued => context.t.download_enqueue,
|
||||
TaskStatus.notFound => context.t.download_notfound,
|
||||
TaskStatus.waitingToRetry => context.t.download_waiting_to_retry,
|
||||
};
|
||||
|
||||
return SizedBox(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
|
@ -64,7 +63,7 @@ class HeaderSettingsPage extends HookConsumerWidget {
|
|||
headers.value = headers.value.toList();
|
||||
},
|
||||
icon: const Icon(Icons.add_outlined),
|
||||
tooltip: 'header_settings_add_header_tip'.tr(),
|
||||
tooltip: context.t.header_settings_add_header_tip,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -111,7 +110,7 @@ class HeaderKeyValueSettings extends StatelessWidget {
|
|||
|
||||
String? emptyFieldValidator(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'header_settings_field_validator_msg'.tr();
|
||||
return StaticTranslations.instance.header_settings_field_validator_msg;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
@ -129,7 +128,7 @@ class HeaderKeyValueSettings extends StatelessWidget {
|
|||
child: TextFormField(
|
||||
controller: keyController,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'header_settings_header_name_input'.tr(),
|
||||
labelText: context.t.header_settings_header_name_input,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
autocorrect: false,
|
||||
|
|
@ -157,7 +156,7 @@ class HeaderKeyValueSettings extends StatelessWidget {
|
|||
child: TextFormField(
|
||||
controller: valueController,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'header_settings_header_value_input'.tr(),
|
||||
labelText: context.t.header_settings_header_value_input,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
autocorrect: false,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/models/events.model.dart';
|
||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/pages/search/paginated_search.provider.dart';
|
||||
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
|
|
@ -34,24 +34,24 @@ class _TabShellPageState extends ConsumerState<TabShellPage> {
|
|||
|
||||
final navigationDestinations = [
|
||||
NavigationDestination(
|
||||
label: 'photos'.tr(),
|
||||
label: context.t.photos,
|
||||
icon: const Icon(Icons.photo_library_outlined),
|
||||
selectedIcon: Icon(Icons.photo_library, color: context.primaryColor),
|
||||
),
|
||||
NavigationDestination(
|
||||
label: 'search'.tr(),
|
||||
label: context.t.search,
|
||||
icon: const Icon(Icons.search_rounded),
|
||||
selectedIcon: Icon(Icons.search, color: context.primaryColor),
|
||||
enabled: !isReadonlyModeEnabled,
|
||||
),
|
||||
NavigationDestination(
|
||||
label: 'albums'.tr(),
|
||||
label: context.t.albums,
|
||||
icon: const Icon(Icons.photo_album_outlined),
|
||||
selectedIcon: Icon(Icons.photo_album_rounded, color: context.primaryColor),
|
||||
enabled: !isReadonlyModeEnabled,
|
||||
),
|
||||
NavigationDestination(
|
||||
label: 'library'.tr(),
|
||||
label: context.t.library$,
|
||||
icon: const Icon(Icons.space_dashboard_outlined),
|
||||
selectedIcon: Icon(Icons.space_dashboard_rounded, color: context.primaryColor),
|
||||
enabled: !isReadonlyModeEnabled,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart';
|
||||
import 'package:immich_mobile/pages/common/large_leading_tile.dart';
|
||||
import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart';
|
||||
|
|
@ -58,7 +58,7 @@ class ShareIntentPage extends ConsumerWidget {
|
|||
appBar: AppBar(
|
||||
title: Column(
|
||||
children: [
|
||||
const Text('upload_to_immich').tr(namedArgs: {'count': candidates.length.toString()}),
|
||||
Text(context.t.upload_to_immich(count: candidates.length)),
|
||||
Text(
|
||||
currentEndpoint,
|
||||
style: context.textTheme.labelMedium?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)),
|
||||
|
|
@ -130,7 +130,7 @@ class ShareIntentPage extends ConsumerWidget {
|
|||
height: 48,
|
||||
child: ElevatedButton(
|
||||
onPressed: (isUploading || isUploaded) ? null : upload,
|
||||
child: (isUploading || isUploaded) ? UploadingText(candidates: candidates) : const Text('upload').tr(),
|
||||
child: (isUploading || isUploaded) ? UploadingText(candidates: candidates) : Text(context.t.upload),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -149,9 +149,7 @@ class UploadingText extends StatelessWidget {
|
|||
return element.status == UploadStatus.complete;
|
||||
}).length;
|
||||
|
||||
return const Text(
|
||||
"shared_intent_upload_button_progress_text",
|
||||
).tr(namedArgs: {'current': uploadedCount.toString(), 'total': candidates.length.toString()});
|
||||
return Text(context.t.shared_intent_upload_button_progress_text(current: uploadedCount, total: candidates.length));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +166,7 @@ class UploadStatusIcon extends StatelessWidget {
|
|||
return Icon(
|
||||
Icons.check_circle_outline_rounded,
|
||||
color: context.colorScheme.onSurface.withAlpha(100),
|
||||
semanticLabel: 'not_selected'.tr(),
|
||||
semanticLabel: context.t.not_selected,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +174,7 @@ class UploadStatusIcon extends StatelessWidget {
|
|||
UploadStatus.enqueued => Icon(
|
||||
Icons.check_circle_rounded,
|
||||
color: context.primaryColor,
|
||||
semanticLabel: 'enqueued'.tr(),
|
||||
semanticLabel: context.t.enqueued,
|
||||
),
|
||||
UploadStatus.running => Stack(
|
||||
alignment: AlignmentDirectional.center,
|
||||
|
|
@ -191,7 +189,7 @@ class UploadStatusIcon extends StatelessWidget {
|
|||
backgroundColor: context.colorScheme.surfaceContainerLow,
|
||||
strokeWidth: 3,
|
||||
value: value,
|
||||
semanticsLabel: 'uploading'.tr(),
|
||||
semanticsLabel: context.t.uploading,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -201,8 +199,12 @@ class UploadStatusIcon extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
UploadStatus.complete => Icon(Icons.check_circle_rounded, color: Colors.green, semanticLabel: 'completed'.tr()),
|
||||
UploadStatus.failed => Icon(Icons.error_rounded, color: Colors.red, semanticLabel: 'failed'.tr()),
|
||||
UploadStatus.complete => Icon(
|
||||
Icons.check_circle_rounded,
|
||||
color: Colors.green,
|
||||
semanticLabel: context.t.completed,
|
||||
),
|
||||
UploadStatus.failed => Icon(Icons.error_rounded, color: Colors.red, semanticLabel: context.t.failed),
|
||||
};
|
||||
|
||||
return statusIcon;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
|
|
@ -56,7 +56,7 @@ class LocalMediaSummaryPage extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('local_media_summary'.tr())),
|
||||
appBar: AppBar(title: Text(context.t.local_media_summary)),
|
||||
body: Consumer(
|
||||
builder: (ctx, ref, __) {
|
||||
final db = ref.watch(driftProvider);
|
||||
|
|
@ -79,7 +79,7 @@ class LocalMediaSummaryPage extends StatelessWidget {
|
|||
const Divider(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 15),
|
||||
child: Text("album_summary".tr(), style: ctx.textTheme.titleMedium),
|
||||
child: Text(ctx.t.album_summary, style: ctx.textTheme.titleMedium),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -136,7 +136,7 @@ class RemoteMediaSummaryPage extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('remote_media_summary'.tr())),
|
||||
appBar: AppBar(title: Text(context.t.remote_media_summary)),
|
||||
body: Consumer(
|
||||
builder: (ctx, ref, __) {
|
||||
final db = ref.watch(driftProvider);
|
||||
|
|
@ -159,7 +159,7 @@ class RemoteMediaSummaryPage extends StatelessWidget {
|
|||
const Divider(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 15),
|
||||
child: Text("album_summary".tr(), style: ctx.textTheme.titleMedium),
|
||||
child: Text(ctx.t.album_summary, style: ctx.textTheme.titleMedium),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
|
||||
@RoutePage()
|
||||
|
|
@ -18,7 +18,7 @@ class AssetTroubleshootPage extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('asset_troubleshoot'.tr())),
|
||||
appBar: AppBar(title: Text(context.t.asset_troubleshoot)),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
|
|
@ -42,7 +42,7 @@ class _AssetDetailsView extends StatelessWidget {
|
|||
_AssetPropertiesSection(asset: asset),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'matching_assets'.tr(),
|
||||
context.t.matching_assets,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
if (asset.checksum != null) ...[
|
||||
|
|
@ -52,12 +52,12 @@ class _AssetDetailsView extends StatelessWidget {
|
|||
] else ...[
|
||||
_PropertySectionCard(
|
||||
title: 'Local Assets',
|
||||
properties: [_PropertyItem(label: 'Status', value: 'no_checksum_local'.tr())],
|
||||
properties: [_PropertyItem(label: 'Status', value: context.t.no_checksum_local)],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_PropertySectionCard(
|
||||
title: 'Remote Assets',
|
||||
properties: [_PropertyItem(label: 'Status', value: 'no_checksum_remote'.tr())],
|
||||
properties: [_PropertyItem(label: 'Status', value: context.t.no_checksum_remote)],
|
||||
),
|
||||
],
|
||||
],
|
||||
|
|
@ -243,7 +243,7 @@ class _LocalAssetsSection extends ConsumerWidget {
|
|||
if (localAssets.isEmpty) {
|
||||
return _PropertySectionCard(
|
||||
title: 'Local Assets',
|
||||
properties: [_PropertyItem(label: 'Status', value: 'no_local_assets_found'.tr())],
|
||||
properties: [_PropertyItem(label: 'Status', value: context.t.no_local_assets_found)],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +302,7 @@ class _RemoteAssetSection extends ConsumerWidget {
|
|||
if (remoteAsset == null) {
|
||||
return _PropertySectionCard(
|
||||
title: 'Remote Assets',
|
||||
properties: [_PropertyItem(label: 'Status', value: 'no_remote_assets_found'.tr())],
|
||||
properties: [_PropertyItem(label: 'Status', value: context.t.no_remote_assets_found)],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +356,7 @@ class _PropertyItem extends StatelessWidget {
|
|||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value ?? 'not_available'.tr(),
|
||||
value ?? context.t.not_available,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.secondary),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/auth/biometric_status.model.dart';
|
||||
import 'package:immich_mobile/services/local_auth.service.dart';
|
||||
import 'package:immich_mobile/services/secure_storage.service.dart';
|
||||
|
|
@ -43,6 +43,7 @@ class LocalAuthNotifier extends StateNotifier<BiometricStatus> {
|
|||
}
|
||||
|
||||
Future<bool> authenticate(BuildContext context, String? message) async {
|
||||
final t = StaticTranslations.instance;
|
||||
String errorMessage = "";
|
||||
|
||||
try {
|
||||
|
|
@ -51,20 +52,20 @@ class LocalAuthNotifier extends StateNotifier<BiometricStatus> {
|
|||
switch (error.code) {
|
||||
case "NotEnrolled":
|
||||
_log.warning("User is not enrolled in biometrics");
|
||||
errorMessage = "biometric_no_options".tr();
|
||||
errorMessage = t.biometric_no_options;
|
||||
case "NotAvailable":
|
||||
_log.warning("Biometric authentication is not available");
|
||||
errorMessage = "biometric_not_available".tr();
|
||||
errorMessage = t.biometric_not_available;
|
||||
case "LockedOut":
|
||||
_log.warning("User is locked out of biometric authentication");
|
||||
errorMessage = "biometric_locked_out".tr();
|
||||
errorMessage = t.biometric_locked_out;
|
||||
default:
|
||||
_log.warning("Failed to authenticate with unknown reason");
|
||||
errorMessage = 'failed_to_authenticate'.tr();
|
||||
errorMessage = t.failed_to_authenticate;
|
||||
}
|
||||
} catch (error) {
|
||||
_log.warning("Error during authentication: $error");
|
||||
errorMessage = 'failed_to_authenticate'.tr();
|
||||
errorMessage = t.failed_to_authenticate;
|
||||
} finally {
|
||||
if (errorMessage.isNotEmpty) {
|
||||
context.showSnackBar(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
part 'sync_status.provider.freezed.dart';
|
||||
|
||||
|
|
@ -12,11 +12,12 @@ enum SyncStatus {
|
|||
error;
|
||||
|
||||
String localized() {
|
||||
final t = StaticTranslations.instance;
|
||||
return switch (this) {
|
||||
SyncStatus.idle => "idle".tr(),
|
||||
SyncStatus.syncing => "running".tr(),
|
||||
SyncStatus.success => "success".tr(),
|
||||
SyncStatus.error => "error".tr(),
|
||||
SyncStatus.idle => t.idle,
|
||||
SyncStatus.syncing => t.running,
|
||||
SyncStatus.success => t.success,
|
||||
SyncStatus.error => t.error,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/auth/biometric_status.model.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
|
||||
|
|
@ -19,6 +19,6 @@ class BiometricRepository {
|
|||
}
|
||||
|
||||
Future<bool> authenticate(String? message) async {
|
||||
return _localAuth.authenticate(localizedReason: message ?? 'please_auth_to_access'.tr());
|
||||
return _localAuth.authenticate(localizedReason: message ?? StaticTranslations.instance.please_auth_to_access);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:immich_mobile/domain/models/store.model.dart';
|
|||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/extensions/network_capability_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||
|
|
@ -241,16 +241,17 @@ class ForegroundUploadService {
|
|||
Completer<void>? cancelToken, {
|
||||
required UploadCallbacks callbacks,
|
||||
}) async {
|
||||
final t = StaticTranslations.instance;
|
||||
final assetNotFoundOnDevice = CurrentPlatform.isAndroid
|
||||
? t.asset_not_found_on_device_android
|
||||
: t.asset_not_found_on_device_ios;
|
||||
File? file;
|
||||
File? livePhotoFile;
|
||||
|
||||
try {
|
||||
final entity = await _storageRepository.getAssetEntityForAsset(asset);
|
||||
if (entity == null) {
|
||||
callbacks.onError?.call(
|
||||
asset.localId!,
|
||||
CurrentPlatform.isAndroid ? "asset_not_found_on_device_android".t() : "asset_not_found_on_device_ios".t(),
|
||||
);
|
||||
callbacks.onError?.call(asset.localId!, assetNotFoundOnDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -284,10 +285,7 @@ class ForegroundUploadService {
|
|||
file = await _storageRepository.getFileForAsset(asset.id);
|
||||
if (file == null) {
|
||||
_logger.warning("Failed to get file ${asset.id} - ${asset.name}");
|
||||
callbacks.onError?.call(
|
||||
asset.localId!,
|
||||
CurrentPlatform.isAndroid ? "asset_not_found_on_device_android".t() : "asset_not_found_on_device_ios".t(),
|
||||
);
|
||||
callbacks.onError?.call(asset.localId!, assetNotFoundOnDevice);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -296,17 +294,14 @@ class ForegroundUploadService {
|
|||
livePhotoFile = await _storageRepository.getMotionFileForAsset(asset);
|
||||
if (livePhotoFile == null) {
|
||||
_logger.warning("Failed to obtain motion part of the livePhoto - ${asset.name}");
|
||||
callbacks.onError?.call(
|
||||
asset.localId!,
|
||||
CurrentPlatform.isAndroid ? "asset_not_found_on_device_android".t() : "asset_not_found_on_device_ios".t(),
|
||||
);
|
||||
callbacks.onError?.call(asset.localId!, assetNotFoundOnDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file == null) {
|
||||
_logger.warning("Failed to obtain file from iCloud for asset ${asset.id} - ${asset.name}");
|
||||
callbacks.onError?.call(asset.localId!, "asset_not_found_on_icloud".t());
|
||||
callbacks.onError?.call(asset.localId!, t.asset_not_found_on_icloud);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
|
|
@ -7,6 +6,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|||
import 'package:immich_mobile/domain/models/events.model.dart';
|
||||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.widget.dart';
|
||||
import 'package:immich_mobile/presentation/actions/archive.action.dart';
|
||||
import 'package:immich_mobile/presentation/actions/asset_debug.action.dart';
|
||||
|
|
@ -203,13 +203,13 @@ enum ActionButtonType {
|
|||
),
|
||||
ActionButtonType.setProfilePicture => ActionMenuItem(action: SetProfilePictureAction(asset: context.asset)),
|
||||
ActionButtonType.openInfo => BaseActionButton(
|
||||
label: 'info'.tr(),
|
||||
label: StaticTranslations.instance.info,
|
||||
iconData: Icons.info_outline,
|
||||
menuItem: true,
|
||||
onPressed: () => EventStream.shared.emit(const ViewerShowDetailsEvent()),
|
||||
),
|
||||
ActionButtonType.viewInTimeline => BaseActionButton(
|
||||
label: 'view_in_timeline'.tr(),
|
||||
label: StaticTranslations.instance.view_in_timeline,
|
||||
iconData: Icons.image_search,
|
||||
iconOnly: iconOnly,
|
||||
menuItem: menuItem,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'package:background_downloader/background_downloader.dart';
|
|||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/services/log.service.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/log.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/logger_db.repository.dart';
|
||||
|
|
@ -15,31 +15,33 @@ import 'package:photo_manager/photo_manager.dart';
|
|||
import 'package:sqlite3/common.dart';
|
||||
|
||||
void configureFileDownloaderNotifications() {
|
||||
final t = StaticTranslations.instance;
|
||||
|
||||
FileDownloader().configureNotificationForGroup(
|
||||
kDownloadGroupImage,
|
||||
running: TaskNotification('downloading_media'.t(), '${'file_name_text'.t()}: {filename}'),
|
||||
complete: TaskNotification('download_finished'.t(), '${'file_name_text'.t()}: {filename}'),
|
||||
running: TaskNotification(t.downloading_media, '${t.file_name_text}: {filename}'),
|
||||
complete: TaskNotification(t.download_finished, '${t.file_name_text}: {filename}'),
|
||||
progressBar: true,
|
||||
);
|
||||
|
||||
FileDownloader().configureNotificationForGroup(
|
||||
kDownloadGroupVideo,
|
||||
running: TaskNotification('downloading_media'.t(), '${'file_name_text'.t()}: {filename}'),
|
||||
complete: TaskNotification('download_finished'.t(), '${'file_name_text'.t()}: {filename}'),
|
||||
running: TaskNotification(t.downloading_media, '${t.file_name_text}: {filename}'),
|
||||
complete: TaskNotification(t.download_finished, '${t.file_name_text}: {filename}'),
|
||||
progressBar: true,
|
||||
);
|
||||
|
||||
FileDownloader().configureNotificationForGroup(
|
||||
kManualUploadGroup,
|
||||
running: TaskNotification('uploading_media'.t(), 'backup_background_service_in_progress_notification'.t()),
|
||||
complete: TaskNotification('upload_finished'.t(), 'backup_background_service_complete_notification'.t()),
|
||||
running: TaskNotification(t.uploading_media, t.backup_background_service_in_progress_notification),
|
||||
complete: TaskNotification(t.upload_finished, t.backup_background_service_complete_notification),
|
||||
groupNotificationId: kManualUploadGroup,
|
||||
);
|
||||
|
||||
FileDownloader().configureNotificationForGroup(
|
||||
kBackupGroup,
|
||||
running: TaskNotification('uploading_media'.t(), 'backup_background_service_in_progress_notification'.t()),
|
||||
complete: TaskNotification('upload_finished'.t(), 'backup_background_service_complete_notification'.t()),
|
||||
running: TaskNotification(t.uploading_media, t.backup_background_service_in_progress_notification),
|
||||
complete: TaskNotification(t.upload_finished, t.backup_background_service_complete_notification),
|
||||
groupNotificationId: kBackupGroup,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/domain/models/person.model.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/people/person_edit_birthday_modal.widget.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/people/person_edit_name_modal.widget.dart';
|
||||
|
||||
|
|
@ -8,12 +8,13 @@ String formatAge(DateTime birthDate, DateTime referenceDate) {
|
|||
final int ageInYears = _calculateAge(birthDate, referenceDate);
|
||||
final int ageInMonths = _calculateAgeInMonths(birthDate, referenceDate);
|
||||
|
||||
final t = StaticTranslations.instance;
|
||||
if (ageInMonths <= 11) {
|
||||
return "person_age_months".t(args: {'months': ageInMonths.toString()});
|
||||
return t.person_age_months(months: ageInMonths);
|
||||
} else if (ageInMonths > 12 && ageInMonths <= 23) {
|
||||
return "person_age_year_months".t(args: {'months': (ageInMonths - 12).toString()});
|
||||
return t.person_age_year_months(months: ageInMonths - 12);
|
||||
} else {
|
||||
return "person_age_years".t(args: {'years': ageInYears.toString()});
|
||||
return t.person_age_years(years: ageInYears);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_disk_info.model.dart';
|
||||
import 'package:immich_mobile/pages/common/settings.page.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
|
|
@ -78,20 +78,24 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
title: Text(
|
||||
text,
|
||||
style: theme.textTheme.labelLarge?.copyWith(color: theme.textTheme.labelLarge?.color?.withAlpha(250)),
|
||||
).tr(),
|
||||
),
|
||||
onTap: onTap,
|
||||
trailing: trailing,
|
||||
);
|
||||
}
|
||||
|
||||
ListTile buildSettingButton() {
|
||||
return buildActionButton(Icons.settings_outlined, "settings", () => context.pushRoute(const SettingsRoute()));
|
||||
return buildActionButton(
|
||||
Icons.settings_outlined,
|
||||
context.t.settings,
|
||||
() => context.pushRoute(const SettingsRoute()),
|
||||
);
|
||||
}
|
||||
|
||||
ListTile buildFreeUpSpaceButton() {
|
||||
return buildActionButton(
|
||||
Icons.cleaning_services_outlined,
|
||||
"free_up_space",
|
||||
context.t.free_up_space,
|
||||
() => context.pushRoute(SettingsSubRoute(section: SettingSection.freeUpSpace)),
|
||||
);
|
||||
}
|
||||
|
|
@ -99,7 +103,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
ListTile buildAppLogButton() {
|
||||
return buildActionButton(
|
||||
Icons.assignment_outlined,
|
||||
"profile_drawer_app_logs",
|
||||
context.t.profile_drawer_app_logs,
|
||||
() => context.pushRoute(const AppLogRoute()),
|
||||
);
|
||||
}
|
||||
|
|
@ -107,7 +111,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
ListTile buildSignOutButton() {
|
||||
return buildActionButton(
|
||||
Icons.logout_rounded,
|
||||
"sign_out",
|
||||
context.t.sign_out,
|
||||
() async {
|
||||
if (isLoggingOut.value) {
|
||||
return;
|
||||
|
|
@ -163,16 +167,16 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 12,
|
||||
children: [
|
||||
Text("backup_controller_page_server_storage".tr(), style: context.textTheme.labelLarge),
|
||||
Text(context.t.backup_controller_page_server_storage, style: context.textTheme.labelLarge),
|
||||
LinearProgressIndicator(
|
||||
minHeight: 10.0,
|
||||
value: percentage,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10.0)),
|
||||
),
|
||||
Text(
|
||||
'backup_controller_page_storage_format',
|
||||
context.t.backup_controller_page_storage_format(used: usedDiskSpace, total: totalDiskSpace),
|
||||
style: context.textTheme.bodySmall,
|
||||
).tr(namedArgs: {'used': usedDiskSpace, 'total': totalDiskSpace}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
@ -189,7 +193,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
ContextHelper(context).pop();
|
||||
unawaited(launchUrl(Uri.parse('https://docs.immich.app'), mode: LaunchMode.externalApplication));
|
||||
},
|
||||
child: Text("documentation", style: context.textTheme.bodySmall).tr(),
|
||||
child: Text(context.t.documentation, style: context.textTheme.bodySmall),
|
||||
),
|
||||
const SizedBox(width: 20, child: Text("•", textAlign: TextAlign.center)),
|
||||
InkWell(
|
||||
|
|
@ -199,7 +203,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
launchUrl(Uri.parse('https://github.com/immich-app/immich'), mode: LaunchMode.externalApplication),
|
||||
);
|
||||
},
|
||||
child: Text("profile_drawer_github", style: context.textTheme.bodySmall).tr(),
|
||||
child: Text(context.t.profile_drawer_github, style: context.textTheme.bodySmall),
|
||||
),
|
||||
const SizedBox(width: 20, child: Text("•", textAlign: TextAlign.center)),
|
||||
InkWell(
|
||||
|
|
@ -219,7 +223,7 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
applicationVersion: packageInfo.version,
|
||||
);
|
||||
},
|
||||
child: Text("licenses", style: context.textTheme.bodySmall).tr(),
|
||||
child: Text(context.t.licenses, style: context.textTheme.bodySmall),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -237,10 +241,10 @@ class ImmichAppBarDialog extends HookConsumerWidget {
|
|||
minLeadingWidth: 20,
|
||||
tileColor: theme.primaryColor.withAlpha(80),
|
||||
title: Text(
|
||||
"profile_drawer_readonly_mode",
|
||||
context.t.profile_drawer_readonly_mode,
|
||||
style: theme.textTheme.labelLarge?.copyWith(color: theme.textTheme.labelLarge?.color?.withAlpha(250)),
|
||||
textAlign: TextAlign.center,
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
|
||||
|
|
@ -68,7 +68,7 @@ class AppBarProfileInfoBox extends HookConsumerWidget {
|
|||
SnackBar(
|
||||
duration: const Duration(seconds: 2),
|
||||
content: Text(
|
||||
(isReadonlyModeEnabled ? "readonly_mode_disabled" : "readonly_mode_enabled").tr(),
|
||||
isReadonlyModeEnabled ? context.t.readonly_mode_disabled : context.t.readonly_mode_enabled,
|
||||
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_info.model.dart';
|
||||
import 'package:immich_mobile/providers/locale_provider.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
|
|
@ -46,20 +46,20 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||
children: [
|
||||
if (showVersionWarning) ...[const ServerUpdateNotification(), divider],
|
||||
_ServerInfoItem(
|
||||
label: "server_info_box_app_version".tr(),
|
||||
label: context.t.server_info_box_app_version,
|
||||
text: "${appInfo.value["version"]} build.${appInfo.value["buildNumber"]}",
|
||||
),
|
||||
divider,
|
||||
_ServerInfoItem(
|
||||
label: "server_version".tr(),
|
||||
label: context.t.server_version,
|
||||
text: serverInfoState.serverVersion.major > 0 ? "${serverInfoState.serverVersion}" : "--",
|
||||
),
|
||||
divider,
|
||||
_ServerInfoItem(label: "server_info_box_server_url".tr(), text: getServerUrl() ?? '--', tooltip: true),
|
||||
_ServerInfoItem(label: context.t.server_info_box_server_url, text: getServerUrl() ?? '--', tooltip: true),
|
||||
if (serverInfoState.latestVersion != null) ...[
|
||||
divider,
|
||||
_ServerInfoItem(
|
||||
label: "latest_version".tr(),
|
||||
label: context.t.latest_version,
|
||||
text: serverInfoState.latestVersion!.major > 0 ? "${serverInfoState.latestVersion!}" : "--",
|
||||
tooltip: true,
|
||||
icon: serverInfoState.versionStatus == VersionStatus.serverOutOfDate
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_info.model.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
|
@ -76,8 +76,8 @@ class ServerUpdateNotification extends HookConsumerWidget {
|
|||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
),
|
||||
child: serverInfoState.versionStatus == VersionStatus.clientOutOfDate
|
||||
? Text("action_common_update".tr(context: context))
|
||||
: Text("view".tr()),
|
||||
? Text(context.t.action_common_update)
|
||||
: Text(context.t.view),
|
||||
),
|
||||
],
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/duration_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/widgets/common/dropdown_search_menu.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:timezone/timezone.dart' as tz;
|
||||
import 'package:timezone/timezone.dart';
|
||||
|
||||
|
|
@ -116,26 +117,26 @@ class _DateTimePicker extends HookWidget {
|
|||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(
|
||||
"cancel",
|
||||
context.t.cancel,
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: context.colorScheme.error,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: popWithDateTime,
|
||||
child: Text(
|
||||
"action_common_update",
|
||||
context.t.action_common_update,
|
||||
style: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
],
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text("date_and_time", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)).tr(),
|
||||
Text(context.t.date_and_time, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
const SizedBox(height: 32),
|
||||
ListTile(
|
||||
tileColor: context.colorScheme.surfaceContainerHighest,
|
||||
|
|
@ -151,8 +152,8 @@ class _DateTimePicker extends HookWidget {
|
|||
const SizedBox(height: 24),
|
||||
DropdownSearchMenu(
|
||||
trailingIcon: Icon(Icons.arrow_drop_down, color: context.primaryColor),
|
||||
hintText: "timezone".tr(),
|
||||
label: const Text('timezone').tr(),
|
||||
hintText: context.t.timezone,
|
||||
label: Text(context.t.timezone),
|
||||
textStyle: context.textTheme.bodyMedium,
|
||||
onSelected: (value) => tzOffset.value = value,
|
||||
initialSelection: tzOffset.value,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
class DropdownSearchMenu<T> extends HookWidget {
|
||||
const DropdownSearchMenu({
|
||||
|
|
@ -81,7 +81,7 @@ class DropdownSearchMenu<T> extends HookWidget {
|
|||
autofocus: true,
|
||||
focusNode: focusNode,
|
||||
controller: textEditingController,
|
||||
decoration: inputDecoration.copyWith(hintText: "search_timezone".tr()),
|
||||
decoration: inputDecoration.copyWith(hintText: context.t.search_timezone),
|
||||
maxLines: 1,
|
||||
style: context.textTheme.bodyMedium,
|
||||
expands: false,
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ import 'dart:async';
|
|||
import 'dart:math' as math;
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/models/server_info/server_info.model.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/cast.provider.dart';
|
||||
|
|
@ -120,7 +120,7 @@ class _ProfileIndicator extends ConsumerWidget {
|
|||
SnackBar(
|
||||
duration: const Duration(seconds: 2),
|
||||
content: Text(
|
||||
(isReadonlyModeEnabled ? "readonly_mode_disabled" : "readonly_mode_enabled").tr(),
|
||||
isReadonlyModeEnabled ? context.t.readonly_mode_disabled : context.t.readonly_mode_enabled,
|
||||
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
|
||||
),
|
||||
),
|
||||
|
|
@ -143,7 +143,7 @@ class _ProfileIndicator extends ConsumerWidget {
|
|||
? context.colorScheme.error
|
||||
: context.primaryColor,
|
||||
size: widgetSize / 2 - 3,
|
||||
semanticLabel: 'new_version_available'.tr(),
|
||||
semanticLabel: context.t.new_version_available,
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.transparent,
|
||||
|
|
@ -153,7 +153,7 @@ class _ProfileIndicator extends ConsumerWidget {
|
|||
child: user == null
|
||||
? const Icon(Icons.face_outlined, size: widgetSize)
|
||||
: Semantics(
|
||||
label: "logged_in_as".tr(namedArgs: {"user": user.name}),
|
||||
label: context.t.logged_in_as(user: user.name),
|
||||
child: AbsorbPointer(
|
||||
child: Builder(
|
||||
builder: (context) => UserCircleAvatar(
|
||||
|
|
@ -201,7 +201,12 @@ class _BackupIndicator extends ConsumerWidget {
|
|||
|
||||
if (!backupEnabled) {
|
||||
return _BadgeLabel(
|
||||
Icon(Icons.cloud_off_rounded, size: 9, color: iconColor, semanticLabel: 'backup_controller_page_backup'.tr()),
|
||||
Icon(
|
||||
Icons.cloud_off_rounded,
|
||||
size: 9,
|
||||
color: iconColor,
|
||||
semanticLabel: context.t.backup_controller_page_backup,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +216,7 @@ class _BackupIndicator extends ConsumerWidget {
|
|||
Icons.warning_rounded,
|
||||
size: 12,
|
||||
color: context.colorScheme.error,
|
||||
semanticLabel: 'backup_controller_page_backup'.tr(),
|
||||
semanticLabel: context.t.backup_controller_page_backup,
|
||||
),
|
||||
backgroundColor: context.colorScheme.errorContainer,
|
||||
);
|
||||
|
|
@ -229,7 +234,7 @@ class _BackupIndicator extends ConsumerWidget {
|
|||
strokeWidth: 2,
|
||||
strokeCap: StrokeCap.round,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(iconColor),
|
||||
semanticsLabel: 'backup_controller_page_backup'.tr(),
|
||||
semanticsLabel: context.t.backup_controller_page_backup,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -237,7 +242,7 @@ class _BackupIndicator extends ConsumerWidget {
|
|||
}
|
||||
|
||||
return _BadgeLabel(
|
||||
Icon(Icons.check_outlined, size: 9, color: iconColor, semanticLabel: 'backup_controller_page_backup'.tr()),
|
||||
Icon(Icons.check_outlined, size: 9, color: iconColor, semanticLabel: context.t.backup_controller_page_backup),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/string_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||
|
||||
|
|
@ -73,11 +73,11 @@ class _LocationPicker extends HookWidget {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("edit_location_dialog_title", style: context.textTheme.titleMedium).tr(),
|
||||
Text(context.t.edit_location_dialog_title, style: context.textTheme.titleMedium),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: TextButton.icon(
|
||||
icon: const Text("location_picker_choose_on_map").tr(),
|
||||
icon: Text(context.t.location_picker_choose_on_map),
|
||||
label: const Icon(Icons.map_outlined, size: 16),
|
||||
onPressed: onMapTap,
|
||||
),
|
||||
|
|
@ -85,9 +85,9 @@ class _LocationPicker extends HookWidget {
|
|||
const SizedBox(height: 12),
|
||||
_ManualPickerInput(
|
||||
controller: latitudeController,
|
||||
decorationText: "latitude",
|
||||
hintText: "location_picker_latitude_hint",
|
||||
errorText: "location_picker_latitude_error",
|
||||
decorationText: context.t.latitude,
|
||||
hintText: context.t.location_picker_latitude_hint,
|
||||
errorText: context.t.location_picker_latitude_error,
|
||||
focusNode: latitiudeFocusNode,
|
||||
validator: _validateLat,
|
||||
onUpdated: onLatitudeUpdated,
|
||||
|
|
@ -95,9 +95,9 @@ class _LocationPicker extends HookWidget {
|
|||
const SizedBox(height: 24),
|
||||
_ManualPickerInput(
|
||||
controller: longitudeController,
|
||||
decorationText: "longitude",
|
||||
hintText: "location_picker_longitude_hint",
|
||||
errorText: "location_picker_longitude_error",
|
||||
decorationText: context.t.longitude,
|
||||
hintText: context.t.location_picker_longitude_hint,
|
||||
errorText: context.t.location_picker_longitude_error,
|
||||
focusNode: longitudeFocusNode,
|
||||
validator: _validateLong,
|
||||
onUpdated: onLongitudeEditingCompleted,
|
||||
|
|
@ -109,19 +109,19 @@ class _LocationPicker extends HookWidget {
|
|||
TextButton(
|
||||
onPressed: () => ContextHelper(context).pop(),
|
||||
child: Text(
|
||||
"cancel",
|
||||
context.t.cancel,
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: context.colorScheme.error,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => context.maybePop(latlng),
|
||||
child: Text(
|
||||
"action_common_update",
|
||||
context.t.action_common_update,
|
||||
style: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
@ -163,13 +163,13 @@ class _ManualPickerInput extends HookWidget {
|
|||
textInputAction: TextInputAction.done,
|
||||
autofocus: false,
|
||||
decoration: InputDecoration(
|
||||
labelText: decorationText.tr(),
|
||||
labelText: decorationText,
|
||||
labelStyle: TextStyle(fontWeight: FontWeight.bold, color: context.primaryColor),
|
||||
floatingLabelBehavior: FloatingLabelBehavior.auto,
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: hintText.tr(),
|
||||
hintText: hintText,
|
||||
hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14),
|
||||
errorText: isValid.value ? null : errorText.tr(),
|
||||
errorText: isValid.value ? null : errorText,
|
||||
),
|
||||
onEditingComplete: onEditingComplete,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true, signed: true),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import 'package:immich_mobile/domain/models/events.model.dart';
|
|||
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||
import 'package:immich_mobile/domain/utils/event_stream.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||
|
|
@ -237,7 +237,7 @@ class _ItemCountTextState extends ConsumerState<_ItemCountText> {
|
|||
final assetCount = ref.watch(timelineServiceProvider.select((s) => s.totalAssets));
|
||||
|
||||
return Text(
|
||||
'items_count'.t(context: context, args: {"count": assetCount}),
|
||||
context.t.items_count(count: assetCount),
|
||||
style: context.textTheme.labelLarge?.copyWith(
|
||||
// letterSpacing: 0.2,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
|
||||
// Error widget to be used in Scaffold when an AsyncError is received
|
||||
class ScaffoldErrorBody extends StatelessWidget {
|
||||
|
|
@ -15,7 +15,11 @@ class ScaffoldErrorBody extends StatelessWidget {
|
|||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text("scaffold_body_error_occurred", style: context.textTheme.displayMedium, textAlign: TextAlign.center).tr(),
|
||||
Text(
|
||||
context.t.scaffold_body_error_occurred,
|
||||
style: context.textTheme.displayMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
if (withIcon)
|
||||
Center(
|
||||
child: Padding(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||
|
||||
class SelectionSliverAppBar extends ConsumerStatefulWidget {
|
||||
|
|
@ -43,12 +43,12 @@ class _SelectionSliverAppBarState extends ConsumerState<SelectionSliverAppBar> {
|
|||
},
|
||||
),
|
||||
centerTitle: true,
|
||||
title: Text("Select {count}".t(context: context, args: {'count': filteredAssets.length.toString()})),
|
||||
title: Text(context.t.selected_count(count: filteredAssets.length)),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => onDone(filteredAssets),
|
||||
child: Text(
|
||||
'done'.t(context: context),
|
||||
context.t.done,
|
||||
style: context.textTheme.titleSmall?.copyWith(color: context.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/tag.model.dart';
|
||||
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/tag.provider.dart';
|
||||
import 'package:immich_mobile/widgets/common/search_field.dart';
|
||||
|
||||
|
|
@ -41,19 +41,19 @@ class _TagPickerModal extends HookWidget {
|
|||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(
|
||||
"cancel",
|
||||
context.t.cancel,
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: context.colorScheme.error,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => context.pop((selectedTagIds.value, newTagValues.value)),
|
||||
child: Text(
|
||||
"action_common_update",
|
||||
context.t.action_common_update,
|
||||
style: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
],
|
||||
content: SizedBox(
|
||||
|
|
@ -98,7 +98,7 @@ class TagPicker extends HookConsumerWidget {
|
|||
onChanged: (value) => searchQuery.value = value,
|
||||
onTapOutside: (_) => formFocus.unfocus(),
|
||||
filled: true,
|
||||
hintText: 'filter_tags'.tr(),
|
||||
hintText: context.t.filter_tags,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue