chore(mobile): translate missing strings (#22057)

This commit is contained in:
bo0tzz 2025-09-16 15:51:03 +02:00 committed by GitHub
parent df7ea4d8ea
commit 4d00261bc1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 87 additions and 43 deletions

View file

@ -423,6 +423,7 @@
"album_remove_user_confirmation": "Are you sure you want to remove {user}?",
"album_search_not_found": "No albums found matching your search",
"album_share_no_users": "Looks like you have shared this album with all users or you don't have any user to share with.",
"album_summary": "Album summary",
"album_updated": "Album updated",
"album_updated_setting_description": "Receive an email notification when a shared album has new assets",
"album_user_left": "Left {album}",
@ -494,6 +495,8 @@
"asset_restored_successfully": "Asset restored successfully",
"asset_skipped": "Skipped",
"asset_skipped_in_trash": "In trash",
"asset_trashed": "Asset trashed",
"asset_troubleshoot": "Asset Troubleshoot",
"asset_uploaded": "Uploaded",
"asset_uploading": "Uploading…",
"asset_viewer_settings_subtitle": "Manage your gallery viewer settings",
@ -527,6 +530,7 @@
"autoplay_slideshow": "Autoplay slideshow",
"back": "Back",
"back_close_deselect": "Back, close, or deselect",
"background_backup_running_error": "Background backup is currently running, cannot start manual backup",
"background_location_permission": "Background location permission",
"background_location_permission_content": "In order to switch networks when running in the background, Immich must *always* have precise location access so the app can read the Wi-Fi network's name",
"backup": "Backup",
@ -738,6 +742,7 @@
"create_user": "Create user",
"created": "Created",
"created_at": "Created",
"creating_linked_albums": "Creating linked albums...",
"crop": "Crop",
"curated_object_page_title": "Things",
"current_device": "Current device",
@ -887,7 +892,9 @@
"error": "Error",
"error_change_sort_album": "Failed to change album sort order",
"error_delete_face": "Error deleting face from asset",
"error_getting_places": "Error getting places",
"error_loading_image": "Error loading image",
"error_loading_partners": "Error loading partners: {error}",
"error_saving_image": "Error: {error}",
"error_tag_face_bounding_box": "Error tagging face - cannot get bounding box coordinates",
"error_title": "Error - Something went wrong",
@ -1052,6 +1059,7 @@
"favorites_page_no_favorites": "No favorite assets found",
"feature_photo_updated": "Feature photo updated",
"features": "Features",
"features_in_development": "Features in Development",
"features_setting_description": "Manage the app features",
"file_name": "File name",
"file_name_or_extension": "File name or extension",
@ -1216,6 +1224,7 @@
"local": "Local",
"local_asset_cast_failed": "Unable to cast an asset that is not uploaded to the server",
"local_assets": "Local Assets",
"local_media_summary": "Local Media Summary",
"local_network": "Local network",
"local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network",
"location_permission": "Location permission",
@ -1227,6 +1236,7 @@
"location_picker_longitude_hint": "Enter your longitude here",
"lock": "Lock",
"locked_folder": "Locked Folder",
"log_detail_title": "Log Detail",
"log_out": "Log out",
"log_out_all_devices": "Log Out All Devices",
"logged_in_as": "Logged in as {user}",
@ -1257,6 +1267,7 @@
"login_password_changed_success": "Password updated successfully",
"logout_all_device_confirmation": "Are you sure you want to log out all devices?",
"logout_this_device_confirmation": "Are you sure you want to log out this device?",
"logs": "Logs",
"longitude": "Longitude",
"look": "Look",
"loop_videos": "Loop videos",
@ -1299,6 +1310,7 @@
"mark_as_read": "Mark as read",
"marked_all_as_read": "Marked all as read",
"matches": "Matches",
"matching_assets": "Matching Assets",
"media_type": "Media type",
"memories": "Memories",
"memories_all_caught_up": "All caught up",
@ -1363,20 +1375,25 @@
"no_assets_message": "CLICK TO UPLOAD YOUR FIRST PHOTO",
"no_assets_to_show": "No assets to show",
"no_cast_devices_found": "No cast devices found",
"no_checksum_local": "No checksum available - cannot fetch local assets",
"no_checksum_remote": "No checksum available - cannot fetch remote asset",
"no_duplicates_found": "No duplicates were found.",
"no_exif_info_available": "No exif info available",
"no_explore_results_message": "Upload more photos to explore your collection.",
"no_favorites_message": "Add favorites to quickly find your best pictures and videos",
"no_libraries_message": "Create an external library to view your photos and videos",
"no_local_assets_found": "No local assets found with this checksum",
"no_locked_photos_message": "Photos and videos in the locked folder are hidden and won't show up as you browse or search your library.",
"no_name": "No Name",
"no_notifications": "No notifications",
"no_people_found": "No matching people found",
"no_places": "No places",
"no_remote_assets_found": "No remote assets found with this checksum",
"no_results": "No results",
"no_results_description": "Try a synonym or more general keyword",
"no_shared_albums_message": "Create an album to share photos and videos with people in your network",
"no_uploads_in_progress": "No uploads in progress",
"not_available": "N/A",
"not_in_any_album": "Not in any album",
"not_selected": "Not selected",
"note_apply_storage_label_to_previously_uploaded assets": "Note: To apply the Storage Label to previously uploaded assets, run the",
@ -1587,6 +1604,7 @@
"regenerating_thumbnails": "Regenerating thumbnails",
"remote": "Remote",
"remote_assets": "Remote Assets",
"remote_media_summary": "Remote Media Summary",
"remove": "Remove",
"remove_assets_album_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from the album?",
"remove_assets_shared_link_confirmation": "Are you sure you want to remove {count, plural, one {# asset} other {# assets}} from this shared link?",
@ -1862,6 +1880,7 @@
"show_slideshow_transition": "Show slideshow transition",
"show_supporter_badge": "Supporter badge",
"show_supporter_badge_description": "Show a supporter badge",
"show_text_search_menu": "Show text search menu",
"shuffle": "Shuffle",
"sidebar": "Sidebar",
"sidebar_display_description": "Display a link to the view in the sidebar",
@ -2094,5 +2113,6 @@
"yes": "Yes",
"you_dont_have_any_shared_links": "You don't have any shared links",
"your_wifi_name": "Your Wi-Fi name",
"zoom_image": "Zoom Image"
"zoom_image": "Zoom Image",
"zoom_to_bounds": "Zoom to bounds"
}

View file

@ -205,9 +205,9 @@ class BackupControllerPage extends HookConsumerWidget {
}
buildBackgroundBackupInfo() {
return const ListTile(
leading: Icon(Icons.info_outline_rounded),
title: Text("Background backup is currently running, cannot start manual backup"),
return ListTile(
leading: const Icon(Icons.info_outline_rounded),
title: Text('background_backup_running_error'.tr()),
);
}

View file

@ -1,6 +1,7 @@
import 'dart:io';
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/album/local_album.model.dart';
@ -249,7 +250,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
mainAxisSize: MainAxisSize.max,
children: [
const CircularProgressIndicator(strokeWidth: 4),
Text("Creating linked albums...", style: context.textTheme.labelLarge),
Text('creating_linked_albums'.tr(), style: context.textTheme.labelLarge),
],
),
),

View file

@ -1,4 +1,5 @@
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';
@ -58,8 +59,10 @@ class DriftBackupAssetDetailPage extends ConsumerWidget {
overflow: TextOverflow.ellipsis,
);
},
error: (error, stackTrace) =>
Text('Error: $error', style: TextStyle(color: context.colorScheme.error)),
error: (error, stackTrace) => Text(
'error_saving_image'.tr(args: [error.toString()]),
style: TextStyle(color: context.colorScheme.error),
),
loading: () => const SizedBox(height: 16, width: 16, child: CircularProgressIndicator.adaptive()),
),
],
@ -83,7 +86,7 @@ class DriftBackupAssetDetailPage extends ConsumerWidget {
);
},
error: (Object error, StackTrace stackTrace) {
return Center(child: Text('Error: $error'));
return Center(child: Text('error_saving_image'.tr(args: [error.toString()])));
},
loading: () {
return const SizedBox(height: 48, width: 48, child: Center(child: CircularProgressIndicator.adaptive()));

View file

@ -1,4 +1,5 @@
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';
@ -8,7 +9,6 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.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 HookConsumerWidget {
@ -49,7 +49,7 @@ class AppLogPage extends HookConsumerWidget {
return Scaffold(
appBar: AppBar(
title: const Text("Logs", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0)),
title: Text('logs'.tr(), style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0)),
scrolledUnderElevation: 1,
elevation: 2,
actions: [

View file

@ -1,4 +1,5 @@
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:hooks_riverpod/hooks_riverpod.dart';
@ -36,7 +37,7 @@ class AppLogDetailPage extends HookConsumerWidget {
context.scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
"Copied to clipboard",
"copied_to_clipboard".tr(),
style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor),
),
),
@ -97,7 +98,7 @@ class AppLogDetailPage extends HookConsumerWidget {
}
return Scaffold(
appBar: AppBar(title: const Text("Log Detail")),
appBar: AppBar(title: Text("log_detail_title".tr())),
body: SafeArea(
child: ListView(
children: [

View file

@ -134,7 +134,7 @@ class _SharedToPartnerList extends ConsumerWidget {
);
},
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) => Center(child: Text("Error loading partners: $error")),
error: (error, stack) => Center(child: Text('error_loading_partners'.tr(args: [error.toString()]))),
);
}
}

View file

@ -85,7 +85,7 @@ class PlacesCollectionPage extends HookConsumerWidget {
},
);
},
error: (error, stask) => const Text('Error getting places'),
error: (error, stask) => Text('error_getting_places'.tr()),
loading: () => const Center(child: CircularProgressIndicator()),
),
],

View file

@ -435,7 +435,7 @@ class SearchPage extends HookConsumerWidget {
}
},
icon: const Icon(Icons.more_vert_rounded),
tooltip: 'Show text search menu',
tooltip: 'show_text_search_menu'.tr(),
);
},
menuChildren: [

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:auto_route/auto_route.dart';
import 'package:drift/drift.dart' hide Column;
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';
@ -135,7 +136,7 @@ class FeatInDevPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Features in Development'), centerTitle: true),
appBar: AppBar(title: Text('features_in_development'.tr()), centerTitle: true),
body: Column(
children: [
Flexible(

View file

@ -1,5 +1,6 @@
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';
@ -55,7 +56,7 @@ class LocalMediaSummaryPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Local Media Summary')),
appBar: AppBar(title: Text('local_media_summary'.tr())),
body: Consumer(
builder: (ctx, ref, __) {
final db = ref.watch(driftProvider);
@ -78,7 +79,7 @@ class LocalMediaSummaryPage extends StatelessWidget {
const Divider(),
Padding(
padding: const EdgeInsets.only(left: 15),
child: Text("Album summary", style: ctx.textTheme.titleMedium),
child: Text("album_summary".tr(), style: ctx.textTheme.titleMedium),
),
],
),
@ -135,7 +136,7 @@ class RemoteMediaSummaryPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Remote Media Summary')),
appBar: AppBar(title: Text('remote_media_summary'.tr())),
body: Consumer(
builder: (ctx, ref, __) {
final db = ref.watch(driftProvider);
@ -158,7 +159,7 @@ class RemoteMediaSummaryPage extends StatelessWidget {
const Divider(),
Padding(
padding: const EdgeInsets.only(left: 15),
child: Text("Album summary", style: ctx.textTheme.titleMedium),
child: Text("album_summary".tr(), style: ctx.textTheme.titleMedium),
),
],
),

View file

@ -1,4 +1,5 @@
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';
@ -14,7 +15,7 @@ class AssetTroubleshootPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(title: const Text("Asset Troubleshoot")),
appBar: AppBar(title: Text('asset_troubleshoot'.tr())),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
@ -37,20 +38,23 @@ class _AssetDetailsView extends ConsumerWidget {
children: [
_AssetPropertiesSection(asset: asset),
const SizedBox(height: 16),
Text('Matching Assets', style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold)),
Text(
'matching_assets'.tr(),
style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold),
),
if (asset.checksum != null) ...[
_LocalAssetsSection(asset: asset),
const SizedBox(height: 16),
_RemoteAssetSection(asset: asset),
] else ...[
const _PropertySectionCard(
_PropertySectionCard(
title: 'Local Assets',
properties: [_PropertyItem(label: 'Status', value: 'No checksum available - cannot fetch local assets')],
properties: [_PropertyItem(label: 'Status', value: 'no_checksum_local'.tr())],
),
const SizedBox(height: 16),
const _PropertySectionCard(
_PropertySectionCard(
title: 'Remote Assets',
properties: [_PropertyItem(label: 'Status', value: 'No checksum available - cannot fetch remote asset')],
properties: [_PropertyItem(label: 'Status', value: 'no_checksum_remote'.tr())],
),
],
],
@ -222,9 +226,9 @@ class _LocalAssetsSection extends ConsumerWidget {
}
if (localAssets.isEmpty) {
return const _PropertySectionCard(
return _PropertySectionCard(
title: 'Local Assets',
properties: [_PropertyItem(label: 'Status', value: 'No local assets found with this checksum')],
properties: [_PropertyItem(label: 'Status', value: 'no_local_assets_found'.tr())],
);
}
@ -281,9 +285,9 @@ class _RemoteAssetSection extends ConsumerWidget {
final remoteAsset = snapshot.data;
if (remoteAsset == null) {
return const _PropertySectionCard(
return _PropertySectionCard(
title: 'Remote Assets',
properties: [_PropertyItem(label: 'Status', value: 'No remote asset found with this checksum')],
properties: [_PropertyItem(label: 'Status', value: 'no_remote_assets_found'.tr())],
);
}
@ -336,7 +340,10 @@ class _PropertyItem extends StatelessWidget {
child: Text('$label:', style: const TextStyle(fontWeight: FontWeight.w500)),
),
Expanded(
child: Text(value ?? 'N/A', style: TextStyle(color: Theme.of(context).colorScheme.secondary)),
child: Text(
value ?? 'not_available'.tr(),
style: TextStyle(color: Theme.of(context).colorScheme.secondary),
),
),
],
),

View file

@ -1,4 +1,5 @@
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/user.model.dart';
@ -302,7 +303,9 @@ class _LocalAlbumsCollectionCard extends ConsumerWidget {
}).toList();
},
error: (error, _) {
return [Center(child: Text('Error: $error'))];
return [
Center(child: Text('error_saving_image'.tr(args: [error.toString()]))),
];
},
loading: () {
return [const Center(child: CircularProgressIndicator())];

View file

@ -1,4 +1,5 @@
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';
@ -46,9 +47,9 @@ class _AlbumList extends ConsumerWidget {
),
data: (albums) {
if (albums.isEmpty) {
return const SliverToBoxAdapter(
return SliverToBoxAdapter(
child: Center(
child: Padding(padding: EdgeInsets.all(20.0), child: Text('No albums found')),
child: Padding(padding: const EdgeInsets.all(20.0), child: Text('no_albums_yet'.tr())),
),
);
}

View file

@ -440,7 +440,7 @@ class DriftSearchPage extends HookConsumerWidget {
}
},
icon: const Icon(Icons.more_vert_rounded),
tooltip: 'Show text search menu',
tooltip: 'show_text_search_menu'.tr(),
);
},
menuChildren: [

View file

@ -1,4 +1,5 @@
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/domain/models/asset/base_asset.model.dart';
@ -58,7 +59,7 @@ class LikeActivityActionButton extends ConsumerWidget {
label: "like".t(context: context),
menuItem: menuItem,
),
error: (error, stack) => Text("Error: $error"),
error: (error, stack) => Text('error_saving_image'.tr(args: [error.toString()])),
);
}
}

View file

@ -504,9 +504,9 @@ class _AlbumList extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
if (albums.isEmpty) {
return const SliverToBoxAdapter(
return SliverToBoxAdapter(
child: Center(
child: Padding(padding: EdgeInsets.all(20.0), child: Text('No albums found')),
child: Padding(padding: const EdgeInsets.all(20.0), child: Text('album_search_not_found'.tr())),
),
);
}
@ -599,9 +599,9 @@ class _AlbumGrid extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (albums.isEmpty) {
return const SliverToBoxAdapter(
return SliverToBoxAdapter(
child: Center(
child: Padding(padding: EdgeInsets.all(20.0), child: Text('No albums found')),
child: Padding(padding: const EdgeInsets.all(20.0), child: Text('album_search_not_found'.tr())),
),
);
}

View file

@ -98,7 +98,12 @@ class BottomGalleryBar extends ConsumerWidget {
if (isDeleted) {
// Can only trash assets stored in server. Local assets are always permanently removed for now
if (context.mounted && asset.isRemote && isStackPrimaryAsset) {
ImmichToast.show(durationInSecond: 1, context: context, msg: 'Asset trashed', gravity: ToastGravity.BOTTOM);
ImmichToast.show(
durationInSecond: 1,
context: context,
msg: 'asset_trashed'.tr(),
gravity: ToastGravity.BOTTOM,
);
}
removeAssetFromStack();
}

View file

@ -29,7 +29,7 @@ class CastDialog extends ConsumerWidget {
future: ref.read(castProvider.notifier).getDevices(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Error: ${snapshot.error.toString()}');
return Text('error_saving_image'.tr(args: [snapshot.error.toString()]));
} else if (!snapshot.hasData) {
return const SizedBox(height: 48, child: Center(child: CircularProgressIndicator()));
}

View file

@ -275,7 +275,7 @@ class _MapSheetDragRegion extends StatelessWidget {
child: IconButton(
icon: Icon(Icons.map_outlined, color: context.textTheme.displayLarge?.color),
iconSize: 24,
tooltip: 'Zoom to bounds',
tooltip: 'zoom_to_bounds'.tr(),
onPressed: () => onZoomToAsset?.call(value!),
),
),