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:
Matthias Rupp 2022-07-07 20:40:54 +02:00 committed by GitHub
parent f3032f74a4
commit 2b5cef156c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 601 additions and 213 deletions

View file

@ -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,

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: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,
);

View file

@ -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(),
),
);
}

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: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(),
),
),
)

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';
@ -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(),
),
],
),

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';
@ -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(),
),
],
),

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';
@ -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,
),

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';
@ -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(),
)
],
),

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';
@ -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(

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: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