mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
Internationalization (German) of the mobile app. (#246)
* Add i18n framework to mobile app and write simple translation generator * Replace all texts in login_form with i18n keys * Localization of sharing section * Localization of asset viewer section * Use JSON as base translation format * Add check for missing/unused translation keys * Add localizely * Remove i18n directory in favour of localizely * Backup Translation * More translations * Translate home page * Translation of search page * Translate new server version announcement * Reformat code * Fix typo in german translation * Update englisch translations * Change translation keys to match dart filenames * Add /api to translated endpoint_urls * Update localizely.yml * Add languages to ios plist * Remove unused keys * Added script to check outdated key in other translations * Add download key to localizely.yml Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
parent
f3032f74a4
commit
2b5cef156c
36 changed files with 601 additions and 213 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/modules/sharing/providers/album_title.provider.dart';
|
||||
|
|
@ -59,7 +60,7 @@ class AlbumTitleTextField extends ConsumerWidget {
|
|||
borderSide: const BorderSide(color: Colors.transparent),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
hintText: 'Add a title',
|
||||
hintText: 'share_add_title'.tr(),
|
||||
focusColor: Colors.grey[300],
|
||||
fillColor: Colors.grey[200],
|
||||
filled: isAlbumTitleTextFieldFocus.value,
|
||||
|
|
|
|||
|
|
@ -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:fluttertoast/fluttertoast.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
|
@ -45,7 +46,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
|
|||
} else {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "Failed to delete album",
|
||||
msg: "album_viewer_appbar_share_err_delete".tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
|
|
@ -67,7 +68,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
|
|||
Navigator.pop(context);
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "Failed to leave album",
|
||||
msg: "album_viewer_appbar_share_err_leave".tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
|
|
@ -93,7 +94,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
|
|||
Navigator.pop(context);
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "There are problems in removing assets from album",
|
||||
msg: "album_viewer_appbar_share_err_remove".tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
|
|
@ -108,9 +109,9 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
|
|||
return ListTile(
|
||||
leading: const Icon(Icons.delete_sweep_rounded),
|
||||
title: const Text(
|
||||
'Remove from album',
|
||||
'album_viewer_appbar_share_remove',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
).tr(),
|
||||
onTap: () => _onRemoveFromAlbumPressed(albumId),
|
||||
);
|
||||
} else {
|
||||
|
|
@ -121,18 +122,18 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
|
|||
return ListTile(
|
||||
leading: const Icon(Icons.delete_forever_rounded),
|
||||
title: const Text(
|
||||
'Delete album',
|
||||
'album_viewer_appbar_share_delete',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
).tr(),
|
||||
onTap: () => _onDeleteAlbumPressed(albumId),
|
||||
);
|
||||
} else {
|
||||
return ListTile(
|
||||
leading: const Icon(Icons.person_remove_rounded),
|
||||
title: const Text(
|
||||
'Leave album',
|
||||
'album_viewer_appbar_share_leave',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
).tr(),
|
||||
onTap: () => _onLeaveAlbumPressed(albumId),
|
||||
);
|
||||
}
|
||||
|
|
@ -176,7 +177,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
|
|||
if (!isSuccess) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "Failed to change album title",
|
||||
msg: "album_viewer_appbar_share_err_title".tr(),
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
toastType: ToastType.error,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
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';
|
||||
|
|
@ -74,7 +75,7 @@ class AlbumViewerEditableTitle extends HookConsumerWidget {
|
|||
focusColor: Colors.grey[300],
|
||||
fillColor: Colors.grey[200],
|
||||
filled: titleFocusNode.hasFocus,
|
||||
hintText: 'Add a title',
|
||||
hintText: 'share_add_title'.tr(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:immich_mobile/routing/router.dart';
|
||||
|
||||
|
|
@ -51,10 +52,10 @@ class SharingSliverAppBar extends StatelessWidget {
|
|||
size: 20,
|
||||
),
|
||||
label: const Text(
|
||||
"Create shared album",
|
||||
"sharing_silver_appbar_create_shared_album",
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -73,10 +74,10 @@ class SharingSliverAppBar extends StatelessWidget {
|
|||
size: 20,
|
||||
),
|
||||
label: const Text(
|
||||
"Share with partner",
|
||||
"sharing_silver_appbar_share_partner",
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
@ -204,13 +205,13 @@ class AlbumViewerPage extends HookConsumerWidget {
|
|||
AlbumActionOutlinedButton(
|
||||
iconData: Icons.add_photo_alternate_outlined,
|
||||
onPressed: () => _onAddPhotosPressed(albumInfo),
|
||||
labelText: "Add photos",
|
||||
labelText: "share_add_photos".tr(),
|
||||
),
|
||||
if (userId == albumInfo.ownerId)
|
||||
AlbumActionOutlinedButton(
|
||||
iconData: Icons.person_add_alt_rounded,
|
||||
onPressed: () => _onAddUsersPressed(albumInfo),
|
||||
labelText: "Add users",
|
||||
labelText: "album_viewer_page_share_add_users".tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
@ -65,9 +66,9 @@ class AssetSelectionPage extends HookConsumerWidget {
|
|||
),
|
||||
title: selectedAssets.isEmpty
|
||||
? const Text(
|
||||
'Add photos',
|
||||
'share_add_photos',
|
||||
style: TextStyle(fontSize: 18),
|
||||
)
|
||||
).tr()
|
||||
: Text(
|
||||
_buildAssetCountText(),
|
||||
style: const TextStyle(fontSize: 18),
|
||||
|
|
@ -86,9 +87,9 @@ class AssetSelectionPage extends HookConsumerWidget {
|
|||
AutoRouter.of(context).pop(payload);
|
||||
},
|
||||
child: const Text(
|
||||
"Add",
|
||||
"share_add",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
@ -64,13 +65,13 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
|
|||
|
||||
_buildTitle() {
|
||||
if (selectedAssets.isEmpty) {
|
||||
return const SliverToBoxAdapter(
|
||||
return SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 200, left: 18),
|
||||
child: Text(
|
||||
'ADD ASSETS',
|
||||
'create_shared_album_page_share_add_assets',
|
||||
style: TextStyle(fontSize: 12),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -97,12 +98,12 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
|
|||
label: Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
'Select Photos',
|
||||
'create_shared_album_page_share_select_photos',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.grey[700],
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -123,7 +124,7 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
|
|||
AlbumActionOutlinedButton(
|
||||
iconData: Icons.add_photo_alternate_outlined,
|
||||
onPressed: _onSelectPhotosButtonPressed,
|
||||
labelText: "Add photos",
|
||||
labelText: "share_add_photos".tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -169,16 +170,16 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
|
|||
},
|
||||
icon: const Icon(Icons.close_rounded)),
|
||||
title: const Text(
|
||||
'Create album',
|
||||
'share_create_album',
|
||||
style: TextStyle(color: Colors.black),
|
||||
),
|
||||
).tr(),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: albumTitleController.text.isNotEmpty
|
||||
? _showSelectUserPage
|
||||
: null,
|
||||
child: const Text(
|
||||
'Share',
|
||||
child: Text(
|
||||
'create_shared_album_page_share'.tr(),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
@ -68,10 +69,10 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
|||
Wrap(
|
||||
children: [...usersChip],
|
||||
),
|
||||
const Padding(
|
||||
Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'Suggestions',
|
||||
'select_additional_user_for_sharing_page_suggestions'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey,
|
||||
|
|
@ -112,9 +113,9 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
|||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
'Invite to album',
|
||||
'share_invite',
|
||||
style: TextStyle(color: Colors.black),
|
||||
),
|
||||
).tr(),
|
||||
elevation: 0,
|
||||
centerTitle: false,
|
||||
leading: IconButton(
|
||||
|
|
@ -128,9 +129,9 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
|
|||
onPressed:
|
||||
sharedUsersList.value.isEmpty ? null : _addNewUsersHandler,
|
||||
child: const Text(
|
||||
"Add",
|
||||
"share_add",
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
|
||||
),
|
||||
).tr(),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
@ -36,8 +37,7 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
|||
.navigate(const TabControllerRoute(children: [SharingRoute()]));
|
||||
}
|
||||
|
||||
const ScaffoldMessenger(
|
||||
child: SnackBar(content: Text('Failed to create album')));
|
||||
ScaffoldMessenger(child: SnackBar(content: Text('select_user_for_sharing_page_err_album').tr()));
|
||||
}
|
||||
|
||||
_buildTileIcon(User user) {
|
||||
|
|
@ -84,15 +84,15 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
|||
Wrap(
|
||||
children: [...usersChip],
|
||||
),
|
||||
const Padding(
|
||||
Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'Suggestions',
|
||||
'share_suggestions',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
|
|
@ -128,9 +128,9 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
|||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
'Invite to album',
|
||||
'share_invite',
|
||||
style: TextStyle(color: Colors.black),
|
||||
),
|
||||
).tr(),
|
||||
elevation: 0,
|
||||
centerTitle: false,
|
||||
leading: IconButton(
|
||||
|
|
@ -144,9 +144,9 @@ class SelectUserForSharingPage extends HookConsumerWidget {
|
|||
onPressed:
|
||||
sharedUsersList.value.isEmpty ? null : _createSharedAlbum,
|
||||
child: const Text(
|
||||
"Create Album",
|
||||
"share_create_album",
|
||||
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
|
||||
))
|
||||
).tr())
|
||||
],
|
||||
),
|
||||
body: suggestedShareUsers.when(
|
||||
|
|
|
|||
|
|
@ -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:hive/hive.dart';
|
||||
|
|
@ -104,20 +105,20 @@ class SharingPage extends HookConsumerWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
'EMPTY LIST',
|
||||
'sharing_page_empty_list',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
'Create shared albums to share photos and videos with people in your network.',
|
||||
'sharing_page_description',
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey[700]),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -131,15 +132,15 @@ class SharingPage extends HookConsumerWidget {
|
|||
body: CustomScrollView(
|
||||
slivers: [
|
||||
const SharingSliverAppBar(),
|
||||
const SliverPadding(
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Text(
|
||||
"Shared albums",
|
||||
"sharing_page_album",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
sharedAlbums.isNotEmpty
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue