From 17ac627ddd86ade3d48f08efcb597b6afc207802 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Tue, 1 Jul 2025 20:52:43 +0200 Subject: [PATCH 01/81] Align icon --- mobile/lib/ui/viewer/people/save_or_edit_person.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/lib/ui/viewer/people/save_or_edit_person.dart b/mobile/lib/ui/viewer/people/save_or_edit_person.dart index 8a3f597873..940530e942 100644 --- a/mobile/lib/ui/viewer/people/save_or_edit_person.dart +++ b/mobile/lib/ui/viewer/people/save_or_edit_person.dart @@ -193,6 +193,8 @@ class _SaveOrEditPersonState extends State { icon: const Icon(Icons.edit), iconSize: 16, // specify the size of the icon + padding: EdgeInsets.zero, + constraints: const BoxConstraints(), onPressed: () async { final result = await showPersonAvatarPhotoSheet( From f66304815eac96ee296b8997bfa4344a43ab72fc Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Tue, 1 Jul 2025 20:58:22 +0200 Subject: [PATCH 02/81] Fix null error --- .../people/person_gallery_suggestion.dart | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/mobile/lib/ui/viewer/people/person_gallery_suggestion.dart b/mobile/lib/ui/viewer/people/person_gallery_suggestion.dart index 910dd70d26..7311e81de5 100644 --- a/mobile/lib/ui/viewer/people/person_gallery_suggestion.dart +++ b/mobile/lib/ui/viewer/people/person_gallery_suggestion.dart @@ -48,10 +48,10 @@ class _PersonGallerySuggestionState extends State bool get personPage => widget.person != null; PersonEntity get relevantPerson => widget.person ?? person!; - late AnimationController _slideController; - late AnimationController _fadeController; - late Animation _slideAnimation; - late Animation _fadeAnimation; + AnimationController? _slideController; + AnimationController? _fadeController; + Animation? _slideAnimation; + Animation? _fadeAnimation; @override void initState() { @@ -76,7 +76,7 @@ class _PersonGallerySuggestionState extends State end: Offset.zero, ).animate( CurvedAnimation( - parent: _slideController, + parent: _slideController!, curve: Curves.easeOutCubic, ), ); @@ -86,7 +86,7 @@ class _PersonGallerySuggestionState extends State end: 1.0, ).animate( CurvedAnimation( - parent: _fadeController, + parent: _fadeController!, curve: Curves.easeInOut, ), ); @@ -121,8 +121,10 @@ class _PersonGallerySuggestionState extends State }); } - unawaited(_fadeController.forward()); - unawaited(_slideController.forward()); + if (mounted && _fadeController != null && _slideController != null) { + unawaited(_fadeController!.forward()); + unawaited(_slideController!.forward()); + } unawaited(_precomputeNextSuggestions()); } else { @@ -371,25 +373,29 @@ class _PersonGallerySuggestionState extends State } Future _animateOut() async { - await Future.wait([ - _fadeController.reverse(), - _slideController.reverse(), - ]); + if (mounted && _fadeController != null && _slideController != null) { + await Future.wait([ + _fadeController!.reverse(), + _slideController!.reverse(), + ]); + } } Future _animateIn() async { - _slideController.reset(); - _fadeController.reset(); - await Future.wait([ - _fadeController.forward(), - _slideController.forward(), - ]); + if (mounted && _fadeController != null && _slideController != null) { + _slideController!.reset(); + _fadeController!.reset(); + await Future.wait([ + _fadeController!.forward(), + _slideController!.forward(), + ]); + } } @override void dispose() { - _slideController.dispose(); - _fadeController.dispose(); + _slideController?.dispose(); + _fadeController?.dispose(); super.dispose(); } @@ -398,7 +404,9 @@ class _PersonGallerySuggestionState extends State if (isLoading || allSuggestions.isEmpty || currentSuggestionIndex >= allSuggestions.length || - !hasCurrentSuggestion) { + !hasCurrentSuggestion || + _slideAnimation == null || + _fadeAnimation == null) { return const SizedBox.shrink(); } @@ -406,9 +414,9 @@ class _PersonGallerySuggestionState extends State final textTheme = getEnteTextTheme(context); return SlideTransition( - position: _slideAnimation, + position: _slideAnimation!, child: FadeTransition( - opacity: _fadeAnimation, + opacity: _fadeAnimation!, child: GestureDetector( key: ValueKey('suggestion_$currentSuggestionIndex'), onTap: _navigateToCluster, From 69fcdcf14b58a2f62d8377b3200de568a619d9f7 Mon Sep 17 00:00:00 2001 From: TKO-GLOBAL <35703717+TKO-GLOBAL@users.noreply.github.com> Date: Thu, 10 Jul 2025 19:21:03 +0100 Subject: [PATCH 03/81] Fix dead link and typo Fix web link to adding-icons doc which have moved. Fix paths in adding-icons to assets which have moved. Fix typo in authenticator --- docs/docs/auth/features/index.md | 4 ++-- mobile/apps/auth/docs/adding-icons.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/docs/auth/features/index.md b/docs/docs/auth/features/index.md index ddee2bd2fb..36d43392fa 100644 --- a/docs/docs/auth/features/index.md +++ b/docs/docs/auth/features/index.md @@ -12,7 +12,7 @@ This page outlines the key features available in Ente Auth. Ente Auth supports the icon pack provided by [simple-icons](https://github.com/simple-icons/simple-icons). If an icon you need is missing, please refer to the -[docs/adding-icons](https://github.com/ente-io/ente/blob/main/auth/docs/adding-icons.md) +[docs/adding-icons](https://github.com/ente-io/ente/blob/main/mobile/apps/auth/docs/adding-icons.md) guide for instructions on how to contribute. ### Search @@ -136,4 +136,4 @@ Easily add or share entries using QR codes: right-click (desktop) a code and select "QR". This allows you to easily share the complete entry (including the secret) with others by letting them scan the displayed QR code. This can also be used to easily add the same entry to - another authenticatior app or service. + another authenticator app or service. diff --git a/mobile/apps/auth/docs/adding-icons.md b/mobile/apps/auth/docs/adding-icons.md index 2d4c4f2c0d..6812332921 100644 --- a/mobile/apps/auth/docs/adding-icons.md +++ b/mobile/apps/auth/docs/adding-icons.md @@ -4,8 +4,8 @@ Ente Auth supports the icon pack provided by [simple-icons](https://github.com/simple-icons/simple-icons). If you would like to add your own custom icon, please open a pull-request with -the relevant SVG placed within `assets/custom-icons/icons` and add the -corresponding entry within `assets/custom-icons/_data/custom-icons.json`. +the relevant SVG placed within `mobile/apps/auth/assets/custom-icons/icons` and add the +corresponding entry within `mobile/apps/auth/assets/custom-icons/_data/custom-icons.json`. Please be careful to upload small and optimized icon files. If your icon file is over 50KB, it is likely not optimized. From 97b3a3cb574e39879015bbb24016d6e3bfddac8b Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Fri, 11 Jul 2025 14:50:52 +0200 Subject: [PATCH 04/81] Fix redirect to person memory --- .../lib/models/memories/memories_cache.dart | 14 +++++ .../lib/models/memories/people_memory.dart | 5 +- .../lib/services/memories_cache_service.dart | 52 ++++++++++++++----- 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/mobile/apps/photos/lib/models/memories/memories_cache.dart b/mobile/apps/photos/lib/models/memories/memories_cache.dart index 949107901d..f45282d30c 100644 --- a/mobile/apps/photos/lib/models/memories/memories_cache.dart +++ b/mobile/apps/photos/lib/models/memories/memories_cache.dart @@ -81,6 +81,8 @@ class ToShowMemory { final String id; final String? personID; + final String? personName; + final bool? isBirthday; final PeopleMemoryType? peopleMemoryType; final ClipMemoryType? clipMemoryType; final Location? location; @@ -107,6 +109,8 @@ class ToShowMemory { this.id, this.calculationTime, { this.personID, + this.personName, + this.isBirthday, this.peopleMemoryType, this.clipMemoryType, this.location, @@ -124,11 +128,15 @@ class ToShowMemory { factory ToShowMemory.fromSmartMemory(SmartMemory memory, DateTime calcTime) { String? personID; + String? personName; + bool? isBirthday; PeopleMemoryType? peopleMemoryType; ClipMemoryType? clipMemoryType; Location? location; if (memory is PeopleMemory) { personID = memory.personID; + personName = memory.personName; + isBirthday = memory.isBirthday; peopleMemoryType = memory.peopleMemoryType; } else if (memory is TripMemory) { location = memory.location; @@ -147,6 +155,8 @@ class ToShowMemory { memory.id, calcTime.microsecondsSinceEpoch, personID: personID, + personName: personName, + isBirthday: isBirthday, peopleMemoryType: peopleMemoryType, clipMemoryType: clipMemoryType, location: location, @@ -163,6 +173,8 @@ class ToShowMemory { json['id'] ?? newID(json['type'] as String), json['calculationTime'], personID: json['personID'], + isBirthday: json['isBirthday'], + personName: json['personName'], peopleMemoryType: json['peopleMemoryType'] != null ? peopleMemoryTypeFromString(json['peopleMemoryType']) : null, @@ -188,6 +200,8 @@ class ToShowMemory { 'id': id, 'calculationTime': calculationTime, 'personID': personID, + 'isBirthday': isBirthday, + 'personName': personName, 'peopleMemoryType': peopleMemoryType?.toString().split('.').last, 'clipMemoryType': clipMemoryType?.toString().split('.').last, 'location': location != null diff --git a/mobile/apps/photos/lib/models/memories/people_memory.dart b/mobile/apps/photos/lib/models/memories/people_memory.dart index 83f6b1a363..fea9190302 100644 --- a/mobile/apps/photos/lib/models/memories/people_memory.dart +++ b/mobile/apps/photos/lib/models/memories/people_memory.dart @@ -108,6 +108,8 @@ class PeopleMemory extends SmartMemory { this.peopleMemoryType, this.personID, this.personName, { + String? title, + String? id, super.firstCreationTime, super.lastCreationTime, this.activity, @@ -116,9 +118,10 @@ class PeopleMemory extends SmartMemory { }) : super( memories, MemoryType.people, - '', + title ?? '', firstDateToShow, lastDateToShow, + id: id, ); PeopleMemory copyWith({ diff --git a/mobile/apps/photos/lib/services/memories_cache_service.dart b/mobile/apps/photos/lib/services/memories_cache_service.dart index 51ea8710bb..9372322f84 100644 --- a/mobile/apps/photos/lib/services/memories_cache_service.dart +++ b/mobile/apps/photos/lib/services/memories_cache_service.dart @@ -241,20 +241,44 @@ class MemoriesCacheService { for (final ToShowMemory memory in cache.toShowMemories) { if (memory.shouldShowNow()) { - final smartMemory = SmartMemory( - memory.fileUploadedIDs - .where((fileID) => minimalFileIdsToFile.containsKey(fileID)) - .map( - (fileID) => - Memory.fromFile(minimalFileIdsToFile[fileID]!, seenTimes), - ) - .toList(), - memory.type, - memory.title, - memory.firstTimeToShow, - memory.lastTimeToShow, - id: memory.id, - ); + late final SmartMemory smartMemory; + if (memory.type == MemoryType.people) { + smartMemory = PeopleMemory( + memory.fileUploadedIDs + .where((fileID) => minimalFileIdsToFile.containsKey(fileID)) + .map( + (fileID) => Memory.fromFile( + minimalFileIdsToFile[fileID]!, + seenTimes, + ), + ) + .toList(), + memory.firstTimeToShow, + memory.lastTimeToShow, + memory.peopleMemoryType!, + memory.personID!, + memory.personName, + title: memory.title, + id: memory.id, + ); + } else { + smartMemory = SmartMemory( + memory.fileUploadedIDs + .where((fileID) => minimalFileIdsToFile.containsKey(fileID)) + .map( + (fileID) => Memory.fromFile( + minimalFileIdsToFile[fileID]!, + seenTimes, + ), + ) + .toList(), + memory.type, + memory.title, + memory.firstTimeToShow, + memory.lastTimeToShow, + id: memory.id, + ); + } if (smartMemory.memories.isNotEmpty) { memories.add(smartMemory); } From 884e805f463c84e775a2512ae64ebda624175567 Mon Sep 17 00:00:00 2001 From: TKO-GLOBAL <35703717+TKO-GLOBAL@users.noreply.github.com> Date: Sat, 12 Jul 2025 02:43:51 +0100 Subject: [PATCH 05/81] Add custom icon for Co-Wheels Add custom authenticator icon for co-wheels.org.uk --- .../auth/assets/custom-icons/_data/custom-icons.json | 4 ++++ mobile/apps/auth/assets/custom-icons/icons/cowheels.svg | 9 +++++++++ 2 files changed, 13 insertions(+) create mode 100644 mobile/apps/auth/assets/custom-icons/icons/cowheels.svg diff --git a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json index 589db8113c..4f8c6f58a4 100644 --- a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json +++ b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json @@ -1511,6 +1511,10 @@ }, { "title": "Zitadel" + }, + { + "title": "Co-Wheels", + "slug": "cowheels" } ] } diff --git a/mobile/apps/auth/assets/custom-icons/icons/cowheels.svg b/mobile/apps/auth/assets/custom-icons/icons/cowheels.svg new file mode 100644 index 0000000000..24faa4aeff --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/cowheels.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file From 2920f77c7529ff23da1861edcb9e962c6b9daee2 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 12 Jul 2025 11:21:35 +0530 Subject: [PATCH 06/81] If too many local files are attempted to be deleted using free up space feature, reduce the batch size and try deleting --- .../photos/lib/utils/delete_file_util.dart | 62 +++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/mobile/apps/photos/lib/utils/delete_file_util.dart b/mobile/apps/photos/lib/utils/delete_file_util.dart index 11a425afa0..839ba7712d 100644 --- a/mobile/apps/photos/lib/utils/delete_file_util.dart +++ b/mobile/apps/photos/lib/utils/delete_file_util.dart @@ -339,6 +339,9 @@ Future deleteLocalFiles( final List deletedIDs = []; final List localAssetIDs = []; final List localSharedMediaIDs = []; + + const largeCountThreshold = 20000; + final tooManyAssets = localIDs.length > largeCountThreshold; try { for (String id in localIDs) { if (id.startsWith(sharedMediaIdentifier)) { @@ -350,11 +353,23 @@ Future deleteLocalFiles( deletedIDs.addAll(await _tryDeleteSharedMediaFiles(localSharedMediaIDs)); final bool shouldDeleteInBatches = - await isAndroidSDKVersionLowerThan(android11SDKINT); + await isAndroidSDKVersionLowerThan(android11SDKINT) || tooManyAssets; if (shouldDeleteInBatches) { - _logger.info("Deleting in batches"); - deletedIDs - .addAll(await deleteLocalFilesInBatches(context, localAssetIDs)); + if (tooManyAssets) { + _logger.info( + "Too many assets (${localIDs.length}) to delete in one shot, deleting in batches", + ); + await _recursivelyReduceBatchSizeAndRetryDeletion( + batchSize: largeCountThreshold, + context: context, + localIDs: localIDs, + deletedIDs: deletedIDs, + ); + } else { + _logger.info("Deleting in batches"); + deletedIDs + .addAll(await deleteLocalFilesInBatches(context, localAssetIDs)); + } } else { _logger.info("Deleting in one shot"); deletedIDs @@ -625,6 +640,45 @@ Future> deleteLocalFilesInBatches( return deletedIDs; } +Future _recursivelyReduceBatchSizeAndRetryDeletion({ + required int batchSize, + required BuildContext context, + required List localIDs, + required List deletedIDs, + int minimumBatchSizeThresholdToStopRetry = 2000, +}) async { + if (batchSize < minimumBatchSizeThresholdToStopRetry) { + _logger.warning( + "Batch size is too small ($batchSize), stopping further retries.", + ); + throw Exception( + "Batch size reached minimum threshold: $batchSize. Stopping further retries.", + ); + } + try { + deletedIDs.addAll( + await deleteLocalFilesInBatches( + context, + localIDs, + minimumBatchSize: 1, + maximumBatchSize: batchSize, + minimumParts: 1, + ), + ); + } catch (e) { + _logger.warning( + "Failed to delete local files in batches of $batchSize. Reducing batch size and retrying.", + e, + ); + await _recursivelyReduceBatchSizeAndRetryDeletion( + batchSize: (batchSize / 2).floor(), + context: context, + localIDs: localIDs, + deletedIDs: deletedIDs, + ); + } +} + Future _localFileExist(EnteFile file) { if (file.isSharedMediaToAppSandbox) { final localFile = File(getSharedMediaFilePath(file)); From e259b06d636de44992adf356102ec586752a9f7c Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 12 Jul 2025 11:32:44 +0530 Subject: [PATCH 07/81] Minor correction in execption --- mobile/apps/photos/lib/utils/delete_file_util.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/apps/photos/lib/utils/delete_file_util.dart b/mobile/apps/photos/lib/utils/delete_file_util.dart index 839ba7712d..efb9db6093 100644 --- a/mobile/apps/photos/lib/utils/delete_file_util.dart +++ b/mobile/apps/photos/lib/utils/delete_file_util.dart @@ -652,7 +652,7 @@ Future _recursivelyReduceBatchSizeAndRetryDeletion({ "Batch size is too small ($batchSize), stopping further retries.", ); throw Exception( - "Batch size reached minimum threshold: $batchSize. Stopping further retries.", + "Batch size is too small ($batchSize), stopping further retries.", ); } try { From 9233149e251158d1b2c612f871fd45fd8f46d359 Mon Sep 17 00:00:00 2001 From: sanojsubran Date: Sun, 13 Jul 2025 13:51:45 +0200 Subject: [PATCH 08/81] fix: Updated the broken link in the README.md --- mobile/apps/auth/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/apps/auth/README.md b/mobile/apps/auth/README.md index 1709302ae8..610b663a8e 100644 --- a/mobile/apps/auth/README.md +++ b/mobile/apps/auth/README.md @@ -73,7 +73,7 @@ If the code you're working needs to modify user facing strings, see ## 🔩 Architecture The architecture that powers end-to-end encrypted storage and sync of your -tokens has been documented [here](../architecture/README.md). +tokens has been documented [here](architecture/README.md). ## 🌍 Translate From d2228ccd584d5e3983f7262fbc684c50f202cc8a Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 14 Jul 2025 01:18:02 +0000 Subject: [PATCH 09/81] New Crowdin translations by GitHub Action --- mobile/apps/auth/lib/l10n/arb/app_be.arb | 38 +++ mobile/apps/auth/lib/l10n/arb/app_ca.arb | 9 +- mobile/apps/auth/lib/l10n/arb/app_ms.arb | 1 + mobile/apps/auth/lib/l10n/arb/app_vi.arb | 388 ++++++++++++----------- 4 files changed, 244 insertions(+), 192 deletions(-) create mode 100644 mobile/apps/auth/lib/l10n/arb/app_ms.arb diff --git a/mobile/apps/auth/lib/l10n/arb/app_be.arb b/mobile/apps/auth/lib/l10n/arb/app_be.arb index 8323190ec7..47168446a0 100644 --- a/mobile/apps/auth/lib/l10n/arb/app_be.arb +++ b/mobile/apps/auth/lib/l10n/arb/app_be.arb @@ -177,24 +177,50 @@ "systemTheme": "Сістэманая", "invalidKey": "Памылковы ключ", "tryAgain": "Паспрабуйце яшчэ раз", + "confirmYourRecoveryKey": "Пацвердзіце свой ключ аднаўлення", "confirm": "Пацвердзіць", "emailYourLogs": "Адправіць журналы", + "pleaseSendTheLogsTo": "Адпраўце журналы на \n{toEmail}", + "copyEmailAddress": "Скапіяваць адрас электроннай пошты", "exportLogs": "Экспартаваць журналы", + "enterYourRecoveryKey": "Увядзіце свой ключ аднаўлення", + "tempErrorContactSupportIfPersists": "Здаецца, што нешта пайшло не так. Паспрабуйце яшчэ раз крыху пазней. Звяжыцеся са службай падтрымкі, калі праблема застанецца.", + "networkHostLookUpErr": "Немагчыма падключыцца да сервера Ente. Праверце свае сеткавыя налады. Звяжыцеся са службай падтрымкі, калі праблема застанецца.", "about": "Аб праграме", + "weAreOpenSource": "Наша праграма мае адкрыты зыходны код!", "privacy": "Прыватнасць", "terms": "Умовы", + "checkForUpdates": "Праверыць абнаўленні", "checkStatus": "Праверыць статус", "downloadUpdate": "Спампаваць", + "criticalUpdateAvailable": "Даступна крытычнае абнаўленне", + "updateAvailable": "Даступна абнаўленне", "update": "Абнавіць", "checking": "Праверка...", + "youAreOnTheLatestVersion": "У вас апошняя версія праграмы", "warning": "Папярэджанне", + "exportWarningDesc": "Экспартаваны файл змяшчае канфідэнцыяльныя звесткі. Захоўвайце яго ў надзейным месцы.", "iUnderStand": "Ясна", "@iUnderStand": { "description": "Text for the button to confirm the user understands the warning" }, + "authToExportCodes": "Прайдзіце аўтэнтыфікацыю, каб экспартаваць свае коды", "importSuccessTitle": "Ура!", + "importSuccessDesc": "Коды паспяхова імпартаваны ({count} шт.)!", + "@importSuccessDesc": { + "placeholders": { + "count": { + "description": "The number of codes imported", + "type": "int", + "example": "1" + } + } + }, "sorry": "Прабачце", + "importFailureDesc": "Не ўдалося прааналізаваць выбраны файл.\nНапішыце нам на support@ente.io, калі вам патрэбная дапамога!", "pendingSyncs": "Папярэджанне", + "pendingSyncsWarningBody": "Некаторыя вашы коды не былі зарэзерваваны.\n\nПераканайцеся, што ў вас ёсць іх рэзервовая копія перад выхадам з сістэмы.", + "checkInboxAndSpamFolder": "Праверце свае ўваходныя лісты (і спам) для завяршэння праверкі", "resendEmail": "Адправіць ліст яшчэ раз", "manualSort": "Карыстальніцкая", "editOrder": "Рэдагаваць заказ", @@ -205,12 +231,24 @@ "thisDevice": "Гэта прылада", "incorrectCode": "Няправільны код", "enterPassword": "Увядзіце пароль", + "selectExportFormat": "Выберыце фармат экспартавання", + "exportDialogDesc": "Зашыфраванае экспартаванне будзе абаронена паролем, які вы выберыце.", "encrypted": "Зашыфравана", "plainText": "Звычайны тэкст", + "passwordToEncryptExport": "Пароль для шыфравання экспартавання", "export": "Экспартаваць", + "useOffline": "Выкарыстоўваць без рэзервовых копій", + "signInToBackup": "Увайсці для рэзервовага капіявання кодаў", "singIn": "Увайсці", + "sigInBackupReminder": "Экспартуйце свае коды, каб у вас была рэзервовая копія з якой вы заўсёды зможаце аднавіць іх.", + "offlineModeWarning": "Вы выбралі працягнуць без рэзервовых копій. Зрабіце рэзервовую копію кодаў уручную, каб не згубіць доступ да іх.", + "showLargeIcons": "Паказваць вялікі значкі", "compactMode": "Кампактны рэжым", "shouldHideCode": "Схаваць коды", + "doubleTapToViewHiddenCode": "Можна двойчы націснуць на запіс, каб паглядзець код", + "focusOnSearchBar": "Сфакусіравацца на пошуку пры запуску праграмы", + "confirmUpdatingkey": "Вы сапраўды хочаце абнавіць сакрэтны ключ?", + "minimizeAppOnCopy": "Згортваць праграму пры капіяванні", "androidBiometricHint": "Праверыць ідэнтыфікацыю", "@androidBiometricHint": { "description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters." diff --git a/mobile/apps/auth/lib/l10n/arb/app_ca.arb b/mobile/apps/auth/lib/l10n/arb/app_ca.arb index f999b4ca29..af7acc29ea 100644 --- a/mobile/apps/auth/lib/l10n/arb/app_ca.arb +++ b/mobile/apps/auth/lib/l10n/arb/app_ca.arb @@ -173,6 +173,7 @@ "invalidQRCode": "Codi QR invàlid", "noRecoveryKeyTitle": "No tens clau de recuperació?", "enterEmailHint": "Introdueix la teva adreça de correu electrònic", + "enterNewEmailHint": "Introdueix la teva nova adreça de correu electrònic", "invalidEmailTitle": "Adreça de correu electrònic no vàlida", "invalidEmailMessage": "Si us plau, introdueix una adreça de correu electrònic vàlida.", "deleteAccount": "Elimina el compte", @@ -499,16 +500,22 @@ "appLockOfflineModeWarning": "Has triat procedir sense còpies de seguretat. Si oblides el bloqueig de l'aplicació, no podràs accedir a les teves dades.", "duplicateCodes": "Codis duplicats", "noDuplicates": "✨ Sense duplicats", + "youveNoDuplicateCodesThatCanBeCleared": "No teniu cap codi duplicat que es puguin esborrar", "deduplicateCodes": "Desduplica codis", "deselectAll": "Desselecciona-ho tot", "selectAll": "Seleccionar-ho tot", "deleteDuplicates": "Elimina duplicats", "plainHTML": "HTML pla", "tellUsWhatYouThink": "Digueu-nos què us sembla", + "dropReviewiOS": "Deixa una ressenya a l'App Store", + "dropReviewAndroid": "Deixa una ressenya a la Play Store", "supportEnte": "Donar suport a ente", "giveUsAStarOnGithub": "Dona'ns una estrella a Github", "free5GB": "5 GB gratuïts a ente Photos", "loginWithAuthAccount": "Inicieu sessió amb el vostre compte Auth", "freeStorageOffer": "10% de descompte a ente photos", - "freeStorageOfferDescription": "Utilitzeu el codi \"AUTH\" per obtenir un 10% de descompte el primer any" + "freeStorageOfferDescription": "Utilitzeu el codi \"AUTH\" per obtenir un 10% de descompte el primer any", + "advanced": "Avançat", + "algorithm": "Algorisme", + "type": "Tipus" } \ No newline at end of file diff --git a/mobile/apps/auth/lib/l10n/arb/app_ms.arb b/mobile/apps/auth/lib/l10n/arb/app_ms.arb new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/mobile/apps/auth/lib/l10n/arb/app_ms.arb @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/mobile/apps/auth/lib/l10n/arb/app_vi.arb b/mobile/apps/auth/lib/l10n/arb/app_vi.arb index 78f328e451..82f8bace1d 100644 --- a/mobile/apps/auth/lib/l10n/arb/app_vi.arb +++ b/mobile/apps/auth/lib/l10n/arb/app_vi.arb @@ -1,28 +1,28 @@ { "account": "Tài khoản", "unlock": "Mở khóa", - "recoveryKey": "Khóa khôi phục", - "counterAppBarTitle": "Bộ Đếm", + "recoveryKey": "Mã khôi phục", + "counterAppBarTitle": "Đếm ngược", "@counterAppBarTitle": { "description": "Text shown in the AppBar of the Counter Page" }, - "onBoardingBody": "Sao lưu mã 2FA của bạn một cách an toàn", + "onBoardingBody": "Sao lưu an toàn mã 2FA của bạn", "onBoardingGetStarted": "Bắt đầu", "setupFirstAccount": "Thiết lập tài khoản đầu tiên của bạn", "importScanQrCode": "Quét mã QR", "qrCode": "Mã QR", "importEnterSetupKey": "Nhập khóa thiết lập", "importAccountPageTitle": "Nhập chi tiết tài khoản", - "secretCanNotBeEmpty": "Khoá bí mật không được để trống", - "bothIssuerAndAccountCanNotBeEmpty": "Cả nhà phát hành và tài khoản không được để trống", - "incorrectDetails": "Thông tin chi tiết không chính xác", + "secretCanNotBeEmpty": "Không được để trống khóa bí mật", + "bothIssuerAndAccountCanNotBeEmpty": "Không được để trống dịch vụ và tài khoản", + "incorrectDetails": "Thông tin không chính xác", "pleaseVerifyDetails": "Vui lòng xác minh chi tiết và thử lại", - "codeIssuerHint": "Bên phát hành", + "codeIssuerHint": "Dịch vụ", "codeSecretKeyHint": "Khóa bí mật", "secret": "Khóa bí mật", "all": "Tất cả", "notes": "Ghi chú", - "notesLengthLimit": "Ghi chú có thể dài tối đa {count} ký tự", + "notesLengthLimit": "Ghi chú dài tối đa {count} ký tự", "@notesLengthLimit": { "description": "Text to indicate the maximum number of characters allowed for notes", "placeholders": { @@ -33,10 +33,10 @@ } } }, - "codeAccountHint": "Tài khoản (bạn@miền.com)", + "codeAccountHint": "Tài khoản (you@domain.com)", "codeTagHint": "Thẻ", "accountKeyType": "Loại khóa", - "sessionExpired": "Phiên làm việc đã hết hạn", + "sessionExpired": "Phiên đăng nhập đã hết hạn", "@sessionExpired": { "description": "Title of the dialog when the users current session is invalid/expired" }, @@ -47,15 +47,15 @@ "saveAction": "Lưu", "nextTotpTitle": "tiếp theo", "deleteCodeTitle": "Xóa mã?", - "deleteCodeMessage": "Bạn có chắc chắn muốn xóa mã này không? Hành động này không thể đảo ngược.", + "deleteCodeMessage": "Bạn có chắc muốn xóa mã này không? Hành động này không thể hoàn tác.", "trashCode": "Xóa mã?", - "trashCodeMessage": "Bạn có chắc chắn muốn xóa mã cho {account} không?", + "trashCodeMessage": "Bạn có chắc muốn xóa mã cho {account} không?", "trash": "Xóa", "viewLogsAction": "Xem nhật ký", - "sendLogsDescription": "Thao tác này sẽ gửi nhật ký để giúp chúng tôi gỡ lỗi sự cố của bạn. Mặc dù chúng tôi thực hiện các biện pháp phòng ngừa để đảm bảo rằng thông tin nhạy cảm không được ghi lại, nhưng chúng tôi khuyến khích bạn xem các nhật ký này trước khi chia sẻ chúng.", - "preparingLogsTitle": "Đang chuẩn bị nhật ký...", + "sendLogsDescription": "Gửi nhật ký để giúp chúng tôi xử lý vấn đề của bạn. Dù chúng tôi thực hiện các biện pháp phòng ngừa để đảm bảo rằng thông tin nhạy cảm không được ghi lại, bạn vẫn nên xem các nhật ký này trước khi chia sẻ chúng.", + "preparingLogsTitle": "Đang ghi nhật ký...", "emailLogsTitle": "Nhật ký email", - "emailLogsMessage": "Vui lòng gửi nhật ký tới {email}", + "emailLogsMessage": "Vui lòng gửi nhật ký đến {email}", "@emailLogsMessage": { "placeholders": { "email": { @@ -65,7 +65,7 @@ }, "copyEmailAction": "Sao chép email", "exportLogsAction": "Xuất nhật ký", - "reportABug": "Báo cáo lỗi", + "reportABug": "Báo lỗi", "crashAndErrorReporting": "Báo cáo sự cố & lỗi", "reportBug": "Báo lỗi", "emailUsMessage": "Vui lòng gửi email cho chúng tôi tại {email}", @@ -79,88 +79,88 @@ "contactSupport": "Liên hệ hỗ trợ", "rateUsOnStore": "Đánh giá chúng tôi trên {storeName}", "blog": "Blog", - "merchandise": "Hàng hóa", - "verifyPassword": "Xác nhận mật khẩu", + "merchandise": "Vật phẩm", + "verifyPassword": "Xác minh mật khẩu", "pleaseWait": "Vui lòng chờ...", "generatingEncryptionKeysTitle": "Đang tạo khóa mã hóa...", "recreatePassword": "Tạo lại mật khẩu", - "recreatePasswordMessage": "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn, vì vậy chúng tôi cần tạo lại mật khẩu một lần theo cách hoạt động với tất cả các thiết bị.\n\nVui lòng đăng nhập bằng khóa khôi phục và tạo lại mật khẩu của bạn (bạn có thể sử dụng lại cùng một mật khẩu nếu muốn).", - "useRecoveryKey": "Dùng khóa khôi phục", + "recreatePasswordMessage": "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn, nhưng chúng tôi có thể tạo lại để nó hoạt động với tất cả thiết bị.\n\nVui lòng đăng nhập bằng mã khôi phục và tạo lại mật khẩu (bạn có thể dùng lại mật khẩu cũ nếu muốn).", + "useRecoveryKey": "Dùng mã khôi phục", "incorrectPasswordTitle": "Mật khẩu không đúng", "welcomeBack": "Chào mừng trở lại!", - "emailAlreadyRegistered": "Email đã được đăng kí.", - "emailNotRegistered": "Email chưa được đăng kí.", - "madeWithLoveAtPrefix": "được làm bằng ❤️ tại ", + "emailAlreadyRegistered": "Email đã được đăng ký.", + "emailNotRegistered": "Email chưa được đăng ký.", + "madeWithLoveAtPrefix": "lập trình bằng ❤️ bởi ", "supportDevs": "Đăng ký ente để hỗ trợ dự án này.", - "supportDiscount": "Sử dụng mã giảm giá \"AUTH\" để được giảm 10% trong năm đầu tiên", - "changeEmail": "Thay đổi email", + "supportDiscount": "Dùng mã \"AUTH\" để được giảm 10% trong năm đầu tiên", + "changeEmail": "Đổi email", "changePassword": "Đổi mật khẩu", "data": "Dữ liệu", "importCodes": "Nhập mã", "importTypePlainText": "Văn bản thuần", - "importTypeEnteEncrypted": "Xuất key đã được mã hóa", - "passwordForDecryptingExport": "Mật khẩu để giải mã xuất", + "importTypeEnteEncrypted": "Ente Auth", + "passwordForDecryptingExport": "Mật khẩu để giải mã tệp xuất", "passwordEmptyError": "Mật khẩu không thể để trống", "importFromApp": "Nhập mã từ {appName}", - "importGoogleAuthGuide": "Xuất dữ liệu tài khoản của bạn từ Google Authenticator sang mã QR bằng tùy chọn \"Chuyển tài khoản\". Sau đó dùng thiết bị khác quét mã QR.", + "importGoogleAuthGuide": "Xuất dữ liệu tài khoản Google Authenticator của bạn thành mã QR bằng tùy chọn \"Chuyển tài khoản\". Sau đó, dùng thiết bị khác quét mã QR.", "importSelectJsonFile": "Chọn tệp JSON", - "importSelectAppExport": "Chọn {appName} tệp dữ liệu xuất", - "importEnteEncGuide": "Chọn tệp JSON được mã hóa đã xuất từ ​​ente", - "importRaivoGuide": "Sử dụng tùy chọn \"Xuất OTP sang lưu trữ Zip\" trong cài đặt của Raivo.", - "importBitwardenGuide": "Sử dụng tùy chọn \"Xuất vault\" trong công cụ Bitwarden và nhập tệp JSON không được mã hóa.", - "importAegisGuide": "Nếu vault của bạn được mã hóa, bạn sẽ cần nhập mật khẩu vault để giải mã vault.", - "import2FasGuide": "Sử dụng tùy chọn \"Cài đặt->Sao lưu -Xuất dữ liệu\" trong 2FAS.\n\nNếu bản sao lưu của bạn được mã hóa, bạn sẽ cần nhập mật khẩu để giải mã bản sao lưu", - "importLastpassGuide": "Sử dụng tùy chọn \"Chuyển tài khoản\" trong Cài đặt Lastpass Authenticator và nhấn \"Xuất tài khoản ra tệp\". Nhập tệp JSON đã tải xuống.", + "importSelectAppExport": "Chọn tệp xuất từ {appName}", + "importEnteEncGuide": "Chọn tệp JSON Ente đã mã hóa", + "importRaivoGuide": "Dùng tùy chọn \"Xuất OTP thành tệp Zip\" của Raivo.\n\nGiải nén tệp Zip đó và nhập tệp JSON.", + "importBitwardenGuide": "Dùng tùy chọn \"Xuất kho\" của Bitwarden và nhập tệp JSON không có mã hóa.", + "importAegisGuide": "Dùng tùy chọn \"Xuất kho\" của Aegis.\n\nNếu kho của bạn có mã hóa, bạn phải có mật khẩu để giải mã.", + "import2FasGuide": "Dùng tùy chọn \"Cài đặt->Sao lưu -Xuất dữ liệu\" của 2FAS.\n\nNếu bản sao lưu của bạn có mã hóa, bạn phải có mật khẩu để giải mã.", + "importLastpassGuide": "Dùng tùy chọn \"Chuyển tài khoản\" của Lastpass Authenticator và nhấn \"Xuất tài khoản ra tệp\". Nhập tệp JSON đã tải xuống.", "exportCodes": "Xuất mã", "importLabel": "Nhập", - "importInstruction": "Vui lòng chọn tệp chứa danh sách mã của bạn ở định dạng sau", - "importCodeDelimiterInfo": "Các mã có thể được phân tách bằng một dấu phẩy hoặc một dòng mới", - "selectFile": "Chọn tập tin", - "emailVerificationToggle": "Email xác thực", + "importInstruction": "Vui lòng chọn tệp chứa danh sách mã của bạn có định dạng", + "importCodeDelimiterInfo": "Phân tách mã bằng dấu phẩy hoặc xuống dòng", + "selectFile": "Chọn tệp", + "emailVerificationToggle": "Xác minh email", "emailVerificationEnableWarning": "Để tránh bị khóa tài khoản, hãy đảm bảo lưu trữ bản sao email 2FA của bạn bên ngoài Ente Auth trước khi bật xác minh email.", - "authToChangeEmailVerificationSetting": "Vui lòng xác thực để thay đổi email", + "authToChangeEmailVerificationSetting": "Vui lòng xác thực để đổi email", "authenticateGeneric": "Vui lòng xác thực", - "authToViewYourRecoveryKey": "Vui lòng xác thực để xem khóa khôi phục của bạn", + "authToViewYourRecoveryKey": "Vui lòng xác thực để xem mã khôi phục", "authToChangeYourEmail": "Vui lòng xác thực để thay đổi email của bạn", - "authToChangeYourPassword": "Vui lòng xác thực để thay đổi mật khẩu của bạn", - "authToViewSecrets": "Vui lòng xác thực để xem bí mật của bạn", - "authToInitiateSignIn": "Vui lòng xác thực để bắt đầu đăng nhập nhằm sao lưu.", - "ok": "Đồng ý", + "authToChangeYourPassword": "Vui lòng xác thực để đổi mật khẩu", + "authToViewSecrets": "Vui lòng xác thực để xem khóa bí mật", + "authToInitiateSignIn": "Vui lòng xác thực để bắt đầu sao lưu", + "ok": "Được", "cancel": "Hủy", - "yes": "Đúng", + "yes": "Có", "no": "Không", - "email": "Thư điện tử", + "email": "Email", "support": "Hỗ trợ", - "general": "Tổng quan", + "general": "Chung", "settings": "Cài đặt", "copied": "Đã sao chép", "pleaseTryAgain": "Vui lòng thử lại", - "existingUser": "Người dùng hiện tại", - "newUser": "Mới tham gia Ente", + "existingUser": "Đã có tài khoản", + "newUser": "Mới dùng Ente", "delete": "Xóa", "enterYourPasswordHint": "Nhập mật khẩu của bạn", "forgotPassword": "Quên mật khẩu", - "oops": "Rất tiếc", - "suggestFeatures": "Gợi ý tính năng", + "oops": "Ốii!", + "suggestFeatures": "Đề xuất tính năng", "faq": "Câu hỏi thường gặp", - "somethingWentWrongMessage": "Đã xảy ra lỗi, xin thử lại", - "leaveFamily": "Rời khỏi gia đình", - "leaveFamilyMessage": "Bạn có chắc chắn muốn thoát khỏi gói dành cho gia đình không?", - "inFamilyPlanMessage": "Bạn đang sử dụng gói dành cho gia đình!", - "hintForMobile": "Nhấn giữ trên mã để chỉnh sửa hoặc xóa.", - "hintForDesktop": "Nhấp chuột phải vào mã để chỉnh sửa hoặc xóa.", + "somethingWentWrongMessage": "Có gì đó không ổn, vui lòng thử lại", + "leaveFamily": "Rời khỏi gói gia đình", + "leaveFamilyMessage": "Bạn có chắc muốn rời khỏi gói gia đình không?", + "inFamilyPlanMessage": "Bạn đang dùng gói gia đình!", + "hintForMobile": "Nhấn giữ mã để chỉnh sửa hoặc xóa.", + "hintForDesktop": "Nhấn chuột phải vào mã để chỉnh sửa hoặc xóa.", "scan": "Quét", "scanACode": "Quét mã", "verify": "Xác minh", - "verifyEmail": "Xác nhận địa chỉ Email", - "enterCodeHint": "Nhập mã gồm 6 chữ số từ ứng dụng xác thực của bạn", + "verifyEmail": "Xác minh email", + "enterCodeHint": "Nhập mã 6 chữ số từ\nứng dụng xác thực của bạn", "lostDeviceTitle": "Mất thiết bị?", - "twoFactorAuthTitle": "Xác thực hai yếu tố", - "passkeyAuthTitle": "Xác minh mã khóa", - "verifyPasskey": "Xác minh mã khóa", + "twoFactorAuthTitle": "Xác thực 2 bước", + "passkeyAuthTitle": "Xác minh khóa truy cập", + "verifyPasskey": "Xác minh khóa truy cập", "loginWithTOTP": "Đăng nhập bằng TOTP", "recoverAccount": "Khôi phục tài khoản", - "enterRecoveryKeyHint": "Nhập khóa khôi phục của bạn", + "enterRecoveryKeyHint": "Nhập mã khôi phục của bạn", "recover": "Khôi phục", "contactSupportViaEmailMessage": "Vui lòng gửi email đến {email} từ địa chỉ email đã đăng ký của bạn", "@contactSupportViaEmailMessage": { @@ -171,12 +171,13 @@ } }, "invalidQRCode": "Mã QR không hợp lệ", - "noRecoveryKeyTitle": "Không có khóa khôi phục?", + "noRecoveryKeyTitle": "Không có mã khôi phục?", "enterEmailHint": "Nhập địa chỉ email của bạn", + "enterNewEmailHint": "Nhập địa chỉ email mới của bạn", "invalidEmailTitle": "Địa chỉ email không hợp lệ", - "invalidEmailMessage": "Xin vui lòng nhập một địa chỉ email hợp lệ.", - "deleteAccount": "Xoá tài khoản", - "deleteAccountQuery": "Chúng tôi sẽ rất tiếc khi thấy bạn đi. Bạn đang phải đối mặt với một số vấn đề?", + "invalidEmailMessage": "Vui lòng nhập một địa chỉ email hợp lệ.", + "deleteAccount": "Xóa tài khoản", + "deleteAccountQuery": "Chúng tôi rất tiếc khi thấy bạn ra đi. Có phải bạn gặp vấn đề?", "yesSendFeedbackAction": "Có, gửi phản hồi", "noDeleteAccountAction": "Không, xóa tài khoản", "initiateAccountDeleteTitle": "Vui lòng xác thực để bắt đầu xóa tài khoản", @@ -187,40 +188,40 @@ "moderateStrength": "Trung bình", "confirmPassword": "Xác nhận mật khẩu", "close": "Đóng", - "oopsSomethingWentWrong": "Rất tiếc, Đã xảy ra lỗi.", + "oopsSomethingWentWrong": "Ốii!, có gì đó không ổn.", "selectLanguage": "Chọn ngôn ngữ", "language": "Ngôn ngữ", - "social": "Xã hội", + "social": "Mạng xã hội", "security": "Bảo mật", - "lockscreen": "Màn hình khoá", - "authToChangeLockscreenSetting": "Vui lòng xác thực để thay đổi cài đặt màn hình khóa", + "lockscreen": "Khóa màn hình", + "authToChangeLockscreenSetting": "Vui lòng xác thực để thay đổi cài đặt khóa màn hình", "deviceLockEnablePreSteps": "Để bật khoá thiết bị, vui lòng thiết lập mật khẩu thiết bị hoặc khóa màn hình trong cài đặt hệ thống của bạn.", - "viewActiveSessions": "Xem danh sách phiên làm việc hiện tại", - "authToViewYourActiveSessions": "Vui lòng xác thực để xem danh sách phiên làm việc của bạn", + "viewActiveSessions": "Xem phiên hoạt động", + "authToViewYourActiveSessions": "Vui lòng xác thực để xem các phiên hoạt động", "searchHint": "Tìm kiếm...", "search": "Tìm kiếm", "sorryUnableToGenCode": "Rất tiếc, không thể tạo mã cho {issuerName}", "noResult": "Không có kết quả", "addCode": "Thêm mã", "scanAQrCode": "Quét mã QR", - "enterDetailsManually": "Nhập chi tiết thủ công", + "enterDetailsManually": "Nhập thủ công", "edit": "Sửa", "share": "Chia sẻ", "shareCodes": "Chia sẻ mã", - "shareCodesDuration": "Chọn khoảng thời gian mà bạn muốn chia sẻ mã.", + "shareCodesDuration": "Chọn thời hạn bạn muốn chia sẻ mã.", "restore": "Khôi phục", - "copiedToClipboard": "Đã sao chép vào khay nhớ tạm", - "copiedNextToClipboard": "Đã sao chép mã tiếp theo vào bảng nhớ tạm", + "copiedToClipboard": "Đã sao chép vào bộ nhớ tạm", + "copiedNextToClipboard": "Đã sao chép mã tiếp theo vào bộ nhớ tạm", "error": "Lỗi", - "recoveryKeyCopiedToClipboard": "Đã sao chép khóa khôi phục vào bộ nhớ tạm", - "recoveryKeyOnForgotPassword": "Nếu bạn quên mật khẩu, cách duy nhất bạn có thể khôi phục dữ liệu của mình là sử dụng khóa này.", - "recoveryKeySaveDescription": "Chúng tôi không lưu trữ khóa này, vui lòng lưu khóa 24 từ này ở nơi an toàn.", + "recoveryKeyCopiedToClipboard": "Đã sao chép mã khôi phục vào bộ nhớ tạm", + "recoveryKeyOnForgotPassword": "Nếu bạn quên mật khẩu, cách duy nhất để khôi phục dữ liệu của bạn là dùng mã này.", + "recoveryKeySaveDescription": "Chúng tôi không lưu trữ mã này, nên hãy lưu nó ở nơi an toàn.", "doThisLater": "Để sau", - "saveKey": "Lưu khóa", + "saveKey": "Lưu mã", "save": "Lưu", "send": "Gửi", - "saveOrSendDescription": "Bạn có muốn lưu vào bộ nhớ (Mặc định lưu vào thư mục Tải về) hoặc chuyển qua ứng dụng khác?", - "saveOnlyDescription": "Bạn có muốn lưu vào bộ nhớ không (Mặc định lưu vào thư mục Tải về)?", + "saveOrSendDescription": "Bạn muốn lưu vào bộ nhớ (Mặc định là thư mục Tải xuống) hay gửi qua ứng dụng khác?", + "saveOnlyDescription": "Bạn muốn lưu vào bộ nhớ (Mặc định là thư mục Tải xuống)?", "back": "Quay lại", "createAccount": "Tạo tài khoản", "passwordStrength": "Độ mạnh mật khẩu: {passwordStrengthValue}", @@ -236,76 +237,76 @@ "message": "Password Strength: {passwordStrengthText}" }, "password": "Mật khẩu", - "signUpTerms": "Tôi đồng ý với điều khoản dịch vụchính sách quyền riêng tư", + "signUpTerms": "Tôi đồng ý với điều khoảnchính sách bảo mật", "privacyPolicyTitle": "Chính sách bảo mật", "termsOfServicesTitle": "Điều khoản", "encryption": "Mã hóa", "setPasswordTitle": "Đặt mật khẩu", - "changePasswordTitle": "Thay đổi mật khẩu", + "changePasswordTitle": "Đổi mật khẩu", "resetPasswordTitle": "Đặt lại mật khẩu", "encryptionKeys": "Khóa mã hóa", - "passwordWarning": "Chúng tôi không lưu trữ mật khẩu này, vì vậy nếu bạn quên, chúng tôi không thể giải mã dữ liệu của bạn", - "enterPasswordToEncrypt": "Nhập mật khẩu mà chúng tôi có thể sử dụng để mã hóa dữ liệu của bạn", - "enterNewPasswordToEncrypt": "Nhập một mật khẩu mới mà chúng tôi có thể sử dụng để mã hóa dữ liệu của bạn", - "passwordChangedSuccessfully": "Thay đổi mật khẩu thành công", + "passwordWarning": "Chúng tôi không lưu trữ mật khẩu này, nên nếu bạn quên, chúng tôi không thể giải mã dữ liệu của bạn", + "enterPasswordToEncrypt": "Vui lòng nhập một mật khẩu dùng để mã hóa dữ liệu của bạn", + "enterNewPasswordToEncrypt": "Vui lòng nhập một mật khẩu mới để mã hóa dữ liệu của bạn", + "passwordChangedSuccessfully": "Đã thay đổi mật khẩu thành công", "generatingEncryptionKeys": "Đang tạo khóa mã hóa...", "continueLabel": "Tiếp tục", "insecureDevice": "Thiết bị không an toàn", - "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Rất tiếc, chúng tôi không thể tạo khóa bảo mật trên thiết bị này.\n\nvui lòng đăng ký từ một thiết bị khác.", + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Rất tiếc, chúng tôi không thể tạo khóa an toàn trên thiết bị này.\n\nVui lòng đăng ký từ một thiết bị khác.", "howItWorks": "Cách thức hoạt động", - "ackPasswordLostWarning": "Tôi hiểu rằng việc mất mật khẩu có thể đồng nghĩa với việc mất dữ liệu của tôi vì dữ liệu của tôi được mã hóa hai đầu.", - "loginTerms": "Bằng cách nhấp vào đăng nhập, tôi đồng ý với điều khoản dịch vụchính sách quyền riêng tư", + "ackPasswordLostWarning": "Tôi hiểu rằng nếu mất mật khẩu, dữ liệu của tôi sẽ mất vì nó được mã hóa đầu cuối.", + "loginTerms": "Nhấn vào đăng nhập, tôi đồng ý với điều khoảnchính sách bảo mật", "logInLabel": "Đăng nhập", "logout": "Đăng xuất", - "areYouSureYouWantToLogout": "Bạn có chắc chắn muốn đăng xuất?", + "areYouSureYouWantToLogout": "Bạn có chắc muốn đăng xuất không?", "yesLogout": "Có, đăng xuất", "exit": "Thoát", "theme": "Chủ đề", "lightTheme": "Sáng", "darkTheme": "Tối", - "systemTheme": "Hệ thống", - "verifyingRecoveryKey": "Đang xác minh khóa khôi phục...", - "recoveryKeyVerified": "Khóa khôi phục đã được xác thực", - "recoveryKeySuccessBody": "Tuyệt vời! Khóa khôi phục của bạn hợp lệ. Cảm ơn bạn đã xác minh.\n\nHãy nhớ sao lưu khóa khôi phục của bạn một cách an toàn.", - "invalidRecoveryKey": "Khóa khôi phục bạn đã nhập không hợp lệ. Vui lòng đảm bảo rằng nó chứa 24 từ và kiểm tra chính tả của từng từ.\n\nNếu bạn đã nhập mã khôi phục cũ hơn, hãy đảm bảo mã đó dài 64 ký tự và kiểm tra từng ký tự.", + "systemTheme": "Giống hệ thống", + "verifyingRecoveryKey": "Đang xác minh mã khôi phục...", + "recoveryKeyVerified": "Mã khôi phục đã được xác minh", + "recoveryKeySuccessBody": "Tuyệt! Mã khôi phục của bạn hợp lệ. Cảm ơn đã xác minh.\n\nNhớ lưu giữ mã khôi phục của bạn ở nơi an toàn.", + "invalidRecoveryKey": "Mã khôi phục không hợp lệ. Vui lòng đảm bảo nó chứa 24 từ, và đúng chính tả từng từ.\n\nNếu bạn nhập loại mã khôi phục cũ, hãy đảm bảo nó dài 64 ký tự, và kiểm tra từng ký tự.", "recreatePasswordTitle": "Tạo lại mật khẩu", - "recreatePasswordBody": "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn nhưng chúng tôi có thể tạo lại mật khẩu theo cách hoạt động với tất cả các thiết bị.\n\nVui lòng đăng nhập bằng khóa khôi phục và tạo lại mật khẩu của bạn (bạn có thể sử dụng lại cùng một mật khẩu nếu muốn).", - "invalidKey": "Khoá không hợp lệ", + "recreatePasswordBody": "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn, nhưng chúng tôi có thể tạo lại để nó hoạt động với tất cả thiết bị.\n\nVui lòng đăng nhập bằng mã khôi phục và tạo lại mật khẩu (bạn có thể dùng lại mật khẩu cũ nếu muốn).", + "invalidKey": "Mã không hợp lệ", "tryAgain": "Thử lại", - "viewRecoveryKey": "Hiển thị khóa khôi phục", - "confirmRecoveryKey": "Xác nhận khóa khôi phục", - "recoveryKeyVerifyReason": "Nếu bạn quên mật khẩu, khóa khôi phục là cách duy nhất để khôi phục ảnh của bạn. Bạn có thể tìm thấy khóa khôi phục của mình trong Cài đặt > Tài khoản.\n\nVui lòng nhập khóa khôi phục của bạn tại đây để xác minh rằng bạn đã lưu chính xác.", - "confirmYourRecoveryKey": "Xác nhận khóa khôi phục", + "viewRecoveryKey": "Xem mã khôi phục", + "confirmRecoveryKey": "Xác nhận mã khôi phục", + "recoveryKeyVerifyReason": "Mã khôi phục là cách duy nhất để khôi phục ảnh của bạn nếu bạn quên mật khẩu. Bạn có thể xem mã khôi phục của mình trong Cài đặt > Tài khoản.\n\nVui lòng nhập mã khôi phục của bạn ở đây để xác minh rằng bạn đã lưu nó đúng cách.", + "confirmYourRecoveryKey": "Xác nhận mã khôi phục của bạn", "confirm": "Xác nhận", - "emailYourLogs": "Gửi email nhật ký của bạn", + "emailYourLogs": "Gửi nhật ký qua email", "pleaseSendTheLogsTo": "Vui lòng gửi nhật ký đến \n{toEmail}", "copyEmailAddress": "Sao chép địa chỉ email", "exportLogs": "Xuất nhật ký", - "enterYourRecoveryKey": "Nhập khóa khôi phục của bạn", - "tempErrorContactSupportIfPersists": "Có vẻ như đã xảy ra sự cố. Vui lòng thử lại sau một thời gian. Nếu lỗi vẫn tiếp diễn, vui lòng liên hệ với nhóm hỗ trợ của chúng tôi.", - "networkHostLookUpErr": "Không thể kết nối đến Ente, vui lòng kiểm tra lại kết nối mạng. Nếu vẫn còn lỗi, xin vui lòng liên hệ hỗ trợ.", - "networkConnectionRefusedErr": "Không thể kết nối đến Ente, vui lòng thử lại sau. Nếu vẫn còn lỗi, xin vui lòng liên hệ hỗ trợ.", - "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Có vẻ như đã xảy ra sự cố. Vui lòng thử lại sau một thời gian. Nếu lỗi vẫn tiếp diễn, vui lòng liên hệ với nhóm hỗ trợ của chúng tôi.", - "about": "Về chúng tôi", - "weAreOpenSource": "Chúng tôi có mã nguồn mở!", + "enterYourRecoveryKey": "Nhập mã khôi phục của bạn", + "tempErrorContactSupportIfPersists": "Có vẻ đã xảy ra sự cố. Vui lòng thử lại sau ít phút. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với đội ngũ hỗ trợ của chúng tôi.", + "networkHostLookUpErr": "Không thể kết nối với Ente, vui lòng kiểm tra cài đặt mạng của bạn và liên hệ với bộ phận hỗ trợ nếu lỗi vẫn tiếp diễn.", + "networkConnectionRefusedErr": "Không thể kết nối với Ente, vui lòng thử lại sau ít phút. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với bộ phận hỗ trợ.", + "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Có vẻ đã xảy ra sự cố. Vui lòng thử lại sau ít phút. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với đội ngũ hỗ trợ của chúng tôi.", + "about": "Giới thiệu", + "weAreOpenSource": "Chúng tôi là mã nguồn mở!", "privacy": "Riêng tư", "terms": "Điều khoản", "checkForUpdates": "Kiểm tra cập nhật", "checkStatus": "Kiểm tra trạng thái", "downloadUpdate": "Tải xuống", - "criticalUpdateAvailable": "Đã có bản cập nhật quan trọng", - "updateAvailable": "Đã có bản cập nhật", + "criticalUpdateAvailable": "Cập nhật quan trọng có sẵn", + "updateAvailable": "Cập nhật có sẵn", "update": "Cập nhật", "checking": "Đang kiểm tra...", "youAreOnTheLatestVersion": "Bạn đang sử dụng phiên bản mới nhất", - "warning": "Cánh báo", - "exportWarningDesc": "Tệp đã xuất chứa thông tin nhạy cảm. Hãy lưu trữ tệp này một cách an toàn.", + "warning": "Cảnh báo", + "exportWarningDesc": "Tệp xuất chứa thông tin nhạy cảm. Hãy lưu trữ tệp này một cách an toàn.", "iUnderStand": "Tôi hiểu", "@iUnderStand": { "description": "Text for the button to confirm the user understands the warning" }, - "authToExportCodes": "Vui lòng xác thực để xuất mã của bạn", - "importSuccessTitle": "Hoan hô!", + "authToExportCodes": "Vui lòng xác thực để xuất mã", + "importSuccessTitle": "Tuyệt!", "importSuccessDesc": "Bạn đã nhập {count} mã!", "@importSuccessDesc": { "placeholders": { @@ -316,14 +317,14 @@ } } }, - "sorry": "Xin lỗi", - "importFailureDesc": "Không thể phân tích cú pháp tệp đã chọn.\nVui lòng viết thư cho support@ente.io nếu bạn cần trợ giúp!", - "pendingSyncs": "Cánh báo", + "sorry": "Rất tiếc", + "importFailureDesc": "Không thể phân tích tệp đã chọn.\nVui lòng liên hệ support@ente.io nếu bạn cần trợ giúp!", + "pendingSyncs": "Cảnh báo", "pendingSyncsWarningBody": "Một số mã của bạn chưa được sao lưu.\n\nVui lòng đảm bảo rằng bạn có bản sao lưu cho các mã này trước khi đăng xuất.", - "checkInboxAndSpamFolder": "Vui lòng kiểm tra hộp thư đến (và thư rác) của bạn để hoàn tất xác minh", - "tapToEnterCode": "Chạm để nhập mã", + "checkInboxAndSpamFolder": "Vui lòng kiểm tra hộp thư đến (và thư rác) để hoàn tất xác minh", + "tapToEnterCode": "Nhấn để nhập mã", "resendEmail": "Gửi lại email", - "weHaveSendEmailTo": "Chúng tôi đã gửi thư đến {email}", + "weHaveSendEmailTo": "Chúng tôi đã gửi một email đến {email}", "@weHaveSendEmailTo": { "description": "Text to indicate that we have sent a mail to the user", "placeholders": { @@ -335,57 +336,57 @@ } }, "manualSort": "Tùy chỉnh", - "editOrder": "Chỉnh sửa đơn hàng", + "editOrder": "Chỉnh sửa thứ tự", "mostFrequentlyUsed": "Thường dùng", "mostRecentlyUsed": "Dùng gần đây", - "activeSessions": "Các phiên làm việc hiện tại", - "somethingWentWrongPleaseTryAgain": "Phát hiện có lỗi, xin thử lại", - "thisWillLogYouOutOfThisDevice": "Thao tác này sẽ đăng xuất bạn khỏi thiết bị này!", - "thisWillLogYouOutOfTheFollowingDevice": "Thao tác này sẽ đăng xuất bạn khỏi thiết bị sau:", + "activeSessions": "Phiên hoạt động", + "somethingWentWrongPleaseTryAgain": "Có gì đó không ổn, vui lòng thử lại", + "thisWillLogYouOutOfThisDevice": "Bạn sẽ đăng xuất khỏi thiết bị này!", + "thisWillLogYouOutOfTheFollowingDevice": "Bạn cũng sẽ đăng xuất khỏi những thiết bị sau:", "terminateSession": "Kết thúc phiên?", "terminate": "Kết thúc", "thisDevice": "Thiết bị này", "toResetVerifyEmail": "Để đặt lại mật khẩu, vui lòng xác minh email của bạn trước.", "thisEmailIsAlreadyInUse": "Email này đã được sử dụng", - "verificationFailedPleaseTryAgain": "Mã xác nhận thất bại. Vui lòng thử lại", + "verificationFailedPleaseTryAgain": "Xác minh không thành công, vui lòng thử lại", "yourVerificationCodeHasExpired": "Mã xác minh của bạn đã hết hạn", "incorrectCode": "Mã không chính xác", - "sorryTheCodeYouveEnteredIsIncorrect": "Xin lỗi, mã bạn đã nhập không chính xác", - "emailChangedTo": "Thay đổi email thành {newEmail}", - "authenticationFailedPleaseTryAgain": "Xác thực lỗi, vui lòng thử lại", + "sorryTheCodeYouveEnteredIsIncorrect": "Rất tiếc, mã bạn nhập không chính xác", + "emailChangedTo": "Email đã được đổi thành {newEmail}", + "authenticationFailedPleaseTryAgain": "Xác thực không thành công, vui lòng thử lại", "authenticationSuccessful": "Xác thực thành công!", - "twofactorAuthenticationSuccessfullyReset": "Xác thực hai bước được khôi phục thành công", - "incorrectRecoveryKey": "Khóa khôi phục không chính xác", - "theRecoveryKeyYouEnteredIsIncorrect": "Khóa khôi phục bạn đã nhập không chính xác", + "twofactorAuthenticationSuccessfullyReset": "Xác thực 2 bước đã được đặt lại thành công", + "incorrectRecoveryKey": "Mã khôi phục không chính xác", + "theRecoveryKeyYouEnteredIsIncorrect": "Mã khôi phục bạn nhập không chính xác", "enterPassword": "Nhập mật khẩu", "selectExportFormat": "Chọn định dạng dữ liệu xuất", - "exportDialogDesc": "Xuất dữ liệu được mã hóa sẽ được bảo vệ bằng mật khẩu bạn chọn.", - "encrypted": "Đã mã hóa", + "exportDialogDesc": "Dữ liệu xuất được mã hóa sẽ được bảo vệ bằng mật khẩu bạn chọn.", + "encrypted": "Được mã hóa", "plainText": "Văn bản thuần", "passwordToEncryptExport": "Mật khẩu để giải mã dữ liệu xuất", - "export": "Xuất dữ liệu", + "export": "Xuất", "useOffline": "Sử dụng mà không sao lưu", "signInToBackup": "Đăng nhập để sao lưu mã của bạn", "singIn": "Đăng nhập", "sigInBackupReminder": "Vui lòng xuất mã của bạn để đảm bảo rằng bạn có bản sao lưu có thể khôi phục.", - "offlineModeWarning": "Bạn đã chọn tiếp tục mà không cần sao lưu. Vui lòng sao lưu thủ công để đảm bảo mã của bạn được an toàn.", - "showLargeIcons": "Hiển thị biểu tượng lớn", + "offlineModeWarning": "Bạn đã chọn tiếp tục mà không sao lưu. Vui lòng sao lưu thủ công để đảm bảo mã của bạn được an toàn.", + "showLargeIcons": "Hiện biểu tượng lớn", "compactMode": "Chế độ thu gọn", "shouldHideCode": "Ẩn mã", "doubleTapToViewHiddenCode": "Bạn có thể nhấn đúp vào một mục để xem mã", "focusOnSearchBar": "Mở tìm kiếm khi khởi động ứng dụng", - "confirmUpdatingkey": "Bạn có chắc chắn muốn cập nhật khóa bí mật không?", + "confirmUpdatingkey": "Bạn có chắc muốn cập nhật khóa bí mật không?", "minimizeAppOnCopy": "Thu nhỏ khi sao chép", - "editCodeAuthMessage": "Xác minh để chỉnh sửa mã", - "deleteCodeAuthMessage": "Xác minh để xóa mã", - "showQRAuthMessage": "Xác minh để hiển thị mã QR", + "editCodeAuthMessage": "Xác thực để sửa mã", + "deleteCodeAuthMessage": "Xác thực để xóa mã", + "showQRAuthMessage": "Xác thực để hiện mã QR", "confirmAccountDeleteTitle": "Xác nhận xóa tài khoản", - "confirmAccountDeleteMessage": "Tài khoản này được liên kết với các ứng dụng Ente trên các nền tảng khác, nếu bạn có sử dụng.\n\nDữ liệu đã tải lên của bạn, trên mọi nền tảng, sẽ bị lên lịch xóa và tài khoản của bạn sẽ bị xóa vĩnh viễn.", - "androidBiometricHint": "Xác định danh tính", + "confirmAccountDeleteMessage": "Tài khoản này được liên kết với các ứng dụng Ente khác, nếu bạn có dùng.\n\nDữ liệu bạn đã tải lên, trên tất cả ứng dụng Ente, sẽ được lên lịch để xóa, và tài khoản của bạn sẽ bị xóa vĩnh viễn.", + "androidBiometricHint": "Xác minh danh tính", "@androidBiometricHint": { "description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters." }, - "androidBiometricNotRecognized": "Không nhận dạng được. Vui lòng thử lại.", + "androidBiometricNotRecognized": "Không nhận diện được. Thử lại.", "@androidBiometricNotRecognized": { "description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters." }, @@ -413,19 +414,19 @@ "@androidDeviceCredentialsSetupDescription": { "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." }, - "goToSettings": "Chuyển đến cài đặt", + "goToSettings": "Đi đến cài đặt", "@goToSettings": { "description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters." }, - "androidGoToSettingsDescription": "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Đi tới 'Cài đặt > Bảo mật' để thêm xác thực sinh trắc học.", + "androidGoToSettingsDescription": "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Đi đến 'Cài đặt > Bảo mật' để thêm xác thực sinh trắc học.", "@androidGoToSettingsDescription": { "description": "Message advising the user to go to the settings and configure biometric on their device. It shows in a dialog on Android side." }, - "iOSLockOut": "Xác thực sinh trắc học bị vô hiệu hóa. Vui lòng khóa và mở khóa màn hình của bạn để kích hoạt nó.", + "iOSLockOut": "Xác thực sinh trắc học đã bị vô hiệu hóa. Vui lòng khóa và mở khóa màn hình của bạn để kích hoạt lại.", "@iOSLockOut": { "description": "Message advising the user to re-enable biometrics on their device. It shows in a dialog on iOS side." }, - "iOSGoToSettingsDescription": "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Vui lòng bật Touch ID hoặc Face ID trên điện thoại của bạn.", + "iOSGoToSettingsDescription": "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Vui lòng kích hoạt Touch ID hoặc Face ID.", "@iOSGoToSettingsDescription": { "description": "Message advising the user to go to the settings and configure Biometrics for their device. It shows in a dialog on iOS side." }, @@ -436,25 +437,25 @@ "noInternetConnection": "Không có kết nối Internet", "pleaseCheckYourInternetConnectionAndTryAgain": "Vui lòng kiểm tra kết nối internet của bạn và thử lại.", "signOutFromOtherDevices": "Đăng xuất khỏi các thiết bị khác", - "signOutOtherBody": "Nếu bạn cho rằng ai đó có thể biết mật khẩu của mình, bạn có thể buộc đăng xuất tất cả các thiết bị khác đang sử dụng tài khoản của mình.", + "signOutOtherBody": "Nếu bạn nghĩ rằng ai đó biết mật khẩu của bạn, hãy ép tài khoản của bạn đăng xuất khỏi tất cả thiết bị khác đang sử dụng.", "signOutOtherDevices": "Đăng xuất khỏi các thiết bị khác", - "doNotSignOut": "Không được đăng xuất", - "hearUsWhereTitle": "Bạn biết đến Ente bằng cách nào? (không bắt buộc)", - "hearUsExplanation": "Chúng tôi không theo dõi lượt cài đặt ứng dụng. Sẽ rất hữu ích nếu bạn cho chúng tôi biết nơi bạn tìm thấy chúng tôi!", - "recoveryKeySaved": "Đã lưu khoá dự phòng vào thư mục Tải về!", + "doNotSignOut": "Không đăng xuất", + "hearUsWhereTitle": "Bạn biết Ente từ đâu? (tùy chọn)", + "hearUsExplanation": "Chúng tôi không theo dõi cài đặt ứng dụng, nên nếu bạn bật mí bạn tìm thấy chúng tôi từ đâu sẽ rất hữu ích!", + "recoveryKeySaved": "Đã lưu mã khôi phục vào thư mục Tải xuống!", "waitingForBrowserRequest": "Đang chờ yêu cầu từ trình duyệt...", - "waitingForVerification": "Đang chờ xác thực", - "passkey": "Mã khoá", - "passKeyPendingVerification": "Đang chờ xác thực", - "loginSessionExpired": "Phiên làm việc hết hạn", - "loginSessionExpiredDetails": "Phiên làm việc hết hạn. Vui lòng đăng nhập lại.", - "developerSettingsWarning": "Bạn có chắc chắn muốn thay đổi Tuỳ chọn cho nhà phát triển không?", - "developerSettings": "Cài đặt cho nhà phát triển", + "waitingForVerification": "Đang chờ xác minh...", + "passkey": "Khóa truy cập", + "passKeyPendingVerification": "Xác minh vẫn đang chờ", + "loginSessionExpired": "Phiên đăng nhập đã hết hạn", + "loginSessionExpiredDetails": "Phiên đăng nhập của bạn đã hết hạn. Vui lòng đăng nhập lại.", + "developerSettingsWarning": "Bạn có chắc muốn thay đổi cài đặt Nhà phát triển không?", + "developerSettings": "Cài đặt Nhà phát triển", "serverEndpoint": "Điểm cuối máy chủ", "invalidEndpoint": "Điểm cuối không hợp lệ", "invalidEndpointMessage": "Xin lỗi, điểm cuối bạn nhập không hợp lệ. Vui lòng nhập một điểm cuối hợp lệ và thử lại.", - "endpointUpdatedMessage": "Cập nhật điểm cuối thành công", - "customEndpoint": "Đã kết nối đến", + "endpointUpdatedMessage": "Điểm cuối đã được cập nhật thành công", + "customEndpoint": "Đã kết nối với {endpoint}", "pinText": "Ghim", "unpinText": "Bỏ ghim", "pinnedCodeMessage": "{code} đã được ghim", @@ -466,37 +467,37 @@ "create": "Tạo", "editTag": "Sửa thẻ", "deleteTagTitle": "Xóa thẻ?", - "deleteTagMessage": "Bạn có chắc chắn muốn xóa thẻ này không? Hành động này không thể đảo ngược.", + "deleteTagMessage": "Bạn có chắc muốn xóa thẻ này không? Hành động này không thể hoàn tác.", "somethingWentWrongParsingCode": "Chúng tôi không thể phân tích {x} mã.", "updateNotAvailable": "Cập nhật không khả dụng", - "viewRawCodes": "Xem mã nguồn", - "rawCodes": "Mã nguồn", - "rawCodeData": "Dữ liệu thô", + "viewRawCodes": "Xem mã thô", + "rawCodes": "Mã thô", + "rawCodeData": "Dữ liệu mã thô", "appLock": "Khóa ứng dụng", - "noSystemLockFound": "Không thấy khoá hệ thống", - "toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Để bật khoá ứng dụng, vui lòng thiết lập mật khẩu thiết bị hoặc khóa màn hình trong cài đặt hệ thống của bạn.", + "noSystemLockFound": "Không tìm thấy khóa hệ thống", + "toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Để bật khóa ứng dụng, vui lòng thiết lập mã khóa thiết bị hoặc khóa màn hình trong cài đặt hệ thống của bạn.", "autoLock": "Tự động khóa", - "immediately": "Tức thì", + "immediately": "Lập tức", "reEnterPassword": "Nhập lại mật khẩu", - "reEnterPin": "Nhập lại mã PIN", - "next": "Tiếp theo", - "tooManyIncorrectAttempts": "Quá nhiều lần thử không chính xác", + "reEnterPin": "Nhập lại PIN", + "next": "Kế tiếp", + "tooManyIncorrectAttempts": "Thử sai nhiều lần", "tapToUnlock": "Nhấn để mở khóa", - "setNewPassword": "Đặt lại mật khẩu", + "setNewPassword": "Đặt mật khẩu mới", "deviceLock": "Khóa thiết bị", "hideContent": "Ẩn nội dung", "hideContentDescriptionAndroid": "Ẩn nội dung khi chuyển ứng dụng và chặn chụp màn hình", - "hideContentDescriptioniOS": "Ẩn nội dung khi chuyển ứng dụng", - "autoLockFeatureDescription": "Thời gian ứng dụng tự khoá sau khi ở trạng thái nền", - "appLockDescription": "Chọn giữa màn hình khoá mặc định của thiết bị và màn hình khoá tự chọn dùng mã PIN hoặc mật khẩu.", - "pinLock": "Mã PIN", - "enterPin": "Nhập mã PIN", - "setNewPin": "Đổi mã PIN", - "importFailureDescNew": "Không thể phân tích file đã chọn.", + "hideContentDescriptioniOS": "Ẩn nội dung ứng dụng trong trình chuyển đổi ứng dụng", + "autoLockFeatureDescription": "Sau thời gian này, ứng dụng sẽ khóa sau khi được chạy ở chế độ nền", + "appLockDescription": "Chọn giữa màn hình khóa mặc định của thiết bị và màn hình khóa tùy chỉnh với PIN hoặc mật khẩu.", + "pinLock": "Khóa PIN", + "enterPin": "Nhập PIN", + "setNewPin": "Đặt PIN mới", + "importFailureDescNew": "Không thể phân tích tệp đã chọn.", "appLockNotEnabled": "Khóa ứng dụng chưa được bật", "appLockNotEnabledDescription": "Vui lòng bật khóa ứng dụng từ Bảo mật > Khóa ứng dụng", - "authToViewPasskey": "Vui lòng xác thực để xem mã khóa", - "appLockOfflineModeWarning": "Bạn đã chọn tiếp tục mà không có bản sao lưu. Nếu bạn quên khóa ứng dụng, bạn sẽ bị khóa khỏi việc truy cập dữ liệu của mình.", + "authToViewPasskey": "Vui lòng xác thực để xem mã truy cập", + "appLockOfflineModeWarning": "Bạn đã chọn tiếp tục mà không sao lưu. Nếu bạn quên khóa ứng dụng, bạn sẽ không thể truy cập dữ liệu của mình.", "duplicateCodes": "Mã trùng lặp", "noDuplicates": "✨ Không có trùng lặp", "youveNoDuplicateCodesThatCanBeCleared": "Bạn không có mã nào bị trùng để xóa", @@ -509,9 +510,14 @@ "dropReviewiOS": "Đánh giá ngay trên App Store", "dropReviewAndroid": "Đánh giá ngay trên Play Store", "supportEnte": "Hỗ trợ ente", - "giveUsAStarOnGithub": "Cho chúng tôi ngôi sao trên Github", - "free5GB": "Miễn phí 5GB cho ente Hình ảnh", + "giveUsAStarOnGithub": "Tặng sao trên GitHub", + "free5GB": "Miễn phí 5GB cho ente Photos", "loginWithAuthAccount": "Đăng nhập bằng tài khoản Ente Auth", - "freeStorageOffer": "Giảm giá 10% cho ente Hình ảnh", - "freeStorageOfferDescription": "Sử dụng mã giảm giá \"AUTH\" để được giảm 10% trong năm đầu tiên" + "freeStorageOffer": "Giảm giá 10% cho ente Photos", + "freeStorageOfferDescription": "Dùng mã \"AUTH\" để được giảm 10% trong năm đầu tiên", + "advanced": "Nâng cao", + "algorithm": "Thuật toán", + "type": "Loại", + "period": "Thời hạn", + "digits": "Chữ số" } \ No newline at end of file From 3b7d13aec0ea7d21abf0637a4dcbae110037650e Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 14 Jul 2025 11:31:18 +0530 Subject: [PATCH 10/81] [server] Handle expiry buffer in user_detail computation --- server/pkg/controller/user/user_details.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server/pkg/controller/user/user_details.go b/server/pkg/controller/user/user_details.go index 6874910bf6..d9224d14fd 100644 --- a/server/pkg/controller/user/user_details.go +++ b/server/pkg/controller/user/user_details.go @@ -5,6 +5,7 @@ import ( "github.com/ente-io/museum/ente" "github.com/ente-io/museum/ente/details" bonus "github.com/ente-io/museum/ente/storagebonus" + "github.com/ente-io/museum/pkg/utils/billing" "github.com/ente-io/museum/pkg/utils/recover" "github.com/ente-io/museum/pkg/utils/time" "github.com/ente-io/stacktrace" @@ -100,11 +101,15 @@ func (c *UserController) GetDetailsV2(ctx *gin.Context, userID int64, fetchMemor return details.UserDetailsResponse{}, stacktrace.Propagate(err, "") } var planStoreForBonusComputation = subscription.Storage - if subscription.ExpiryTime < time.Microseconds() { + expiryBuffer := int64(0) + if value, ok := billing.ProviderToExpiryGracePeriodMap[subscription.PaymentProvider]; ok { + expiryBuffer = value + } + if (subscription.ExpiryTime + expiryBuffer) < time.Microseconds() { planStoreForBonusComputation = 0 } if familyData != nil { - if familyData.ExpiryTime < time.Microseconds() { + if (familyData.ExpiryTime + expiryBuffer) < time.Microseconds() { familyData.Storage = 0 } else { planStoreForBonusComputation = familyData.Storage From 8a4b038e86c2d47e85d501a29206fcd5a72cdb75 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 14 Jul 2025 09:22:37 +0000 Subject: [PATCH 11/81] New Crowdin translations by GitHub Action --- .../base/locales/de-DE/translation.json | 4 +- .../base/locales/ms-BN/translation.json | 689 ++++++++++++++++++ .../base/locales/ms-MY/translation.json | 689 ++++++++++++++++++ .../base/locales/pl-PL/translation.json | 40 +- .../base/locales/vi-VN/translation.json | 92 +-- .../base/locales/zh-HK/translation.json | 154 ++-- 6 files changed, 1523 insertions(+), 145 deletions(-) create mode 100644 web/packages/base/locales/ms-BN/translation.json create mode 100644 web/packages/base/locales/ms-MY/translation.json diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index c696095562..d38ba3147f 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -162,7 +162,7 @@ "ok": "OK", "success": "Erfolgreich", "error": "Fehler", - "note": "", + "note": "Notiz", "offline_message": "Du bist offline, gecachte Erinnerungen werden angezeigt", "install": "Installieren", "install_mobile_app": "Installiere unsere Android oder iOS App, um automatisch alle deine Fotos zu sichern", @@ -685,5 +685,5 @@ "person_favorites": "{{name}}s Favoriten", "shared_favorites": "Geteilte Favoriten", "added_by_name": "Von {{name}} hinzugefügt", - "unowned_files_not_processed": "" + "unowned_files_not_processed": "Von anderen Benutzern hinzugefügte Dateien wurden nicht verarbeitet" } diff --git a/web/packages/base/locales/ms-BN/translation.json b/web/packages/base/locales/ms-BN/translation.json new file mode 100644 index 0000000000..23a6018ed0 --- /dev/null +++ b/web/packages/base/locales/ms-BN/translation.json @@ -0,0 +1,689 @@ +{ + "intro_slide_1_title": "", + "intro_slide_1": "", + "intro_slide_2_title": "", + "intro_slide_2": "", + "intro_slide_3_title": "", + "intro_slide_3": "", + "login": "", + "sign_up": "", + "new_to_ente": "", + "existing_user": "", + "enter_email": "", + "invalid_email_error": "", + "required": "", + "email_not_registered": "", + "email_already_registered": "", + "email_sent": "", + "check_inbox_hint": "", + "verification_code": "", + "resend_code": "", + "verify": "", + "send_otp": "", + "generic_error": "", + "generic_error_retry": "", + "invalid_code_error": "", + "expired_code_error": "", + "status_sending": "", + "status_sent": "", + "password": "", + "link_password_description": "", + "unlock": "", + "set_password": "", + "sign_in": "", + "incorrect_password": "", + "incorrect_password_or_no_account": "", + "pick_password_hint": "", + "pick_password_caution": "", + "key_generation_in_progress": "", + "confirm_password": "", + "referral_source_hint": "", + "referral_source_info": "", + "password_mismatch_error": "", + "show_or_hide_password": "", + "welcome_to_ente_title": "", + "welcome_to_ente_subtitle": "", + "new_album": "", + "create_albums": "", + "album_name": "", + "close": "", + "yes": "", + "no": "", + "nothing_here": "", + "upload": "", + "import": "", + "add_photos": "", + "add_more_photos": "", + "add_photos_count_one": "", + "add_photos_count": "", + "select_photos": "", + "file_upload": "", + "preparing": "", + "processed_counts": "", + "upload_reading_metadata_files": "", + "upload_cancelling": "", + "upload_done": "", + "upload_skipped": "", + "initial_load_delay_warning": "", + "no_account": "", + "existing_account": "", + "create": "", + "files_count": "", + "download": "", + "download_album": "", + "download_favorites": "", + "download_uncategorized": "", + "download_hidden_items": "", + "audio": "", + "more": "", + "mouse_scroll": "", + "pan": "", + "pinch": "", + "drag": "", + "tap_inside_image": "", + "tap_outside_image": "", + "shortcuts": "", + "show_shortcuts": "", + "zoom_preset": "", + "toggle_controls": "", + "toggle_live": "", + "toggle_audio": "", + "toggle_favorite": "", + "toggle_archive": "", + "view_info": "", + "copy_as_png": "", + "toggle_fullscreen": "", + "exit_fullscreen": "", + "go_fullscreen": "", + "zoom": "", + "play": "", + "pause": "", + "previous": "", + "next": "", + "video_seek": "", + "quality": "", + "auto": "", + "original": "", + "speed": "", + "title_photos": "", + "title_auth": "", + "title_accounts": "", + "upload_first_photo": "", + "import_your_folders": "", + "upload_dropzone_hint": "", + "watch_folder_dropzone_hint": "", + "trash_files_title": "", + "trash_file_title": "", + "delete_files_title": "", + "delete_files_message": "", + "selected_count": "", + "selected_and_yours_count": "", + "delete": "", + "favorite": "", + "convert": "", + "multi_folder_upload": "", + "upload_to_choice": "", + "upload_to_single_album": "", + "upload_to_album_per_folder": "", + "session_expired": "", + "session_expired_message": "", + "password_generation_failed": "", + "change_password": "", + "password_changed_elsewhere": "", + "password_changed_elsewhere_message": "", + "go_back": "", + "account": "", + "recovery_key": "", + "do_this_later": "", + "save_key": "", + "recovery_key_description": "", + "key_not_stored_note": "", + "recovery_key_generation_failed": "", + "forgot_password": "", + "recover_account": "", + "recover": "", + "no_recovery_key_title": "", + "incorrect_recovery_key": "", + "sorry": "", + "no_recovery_key_message": "", + "no_two_factor_recovery_key_message": "", + "contact_support": "", + "help": "", + "ente_help": "", + "blog": "", + "request_feature": "", + "support": "", + "cancel": "", + "logout": "", + "logout_message": "", + "delete_account": "", + "delete_account_manually_message": "", + "change_email": "", + "ok": "", + "success": "", + "error": "", + "note": "", + "offline_message": "", + "install": "", + "install_mobile_app": "", + "download_app": "", + "download_app_message": "", + "subscription": "", + "manage_payment_method": "", + "manage_family": "", + "family_plan": "", + "leave_family_plan": "", + "leave": "", + "leave_family_plan_confirm": "", + "choose_plan": "", + "manage_plan": "", + "current_usage": "", + "two_months_free": "", + "free_plan_option": "", + "free_plan_description": "", + "active": "", + "subscription_info_free": "", + "subscription_info_family": "", + "subscription_info_expired": "", + "subscription_info_renewal_cancelled": "", + "subscription_info_storage_quota_exceeded": "", + "subscription_status_renewal_active": "", + "subscription_status_renewal_cancelled": "", + "add_on_valid_till": "", + "subscription_expired": "", + "storage_quota_exceeded": "", + "subscription_purchase_success": "", + "subscription_purchase_cancelled": "", + "subscription_purchase_failed": "", + "subscription_verification_error": "", + "update_payment_method_message": "", + "payment_method_authentication_failed": "", + "update_payment_method": "", + "monthly": "", + "yearly": "", + "month_short": "", + "year": "", + "update_subscription": "", + "update_subscription_title": "", + "update_subscription_message": "", + "cancel_subscription": "", + "cancel_subscription_message": "", + "cancel_subscription_with_addon_message": "", + "subscription_cancel_success": "", + "reactivate_subscription": "", + "reactivate_subscription_message": "", + "subscription_activate_success": "", + "thank_you": "", + "cancel_subscription_on_mobile": "", + "cancel_subscription_on_mobile_message": "", + "mail_to_manage_subscription": "", + "rename": "", + "rename_file": "", + "rename_album": "", + "delete_album": "", + "delete_album_title": "", + "delete_album_message": "", + "delete_photos": "", + "keep_photos": "", + "share_album": "", + "sharing_with_self": "", + "sharing_already_shared": "", + "sharing_album_not_allowed": "", + "sharing_disabled_for_free_accounts": "", + "sharing_user_does_not_exist": "", + "search": "", + "search_results": "", + "no_results": "", + "search_hint": "", + "album": "", + "date": "", + "description": "", + "file_type": "", + "magic": "", + "photos_count_zero": "", + "photos_count_one": "", + "photos_count": "", + "terms_and_conditions": "", + "people": "", + "indexing_scheduled": "", + "indexing_photos": "", + "indexing_fetching": "", + "indexing_people": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", + "info": "", + "file_name": "", + "caption_placeholder": "", + "location": "", + "view_on_map": "", + "map": "", + "enable_map": "", + "enable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", + "details": "", + "view_exif": "", + "no_exif": "", + "exif": "", + "two_factor": "", + "two_factor_authentication": "", + "two_factor_qr_help": "", + "two_factor_manual_entry_title": "", + "two_factor_manual_entry_message": "", + "scan_qr_title": "", + "enable_two_factor": "", + "enable": "", + "enabled": "", + "lost_2fa_device": "", + "incorrect_code": "", + "two_factor_info": "", + "disable": "", + "reconfigure": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", + "export_data": "", + "select_folder": "", + "select_zips": "", + "faq": "", + "takeout_hint": "", + "destination": "", + "start": "", + "last_export_time": "", + "export_again": "", + "local_storage_not_accessible": "", + "email_already_taken": "", + "live_photos_detected": "", + "ignored_uploads": "", + "ignored_uploads_hint": "", + "file_not_uploaded_list": "", + "failed_uploads": "", + "failed_uploads_hint": "", + "retry_failed_uploads": "", + "thumbnail_generation_failed": "", + "thumbnail_generation_failed_hint": "", + "unsupported_files": "", + "unsupported_files_hint": "", + "blocked_uploads": "", + "blocked_uploads_hint": "", + "large_files": "", + "large_files_hint": "", + "insufficient_storage": "", + "insufficient_storage_hint": "", + "uploads_in_progress": "", + "successful_uploads": "", + "upload_to_album": "", + "add_to_album": "", + "move_to_album": "", + "unhide_to_album": "", + "restore_to_album": "", + "section_all": "", + "section_uncategorized": "", + "section_archive": "", + "section_hidden": "", + "section_trash": "", + "favorites": "", + "archive": "", + "archive_album": "", + "unarchive": "", + "unarchive_album": "", + "hide_collection": "", + "unhide_collection": "", + "move": "", + "add": "", + "remove": "", + "yes_remove": "", + "remove_from_album": "", + "move_to_trash": "", + "trash_files_message": "", + "trash_file_message": "", + "delete_permanently": "", + "restore": "", + "empty_trash": "", + "empty_trash_title": "", + "empty_trash_message": "", + "leave_album": "", + "leave_shared_album_title": "", + "leave_shared_album_message": "", + "leave_shared_album": "", + "confirm_remove_message": "", + "confirm_remove_incl_others_message": "", + "oldest": "", + "last_updated": "", + "name": "", + "fix_creation_time": "", + "fix_creation_time_in_progress": "", + "fix_creation_time_file_updated": "", + "fix_creation_time_completed": "", + "fix_creation_time_completed_with_errors": "", + "fix_creation_time_options": "", + "exif_date_time_original": "", + "exif_date_time_digitized": "", + "exif_metadata_date": "", + "custom_time": "", + "caption_character_limit": "", + "sharing_details": "", + "modify_sharing": "", + "add_collaborators": "", + "add_new_email": "", + "shared_with_people_count_zero": "", + "shared_with_people_count_one": "", + "shared_with_people_count": "", + "participants_count_zero": "", + "participants_count_one": "", + "participants_count": "", + "add_viewers": "", + "change_permission_to_viewer": "", + "change_permission_to_collaborator": "", + "change_permission_title": "", + "confirm_convert_to_viewer": "", + "confirm_convert_to_collaborator": "", + "manage": "", + "added_as": "", + "collaborator_hint": "", + "remove_participant": "", + "remove_participant_title": "", + "remove_participant_message": "", + "confirm_remove": "", + "owner": "", + "collaborators": "", + "viewers": "", + "add_more": "", + "or_add_existing": "", + "not_found": "", + "link_expired": "", + "link_expired_message": "", + "manage_link": "", + "link_request_limit_exceeded": "", + "allow_downloads": "", + "allow_adding_photos": "", + "allow_adding_photos_hint": "", + "device_limit": "", + "none": "", + "link_expiry": "", + "never": "", + "after_time": { + "hour": "", + "day": "", + "week": "", + "month": "", + "year": "" + }, + "copy_link": "", + "done": "", + "share_link_section_title": "", + "remove_link": "", + "create_public_link": "", + "public_link_created": "", + "public_link_enabled": "", + "collect_photos": "", + "disable_file_download": "", + "disable_file_download_message": "", + "shared_using": "", + "sharing_referral_code": "", + "disable_password": "", + "disable_password_message": "", + "password_lock": "", + "lock": "", + "file": "", + "folder": "", + "google_takeout": "", + "deduplicate_files": "", + "remove_duplicates": "", + "total_size": "", + "count": "", + "deselect_all": "", + "no_duplicates": "", + "duplicate_group_description": "", + "remove_duplicates_button_count": "", + "stop_uploads_title": "", + "stop_uploads_message": "", + "yes_stop_uploads": "", + "stop_downloads_title": "", + "stop_downloads_message": "", + "yes_stop_downloads": "", + "albums": "", + "albums_count_one": "", + "albums_count": "", + "all_albums": "", + "all_hidden_albums": "", + "hidden_albums": "", + "hidden_items": "", + "enter_two_factor_otp": "", + "create_account": "", + "copied": "", + "upgrade_now": "", + "renew_now": "", + "storage": "", + "used": "", + "you": "", + "family": "", + "free": "", + "of": "", + "watch_folders": "", + "watched_folders": "", + "no_folders_added": "", + "watch_folders_hint_1": "", + "watch_folders_hint_2": "", + "watch_folders_hint_3": "", + "add_folder": "", + "stop_watching": "", + "stop_watching_folder_title": "", + "stop_watching_folder_message": "", + "yes_stop": "", + "change_folder": "", + "view_logs": "", + "view_logs_message": "", + "weak_device_hint": "", + "drag_and_drop_hint": "", + "authenticate": "", + "uploaded_to_single_collection": "", + "uploaded_to_separate_collections": "", + "nevermind": "", + "update_available": "", + "update_installable_message": "", + "install_now": "", + "install_on_next_launch": "", + "update_available_message": "", + "download_and_install": "", + "ignore_this_version": "", + "today": "", + "yesterday": "", + "enter_name": "", + "uploader_name_hint": "", + "name_placeholder": "", + "more_details": "", + "ml_search": "", + "ml_search_description": "", + "ml_search_footnote": "", + "indexing": "", + "processed": "", + "indexing_status_running": "", + "indexing_status_fetching": "", + "indexing_status_scheduled": "", + "indexing_status_done": "", + "ml_search_disable": "", + "ml_search_disable_confirm": "", + "ml_consent": "", + "ml_consent_title": "", + "ml_consent_description": "", + "ml_consent_confirmation": "", + "labs": "", + "password_strength_weak": "", + "password_strength_moderate": "", + "password_strength_strong": "", + "preferences": "", + "language": "", + "advanced": "", + "export_directory_does_not_exist": "", + "export_directory_does_not_exist_message": "", + "storage_unit": { + "b": "", + "kb": "", + "mb": "", + "gb": "", + "tb": "" + }, + "stop": "", + "sync_continuously": "", + "export_starting": "", + "export_preparing": "", + "export_renaming_album_folders": "", + "export_trashing_deleted_files": "", + "export_trashing_deleted_albums": "", + "export_progress": "", + "pending_items": "", + "delete_account_reason_label": "", + "delete_account_reason_placeholder": "", + "delete_reason": { + "missing_feature": "", + "behaviour": "", + "found_another_service": "", + "not_listed": "" + }, + "delete_account_feedback_label": "", + "delete_account_feedback_placeholder": "", + "delete_account_confirm_checkbox_label": "", + "delete_account_confirm": "", + "delete_account_confirm_message": "", + "feedback_required": "", + "feedback_required_found_another_service": "", + "recover_two_factor": "", + "at": "", + "auth_next": "", + "auth_download_mobile_app": "", + "no_codes_added_yet": "", + "hide": "", + "unhide": "", + "sort_by": "", + "newest_first": "", + "oldest_first": "", + "pin_album": "", + "unpin_album": "", + "unpreviewable_file_message": "", + "download_complete": "", + "downloading_album": "", + "download_failed": "", + "download_progress": "", + "christmas": "", + "christmas_eve": "", + "new_year": "", + "new_year_eve": "", + "image": "", + "video": "", + "live_photo": "", + "live": "", + "edit_image": "", + "photo_editor": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", + "brightness": "", + "contrast": "", + "saturation": "", + "blur": "", + "transform": "", + "crop": "", + "aspect_ratio": "", + "square": "", + "freehand": "", + "apply_crop": "", + "rotation": "", + "rotate_left": "", + "rotate_right": "", + "flip": "", + "flip_vertically": "", + "flip_horizontally": "", + "download_edited": "", + "save_a_copy_to_ente": "", + "restore_original": "", + "photo_edit_required_to_save": "", + "colors": "", + "invert_colors": "", + "reset": "", + "faster_upload": "", + "faster_upload_description": "", + "open_ente_on_startup": "", + "cast_album_to_tv": "", + "cast_to_tv": "", + "enter_cast_pin_code": "", + "code": "", + "pair_device_to_tv": "", + "tv_not_found": "", + "cast_auto_pair": "", + "cast_auto_pair_description": "", + "choose_device_from_browser": "", + "cast_auto_pair_failed": "", + "pair_with_pin": "", + "pair_with_pin_description": "", + "visit_cast_url": "", + "passkeys": "", + "passkey_fetch_failed": "", + "manage_passkey": "", + "delete_passkey": "", + "delete_passkey_confirmation": "", + "rename_passkey": "", + "add_passkey": "", + "enter_passkey_name": "", + "passkeys_description": "", + "created_at": "", + "passkey_add_failed": "", + "passkey_login_failed": "", + "passkey_login_invalid_url": "", + "passkey_login_already_claimed_session": "", + "passkey_login_generic_error": "", + "passkey_login_credential_hint": "", + "passkeys_not_supported": "", + "try_again": "", + "check_status": "", + "passkey_login_instructions": "", + "passkey_login": "", + "totp_login": "", + "passkey": "", + "passkey_verify_description": "", + "waiting_for_verification": "", + "verification_still_pending": "", + "passkey_verified": "", + "redirecting_back_to_app": "", + "redirect_close_instructions": "", + "redirect_again": "", + "autogenerated_first_album_name": "", + "autogenerated_default_album_name": "", + "developer_settings": "", + "server_endpoint": "", + "more_information": "", + "save": "", + "theme": "", + "system": "", + "light": "", + "dark": "", + "streamable_videos": "", + "processing_videos_status": "", + "share_favorites": "", + "person_favorites": "", + "shared_favorites": "", + "added_by_name": "", + "unowned_files_not_processed": "" +} diff --git a/web/packages/base/locales/ms-MY/translation.json b/web/packages/base/locales/ms-MY/translation.json new file mode 100644 index 0000000000..23a6018ed0 --- /dev/null +++ b/web/packages/base/locales/ms-MY/translation.json @@ -0,0 +1,689 @@ +{ + "intro_slide_1_title": "", + "intro_slide_1": "", + "intro_slide_2_title": "", + "intro_slide_2": "", + "intro_slide_3_title": "", + "intro_slide_3": "", + "login": "", + "sign_up": "", + "new_to_ente": "", + "existing_user": "", + "enter_email": "", + "invalid_email_error": "", + "required": "", + "email_not_registered": "", + "email_already_registered": "", + "email_sent": "", + "check_inbox_hint": "", + "verification_code": "", + "resend_code": "", + "verify": "", + "send_otp": "", + "generic_error": "", + "generic_error_retry": "", + "invalid_code_error": "", + "expired_code_error": "", + "status_sending": "", + "status_sent": "", + "password": "", + "link_password_description": "", + "unlock": "", + "set_password": "", + "sign_in": "", + "incorrect_password": "", + "incorrect_password_or_no_account": "", + "pick_password_hint": "", + "pick_password_caution": "", + "key_generation_in_progress": "", + "confirm_password": "", + "referral_source_hint": "", + "referral_source_info": "", + "password_mismatch_error": "", + "show_or_hide_password": "", + "welcome_to_ente_title": "", + "welcome_to_ente_subtitle": "", + "new_album": "", + "create_albums": "", + "album_name": "", + "close": "", + "yes": "", + "no": "", + "nothing_here": "", + "upload": "", + "import": "", + "add_photos": "", + "add_more_photos": "", + "add_photos_count_one": "", + "add_photos_count": "", + "select_photos": "", + "file_upload": "", + "preparing": "", + "processed_counts": "", + "upload_reading_metadata_files": "", + "upload_cancelling": "", + "upload_done": "", + "upload_skipped": "", + "initial_load_delay_warning": "", + "no_account": "", + "existing_account": "", + "create": "", + "files_count": "", + "download": "", + "download_album": "", + "download_favorites": "", + "download_uncategorized": "", + "download_hidden_items": "", + "audio": "", + "more": "", + "mouse_scroll": "", + "pan": "", + "pinch": "", + "drag": "", + "tap_inside_image": "", + "tap_outside_image": "", + "shortcuts": "", + "show_shortcuts": "", + "zoom_preset": "", + "toggle_controls": "", + "toggle_live": "", + "toggle_audio": "", + "toggle_favorite": "", + "toggle_archive": "", + "view_info": "", + "copy_as_png": "", + "toggle_fullscreen": "", + "exit_fullscreen": "", + "go_fullscreen": "", + "zoom": "", + "play": "", + "pause": "", + "previous": "", + "next": "", + "video_seek": "", + "quality": "", + "auto": "", + "original": "", + "speed": "", + "title_photos": "", + "title_auth": "", + "title_accounts": "", + "upload_first_photo": "", + "import_your_folders": "", + "upload_dropzone_hint": "", + "watch_folder_dropzone_hint": "", + "trash_files_title": "", + "trash_file_title": "", + "delete_files_title": "", + "delete_files_message": "", + "selected_count": "", + "selected_and_yours_count": "", + "delete": "", + "favorite": "", + "convert": "", + "multi_folder_upload": "", + "upload_to_choice": "", + "upload_to_single_album": "", + "upload_to_album_per_folder": "", + "session_expired": "", + "session_expired_message": "", + "password_generation_failed": "", + "change_password": "", + "password_changed_elsewhere": "", + "password_changed_elsewhere_message": "", + "go_back": "", + "account": "", + "recovery_key": "", + "do_this_later": "", + "save_key": "", + "recovery_key_description": "", + "key_not_stored_note": "", + "recovery_key_generation_failed": "", + "forgot_password": "", + "recover_account": "", + "recover": "", + "no_recovery_key_title": "", + "incorrect_recovery_key": "", + "sorry": "", + "no_recovery_key_message": "", + "no_two_factor_recovery_key_message": "", + "contact_support": "", + "help": "", + "ente_help": "", + "blog": "", + "request_feature": "", + "support": "", + "cancel": "", + "logout": "", + "logout_message": "", + "delete_account": "", + "delete_account_manually_message": "", + "change_email": "", + "ok": "", + "success": "", + "error": "", + "note": "", + "offline_message": "", + "install": "", + "install_mobile_app": "", + "download_app": "", + "download_app_message": "", + "subscription": "", + "manage_payment_method": "", + "manage_family": "", + "family_plan": "", + "leave_family_plan": "", + "leave": "", + "leave_family_plan_confirm": "", + "choose_plan": "", + "manage_plan": "", + "current_usage": "", + "two_months_free": "", + "free_plan_option": "", + "free_plan_description": "", + "active": "", + "subscription_info_free": "", + "subscription_info_family": "", + "subscription_info_expired": "", + "subscription_info_renewal_cancelled": "", + "subscription_info_storage_quota_exceeded": "", + "subscription_status_renewal_active": "", + "subscription_status_renewal_cancelled": "", + "add_on_valid_till": "", + "subscription_expired": "", + "storage_quota_exceeded": "", + "subscription_purchase_success": "", + "subscription_purchase_cancelled": "", + "subscription_purchase_failed": "", + "subscription_verification_error": "", + "update_payment_method_message": "", + "payment_method_authentication_failed": "", + "update_payment_method": "", + "monthly": "", + "yearly": "", + "month_short": "", + "year": "", + "update_subscription": "", + "update_subscription_title": "", + "update_subscription_message": "", + "cancel_subscription": "", + "cancel_subscription_message": "", + "cancel_subscription_with_addon_message": "", + "subscription_cancel_success": "", + "reactivate_subscription": "", + "reactivate_subscription_message": "", + "subscription_activate_success": "", + "thank_you": "", + "cancel_subscription_on_mobile": "", + "cancel_subscription_on_mobile_message": "", + "mail_to_manage_subscription": "", + "rename": "", + "rename_file": "", + "rename_album": "", + "delete_album": "", + "delete_album_title": "", + "delete_album_message": "", + "delete_photos": "", + "keep_photos": "", + "share_album": "", + "sharing_with_self": "", + "sharing_already_shared": "", + "sharing_album_not_allowed": "", + "sharing_disabled_for_free_accounts": "", + "sharing_user_does_not_exist": "", + "search": "", + "search_results": "", + "no_results": "", + "search_hint": "", + "album": "", + "date": "", + "description": "", + "file_type": "", + "magic": "", + "photos_count_zero": "", + "photos_count_one": "", + "photos_count": "", + "terms_and_conditions": "", + "people": "", + "indexing_scheduled": "", + "indexing_photos": "", + "indexing_fetching": "", + "indexing_people": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", + "info": "", + "file_name": "", + "caption_placeholder": "", + "location": "", + "view_on_map": "", + "map": "", + "enable_map": "", + "enable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", + "details": "", + "view_exif": "", + "no_exif": "", + "exif": "", + "two_factor": "", + "two_factor_authentication": "", + "two_factor_qr_help": "", + "two_factor_manual_entry_title": "", + "two_factor_manual_entry_message": "", + "scan_qr_title": "", + "enable_two_factor": "", + "enable": "", + "enabled": "", + "lost_2fa_device": "", + "incorrect_code": "", + "two_factor_info": "", + "disable": "", + "reconfigure": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", + "export_data": "", + "select_folder": "", + "select_zips": "", + "faq": "", + "takeout_hint": "", + "destination": "", + "start": "", + "last_export_time": "", + "export_again": "", + "local_storage_not_accessible": "", + "email_already_taken": "", + "live_photos_detected": "", + "ignored_uploads": "", + "ignored_uploads_hint": "", + "file_not_uploaded_list": "", + "failed_uploads": "", + "failed_uploads_hint": "", + "retry_failed_uploads": "", + "thumbnail_generation_failed": "", + "thumbnail_generation_failed_hint": "", + "unsupported_files": "", + "unsupported_files_hint": "", + "blocked_uploads": "", + "blocked_uploads_hint": "", + "large_files": "", + "large_files_hint": "", + "insufficient_storage": "", + "insufficient_storage_hint": "", + "uploads_in_progress": "", + "successful_uploads": "", + "upload_to_album": "", + "add_to_album": "", + "move_to_album": "", + "unhide_to_album": "", + "restore_to_album": "", + "section_all": "", + "section_uncategorized": "", + "section_archive": "", + "section_hidden": "", + "section_trash": "", + "favorites": "", + "archive": "", + "archive_album": "", + "unarchive": "", + "unarchive_album": "", + "hide_collection": "", + "unhide_collection": "", + "move": "", + "add": "", + "remove": "", + "yes_remove": "", + "remove_from_album": "", + "move_to_trash": "", + "trash_files_message": "", + "trash_file_message": "", + "delete_permanently": "", + "restore": "", + "empty_trash": "", + "empty_trash_title": "", + "empty_trash_message": "", + "leave_album": "", + "leave_shared_album_title": "", + "leave_shared_album_message": "", + "leave_shared_album": "", + "confirm_remove_message": "", + "confirm_remove_incl_others_message": "", + "oldest": "", + "last_updated": "", + "name": "", + "fix_creation_time": "", + "fix_creation_time_in_progress": "", + "fix_creation_time_file_updated": "", + "fix_creation_time_completed": "", + "fix_creation_time_completed_with_errors": "", + "fix_creation_time_options": "", + "exif_date_time_original": "", + "exif_date_time_digitized": "", + "exif_metadata_date": "", + "custom_time": "", + "caption_character_limit": "", + "sharing_details": "", + "modify_sharing": "", + "add_collaborators": "", + "add_new_email": "", + "shared_with_people_count_zero": "", + "shared_with_people_count_one": "", + "shared_with_people_count": "", + "participants_count_zero": "", + "participants_count_one": "", + "participants_count": "", + "add_viewers": "", + "change_permission_to_viewer": "", + "change_permission_to_collaborator": "", + "change_permission_title": "", + "confirm_convert_to_viewer": "", + "confirm_convert_to_collaborator": "", + "manage": "", + "added_as": "", + "collaborator_hint": "", + "remove_participant": "", + "remove_participant_title": "", + "remove_participant_message": "", + "confirm_remove": "", + "owner": "", + "collaborators": "", + "viewers": "", + "add_more": "", + "or_add_existing": "", + "not_found": "", + "link_expired": "", + "link_expired_message": "", + "manage_link": "", + "link_request_limit_exceeded": "", + "allow_downloads": "", + "allow_adding_photos": "", + "allow_adding_photos_hint": "", + "device_limit": "", + "none": "", + "link_expiry": "", + "never": "", + "after_time": { + "hour": "", + "day": "", + "week": "", + "month": "", + "year": "" + }, + "copy_link": "", + "done": "", + "share_link_section_title": "", + "remove_link": "", + "create_public_link": "", + "public_link_created": "", + "public_link_enabled": "", + "collect_photos": "", + "disable_file_download": "", + "disable_file_download_message": "", + "shared_using": "", + "sharing_referral_code": "", + "disable_password": "", + "disable_password_message": "", + "password_lock": "", + "lock": "", + "file": "", + "folder": "", + "google_takeout": "", + "deduplicate_files": "", + "remove_duplicates": "", + "total_size": "", + "count": "", + "deselect_all": "", + "no_duplicates": "", + "duplicate_group_description": "", + "remove_duplicates_button_count": "", + "stop_uploads_title": "", + "stop_uploads_message": "", + "yes_stop_uploads": "", + "stop_downloads_title": "", + "stop_downloads_message": "", + "yes_stop_downloads": "", + "albums": "", + "albums_count_one": "", + "albums_count": "", + "all_albums": "", + "all_hidden_albums": "", + "hidden_albums": "", + "hidden_items": "", + "enter_two_factor_otp": "", + "create_account": "", + "copied": "", + "upgrade_now": "", + "renew_now": "", + "storage": "", + "used": "", + "you": "", + "family": "", + "free": "", + "of": "", + "watch_folders": "", + "watched_folders": "", + "no_folders_added": "", + "watch_folders_hint_1": "", + "watch_folders_hint_2": "", + "watch_folders_hint_3": "", + "add_folder": "", + "stop_watching": "", + "stop_watching_folder_title": "", + "stop_watching_folder_message": "", + "yes_stop": "", + "change_folder": "", + "view_logs": "", + "view_logs_message": "", + "weak_device_hint": "", + "drag_and_drop_hint": "", + "authenticate": "", + "uploaded_to_single_collection": "", + "uploaded_to_separate_collections": "", + "nevermind": "", + "update_available": "", + "update_installable_message": "", + "install_now": "", + "install_on_next_launch": "", + "update_available_message": "", + "download_and_install": "", + "ignore_this_version": "", + "today": "", + "yesterday": "", + "enter_name": "", + "uploader_name_hint": "", + "name_placeholder": "", + "more_details": "", + "ml_search": "", + "ml_search_description": "", + "ml_search_footnote": "", + "indexing": "", + "processed": "", + "indexing_status_running": "", + "indexing_status_fetching": "", + "indexing_status_scheduled": "", + "indexing_status_done": "", + "ml_search_disable": "", + "ml_search_disable_confirm": "", + "ml_consent": "", + "ml_consent_title": "", + "ml_consent_description": "", + "ml_consent_confirmation": "", + "labs": "", + "password_strength_weak": "", + "password_strength_moderate": "", + "password_strength_strong": "", + "preferences": "", + "language": "", + "advanced": "", + "export_directory_does_not_exist": "", + "export_directory_does_not_exist_message": "", + "storage_unit": { + "b": "", + "kb": "", + "mb": "", + "gb": "", + "tb": "" + }, + "stop": "", + "sync_continuously": "", + "export_starting": "", + "export_preparing": "", + "export_renaming_album_folders": "", + "export_trashing_deleted_files": "", + "export_trashing_deleted_albums": "", + "export_progress": "", + "pending_items": "", + "delete_account_reason_label": "", + "delete_account_reason_placeholder": "", + "delete_reason": { + "missing_feature": "", + "behaviour": "", + "found_another_service": "", + "not_listed": "" + }, + "delete_account_feedback_label": "", + "delete_account_feedback_placeholder": "", + "delete_account_confirm_checkbox_label": "", + "delete_account_confirm": "", + "delete_account_confirm_message": "", + "feedback_required": "", + "feedback_required_found_another_service": "", + "recover_two_factor": "", + "at": "", + "auth_next": "", + "auth_download_mobile_app": "", + "no_codes_added_yet": "", + "hide": "", + "unhide": "", + "sort_by": "", + "newest_first": "", + "oldest_first": "", + "pin_album": "", + "unpin_album": "", + "unpreviewable_file_message": "", + "download_complete": "", + "downloading_album": "", + "download_failed": "", + "download_progress": "", + "christmas": "", + "christmas_eve": "", + "new_year": "", + "new_year_eve": "", + "image": "", + "video": "", + "live_photo": "", + "live": "", + "edit_image": "", + "photo_editor": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", + "brightness": "", + "contrast": "", + "saturation": "", + "blur": "", + "transform": "", + "crop": "", + "aspect_ratio": "", + "square": "", + "freehand": "", + "apply_crop": "", + "rotation": "", + "rotate_left": "", + "rotate_right": "", + "flip": "", + "flip_vertically": "", + "flip_horizontally": "", + "download_edited": "", + "save_a_copy_to_ente": "", + "restore_original": "", + "photo_edit_required_to_save": "", + "colors": "", + "invert_colors": "", + "reset": "", + "faster_upload": "", + "faster_upload_description": "", + "open_ente_on_startup": "", + "cast_album_to_tv": "", + "cast_to_tv": "", + "enter_cast_pin_code": "", + "code": "", + "pair_device_to_tv": "", + "tv_not_found": "", + "cast_auto_pair": "", + "cast_auto_pair_description": "", + "choose_device_from_browser": "", + "cast_auto_pair_failed": "", + "pair_with_pin": "", + "pair_with_pin_description": "", + "visit_cast_url": "", + "passkeys": "", + "passkey_fetch_failed": "", + "manage_passkey": "", + "delete_passkey": "", + "delete_passkey_confirmation": "", + "rename_passkey": "", + "add_passkey": "", + "enter_passkey_name": "", + "passkeys_description": "", + "created_at": "", + "passkey_add_failed": "", + "passkey_login_failed": "", + "passkey_login_invalid_url": "", + "passkey_login_already_claimed_session": "", + "passkey_login_generic_error": "", + "passkey_login_credential_hint": "", + "passkeys_not_supported": "", + "try_again": "", + "check_status": "", + "passkey_login_instructions": "", + "passkey_login": "", + "totp_login": "", + "passkey": "", + "passkey_verify_description": "", + "waiting_for_verification": "", + "verification_still_pending": "", + "passkey_verified": "", + "redirecting_back_to_app": "", + "redirect_close_instructions": "", + "redirect_again": "", + "autogenerated_first_album_name": "", + "autogenerated_default_album_name": "", + "developer_settings": "", + "server_endpoint": "", + "more_information": "", + "save": "", + "theme": "", + "system": "", + "light": "", + "dark": "", + "streamable_videos": "", + "processing_videos_status": "", + "share_favorites": "", + "person_favorites": "", + "shared_favorites": "", + "added_by_name": "", + "unowned_files_not_processed": "" +} diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index e97679c9e8..0eb8b4c74d 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -74,7 +74,7 @@ "download_favorites": "Pobierz ulubione", "download_uncategorized": "Pobierz nieskategoryzowane", "download_hidden_items": "Pobierz ukryte elementy", - "audio": "", + "audio": "Dźwięk", "more": "Więcej", "mouse_scroll": "Przewijanie kółkiem myszy", "pan": "", @@ -95,16 +95,16 @@ "toggle_fullscreen": "Przełącz tryb pełnoekranowy", "exit_fullscreen": "Zamknij tryb pełnoekranowy", "go_fullscreen": "Przejdź do trybu pełnoekranowego", - "zoom": "", - "play": "", - "pause": "", + "zoom": "Powiększenie", + "play": "Odtwórz", + "pause": "Wstrzymaj", "previous": "Poprzedni", "next": "Następny", "video_seek": "", - "quality": "", + "quality": "Jakość", "auto": "Automatycznie", - "original": "", - "speed": "", + "original": "Oryginał", + "speed": "Prędkość", "title_photos": "Zdjęcia Ente", "title_auth": "Ente Auth", "title_accounts": "Konta Ente", @@ -132,7 +132,7 @@ "password_changed_elsewhere": "Hasło zostało zmienione gdzie indziej", "password_changed_elsewhere_message": "Zaloguj się ponownie na tym urządzeniu, aby użyć nowego hasła, aby się uwierzytelnić.", "go_back": "Cofnij się", - "account": "", + "account": "Konto", "recovery_key": "Klucz odzyskiwania", "do_this_later": "Zrób to później", "save_key": "Zapisz Klucz", @@ -230,7 +230,7 @@ "sharing_already_shared": "Już udostępniasz to {{email}}", "sharing_album_not_allowed": "Udostępnianie albumu nie jest dozwolone", "sharing_disabled_for_free_accounts": "Udostępnianie jest wyłączone dla darmowych kont", - "sharing_user_does_not_exist": "", + "sharing_user_does_not_exist": "Nie można znaleźć użytkownika z tym adresem e-mail", "search": "Szukaj", "search_results": "Wyniki wyszukiwania", "no_results": "Nie znaleziono wyników", @@ -625,9 +625,9 @@ "reset": "Zresetuj", "faster_upload": "Szybsze przesłania", "faster_upload_description": "Kieruj przesłania przez pobliskie serwery", - "open_ente_on_startup": "", + "open_ente_on_startup": "Uruchom Ente przy starcie systemu", "cast_album_to_tv": "Odtwórz album na telewizorze", - "cast_to_tv": "", + "cast_to_tv": "Odtwarzaj na telewizorze", "enter_cast_pin_code": "Wprowadź kod, który widzisz na telewizorze poniżej, aby sparować to urządzenie.", "code": "Kod", "pair_device_to_tv": "Sparuj urządzenia", @@ -677,13 +677,13 @@ "save": "Zapisz", "theme": "Motyw", "system": "Systemowy", - "light": "", - "dark": "", - "streamable_videos": "", - "processing_videos_status": "", - "share_favorites": "", - "person_favorites": "", - "shared_favorites": "", - "added_by_name": "", - "unowned_files_not_processed": "" + "light": "Jasny", + "dark": "Ciemny", + "streamable_videos": "Streamowalne wideo", + "processing_videos_status": "Przetwarzanie wideo...", + "share_favorites": "Udostępnij ulubione", + "person_favorites": "Ulubione użytkownika {{name}}", + "shared_favorites": "Udostępnione ulubione", + "added_by_name": "Dodane przez {{name}}", + "unowned_files_not_processed": "Pliki dodane przez innych użytkowników nie były przetwarzane" } diff --git a/web/packages/base/locales/vi-VN/translation.json b/web/packages/base/locales/vi-VN/translation.json index 6212bc57a2..d4a6197a5a 100644 --- a/web/packages/base/locales/vi-VN/translation.json +++ b/web/packages/base/locales/vi-VN/translation.json @@ -12,7 +12,7 @@ "enter_email": "Nhập địa chỉ email", "invalid_email_error": "Nhập một email hợp lệ", "required": "Bắt buộc", - "email_not_registered": "Email chưa được đăng kí", + "email_not_registered": "Email chưa được đăng ký", "email_already_registered": "Email đã được đăng ký", "email_sent": "Mã xác minh đã được gửi đến {{email}}", "check_inbox_hint": "Vui lòng kiểm tra hộp thư đến (và thư rác) để hoàn tất xác minh", @@ -20,8 +20,8 @@ "resend_code": "Gửi lại mã", "verify": "Xác minh", "send_otp": "Gửi OTP", - "generic_error": "Có gì đó không đúng", - "generic_error_retry": "Có gì đó không đúng, vui lòng thử lại", + "generic_error": "Có gì đó không ổn", + "generic_error_retry": "Có gì đó không ổn, vui lòng thử lại", "invalid_code_error": "Mã xác minh không hợp lệ", "expired_code_error": "Mã xác minh của bạn đã hết hạn", "status_sending": "Đang gửi...", @@ -31,7 +31,7 @@ "unlock": "Mở khóa", "set_password": "Đặt mật khẩu", "sign_in": "Đăng nhập", - "incorrect_password": "Mật khẩu không chính xác", + "incorrect_password": "Mật khẩu không đúng", "incorrect_password_or_no_account": "Sai mật khẩu hoặc email chưa được đăng ký", "pick_password_hint": "Vui lòng nhập một mật khẩu dùng để mã hóa dữ liệu của bạn", "pick_password_caution": "Chúng tôi không lưu trữ mật khẩu của bạn, nên nếu bạn quên, chúng tôi sẽ không thể giúp bạn khôi phục dữ liệu nếu không có mã khôi phục.", @@ -64,14 +64,14 @@ "upload_cancelling": "Hủy bỏ các lượt tải lên còn lại", "upload_done": "Đã tải lên {{count, number}}", "upload_skipped": "{{count, number}} bị bỏ qua", - "initial_load_delay_warning": "Lần đầu tải có thể mất một ít thời gian", + "initial_load_delay_warning": "Lần đầu tải có thể mất ít phút", "no_account": "Chưa có tài khoản", "existing_account": "Đã có tài khoản", "create": "Tạo", "files_count": "{{count, number}} tệp", "download": "Tải xuống", "download_album": "Tải xuống album", - "download_favorites": "Tải xuống mục yêu thích", + "download_favorites": "Tải xuống những mục đã thích", "download_uncategorized": "Tải xuống mục chưa phân loại", "download_hidden_items": "Tải xuống mục ẩn", "audio": "Âm thanh", @@ -86,7 +86,7 @@ "show_shortcuts": "Hiện phím tắt", "zoom_preset": "Phóng to chi tiết", "toggle_controls": "Bật/tắt điều khiển", - "toggle_live": "Bật/tắt Live", + "toggle_live": "Bật/tắt ảnh động", "toggle_audio": "Bật/tắt âm thanh", "toggle_favorite": "Thích/bỏ thích", "toggle_archive": "Lưu trữ/bỏ lưu trữ", @@ -122,7 +122,7 @@ "favorite": "Thích", "convert": "Chuyển đổi", "multi_folder_upload": "Phát hiện nhiều thư mục", - "upload_to_choice": "Bạn có muốn tải chúng thành", + "upload_to_choice": "Bạn sẽ tải lên thành", "upload_to_single_album": "Một album duy nhất", "upload_to_album_per_folder": "Các album riêng biệt", "session_expired": "Phiên đã hết hạn", @@ -137,7 +137,7 @@ "do_this_later": "Để sau", "save_key": "Lưu mã", "recovery_key_description": "Nếu bạn quên mật khẩu, cách duy nhất để khôi phục dữ liệu của bạn là dùng mã này.", - "key_not_stored_note": "Chúng tôi không lưu trữ mã này, nên hãy lưu nó ở một nơi an toàn", + "key_not_stored_note": "Chúng tôi không lưu trữ mã này, nên hãy lưu nó ở nơi an toàn", "recovery_key_generation_failed": "Không tạo được mã khôi phục, vui lòng thử lại", "forgot_password": "Quên mật khẩu", "recover_account": "Khôi phục tài khoản", @@ -165,7 +165,7 @@ "note": "Ghi chú", "offline_message": "Bạn đang ngoại tuyến, các kỷ niệm hiển thị là từ bộ nhớ đệm", "install": "Cài đặt", - "install_mobile_app": "Cài đặt ứng dụng Android hoặc iOS của chúng tôi để tự động sao lưu tất cả ảnh của bạn", + "install_mobile_app": "Cài đặt ứng dụng Android hoặc iOS để sao lưu tự động tất cả ảnh của bạn", "download_app": "Tải xuống ứng dụng máy tính", "download_app_message": "Rất tiếc, thao tác này hiện chỉ hỗ trợ trên ứng dụng máy tính", "subscription": "Gói đăng ký", @@ -179,7 +179,7 @@ "manage_plan": "Quản lý gói đăng ký", "current_usage": "Hiện dùng {{usage}}", "two_months_free": "Nhận 2 tháng miễn phí với các gói theo năm", - "free_plan_option": "Dùng tiếp gói miễn phí", + "free_plan_option": "Tiếp tục dùng gói miễn phí", "free_plan_description": "{{storage}} miễn phí vĩnh viễn", "active": "Hoạt động", "subscription_info_free": "Bạn đang dùng gói miễn phí", @@ -222,7 +222,7 @@ "rename_album": "Đổi tên album", "delete_album": "Xóa album", "delete_album_title": "Xóa album?", - "delete_album_message": "Xóa luôn các tấm ảnh (và video) có trong album này khỏi toàn bộ album khác cũng đang chứa chúng?", + "delete_album_message": "Xóa luôn ảnh (và video) trong album này khỏi toàn bộ album khác cũng đang chứa chúng?", "delete_photos": "Xóa ảnh", "keep_photos": "Giữ ảnh", "share_album": "Chia sẻ album", @@ -240,10 +240,10 @@ "description": "Mô tả", "file_type": "Loại tệp", "magic": "Ma thuật", - "photos_count_zero": "Chưa có ảnh nào", - "photos_count_one": "1 ảnh", - "photos_count": "{{count, number}} ảnh", - "terms_and_conditions": "Tôi đồng ý điều khoảnchính sách bảo mật", + "photos_count_zero": "Chưa có kỷ niệm", + "photos_count_one": "1 kỷ niệm", + "photos_count": "{{count, number}} kỷ niệm", + "terms_and_conditions": "Tôi đồng ý với điều khoảnchính sách bảo mật", "people": "Người", "indexing_scheduled": "Đã lên lịch lập chỉ mục...", "indexing_photos": "Đang cập nhật chỉ mục...", @@ -277,7 +277,7 @@ "map": "Bản đồ", "enable_map": "Bật bản đồ", "enable_maps_confirm": "Bật bản đồ?", - "enable_maps_confirm_message": "

Ảnh của bạn sẽ hiển thị trên bản đồ thế giới.

Bản đồ được lưu trữ bởi OpenStreetMap, và vị trí chính xác ảnh của bạn không bao giờ được chia sẻ.

Bạn có thể tắt tính năng này bất cứ lúc nào từ Cài đặt.

", + "enable_maps_confirm_message": "

Ảnh của bạn sẽ hiển thị trên bản đồ thế giới.

Bản đồ được lưu trữ bởi OpenStreetMap và vị trí chính xác ảnh của bạn không bao giờ được chia sẻ.

Bạn có thể tắt tính năng này bất cứ lúc nào từ Cài đặt.

", "disable_map": "Tắt bản đồ", "disable_maps_confirm": "Tắt bản đồ?", "disable_maps_confirm_message": "

Ảnh của bạn sẽ thôi hiển thị trên bản đồ thế giới.

Bạn có thể bật tính năng này bất cứ lúc nào từ Cài đặt.

", @@ -293,10 +293,10 @@ "scan_qr_title": "Quét mã QR", "enable_two_factor": "Bật xác thực 2 bước", "enable": "Bật", - "enabled": "Đã bật", + "enabled": "Bật", "lost_2fa_device": "Mất thiết bị xác thực 2 bước", "incorrect_code": "Mã không chính xác", - "two_factor_info": "Thêm một lớp bảo mật bổ sung bằng cách yêu cầu nhiều hơn email và mật khẩu của bạn để đăng nhập", + "two_factor_info": "Thêm một lớp bảo mật bằng cách yêu cầu nhiều hơn email và mật khẩu của bạn để đăng nhập", "disable": "Tắt", "reconfigure": "Cấu hình lại", "reconfigure_two_factor_hint": "Cập nhật thiết bị xác thực của bạn", @@ -309,7 +309,7 @@ "select_folder": "Chọn thư mục", "select_zips": "Chọn tệp zip", "faq": "Câu hỏi thường gặp", - "takeout_hint": "Giải nén tất cả tệp zip vào cùng một thư mục và tải lên. Hoặc tải lên trực tiếp các tệp zip. Xem Câu hỏi thường gặp để biết thêm.", + "takeout_hint": "Giải nén tất cả tệp zip vào cùng một thư mục rồi tải lên. Hoặc tải lên trực tiếp các tệp zip. Xem Câu hỏi thường gặp để biết thêm.", "destination": "Đích đến", "start": "Bắt đầu", "last_export_time": "Thời gian xuất gần nhất", @@ -323,8 +323,8 @@ "failed_uploads": "Tải lên không thành công", "failed_uploads_hint": "Sẽ có tùy chọn thử lại sau khi việc tải lên hoàn tất", "retry_failed_uploads": "Thử tải lên lại các tệp không thành công", - "thumbnail_generation_failed": "Tạo hình thu nhỏ không thành công", - "thumbnail_generation_failed_hint": "Các tệp này đã được tải lên, nhưng rất tiếc chúng tôi không thể tạo hình thu nhỏ cho chúng.", + "thumbnail_generation_failed": "Tạo ảnh thu nhỏ không thành công", + "thumbnail_generation_failed_hint": "Các tệp này đã được tải lên, nhưng rất tiếc chúng tôi không thể tạo ảnh thu nhỏ cho chúng.", "unsupported_files": "Tệp không được hỗ trợ", "unsupported_files_hint": "Ente chưa hỗ trợ các định dạng tệp này", "blocked_uploads": "Tải lên bị chặn", @@ -415,7 +415,7 @@ "or_add_existing": "Hoặc chọn một cái có sẵn", "not_found": "404 - Không tìm thấy", "link_expired": "Liên kết đã hết hạn", - "link_expired_message": "Liên kết này đã hết hạn hoặc đã bị vô hiệu hóa", + "link_expired_message": "Liên kết này đã hết hạn hoặc bị vô hiệu hóa", "manage_link": "Quản lý liên kết", "link_request_limit_exceeded": "Album này đang được xem trên quá nhiều thiết bị", "allow_downloads": "Cho phép tải xuống", @@ -441,7 +441,7 @@ "public_link_enabled": "Liên kết công khai đã được bật", "collect_photos": "Thu thập ảnh", "disable_file_download": "Tắt tải xuống", - "disable_file_download_message": "

Bạn có chắc muốn tắt nút tải xuống các tệp không?

Người xem vẫn có thể chụp ảnh màn hình hoặc sao chép ảnh của bạn bằng các công cụ bên ngoài.

", + "disable_file_download_message": "

Bạn có chắc muốn tắt nút tải xuống các tệp không?

Người xem vẫn có thể chụp màn hình hoặc sao chép ảnh của bạn bằng các công cụ bên ngoài.

", "shared_using": "Chia sẻ bằng {{url}}", "sharing_referral_code": "Dùng mã {{referralCode}} để nhận 10 GB miễn phí", "disable_password": "Vô hiệu hóa khóa mật khẩu", @@ -477,13 +477,13 @@ "copied": "Đã sao chép", "upgrade_now": "Nâng cấp ngay", "renew_now": "Gia hạn ngay", - "storage": "Lưu trữ", + "storage": "Dung lượng", "used": "đã dùng", "you": "Bạn", "family": "Gia đình", - "free": "miễn phí", - "of": "của", - "watch_folders": "Theo dõi thư mục", + "free": "trống", + "of": "/", + "watch_folders": "Thư mục theo dõi", "watched_folders": "Thư mục đã theo dõi", "no_folders_added": "Chưa thêm thư mục nào", "watch_folders_hint_1": "Các thư mục bạn thêm ở đây sẽ được theo dõi tự động", @@ -495,7 +495,7 @@ "stop_watching_folder_message": "Các tệp hiện có của bạn sẽ không bị xóa, nhưng Ente sẽ ngừng tự động cập nhật album Ente liên kết khi có thay đổi trong thư mục này.", "yes_stop": "Có, dừng lại", "change_folder": "Thay đổi Thư mục", - "view_logs": "Xem log", + "view_logs": "Xem nhật ký", "view_logs_message": "

Tải xuống nhật ký lỗi, để bạn có thể gửi qua email cho chúng tôi.

Lưu ý rằng, trong nhật ký lỗi sẽ bao gồm tên các tệp để giúp theo dõi vấn đề với từng tệp cụ thể.

", "weak_device_hint": "Trình duyệt bạn đang sử dụng không đủ mạnh để mã hóa ảnh. Vui lòng dùng Ente trên máy tính, hoặc tải xuống ứng dụng di động/máy tính của Ente.", "drag_and_drop_hint": "Hoặc kéo thả vào cửa sổ Ente", @@ -513,7 +513,7 @@ "today": "Hôm nay", "yesterday": "Hôm qua", "enter_name": "Nhập tên", - "uploader_name_hint": "Thêm một tên để bạn bè biết ai là người chụp những tấm ảnh tuyệt vời này!", + "uploader_name_hint": "Thêm tên để bạn bè biết ai là người chụp những tấm ảnh tuyệt vời này!", "name_placeholder": "Tên...", "more_details": "Thêm chi tiết", "ml_search": "Học máy", @@ -589,17 +589,17 @@ "download_failed": "Tải xuống thất bại", "download_progress": "{{count, number}} / {{total, number}} tệp", "christmas": "Giáng Sinh", - "christmas_eve": "Đêm Thánh", + "christmas_eve": "Đêm Vọng", "new_year": "Năm Mới", "new_year_eve": "Đêm Giao Thừa", "image": "Hình ảnh", "video": "Video", - "live_photo": "Ảnh Live", - "live": "Live", + "live_photo": "Ảnh động", + "live": "Ảnh động", "edit_image": "Chỉnh sửa ảnh", "photo_editor": "Trình chỉnh sửa ảnh", "confirm_editor_close": "Bạn có chắc muốn đóng trình chỉnh sửa không?", - "confirm_editor_close_message": "Tải xuống hình ảnh đã chỉnh sửa hoặc lưu bản sao vào Ente để giữ các thay đổi của bạn.", + "confirm_editor_close_message": "Tải xuống ảnh đã chỉnh sửa hoặc lưu bản sao vào Ente để giữ các thay đổi của bạn.", "brightness": "Độ sáng", "contrast": "Độ tương phản", "saturation": "Độ bão hòa", @@ -608,7 +608,7 @@ "crop": "Cắt", "aspect_ratio": "Tỉ lệ khung hình", "square": "Hình vuông", - "freehand": "Vẽ tự do", + "freehand": "Chọn tự do", "apply_crop": "Áp dụng cắt", "rotation": "Xoay", "rotate_left": "Xoay trái", @@ -628,17 +628,17 @@ "open_ente_on_startup": "Mở Ente khi khởi động", "cast_album_to_tv": "Phát album trên TV", "cast_to_tv": "Phát trên TV", - "enter_cast_pin_code": "Nhập mã bạn thấy trên TV bên dưới để ghép nối thiết bị này.", + "enter_cast_pin_code": "Nhập mã bạn thấy trên TV bên dưới để kết nối thiết bị này.", "code": "Mã", - "pair_device_to_tv": "Ghép nối thiết bị", + "pair_device_to_tv": "Kết nối thiết bị", "tv_not_found": "Không tìm thấy TV. Bạn đã nhập mã PIN đúng chưa?", - "cast_auto_pair": "Ghép nối tự động", - "cast_auto_pair_description": "Ghép nối tự động chỉ hoạt động với các thiết bị hỗ trợ Chromecast.", + "cast_auto_pair": "Kết nối tự động", + "cast_auto_pair_description": "Kết nối tự động chỉ hoạt động với các thiết bị hỗ trợ Chromecast.", "choose_device_from_browser": "Chọn một thiết bị phát tương thích từ cửa sổ trình duyệt.", - "cast_auto_pair_failed": "Ghép nối tự động Chromecast thất bại. Vui lòng thử lại.", - "pair_with_pin": "Ghép nối bằng PIN", - "pair_with_pin_description": "Ghép nối bằng PIN hoạt động với bất kỳ màn hình nào bạn muốn xem album của mình.", - "visit_cast_url": "Truy cập {{url}} trên thiết bị bạn muốn ghép nối.", + "cast_auto_pair_failed": "Kết nối tự động Chromecast thất bại. Vui lòng thử lại.", + "pair_with_pin": "Kết nối bằng PIN", + "pair_with_pin_description": "Kết nối bằng PIN hoạt động với bất kỳ màn hình nào bạn muốn.", + "visit_cast_url": "Truy cập {{url}} trên thiết bị bạn muốn kết nối.", "passkeys": "Khóa truy cập", "passkey_fetch_failed": "Không thể lấy khóa truy cập của bạn.", "manage_passkey": "Quản lý khóa truy cập", @@ -671,7 +671,7 @@ "redirect_again": "Chuyển hướng lại", "autogenerated_first_album_name": "Album Đầu Tiên Của Tôi", "autogenerated_default_album_name": "Album Mới", - "developer_settings": "Cài đặt nhà phát triển", + "developer_settings": "Cài đặt Nhà phát triển", "server_endpoint": "Điểm cuối máy chủ", "more_information": "Thêm thông tin", "save": "Lưu", @@ -679,9 +679,9 @@ "system": "Giống hệ thống", "light": "Sáng", "dark": "Tối", - "streamable_videos": "Video có thể phát", + "streamable_videos": "Phát trực tuyến video", "processing_videos_status": "Đang xử lý video...", - "share_favorites": "Chia sẻ những mục thích", + "share_favorites": "Chia sẻ những mục đã thích", "person_favorites": "{{name}} đã thích", "shared_favorites": "Những mục thích đã chia sẻ", "added_by_name": "Được thêm bởi {{name}}", diff --git a/web/packages/base/locales/zh-HK/translation.json b/web/packages/base/locales/zh-HK/translation.json index f4e64f7bcf..05fbcc6e4d 100644 --- a/web/packages/base/locales/zh-HK/translation.json +++ b/web/packages/base/locales/zh-HK/translation.json @@ -7,7 +7,7 @@ "intro_slide_3": "", "login": "登入", "sign_up": "註冊", - "new_to_ente": "", + "new_to_ente": "新用戶", "existing_user": "現有用戶", "enter_email": "輸入電郵地址", "invalid_email_error": "輸入有效的電郵地址", @@ -27,22 +27,22 @@ "status_sending": "正在發送……", "status_sent": "已發送!", "password": "密碼", - "link_password_description": "", + "link_password_description": "輸入密碼以解鎖相簿", "unlock": "解鎖", "set_password": "設定密碼", "sign_in": "登入", "incorrect_password": "密碼錯誤", - "incorrect_password_or_no_account": "", - "pick_password_hint": "", - "pick_password_caution": "", - "key_generation_in_progress": "", + "incorrect_password_or_no_account": "密碼錯誤或電郵未註冊", + "pick_password_hint": "請輸入用於加密數據的密碼", + "pick_password_caution": "我們不會儲存你的密碼,如果你忘記密碼, 我們無法協助你 在沒有復原金鑰的情況下復原數據。", + "key_generation_in_progress": "正在產生加密金鑰……", "confirm_password": "確認密碼", - "referral_source_hint": "", + "referral_source_hint": "你如何認識 Ente?(可選)", "referral_source_info": "", - "password_mismatch_error": "", + "password_mismatch_error": "密碼不相同", "show_or_hide_password": "顯示或隱藏密碼", "welcome_to_ente_title": "歡迎來到 ", - "welcome_to_ente_subtitle": "", + "welcome_to_ente_subtitle": "端對端加密相片儲存及分享", "new_album": "新相簿", "create_albums": "創建相簿", "album_name": "相簿名稱", @@ -92,7 +92,7 @@ "toggle_archive": "", "view_info": "", "copy_as_png": "複製為 PNG", - "toggle_fullscreen": "", + "toggle_fullscreen": "切換全螢幕", "exit_fullscreen": "退出全螢幕", "go_fullscreen": "進入全螢幕", "zoom": "縮放", @@ -110,7 +110,7 @@ "title_accounts": "", "upload_first_photo": "上載你的第一張照片", "import_your_folders": "匯入你的資料夾", - "upload_dropzone_hint": "", + "upload_dropzone_hint": "放開以上傳檔案", "watch_folder_dropzone_hint": "", "trash_files_title": "刪除多個檔案?", "trash_file_title": "刪除檔案?", @@ -130,14 +130,14 @@ "password_generation_failed": "", "change_password": "更改密碼", "password_changed_elsewhere": "", - "password_changed_elsewhere_message": "", + "password_changed_elsewhere_message": "請以新密碼重新登入以作驗證。", "go_back": "返回", "account": "帳戶", "recovery_key": "復原金鑰", "do_this_later": "稍後再做", "save_key": "儲存金鑰", - "recovery_key_description": "", - "key_not_stored_note": "", + "recovery_key_description": "如果你忘記密碼,你只可以使用此金鑰復原數據。", + "key_not_stored_note": "我們不會儲存此金鑰,請妥善保存此金鑰", "recovery_key_generation_failed": "未能生成復原金鑰,請再試", "forgot_password": "忘記密碼", "recover_account": "復原帳戶", @@ -167,30 +167,30 @@ "install": "安裝", "install_mobile_app": "安裝我們的 AndroidiOS 應用程式來自動備份所有照片", "download_app": "下載桌面程式", - "download_app_message": "", + "download_app_message": "對不起,此動作只在桌面版支援", "subscription": "訂閱", - "manage_payment_method": "", - "manage_family": "", + "manage_payment_method": "管理支付方式", + "manage_family": "管理家庭", "family_plan": "家庭計劃", "leave_family_plan": "離開家庭計劃", "leave": "離開", - "leave_family_plan_confirm": "", - "choose_plan": "", - "manage_plan": "", - "current_usage": "", + "leave_family_plan_confirm": "你確定要離開家庭計劃嗎?", + "choose_plan": "選擇你的計劃", + "manage_plan": "管理你的訂閲", + "current_usage": "目前已使用 {{usage}}", "two_months_free": "", - "free_plan_option": "", + "free_plan_option": "以免費計劃繼續", "free_plan_description": "", - "active": "", - "subscription_info_free": "", + "active": "已啓用", + "subscription_info_free": "你正使用免費計劃", "subscription_info_family": "", - "subscription_info_expired": "", - "subscription_info_renewal_cancelled": "", + "subscription_info_expired": "你的訂閲已過期,請 續訂", + "subscription_info_renewal_cancelled": "你的訂閲將於 {{date, date}} 取消", "subscription_info_storage_quota_exceeded": "", "subscription_status_renewal_active": "", "subscription_status_renewal_cancelled": "", "add_on_valid_till": "", - "subscription_expired": "", + "subscription_expired": "訂閲已過期", "storage_quota_exceeded": "", "subscription_purchase_success": "", "subscription_purchase_cancelled": "", @@ -198,23 +198,23 @@ "subscription_verification_error": "", "update_payment_method_message": "", "payment_method_authentication_failed": "", - "update_payment_method": "", + "update_payment_method": "更新支付方式", "monthly": "每月", "yearly": "每年", "month_short": "月", "year": "年", - "update_subscription": "", - "update_subscription_title": "", + "update_subscription": "更變計劃", + "update_subscription_title": "確定更變計劃", "update_subscription_message": "", "cancel_subscription": "取消訂閱", "cancel_subscription_message": "", "cancel_subscription_with_addon_message": "", - "subscription_cancel_success": "", - "reactivate_subscription": "", + "subscription_cancel_success": "訂閲成功取消", + "reactivate_subscription": "重新啓用訂閲", "reactivate_subscription_message": "", - "subscription_activate_success": "", + "subscription_activate_success": "訂閲成功啓用 ", "thank_you": "感謝", - "cancel_subscription_on_mobile": "", + "cancel_subscription_on_mobile": "取消手機訂閱", "cancel_subscription_on_mobile_message": "", "mail_to_manage_subscription": "", "rename": "重新命名", @@ -237,17 +237,17 @@ "search_hint": "", "album": "相簿", "date": "日期", - "description": "", + "description": "描述", "file_type": "檔案類型", "magic": "魔術", - "photos_count_zero": "", - "photos_count_one": "", - "photos_count": "", - "terms_and_conditions": "", + "photos_count_zero": "沒有回憶", + "photos_count_one": "1 個回憶", + "photos_count": "{count, number} 個回憶", + "terms_and_conditions": "我同意 條款私隱政策", "people": "", "indexing_scheduled": "", - "indexing_photos": "", - "indexing_fetching": "", + "indexing_photos": "正在更新索引……", + "indexing_fetching": "正在同步索引……", "indexing_people": "", "syncing_wait": "正在同步……", "people_empty_too_few": "", @@ -290,7 +290,7 @@ "two_factor_qr_help": "", "two_factor_manual_entry_title": "", "two_factor_manual_entry_message": "", - "scan_qr_title": "", + "scan_qr_title": "以掃描 QR code 代替", "enable_two_factor": "啟用兩步驟", "enable": "啟用", "enabled": "已啟用", @@ -306,23 +306,23 @@ "disable_two_factor": "", "disable_two_factor_message": "", "export_data": "匯出數據", - "select_folder": "", + "select_folder": "選擇資料夾", "select_zips": "", "faq": "常見問題", "takeout_hint": "", "destination": "目的地", "start": "開始", - "last_export_time": "", - "export_again": "", - "local_storage_not_accessible": "", - "email_already_taken": "", + "last_export_time": "上次匯出時間", + "export_again": "重新同步", + "local_storage_not_accessible": "你的瀏覽器或插件正阻擋 Ente 儲存數據至本地儲存", + "email_already_taken": "電郵已被使用", "live_photos_detected": "", - "ignored_uploads": "", + "ignored_uploads": "無視上傳", "ignored_uploads_hint": "", "file_not_uploaded_list": "以下檔案未上傳", - "failed_uploads": "", + "failed_uploads": "失敗上傳", "failed_uploads_hint": "", - "retry_failed_uploads": "", + "retry_failed_uploads": "重試失敗上傳", "thumbnail_generation_failed": "", "thumbnail_generation_failed_hint": "", "unsupported_files": "", @@ -342,25 +342,25 @@ "restore_to_album": "", "section_all": "所有", "section_uncategorized": "未分類", - "section_archive": "", + "section_archive": "封存", "section_hidden": "隱藏", "section_trash": "垃圾箱", - "favorites": "", - "archive": "", + "favorites": "我的最愛", + "archive": "封存", "archive_album": "", - "unarchive": "", - "unarchive_album": "", - "hide_collection": "", - "unhide_collection": "", + "unarchive": "解除封存", + "unarchive_album": "取消封存相簿", + "hide_collection": "隱藏相簿", + "unhide_collection": "取消隱藏相簿", "move": "移動", "add": "新增", "remove": "移除", - "yes_remove": "", + "yes_remove": "是,移除", "remove_from_album": "從相簿移除", "move_to_trash": "移至垃圾桶", - "trash_files_message": "", - "trash_file_message": "", - "delete_permanently": "", + "trash_files_message": "被選擇的檔案將在所有相簿移除並移動至垃圾桶。", + "trash_file_message": "此檔案將在所有相簿移除並移動至垃圾桶。", + "delete_permanently": "永遠刪除", "restore": "還原", "empty_trash": "", "empty_trash_title": "", @@ -384,7 +384,7 @@ "exif_date_time_digitized": "", "exif_metadata_date": "", "custom_time": "", - "caption_character_limit": "", + "caption_character_limit": "最多 5000 字元", "sharing_details": "", "modify_sharing": "", "add_collaborators": "", @@ -392,9 +392,9 @@ "shared_with_people_count_zero": "", "shared_with_people_count_one": "", "shared_with_people_count": "", - "participants_count_zero": "", - "participants_count_one": "", - "participants_count": "", + "participants_count_zero": "沒有參加者", + "participants_count_one": "1 個參加者", + "participants_count": "{count, number} 個參加者", "add_viewers": "", "change_permission_to_viewer": "", "change_permission_to_collaborator": "", @@ -414,16 +414,16 @@ "add_more": "", "or_add_existing": "", "not_found": "", - "link_expired": "", - "link_expired_message": "", - "manage_link": "", + "link_expired": "連結過期", + "link_expired_message": "此連結已過期或已被禁用", + "manage_link": "管理連結", "link_request_limit_exceeded": "", - "allow_downloads": "", - "allow_adding_photos": "", - "allow_adding_photos_hint": "", - "device_limit": "", - "none": "", - "link_expiry": "", + "allow_downloads": "允許下載", + "allow_adding_photos": "允許加入相片", + "allow_adding_photos_hint": "允許持有連結的人加入相片到已分享的相簿。", + "device_limit": "裝置上限", + "none": "無", + "link_expiry": "連結過期", "never": "永不", "after_time": { "hour": "一小時後", @@ -434,13 +434,13 @@ }, "copy_link": "複製鏈接", "done": "完成", - "share_link_section_title": "", - "remove_link": "", + "share_link_section_title": "或分享連結", + "remove_link": "移除連結", "create_public_link": "", "public_link_created": "", "public_link_enabled": "", "collect_photos": "", - "disable_file_download": "", + "disable_file_download": "禁用下載", "disable_file_download_message": "", "shared_using": "", "sharing_referral_code": "", From e31768afe90de413454ce90e71815bd64882ab73 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 14 Jul 2025 16:12:46 +0530 Subject: [PATCH 12/81] [mob][ios] Remove automatic limit access alert on app start --- mobile/apps/photos/ios/Runner/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/apps/photos/ios/Runner/Info.plist b/mobile/apps/photos/ios/Runner/Info.plist index 5e9b8a7005..b7fe2f710e 100644 --- a/mobile/apps/photos/ios/Runner/Info.plist +++ b/mobile/apps/photos/ios/Runner/Info.plist @@ -84,6 +84,8 @@ Please allow access to your camera so that you can take photos within ente NSPhotoLibraryUsageDescription Please allow access to your photos so that ente can encrypt and back them up. + PHPhotoLibraryPreventAutomaticLimitedAccessAlert + UIBackgroundModes fetch From d2c14372109a8529583c280395784afe7b508897 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 14 Jul 2025 16:33:02 +0530 Subject: [PATCH 13/81] Make dialog dismissible --- .../apps/photos/lib/ui/payment/store_subscription_page.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mobile/apps/photos/lib/ui/payment/store_subscription_page.dart b/mobile/apps/photos/lib/ui/payment/store_subscription_page.dart index b83b65b5d2..6b27a57d24 100644 --- a/mobile/apps/photos/lib/ui/payment/store_subscription_page.dart +++ b/mobile/apps/photos/lib/ui/payment/store_subscription_page.dart @@ -161,7 +161,11 @@ class _StoreSubscriptionPageState extends State { _isLoading = true; _fetchSubData(); } - _dialog = createProgressDialog(context, S.of(context).pleaseWait); + _dialog = createProgressDialog( + context, + S.of(context).pleaseWait, + isDismissible: true, + ); return Scaffold( appBar: AppBar(), body: Column( From aa60c3c71a90a2d9541a82e9200867c97857d6cf Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 14 Jul 2025 16:35:33 +0530 Subject: [PATCH 14/81] Log error during sub fetch --- .../lib/ui/payment/store_subscription_page.dart | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/mobile/apps/photos/lib/ui/payment/store_subscription_page.dart b/mobile/apps/photos/lib/ui/payment/store_subscription_page.dart index 6b27a57d24..c25ab461b9 100644 --- a/mobile/apps/photos/lib/ui/payment/store_subscription_page.dart +++ b/mobile/apps/photos/lib/ui/payment/store_subscription_page.dart @@ -204,8 +204,9 @@ class _StoreSubscriptionPageState extends State { } Future _fetchSubData() async { - // ignore: unawaited_futures - _userService.getUserDetailsV2(memoryCount: false).then((userDetails) async { + try { + final userDetails = + await _userService.getUserDetailsV2(memoryCount: false); _userDetails = userDetails; _currentSubscription = userDetails.subscription; @@ -236,7 +237,14 @@ class _StoreSubscriptionPageState extends State { if (mounted) { setState(() {}); } - }); + } catch (e, s) { + _logger.severe("Error fetching subscription data", e, s); + if (mounted) { + setState(() { + _isLoading = false; + }); + } + } } Widget _getBody() { From 35f0251064bb645540c4c0ebb8c4dd362b7f8401 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Mon, 14 Jul 2025 13:19:58 +0200 Subject: [PATCH 15/81] Remove old todos --- mobile/apps/photos/lib/models/search/search_types.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/mobile/apps/photos/lib/models/search/search_types.dart b/mobile/apps/photos/lib/models/search/search_types.dart index 2a209cafc9..3485429bc2 100644 --- a/mobile/apps/photos/lib/models/search/search_types.dart +++ b/mobile/apps/photos/lib/models/search/search_types.dart @@ -108,7 +108,6 @@ extension SectionTypeExtensions on SectionType { } } - // TODO: lau: check if we should sort moment again bool get sortByName => this != SectionType.face && this != SectionType.magic && @@ -238,7 +237,6 @@ extension SectionTypeExtensions on SectionType { case SectionType.moment: if (flagService.internalUser) { - // TODO: lau: remove this whole smart memories and moment altogether return SearchService.instance.smartMemories(context!, limit); } return SearchService.instance.getRandomMomentsSearchResults(context!); From fa6694e2f944bb460816a7b70ea65185ccc1ddd2 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Mon, 14 Jul 2025 14:41:33 +0200 Subject: [PATCH 16/81] Remove moments and disable memories debug by default --- .../lib/models/search/search_types.dart | 34 +++++++++---------- .../ui/viewer/search_tab/moments_section.dart | 12 +++---- .../lib/ui/viewer/search_tab/search_tab.dart | 15 +++++--- .../apps/photos/lib/utils/local_settings.dart | 9 +++++ 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/mobile/apps/photos/lib/models/search/search_types.dart b/mobile/apps/photos/lib/models/search/search_types.dart index 3485429bc2..e0df25fe2c 100644 --- a/mobile/apps/photos/lib/models/search/search_types.dart +++ b/mobile/apps/photos/lib/models/search/search_types.dart @@ -44,8 +44,10 @@ enum SectionType { face, magic, location, - // includes year, month , day, event ResultType - moment, + + /// WARNING: Not for production purposes, only kept for debugging memories + memoriesDebug, + album, // People section shows the files shared by other persons contacts, @@ -60,8 +62,8 @@ extension SectionTypeExtensions on SectionType { return S.of(context).people; case SectionType.magic: return S.of(context).discover; - case SectionType.moment: - return S.of(context).moments; + case SectionType.memoriesDebug: + return "Debug memories (internal)"; case SectionType.location: return S.of(context).locations; case SectionType.contacts: @@ -79,8 +81,8 @@ extension SectionTypeExtensions on SectionType { return S.of(context).searchPersonsEmptySection; case SectionType.magic: return S.of(context).searchDiscoverEmptySection; - case SectionType.moment: - return S.of(context).searchDatesEmptySection; + case SectionType.memoriesDebug: + return "For debugging for internal users only"; case SectionType.location: return S.of(context).searchLocationEmptySection; case SectionType.contacts: @@ -98,7 +100,7 @@ extension SectionTypeExtensions on SectionType { switch (this) { case SectionType.face: case SectionType.magic: - case SectionType.moment: + case SectionType.memoriesDebug: case SectionType.fileTypesAndExtension: return false; case SectionType.location: @@ -111,14 +113,14 @@ extension SectionTypeExtensions on SectionType { bool get sortByName => this != SectionType.face && this != SectionType.magic && - this != SectionType.moment && + this != SectionType.memoriesDebug && this != SectionType.contacts; bool get isEmptyCTAVisible { switch (this) { case SectionType.face: case SectionType.magic: - case SectionType.moment: + case SectionType.memoriesDebug: case SectionType.fileTypesAndExtension: return false; case SectionType.location: @@ -136,8 +138,8 @@ extension SectionTypeExtensions on SectionType { case SectionType.magic: // todo: later return "temp"; - case SectionType.moment: - return S.of(context).addNew; + case SectionType.memoriesDebug: + return "Test memories"; case SectionType.location: return S.of(context).addNew; case SectionType.contacts: @@ -155,7 +157,7 @@ extension SectionTypeExtensions on SectionType { return Icons.adaptive.arrow_forward_outlined; case SectionType.magic: return null; - case SectionType.moment: + case SectionType.memoriesDebug: return null; case SectionType.location: return Icons.add_location_alt_outlined; @@ -234,13 +236,11 @@ extension SectionTypeExtensions on SectionType { return SearchService.instance.getAllFace(limit); case SectionType.magic: return SearchService.instance.getMagicSectionResults(context!); - - case SectionType.moment: - if (flagService.internalUser) { + case SectionType.memoriesDebug: + if (flagService.internalUser && localSettings.isDebugMemoriesEnabled) { return SearchService.instance.smartMemories(context!, limit); } - return SearchService.instance.getRandomMomentsSearchResults(context!); - + return Future.value([]); case SectionType.location: return SearchService.instance.getAllLocationTags(limit); diff --git a/mobile/apps/photos/lib/ui/viewer/search_tab/moments_section.dart b/mobile/apps/photos/lib/ui/viewer/search_tab/moments_section.dart index 8ac738d70e..85496fbc90 100644 --- a/mobile/apps/photos/lib/ui/viewer/search_tab/moments_section.dart +++ b/mobile/apps/photos/lib/ui/viewer/search_tab/moments_section.dart @@ -33,11 +33,11 @@ class _MomentsSectionState extends State { super.initState(); _momentsSearchResults = widget.momentsSearchResults; - final streamsToListenTo = SectionType.moment.sectionUpdateEvents(); + final streamsToListenTo = SectionType.memoriesDebug.sectionUpdateEvents(); for (Stream stream in streamsToListenTo) { streamSubscriptions.add( stream.listen((event) async { - _momentsSearchResults = (await SectionType.moment.getData( + _momentsSearchResults = (await SectionType.memoriesDebug.getData( context, limit: kSearchSectionLimit, )) as List; @@ -74,14 +74,14 @@ class _MomentsSectionState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - SectionType.moment.sectionTitle(context), + SectionType.memoriesDebug.sectionTitle(context), style: textTheme.largeBold, ), const SizedBox(height: 24), Padding( padding: const EdgeInsets.only(left: 4), child: Text( - SectionType.moment.getEmptyStateText(context), + SectionType.memoriesDebug.getEmptyStateText(context), style: textTheme.smallMuted, ), ), @@ -89,7 +89,7 @@ class _MomentsSectionState extends State { ), ), const SizedBox(width: 8), - const SearchSectionEmptyCTAIcon(SectionType.moment), + const SearchSectionEmptyCTAIcon(SectionType.memoriesDebug), ], ), ); @@ -100,7 +100,7 @@ class _MomentsSectionState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ SectionHeader( - SectionType.moment, + SectionType.memoriesDebug, hasMore: (_momentsSearchResults.length >= kSearchSectionLimit - 1), ), diff --git a/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart b/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart index 64643232c3..935e5c8064 100644 --- a/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart +++ b/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart @@ -130,11 +130,16 @@ class _AllSearchSectionsState extends State { snapshot.data!.elementAt(index) as List, ); - case SectionType.moment: - return MomentsSection( - snapshot.data!.elementAt(index) - as List, - ); + case SectionType.memoriesDebug: + if (flagService.internalUser && + localSettings.isDebugMemoriesEnabled) { + return MomentsSection( + snapshot.data!.elementAt(index) + as List, + ); + } else { + return const SizedBox.shrink(); + } case SectionType.location: return LocationsSection( snapshot.data!.elementAt(index) diff --git a/mobile/apps/photos/lib/utils/local_settings.dart b/mobile/apps/photos/lib/utils/local_settings.dart index 4133bf0087..b5f0031152 100644 --- a/mobile/apps/photos/lib/utils/local_settings.dart +++ b/mobile/apps/photos/lib/utils/local_settings.dart @@ -26,6 +26,7 @@ class LocalSettings { static const kRateUsShownCount = "rate_us_shown_count"; static const kEnableMultiplePart = "ls.enable_multiple_part"; static const kCuratedMemoriesEnabled = "ls.curated_memories_enabled"; + static const _kDebugMemoriesEnabled = "ls.debug_memories_enabled"; static const kOnThisDayNotificationsEnabled = "ls.on_this_day_notifications_enabled"; static const kBirthdayNotificationsEnabled = @@ -118,11 +119,19 @@ class LocalSettings { bool get isSmartMemoriesEnabled => _prefs.getBool(kCuratedMemoriesEnabled) ?? true; + bool get isDebugMemoriesEnabled => + _prefs.getBool(_kDebugMemoriesEnabled) ?? false; + Future setSmartMemories(bool value) async { await _prefs.setBool(kCuratedMemoriesEnabled, value); return value; } + Future toggleDebugMemories() async { + await _prefs.setBool(_kDebugMemoriesEnabled, !isDebugMemoriesEnabled); + return isDebugMemoriesEnabled; + } + bool get isOnThisDayNotificationsEnabled => _prefs.getBool(kOnThisDayNotificationsEnabled) ?? true; From 86f14f985becce0b91a053031d5d163ceadd5288 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Mon, 14 Jul 2025 14:46:18 +0200 Subject: [PATCH 17/81] Option to debug memories --- .../settings/debug/ml_debug_section_widget.dart | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart b/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart index 7cffcf77f0..ba0d300442 100644 --- a/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart +++ b/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart @@ -431,6 +431,23 @@ class _MLDebugSectionWidgetState extends State { }, ), sectionOptionSpacing, + MenuItemWidget( + captionedTextWidget: const CaptionedTextWidget( + title: "Debug memories section", + ), + trailingWidget: ToggleSwitchWidget( + value: () => localSettings.isDebugMemoriesEnabled, + onChanged: () async { + await localSettings.toggleDebugMemories(); + if (mounted) { + setState(() {}); + } + }, + ), + singleBorderRadius: 8, + isGestureDetectorDisabled: true, + ), + sectionOptionSpacing, MenuItemWidget( captionedTextWidget: const CaptionedTextWidget( title: "Sync person mappings ", From 1c780c4b0207e236c411063d7d33988402423ebc Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Mon, 14 Jul 2025 14:52:58 +0200 Subject: [PATCH 18/81] Rename --- ...oments_section.dart => memories_debug_section.dart} | 10 +++++----- .../photos/lib/ui/viewer/search_tab/search_tab.dart | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) rename mobile/apps/photos/lib/ui/viewer/search_tab/{moments_section.dart => memories_debug_section.dart} (96%) diff --git a/mobile/apps/photos/lib/ui/viewer/search_tab/moments_section.dart b/mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart similarity index 96% rename from mobile/apps/photos/lib/ui/viewer/search_tab/moments_section.dart rename to mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart index 85496fbc90..98dddae6a1 100644 --- a/mobile/apps/photos/lib/ui/viewer/search_tab/moments_section.dart +++ b/mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart @@ -16,15 +16,15 @@ import "package:photos/ui/viewer/search/search_section_cta.dart"; import "package:photos/ui/viewer/search_tab/section_header.dart"; import "package:photos/utils/navigation_util.dart"; -class MomentsSection extends StatefulWidget { +class MemoriesDebugSection extends StatefulWidget { final List momentsSearchResults; - const MomentsSection(this.momentsSearchResults, {super.key}); + const MemoriesDebugSection(this.momentsSearchResults, {super.key}); @override - State createState() => _MomentsSectionState(); + State createState() => _MemoriesDebugSectionState(); } -class _MomentsSectionState extends State { +class _MemoriesDebugSectionState extends State { late List _momentsSearchResults; final streamSubscriptions = []; @@ -56,7 +56,7 @@ class _MomentsSectionState extends State { } @override - void didUpdateWidget(covariant MomentsSection oldWidget) { + void didUpdateWidget(covariant MemoriesDebugSection oldWidget) { super.didUpdateWidget(oldWidget); _momentsSearchResults = widget.momentsSearchResults; } diff --git a/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart b/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart index 935e5c8064..e849c2ead2 100644 --- a/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart +++ b/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart @@ -19,7 +19,7 @@ import 'package:photos/ui/viewer/search_tab/albums_section.dart'; import "package:photos/ui/viewer/search_tab/file_type_section.dart"; import "package:photos/ui/viewer/search_tab/locations_section.dart"; import "package:photos/ui/viewer/search_tab/magic_section.dart"; -import "package:photos/ui/viewer/search_tab/moments_section.dart"; +import "package:photos/ui/viewer/search_tab/memories_debug_section.dart"; import "package:photos/ui/viewer/search_tab/people_section.dart"; class SearchTab extends StatefulWidget { @@ -133,7 +133,7 @@ class _AllSearchSectionsState extends State { case SectionType.memoriesDebug: if (flagService.internalUser && localSettings.isDebugMemoriesEnabled) { - return MomentsSection( + return MemoriesDebugSection( snapshot.data!.elementAt(index) as List, ); From 82cc0559b41c865b615fa312d27ed705d14c0919 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Mon, 14 Jul 2025 14:53:16 +0200 Subject: [PATCH 19/81] Remove old moments calculation logic --- .../photos/lib/services/search_service.dart | 159 ------------------ 1 file changed, 159 deletions(-) diff --git a/mobile/apps/photos/lib/services/search_service.dart b/mobile/apps/photos/lib/services/search_service.dart index f0429ed947..30ef268bf2 100644 --- a/mobile/apps/photos/lib/services/search_service.dart +++ b/mobile/apps/photos/lib/services/search_service.dart @@ -3,7 +3,6 @@ import "dart:math"; import "package:flutter/cupertino.dart"; import "package:flutter/material.dart"; -import "package:intl/intl.dart"; import 'package:logging/logging.dart'; import "package:path_provider/path_provider.dart"; import "package:photos/core/configuration.dart"; @@ -261,56 +260,6 @@ class SearchService { } } - Future> getRandomMomentsSearchResults( - BuildContext context, - ) async { - try { - final nonNullSearchResults = []; - final randomYear = getRadomYearSearchResult(); - final randomMonth = getRandomMonthSearchResult(context); - final randomDate = getRandomDateResults(context); - final randomHoliday = getRandomHolidaySearchResult(context); - - final searchResults = await Future.wait( - [randomYear, randomMonth, randomDate, randomHoliday], - ); - - for (GenericSearchResult? searchResult in searchResults) { - if (searchResult != null) { - nonNullSearchResults.add(searchResult); - } - } - - return nonNullSearchResults; - } catch (e) { - _logger.severe("Error getting RandomMomentsSearchResult", e); - return []; - } - } - - Future getRadomYearSearchResult() async { - for (var yearData in YearsData.instance.yearsData..shuffle()) { - final List filesInYear = - await _getFilesInYear(yearData.duration); - if (filesInYear.isNotEmpty) { - return GenericSearchResult( - ResultType.year, - yearData.year, - filesInYear, - hierarchicalSearchFilter: TopLevelGenericFilter( - filterName: yearData.year, - occurrence: kMostRelevantFilter, - filterResultType: ResultType.year, - matchedUploadedIDs: filesToUploadedFileIDs(filesInYear), - filterIcon: Icons.calendar_month_outlined, - ), - ); - } - } - //todo this throws error - return null; - } - Future> getMonthSearchResults( BuildContext context, String query, @@ -343,35 +292,6 @@ class SearchService { return searchResults; } - Future getRandomMonthSearchResult( - BuildContext context, - ) async { - final months = getMonthData(context)..shuffle(); - for (MonthData month in months) { - final matchedFiles = - await FilesDB.instance.getFilesCreatedWithinDurations( - _getDurationsOfMonthInEveryYear(month.monthNumber), - ignoreCollections(), - order: 'DESC', - ); - if (matchedFiles.isNotEmpty) { - return GenericSearchResult( - ResultType.month, - month.name, - matchedFiles, - hierarchicalSearchFilter: TopLevelGenericFilter( - filterName: month.name, - occurrence: kMostRelevantFilter, - filterResultType: ResultType.month, - matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), - filterIcon: Icons.calendar_month_outlined, - ), - ); - } - } - return null; - } - Future> getHolidaySearchResults( BuildContext context, String query, @@ -411,35 +331,6 @@ class SearchService { return searchResults; } - Future getRandomHolidaySearchResult( - BuildContext context, - ) async { - final holidays = getHolidays(context)..shuffle(); - for (var holiday in holidays) { - final matchedFiles = - await FilesDB.instance.getFilesCreatedWithinDurations( - _getDurationsForCalendarDateInEveryYear(holiday.day, holiday.month), - ignoreCollections(), - order: 'DESC', - ); - if (matchedFiles.isNotEmpty) { - return GenericSearchResult( - ResultType.event, - holiday.name, - matchedFiles, - hierarchicalSearchFilter: TopLevelGenericFilter( - filterName: holiday.name, - occurrence: kMostRelevantFilter, - filterResultType: ResultType.event, - matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), - filterIcon: Icons.event_outlined, - ), - ); - } - } - return null; - } - Future> getFileTypeResults( BuildContext context, String query, @@ -1334,56 +1225,6 @@ class SearchService { return searchResults; } - Future getRandomDateResults( - BuildContext context, - ) async { - final allFiles = await getAllFilesForSearch(); - if (allFiles.isEmpty) return null; - - final length = allFiles.length; - final randomFile = allFiles[Random().nextInt(length)]; - final creationTime = randomFile.creationTime!; - - final originalDateTime = DateTime.fromMicrosecondsSinceEpoch(creationTime); - final startOfDay = DateTime( - originalDateTime.year, - originalDateTime.month, - originalDateTime.day, - ); - - final endOfDay = DateTime( - originalDateTime.year, - originalDateTime.month, - originalDateTime.day + 1, - ); - - final durationOfDay = [ - startOfDay.microsecondsSinceEpoch, - endOfDay.microsecondsSinceEpoch, - ]; - - final matchedFiles = await FilesDB.instance.getFilesCreatedWithinDurations( - [durationOfDay], - ignoreCollections(), - order: 'DESC', - ); - - final name = DateFormat.yMMMd(Localizations.localeOf(context).languageCode) - .format(originalDateTime.toLocal()); - return GenericSearchResult( - ResultType.event, - name, - matchedFiles, - hierarchicalSearchFilter: TopLevelGenericFilter( - filterName: name, - occurrence: kMostRelevantFilter, - filterResultType: ResultType.event, - matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), - filterIcon: Icons.event_outlined, - ), - ); - } - Future> getContactSearchResults( String query, ) async { From b8d69e79f061c7225d982088fd0fe6089c304089 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Tue, 15 Jul 2025 11:51:23 +0200 Subject: [PATCH 20/81] Add memories debug to debug section --- .../debug/ml_debug_section_widget.dart | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart b/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart index ba0d300442..902b2f0a9a 100644 --- a/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart +++ b/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart @@ -2,16 +2,19 @@ import "dart:async"; import 'package:flutter/material.dart'; import "package:logging/logging.dart"; +import "package:photos/core/constants.dart"; import "package:photos/core/event_bus.dart"; import "package:photos/db/ml/db.dart"; import "package:photos/events/people_changed_event.dart"; import "package:photos/models/ml/face/person.dart"; +import "package:photos/models/search/generic_search_result.dart"; import "package:photos/service_locator.dart"; import "package:photos/services/machine_learning/face_ml/person/person_service.dart"; import "package:photos/services/machine_learning/ml_indexing_isolate.dart"; import 'package:photos/services/machine_learning/ml_service.dart'; import "package:photos/services/machine_learning/semantic_search/semantic_search_service.dart"; import "package:photos/services/notification_service.dart"; +import "package:photos/services/search_service.dart"; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/components/captioned_text_widget.dart'; import 'package:photos/ui/components/expandable_menu_item_widget.dart'; @@ -19,6 +22,7 @@ import 'package:photos/ui/components/menu_item_widget/menu_item_widget.dart'; import "package:photos/ui/components/toggle_switch_widget.dart"; import 'package:photos/ui/notification/toast.dart'; import 'package:photos/ui/settings/common_settings.dart'; +import "package:photos/ui/viewer/search_tab/memories_debug_section.dart"; import "package:photos/utils/dialog_util.dart"; import "package:photos/utils/ml_util.dart"; @@ -32,6 +36,7 @@ class MLDebugSectionWidget extends StatefulWidget { class _MLDebugSectionWidgetState extends State { Timer? _timer; bool isExpanded = false; + bool _showMemoriesDebugSection = false; final Logger logger = Logger("MLDebugSectionWidget"); late final mlDataDB = MLDataDB.instance; @override @@ -431,23 +436,6 @@ class _MLDebugSectionWidgetState extends State { }, ), sectionOptionSpacing, - MenuItemWidget( - captionedTextWidget: const CaptionedTextWidget( - title: "Debug memories section", - ), - trailingWidget: ToggleSwitchWidget( - value: () => localSettings.isDebugMemoriesEnabled, - onChanged: () async { - await localSettings.toggleDebugMemories(); - if (mounted) { - setState(() {}); - } - }, - ), - singleBorderRadius: 8, - isGestureDetectorDisabled: true, - ), - sectionOptionSpacing, MenuItemWidget( captionedTextWidget: const CaptionedTextWidget( title: "Sync person mappings ", @@ -595,6 +583,36 @@ class _MLDebugSectionWidgetState extends State { ); }, ), + sectionOptionSpacing, + MenuItemWidget( + captionedTextWidget: const CaptionedTextWidget( + title: "Toggle memories section", + ), + trailingWidget: ToggleSwitchWidget( + value: () => _showMemoriesDebugSection, + onChanged: () async { + _showMemoriesDebugSection = !_showMemoriesDebugSection; + if (mounted) { + setState(() {}); + } + }, + ), + singleBorderRadius: 8, + isGestureDetectorDisabled: true, + ), + if (_showMemoriesDebugSection) sectionOptionSpacing, + if (_showMemoriesDebugSection) + FutureBuilder>( + future: SearchService.instance + .smartMemories(context, kSearchSectionLimit), + builder: (context, snapshot) { + if (snapshot.hasData) { + final memories = snapshot.data!; + return MemoriesDebugSection(memories); + } + return const SizedBox.shrink(); + }, + ), ], ); } From 9696409b01ca2fcd7cf8746fbc9ee75dd3f008d4 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Tue, 15 Jul 2025 13:16:56 +0200 Subject: [PATCH 21/81] Remove memories debug from sections types --- .../lib/models/search/search_types.dart | 21 ------ .../debug/ml_debug_section_widget.dart | 16 ++++- .../search_tab/memories_debug_section.dart | 70 ++++++++++++------- .../lib/ui/viewer/search_tab/search_tab.dart | 12 ---- .../apps/photos/lib/utils/local_settings.dart | 9 --- 5 files changed, 56 insertions(+), 72 deletions(-) diff --git a/mobile/apps/photos/lib/models/search/search_types.dart b/mobile/apps/photos/lib/models/search/search_types.dart index e0df25fe2c..eb0cd0ea85 100644 --- a/mobile/apps/photos/lib/models/search/search_types.dart +++ b/mobile/apps/photos/lib/models/search/search_types.dart @@ -13,7 +13,6 @@ import "package:photos/models/collection/collection.dart"; import "package:photos/models/collection/collection_items.dart"; import "package:photos/models/search/search_result.dart"; import "package:photos/models/typedefs.dart"; -import "package:photos/service_locator.dart"; import "package:photos/services/collections_service.dart"; import "package:photos/services/search_service.dart"; import "package:photos/ui/viewer/gallery/collection_page.dart"; @@ -44,10 +43,6 @@ enum SectionType { face, magic, location, - - /// WARNING: Not for production purposes, only kept for debugging memories - memoriesDebug, - album, // People section shows the files shared by other persons contacts, @@ -62,8 +57,6 @@ extension SectionTypeExtensions on SectionType { return S.of(context).people; case SectionType.magic: return S.of(context).discover; - case SectionType.memoriesDebug: - return "Debug memories (internal)"; case SectionType.location: return S.of(context).locations; case SectionType.contacts: @@ -81,8 +74,6 @@ extension SectionTypeExtensions on SectionType { return S.of(context).searchPersonsEmptySection; case SectionType.magic: return S.of(context).searchDiscoverEmptySection; - case SectionType.memoriesDebug: - return "For debugging for internal users only"; case SectionType.location: return S.of(context).searchLocationEmptySection; case SectionType.contacts: @@ -100,7 +91,6 @@ extension SectionTypeExtensions on SectionType { switch (this) { case SectionType.face: case SectionType.magic: - case SectionType.memoriesDebug: case SectionType.fileTypesAndExtension: return false; case SectionType.location: @@ -113,14 +103,12 @@ extension SectionTypeExtensions on SectionType { bool get sortByName => this != SectionType.face && this != SectionType.magic && - this != SectionType.memoriesDebug && this != SectionType.contacts; bool get isEmptyCTAVisible { switch (this) { case SectionType.face: case SectionType.magic: - case SectionType.memoriesDebug: case SectionType.fileTypesAndExtension: return false; case SectionType.location: @@ -138,8 +126,6 @@ extension SectionTypeExtensions on SectionType { case SectionType.magic: // todo: later return "temp"; - case SectionType.memoriesDebug: - return "Test memories"; case SectionType.location: return S.of(context).addNew; case SectionType.contacts: @@ -157,8 +143,6 @@ extension SectionTypeExtensions on SectionType { return Icons.adaptive.arrow_forward_outlined; case SectionType.magic: return null; - case SectionType.memoriesDebug: - return null; case SectionType.location: return Icons.add_location_alt_outlined; case SectionType.contacts: @@ -236,11 +220,6 @@ extension SectionTypeExtensions on SectionType { return SearchService.instance.getAllFace(limit); case SectionType.magic: return SearchService.instance.getMagicSectionResults(context!); - case SectionType.memoriesDebug: - if (flagService.internalUser && localSettings.isDebugMemoriesEnabled) { - return SearchService.instance.smartMemories(context!, limit); - } - return Future.value([]); case SectionType.location: return SearchService.instance.getAllLocationTags(limit); diff --git a/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart b/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart index 902b2f0a9a..35e98683ba 100644 --- a/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart +++ b/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart @@ -37,6 +37,7 @@ class _MLDebugSectionWidgetState extends State { Timer? _timer; bool isExpanded = false; bool _showMemoriesDebugSection = false; + bool _showAllMemories = false; final Logger logger = Logger("MLDebugSectionWidget"); late final mlDataDB = MLDataDB.instance; @override @@ -603,12 +604,21 @@ class _MLDebugSectionWidgetState extends State { if (_showMemoriesDebugSection) sectionOptionSpacing, if (_showMemoriesDebugSection) FutureBuilder>( - future: SearchService.instance - .smartMemories(context, kSearchSectionLimit), + key: ValueKey(_showAllMemories), + future: SearchService.instance.smartMemories( + context, + _showAllMemories ? null : kSearchSectionLimit, + ), builder: (context, snapshot) { if (snapshot.hasData) { final memories = snapshot.data!; - return MemoriesDebugSection(memories); + return MemoriesDebugSection(memories, () async { + _showAllMemories = !_showAllMemories; + _timer?.cancel(); + if (mounted) { + setState(() {}); + } + }); } return const SizedBox.shrink(); }, diff --git a/mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart b/mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart index 98dddae6a1..c45a88d2c3 100644 --- a/mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart +++ b/mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart @@ -3,22 +3,22 @@ import "dart:math"; import "package:figma_squircle/figma_squircle.dart"; import "package:flutter/material.dart"; -import "package:photos/core/constants.dart"; -import "package:photos/events/event.dart"; import "package:photos/models/search/generic_search_result.dart"; import "package:photos/models/search/recent_searches.dart"; -import "package:photos/models/search/search_types.dart"; import "package:photos/theme/ente_theme.dart"; import "package:photos/ui/viewer/file/no_thumbnail_widget.dart"; import "package:photos/ui/viewer/file/thumbnail_widget.dart"; import "package:photos/ui/viewer/search/result/search_result_page.dart"; -import "package:photos/ui/viewer/search/search_section_cta.dart"; -import "package:photos/ui/viewer/search_tab/section_header.dart"; import "package:photos/utils/navigation_util.dart"; class MemoriesDebugSection extends StatefulWidget { final List momentsSearchResults; - const MemoriesDebugSection(this.momentsSearchResults, {super.key}); + final VoidCallback onTapCallback; + const MemoriesDebugSection( + this.momentsSearchResults, + this.onTapCallback, { + super.key, + }); @override State createState() => _MemoriesDebugSectionState(); @@ -32,19 +32,6 @@ class _MemoriesDebugSectionState extends State { void initState() { super.initState(); _momentsSearchResults = widget.momentsSearchResults; - - final streamsToListenTo = SectionType.memoriesDebug.sectionUpdateEvents(); - for (Stream stream in streamsToListenTo) { - streamSubscriptions.add( - stream.listen((event) async { - _momentsSearchResults = (await SectionType.memoriesDebug.getData( - context, - limit: kSearchSectionLimit, - )) as List; - setState(() {}); - }), - ); - } } @override @@ -74,14 +61,14 @@ class _MemoriesDebugSectionState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - SectionType.memoriesDebug.sectionTitle(context), + "Smart memories debug (I)", style: textTheme.largeBold, ), const SizedBox(height: 24), Padding( padding: const EdgeInsets.only(left: 4), child: Text( - SectionType.memoriesDebug.getEmptyStateText(context), + "Test memories", style: textTheme.smallMuted, ), ), @@ -89,7 +76,6 @@ class _MemoriesDebugSectionState extends State { ), ), const SizedBox(width: 8), - const SearchSectionEmptyCTAIcon(SectionType.memoriesDebug), ], ), ); @@ -99,11 +85,7 @@ class _MemoriesDebugSectionState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SectionHeader( - SectionType.memoriesDebug, - hasMore: - (_momentsSearchResults.length >= kSearchSectionLimit - 1), - ), + _SectionHeader(widget.onTapCallback), const SizedBox(height: 2), SizedBox( child: SingleChildScrollView( @@ -129,6 +111,40 @@ class _MemoriesDebugSectionState extends State { } } +class _SectionHeader extends StatelessWidget { + final VoidCallback onTapCallback; + const _SectionHeader(this.onTapCallback); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTapCallback, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.all(12), + child: Text( + "Smart memories debug (I)", + style: getEnteTextTheme(context).largeBold, + ), + ), + Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.fromLTRB(24, 12, 12, 12), + child: Icon( + Icons.chevron_right_outlined, + color: getEnteColorScheme(context).blurStrokePressed, + ), + ), + ), + ], + ), + ); + } +} + class MomentRecommendation extends StatelessWidget { static const _width = 100.0; static const _height = 145.0; diff --git a/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart b/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart index e849c2ead2..81359099cc 100644 --- a/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart +++ b/mobile/apps/photos/lib/ui/viewer/search_tab/search_tab.dart @@ -19,7 +19,6 @@ import 'package:photos/ui/viewer/search_tab/albums_section.dart'; import "package:photos/ui/viewer/search_tab/file_type_section.dart"; import "package:photos/ui/viewer/search_tab/locations_section.dart"; import "package:photos/ui/viewer/search_tab/magic_section.dart"; -import "package:photos/ui/viewer/search_tab/memories_debug_section.dart"; import "package:photos/ui/viewer/search_tab/people_section.dart"; class SearchTab extends StatefulWidget { @@ -125,21 +124,10 @@ class _AllSearchSectionsState extends State { as List, ); case SectionType.album: - // return const SizedBox.shrink(); return AlbumsSection( snapshot.data!.elementAt(index) as List, ); - case SectionType.memoriesDebug: - if (flagService.internalUser && - localSettings.isDebugMemoriesEnabled) { - return MemoriesDebugSection( - snapshot.data!.elementAt(index) - as List, - ); - } else { - return const SizedBox.shrink(); - } case SectionType.location: return LocationsSection( snapshot.data!.elementAt(index) diff --git a/mobile/apps/photos/lib/utils/local_settings.dart b/mobile/apps/photos/lib/utils/local_settings.dart index b5f0031152..4133bf0087 100644 --- a/mobile/apps/photos/lib/utils/local_settings.dart +++ b/mobile/apps/photos/lib/utils/local_settings.dart @@ -26,7 +26,6 @@ class LocalSettings { static const kRateUsShownCount = "rate_us_shown_count"; static const kEnableMultiplePart = "ls.enable_multiple_part"; static const kCuratedMemoriesEnabled = "ls.curated_memories_enabled"; - static const _kDebugMemoriesEnabled = "ls.debug_memories_enabled"; static const kOnThisDayNotificationsEnabled = "ls.on_this_day_notifications_enabled"; static const kBirthdayNotificationsEnabled = @@ -119,19 +118,11 @@ class LocalSettings { bool get isSmartMemoriesEnabled => _prefs.getBool(kCuratedMemoriesEnabled) ?? true; - bool get isDebugMemoriesEnabled => - _prefs.getBool(_kDebugMemoriesEnabled) ?? false; - Future setSmartMemories(bool value) async { await _prefs.setBool(kCuratedMemoriesEnabled, value); return value; } - Future toggleDebugMemories() async { - await _prefs.setBool(_kDebugMemoriesEnabled, !isDebugMemoriesEnabled); - return isDebugMemoriesEnabled; - } - bool get isOnThisDayNotificationsEnabled => _prefs.getBool(kOnThisDayNotificationsEnabled) ?? true; From f06314fb13d2dc5c995afaf1d118cec519afdad5 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Tue, 15 Jul 2025 14:00:04 +0200 Subject: [PATCH 22/81] Move file --- .../debug/ml_debug_section_widget.dart | 2 +- .../search_tab/memories_debug_section.dart | 275 ------------------ 2 files changed, 1 insertion(+), 276 deletions(-) delete mode 100644 mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart diff --git a/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart b/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart index 35e98683ba..fd83bcc7e0 100644 --- a/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart +++ b/mobile/apps/photos/lib/ui/settings/debug/ml_debug_section_widget.dart @@ -22,7 +22,7 @@ import 'package:photos/ui/components/menu_item_widget/menu_item_widget.dart'; import "package:photos/ui/components/toggle_switch_widget.dart"; import 'package:photos/ui/notification/toast.dart'; import 'package:photos/ui/settings/common_settings.dart'; -import "package:photos/ui/viewer/search_tab/memories_debug_section.dart"; +import "package:photos/ui/settings/debug/memories_debug_section.dart"; import "package:photos/utils/dialog_util.dart"; import "package:photos/utils/ml_util.dart"; diff --git a/mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart b/mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart deleted file mode 100644 index c45a88d2c3..0000000000 --- a/mobile/apps/photos/lib/ui/viewer/search_tab/memories_debug_section.dart +++ /dev/null @@ -1,275 +0,0 @@ -import "dart:async"; -import "dart:math"; - -import "package:figma_squircle/figma_squircle.dart"; -import "package:flutter/material.dart"; -import "package:photos/models/search/generic_search_result.dart"; -import "package:photos/models/search/recent_searches.dart"; -import "package:photos/theme/ente_theme.dart"; -import "package:photos/ui/viewer/file/no_thumbnail_widget.dart"; -import "package:photos/ui/viewer/file/thumbnail_widget.dart"; -import "package:photos/ui/viewer/search/result/search_result_page.dart"; -import "package:photos/utils/navigation_util.dart"; - -class MemoriesDebugSection extends StatefulWidget { - final List momentsSearchResults; - final VoidCallback onTapCallback; - const MemoriesDebugSection( - this.momentsSearchResults, - this.onTapCallback, { - super.key, - }); - - @override - State createState() => _MemoriesDebugSectionState(); -} - -class _MemoriesDebugSectionState extends State { - late List _momentsSearchResults; - final streamSubscriptions = []; - - @override - void initState() { - super.initState(); - _momentsSearchResults = widget.momentsSearchResults; - } - - @override - void dispose() { - for (var subscriptions in streamSubscriptions) { - subscriptions.cancel(); - } - super.dispose(); - } - - @override - void didUpdateWidget(covariant MemoriesDebugSection oldWidget) { - super.didUpdateWidget(oldWidget); - _momentsSearchResults = widget.momentsSearchResults; - } - - @override - Widget build(BuildContext context) { - if (_momentsSearchResults.isEmpty) { - final textTheme = getEnteTextTheme(context); - return Padding( - padding: const EdgeInsets.only(left: 12, right: 8), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Smart memories debug (I)", - style: textTheme.largeBold, - ), - const SizedBox(height: 24), - Padding( - padding: const EdgeInsets.only(left: 4), - child: Text( - "Test memories", - style: textTheme.smallMuted, - ), - ), - ], - ), - ), - const SizedBox(width: 8), - ], - ), - ); - } else { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _SectionHeader(widget.onTapCallback), - const SizedBox(height: 2), - SizedBox( - child: SingleChildScrollView( - clipBehavior: Clip.none, - padding: const EdgeInsets.symmetric(horizontal: 4.5), - physics: const BouncingScrollPhysics(), - scrollDirection: Axis.horizontal, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: _momentsSearchResults - .map( - (momentSearchResult) => - MomentRecommendation(momentSearchResult), - ) - .toList(), - ), - ), - ), - ], - ), - ); - } - } -} - -class _SectionHeader extends StatelessWidget { - final VoidCallback onTapCallback; - const _SectionHeader(this.onTapCallback); - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: onTapCallback, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.all(12), - child: Text( - "Smart memories debug (I)", - style: getEnteTextTheme(context).largeBold, - ), - ), - Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.fromLTRB(24, 12, 12, 12), - child: Icon( - Icons.chevron_right_outlined, - color: getEnteColorScheme(context).blurStrokePressed, - ), - ), - ), - ], - ), - ); - } -} - -class MomentRecommendation extends StatelessWidget { - static const _width = 100.0; - static const _height = 145.0; - static const _borderWidth = 1.0; - static const _cornerRadius = 5.0; - static const _cornerSmoothing = 1.0; - final GenericSearchResult momentSearchResult; - const MomentRecommendation(this.momentSearchResult, {super.key}); - - @override - Widget build(BuildContext context) { - final heroTag = momentSearchResult.heroTag() + - (momentSearchResult.previewThumbnail()?.tag ?? ""); - final enteTextTheme = getEnteTextTheme(context); - return Padding( - padding: EdgeInsets.symmetric(horizontal: max(2.5 - _borderWidth, 0)), - child: GestureDetector( - onTap: () { - RecentSearches().add(momentSearchResult.name()); - if (momentSearchResult.onResultTap != null) { - momentSearchResult.onResultTap!(context); - } else { - routeToPage( - context, - SearchResultPage(momentSearchResult), - ); - } - }, - child: SizedBox( - width: _width + _borderWidth * 2, - height: _height + _borderWidth * 2, - child: Stack( - clipBehavior: Clip.none, - alignment: Alignment.center, - children: [ - ClipSmoothRect( - radius: SmoothBorderRadius( - cornerRadius: _cornerRadius + _borderWidth, - cornerSmoothing: _cornerSmoothing, - ), - child: Container( - color: Colors.white.withOpacity(0.16), - width: _width + _borderWidth * 2, - height: _height + _borderWidth * 2, - ), - ), - Container( - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 6.25, - offset: const Offset(-1.25, 2.5), - ), - ], - ), - child: ClipSmoothRect( - radius: SmoothBorderRadius( - cornerRadius: _cornerRadius, - cornerSmoothing: _cornerSmoothing, - ), - child: Stack( - alignment: Alignment.bottomCenter, - clipBehavior: Clip.none, - children: [ - SizedBox( - width: _width, - height: _height, - child: momentSearchResult.previewThumbnail() != null - ? Hero( - tag: heroTag, - child: ThumbnailWidget( - momentSearchResult.previewThumbnail()!, - shouldShowArchiveStatus: false, - shouldShowSyncStatus: false, - ), - ) - : const NoThumbnailWidget(), - ), - Container( - height: 145, - width: 100, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Colors.black.withOpacity(0), - Colors.black.withOpacity(0), - Colors.black.withOpacity(0.5), - ], - stops: const [ - 0, - 0.1, - 1, - ], - ), - ), - ), - ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 76, - ), - child: Padding( - padding: const EdgeInsets.only( - bottom: 8, - ), - child: Text( - momentSearchResult.name(), - style: enteTextTheme.small.copyWith( - color: Colors.white, - ), - maxLines: 3, - overflow: TextOverflow.fade, - ), - ), - ), - ], - ), - ), - ), - ], - ), - ), - ), - ); - } -} From 06d3f679f1efa8377f0efdb920cebf51d38b453a Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Tue, 15 Jul 2025 14:02:17 +0200 Subject: [PATCH 23/81] Complete move --- .../debug/memories_debug_section.dart | 275 ++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 mobile/apps/photos/lib/ui/settings/debug/memories_debug_section.dart diff --git a/mobile/apps/photos/lib/ui/settings/debug/memories_debug_section.dart b/mobile/apps/photos/lib/ui/settings/debug/memories_debug_section.dart new file mode 100644 index 0000000000..c45a88d2c3 --- /dev/null +++ b/mobile/apps/photos/lib/ui/settings/debug/memories_debug_section.dart @@ -0,0 +1,275 @@ +import "dart:async"; +import "dart:math"; + +import "package:figma_squircle/figma_squircle.dart"; +import "package:flutter/material.dart"; +import "package:photos/models/search/generic_search_result.dart"; +import "package:photos/models/search/recent_searches.dart"; +import "package:photos/theme/ente_theme.dart"; +import "package:photos/ui/viewer/file/no_thumbnail_widget.dart"; +import "package:photos/ui/viewer/file/thumbnail_widget.dart"; +import "package:photos/ui/viewer/search/result/search_result_page.dart"; +import "package:photos/utils/navigation_util.dart"; + +class MemoriesDebugSection extends StatefulWidget { + final List momentsSearchResults; + final VoidCallback onTapCallback; + const MemoriesDebugSection( + this.momentsSearchResults, + this.onTapCallback, { + super.key, + }); + + @override + State createState() => _MemoriesDebugSectionState(); +} + +class _MemoriesDebugSectionState extends State { + late List _momentsSearchResults; + final streamSubscriptions = []; + + @override + void initState() { + super.initState(); + _momentsSearchResults = widget.momentsSearchResults; + } + + @override + void dispose() { + for (var subscriptions in streamSubscriptions) { + subscriptions.cancel(); + } + super.dispose(); + } + + @override + void didUpdateWidget(covariant MemoriesDebugSection oldWidget) { + super.didUpdateWidget(oldWidget); + _momentsSearchResults = widget.momentsSearchResults; + } + + @override + Widget build(BuildContext context) { + if (_momentsSearchResults.isEmpty) { + final textTheme = getEnteTextTheme(context); + return Padding( + padding: const EdgeInsets.only(left: 12, right: 8), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Smart memories debug (I)", + style: textTheme.largeBold, + ), + const SizedBox(height: 24), + Padding( + padding: const EdgeInsets.only(left: 4), + child: Text( + "Test memories", + style: textTheme.smallMuted, + ), + ), + ], + ), + ), + const SizedBox(width: 8), + ], + ), + ); + } else { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionHeader(widget.onTapCallback), + const SizedBox(height: 2), + SizedBox( + child: SingleChildScrollView( + clipBehavior: Clip.none, + padding: const EdgeInsets.symmetric(horizontal: 4.5), + physics: const BouncingScrollPhysics(), + scrollDirection: Axis.horizontal, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: _momentsSearchResults + .map( + (momentSearchResult) => + MomentRecommendation(momentSearchResult), + ) + .toList(), + ), + ), + ), + ], + ), + ); + } + } +} + +class _SectionHeader extends StatelessWidget { + final VoidCallback onTapCallback; + const _SectionHeader(this.onTapCallback); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTapCallback, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.all(12), + child: Text( + "Smart memories debug (I)", + style: getEnteTextTheme(context).largeBold, + ), + ), + Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.fromLTRB(24, 12, 12, 12), + child: Icon( + Icons.chevron_right_outlined, + color: getEnteColorScheme(context).blurStrokePressed, + ), + ), + ), + ], + ), + ); + } +} + +class MomentRecommendation extends StatelessWidget { + static const _width = 100.0; + static const _height = 145.0; + static const _borderWidth = 1.0; + static const _cornerRadius = 5.0; + static const _cornerSmoothing = 1.0; + final GenericSearchResult momentSearchResult; + const MomentRecommendation(this.momentSearchResult, {super.key}); + + @override + Widget build(BuildContext context) { + final heroTag = momentSearchResult.heroTag() + + (momentSearchResult.previewThumbnail()?.tag ?? ""); + final enteTextTheme = getEnteTextTheme(context); + return Padding( + padding: EdgeInsets.symmetric(horizontal: max(2.5 - _borderWidth, 0)), + child: GestureDetector( + onTap: () { + RecentSearches().add(momentSearchResult.name()); + if (momentSearchResult.onResultTap != null) { + momentSearchResult.onResultTap!(context); + } else { + routeToPage( + context, + SearchResultPage(momentSearchResult), + ); + } + }, + child: SizedBox( + width: _width + _borderWidth * 2, + height: _height + _borderWidth * 2, + child: Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + ClipSmoothRect( + radius: SmoothBorderRadius( + cornerRadius: _cornerRadius + _borderWidth, + cornerSmoothing: _cornerSmoothing, + ), + child: Container( + color: Colors.white.withOpacity(0.16), + width: _width + _borderWidth * 2, + height: _height + _borderWidth * 2, + ), + ), + Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 6.25, + offset: const Offset(-1.25, 2.5), + ), + ], + ), + child: ClipSmoothRect( + radius: SmoothBorderRadius( + cornerRadius: _cornerRadius, + cornerSmoothing: _cornerSmoothing, + ), + child: Stack( + alignment: Alignment.bottomCenter, + clipBehavior: Clip.none, + children: [ + SizedBox( + width: _width, + height: _height, + child: momentSearchResult.previewThumbnail() != null + ? Hero( + tag: heroTag, + child: ThumbnailWidget( + momentSearchResult.previewThumbnail()!, + shouldShowArchiveStatus: false, + shouldShowSyncStatus: false, + ), + ) + : const NoThumbnailWidget(), + ), + Container( + height: 145, + width: 100, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.black.withOpacity(0), + Colors.black.withOpacity(0), + Colors.black.withOpacity(0.5), + ], + stops: const [ + 0, + 0.1, + 1, + ], + ), + ), + ), + ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 76, + ), + child: Padding( + padding: const EdgeInsets.only( + bottom: 8, + ), + child: Text( + momentSearchResult.name(), + style: enteTextTheme.small.copyWith( + color: Colors.white, + ), + maxLines: 3, + overflow: TextOverflow.fade, + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ); + } +} From 96c22700621797aee055cce333896c044943b69f Mon Sep 17 00:00:00 2001 From: Daniel T Date: Tue, 15 Jul 2025 13:27:31 -0500 Subject: [PATCH 24/81] chore: add custom icon for temu --- mobile/apps/auth/assets/custom-icons/_data/custom-icons.json | 4 ++++ mobile/apps/auth/assets/custom-icons/icons/temu.svg | 2 ++ 2 files changed, 6 insertions(+) create mode 100644 mobile/apps/auth/assets/custom-icons/icons/temu.svg diff --git a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json index 589db8113c..53486c202b 100644 --- a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json +++ b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json @@ -1300,6 +1300,10 @@ "title": "Termius", "hex": "858585" }, + { + "title": "Temu", + "slug": "temu" + }, { "title": "tianyiyun", "altNames": [ diff --git a/mobile/apps/auth/assets/custom-icons/icons/temu.svg b/mobile/apps/auth/assets/custom-icons/icons/temu.svg new file mode 100644 index 0000000000..81e3928b4e --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/temu.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file From 27af2c3bbc28dd2684bf26e8d18f015681b74a9e Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Tue, 15 Jul 2025 22:10:32 +0200 Subject: [PATCH 25/81] Set high minimum for compression --- mobile/apps/photos/lib/utils/image_ml_util.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mobile/apps/photos/lib/utils/image_ml_util.dart b/mobile/apps/photos/lib/utils/image_ml_util.dart index 49471ea87b..ea894c3781 100644 --- a/mobile/apps/photos/lib/utils/image_ml_util.dart +++ b/mobile/apps/photos/lib/utils/image_ml_util.dart @@ -65,6 +65,8 @@ Future decodeImageFromPath( await FlutterImageCompress.compressWithFile( imagePath, format: CompressFormat.jpeg, + minWidth: 8000, // High value to ensure image is not scaled down + minHeight: 8000, // High value to ensure image is not scaled down ); final image = await decodeImageFromData(convertedData!); _logger.info('Conversion successful, jpeg decoded'); From 0f8ea1e814531aa2303a493f24d802bb967788b4 Mon Sep 17 00:00:00 2001 From: Florian Lippert <973586+flol@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:23:33 +0000 Subject: [PATCH 26/81] Make use_path_style_urls and disable_ssl configurable per bucket --- server/pkg/utils/s3config/s3config.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/pkg/utils/s3config/s3config.go b/server/pkg/utils/s3config/s3config.go index 469d3fb632..d0858fc246 100644 --- a/server/pkg/utils/s3config/s3config.go +++ b/server/pkg/utils/s3config/s3config.go @@ -136,12 +136,11 @@ func (config *S3Config) initialize() { Endpoint: aws.String(viper.GetString("s3." + dc + ".endpoint")), Region: aws.String(viper.GetString("s3." + dc + ".region")), } - if usePathStyleURLs { + if usePathStyleURLs || viper.GetBool("s3." + dc + ".use_path_style_urls") || areLocalBuckets { s3Config.S3ForcePathStyle = aws.Bool(true) } - if areLocalBuckets { + if areLocalBuckets || viper.GetBool("s3." + dc + ".disable_ssl") { s3Config.DisableSSL = aws.Bool(true) - s3Config.S3ForcePathStyle = aws.Bool(true) } s3Session, err := session.NewSession(&s3Config) if err != nil { From b68fda70ef75771bfb8c683e229317247f0f361e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 10:02:23 +0530 Subject: [PATCH 27/81] Start deduping --- web/apps/photos/src/components/FileList.tsx | 28 +++--------------- .../components/utils/thumbnail-grid-layout.ts | 29 +++++-------------- 2 files changed, 12 insertions(+), 45 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index b419a81296..c6dfc04278 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -26,6 +26,10 @@ import { StaticThumbnail, } from "ente-new/photos/components/PlaceholderThumbnails"; import { TileBottomTextOverlay } from "ente-new/photos/components/Tiles"; +import { + getFractionFittableColumns, + getShrinkRatio, +} from "ente-new/photos/components/utils/thumbnail-grid-layout"; import { PseudoCollectionID } from "ente-new/photos/services/collection-summary"; import { t } from "i18next"; import memoize from "memoize-one"; @@ -800,30 +804,6 @@ const getTemplateColumns = ( } }; -function getFractionFittableColumns(width: number): number { - return ( - (width - 2 * getGapFromScreenEdge(width) + GAP_BTW_TILES) / - (IMAGE_CONTAINER_MAX_WIDTH + GAP_BTW_TILES) - ); -} - -function getGapFromScreenEdge(width: number) { - if (width > MIN_COLUMNS * IMAGE_CONTAINER_MAX_WIDTH) { - return 24; - } else { - return 4; - } -} - -function getShrinkRatio(width: number, columns: number) { - return ( - (width - - 2 * getGapFromScreenEdge(width) - - (columns - 1) * GAP_BTW_TILES) / - (columns * IMAGE_CONTAINER_MAX_WIDTH) - ); -} - const ListContainer = styled(Box, { shouldForwardProp: (propName) => propName != "gridTemplateColumns", })<{ gridTemplateColumns: string }>` diff --git a/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts b/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts index 62cc057699..9e796ae8f1 100644 --- a/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts +++ b/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts @@ -84,26 +84,13 @@ const IMAGE_CONTAINER_MAX_HEIGHT = 180; const IMAGE_CONTAINER_MAX_WIDTH = 180; const MIN_COLUMNS = 4; -function getFractionFittableColumns(width: number): number { - return ( - (width - 2 * getGapFromScreenEdge(width) + GAP_BTW_TILES) / - (IMAGE_CONTAINER_MAX_WIDTH + GAP_BTW_TILES) - ); -} +export const getFractionFittableColumns = (width: number): number => + (width - 2 * getGapFromScreenEdge(width) + GAP_BTW_TILES) / + (IMAGE_CONTAINER_MAX_WIDTH + GAP_BTW_TILES); -function getGapFromScreenEdge(width: number) { - if (width > MIN_COLUMNS * IMAGE_CONTAINER_MAX_WIDTH) { - return 24; - } else { - return 4; - } -} +export const getGapFromScreenEdge = (width: number) => + width > MIN_COLUMNS * IMAGE_CONTAINER_MAX_WIDTH ? 24 : 4; -function getShrinkRatio(width: number, columns: number) { - return ( - (width - - 2 * getGapFromScreenEdge(width) - - (columns - 1) * GAP_BTW_TILES) / - (columns * IMAGE_CONTAINER_MAX_WIDTH) - ); -} +export const getShrinkRatio = (width: number, columns: number) => + (width - 2 * getGapFromScreenEdge(width) - (columns - 1) * GAP_BTW_TILES) / + (columns * IMAGE_CONTAINER_MAX_WIDTH); From 99a8f5152afcc90de937669a3b2c1bc6794a001b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 10:55:45 +0530 Subject: [PATCH 28/81] Start using the existing function --- web/apps/photos/src/components/FileList.tsx | 53 ++++++++++----------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index c6dfc04278..1685ec9cb3 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -16,7 +16,6 @@ import { fileCreationTime, fileDurationString } from "ente-media/file-metadata"; import { FileType } from "ente-media/file-type"; import { GAP_BTW_TILES, - IMAGE_CONTAINER_MAX_HEIGHT, IMAGE_CONTAINER_MAX_WIDTH, MIN_COLUMNS, } from "ente-new/photos/components/FileList"; @@ -27,7 +26,7 @@ import { } from "ente-new/photos/components/PlaceholderThumbnails"; import { TileBottomTextOverlay } from "ente-new/photos/components/Tiles"; import { - getFractionFittableColumns, + computeThumbnailGridLayoutParams, getShrinkRatio, } from "ente-new/photos/components/utils/thumbnail-grid-layout"; import { PseudoCollectionID } from "ente-new/photos/services/collection-summary"; @@ -51,8 +50,6 @@ import { handleSelectCreatorMulti, } from "utils/photoFrame"; -export const SPACE_BTW_DATES = 44; - /** * A component with an explicit height suitable for being plugged in as the * {@link header} or {@link footer} of the {@link FileList}. @@ -233,18 +230,22 @@ export const FileList: React.FC = ({ const [currentHover, setCurrentHover] = useState(null); const [isShiftKeyPressed, setIsShiftKeyPressed] = useState(false); - const fittableColumns = getFractionFittableColumns(width); - let columns = Math.floor(fittableColumns); - - let skipMerge = false; - if (columns < MIN_COLUMNS) { - columns = MIN_COLUMNS; - skipMerge = true; - } - + const layoutParams = useMemo( + () => computeThumbnailGridLayoutParams(width), + [width], + ); + const { + // containerWidth, + isSmallerLayout, + // paddingInline, + columns, + // itemWidth, + itemHeight, + gap, + } = layoutParams; + // TODO(RE): const shrinkRatio = getShrinkRatio(width, columns); - const listItemHeight = - IMAGE_CONTAINER_MAX_HEIGHT * shrinkRatio + GAP_BTW_TILES; + const listItemHeight = itemHeight + gap; useEffect(() => { // Since width and height are dependencies, there might be too many @@ -267,7 +268,7 @@ export const FileList: React.FC = ({ groupByTime(timeStampList); } - if (!skipMerge) { + if (!isSmallerLayout) { timeStampList = mergeTimeStampList(timeStampList, columns); } @@ -786,17 +787,15 @@ const getTemplateColumns = ( groups?: number[], ): string => { if (groups) { - // need to confirm why this was there - // const sum = groups.reduce((acc, item) => acc + item, 0); - // if (sum < columns) { - // groups[groups.length - 1] += columns - sum; - // } - return groups - .map( - (x) => - `repeat(${x}, ${IMAGE_CONTAINER_MAX_WIDTH * shrinkRatio}px)`, - ) - .join(` ${SPACE_BTW_DATES}px `); + return ( + groups + .map( + (x) => + `repeat(${x}, ${IMAGE_CONTAINER_MAX_WIDTH * shrinkRatio}px)`, + ) + // Space between date groups + .join(` 44px `) + ); } else { return `repeat(${columns},${ IMAGE_CONTAINER_MAX_WIDTH * shrinkRatio From 14bc47c0556f2d46a0fdb9c6ceddd4035df8252c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 12:35:07 +0530 Subject: [PATCH 29/81] Fix regression in date color --- web/apps/photos/src/components/FileList.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 1685ec9cb3..e10d79ea62 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -848,13 +848,15 @@ const asFullSpanListItem = ({ item, ...rest }: FileListHeaderOrFooter) => ({ */ const dateContainerHeight = 48; -const DateContainer = styled(ListItemContainer)` +const DateContainer = styled(ListItemContainer)( + ({ theme }) => ` white-space: nowrap; overflow: hidden; text-overflow: ellipsis; height: ${dateContainerHeight}px; - color: "text.muted"; -`; + color: ${theme.vars.palette.text.muted}; +`, +); const NoFilesContainer = styled(ListItemContainer)` text-align: center; From e3ab4eda159b6a370c4fc62dda451ed5a50936e1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 13:19:54 +0530 Subject: [PATCH 30/81] lp --- web/apps/photos/src/components/FileList.tsx | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index e10d79ea62..8b1fa0e01f 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -28,6 +28,7 @@ import { TileBottomTextOverlay } from "ente-new/photos/components/Tiles"; import { computeThumbnailGridLayoutParams, getShrinkRatio, + type ThumbnailGridLayoutParams, } from "ente-new/photos/components/utils/thumbnail-grid-layout"; import { PseudoCollectionID } from "ente-new/photos/services/collection-summary"; import { t } from "i18next"; @@ -240,12 +241,11 @@ export const FileList: React.FC = ({ // paddingInline, columns, // itemWidth, - itemHeight, - gap, + // itemHeight, + // gap, } = layoutParams; // TODO(RE): - const shrinkRatio = getShrinkRatio(width, columns); - const listItemHeight = itemHeight + gap; + const listItemHeight = layoutParams.itemHeight + layoutParams.gap; useEffect(() => { // Since width and height are dependencies, there might be too many @@ -738,7 +738,8 @@ export const FileList: React.FC = ({ const itemData = createItemData( timeStampList, columns, - shrinkRatio, + layoutParams, + layoutParams.shrinkRatio, renderListItem, ); @@ -866,6 +867,7 @@ const NoFilesContainer = styled(ListItemContainer)` interface ItemData { timeStampList: TimeStampListItem[]; columns: number; + layoutParams: ThumbnailGridLayoutParams; shrinkRatio: number; renderListItem: ( timeStampListItem: TimeStampListItem, @@ -877,12 +879,19 @@ const createItemData = memoize( ( timeStampList: TimeStampListItem[], columns: number, + layoutParams: ThumbnailGridLayoutParams, shrinkRatio: number, renderListItem: ( timeStampListItem: TimeStampListItem, isScrolling?: boolean, ) => React.JSX.Element, - ): ItemData => ({ timeStampList, columns, shrinkRatio, renderListItem }), + ): ItemData => ({ + timeStampList, + columns, + layoutParams, + shrinkRatio, + renderListItem, + }), ); const PhotoListRow = React.memo( From a6e78ab732a86d26f237e24ec8e867526b19876d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 13:44:26 +0530 Subject: [PATCH 31/81] Use layoutParams --- web/apps/photos/src/components/FileList.tsx | 85 +++++++------------ .../components/utils/thumbnail-grid-layout.ts | 6 +- 2 files changed, 32 insertions(+), 59 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 8b1fa0e01f..3083214b90 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -27,7 +27,6 @@ import { import { TileBottomTextOverlay } from "ente-new/photos/components/Tiles"; import { computeThumbnailGridLayoutParams, - getShrinkRatio, type ThumbnailGridLayoutParams, } from "ente-new/photos/components/utils/thumbnail-grid-layout"; import { PseudoCollectionID } from "ente-new/photos/services/collection-summary"; @@ -235,9 +234,10 @@ export const FileList: React.FC = ({ () => computeThumbnailGridLayoutParams(width), [width], ); + const { // containerWidth, - isSmallerLayout, + // isSmallerLayout, // paddingInline, columns, // itemWidth, @@ -262,8 +262,22 @@ export const FileList: React.FC = ({ timeStampList.push(asFullSpanListItem(header)); } + const { isSmallerLayout, columns } = layoutParams; if (disableGrouping) { - noGrouping(timeStampList); + let listItemIndex = columns; + annotatedFiles.forEach((item, index) => { + if (listItemIndex < columns) { + timeStampList[timeStampList.length - 1]!.items!.push(item); + listItemIndex++; + } else { + listItemIndex = 1; + timeStampList.push({ + tag: "file", + items: [item], + itemStartIndex: index, + }); + } + }); } else { groupByTime(timeStampList); } @@ -302,7 +316,7 @@ export const FileList: React.FC = ({ footer, annotatedFiles, disableGrouping, - columns, + layoutParams, ]); useEffect(() => { @@ -348,23 +362,6 @@ export const FileList: React.FC = ({ }); }; - const noGrouping = (timeStampList: TimeStampListItem[]) => { - let listItemIndex = columns; - annotatedFiles.forEach((item, index) => { - if (listItemIndex < columns) { - timeStampList[timeStampList.length - 1]!.items!.push(item); - listItemIndex++; - } else { - listItemIndex = 1; - timeStampList.push({ - tag: "file", - items: [item], - itemStartIndex: index, - }); - } - }); - }; - const getVacuumItem = ( timeStampList: TimeStampListItem[], footerHeight: number, @@ -737,9 +734,7 @@ export const FileList: React.FC = ({ const itemData = createItemData( timeStampList, - columns, layoutParams, - layoutParams.shrinkRatio, renderListItem, ); @@ -783,26 +778,15 @@ const ListItem = styled("div")` `; const getTemplateColumns = ( - columns: number, - shrinkRatio: number, + { columns, itemWidth }: ThumbnailGridLayoutParams, groups?: number[], -): string => { - if (groups) { - return ( - groups - .map( - (x) => - `repeat(${x}, ${IMAGE_CONTAINER_MAX_WIDTH * shrinkRatio}px)`, - ) - // Space between date groups - .join(` 44px `) - ); - } else { - return `repeat(${columns},${ - IMAGE_CONTAINER_MAX_WIDTH * shrinkRatio - }px)`; - } -}; +): string => + groups + ? groups + .map((x) => `repeat(${x}, ${itemWidth}px)`) + // Space between date groups + .join(` 44px `) + : `repeat(${columns},${itemWidth}px)`; const ListContainer = styled(Box, { shouldForwardProp: (propName) => propName != "gridTemplateColumns", @@ -866,9 +850,7 @@ const NoFilesContainer = styled(ListItemContainer)` interface ItemData { timeStampList: TimeStampListItem[]; - columns: number; layoutParams: ThumbnailGridLayoutParams; - shrinkRatio: number; renderListItem: ( timeStampListItem: TimeStampListItem, isScrolling?: boolean, @@ -878,20 +860,12 @@ interface ItemData { const createItemData = memoize( ( timeStampList: TimeStampListItem[], - columns: number, layoutParams: ThumbnailGridLayoutParams, - shrinkRatio: number, renderListItem: ( timeStampListItem: TimeStampListItem, isScrolling?: boolean, ) => React.JSX.Element, - ): ItemData => ({ - timeStampList, - columns, - layoutParams, - shrinkRatio, - renderListItem, - }), + ): ItemData => ({ timeStampList, layoutParams, renderListItem }), ); const PhotoListRow = React.memo( @@ -901,13 +875,12 @@ const PhotoListRow = React.memo( isScrolling, data, }: ListChildComponentProps) => { - const { timeStampList, columns, shrinkRatio, renderListItem } = data; + const { timeStampList, layoutParams, renderListItem } = data; return ( diff --git a/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts b/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts index 9e796ae8f1..58f6f12612 100644 --- a/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts +++ b/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts @@ -84,13 +84,13 @@ const IMAGE_CONTAINER_MAX_HEIGHT = 180; const IMAGE_CONTAINER_MAX_WIDTH = 180; const MIN_COLUMNS = 4; -export const getFractionFittableColumns = (width: number): number => +const getFractionFittableColumns = (width: number): number => (width - 2 * getGapFromScreenEdge(width) + GAP_BTW_TILES) / (IMAGE_CONTAINER_MAX_WIDTH + GAP_BTW_TILES); -export const getGapFromScreenEdge = (width: number) => +const getGapFromScreenEdge = (width: number) => width > MIN_COLUMNS * IMAGE_CONTAINER_MAX_WIDTH ? 24 : 4; -export const getShrinkRatio = (width: number, columns: number) => +const getShrinkRatio = (width: number, columns: number) => (width - 2 * getGapFromScreenEdge(width) - (columns - 1) * GAP_BTW_TILES) / (columns * IMAGE_CONTAINER_MAX_WIDTH); From b6dafd5a17b0cdbbac2b70a715705610410d2cfe Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 14:00:31 +0530 Subject: [PATCH 32/81] Update --- web/apps/photos/src/components/FileList.tsx | 22 ++++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 3083214b90..567eefadc0 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -782,10 +782,7 @@ const getTemplateColumns = ( groups?: number[], ): string => groups - ? groups - .map((x) => `repeat(${x}, ${itemWidth}px)`) - // Space between date groups - .join(` 44px `) + ? groups.map((x) => `repeat(${x}, ${itemWidth}px)`).join(" 44px ") : `repeat(${columns},${itemWidth}px)`; const ListContainer = styled(Box, { @@ -848,8 +845,8 @@ const NoFilesContainer = styled(ListItemContainer)` justify-content: center; `; -interface ItemData { - timeStampList: TimeStampListItem[]; +interface FileListItemData { + items: TimeStampListItem[]; layoutParams: ThumbnailGridLayoutParams; renderListItem: ( timeStampListItem: TimeStampListItem, @@ -859,13 +856,13 @@ interface ItemData { const createItemData = memoize( ( - timeStampList: TimeStampListItem[], + items: TimeStampListItem[], layoutParams: ThumbnailGridLayoutParams, renderListItem: ( timeStampListItem: TimeStampListItem, isScrolling?: boolean, ) => React.JSX.Element, - ): ItemData => ({ timeStampList, layoutParams, renderListItem }), + ): FileListItemData => ({ items, layoutParams, renderListItem }), ); const PhotoListRow = React.memo( @@ -874,17 +871,18 @@ const PhotoListRow = React.memo( style, isScrolling, data, - }: ListChildComponentProps) => { - const { timeStampList, layoutParams, renderListItem } = data; + }: ListChildComponentProps) => { + const { items, layoutParams, renderListItem } = data; + const item = items[index]!; return ( - {renderListItem(timeStampList[index]!, isScrolling)} + {renderListItem(item, isScrolling)} ); From a97658b67d950567251552378cf1fc427decad8e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 14:23:40 +0530 Subject: [PATCH 33/81] Rename --- web/apps/photos/src/components/FileList.tsx | 124 +++++++++----------- 1 file changed, 57 insertions(+), 67 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 567eefadc0..83e94ba8c5 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -33,6 +33,7 @@ import { PseudoCollectionID } from "ente-new/photos/services/collection-summary" import { t } from "i18next"; import memoize from "memoize-one"; import React, { + memo, useDeferredValue, useEffect, useMemo, @@ -65,10 +66,14 @@ export interface FileListHeaderOrFooter { height: number; } -interface TimeStampListItem { +/** + * Data needed to render each row in the variable size list that comprises the + * file list. + */ +interface FileListRow { /** - * An optional {@link FileListItemTag} that can be used to identify item - * types for conditional behaviour. + * An optional tag that can be used to identify item types for conditional + * behaviour. */ tag?: "date" | "file"; items?: FileListAnnotatedFile[]; @@ -213,10 +218,8 @@ export const FileList: React.FC = ({ emailByUserID, onItemClick, }) => { - const [_timeStampList, setTimeStampList] = useState( - new Array(), - ); - const timeStampList = useDeferredValue(_timeStampList); + const [_rows, setRows] = useState([]); + const rows = useDeferredValue(_rows); const listRef = useRef(null); @@ -256,22 +259,20 @@ export const FileList: React.FC = ({ // another update when processing one, React will restart the background // rerender from scratch. - let timeStampList: TimeStampListItem[] = []; + let rows: FileListRow[] = []; - if (header) { - timeStampList.push(asFullSpanListItem(header)); - } + if (header) rows.push(asFullSpanListItem(header)); const { isSmallerLayout, columns } = layoutParams; if (disableGrouping) { let listItemIndex = columns; annotatedFiles.forEach((item, index) => { if (listItemIndex < columns) { - timeStampList[timeStampList.length - 1]!.items!.push(item); + rows[rows.length - 1]!.items!.push(item); listItemIndex++; } else { listItemIndex = 1; - timeStampList.push({ + rows.push({ tag: "file", items: [item], itemStartIndex: index, @@ -279,15 +280,15 @@ export const FileList: React.FC = ({ } }); } else { - groupByTime(timeStampList); + groupByTime(rows); } if (!isSmallerLayout) { - timeStampList = mergeTimeStampList(timeStampList, columns); + rows = mergeTimeStampList(rows, columns); } - if (timeStampList.length == 1) { - timeStampList.push({ + if (rows.length == 1) { + rows.push({ item: ( @@ -301,12 +302,14 @@ export const FileList: React.FC = ({ } const footerHeight = footer?.height ?? 0; - timeStampList.push(getVacuumItem(timeStampList, footerHeight)); + rows.push(getVacuumItem(rows, footerHeight)); if (footer) { - timeStampList.push(asFullSpanListItem(footer)); + rows.push(asFullSpanListItem(footer)); } - setTimeStampList(timeStampList); + setRows(rows); + // Refresh list. + listRef.current?.resetAfterIndex(0); // TODO: // eslint-disable-next-line react-hooks/exhaustive-deps }, [ @@ -319,14 +322,9 @@ export const FileList: React.FC = ({ layoutParams, ]); - useEffect(() => { - // Refresh list. - listRef.current?.resetAfterIndex(0); - }, [timeStampList]); - // TODO: Too many non-null assertions - const groupByTime = (timeStampList: TimeStampListItem[]) => { + const groupByTime = (timeStampList: FileListRow[]) => { let listItemIndex = 0; let lastCreationTime: number | undefined; annotatedFiles.forEach((item, index) => { @@ -362,14 +360,11 @@ export const FileList: React.FC = ({ }); }; - const getVacuumItem = ( - timeStampList: TimeStampListItem[], - footerHeight: number, - ) => { + const getVacuumItem = (rows: FileListRow[], footerHeight: number) => { const fileListHeight = (() => { let sum = 0; - const getCurrentItemSize = getItemSize(timeStampList); - for (let i = 0; i < timeStampList.length; i++) { + const getCurrentItemSize = getItemSize(rows); + for (let i = 0; i < rows.length; i++) { sum += getCurrentItemSize(i); if (height - sum <= footerHeight) { break; @@ -387,10 +382,10 @@ export const FileList: React.FC = ({ * Checks and merge multiple dates into a single row. */ const mergeTimeStampList = ( - items: TimeStampListItem[], + items: FileListRow[], columns: number, - ): TimeStampListItem[] => { - const newList: TimeStampListItem[] = []; + ): FileListRow[] => { + const newList: FileListRow[] = []; let index = 0; let newIndex = 0; while (index < items.length) { @@ -463,26 +458,25 @@ export const FileList: React.FC = ({ return newList; }; - const getItemSize = - (timeStampList: TimeStampListItem[]) => (index: number) => { - switch (timeStampList[index]!.tag) { - case "date": - return dateContainerHeight; - case "file": - return listItemHeight; - default: - return timeStampList[index]!.height!; - } - }; + const getItemSize = (timeStampList: FileListRow[]) => (index: number) => { + switch (timeStampList[index]!.tag) { + case "date": + return dateContainerHeight; + case "file": + return listItemHeight; + default: + return timeStampList[index]!.height!; + } + }; const generateKey = (index: number) => { - switch (timeStampList[index]!.tag) { + switch (rows[index]!.tag) { case "file": - return `${timeStampList[index]!.items![0]!.file.id}-${ - timeStampList[index]!.items!.slice(-1)[0]!.file.id + return `${rows[index]!.items![0]!.file.id}-${ + rows[index]!.items!.slice(-1)[0]!.file.id }`; default: - return `${timeStampList[index]!.id}-${index}`; + return `${rows[index]!.id}-${index}`; } }; @@ -649,7 +643,7 @@ export const FileList: React.FC = ({ ); const renderListItem = ( - listItem: TimeStampListItem, + listItem: FileListRow, isScrolling: boolean | undefined, ) => { const haveSelection = selected.count > 0; @@ -728,15 +722,11 @@ export const FileList: React.FC = ({ } }; - if (!timeStampList.length) { + if (!rows.length) { return <>; } - const itemData = createItemData( - timeStampList, - layoutParams, - renderListItem, - ); + const itemData = createItemData(rows, layoutParams, renderListItem); // The old, mode unaware, behaviour. let key = `${activeCollectionID}`; @@ -759,15 +749,15 @@ export const FileList: React.FC = ({ key={key} itemData={itemData} ref={listRef} - itemSize={getItemSize(timeStampList)} + itemSize={getItemSize(rows)} height={height} width={width} - itemCount={timeStampList.length} + itemCount={rows.length} itemKey={generateKey} overscanCount={3} useIsScrolling > - {PhotoListRow} + {FileListItem} ); }; @@ -817,7 +807,7 @@ const FullSpanListItemContainer = styled("div")` `; /** - * Convert a {@link FileListHeaderOrFooter} into a {@link TimeStampListItem} + * Convert a {@link FileListHeaderOrFooter} into a {@link FileListRow} * that spans all columns. */ const asFullSpanListItem = ({ item, ...rest }: FileListHeaderOrFooter) => ({ @@ -846,26 +836,26 @@ const NoFilesContainer = styled(ListItemContainer)` `; interface FileListItemData { - items: TimeStampListItem[]; + items: FileListRow[]; layoutParams: ThumbnailGridLayoutParams; renderListItem: ( - timeStampListItem: TimeStampListItem, + timeStampListItem: FileListRow, isScrolling?: boolean, ) => React.JSX.Element; } const createItemData = memoize( ( - items: TimeStampListItem[], + rowDatas: FileListRow[], layoutParams: ThumbnailGridLayoutParams, renderListItem: ( - timeStampListItem: TimeStampListItem, + timeStampListItem: FileListRow, isScrolling?: boolean, ) => React.JSX.Element, - ): FileListItemData => ({ items, layoutParams, renderListItem }), + ): FileListItemData => ({ items: rowDatas, layoutParams, renderListItem }), ); -const PhotoListRow = React.memo( +const FileListItem = memo( ({ index, style, From 689edebec4fbc1592581ef3392cad856a467469d Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Wed, 16 Jul 2025 13:29:53 +0200 Subject: [PATCH 34/81] Increase limit to 20000 --- mobile/apps/photos/lib/utils/image_ml_util.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/apps/photos/lib/utils/image_ml_util.dart b/mobile/apps/photos/lib/utils/image_ml_util.dart index ea894c3781..ffecd69db5 100644 --- a/mobile/apps/photos/lib/utils/image_ml_util.dart +++ b/mobile/apps/photos/lib/utils/image_ml_util.dart @@ -65,8 +65,8 @@ Future decodeImageFromPath( await FlutterImageCompress.compressWithFile( imagePath, format: CompressFormat.jpeg, - minWidth: 8000, // High value to ensure image is not scaled down - minHeight: 8000, // High value to ensure image is not scaled down + minWidth: 20000, // High value to ensure image is not scaled down + minHeight: 20000, // High value to ensure image is not scaled down ); final image = await decodeImageFromData(convertedData!); _logger.info('Conversion successful, jpeg decoded'); From bcb389c56d1a161e7494c4f1edd1a661766cc41a Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Wed, 16 Jul 2025 13:42:32 +0200 Subject: [PATCH 35/81] Log higher image resolutions and store empty result --- mobile/apps/photos/lib/utils/image_ml_util.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mobile/apps/photos/lib/utils/image_ml_util.dart b/mobile/apps/photos/lib/utils/image_ml_util.dart index ffecd69db5..7d7ea1d0c8 100644 --- a/mobile/apps/photos/lib/utils/image_ml_util.dart +++ b/mobile/apps/photos/lib/utils/image_ml_util.dart @@ -70,6 +70,12 @@ Future decodeImageFromPath( ); final image = await decodeImageFromData(convertedData!); _logger.info('Conversion successful, jpeg decoded'); + if (image.width >= 20000 || image.height >= 20000) { + // Failing and storing empty result when the image dimensions are higher than max compression limits + _logger + .severe('Image res too high, W:${image.width} H:${image.height}'); + throw Exception('Res too high W:${image.width} H:${image.height}'); + } if (!includeRgbaBytes) { return DecodedImage(image); } From 08a43f5d6470fdbe8a8bad2edb43ead9f66321e4 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 16:32:50 +0530 Subject: [PATCH 36/81] Rework --- .../Collections/GalleryBarAndListHeader.tsx | 2 +- web/apps/photos/src/components/FileList.tsx | 448 +++++++++--------- web/apps/photos/src/pages/gallery.tsx | 4 +- web/apps/photos/src/pages/shared-albums.tsx | 9 +- 4 files changed, 220 insertions(+), 243 deletions(-) diff --git a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx index d7cddb8291..1cfa7886db 100644 --- a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx +++ b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx @@ -136,7 +136,7 @@ export const GalleryBarAndListHeader: React.FC< if (shouldHide) return; setFileListHeader({ - item: + component: mode != "people" ? ( = ({ emailByUserID, onItemClick, }) => { - const [_rows, setRows] = useState([]); - const rows = useDeferredValue(_rows); + const [_items, setItems] = useState([]); + const items = useDeferredValue(_items); const listRef = useRef(null); @@ -247,8 +249,6 @@ export const FileList: React.FC = ({ // itemHeight, // gap, } = layoutParams; - // TODO(RE): - const listItemHeight = layoutParams.itemHeight + layoutParams.gap; useEffect(() => { // Since width and height are dependencies, there might be too many @@ -259,59 +259,98 @@ export const FileList: React.FC = ({ // another update when processing one, React will restart the background // rerender from scratch. - let rows: FileListRow[] = []; + let items: FileListItem[] = []; - if (header) rows.push(asFullSpanListItem(header)); + if (header) items.push(asFullSpanListItem(header)); const { isSmallerLayout, columns } = layoutParams; + const fileItemHeight = layoutParams.itemHeight + layoutParams.gap; if (disableGrouping) { let listItemIndex = columns; - annotatedFiles.forEach((item, index) => { + for (const [index, af] of annotatedFiles.entries()) { if (listItemIndex < columns) { - rows[rows.length - 1]!.items!.push(item); + items[items.length - 1]!.items!.push(af); listItemIndex++; } else { listItemIndex = 1; - rows.push({ + items.push({ + height: fileItemHeight, tag: "file", - items: [item], + items: [af], itemStartIndex: index, }); } - }); + } } else { - groupByTime(rows); + let listItemIndex = 0; + let lastCreationTime: number | undefined; + for (const [index, af] of annotatedFiles.entries()) { + const creationTime = fileCreationTime(af.file) / 1000; + if ( + !lastCreationTime || + !isSameDay( + new Date(creationTime), + new Date(lastCreationTime), + ) + ) { + lastCreationTime = creationTime; + + items.push({ + height: dateContainerHeight, + tag: "date", + date: af.timelineDateString, + }); + items.push({ + height: fileItemHeight, + tag: "file", + items: [af], + itemStartIndex: index, + }); + listItemIndex = 1; + } else if (listItemIndex < columns) { + items[items.length - 1]!.items!.push(af); + listItemIndex++; + } else { + listItemIndex = 1; + items.push({ + height: fileItemHeight, + tag: "file", + items: [af], + itemStartIndex: index, + }); + } + } } if (!isSmallerLayout) { - rows = mergeTimeStampList(rows, columns); + items = mergeTimeStampList(items, columns); } - if (rows.length == 1) { - rows.push({ - item: ( + if (items.length == 1) { + items.push({ + height: height - 48, + component: ( {t("nothing_here")} ), - id: "empty-list-banner", - height: height - 48, }); } - const footerHeight = footer?.height ?? 0; - rows.push(getVacuumItem(rows, footerHeight)); - if (footer) { - rows.push(asFullSpanListItem(footer)); + let leftoverHeight = height - (footer?.height ?? 0); + for (const item of items) { + leftoverHeight -= item.height; + if (leftoverHeight <= 0) break; + } + if (leftoverHeight > 0) { + items.push({ height: leftoverHeight, component: <> }); } - setRows(rows); - // Refresh list. - listRef.current?.resetAfterIndex(0); - // TODO: - // eslint-disable-next-line react-hooks/exhaustive-deps + if (footer) items.push(asFullSpanListItem(footer)); + + setItems(items); }, [ width, height, @@ -322,181 +361,32 @@ export const FileList: React.FC = ({ layoutParams, ]); + useEffect(() => { + // Refresh list + listRef.current?.resetAfterIndex(0); + }, [items]); + // TODO: Too many non-null assertions - const groupByTime = (timeStampList: FileListRow[]) => { - let listItemIndex = 0; - let lastCreationTime: number | undefined; - annotatedFiles.forEach((item, index) => { - const creationTime = fileCreationTime(item.file) / 1000; - if ( - !lastCreationTime || - !isSameDay(new Date(creationTime), new Date(lastCreationTime)) - ) { - lastCreationTime = creationTime; - - timeStampList.push({ - tag: "date", - date: item.timelineDateString, - id: lastCreationTime.toString(), - }); - timeStampList.push({ - tag: "file", - items: [item], - itemStartIndex: index, - }); - listItemIndex = 1; - } else if (listItemIndex < columns) { - timeStampList[timeStampList.length - 1]!.items!.push(item); - listItemIndex++; - } else { - listItemIndex = 1; - timeStampList.push({ - tag: "file", - items: [item], - itemStartIndex: index, - }); - } - }); - }; - - const getVacuumItem = (rows: FileListRow[], footerHeight: number) => { - const fileListHeight = (() => { - let sum = 0; - const getCurrentItemSize = getItemSize(rows); - for (let i = 0; i < rows.length; i++) { - sum += getCurrentItemSize(i); - if (height - sum <= footerHeight) { - break; - } - } - return sum; - })(); - return { - item: <>, - height: Math.max(height - fileListHeight - footerHeight, 0), - }; - }; - - /** - * Checks and merge multiple dates into a single row. - */ - const mergeTimeStampList = ( - items: FileListRow[], - columns: number, - ): FileListRow[] => { - const newList: FileListRow[] = []; - let index = 0; - let newIndex = 0; - while (index < items.length) { - const currItem = items[index]!; - // If the current item is of type time, then it is not part of an ongoing date. - // So, there is a possibility of merge. - if (currItem.tag == "date") { - // If new list pointer is not at the end of list then - // we can add more items to the same list. - if (newList[newIndex]) { - const SPACE_BTW_DATES_TO_IMAGE_CONTAINER_WIDTH_RATIO = 0.244; - // Check if items can be added to same list - if ( - newList[newIndex + 1]!.items!.length + - items[index + 1]!.items!.length + - Math.ceil( - newList[newIndex]!.dates!.length * - SPACE_BTW_DATES_TO_IMAGE_CONTAINER_WIDTH_RATIO, - ) <= - columns - ) { - newList[newIndex]!.dates!.push({ - date: currItem.date!, - span: items[index + 1]!.items!.length, - }); - newList[newIndex + 1]!.items = [ - ...newList[newIndex + 1]!.items!, - ...items[index + 1]!.items!, - ]; - index += 2; - } else { - // Adding items would exceed the number of columns. - // So, move new list pointer to the end. Hence, in next iteration, - // items will be added to a new list. - newIndex += 2; - } - } else { - // New list pointer was at the end of list so simply add new items to the list. - newList.push({ - ...currItem, - date: null, - dates: [ - { - date: currItem.date!, - span: items[index + 1]!.items!.length, - }, - ], - }); - newList.push(items[index + 1]!); - index += 2; - } - } else { - // Merge cannot happen. Simply add all items to new list - // and set new list point to the end of list. - newList.push(currItem); - index++; - newIndex = newList.length; - } - } - for (let i = 0; i < newList.length; i++) { - const currItem = newList[i]!; - const nextItem = newList[i + 1]!; - if (currItem.tag == "date") { - if (currItem.dates!.length > 1) { - currItem.groups = currItem.dates!.map((item) => item.span); - nextItem.groups = currItem.groups; - } - } - } - return newList; - }; - - const getItemSize = (timeStampList: FileListRow[]) => (index: number) => { - switch (timeStampList[index]!.tag) { - case "date": - return dateContainerHeight; - case "file": - return listItemHeight; - default: - return timeStampList[index]!.height!; - } - }; - - const generateKey = (index: number) => { - switch (rows[index]!.tag) { - case "file": - return `${rows[index]!.items![0]!.file.id}-${ - rows[index]!.items!.slice(-1)[0]!.file.id - }`; - default: - return `${rows[index]!.id}-${index}`; - } - }; - useEffect(() => { const notSelectedFiles = annotatedFiles.filter( - (item) => !selected[item.file.id], + (af) => !selected[af.file.id], ); + // Get dates of files which were manually unselected. const unselectedDates = new Set( - notSelectedFiles.map((item) => item.timelineDateString), - ); // to get file's date which were manually unselected - - const localSelectedFiles = annotatedFiles.filter( - // to get files which were manually selected - (item) => !unselectedDates.has(item.timelineDateString), + notSelectedFiles.map((af) => af.timelineDateString), ); + // Get files which were manually selected. + const localSelectedFiles = annotatedFiles.filter( + (af) => !unselectedDates.has(af.timelineDateString), + ); + + // Get dates of files which were manually selected. const localSelectedDates = new Set( - localSelectedFiles.map((item) => item.timelineDateString), - ); // to get file's date which were manually selected + localSelectedFiles.map((af) => af.timelineDateString), + ); setCheckedTimelineDateStrings((prev) => { const checked = new Set(prev); @@ -508,9 +398,7 @@ export const FileList: React.FC = ({ localSelectedDates.forEach((date) => checked.add(date)); return checked; }); - // TODO: - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selected]); + }, [annotatedFiles, selected]); const handleSelectMulti = handleSelectCreatorMulti( setSelected, @@ -642,8 +530,9 @@ export const FileList: React.FC = ({ /> ); + // eslint-disable-next-line react-hooks/exhaustive-deps const renderListItem = ( - listItem: FileListRow, + listItem: FileListItem, isScrolling: boolean | undefined, ) => { const haveSelection = selected.count > 0; @@ -716,18 +605,38 @@ export const FileList: React.FC = ({ return ret; } default: - // TODO: - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return listItem.item; + return listItem.component; } }; - if (!rows.length) { + const itemData = useMemo( + () => ({ items, layoutParams, renderListItem }), + [items, layoutParams, renderListItem], + ); + + const itemSize = useCallback( + (index: number) => itemData.items[index]!.height, + [itemData], + ); + + const itemKey = useCallback((index: number, itemData: FileListItemData) => { + const item = itemData.items[index]!; + switch (item.tag) { + case "date": + return `${item.date ?? ""}-${index}`; + case "file": + return `${item.items![0]!.file.id}-${ + item.items!.slice(-1)[0]!.file.id + }`; + default: + return `${index}`; + } + }, []); + + if (!items.length) { return <>; } - const itemData = createItemData(rows, layoutParams, renderListItem); - // The old, mode unaware, behaviour. let key = `${activeCollectionID}`; if (modePlus) { @@ -747,21 +656,97 @@ export const FileList: React.FC = ({ return ( - {FileListItem} + {FileListRow} ); }; +/** + * Checks and merge multiple dates into a single row. + */ +const mergeTimeStampList = ( + items: FileListItem[], + columns: number, +): FileListItem[] => { + const newList: FileListItem[] = []; + let index = 0; + let newIndex = 0; + while (index < items.length) { + const currItem = items[index]!; + // If the current item is of type time, then it is not part of an ongoing date. + // So, there is a possibility of merge. + if (currItem.tag == "date") { + // If new list pointer is not at the end of list then + // we can add more items to the same list. + if (newList[newIndex]) { + const SPACE_BTW_DATES_TO_IMAGE_CONTAINER_WIDTH_RATIO = 0.244; + // Check if items can be added to same list + if ( + newList[newIndex + 1]!.items!.length + + items[index + 1]!.items!.length + + Math.ceil( + newList[newIndex]!.dates!.length * + SPACE_BTW_DATES_TO_IMAGE_CONTAINER_WIDTH_RATIO, + ) <= + columns + ) { + newList[newIndex]!.dates!.push({ + date: currItem.date!, + span: items[index + 1]!.items!.length, + }); + newList[newIndex + 1]!.items = [ + ...newList[newIndex + 1]!.items!, + ...items[index + 1]!.items!, + ]; + index += 2; + } else { + // Adding items would exceed the number of columns. + // So, move new list pointer to the end. Hence, in next iteration, + // items will be added to a new list. + newIndex += 2; + } + } else { + // New list pointer was at the end of list so simply add new items to the list. + newList.push({ + ...currItem, + date: null, + dates: [ + { + date: currItem.date!, + span: items[index + 1]!.items!.length, + }, + ], + }); + newList.push(items[index + 1]!); + index += 2; + } + } else { + // Merge cannot happen. Simply add all items to new list + // and set new list point to the end of list. + newList.push(currItem); + index++; + newIndex = newList.length; + } + } + for (let i = 0; i < newList.length; i++) { + const currItem = newList[i]!; + const nextItem = newList[i + 1]!; + if (currItem.tag == "date") { + if (currItem.dates!.length > 1) { + currItem.groups = currItem.dates!.map((item) => item.span); + nextItem.groups = currItem.groups; + } + } + } + return newList; +}; + const ListItem = styled("div")` display: flex; justify-content: center; @@ -807,12 +792,14 @@ const FullSpanListItemContainer = styled("div")` `; /** - * Convert a {@link FileListHeaderOrFooter} into a {@link FileListRow} + * Convert a {@link FileListHeaderOrFooter} into a {@link FileListItem} * that spans all columns. */ -const asFullSpanListItem = ({ item, ...rest }: FileListHeaderOrFooter) => ({ - ...rest, - item: {item}, +const asFullSpanListItem = ({ component, height }: FileListHeaderOrFooter) => ({ + height, + component: ( + {component} + ), }); /** @@ -836,26 +823,15 @@ const NoFilesContainer = styled(ListItemContainer)` `; interface FileListItemData { - items: FileListRow[]; + items: FileListItem[]; layoutParams: ThumbnailGridLayoutParams; renderListItem: ( - timeStampListItem: FileListRow, + timeStampListItem: FileListItem, isScrolling?: boolean, ) => React.JSX.Element; } -const createItemData = memoize( - ( - rowDatas: FileListRow[], - layoutParams: ThumbnailGridLayoutParams, - renderListItem: ( - timeStampListItem: FileListRow, - isScrolling?: boolean, - ) => React.JSX.Element, - ): FileListItemData => ({ items: rowDatas, layoutParams, renderListItem }), -); - -const FileListItem = memo( +const FileListRow = memo( ({ index, style, diff --git a/web/apps/photos/src/pages/gallery.tsx b/web/apps/photos/src/pages/gallery.tsx index 5e1437d64b..bfd47be17a 100644 --- a/web/apps/photos/src/pages/gallery.tsx +++ b/web/apps/photos/src/pages/gallery.tsx @@ -412,7 +412,7 @@ const Page: React.FC = () => { useEffect(() => { if (isInSearchMode && state.searchSuggestion) { setFileListHeader({ - item: ( + component: ( ({ - item: ( + component: ( ( () => publicCollection && publicFiles ? { - item: ( + component: ( { + const fileListFooter = useMemo(() => { const props = { referralCode, onAddPhotos }; return { - item: , + component: , height: fileListFooterHeightForProps(props), }; }, [referralCode, onAddPhotos]); From d1717ef3084778e6f42f633007ea2d19ea500a06 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 17:53:09 +0530 Subject: [PATCH 37/81] Unwrap --- web/apps/photos/src/components/FileList.tsx | 28 ++++++++------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 61bbcdfdce..70011acda9 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -2,7 +2,7 @@ import AlbumOutlinedIcon from "@mui/icons-material/AlbumOutlined"; import FavoriteRoundedIcon from "@mui/icons-material/FavoriteRounded"; import PlayCircleOutlineOutlinedIcon from "@mui/icons-material/PlayCircleOutlineOutlined"; -import { Box, Checkbox, Typography, styled } from "@mui/material"; +import { Checkbox, Typography, styled } from "@mui/material"; import Avatar from "components/Avatar"; import type { LocalUser } from "ente-accounts/services/user"; import { assertionFailed } from "ente-base/assert"; @@ -747,11 +747,6 @@ const mergeTimeStampList = ( return newList; }; -const ListItem = styled("div")` - display: flex; - justify-content: center; -`; - const getTemplateColumns = ( { columns, itemWidth }: ThumbnailGridLayoutParams, groups?: number[], @@ -760,7 +755,7 @@ const getTemplateColumns = ( ? groups.map((x) => `repeat(${x}, ${itemWidth}px)`).join(" 44px ") : `repeat(${columns},${itemWidth}px)`; -const ListContainer = styled(Box, { +const ListItemGrid = styled("div", { shouldForwardProp: (propName) => propName != "gridTemplateColumns", })<{ gridTemplateColumns: string }>` display: grid; @@ -841,16 +836,15 @@ const FileListRow = memo( const { items, layoutParams, renderListItem } = data; const item = items[index]!; return ( - - - {renderListItem(item, isScrolling)} - - + + {renderListItem(item, isScrolling)} + ); }, areEqual, From 127c4808550bbd06e243654d51cb86b90c003660 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 18:53:57 +0530 Subject: [PATCH 38/81] Fix overflow --- web/apps/photos/src/components/FileList.tsx | 87 ++++++++++++--------- web/apps/photos/src/pages/shared-albums.tsx | 4 +- 2 files changed, 49 insertions(+), 42 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 70011acda9..e3ac4a4040 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -2,7 +2,7 @@ import AlbumOutlinedIcon from "@mui/icons-material/AlbumOutlined"; import FavoriteRoundedIcon from "@mui/icons-material/FavoriteRounded"; import PlayCircleOutlineOutlinedIcon from "@mui/icons-material/PlayCircleOutlineOutlined"; -import { Checkbox, Typography, styled } from "@mui/material"; +import { Box, Checkbox, Typography, styled } from "@mui/material"; import Avatar from "components/Avatar"; import type { LocalUser } from "ente-accounts/services/user"; import { assertionFailed } from "ente-base/assert"; @@ -14,11 +14,7 @@ import { downloadManager } from "ente-gallery/services/download"; import type { EnteFile } from "ente-media/file"; import { fileCreationTime, fileDurationString } from "ente-media/file-metadata"; import { FileType } from "ente-media/file-type"; -import { - GAP_BTW_TILES, - IMAGE_CONTAINER_MAX_WIDTH, - MIN_COLUMNS, -} from "ente-new/photos/components/FileList"; +import { GAP_BTW_TILES } from "ente-new/photos/components/FileList"; import type { GalleryBarMode } from "ente-new/photos/components/gallery/reducer"; import { LoadingThumbnail, @@ -64,13 +60,21 @@ export interface FileListHeaderOrFooter { * The height of the component (in px). */ height: number; + /** + * By default, all items in the {@link FileList}, including headers and + * footers injected using this type, get an inline margin. + * + * Set this property to `true` to omit this default margin, and instead + * have the component extend to the container's edges. + */ + extendToInlineEdges?: boolean; } /** * Data needed to render each row in the variable size list that comprises the * file list. */ -interface FileListItem { +type FileListItem = { /** * The height of the row that will render this item. */ @@ -79,7 +83,7 @@ interface FileListItem { * An optional tag that can be used to identify item types for conditional * behaviour. */ - tag?: "date" | "file"; + tag?: "date" | "file" | "span"; items?: FileListAnnotatedFile[]; itemStartIndex?: number; date?: string | null; @@ -89,7 +93,7 @@ interface FileListItem { * The React component that is the rendered representation of the item. */ component?: React.ReactNode; -} +} & Pick; export interface FileListAnnotatedFile { file: EnteFile; @@ -747,27 +751,6 @@ const mergeTimeStampList = ( return newList; }; -const getTemplateColumns = ( - { columns, itemWidth }: ThumbnailGridLayoutParams, - groups?: number[], -): string => - groups - ? groups.map((x) => `repeat(${x}, ${itemWidth}px)`).join(" 44px ") - : `repeat(${columns},${itemWidth}px)`; - -const ListItemGrid = styled("div", { - shouldForwardProp: (propName) => propName != "gridTemplateColumns", -})<{ gridTemplateColumns: string }>` - display: grid; - grid-template-columns: ${(props) => props.gridTemplateColumns}; - grid-column-gap: ${GAP_BTW_TILES}px; - width: 100%; - padding: 0 24px; - @media (max-width: ${IMAGE_CONTAINER_MAX_WIDTH * MIN_COLUMNS}px) { - padding: 0 4px; - } -`; - /** * An grid item, spanning {@link span} columns. */ @@ -781,7 +764,7 @@ const ListItemContainer = styled("div")<{ span: number }>` * A grid items that spans all columns. */ const FullSpanListItemContainer = styled("div")` - grid-column: 1 / -1; + // grid-column: 1 / -1; display: flex; align-items: center; `; @@ -790,8 +773,12 @@ const FullSpanListItemContainer = styled("div")` * Convert a {@link FileListHeaderOrFooter} into a {@link FileListItem} * that spans all columns. */ -const asFullSpanListItem = ({ component, height }: FileListHeaderOrFooter) => ({ - height, +const asFullSpanListItem = ({ + component, + ...rest +}: FileListHeaderOrFooter) => ({ + ...rest, + tag: "span", component: ( {component} ), @@ -834,17 +821,39 @@ const FileListRow = memo( data, }: ListChildComponentProps) => { const { items, layoutParams, renderListItem } = data; + const { columns, itemWidth, paddingInline, gap } = layoutParams; + const item = items[index]!; + const { groups } = item; + + const gridTemplateColumns = groups + ? groups.map((x) => `repeat(${x}, ${itemWidth}px)`).join(" 44px ") + : `repeat(${columns}, ${itemWidth}px)`; + const px = item.extendToInlineEdges ? 0 : paddingInline; + + if (item.tag == "span") { + return ( + + {renderListItem(item, isScrolling)} + + ); + } return ( - {renderListItem(item, isScrolling)} - + ); }, areEqual, diff --git a/web/apps/photos/src/pages/shared-albums.tsx b/web/apps/photos/src/pages/shared-albums.tsx index c42a745718..b366b64378 100644 --- a/web/apps/photos/src/pages/shared-albums.tsx +++ b/web/apps/photos/src/pages/shared-albums.tsx @@ -419,6 +419,7 @@ export default function PublicCollectionGallery() { return { component: , height: fileListFooterHeightForProps(props), + extendToInlineEdges: true, }; }, [referralCode, onAddPhotos]); @@ -741,9 +742,6 @@ const FileListFooter: React.FC = ({ sx={{ mt: "6px", mb: 0, - /* Negative margin to extend to edges by counteracting the - maximum margin that can be added by FileViewer. */ - mx: "-24px", padding: "8px", bgcolor: "accent.main", color: "accent.contrastText", From 9cd6784837755ffb0074cfcd00c82a2f3d474095 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Wed, 16 Jul 2025 16:58:32 +0200 Subject: [PATCH 39/81] Locally fail indexing on different exif orientation --- .../services/machine_learning/ml_service.dart | 1 + .../apps/photos/lib/utils/image_ml_util.dart | 34 ++++++++++++------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/mobile/apps/photos/lib/services/machine_learning/ml_service.dart b/mobile/apps/photos/lib/services/machine_learning/ml_service.dart index 166421ba08..1312aabc6b 100644 --- a/mobile/apps/photos/lib/services/machine_learning/ml_service.dart +++ b/mobile/apps/photos/lib/services/machine_learning/ml_service.dart @@ -516,6 +516,7 @@ class MLService { final bool acceptedIssue = errorString.contains('ThumbnailRetrievalException') || errorString.contains('InvalidImageFormatException') || + errorString.contains('UnhandledExifOrientation') || errorString.contains('FileSizeTooLargeForMobileIndexing'); if (acceptedIssue) { _logger.severe( diff --git a/mobile/apps/photos/lib/utils/image_ml_util.dart b/mobile/apps/photos/lib/utils/image_ml_util.dart index 7d7ea1d0c8..0ab1428fea 100644 --- a/mobile/apps/photos/lib/utils/image_ml_util.dart +++ b/mobile/apps/photos/lib/utils/image_ml_util.dart @@ -4,6 +4,7 @@ import "dart:math" show exp, max, min, pi; import "dart:typed_data" show Float32List, Uint8List; import "dart:ui"; +import "package:exif_reader/exif_reader.dart"; import 'package:flutter/painting.dart' as paint show decodeImageFromList; import "package:flutter_image_compress/flutter_image_compress.dart"; import "package:logging/logging.dart"; @@ -47,14 +48,21 @@ Future decodeImageFromPath( String imagePath, { required bool includeRgbaBytes, }) async { + final imageData = await File(imagePath).readAsBytes(); + + final Map exifData = await readExifFromBytes(imageData); + final int orientation = + exifData['Image Orientation']?.values.firstAsInt() ?? 1; + if (orientation > 1 && includeRgbaBytes) { + _logger.severe("Image EXIF orientation $orientation is not supported"); + throw Exception( + 'UnhandledExifOrientation: exif orientation $orientation', + ); + } + + late Image image; try { - final imageData = await File(imagePath).readAsBytes(); - final image = await decodeImageFromData(imageData); - if (!includeRgbaBytes) { - return DecodedImage(image); - } - final rawRgbaBytes = await _getRawRgbaBytes(image); - return DecodedImage(image, rawRgbaBytes); + image = await decodeImageFromData(imageData); } catch (e, s) { final format = imagePath.split('.').last; _logger.info( @@ -68,7 +76,7 @@ Future decodeImageFromPath( minWidth: 20000, // High value to ensure image is not scaled down minHeight: 20000, // High value to ensure image is not scaled down ); - final image = await decodeImageFromData(convertedData!); + image = await decodeImageFromData(convertedData!); _logger.info('Conversion successful, jpeg decoded'); if (image.width >= 20000 || image.height >= 20000) { // Failing and storing empty result when the image dimensions are higher than max compression limits @@ -76,11 +84,6 @@ Future decodeImageFromPath( .severe('Image res too high, W:${image.width} H:${image.height}'); throw Exception('Res too high W:${image.width} H:${image.height}'); } - if (!includeRgbaBytes) { - return DecodedImage(image); - } - final rawRgbaBytes = await _getRawRgbaBytes(image); - return DecodedImage(image, rawRgbaBytes); } catch (e) { _logger.severe( 'Error decoding image of format $format on ${Platform.isAndroid ? "Android" : "iOS"}', @@ -92,6 +95,11 @@ Future decodeImageFromPath( ); } } + if (!includeRgbaBytes) { + return DecodedImage(image); + } + final rawRgbaBytes = await _getRawRgbaBytes(image); + return DecodedImage(image, rawRgbaBytes); } /// Decodes [Uint8List] image data to an ui.[Image] object. From fd9824339402d6ea224af4cb1c514ed875d22b10 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 19:48:30 +0530 Subject: [PATCH 40/81] Update --- web/apps/photos/src/components/FileList.tsx | 140 ++++++++++---------- 1 file changed, 69 insertions(+), 71 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index e3ac4a4040..1fe3022dff 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -37,9 +37,9 @@ import React, { useState, } from "react"; import { - type ListChildComponentProps, VariableSizeList, areEqual, + type ListChildComponentProps, } from "react-window"; import { type SelectedState } from "utils/file"; import { @@ -265,7 +265,7 @@ export const FileList: React.FC = ({ let items: FileListItem[] = []; - if (header) items.push(asFullSpanListItem(header)); + if (header) items.push(asFullSpanFileListItem(header)); const { isSmallerLayout, columns } = layoutParams; const fileItemHeight = layoutParams.itemHeight + layoutParams.gap; @@ -300,7 +300,7 @@ export const FileList: React.FC = ({ lastCreationTime = creationTime; items.push({ - height: dateContainerHeight, + height: dateListItemHeight, tag: "date", date: af.timelineDateString, }); @@ -330,15 +330,16 @@ export const FileList: React.FC = ({ items = mergeTimeStampList(items, columns); } - if (items.length == 1) { + if (annotatedFiles.length == 0) { items.push({ height: height - 48, + tag: "span", component: ( - + {t("nothing_here")} - + ), }); } @@ -349,10 +350,14 @@ export const FileList: React.FC = ({ if (leftoverHeight <= 0) break; } if (leftoverHeight > 0) { - items.push({ height: leftoverHeight, component: <> }); + items.push({ + height: leftoverHeight, + tag: "span", + component: <>, + }); } - if (footer) items.push(asFullSpanListItem(footer)); + if (footer) items.push(asFullSpanFileListItem(footer)); setItems(items); }, [ @@ -424,9 +429,10 @@ export const FileList: React.FC = ({ } setCheckedTimelineDateStrings(next); + // All files on a checked/unchecked day. const filesOnADay = annotatedFiles.filter( - (item) => item.timelineDateString === date, - ); // all files on a checked/unchecked day + (af) => af.timelineDateString === date, + ); handleSelectMulti(filesOnADay.map((af) => af.file))(isDateSelected); }; @@ -545,7 +551,7 @@ export const FileList: React.FC = ({ return listItem.dates ? ( listItem.dates .map((item) => [ - + {haveSelection && ( = ({ /> )} {item.date} - , + ,
, ]) .flat() ) : ( - + {haveSelection && ( = ({ /> )} {listItem.date} - + ); case "file": { const ret = listItem.items!.map((item, idx) => @@ -658,6 +664,9 @@ export const FileList: React.FC = ({ } return ( + // TODO(RE): + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore ({ + ...rest, + tag: "span", + component: {component}, +}); + /** * An grid item, spanning {@link span} columns. */ -const ListItemContainer = styled("div")<{ span: number }>` +const GridSpanListItem = styled("div")<{ span: number }>` grid-column: span ${({ span }) => span}; display: flex; align-items: center; `; /** - * A grid items that spans all columns. + * The fixed height (in px) of {@link DateListItem}. */ -const FullSpanListItemContainer = styled("div")` - // grid-column: 1 / -1; - display: flex; - align-items: center; -`; +const dateListItemHeight = 48; -/** - * Convert a {@link FileListHeaderOrFooter} into a {@link FileListItem} - * that spans all columns. - */ -const asFullSpanListItem = ({ - component, - ...rest -}: FileListHeaderOrFooter) => ({ - ...rest, - tag: "span", - component: ( - {component} - ), -}); - -/** - * The fixed height (in px) of {@link DateContainer}. - */ -const dateContainerHeight = 48; - -const DateContainer = styled(ListItemContainer)( +const DateListItem = styled(GridSpanListItem)( ({ theme }) => ` white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - height: ${dateContainerHeight}px; + height: ${dateListItemHeight}px; color: ${theme.vars.palette.text.muted}; `, ); -const NoFilesContainer = styled(ListItemContainer)` - text-align: center; - justify-content: center; -`; - interface FileListItemData { items: FileListItem[]; layoutParams: ThumbnailGridLayoutParams; @@ -824,33 +830,25 @@ const FileListRow = memo( const { columns, itemWidth, paddingInline, gap } = layoutParams; const item = items[index]!; - const { groups } = item; - const gridTemplateColumns = groups - ? groups.map((x) => `repeat(${x}, ${itemWidth}px)`).join(" 44px ") - : `repeat(${columns}, ${itemWidth}px)`; - const px = item.extendToInlineEdges ? 0 : paddingInline; - - if (item.tag == "span") { - return ( - - {renderListItem(item, isScrolling)} - - ); - } return ( `repeat(${x}, ${itemWidth}px)`) + .join(" 44px ") + : `repeat(${columns}, ${itemWidth}px)`, + columnGap: `${gap}px`, + }, + ]} > {renderListItem(item, isScrolling)} From 3369e14f6994ca29be36b0b48cff375cfd426585 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Wed, 16 Jul 2025 17:17:01 +0200 Subject: [PATCH 41/81] Surface when file analysis failed --- .../viewer/file_details/file_info_faces_item_widget.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mobile/apps/photos/lib/ui/viewer/file_details/file_info_faces_item_widget.dart b/mobile/apps/photos/lib/ui/viewer/file_details/file_info_faces_item_widget.dart index 4f46e85950..4668bdc0d7 100644 --- a/mobile/apps/photos/lib/ui/viewer/file_details/file_info_faces_item_widget.dart +++ b/mobile/apps/photos/lib/ui/viewer/file_details/file_info_faces_item_widget.dart @@ -351,6 +351,12 @@ class _FacesItemWidgetState extends State { defaultFaces.add(face); } else if (face.score >= kMinFaceDetectionScore) { remainingFaces.add(face); + } else if (face.score == -1.0) { + return _FaceDataResult( + defaultFaces: [], + remainingFaces: [], + errorReason: NoFacesReason.fileAnalysisFailed, + ); } } if (defaultFaces.isEmpty && remainingFaces.isEmpty) { @@ -433,6 +439,7 @@ enum NoFacesReason { fileNotAnalyzed, noFacesFound, faceThumbnailGenerationFailed, + fileAnalysisFailed, } String getNoFaceReasonText(BuildContext context, NoFacesReason reason) { @@ -445,5 +452,7 @@ String getNoFaceReasonText(BuildContext context, NoFacesReason reason) { return S.of(context).noFacesFound; case NoFacesReason.faceThumbnailGenerationFailed: return "Unable to generate face thumbnails"; + case NoFacesReason.fileAnalysisFailed: + return "File analysis failed"; } } From f7d4273c1dc22f3f32ac9ec93d3f3aecb1d559be Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Wed, 16 Jul 2025 17:31:13 +0200 Subject: [PATCH 42/81] Extract strings --- .../lib/generated/intl/messages_ar.dart | 45 +- .../lib/generated/intl/messages_be.dart | 3 - .../lib/generated/intl/messages_bg.dart | 5 +- .../lib/generated/intl/messages_ca.dart | 5 +- .../lib/generated/intl/messages_cs.dart | 16 - .../lib/generated/intl/messages_da.dart | 3 - .../lib/generated/intl/messages_de.dart | 63 +- .../lib/generated/intl/messages_el.dart | 5 +- .../lib/generated/intl/messages_en.dart | 4 + .../lib/generated/intl/messages_es.dart | 27 - .../lib/generated/intl/messages_et.dart | 3 - .../lib/generated/intl/messages_eu.dart | 3 - .../lib/generated/intl/messages_fa.dart | 3 - .../lib/generated/intl/messages_fr.dart | 65 +- .../lib/generated/intl/messages_gu.dart | 5 +- .../lib/generated/intl/messages_he.dart | 3 - .../lib/generated/intl/messages_hi.dart | 3 - .../lib/generated/intl/messages_hu.dart | 715 ++++++++++- .../lib/generated/intl/messages_id.dart | 3 - .../lib/generated/intl/messages_it.dart | 27 - .../lib/generated/intl/messages_ja.dart | 21 - .../lib/generated/intl/messages_km.dart | 5 +- .../lib/generated/intl/messages_ko.dart | 3 - .../lib/generated/intl/messages_ku.dart | 5 +- .../lib/generated/intl/messages_lt.dart | 9 +- .../lib/generated/intl/messages_lv.dart | 5 +- .../lib/generated/intl/messages_ml.dart | 3 - .../lib/generated/intl/messages_nl.dart | 40 +- .../lib/generated/intl/messages_or.dart | 5 +- .../lib/generated/intl/messages_pl.dart | 3 - .../lib/generated/intl/messages_pt_BR.dart | 66 +- .../lib/generated/intl/messages_pt_PT.dart | 157 ++- .../lib/generated/intl/messages_ro.dart | 3 - .../lib/generated/intl/messages_ru.dart | 115 +- .../lib/generated/intl/messages_sl.dart | 5 +- .../lib/generated/intl/messages_sr.dart | 19 +- .../lib/generated/intl/messages_sv.dart | 16 - .../lib/generated/intl/messages_ta.dart | 3 - .../lib/generated/intl/messages_te.dart | 5 +- .../lib/generated/intl/messages_th.dart | 3 - .../lib/generated/intl/messages_ti.dart | 5 +- .../lib/generated/intl/messages_tr.dart | 3 - .../lib/generated/intl/messages_uk.dart | 3 - .../lib/generated/intl/messages_vi.dart | 1054 +++++++++++------ .../lib/generated/intl/messages_zh.dart | 115 +- mobile/apps/photos/lib/generated/l10n.dart | 20 + mobile/apps/photos/lib/l10n/intl_en.arb | 4 +- .../file_info_faces_item_widget.dart | 4 +- 48 files changed, 1993 insertions(+), 712 deletions(-) diff --git a/mobile/apps/photos/lib/generated/intl/messages_ar.dart b/mobile/apps/photos/lib/generated/intl/messages_ar.dart index 3e7734f881..ac978411b1 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ar.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ar.dart @@ -54,7 +54,7 @@ class MessageLookup extends MessageLookupByLibrary { "يرجى إلغاء اشتراكك الحالي من ${paymentProvider} أولاً."; static String m13(user) => - "لن يتمكن ${user} من إضافة المزيد من الصور إلى هذا الألبوم.\n\nسيظل بإمكانه إزالة الصور الحالية التي أضافها."; + "لن يتمكن ${user} من إضافة المزيد من الصور إلى هذا الألبوم\n\nسيظل بإمكانه إزالة الصور الحالية التي أضافها"; static String m14(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { @@ -314,7 +314,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "لقد أرسلنا بريدًا إلكترونيًا إلى ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "أتمنى لـ${name} عيد ميلاد سعيد! 🎉"; static String m116(count) => "${Intl.plural(count, one: 'قبل سنة', two: 'قبل سنتين', other: 'قبل ${count} سنة')}"; @@ -367,6 +367,8 @@ class MessageLookup extends MessageLookupByLibrary { "addOns": MessageLookupByLibrary.simpleMessage("الإضافات"), "addParticipants": MessageLookupByLibrary.simpleMessage("إضافة مشاركين"), + "addPeopleWidgetPrompt": MessageLookupByLibrary.simpleMessage( + "أضف عنصر واجهة الأشخاص إلى شاشتك الرئيسية ثم عد إلى هنا لتخصيصه."), "addPhotos": MessageLookupByLibrary.simpleMessage("إضافة صور"), "addSelected": MessageLookupByLibrary.simpleMessage("إضافة المحدد"), "addToAlbum": MessageLookupByLibrary.simpleMessage("إضافة إلى الألبوم"), @@ -399,11 +401,16 @@ class MessageLookup extends MessageLookupByLibrary { "albumUpdated": MessageLookupByLibrary.simpleMessage("تم تحديث الألبوم"), "albums": MessageLookupByLibrary.simpleMessage("الألبومات"), + "albumsWidgetDesc": MessageLookupByLibrary.simpleMessage( + "حدد الألبومات التي تريد ظهورها على شاشتك الرئيسية."), "allClear": MessageLookupByLibrary.simpleMessage("✨ كل شيء واضح"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("تم حفظ جميع الذكريات"), "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( "سيتم إعادة تعيين جميع تجمعات هذا الشخص، وستفقد جميع الاقتراحات المقدمة لهذا الشخص."), + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": + MessageLookupByLibrary.simpleMessage( + "سيتم دمج جميع المجموعات غير المسماة مع الشخص المحدد. يمكن التراجع عن هذا الإجراء لاحقًا من خلال نظرة عامة على سجل الاقتراحات التابع لهذا الشخص."), "allWillShiftRangeBasedOnFirst": MessageLookupByLibrary.simpleMessage( "هذه هي الأولى في المجموعة. سيتم تغيير تواريخ الصور المحددة الأخرى تلقائيًا بناءً على هذا التاريخ الجديد."), "allow": MessageLookupByLibrary.simpleMessage("السماح"), @@ -452,6 +459,10 @@ class MessageLookup extends MessageLookupByLibrary { "archive": MessageLookupByLibrary.simpleMessage("الأرشيف"), "archiveAlbum": MessageLookupByLibrary.simpleMessage("أرشفة الألبوم"), "archiving": MessageLookupByLibrary.simpleMessage("جارٍ الأرشفة..."), + "areThey": MessageLookupByLibrary.simpleMessage("هل هم "), + "areYouSureRemoveThisFaceFromPerson": + MessageLookupByLibrary.simpleMessage( + "هل أنت متأكد من رغبتك في إزالة هذا الوجه من هذا الشخص؟"), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage( "هل أنت متأكد من رغبتك في مغادرة الخطة العائلية؟"), @@ -464,6 +475,8 @@ class MessageLookup extends MessageLookupByLibrary { "هل أنت متأكد من رغبتك في الخروج؟"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "هل أنت متأكد من رغبتك في تسجيل الخروج؟"), + "areYouSureYouWantToMergeThem": MessageLookupByLibrary.simpleMessage( + "هل أنت متأكد من رغبتك في دمجهم؟"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "هل أنت متأكد من رغبتك في التجديد؟"), "areYouSureYouWantToResetThisPerson": @@ -619,6 +632,8 @@ class MessageLookup extends MessageLookupByLibrary { "click": MessageLookupByLibrary.simpleMessage("• انقر على"), "clickOnTheOverflowMenu": MessageLookupByLibrary.simpleMessage( "• انقر على قائمة الخيارات الإضافية"), + "clickToInstallOurBestVersionYet": MessageLookupByLibrary.simpleMessage( + "انقر لتثبيت أفضل إصدار لنا حتى الآن"), "close": MessageLookupByLibrary.simpleMessage("إغلاق"), "clubByCaptureTime": MessageLookupByLibrary.simpleMessage("التجميع حسب وقت الالتقاط"), @@ -1077,6 +1092,7 @@ class MessageLookup extends MessageLookupByLibrary { "iOSLockOut": MessageLookupByLibrary.simpleMessage( "تم تعطيل المصادقة البيومترية. يرجى قفل شاشتك وفتحها لتمكينها."), "iOSOkButton": MessageLookupByLibrary.simpleMessage("موافق"), + "ignore": MessageLookupByLibrary.simpleMessage("تجاهل"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("تجاهل"), "ignored": MessageLookupByLibrary.simpleMessage("تم التجاهل"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( @@ -1272,9 +1288,12 @@ class MessageLookup extends MessageLookupByLibrary { "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), "me": MessageLookupByLibrary.simpleMessage("أنا"), "memories": MessageLookupByLibrary.simpleMessage("ذكريات"), + "memoriesWidgetDesc": MessageLookupByLibrary.simpleMessage( + "اختر نوع الذكريات التي ترغب في رؤيتها على شاشتك الرئيسية."), "memoryCount": m50, "merchandise": MessageLookupByLibrary.simpleMessage("المنتجات الترويجية"), + "merge": MessageLookupByLibrary.simpleMessage("دمج"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("الدمج مع شخص موجود"), "mergedPhotos": MessageLookupByLibrary.simpleMessage("الصور المدمجة"), @@ -1383,6 +1402,9 @@ class MessageLookup extends MessageLookupByLibrary { "onTheRoad": MessageLookupByLibrary.simpleMessage("على الطريق مرة أخرى"), "onThisDay": MessageLookupByLibrary.simpleMessage("في هذا اليوم"), + "onThisDayNotificationExplanation": + MessageLookupByLibrary.simpleMessage( + "تلقي تذكيرات حول ذكريات مثل اليوم في السنوات السابقة."), "onlyFamilyAdminCanChangeCode": m55, "onlyThem": MessageLookupByLibrary.simpleMessage("هم فقط"), "oops": MessageLookupByLibrary.simpleMessage("عفوًا"), @@ -1407,6 +1429,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("أو اختر واحدًا موجودًا"), "orPickFromYourContacts": MessageLookupByLibrary.simpleMessage("أو اختر من جهات اتصالك"), + "otherDetectedFaces": + MessageLookupByLibrary.simpleMessage("وجوه أخرى تم اكتشافها"), "pair": MessageLookupByLibrary.simpleMessage("إقران"), "pairWithPin": MessageLookupByLibrary.simpleMessage("الإقران بالرمز السري"), @@ -1439,6 +1463,8 @@ class MessageLookup extends MessageLookupByLibrary { "people": MessageLookupByLibrary.simpleMessage("الأشخاص"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage("الأشخاص الذين يستخدمون رمزك"), + "peopleWidgetDesc": MessageLookupByLibrary.simpleMessage( + "حدد الأشخاص الذين ترغب في ظهورهم على شاشتك الرئيسية."), "permDeleteWarning": MessageLookupByLibrary.simpleMessage( "سيتم حذف جميع العناصر في سلة المهملات نهائيًا.\n\nلا يمكن التراجع عن هذا الإجراء."), "permanentlyDelete": MessageLookupByLibrary.simpleMessage("حذف نهائي"), @@ -1527,6 +1553,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("تم إنشاء الرابط العام."), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("تمكين الرابط العام"), + "questionmark": MessageLookupByLibrary.simpleMessage("؟"), "queued": MessageLookupByLibrary.simpleMessage("في قائمة الانتظار"), "quickLinks": MessageLookupByLibrary.simpleMessage("روابط سريعة"), "radius": MessageLookupByLibrary.simpleMessage("نصف القطر"), @@ -1539,6 +1566,8 @@ class MessageLookup extends MessageLookupByLibrary { "reassignedToName": m69, "reassigningLoading": MessageLookupByLibrary.simpleMessage("جارٍ إعادة التعيين..."), + "receiveRemindersOnBirthdays": MessageLookupByLibrary.simpleMessage( + "استلم تذكيرات عندما يحين عيد ميلاد أحدهم. النقر على الإشعار سينقلك إلى صور الشخص المحتفل بعيد ميلاده."), "recover": MessageLookupByLibrary.simpleMessage("استعادة"), "recoverAccount": MessageLookupByLibrary.simpleMessage("استعادة الحساب"), @@ -1637,6 +1666,7 @@ class MessageLookup extends MessageLookupByLibrary { "reportBug": MessageLookupByLibrary.simpleMessage("الإبلاغ عن خطأ"), "resendEmail": MessageLookupByLibrary.simpleMessage( "إعادة إرسال البريد الإلكتروني"), + "reset": MessageLookupByLibrary.simpleMessage("إعادة تعيين"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage( "إعادة تعيين الملفات المتجاهلة"), "resetPasswordTitle": @@ -1664,6 +1694,8 @@ class MessageLookup extends MessageLookupByLibrary { "rotateRight": MessageLookupByLibrary.simpleMessage("تدوير لليمين"), "safelyStored": MessageLookupByLibrary.simpleMessage("مخزنة بأمان"), "save": MessageLookupByLibrary.simpleMessage("حفظ"), + "saveAsAnotherPerson": + MessageLookupByLibrary.simpleMessage("حفظ كشخص آخر"), "saveChangesBeforeLeavingQuestion": MessageLookupByLibrary.simpleMessage("حفظ التغييرات قبل المغادرة؟"), "saveCollage": MessageLookupByLibrary.simpleMessage("حفظ الكولاج"), @@ -1821,7 +1853,10 @@ class MessageLookup extends MessageLookupByLibrary { "sharing": MessageLookupByLibrary.simpleMessage("جارٍ المشاركة..."), "shiftDatesAndTime": MessageLookupByLibrary.simpleMessage("تغيير التواريخ والوقت"), + "showLessFaces": MessageLookupByLibrary.simpleMessage("إظهار وجوه أقل"), "showMemories": MessageLookupByLibrary.simpleMessage("عرض الذكريات"), + "showMoreFaces": + MessageLookupByLibrary.simpleMessage("إظهار المزيد من الوجوه"), "showPerson": MessageLookupByLibrary.simpleMessage("إظهار الشخص"), "signOutFromOtherDevices": MessageLookupByLibrary.simpleMessage( "تسجيل الخروج من الأجهزة الأخرى"), @@ -1936,6 +1971,10 @@ class MessageLookup extends MessageLookupByLibrary { "theLinkYouAreTryingToAccessHasExpired": MessageLookupByLibrary.simpleMessage( "انتهت صلاحية الرابط الذي تحاول الوصول إليه."), + "thePersonGroupsWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "لن تظهر مجموعات الأشخاص في قسم الأشخاص بعد الآن. ستظل الصور دون تغيير."), + "thePersonWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "لن يتم عرض هذا الشخص في قسم الأشخاص بعد الآن. الصور ستبقى كما هي دون تغيير."), "theRecoveryKeyYouEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( "مفتاح الاسترداد الذي أدخلته غير صحيح."), @@ -2115,6 +2154,7 @@ class MessageLookup extends MessageLookupByLibrary { "whatsNew": MessageLookupByLibrary.simpleMessage("ما الجديد"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage( "يمكن لجهة الاتصال الموثوقة المساعدة في استعادة بياناتك."), + "widgets": MessageLookupByLibrary.simpleMessage("عناصر واجهة"), "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("سنة"), "yearly": MessageLookupByLibrary.simpleMessage("سنويًا"), @@ -2126,6 +2166,7 @@ class MessageLookup extends MessageLookupByLibrary { "yesDelete": MessageLookupByLibrary.simpleMessage("نعم، حذف"), "yesDiscardChanges": MessageLookupByLibrary.simpleMessage("نعم، تجاهل التغييرات"), + "yesIgnore": MessageLookupByLibrary.simpleMessage("نعم، تجاهل"), "yesLogout": MessageLookupByLibrary.simpleMessage("نعم، تسجيل الخروج"), "yesRemove": MessageLookupByLibrary.simpleMessage("نعم، إزالة"), "yesRenew": MessageLookupByLibrary.simpleMessage("نعم، تجديد"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_be.dart b/mobile/apps/photos/lib/generated/intl/messages_be.dart index 5e13c17451..41a53c6eaf 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_be.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_be.dart @@ -28,8 +28,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Ліст адпраўлены на электронную пошту ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "about": MessageLookupByLibrary.simpleMessage("Пра праграму"), @@ -297,7 +295,6 @@ class MessageLookup extends MessageLookupByLibrary { "weHaveSendEmailTo": m114, "weakStrength": MessageLookupByLibrary.simpleMessage("Ненадзейны"), "welcomeBack": MessageLookupByLibrary.simpleMessage("З вяртаннем!"), - "wishThemAHappyBirthday": m115, "yesDelete": MessageLookupByLibrary.simpleMessage("Так, выдаліць"), "yesLogout": MessageLookupByLibrary.simpleMessage("Так, выйсці"), "yesRemove": MessageLookupByLibrary.simpleMessage("Так, выдаліць"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_bg.dart b/mobile/apps/photos/lib/generated/intl/messages_bg.dart index 9228905e66..e887127f40 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_bg.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_bg.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'bg'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_ca.dart b/mobile/apps/photos/lib/generated/intl/messages_ca.dart index c826f94abe..84dea987b0 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ca.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ca.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ca'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_cs.dart b/mobile/apps/photos/lib/generated/intl/messages_cs.dart index 911cb93921..64aec33ca1 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_cs.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_cs.dart @@ -32,8 +32,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m111(email) => "Ověřit ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m117(name) => "Vy a ${name}"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -80,10 +78,6 @@ class MessageLookup extends MessageLookupByLibrary { "archiveAlbum": MessageLookupByLibrary.simpleMessage("Archivovat album"), "archiving": MessageLookupByLibrary.simpleMessage("Archivování..."), - "areThey": MessageLookupByLibrary.simpleMessage("Are they "), - "areYouSureRemoveThisFaceFromPerson": - MessageLookupByLibrary.simpleMessage( - "Are you sure you want to remove this face from this person?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage("Opravdu se chcete odhlásit?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -365,8 +359,6 @@ class MessageLookup extends MessageLookupByLibrary { "openFile": MessageLookupByLibrary.simpleMessage("Otevřít soubor"), "openSettings": MessageLookupByLibrary.simpleMessage("Otevřít Nastavení"), - "otherDetectedFaces": - MessageLookupByLibrary.simpleMessage("Other detected faces"), "pair": MessageLookupByLibrary.simpleMessage("Spárovat"), "panorama": MessageLookupByLibrary.simpleMessage("Panorama"), "password": MessageLookupByLibrary.simpleMessage("Heslo"), @@ -390,7 +382,6 @@ class MessageLookup extends MessageLookupByLibrary { "processing": MessageLookupByLibrary.simpleMessage("Zpracovává se"), "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Veřejný odkaz vytvořen"), - "questionmark": MessageLookupByLibrary.simpleMessage("?"), "queued": MessageLookupByLibrary.simpleMessage("Ve frontě"), "radius": MessageLookupByLibrary.simpleMessage("Rádius"), "rateUs": MessageLookupByLibrary.simpleMessage("Ohodnoť nás"), @@ -442,8 +433,6 @@ class MessageLookup extends MessageLookupByLibrary { "safelyStored": MessageLookupByLibrary.simpleMessage("Bezpečně uloženo"), "save": MessageLookupByLibrary.simpleMessage("Uložit"), - "saveAsAnotherPerson": - MessageLookupByLibrary.simpleMessage("Save as another person"), "saveCopy": MessageLookupByLibrary.simpleMessage("Uložit kopii"), "saveKey": MessageLookupByLibrary.simpleMessage("Uložit klíč"), "savePerson": MessageLookupByLibrary.simpleMessage("Uložit osobu"), @@ -486,10 +475,6 @@ class MessageLookup extends MessageLookupByLibrary { "sharedWithMe": MessageLookupByLibrary.simpleMessage("Sdíleno se mnou"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Sdíleno s vámi"), "sharing": MessageLookupByLibrary.simpleMessage("Sdílení..."), - "showLessFaces": - MessageLookupByLibrary.simpleMessage("Show less faces"), - "showMoreFaces": - MessageLookupByLibrary.simpleMessage("Show more faces"), "skip": MessageLookupByLibrary.simpleMessage("Přeskočit"), "sorry": MessageLookupByLibrary.simpleMessage("Omlouváme se"), "sort": MessageLookupByLibrary.simpleMessage("Seřadit"), @@ -553,7 +538,6 @@ class MessageLookup extends MessageLookupByLibrary { "weakStrength": MessageLookupByLibrary.simpleMessage("Slabé"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Vítejte zpět!"), "whatsNew": MessageLookupByLibrary.simpleMessage("Co je nového"), - "wishThemAHappyBirthday": m115, "yearly": MessageLookupByLibrary.simpleMessage("Ročně"), "yes": MessageLookupByLibrary.simpleMessage("Ano"), "yesCancel": MessageLookupByLibrary.simpleMessage("Ano, zrušit"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_da.dart b/mobile/apps/photos/lib/generated/intl/messages_da.dart index aff66588e6..ba3d4075a5 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_da.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_da.dart @@ -49,8 +49,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Vi har sendt en email til ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "accountWelcomeBack": @@ -462,7 +460,6 @@ class MessageLookup extends MessageLookupByLibrary { "weakStrength": MessageLookupByLibrary.simpleMessage("Svagt"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Velkommen tilbage!"), - "wishThemAHappyBirthday": m115, "yesConvertToViewer": MessageLookupByLibrary.simpleMessage( "Ja, konverter til præsentation"), "yesRemove": MessageLookupByLibrary.simpleMessage("Ja, fjern"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_de.dart b/mobile/apps/photos/lib/generated/intl/messages_de.dart index 0412e5d31a..5b67f2f277 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_de.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_de.dart @@ -321,7 +321,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Wir haben eine E-Mail an ${email} gesendet"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "Wünsche ${name} alles Gute zum Geburtstag! 🎉"; static String m116(count) => "${Intl.plural(count, one: 'vor einem Jahr', other: 'vor ${count} Jahren')}"; @@ -425,6 +425,9 @@ class MessageLookup extends MessageLookupByLibrary { "Alle Erinnerungsstücke gesichert"), "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( "Alle Gruppierungen für diese Person werden zurückgesetzt und du wirst alle Vorschläge für diese Person verlieren"), + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": + MessageLookupByLibrary.simpleMessage( + "Alle unbenannten Gruppen werden zur ausgewählten Person zusammengeführt. Dies kann im Verlauf der Vorschläge für diese Person rückgängig gemacht werden."), "allWillShiftRangeBasedOnFirst": MessageLookupByLibrary.simpleMessage( "Dies ist die erste in der Gruppe. Andere ausgewählte Fotos werden automatisch nach diesem neuen Datum verschoben"), "allow": MessageLookupByLibrary.simpleMessage("Erlauben"), @@ -478,6 +481,9 @@ class MessageLookup extends MessageLookupByLibrary { "archiveAlbum": MessageLookupByLibrary.simpleMessage("Album archivieren"), "archiving": MessageLookupByLibrary.simpleMessage("Archiviere …"), + "areThey": MessageLookupByLibrary.simpleMessage("Ist das "), + "areYouSureRemoveThisFaceFromPerson": MessageLookupByLibrary.simpleMessage( + "Bist du sicher, dass du dieses Gesicht von dieser Person entfernen möchtest?"), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage( "Bist du sicher, dass du den Familien-Tarif verlassen möchtest?"), @@ -488,8 +494,16 @@ class MessageLookup extends MessageLookupByLibrary { "Bist du sicher, dass du deinen Tarif ändern möchtest?"), "areYouSureYouWantToExit": MessageLookupByLibrary.simpleMessage( "Möchtest du Vorgang wirklich abbrechen?"), + "areYouSureYouWantToIgnoreThesePersons": + MessageLookupByLibrary.simpleMessage( + "Bist du sicher, dass du diese Personen ignorieren willst?"), + "areYouSureYouWantToIgnoreThisPerson": + MessageLookupByLibrary.simpleMessage( + "Bist du sicher, dass du diese Person ignorieren willst?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "Bist Du sicher, dass du dich abmelden möchtest?"), + "areYouSureYouWantToMergeThem": MessageLookupByLibrary.simpleMessage( + "Bist du sicher, dass du sie zusammenführen willst?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Bist du sicher, dass du verlängern möchtest?"), "areYouSureYouWantToResetThisPerson": @@ -578,28 +592,29 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Black-Friday-Aktion"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), "cLDesc1": MessageLookupByLibrary.simpleMessage( - "Nach der Video-Streaming-Beta und der Arbeit an fortsetzbaren Uploads und Downloads haben wir das Datei-Upload-Limit auf 10 GB erhöht. Dies ist jetzt sowohl in Desktop- als auch in mobilen Apps verfügbar."), + "Zusammen mit der Beta-Version des Video-Streamings und der Arbeit an wiederaufnehmbarem Hoch- und Herunterladen haben wir jetzt das Limit für das Hochladen von Dateien auf 10 GB erhöht. Dies ist ab sofort sowohl in den Desktop- als auch Mobil-Apps verfügbar."), "cLDesc2": MessageLookupByLibrary.simpleMessage( - "Hintergrund-Uploads werden jetzt auch auf iOS unterstützt, zusätzlich zu Android-Geräten. Du musst die App nicht öffnen, um deine neuesten Fotos und Videos zu sichern."), + "Das Hochladen im Hintergrund wird jetzt auch unter iOS unterstützt, zusätzlich zu Android-Geräten. Es ist nicht mehr notwendig, die App zu öffnen, um die letzten Fotos und Videos zu sichern."), "cLDesc3": MessageLookupByLibrary.simpleMessage( - "Wir haben erhebliche Verbesserungen an unserer Erinnerungserfahrung vorgenommen, einschließlich Autoplay, Wischen zur nächsten Erinnerung und vieles mehr."), + "Wir haben deutliche Verbesserungen an der Darstellung von Erinnerungen vorgenommen, u.a. automatische Wiedergabe, Wischen zur nächsten Erinnerung und vieles mehr."), "cLDesc4": MessageLookupByLibrary.simpleMessage( - "Zusammen mit vielen internen Verbesserungen ist es jetzt viel einfacher, alle erkannten Gesichter zu sehen, Feedback zu ähnlichen Gesichtern zu geben und Gesichter zu einem einzelnen Foto hinzuzufügen/zu entfernen."), + "Zusammen mit einer Reihe von Verbesserungen unter der Haube ist es jetzt viel einfacher, alle erkannten Gesichter zu sehen, Feedback zu ähnlichen Gesichtern geben und Gesichter für ein einzelnes Foto hinzuzufügen oder zu entfernen."), "cLDesc5": MessageLookupByLibrary.simpleMessage( - "Du erhältst jetzt eine optionale Benachrichtigung für alle Geburtstage, die du auf Ente gespeichert hast, zusammen mit einer Sammlung ihrer besten Fotos."), + "Du erhältst jetzt eine Opt-Out-Benachrichtigung für alle Geburtstage, die du bei Ente gespeichert hast, zusammen mit einer Sammlung der besten Fotos."), "cLDesc6": MessageLookupByLibrary.simpleMessage( - "Kein Warten mehr darauf, dass Uploads/Downloads abgeschlossen werden, bevor du die App schließen kannst. Alle Uploads und Downloads können jetzt mitten im Vorgang pausiert und von dort fortgesetzt werden, wo du aufgehört hast."), - "cLTitle1": - MessageLookupByLibrary.simpleMessage("Upload großer Videodateien"), - "cLTitle2": MessageLookupByLibrary.simpleMessage("Hintergrund-Upload"), - "cLTitle3": - MessageLookupByLibrary.simpleMessage("Autoplay-Erinnerungen"), + "Kein Warten mehr auf das Hoch- oder Herunterladen, bevor du die App schließen kannst. Alle Übertragungen können jetzt mittendrin pausiert und fortgesetzt werden, wo du aufgehört hast."), + "cLTitle1": MessageLookupByLibrary.simpleMessage( + "Lade große Videodateien hoch"), + "cLTitle2": + MessageLookupByLibrary.simpleMessage("Hochladen im Hintergrund"), + "cLTitle3": MessageLookupByLibrary.simpleMessage( + "Automatische Wiedergabe von Erinnerungen"), "cLTitle4": MessageLookupByLibrary.simpleMessage( "Verbesserte Gesichtserkennung"), "cLTitle5": MessageLookupByLibrary.simpleMessage( "Geburtstags-Benachrichtigungen"), "cLTitle6": MessageLookupByLibrary.simpleMessage( - "Fortsetzbare Uploads und Downloads"), + "Wiederaufnehmbares Hoch- und Herunterladen"), "cachedData": MessageLookupByLibrary.simpleMessage("Daten im Cache"), "calculating": MessageLookupByLibrary.simpleMessage("Wird berechnet..."), @@ -855,6 +870,7 @@ class MessageLookup extends MessageLookupByLibrary { "deviceNotFound": MessageLookupByLibrary.simpleMessage("Gerät nicht gefunden"), "didYouKnow": MessageLookupByLibrary.simpleMessage("Schon gewusst?"), + "different": MessageLookupByLibrary.simpleMessage("Verschieden"), "disableAutoLock": MessageLookupByLibrary.simpleMessage( "Automatische Sperre deaktivieren"), "disableDownloadWarningBody": MessageLookupByLibrary.simpleMessage( @@ -1152,6 +1168,7 @@ class MessageLookup extends MessageLookupByLibrary { "iOSLockOut": MessageLookupByLibrary.simpleMessage( "Die biometrische Authentifizierung ist deaktiviert. Bitte sperren und entsperren Sie Ihren Bildschirm, um sie zu aktivieren."), "iOSOkButton": MessageLookupByLibrary.simpleMessage("OK"), + "ignore": MessageLookupByLibrary.simpleMessage("Ignorieren"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("Ignorieren"), "ignored": MessageLookupByLibrary.simpleMessage("ignoriert"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( @@ -1171,6 +1188,8 @@ class MessageLookup extends MessageLookupByLibrary { "Falscher Wiederherstellungs-Schlüssel"), "indexedItems": MessageLookupByLibrary.simpleMessage("Indizierte Elemente"), + "indexingPausedStatusDescription": MessageLookupByLibrary.simpleMessage( + "Die Indizierung ist pausiert. Sie wird automatisch fortgesetzt, wenn das Gerät bereit ist. Das Gerät wird als bereit angesehen, wenn sich der Akkustand, die Akkugesundheit und der thermische Zustand in einem gesunden Bereich befinden."), "ineligible": MessageLookupByLibrary.simpleMessage("Unzulässig"), "info": MessageLookupByLibrary.simpleMessage("Info"), "insecureDevice": @@ -1354,6 +1373,7 @@ class MessageLookup extends MessageLookupByLibrary { "Wähle die Arten von Erinnerungen, die du auf der Startseite sehen möchtest."), "memoryCount": m50, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), + "merge": MessageLookupByLibrary.simpleMessage("Zusammenführen"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage( "Mit vorhandenem zusammenführen"), "mergedPhotos": @@ -1493,6 +1513,8 @@ class MessageLookup extends MessageLookupByLibrary { "Oder eine vorherige auswählen"), "orPickFromYourContacts": MessageLookupByLibrary.simpleMessage( "oder wähle aus deinen Kontakten"), + "otherDetectedFaces": + MessageLookupByLibrary.simpleMessage("Andere erkannte Gesichter"), "pair": MessageLookupByLibrary.simpleMessage("Koppeln"), "pairWithPin": MessageLookupByLibrary.simpleMessage("Mit PIN verbinden"), @@ -1624,6 +1646,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Öffentlicher Link erstellt"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("Öffentlicher Link aktiviert"), + "questionmark": MessageLookupByLibrary.simpleMessage("?"), "queued": MessageLookupByLibrary.simpleMessage("In der Warteschlange"), "quickLinks": MessageLookupByLibrary.simpleMessage("Quick Links"), "radius": MessageLookupByLibrary.simpleMessage("Umkreis"), @@ -1740,6 +1763,7 @@ class MessageLookup extends MessageLookupByLibrary { "reportBug": MessageLookupByLibrary.simpleMessage("Fehler melden"), "resendEmail": MessageLookupByLibrary.simpleMessage("E-Mail erneut senden"), + "reset": MessageLookupByLibrary.simpleMessage("Zurücksetzen"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage( "Ignorierte Dateien zurücksetzen"), "resetPasswordTitle": @@ -1767,7 +1791,11 @@ class MessageLookup extends MessageLookupByLibrary { "rotateRight": MessageLookupByLibrary.simpleMessage("Nach rechts drehen"), "safelyStored": MessageLookupByLibrary.simpleMessage("Gesichert"), + "same": MessageLookupByLibrary.simpleMessage("Gleich"), + "sameperson": MessageLookupByLibrary.simpleMessage("Dieselbe Person?"), "save": MessageLookupByLibrary.simpleMessage("Speichern"), + "saveAsAnotherPerson": + MessageLookupByLibrary.simpleMessage("Als andere Person speichern"), "saveChangesBeforeLeavingQuestion": MessageLookupByLibrary.simpleMessage( "Änderungen vor dem Verlassen speichern?"), @@ -1928,8 +1956,12 @@ class MessageLookup extends MessageLookupByLibrary { "sharing": MessageLookupByLibrary.simpleMessage("Teilt..."), "shiftDatesAndTime": MessageLookupByLibrary.simpleMessage( "Datum und Uhrzeit verschieben"), + "showLessFaces": + MessageLookupByLibrary.simpleMessage("Weniger Gesichter zeigen"), "showMemories": MessageLookupByLibrary.simpleMessage("Erinnerungen anschauen"), + "showMoreFaces": + MessageLookupByLibrary.simpleMessage("Mehr Gesichter zeigen"), "showPerson": MessageLookupByLibrary.simpleMessage("Person anzeigen"), "signOutFromOtherDevices": MessageLookupByLibrary.simpleMessage( "Von anderen Geräten abmelden"), @@ -2057,6 +2089,10 @@ class MessageLookup extends MessageLookupByLibrary { "theLinkYouAreTryingToAccessHasExpired": MessageLookupByLibrary.simpleMessage( "Der Link, den du aufrufen möchtest, ist abgelaufen."), + "thePersonGroupsWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Diese Personengruppen werden im Personen-Abschnitt nicht mehr angezeigt. Die Fotos bleiben unverändert."), + "thePersonWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Diese Person wird im Personen-Abschnitt nicht mehr angezeigt. Die Fotos bleiben unverändert."), "theRecoveryKeyYouEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( "Der eingegebene Schlüssel ist ungültig"), @@ -2256,6 +2292,7 @@ class MessageLookup extends MessageLookupByLibrary { "yesDelete": MessageLookupByLibrary.simpleMessage("Ja, löschen"), "yesDiscardChanges": MessageLookupByLibrary.simpleMessage("Ja, Änderungen verwerfen"), + "yesIgnore": MessageLookupByLibrary.simpleMessage("Ja, ignorieren"), "yesLogout": MessageLookupByLibrary.simpleMessage("Ja, ausloggen"), "yesRemove": MessageLookupByLibrary.simpleMessage("Ja, entfernen"), "yesRenew": MessageLookupByLibrary.simpleMessage("Ja, erneuern"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_el.dart b/mobile/apps/photos/lib/generated/intl/messages_el.dart index 2af0da1ad8..79c0433b27 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_el.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_el.dart @@ -20,12 +20,9 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'el'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "enterYourEmailAddress": MessageLookupByLibrary.simpleMessage( - "Εισάγετε την διεύθυνση ηλ. ταχυδρομείου σας"), - "wishThemAHappyBirthday": m115 + "Εισάγετε την διεύθυνση ηλ. ταχυδρομείου σας") }; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_en.dart b/mobile/apps/photos/lib/generated/intl/messages_en.dart index f9bdd4c629..827e10e931 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_en.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_en.dart @@ -1005,6 +1005,8 @@ class MessageLookup extends MessageLookupByLibrary { "Face not clustered yet, please come back later"), "faceRecognition": MessageLookupByLibrary.simpleMessage("Face recognition"), + "faceThumbnailGenerationFailed": MessageLookupByLibrary.simpleMessage( + "Unable to generate face thumbnails"), "faces": MessageLookupByLibrary.simpleMessage("Faces"), "failed": MessageLookupByLibrary.simpleMessage("Failed"), "failedToApplyCode": @@ -1040,6 +1042,8 @@ class MessageLookup extends MessageLookupByLibrary { "feastingWithThem": m34, "feedback": MessageLookupByLibrary.simpleMessage("Feedback"), "file": MessageLookupByLibrary.simpleMessage("File"), + "fileAnalysisFailed": + MessageLookupByLibrary.simpleMessage("Unable to analyze file"), "fileFailedToSaveToGallery": MessageLookupByLibrary.simpleMessage( "Failed to save file to gallery"), "fileInfoAddDescHint": diff --git a/mobile/apps/photos/lib/generated/intl/messages_es.dart b/mobile/apps/photos/lib/generated/intl/messages_es.dart index c05563119e..30da4ea9d9 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_es.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_es.dart @@ -313,8 +313,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Hemos enviado un correo a ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, one: 'Hace ${count} año', other: 'Hace ${count} años')}"; @@ -554,30 +552,6 @@ class MessageLookup extends MessageLookupByLibrary { "blackFridaySale": MessageLookupByLibrary.simpleMessage("Oferta del Black Friday"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), - "cLDesc1": MessageLookupByLibrary.simpleMessage( - "Tras el lanzamiento de la versión beta de transmisión de video y el trabajo en subidas y descargas reanudables, ahora hemos aumentado el límite de subida de archivos a 10GB. Esto ya está disponible tanto en aplicaciones de escritorio como móviles."), - "cLDesc2": MessageLookupByLibrary.simpleMessage( - "Las subidas en segundo plano ahora también son compatibles con iOS, además de dispositivos Android. No necesitas abrir la aplicación para hacer una copia de seguridad de tus fotos y videos más recientes."), - "cLDesc3": MessageLookupByLibrary.simpleMessage( - "Hemos hecho mejoras significativas en nuestra experiencia de recuerdos, incluyendo reproducción automática, deslizar al siguiente recuerdo y mucho más."), - "cLDesc4": MessageLookupByLibrary.simpleMessage( - "Junto con un montón de mejoras internas, ahora es mucho más fácil ver todas las caras detectadas, proporcionar comentarios sobre caras similares y agregar/eliminar caras de una sola foto."), - "cLDesc5": MessageLookupByLibrary.simpleMessage( - "Ahora recibirás una notificación opcional para todos los cumpleaños que hayas guardado en Ente, junto con una colección de sus mejores fotos."), - "cLDesc6": MessageLookupByLibrary.simpleMessage( - "No más esperas para que se completen las subidas/descargas antes de poder cerrar la aplicación. Todas las subidas y descargas ahora tienen la capacidad de pausarse a mitad de camino y reanudarse desde donde lo dejaste."), - "cLTitle1": MessageLookupByLibrary.simpleMessage( - "Subida de archivos de video grandes"), - "cLTitle2": - MessageLookupByLibrary.simpleMessage("Subida en segundo plano"), - "cLTitle3": MessageLookupByLibrary.simpleMessage( - "Reproducción automática de recuerdos"), - "cLTitle4": MessageLookupByLibrary.simpleMessage( - "Reconocimiento facial mejorado"), - "cLTitle5": MessageLookupByLibrary.simpleMessage( - "Notificaciones de cumpleaños"), - "cLTitle6": MessageLookupByLibrary.simpleMessage( - "Subidas y descargas reanudables"), "cachedData": MessageLookupByLibrary.simpleMessage("Datos almacenados en caché"), "calculating": MessageLookupByLibrary.simpleMessage("Calculando..."), @@ -2199,7 +2173,6 @@ class MessageLookup extends MessageLookupByLibrary { "whatsNew": MessageLookupByLibrary.simpleMessage("Qué hay de nuevo"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage( "Un contacto de confianza puede ayudar a recuperar sus datos."), - "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("año"), "yearly": MessageLookupByLibrary.simpleMessage("Anualmente"), "yearsAgo": m116, diff --git a/mobile/apps/photos/lib/generated/intl/messages_et.dart b/mobile/apps/photos/lib/generated/intl/messages_et.dart index 65c40f7792..dc3a61a6ff 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_et.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_et.dart @@ -20,8 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'et'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "about": MessageLookupByLibrary.simpleMessage("Info"), @@ -260,7 +258,6 @@ class MessageLookup extends MessageLookupByLibrary { "weakStrength": MessageLookupByLibrary.simpleMessage("Nõrk"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Tere tulemast tagasi!"), - "wishThemAHappyBirthday": m115, "yes": MessageLookupByLibrary.simpleMessage("Jah"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage("Jah, muuda vaatajaks"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_eu.dart b/mobile/apps/photos/lib/generated/intl/messages_eu.dart index 2835aecade..232f0cdb1c 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_eu.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_eu.dart @@ -99,8 +99,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Mezua bidali dugu ${email} helbidera"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "accountWelcomeBack": @@ -631,7 +629,6 @@ class MessageLookup extends MessageLookupByLibrary { "weakStrength": MessageLookupByLibrary.simpleMessage("Ahula"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Ongi etorri berriro!"), - "wishThemAHappyBirthday": m115, "yesConvertToViewer": MessageLookupByLibrary.simpleMessage("Bai, egin ikusle"), "yesDelete": MessageLookupByLibrary.simpleMessage("Bai, ezabatu"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_fa.dart b/mobile/apps/photos/lib/generated/intl/messages_fa.dart index 52d3a0ab25..b2c0bfef1f 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_fa.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_fa.dart @@ -42,8 +42,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "ما یک ایمیل به ${email} ارسال کرده‌ایم"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "aNewVersionOfEnteIsAvailable": MessageLookupByLibrary.simpleMessage( @@ -426,7 +424,6 @@ class MessageLookup extends MessageLookupByLibrary { "weakStrength": MessageLookupByLibrary.simpleMessage("ضعیف"), "welcomeBack": MessageLookupByLibrary.simpleMessage("خوش آمدید!"), "whatsNew": MessageLookupByLibrary.simpleMessage("تغییرات جدید"), - "wishThemAHappyBirthday": m115, "yes": MessageLookupByLibrary.simpleMessage("بله"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage("بله، تبدیل به بیننده شود"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_fr.dart b/mobile/apps/photos/lib/generated/intl/messages_fr.dart index cd80d92698..0bd7ac8648 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_fr.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_fr.dart @@ -321,7 +321,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Nous avons envoyé un email à ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "Souhaitez à ${name} un joyeux anniversaire ! 🎉"; static String m116(count) => "${Intl.plural(count, one: 'il y a ${count} an', other: 'il y a ${count} ans')}"; @@ -427,6 +427,9 @@ class MessageLookup extends MessageLookupByLibrary { "Tous les souvenirs sont sauvegardés"), "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( "Tous les groupements pour cette personne seront réinitialisés, et vous perdrez toutes les suggestions faites pour cette personne"), + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": + MessageLookupByLibrary.simpleMessage( + "Tous les groupes sans nom seront fusionnés dans la personne sélectionnée. Cela peut toujours être annulé à partir de l\'historique des suggestions de la personne."), "allWillShiftRangeBasedOnFirst": MessageLookupByLibrary.simpleMessage( "C\'est la première dans le groupe. Les autres photos sélectionnées se déplaceront automatiquement en fonction de cette nouvelle date"), "allow": MessageLookupByLibrary.simpleMessage("Autoriser"), @@ -480,6 +483,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Archiver l\'album"), "archiving": MessageLookupByLibrary.simpleMessage("Archivage en cours..."), + "areThey": MessageLookupByLibrary.simpleMessage("Vraiment"), + "areYouSureRemoveThisFaceFromPerson": + MessageLookupByLibrary.simpleMessage( + "Êtes-vous sûr de vouloir retirer ce visage de cette personne ?"), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage( "Êtes-vous certains de vouloir quitter le plan familial?"), @@ -490,8 +497,16 @@ class MessageLookup extends MessageLookupByLibrary { "Êtes-vous certains de vouloir changer d\'offre ?"), "areYouSureYouWantToExit": MessageLookupByLibrary.simpleMessage( "Êtes-vous sûr de vouloir quitter ?"), + "areYouSureYouWantToIgnoreThesePersons": + MessageLookupByLibrary.simpleMessage( + "Êtes-vous sûr de vouloir ignorer ces personnes ?"), + "areYouSureYouWantToIgnoreThisPerson": + MessageLookupByLibrary.simpleMessage( + "Êtes-vous sûr de vouloir ignorer cette personne ?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "Voulez-vous vraiment vous déconnecter ?"), + "areYouSureYouWantToMergeThem": MessageLookupByLibrary.simpleMessage( + "Êtes-vous sûr de vouloir les fusionner?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Êtes-vous sûr de vouloir renouveler ?"), "areYouSureYouWantToResetThisPerson": @@ -583,29 +598,29 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Offre Black Friday"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), "cLDesc1": MessageLookupByLibrary.simpleMessage( - "Suite à la version bêta du streaming vidéo et au travail sur les téléchargements reprenables, nous avons maintenant augmenté la limite de téléchargement de fichiers à 10 Go. Ceci est maintenant disponible dans les applications desktop et mobiles."), + "Derrière la version beta du streaming vidéo, tout en travaillant sur la reprise des chargements et téléchargements, nous avons maintenant augmenté la limite de téléchargement de fichiers à 10 Go. Ceci est maintenant disponible dans les applications bureau et mobiles."), "cLDesc2": MessageLookupByLibrary.simpleMessage( - "Les téléchargements en arrière-plan sont maintenant pris en charge sur iOS également, en plus des appareils Android. Pas besoin d\'ouvrir l\'application pour sauvegarder vos dernières photos et vidéos."), + "Les chargements en arrière-plan sont maintenant pris en charge sur iOS, en plus des appareils Android. Inutile d\'ouvrir l\'application pour sauvegarder vos dernières photos et vidéos."), "cLDesc3": MessageLookupByLibrary.simpleMessage( - "Nous avons apporté des améliorations significatives à notre expérience de souvenirs, y compris la lecture automatique, le balayage vers le souvenir suivant et bien plus encore."), + "Nous avons apporté des améliorations significatives à l\'expérience des souvenirs, comme la lecture automatique, la glisse vers le souvenir suivant et bien plus encore."), "cLDesc4": MessageLookupByLibrary.simpleMessage( - "Avec un tas d\'améliorations internes, il est maintenant beaucoup plus facile de voir tous les visages détectés, de donner des commentaires sur les visages similaires et d\'ajouter/supprimer des visages d\'une seule photo."), + "Avec un tas d\'améliorations sous le capot, il est maintenant beaucoup plus facile de voir tous les visages détectés, mettre des commentaires sur des visages similaires, et ajouter/supprimer des visages depuis une seule photo."), "cLDesc5": MessageLookupByLibrary.simpleMessage( - "Vous recevrez maintenant une notification optionnelle pour tous les anniversaires que vous avez sauvegardés sur Ente, ainsi qu\'une collection de leurs meilleures photos."), + "Vous recevrez maintenant une notification de désinscription pour tous les anniversaires que vous avez enregistrés sur Ente, ainsi qu\'une collection de leurs meilleures photos."), "cLDesc6": MessageLookupByLibrary.simpleMessage( - "Plus besoin d\'attendre que les téléchargements se terminent avant de pouvoir fermer l\'application. Tous les téléchargements ont maintenant la capacité d\'être mis en pause à mi-chemin et de reprendre là où vous vous êtes arrêté."), + "Plus besoin d\'attendre la fin des chargements/téléchargements avant de pouvoir fermer l\'application. Tous peuvent maintenant être mis en pause en cours de route et reprendre à partir de là où ça s\'est arrêté."), "cLTitle1": MessageLookupByLibrary.simpleMessage( - "Téléchargement de fichiers vidéo volumineux"), - "cLTitle2": MessageLookupByLibrary.simpleMessage( - "Téléchargement en arrière-plan"), + "Envoi de gros fichiers vidéo"), + "cLTitle2": + MessageLookupByLibrary.simpleMessage("Charger en arrière-plan"), "cLTitle3": MessageLookupByLibrary.simpleMessage( "Lecture automatique des souvenirs"), "cLTitle4": MessageLookupByLibrary.simpleMessage( - "Reconnaissance faciale améliorée"), + "Amélioration de la reconnaissance faciale"), "cLTitle5": MessageLookupByLibrary.simpleMessage( - "Notifications d\'anniversaire"), - "cLTitle6": - MessageLookupByLibrary.simpleMessage("Téléchargements reprenables"), + "Notifications d’anniversaire"), + "cLTitle6": MessageLookupByLibrary.simpleMessage( + "Reprise des chargements et téléchargements"), "cachedData": MessageLookupByLibrary.simpleMessage("Données mises en cache"), "calculating": @@ -871,6 +886,7 @@ class MessageLookup extends MessageLookupByLibrary { "deviceNotFound": MessageLookupByLibrary.simpleMessage("Appareil non trouvé"), "didYouKnow": MessageLookupByLibrary.simpleMessage("Le savais-tu ?"), + "different": MessageLookupByLibrary.simpleMessage("Différent(e)"), "disableAutoLock": MessageLookupByLibrary.simpleMessage( "Désactiver le verrouillage automatique"), "disableDownloadWarningBody": MessageLookupByLibrary.simpleMessage( @@ -1169,6 +1185,7 @@ class MessageLookup extends MessageLookupByLibrary { "iOSLockOut": MessageLookupByLibrary.simpleMessage( "L\'authentification biométrique est désactivée. Veuillez verrouiller et déverrouiller votre écran pour l\'activer."), "iOSOkButton": MessageLookupByLibrary.simpleMessage("Ok"), + "ignore": MessageLookupByLibrary.simpleMessage("Ignorer"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("Ignorer"), "ignored": MessageLookupByLibrary.simpleMessage("ignoré"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( @@ -1190,6 +1207,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Clé de secours non valide"), "indexedItems": MessageLookupByLibrary.simpleMessage("Éléments indexés"), + "indexingPausedStatusDescription": MessageLookupByLibrary.simpleMessage( + "L\'indexation est en pause. Elle reprendra automatiquement lorsque l\'appareil sera prêt. Celui-ci est considéré comme prêt lorsque le niveau de batterie, sa santé et son état thermique sont dans une plage saine."), "ineligible": MessageLookupByLibrary.simpleMessage("Non compatible"), "info": MessageLookupByLibrary.simpleMessage("Info"), "insecureDevice": @@ -1377,6 +1396,7 @@ class MessageLookup extends MessageLookupByLibrary { "Sélectionnez le type de souvenirs que vous souhaitez voir sur votre écran d\'accueil."), "memoryCount": m50, "merchandise": MessageLookupByLibrary.simpleMessage("Boutique"), + "merge": MessageLookupByLibrary.simpleMessage("Fusionner"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("Fusionner avec existant"), "mergedPhotos": @@ -1519,6 +1539,8 @@ class MessageLookup extends MessageLookupByLibrary { "Ou sélectionner un email existant"), "orPickFromYourContacts": MessageLookupByLibrary.simpleMessage( "ou choisissez parmi vos contacts"), + "otherDetectedFaces": + MessageLookupByLibrary.simpleMessage("Autres visages détectés"), "pair": MessageLookupByLibrary.simpleMessage("Associer"), "pairWithPin": MessageLookupByLibrary.simpleMessage("Appairer avec le code PIN"), @@ -1657,6 +1679,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Lien public créé"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("Lien public activé"), + "questionmark": MessageLookupByLibrary.simpleMessage("?"), "queued": MessageLookupByLibrary.simpleMessage("En file d\'attente"), "quickLinks": MessageLookupByLibrary.simpleMessage("Liens rapides"), "radius": MessageLookupByLibrary.simpleMessage("Rayon"), @@ -1774,6 +1797,7 @@ class MessageLookup extends MessageLookupByLibrary { "reportBug": MessageLookupByLibrary.simpleMessage("Signaler un bogue"), "resendEmail": MessageLookupByLibrary.simpleMessage("Renvoyer l\'email"), + "reset": MessageLookupByLibrary.simpleMessage("Réinitialiser"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage( "Réinitialiser les fichiers ignorés"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage( @@ -1802,7 +1826,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Faire pivoter à droite"), "safelyStored": MessageLookupByLibrary.simpleMessage("Stockage sécurisé"), + "same": MessageLookupByLibrary.simpleMessage("Identique"), + "sameperson": MessageLookupByLibrary.simpleMessage("Même personne ?"), "save": MessageLookupByLibrary.simpleMessage("Sauvegarder"), + "saveAsAnotherPerson": MessageLookupByLibrary.simpleMessage( + "Enregistrer comme une autre personne"), "saveChangesBeforeLeavingQuestion": MessageLookupByLibrary.simpleMessage( "Enregistrer les modifications avant de quitter ?"), @@ -1974,8 +2002,12 @@ class MessageLookup extends MessageLookupByLibrary { "sharing": MessageLookupByLibrary.simpleMessage("Partage..."), "shiftDatesAndTime": MessageLookupByLibrary.simpleMessage("Dates et heure de décalage"), + "showLessFaces": + MessageLookupByLibrary.simpleMessage("Afficher moins de visages"), "showMemories": MessageLookupByLibrary.simpleMessage("Afficher les souvenirs"), + "showMoreFaces": + MessageLookupByLibrary.simpleMessage("Afficher plus de visages"), "showPerson": MessageLookupByLibrary.simpleMessage("Montrer la personne"), "signOutFromOtherDevices": MessageLookupByLibrary.simpleMessage( @@ -2104,6 +2136,10 @@ class MessageLookup extends MessageLookupByLibrary { "theLinkYouAreTryingToAccessHasExpired": MessageLookupByLibrary.simpleMessage( "Le lien que vous essayez d\'accéder a expiré."), + "thePersonGroupsWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Les groupes de personnes ne seront plus affichés dans la section personnes. Les photos resteront intactes."), + "thePersonWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Les groupes de personnes ne seront plus affichés dans la section personnes. Les photos resteront intactes."), "theRecoveryKeyYouEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( "La clé de récupération que vous avez entrée est incorrecte"), @@ -2307,6 +2343,7 @@ class MessageLookup extends MessageLookupByLibrary { "yesDelete": MessageLookupByLibrary.simpleMessage("Oui, supprimer"), "yesDiscardChanges": MessageLookupByLibrary.simpleMessage( "Oui, ignorer les modifications"), + "yesIgnore": MessageLookupByLibrary.simpleMessage("Oui, ignorer"), "yesLogout": MessageLookupByLibrary.simpleMessage("Oui, se déconnecter"), "yesRemove": MessageLookupByLibrary.simpleMessage("Oui, supprimer"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_gu.dart b/mobile/apps/photos/lib/generated/intl/messages_gu.dart index 886d0aadff..6c1d7e4d90 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_gu.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_gu.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'gu'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_he.dart b/mobile/apps/photos/lib/generated/intl/messages_he.dart index b0d3ee8e5c..28b4d06b6e 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_he.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_he.dart @@ -114,8 +114,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "שלחנו דוא\"ל ל${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, one: 'לפני ${count} שנה', other: 'לפני ${count} שנים')}"; @@ -910,7 +908,6 @@ class MessageLookup extends MessageLookupByLibrary { "weHaveSendEmailTo": m114, "weakStrength": MessageLookupByLibrary.simpleMessage("חלשה"), "welcomeBack": MessageLookupByLibrary.simpleMessage("ברוך שובך!"), - "wishThemAHappyBirthday": m115, "yearly": MessageLookupByLibrary.simpleMessage("שנתי"), "yearsAgo": m116, "yes": MessageLookupByLibrary.simpleMessage("כן"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_hi.dart b/mobile/apps/photos/lib/generated/intl/messages_hi.dart index a8910cfd07..ff4756d8d4 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_hi.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_hi.dart @@ -20,8 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'hi'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "accountWelcomeBack": @@ -107,7 +105,6 @@ class MessageLookup extends MessageLookupByLibrary { "verify": MessageLookupByLibrary.simpleMessage("सत्यापित करें"), "verifyEmail": MessageLookupByLibrary.simpleMessage("ईमेल सत्यापित करें"), - "wishThemAHappyBirthday": m115, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage( "आपका अकाउंट डिलीट कर दिया गया है") }; diff --git a/mobile/apps/photos/lib/generated/intl/messages_hu.dart b/mobile/apps/photos/lib/generated/intl/messages_hu.dart index 466fc30549..6099a04be2 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_hu.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_hu.dart @@ -20,27 +20,738 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'hu'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m8(count) => + "${Intl.plural(count, zero: 'Nincsenek résztvevők', one: '1 résztvevő', other: '${count} résztvevők')}"; + + static String m13(user) => + "${user} nem tud több fotót hozzáadni ehhez az albumhoz.\n\nTovábbra is el tudja távolítani az általa hozzáadott meglévő fotókat"; + + static String m14(isFamilyMember, storageAmountInGb) => + "${Intl.select(isFamilyMember, { + 'true': + 'A családod eddig ${storageAmountInGb} GB tárhelyet igényelt', + 'false': 'Eddig ${storageAmountInGb} GB tárhelyet igényelt', + 'other': 'Eddig ${storageAmountInGb} GB tárhelyet igényelt!', + })}"; + + static String m21(count) => + "${Intl.plural(count, one: 'Elem ${count} törlése', other: 'Elemek ${count} törlése')}"; + + static String m24(albumName) => + "Ez eltávolítja a(z) „${albumName}” eléréséhez szükséges nyilvános linket."; + + static String m25(supportEmail) => + "Kérjük küldjön egy e-mailt a fiók regisztrálásakor megadott címről a következőre címre: ${supportEmail}"; + + static String m27(count, formattedSize) => + "${count} fájl, ${formattedSize} mindegyik"; + + static String m31(email) => + "${email} címnek nincs Ente fiókja.\n\nKüldjön nekik meghívót fotók megosztására."; + + static String m37(storageAmountInGB) => + "${storageAmountInGB} GB minden alkalommal, amikor valaki fizetős csomagra fizet elő és felhasználja a kódodat"; + + static String m44(count) => "${Intl.plural(count, other: '${count} elem')}"; + + static String m47(expiryTime) => "Hivatkozás lejár ${expiryTime} "; + + static String m50(count, formattedCount) => + "${Intl.plural(count, zero: 'nincsenek emlékek', one: '${formattedCount} emlék', other: '${formattedCount} emlékek')}"; + + static String m55(familyAdminEmail) => + "Kérjük, vegye fel a kapcsolatot a ${familyAdminEmail} e-mail címmel a kód módosításához."; + + static String m57(passwordStrengthValue) => + "Jelszó erőssége: ${passwordStrengthValue}"; + + static String m73(storageInGB) => + "3. Mindketten ${storageInGB} GB* ingyenes tárhelyet kaptok"; + + static String m74(userEmail) => + "${userEmail} felhasználó el lesz távolítva ebből a megosztott albumból\n\nAz általa hozzáadott összes fotó is eltávolításra kerül az albumból."; + + static String m80(count) => "${count} kiválasztott"; + + static String m81(count, yourCount) => + "${count} kiválasztott (${yourCount} a tiéd)"; + + static String m83(verificationID) => + "Itt az ellenőrző azonosítóm: ${verificationID} az ente.io-hoz."; + + static String m84(verificationID) => + "Szia, meg tudnád erősíteni, hogy ez az ente.io ellenőrző azonosítód? ${verificationID}"; + + static String m85(referralCode, referralStorageInGB) => + "Add meg a következő ajánlási kódot: ${referralCode}\n\nAlkalmazd a Beállítások → Általános → Ajánlások menüpontban, hogy ${referralStorageInGB} GB ingyenes tárhelyet kapj, miután regisztráltál egy fizetős csomagra\n\nhttps://ente.io"; + + static String m86(numberOfPeople) => + "${Intl.plural(numberOfPeople, zero: 'Megosztás adott személyekkel', one: '1 személlyel megosztva', other: '${numberOfPeople} személlyel megosztva')}"; + + static String m88(fileType) => + "Ez a ${fileType} fájl törlődni fog az eszközéről."; + + static String m89(fileType) => + "Ez a ${fileType} fájltípus megtalálható mind az Enterben, mind az eszközödön."; + + static String m90(fileType) => "Ez a ${fileType} fájl törlődik az Ente-ből."; + + static String m93(storageAmountInGB) => "${storageAmountInGB} GB"; + + static String m99(storageAmountInGB) => + "Emellett ${storageAmountInGB} GB-ot kapnak"; + + static String m100(email) => "Ez ${email} ellenőrző azonosítója"; + + static String m111(email) => "${email} ellenőrzése"; + + static String m114(email) => + "E-mailt küldtünk a következő címre: ${email}"; + + static String m116(count) => + "${Intl.plural(count, one: '${count} évvel ezelőtt', other: '${count} évekkel ezelőtt')}"; + + static String m118(storageSaved) => + "Sikeresen felszabadítottál ${storageSaved} tárhelyet!"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { + "aNewVersionOfEnteIsAvailable": MessageLookupByLibrary.simpleMessage( + "Megjelent az Ente új verziója."), + "about": MessageLookupByLibrary.simpleMessage("Rólunk"), + "account": MessageLookupByLibrary.simpleMessage("Fiók"), "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("Köszöntjük ismét!"), + "ackPasswordLostWarning": MessageLookupByLibrary.simpleMessage( + "Tudomásul veszem, hogy ha elveszítem a jelszavamat, elveszíthetem az adataimat, mivel adataim végponttól végpontig titkosítva vannak."), + "activeSessions": + MessageLookupByLibrary.simpleMessage("Bejelentkezések"), + "addANewEmail": + MessageLookupByLibrary.simpleMessage("Új email cím hozzáadása"), + "addCollaborator": + MessageLookupByLibrary.simpleMessage("Együttműködő hozzáadása"), + "addMore": MessageLookupByLibrary.simpleMessage("További hozzáadása"), + "addViewer": MessageLookupByLibrary.simpleMessage( + "Megtekintésre jogosult hozzáadása"), + "addedAs": MessageLookupByLibrary.simpleMessage("Hozzáadva mint"), + "addingToFavorites": + MessageLookupByLibrary.simpleMessage("Hozzáadás a kedvencekhez..."), + "advancedSettings": MessageLookupByLibrary.simpleMessage("Haladó"), + "after1Day": MessageLookupByLibrary.simpleMessage("Egy nap mólva"), + "after1Hour": MessageLookupByLibrary.simpleMessage("Egy óra múlva"), + "after1Month": MessageLookupByLibrary.simpleMessage("Egy hónap múlva"), + "after1Week": MessageLookupByLibrary.simpleMessage("Egy hét múlva"), + "after1Year": MessageLookupByLibrary.simpleMessage("Egy év múlva"), + "albumOwner": MessageLookupByLibrary.simpleMessage("Tulajdonos"), + "albumParticipantsCount": m8, + "albumUpdated": MessageLookupByLibrary.simpleMessage("Album módosítva"), + "albums": MessageLookupByLibrary.simpleMessage("Album"), + "allClear": MessageLookupByLibrary.simpleMessage("✨ Minden tiszta"), + "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( + "Engedélyezd a linkkel rendelkező személyeknek, hogy ők is hozzáadhassanak fotókat a megosztott albumhoz."), + "allowAddingPhotos": MessageLookupByLibrary.simpleMessage( + "Fotók hozzáadásának engedélyezése"), + "allowDownloads": + MessageLookupByLibrary.simpleMessage("Letöltések engedélyezése"), + "apply": MessageLookupByLibrary.simpleMessage("Alkalmaz"), + "applyCodeTitle": + MessageLookupByLibrary.simpleMessage("Kód alkalmazása"), + "archive": MessageLookupByLibrary.simpleMessage("Archívum"), + "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( + "Biztos benne, hogy kijelentkezik?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage("Miért törli a fiókját?"), + "authToChangeEmailVerificationSetting": + MessageLookupByLibrary.simpleMessage( + "Kérjük, hitelesítse magát az e-mail-cím ellenőrzésének módosításához"), + "authToChangeYourEmail": MessageLookupByLibrary.simpleMessage( + "Kérjük, hitelesítse magát az e-mail címének módosításához"), + "authToChangeYourPassword": MessageLookupByLibrary.simpleMessage( + "Kérjük, hitelesítse magát a jelszó módosításához"), + "authToInitiateAccountDeletion": MessageLookupByLibrary.simpleMessage( + "Kérjük, hitelesítse magát a fiók törlésének megkezdéséhez"), + "authToViewTrashedFiles": MessageLookupByLibrary.simpleMessage( + "Kérjük, hitelesítse magát a kukába helyezett fájlok megtekintéséhez"), + "authToViewYourHiddenFiles": MessageLookupByLibrary.simpleMessage( + "Kérjük, hitelesítse magát a rejtett fájlok megtekintéséhez"), + "backedUpFolders": MessageLookupByLibrary.simpleMessage( + "Biztonsági másolatban lévő mappák"), + "backup": MessageLookupByLibrary.simpleMessage("Biztonsági mentés"), + "backupOverMobileData": MessageLookupByLibrary.simpleMessage( + "Biztonsági mentés mobil adatkapcsolaton keresztül"), + "backupSettings": MessageLookupByLibrary.simpleMessage( + "Biztonsági mentés beállításai"), + "backupStatus": + MessageLookupByLibrary.simpleMessage("Biztonsági mentés állapota"), + "backupStatusDescription": MessageLookupByLibrary.simpleMessage( + "Azok az elemek jelennek meg itt, amelyekről biztonsági másolat készült"), + "backupVideos": MessageLookupByLibrary.simpleMessage("Tartalék videók"), + "canNotOpenBody": MessageLookupByLibrary.simpleMessage( + "Sajnálom, ez az album nem nyitható meg ebben az applikációban."), + "canNotOpenTitle": + MessageLookupByLibrary.simpleMessage("Album nem nyitható meg"), + "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( + "Csak a saját tulajdonú fájlokat távolíthatja el"), "cancel": MessageLookupByLibrary.simpleMessage("Mégse"), + "cannotAddMorePhotosAfterBecomingViewer": m13, + "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( + "Nem lehet törölni a megosztott fájlokat"), + "change": MessageLookupByLibrary.simpleMessage("Módosítás"), + "changeEmail": + MessageLookupByLibrary.simpleMessage("E-mail cím módosítása"), + "changePassword": + MessageLookupByLibrary.simpleMessage("Jelszó megváltoztatása"), + "changePasswordTitle": + MessageLookupByLibrary.simpleMessage("Jelszó megváltoztatása"), + "changePermissions": + MessageLookupByLibrary.simpleMessage("Engedélyek módosítása?"), + "changeYourReferralCode": + MessageLookupByLibrary.simpleMessage("Módosítsa ajánló kódját"), + "checkForUpdates": + MessageLookupByLibrary.simpleMessage("Frissítések ellenőrzése"), + "checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage( + "Kérjük, ellenőrizze beérkező leveleit (és spam mappát) az ellenőrzés befejezéséhez"), + "checkStatus": + MessageLookupByLibrary.simpleMessage("Állapot ellenőrzése"), + "checking": MessageLookupByLibrary.simpleMessage("Ellenőrzés..."), + "claimFreeStorage": MessageLookupByLibrary.simpleMessage( + "Igényeljen ingyenes tárhelyet"), + "claimMore": MessageLookupByLibrary.simpleMessage("Igényelj többet!"), + "claimed": MessageLookupByLibrary.simpleMessage("Megszerezve!"), + "claimedStorageSoFar": m14, + "clearIndexes": MessageLookupByLibrary.simpleMessage("Indexek törlése"), + "codeAppliedPageTitle": + MessageLookupByLibrary.simpleMessage("Kód alkalmazva"), + "codeChangeLimitReached": MessageLookupByLibrary.simpleMessage( + "Sajnáljuk, elérted a kódmódosítások maximális számát."), + "codeCopiedToClipboard": + MessageLookupByLibrary.simpleMessage("A kód a vágólapra másolva"), + "codeUsedByYou": + MessageLookupByLibrary.simpleMessage("Ön által használt kód"), + "collabLinkSectionDescription": MessageLookupByLibrary.simpleMessage( + "Hozzon létre egy hivatkozást, amely lehetővé teszi az emberek számára, hogy fotókat adhassanak hozzá és tekintsenek meg megosztott albumában anélkül, hogy Ente alkalmazásra vagy fiókra lenne szükségük. Kiválóan alkalmas rendezvényfotók gyűjtésére."), + "collaborativeLink": + MessageLookupByLibrary.simpleMessage("Együttműködési hivatkozás"), + "collaborator": MessageLookupByLibrary.simpleMessage("Együttműködő"), + "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": + MessageLookupByLibrary.simpleMessage( + "Az együttműködők hozzá adhatnak fotókat és videókat a megosztott albumban."), + "collectPhotos": MessageLookupByLibrary.simpleMessage("Fotók gyűjtése"), + "confirm": MessageLookupByLibrary.simpleMessage("Megerősítés"), + "confirmAccountDeletion": MessageLookupByLibrary.simpleMessage( + "Felhasználó Törlés Megerősítés"), + "confirmDeletePrompt": MessageLookupByLibrary.simpleMessage( + "Igen, szeretném véglegesen törölni ezt a felhasználót, minden adattal, az összes platformon."), + "confirmPassword": + MessageLookupByLibrary.simpleMessage("Jelszó megerősítés"), + "confirmRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Helyreállítási kulcs megerősítése"), + "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Erősítse meg helyreállítási kulcsát"), + "contactSupport": MessageLookupByLibrary.simpleMessage( + "Lépj kapcsolatba az Ügyfélszolgálattal"), + "continueLabel": MessageLookupByLibrary.simpleMessage("Folytatás"), + "copyLink": MessageLookupByLibrary.simpleMessage("Hivatkozás másolása"), + "copypasteThisCodentoYourAuthenticatorApp": + MessageLookupByLibrary.simpleMessage( + "Kód Másolása-Beillesztése az ön autentikátor alkalmazásába"), + "createAccount": + MessageLookupByLibrary.simpleMessage("Felhasználó létrehozás"), + "createAlbumActionHint": MessageLookupByLibrary.simpleMessage( + "Hosszan nyomva tartva kiválaszthatod a fotókat, majd a + jelre kattintva albumot hozhatsz létre"), + "createNewAccount": + MessageLookupByLibrary.simpleMessage("Új felhasználó létrehozás"), + "createPublicLink": MessageLookupByLibrary.simpleMessage( + "Nyilvános hivatkozás létrehozása"), + "creatingLink": + MessageLookupByLibrary.simpleMessage("Link létrehozása..."), + "criticalUpdateAvailable": + MessageLookupByLibrary.simpleMessage("Kritikus frissítés elérhető"), + "custom": MessageLookupByLibrary.simpleMessage("Egyéni"), + "decrypting": MessageLookupByLibrary.simpleMessage("Dekódolás..."), "deleteAccount": MessageLookupByLibrary.simpleMessage("Fiók törlése"), "deleteAccountFeedbackPrompt": MessageLookupByLibrary.simpleMessage( "Sajnáljuk, hogy távozik. Kérjük, ossza meg velünk visszajelzéseit, hogy segítsen nekünk a fejlődésben."), + "deleteAccountPermanentlyButton": MessageLookupByLibrary.simpleMessage( + "Felhasználó Végleges Törlése"), + "deleteAlbum": MessageLookupByLibrary.simpleMessage("Album törlése"), + "deleteAlbumDialog": MessageLookupByLibrary.simpleMessage( + "Törli az ebben az albumban található fotókat (és videókat) az összes többi albumból is, amelynek részét képezik?"), + "deleteEmailRequest": MessageLookupByLibrary.simpleMessage( + "Kérem küldjön egy emailt a regisztrált email címéről, erre az emailcímre: account-deletion@ente.io."), + "deleteFromBoth": + MessageLookupByLibrary.simpleMessage("Törlés mindkettőből"), + "deleteFromDevice": + MessageLookupByLibrary.simpleMessage("Törlés az eszközről"), + "deleteFromEnte": + MessageLookupByLibrary.simpleMessage("Törlés az Ente-ből"), + "deleteItemCount": m21, + "deletePhotos": MessageLookupByLibrary.simpleMessage("Fotók törlése"), + "deleteReason1": MessageLookupByLibrary.simpleMessage( + "Hiányoznak olyan funkciók, amikre szükségem lenne"), + "deleteReason2": MessageLookupByLibrary.simpleMessage( + "Az applikáció vagy egy adott funkció nem úgy működik ahogy kellene"), + "deleteReason3": MessageLookupByLibrary.simpleMessage( + "Találtam egy jobb szolgáltatót"), + "deleteReason4": + MessageLookupByLibrary.simpleMessage("Nincs a listán az ok"), + "deleteRequestSLAText": MessageLookupByLibrary.simpleMessage( + "A kérése 72 órán belül feldolgozásra kerül."), + "deleteSharedAlbum": + MessageLookupByLibrary.simpleMessage("Törli a megosztott albumot?"), + "deleteSharedAlbumDialogBody": MessageLookupByLibrary.simpleMessage( + "Az album mindenki számára törlődik.\n\nElveszíti a hozzáférést az albumban található, mások tulajdonában lévő megosztott fotókhoz."), + "details": MessageLookupByLibrary.simpleMessage("Részletek"), + "deviceLockExplanation": MessageLookupByLibrary.simpleMessage( + "Disable the device screen lock when Ente is in the foreground and there is a backup in progress. This is normally not needed, but may help big uploads and initial imports of large libraries complete faster."), + "disableAutoLock": + MessageLookupByLibrary.simpleMessage("Automatikus zár letiltása"), + "disableDownloadWarningBody": MessageLookupByLibrary.simpleMessage( + "A nézők továbbra is készíthetnek képernyőképeket, vagy menthetnek másolatot a fotóidról külső eszközök segítségével"), + "disableDownloadWarningTitle": + MessageLookupByLibrary.simpleMessage("Kérjük, vedd figyelembe"), + "disableLinkMessage": m24, + "discover": MessageLookupByLibrary.simpleMessage("Felfedezés"), + "discover_babies": MessageLookupByLibrary.simpleMessage("Babák"), + "discover_celebrations": + MessageLookupByLibrary.simpleMessage("Ünnepségek"), + "discover_food": MessageLookupByLibrary.simpleMessage("Étel"), + "discover_greenery": MessageLookupByLibrary.simpleMessage("Lomb"), + "discover_hills": MessageLookupByLibrary.simpleMessage("Dombok"), + "discover_identity": + MessageLookupByLibrary.simpleMessage("Személyazonosság"), + "discover_memes": MessageLookupByLibrary.simpleMessage("Mémek"), + "discover_notes": MessageLookupByLibrary.simpleMessage("Jegyzetek"), + "discover_pets": MessageLookupByLibrary.simpleMessage("Kisállatok"), + "discover_receipts": MessageLookupByLibrary.simpleMessage("Nyugták"), + "discover_screenshots": + MessageLookupByLibrary.simpleMessage("Képernyőképek"), + "discover_selfies": MessageLookupByLibrary.simpleMessage("Szelfik"), + "discover_sunset": MessageLookupByLibrary.simpleMessage("Napnyugta"), + "discover_visiting_cards": + MessageLookupByLibrary.simpleMessage("Névjegykártyák"), + "discover_wallpapers": + MessageLookupByLibrary.simpleMessage("Háttérképek"), + "doThisLater": MessageLookupByLibrary.simpleMessage("Később"), + "done": MessageLookupByLibrary.simpleMessage("Kész"), + "downloading": MessageLookupByLibrary.simpleMessage("Letöltés..."), + "dropSupportEmail": m25, + "duplicateItemsGroup": m27, + "eligible": MessageLookupByLibrary.simpleMessage("jogosult"), "email": MessageLookupByLibrary.simpleMessage("E-mail"), + "emailAlreadyRegistered": + MessageLookupByLibrary.simpleMessage("Az email cím már foglalt."), + "emailNoEnteAccount": m31, + "emailNotRegistered": + MessageLookupByLibrary.simpleMessage("Nem regisztrált email cím."), + "emailVerificationToggle": + MessageLookupByLibrary.simpleMessage("E-mail cím ellenőrzése"), + "encryption": MessageLookupByLibrary.simpleMessage("Titkosítás"), + "encryptionKeys": + MessageLookupByLibrary.simpleMessage("Titkosító kulcsok"), + "entePhotosPerm": MessageLookupByLibrary.simpleMessage( + "Az Entének engedélyre van szüksége , hogy tárolhassa fotóit"), + "enterCode": MessageLookupByLibrary.simpleMessage("Kód beírása"), + "enterCodeDescription": MessageLookupByLibrary.simpleMessage( + "Add meg a barátod által megadott kódot, hogy mindkettőtöknek ingyenes tárhelyet igényelhess"), + "enterEmail": MessageLookupByLibrary.simpleMessage("Email megadása"), + "enterNewPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( + "Adjon meg egy új jelszót, amellyel titkosíthatjuk adatait"), + "enterPassword": + MessageLookupByLibrary.simpleMessage("Adja meg a jelszót"), + "enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( + "Adjon meg egy jelszót, amellyel titkosíthatjuk adatait"), + "enterReferralCode": + MessageLookupByLibrary.simpleMessage("Adja meg az ajánló kódot"), + "enterThe6digitCodeFromnyourAuthenticatorApp": + MessageLookupByLibrary.simpleMessage( + "Írja be a 6 számjegyű kódot a hitelesítő alkalmazásból"), "enterValidEmail": MessageLookupByLibrary.simpleMessage( "Kérjük, adjon meg egy érvényes e-mail címet."), "enterYourEmailAddress": MessageLookupByLibrary.simpleMessage("Adja meg az e-mail címét"), + "enterYourNewEmailAddress": + MessageLookupByLibrary.simpleMessage("Add meg az új email címed"), + "enterYourPassword": + MessageLookupByLibrary.simpleMessage("Adja meg a jelszavát"), + "enterYourRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Adja meg visszaállítási kulcsát"), + "expiredLinkInfo": MessageLookupByLibrary.simpleMessage( + "Ez a link lejárt. Kérjük, válasszon új lejárati időt, vagy tiltsa le a link lejáratát."), + "exportYourData": + MessageLookupByLibrary.simpleMessage("Adatok exportálása"), + "failedToApplyCode": MessageLookupByLibrary.simpleMessage( + "Nem sikerült alkalmazni a kódot"), + "failedToFetchReferralDetails": MessageLookupByLibrary.simpleMessage( + "Nem sikerült lekérni a hivatkozási adatokat. Kérjük, próbálja meg később."), + "failedToLoadAlbums": MessageLookupByLibrary.simpleMessage( + "Nem sikerült betölteni az albumokat"), + "faq": MessageLookupByLibrary.simpleMessage("GY. I. K."), "feedback": MessageLookupByLibrary.simpleMessage("Visszajelzés"), + "forgotPassword": + MessageLookupByLibrary.simpleMessage("Elfelejtett jelszó"), + "freeStorageClaimed": + MessageLookupByLibrary.simpleMessage("Ingyenes tárhely igénylése"), + "freeStorageOnReferralSuccess": m37, + "freeStorageUsable": MessageLookupByLibrary.simpleMessage( + "Ingyenesen használható tárhely"), + "freeUpDeviceSpace": + MessageLookupByLibrary.simpleMessage("Szabadítson fel tárhelyet"), + "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( + "Takarítson meg helyet az eszközén a már mentett fájlok törlésével."), + "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( + "Titkosítási kulcs generálása..."), + "help": MessageLookupByLibrary.simpleMessage("Segítség"), + "hidden": MessageLookupByLibrary.simpleMessage("Rejtett"), + "howItWorks": MessageLookupByLibrary.simpleMessage("Hogyan működik"), + "howToViewShareeVerificationID": MessageLookupByLibrary.simpleMessage( + "Kérje meg őket, hogy hosszan nyomják meg az e-mail címüket a beállítások képernyőn, és ellenőrizzék, hogy a két eszköz azonosítója megegyezik-e."), + "ignoreUpdate": + MessageLookupByLibrary.simpleMessage("Figyelem kívül hagyás"), + "importing": MessageLookupByLibrary.simpleMessage("Importálás..."), + "incorrectPasswordTitle": + MessageLookupByLibrary.simpleMessage("Érvénytelen jelszó"), + "incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage( + "A megadott visszaállítási kulcs hibás"), + "incorrectRecoveryKeyTitle": + MessageLookupByLibrary.simpleMessage("Hibás visszaállítási kulcs"), + "indexedItems": MessageLookupByLibrary.simpleMessage("Indexelt elemek"), + "insecureDevice": + MessageLookupByLibrary.simpleMessage("Nem biztonságos eszköz"), + "installManually": + MessageLookupByLibrary.simpleMessage("Manuális telepítés"), "invalidEmailAddress": MessageLookupByLibrary.simpleMessage("Érvénytelen e-mail cím"), + "invalidKey": MessageLookupByLibrary.simpleMessage("Érvénytelen kulcs"), + "invalidRecoveryKey": MessageLookupByLibrary.simpleMessage( + "A megadott helyreállítási kulcs érvénytelen. Kérjük, győződjön meg róla, hogy 24 szót tartalmaz, és ellenőrizze mindegyik helyesírását.\n\nHa régebbi helyreállítási kódot adott meg, győződjön meg arról, hogy az 64 karakter hosszú, és ellenőrizze mindegyiket."), + "inviteToEnte": + MessageLookupByLibrary.simpleMessage("Meghívás az Ente-re"), + "inviteYourFriends": + MessageLookupByLibrary.simpleMessage("Hívd meg a barátaidat"), + "itemCount": m44, + "itemsWillBeRemovedFromAlbum": MessageLookupByLibrary.simpleMessage( + "A kiválasztott elemek eltávolításra kerülnek ebből az albumból."), + "keepPhotos": MessageLookupByLibrary.simpleMessage("Fotók megőrzése"), + "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage( + "Legyen kedves segítsen, ezzel az információval"), + "linkDeviceLimit": + MessageLookupByLibrary.simpleMessage("Készülékkorlát"), + "linkEnabled": MessageLookupByLibrary.simpleMessage("Engedélyezett"), + "linkExpired": MessageLookupByLibrary.simpleMessage("Lejárt"), + "linkExpiresOn": m47, + "linkExpiry": MessageLookupByLibrary.simpleMessage("Link lejárata"), + "linkHasExpired": MessageLookupByLibrary.simpleMessage( + "A hivatkozás érvényességi ideje lejárt"), + "linkNeverExpires": MessageLookupByLibrary.simpleMessage("Soha"), + "loadingModel": + MessageLookupByLibrary.simpleMessage("Modellek letöltése..."), + "lockButtonLabel": MessageLookupByLibrary.simpleMessage("Zárolás"), + "logInLabel": MessageLookupByLibrary.simpleMessage("Bejelentkezés"), + "loginTerms": MessageLookupByLibrary.simpleMessage( + "A bejelentkezés gombra kattintva elfogadom az szolgáltatási feltételeket és az adatvédelmi irányelveket"), + "logout": MessageLookupByLibrary.simpleMessage("Kijelentkezés"), + "lostDevice": + MessageLookupByLibrary.simpleMessage("Elveszett a készüléked?"), + "machineLearning": MessageLookupByLibrary.simpleMessage("Gépi tanulás"), + "magicSearch": + MessageLookupByLibrary.simpleMessage("Varázslatos keresés"), + "manage": MessageLookupByLibrary.simpleMessage("Kezelés"), + "manageDeviceStorage": MessageLookupByLibrary.simpleMessage( + "Eszköz gyorsítótárának kezelése"), + "manageDeviceStorageDesc": MessageLookupByLibrary.simpleMessage( + "Tekintse át és törölje a helyi gyorsítótárat."), + "manageLink": + MessageLookupByLibrary.simpleMessage("Hivatkozás kezelése"), + "manageParticipants": MessageLookupByLibrary.simpleMessage("Kezelés"), + "manageSubscription": + MessageLookupByLibrary.simpleMessage("Előfizetés kezelése"), + "memoryCount": m50, + "mlConsent": + MessageLookupByLibrary.simpleMessage("Gépi tanulás engedélyezése"), + "mlConsentConfirmation": MessageLookupByLibrary.simpleMessage( + "Értem, és szeretném engedélyezni a gépi tanulást"), + "mlConsentDescription": MessageLookupByLibrary.simpleMessage( + "Ha engedélyezi a gépi tanulást, az Ente olyan információkat fog kinyerni, mint az arc geometriája, a fájlokból, beleértve azokat is, amelyeket Önnel megosztott.\n\nEz az Ön eszközén fog megtörténni, és minden generált biometrikus információ végponttól végpontig titkosítva lesz."), + "mlConsentPrivacy": MessageLookupByLibrary.simpleMessage( + "Kérjük, kattintson ide az adatvédelmi irányelveinkben található további részletekért erről a funkcióról."), + "mlConsentTitle": MessageLookupByLibrary.simpleMessage( + "Engedélyezi a gépi tanulást?"), + "mlIndexingDescription": MessageLookupByLibrary.simpleMessage( + "Kérjük, vegye figyelembe, hogy a gépi tanulás nagyobb sávszélességet és akkumulátorhasználatot eredményez, amíg az összes elem indexelése meg nem történik. A gyorsabb indexelés érdekében érdemes lehet asztali alkalmazást használni, mivel minden eredmény automatikusan szinkronizálódik."), + "moderateStrength": MessageLookupByLibrary.simpleMessage("Közepes"), + "movedToTrash": + MessageLookupByLibrary.simpleMessage("Áthelyezve a kukába"), + "never": MessageLookupByLibrary.simpleMessage("Soha"), + "newAlbum": MessageLookupByLibrary.simpleMessage("Új album"), + "noDeviceLimit": MessageLookupByLibrary.simpleMessage("Egyik sem"), + "noDeviceThatCanBeDeleted": MessageLookupByLibrary.simpleMessage( + "Nincsenek törölhető fájlok ezen az eszközön."), + "noDuplicates": + MessageLookupByLibrary.simpleMessage("✨ Nincsenek duplikátumok"), + "noRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Nincs visszaállítási kulcsa?"), + "noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage( + "Az általunk használt végpontok közötti titkosítás miatt, az adatait nem lehet dekódolni a jelszava, vagy visszaállítási kulcsa nélkül"), + "ok": MessageLookupByLibrary.simpleMessage("Rendben"), + "onlyFamilyAdminCanChangeCode": m55, + "oops": MessageLookupByLibrary.simpleMessage("Hoppá"), + "oopsSomethingWentWrong": + MessageLookupByLibrary.simpleMessage("Hoppá, valami hiba történt"), + "orPickAnExistingOne": + MessageLookupByLibrary.simpleMessage("Vagy válasszon egy létezőt"), + "password": MessageLookupByLibrary.simpleMessage("Jelszó"), + "passwordChangedSuccessfully": + MessageLookupByLibrary.simpleMessage("Jelszó módosítása sikeres!"), + "passwordLock": + MessageLookupByLibrary.simpleMessage("Kóddal történő lezárás"), + "passwordStrength": m57, + "passwordWarning": MessageLookupByLibrary.simpleMessage( + "Ezt a jelszót nem tároljuk, így ha elfelejti, nem tudjuk visszafejteni adatait"), + "pendingItems": + MessageLookupByLibrary.simpleMessage("függőben lévő elemek"), + "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage( + "Az emberek, akik a kódodat használják"), + "photoGridSize": + MessageLookupByLibrary.simpleMessage("Rács méret beállátás"), + "photoSmallCase": MessageLookupByLibrary.simpleMessage("fénykép"), + "pleaseTryAgain": + MessageLookupByLibrary.simpleMessage("Kérjük, próbálja meg újra"), + "pleaseWait": MessageLookupByLibrary.simpleMessage("Kérem várjon..."), + "privacy": MessageLookupByLibrary.simpleMessage("Adatvédelem"), + "privacyPolicyTitle": + MessageLookupByLibrary.simpleMessage("Adatvédelmi irányelvek"), + "publicLinkEnabled": MessageLookupByLibrary.simpleMessage( + "Nyilvános hivatkozás engedélyezve"), + "rateUs": MessageLookupByLibrary.simpleMessage("Értékeljen minket"), + "recover": MessageLookupByLibrary.simpleMessage("Visszaállít"), + "recoverAccount": + MessageLookupByLibrary.simpleMessage("Fiók visszaállítása"), + "recoverButton": MessageLookupByLibrary.simpleMessage("Visszaállít"), + "recoveryKey": + MessageLookupByLibrary.simpleMessage("Visszaállítási kulcs"), + "recoveryKeyCopiedToClipboard": MessageLookupByLibrary.simpleMessage( + "A helyreállítási kulcs a vágólapra másolva"), + "recoveryKeyOnForgotPassword": MessageLookupByLibrary.simpleMessage( + "Ha elfelejti jelszavát, csak ezzel a kulccsal tudja visszaállítani adatait."), + "recoveryKeySaveDescription": MessageLookupByLibrary.simpleMessage( + "Ezt a kulcsot nem tároljuk, kérjük, őrizze meg ezt a 24 szavas kulcsot egy biztonságos helyen."), + "recoveryKeySuccessBody": MessageLookupByLibrary.simpleMessage( + "Nagyszerű! A helyreállítási kulcs érvényes. Köszönjük az igazolást.\n\nNe felejtsen el biztonsági másolatot készíteni helyreállítási kulcsáról."), + "recoveryKeyVerified": MessageLookupByLibrary.simpleMessage( + "A helyreállítási kulcs ellenőrizve"), + "recoveryKeyVerifyReason": MessageLookupByLibrary.simpleMessage( + "A helyreállítási kulcs az egyetlen módja annak, hogy visszaállítsa fényképeit, ha elfelejti jelszavát. A helyreállítási kulcsot a Beállítások > Fiók menüpontban találhatja meg.\n\nKérjük, írja be ide helyreállítási kulcsát annak ellenőrzéséhez, hogy megfelelően mentette-e el."), + "recoverySuccessful": + MessageLookupByLibrary.simpleMessage("Sikeres visszaállítás!"), + "recreatePasswordBody": MessageLookupByLibrary.simpleMessage( + "A jelenlegi eszköz nem elég erős a jelszavának ellenőrzéséhez, de újra tudjuk úgy generálni, hogy az minden eszközzel működjön.\n\nKérjük, jelentkezzen be helyreállítási kulcsával, és állítsa be újra jelszavát (ha szeretné, újra használhatja ugyanazt)."), + "recreatePasswordTitle": + MessageLookupByLibrary.simpleMessage("Új jelszó létrehozása"), + "referralStep1": MessageLookupByLibrary.simpleMessage( + "1. Add meg ezt a kódot a barátaidnak"), + "referralStep2": MessageLookupByLibrary.simpleMessage( + "2. Fizetős csomagra fizetnek elő"), + "referralStep3": m73, + "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( + "Az ajánlások jelenleg szünetelnek"), + "remindToEmptyDeviceTrash": MessageLookupByLibrary.simpleMessage( + "A felszabadult hely igényléséhez ürítsd ki a „Nemrég törölt” részt a „Beállítások” -> „Tárhely” menüpontban."), + "remindToEmptyEnteTrash": MessageLookupByLibrary.simpleMessage( + "Ürítsd ki a \"Kukát\" is, hogy visszaszerezd a felszabadult helyet."), + "remove": MessageLookupByLibrary.simpleMessage("Eltávolítás"), + "removeDuplicates": MessageLookupByLibrary.simpleMessage( + "Távolítsa el a duplikációkat"), + "removeDuplicatesDesc": MessageLookupByLibrary.simpleMessage( + "Tekintse át és távolítsa el a pontos másolatokat tartalmazó fájlokat."), + "removeFromAlbum": + MessageLookupByLibrary.simpleMessage("Eltávolítás az albumból"), + "removeFromAlbumTitle": + MessageLookupByLibrary.simpleMessage("Eltávolítás az albumból?"), + "removeLink": + MessageLookupByLibrary.simpleMessage("Hivatkozás eltávolítása"), + "removeParticipant": + MessageLookupByLibrary.simpleMessage("Résztvevő eltávolítása"), + "removeParticipantBody": m74, + "removePublicLink": MessageLookupByLibrary.simpleMessage( + "Nyilvános hivatkozás eltávolítása"), + "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( + "Néhány eltávolítandó elemet mások adtak hozzá, és elveszíted a hozzáférésedet hozzájuk."), + "removeWithQuestionMark": + MessageLookupByLibrary.simpleMessage("Eltávolítás?"), + "removingFromFavorites": MessageLookupByLibrary.simpleMessage( + "Eltávolítás a kedvencek közül..."), + "resendEmail": + MessageLookupByLibrary.simpleMessage("E-mail újraküldése"), + "resetPasswordTitle": + MessageLookupByLibrary.simpleMessage("Jelszó visszaállítása"), + "retry": MessageLookupByLibrary.simpleMessage("Újrapróbálkozás"), + "saveKey": MessageLookupByLibrary.simpleMessage("Mentés"), + "saveYourRecoveryKeyIfYouHaventAlready": + MessageLookupByLibrary.simpleMessage( + "Mentse el visszaállítási kulcsát, ha még nem tette"), + "scanCode": MessageLookupByLibrary.simpleMessage("Kód beolvasása"), + "scanThisBarcodeWithnyourAuthenticatorApp": + MessageLookupByLibrary.simpleMessage( + "Olvassa le ezt a QR kódot az autentikátor alkalmazásával"), + "selectAll": MessageLookupByLibrary.simpleMessage("Összes kijelölése"), + "selectFoldersForBackup": MessageLookupByLibrary.simpleMessage( + "Mappák kiválasztása biztonsági mentéshez"), + "selectReason": MessageLookupByLibrary.simpleMessage("Válasszon okot"), + "selectedFoldersWillBeEncryptedAndBackedUp": + MessageLookupByLibrary.simpleMessage( + "A kiválasztott mappák titkosítva lesznek, és biztonsági másolat készül róluk."), + "selectedPhotos": m80, + "selectedPhotosWithYours": m81, + "sendEmail": MessageLookupByLibrary.simpleMessage("Email küldése"), + "sendInvite": MessageLookupByLibrary.simpleMessage("Meghívó küldése"), + "sendLink": MessageLookupByLibrary.simpleMessage("Hivatkozás küldése"), + "setAPassword": + MessageLookupByLibrary.simpleMessage("Állítson be egy jelszót"), + "setPasswordTitle": + MessageLookupByLibrary.simpleMessage("Jelszó beállítás"), + "setupComplete": MessageLookupByLibrary.simpleMessage("Beállítás kész"), + "shareALink": + MessageLookupByLibrary.simpleMessage("Hivatkozás megosztása"), + "shareMyVerificationID": m83, + "shareTextConfirmOthersVerificationID": m84, + "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( + "Töltsd le az Ente-t, hogy könnyen megoszthassunk eredeti minőségű fotókat és videókat\n\nhttps://ente.io"), + "shareTextReferralCode": m85, + "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( + "Megosztás nem Ente felhasználókkal"), + "shareWithPeopleSectionTitle": m86, + "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( + "Hozzon létre megosztott és együttműködő albumokat más Ente-felhasználókkal, beleértve az ingyenes csomagokat használó felhasználókat is."), + "sharing": MessageLookupByLibrary.simpleMessage("Megosztás..."), + "showMemories": + MessageLookupByLibrary.simpleMessage("Emlékek megjelenítése"), + "signUpTerms": MessageLookupByLibrary.simpleMessage( + "Elfogadom az szolgáltatási feltételeket és az adatvédelmi irányelveket"), + "singleFileDeleteFromDevice": m88, + "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( + "Az összes albumból törlésre kerül."), + "singleFileInBothLocalAndRemote": m89, + "singleFileInRemoteOnly": m90, + "skip": MessageLookupByLibrary.simpleMessage("Kihagyás"), + "someoneSharingAlbumsWithYouShouldSeeTheSameId": + MessageLookupByLibrary.simpleMessage( + "Valaki, aki megoszt Önnel albumokat, ugyanazt az azonosítót fogja látni az eszközén."), + "somethingWentWrong": + MessageLookupByLibrary.simpleMessage("Valami hiba történt"), + "somethingWentWrongPleaseTryAgain": + MessageLookupByLibrary.simpleMessage( + "Valami félre sikerült, próbálja újból"), + "sorry": MessageLookupByLibrary.simpleMessage("Sajnálom"), + "sorryCouldNotAddToFavorites": MessageLookupByLibrary.simpleMessage( + "Sajnálom, nem sikerült hozzáadni a kedvencekhez!"), + "sorryCouldNotRemoveFromFavorites": + MessageLookupByLibrary.simpleMessage( + "Sajnálom, nem sikerült eltávolítani a kedvencek közül!"), + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": + MessageLookupByLibrary.simpleMessage( + "Sajnáljuk, nem tudtunk biztonságos kulcsokat generálni ezen az eszközön.\n\nkérjük, regisztráljon egy másik eszközről."), + "status": MessageLookupByLibrary.simpleMessage("Állapot"), + "storageInGB": m93, + "strongStrength": MessageLookupByLibrary.simpleMessage("Erős"), + "subscribe": MessageLookupByLibrary.simpleMessage("Előfizetés"), + "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( + "A megosztás engedélyezéséhez aktív fizetős előfizetésre van szükség."), + "success": MessageLookupByLibrary.simpleMessage("Sikeres"), + "tapToCopy": + MessageLookupByLibrary.simpleMessage("érintse meg másoláshoz"), + "tapToEnterCode": + MessageLookupByLibrary.simpleMessage("Koppintson a kód beírásához"), + "terminate": MessageLookupByLibrary.simpleMessage("Megszakít"), + "terminateSession": + MessageLookupByLibrary.simpleMessage("Megszakítja bejelentkezést?"), + "terms": MessageLookupByLibrary.simpleMessage("Feltételek"), + "termsOfServicesTitle": + MessageLookupByLibrary.simpleMessage("Használati feltételek"), + "theDownloadCouldNotBeCompleted": + MessageLookupByLibrary.simpleMessage("A letöltés nem fejezhető be"), + "theyAlsoGetXGb": m99, + "thisCanBeUsedToRecoverYourAccountIfYou": + MessageLookupByLibrary.simpleMessage( + "Ezzel tudja visszaállítani felhasználóját ha elveszítené a kétlépcsős azonosítóját"), + "thisDevice": MessageLookupByLibrary.simpleMessage("Ez az eszköz"), + "thisIsPersonVerificationId": m100, + "thisIsYourVerificationId": + MessageLookupByLibrary.simpleMessage("Ez az ellenőrző azonosítód"), + "thisWillLogYouOutOfTheFollowingDevice": + MessageLookupByLibrary.simpleMessage( + "Ezzel kijelentkezik az alábbi eszközről:"), + "thisWillLogYouOutOfThisDevice": MessageLookupByLibrary.simpleMessage( + "Ezzel kijelentkezik az eszközről!"), + "toResetVerifyEmail": MessageLookupByLibrary.simpleMessage( + "A Jelszó visszaállításához, kérjük először erősítse meg emailcímét."), + "total": MessageLookupByLibrary.simpleMessage("összesen"), + "trash": MessageLookupByLibrary.simpleMessage("Kuka"), + "tryAgain": MessageLookupByLibrary.simpleMessage("Próbáld újra"), + "twofactorAuthenticationPageTitle": + MessageLookupByLibrary.simpleMessage( + "Kétlépcsős hitelesítés (2FA)"), + "twofactorSetup": MessageLookupByLibrary.simpleMessage( + "Kétlépcsős azonosító beállítás"), + "unavailableReferralCode": MessageLookupByLibrary.simpleMessage( + "Sajnáljuk, ez a kód nem érhető el."), + "uncategorized": + MessageLookupByLibrary.simpleMessage("Kategorizálatlan"), + "unselectAll": + MessageLookupByLibrary.simpleMessage("Összes kijelölés törlése"), + "update": MessageLookupByLibrary.simpleMessage("Frissítés"), + "updateAvailable": + MessageLookupByLibrary.simpleMessage("Elérhető frissítés"), + "updatingFolderSelection": MessageLookupByLibrary.simpleMessage( + "Mappakijelölés frissítése..."), + "usableReferralStorageInfo": MessageLookupByLibrary.simpleMessage( + "A felhasználható tárhelyet a jelenlegi előfizetése korlátozza. A feleslegesen igényelt tárhely automatikusan felhasználhatóvá válik, amikor frissítesz a csomagodra."), + "useRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Helyreállítási kulcs használata"), + "verificationId": + MessageLookupByLibrary.simpleMessage("Ellenőrző azonosító"), "verify": MessageLookupByLibrary.simpleMessage("Hitelesítés"), - "wishThemAHappyBirthday": m115 + "verifyEmail": + MessageLookupByLibrary.simpleMessage("Emailcím megerősítés"), + "verifyEmailID": m111, + "verifyPassword": + MessageLookupByLibrary.simpleMessage("Jelszó megerősítése"), + "verifyingRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Helyreállítási kulcs ellenőrzése..."), + "videoSmallCase": MessageLookupByLibrary.simpleMessage("videó"), + "viewLargeFiles": MessageLookupByLibrary.simpleMessage("Nagy fájlok"), + "viewLargeFilesDesc": MessageLookupByLibrary.simpleMessage( + "Tekintse meg a legtöbb tárhelyet foglaló fájlokat."), + "viewRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Helyreállítási kulcs megtekintése"), + "viewer": MessageLookupByLibrary.simpleMessage("Néző"), + "waitingForWifi": + MessageLookupByLibrary.simpleMessage("Várakozás a WiFi-re..."), + "weAreOpenSource": + MessageLookupByLibrary.simpleMessage("Nyílt forráskódúak vagyunk!"), + "weHaveSendEmailTo": m114, + "weakStrength": MessageLookupByLibrary.simpleMessage("Gyenge"), + "welcomeBack": + MessageLookupByLibrary.simpleMessage("Köszöntjük ismét!"), + "yearsAgo": m116, + "yesConvertToViewer": + MessageLookupByLibrary.simpleMessage("Igen, alakítsa nézővé"), + "yesDelete": MessageLookupByLibrary.simpleMessage("Igen, törlés"), + "yesLogout": + MessageLookupByLibrary.simpleMessage("Igen, kijelentkezés"), + "yesRemove": MessageLookupByLibrary.simpleMessage("Igen, eltávolítás"), + "you": MessageLookupByLibrary.simpleMessage("Te"), + "youAreOnTheLatestVersion": MessageLookupByLibrary.simpleMessage( + "Ön a legújabb verziót használja"), + "youCanAtMaxDoubleYourStorage": MessageLookupByLibrary.simpleMessage( + "* Maximum megduplázhatod a tárhelyed"), + "youCannotShareWithYourself": + MessageLookupByLibrary.simpleMessage("Nem oszthatod meg magaddal"), + "youHaveSuccessfullyFreedUp": m118, + "yourAccountHasBeenDeleted": + MessageLookupByLibrary.simpleMessage("A felhasználód törlődött"), + "youveNoDuplicateFilesThatCanBeCleared": + MessageLookupByLibrary.simpleMessage( + "Nincsenek törölhető duplikált fájljaid") }; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_id.dart b/mobile/apps/photos/lib/generated/intl/messages_id.dart index c97e62ced8..8c2f7c48f0 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_id.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_id.dart @@ -181,8 +181,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Kami telah mengirimkan email ke ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, other: '${count} tahun lalu')}"; @@ -1482,7 +1480,6 @@ class MessageLookup extends MessageLookupByLibrary { "welcomeBack": MessageLookupByLibrary.simpleMessage("Selamat datang kembali!"), "whatsNew": MessageLookupByLibrary.simpleMessage("Hal yang baru"), - "wishThemAHappyBirthday": m115, "yearly": MessageLookupByLibrary.simpleMessage("Tahunan"), "yearsAgo": m116, "yes": MessageLookupByLibrary.simpleMessage("Ya"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_it.dart b/mobile/apps/photos/lib/generated/intl/messages_it.dart index a31cf49207..0981b4774e 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_it.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_it.dart @@ -317,8 +317,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Abbiamo inviato una mail a ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, one: '${count} anno fa', other: '${count} anni fa')}"; @@ -571,30 +569,6 @@ class MessageLookup extends MessageLookupByLibrary { "blackFridaySale": MessageLookupByLibrary.simpleMessage("Offerta del Black Friday"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), - "cLDesc1": MessageLookupByLibrary.simpleMessage( - "Dopo la versione beta dello streaming video e il lavoro sui caricamenti e download ripresi, abbiamo ora aumentato il limite di caricamento file a 10GB. Questo è ora disponibile sia nelle app desktop che mobili."), - "cLDesc2": MessageLookupByLibrary.simpleMessage( - "I caricamenti in background sono ora supportati anche su iOS, oltre ai dispositivi Android. Non è necessario aprire l\'app per eseguire il backup delle tue foto e video più recenti."), - "cLDesc3": MessageLookupByLibrary.simpleMessage( - "Abbiamo apportato miglioramenti significativi alla nostra esperienza dei ricordi, inclusa la riproduzione automatica, scorrimento al ricordo successivo e molto altro."), - "cLDesc4": MessageLookupByLibrary.simpleMessage( - "Insieme a un sacco di miglioramenti interni, ora è molto più facile vedere tutti i volti rilevati, fornire feedback sui volti simili e aggiungere/rimuovere volti da una singola foto."), - "cLDesc5": MessageLookupByLibrary.simpleMessage( - "Ora riceverai una notifica opzionale per tutti i compleanni che hai salvato su Ente, insieme a una raccolta delle loro migliori foto."), - "cLDesc6": MessageLookupByLibrary.simpleMessage( - "Non più attese per il completamento di caricamenti/download prima di poter chiudere l\'app. Tutti i caricamenti e download ora hanno la capacità di essere messi in pausa a metà e ripresi da dove hai lasciato."), - "cLTitle1": MessageLookupByLibrary.simpleMessage( - "Caricamento di file video di grandi dimensioni"), - "cLTitle2": - MessageLookupByLibrary.simpleMessage("Caricamento in background"), - "cLTitle3": MessageLookupByLibrary.simpleMessage( - "Riproduzione automatica dei ricordi"), - "cLTitle4": MessageLookupByLibrary.simpleMessage( - "Riconoscimento facciale migliorato"), - "cLTitle5": - MessageLookupByLibrary.simpleMessage("Notifiche di compleanno"), - "cLTitle6": MessageLookupByLibrary.simpleMessage( - "Caricamenti e download ripresi"), "cachedData": MessageLookupByLibrary.simpleMessage("Dati nella cache"), "calculating": MessageLookupByLibrary.simpleMessage("Calcolando..."), "canNotOpenBody": MessageLookupByLibrary.simpleMessage( @@ -2240,7 +2214,6 @@ class MessageLookup extends MessageLookupByLibrary { "whyAddTrustContact": MessageLookupByLibrary.simpleMessage( "Un contatto fidato può aiutare a recuperare i tuoi dati."), "widgets": MessageLookupByLibrary.simpleMessage("Widget"), - "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("anno"), "yearly": MessageLookupByLibrary.simpleMessage("Annuale"), "yearsAgo": m116, diff --git a/mobile/apps/photos/lib/generated/intl/messages_ja.dart b/mobile/apps/photos/lib/generated/intl/messages_ja.dart index ca801c8176..b9fea86c7a 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ja.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ja.dart @@ -265,8 +265,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "${email}にメールを送りました"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, other: '${count} 年前')}"; static String m117(name) => "あなたと${name}"; @@ -461,24 +459,6 @@ class MessageLookup extends MessageLookupByLibrary { "birthday": MessageLookupByLibrary.simpleMessage("誕生日"), "blackFridaySale": MessageLookupByLibrary.simpleMessage("ブラックフライデーセール"), "blog": MessageLookupByLibrary.simpleMessage("ブログ"), - "cLDesc1": MessageLookupByLibrary.simpleMessage( - "動画ストリーミングベータ版と再開可能なアップロード・ダウンロードの作業により、ファイルアップロード制限を10GBに増加しました。これはデスクトップとモバイルアプリの両方で利用可能です。"), - "cLDesc2": MessageLookupByLibrary.simpleMessage( - "バックグラウンドアップロードがAndroidデバイスに加えてiOSでもサポートされるようになりました。最新の写真や動画をバックアップするためにアプリを開く必要がありません。"), - "cLDesc3": MessageLookupByLibrary.simpleMessage( - "自動再生、次のメモリーへのスワイプなど、メモリー体験に大幅な改善を加えました。"), - "cLDesc4": MessageLookupByLibrary.simpleMessage( - "多くの内部改善とともに、検出されたすべての顔を確認し、類似した顔にフィードバックを提供し、1枚の写真から顔を追加/削除することがはるかに簡単になりました。"), - "cLDesc5": MessageLookupByLibrary.simpleMessage( - "Enteに保存したすべての誕生日について、その人のベスト写真のコレクションとともに、オプトアウト通知を受け取るようになります。"), - "cLDesc6": MessageLookupByLibrary.simpleMessage( - "アプリを閉じる前にアップロード/ダウンロードの完了を待つ必要がなくなりました。すべてのアップロードとダウンロードは途中で一時停止し、中断したところから再開できるようになりました。"), - "cLTitle1": MessageLookupByLibrary.simpleMessage("大きな動画ファイルのアップロード"), - "cLTitle2": MessageLookupByLibrary.simpleMessage("バックグラウンドアップロード"), - "cLTitle3": MessageLookupByLibrary.simpleMessage("メモリーの自動再生"), - "cLTitle4": MessageLookupByLibrary.simpleMessage("顔認識の改善"), - "cLTitle5": MessageLookupByLibrary.simpleMessage("誕生日通知"), - "cLTitle6": MessageLookupByLibrary.simpleMessage("再開可能なアップロードとダウンロード"), "cachedData": MessageLookupByLibrary.simpleMessage("キャッシュデータ"), "calculating": MessageLookupByLibrary.simpleMessage("計算中..."), "canNotOpenBody": MessageLookupByLibrary.simpleMessage( @@ -1824,7 +1804,6 @@ class MessageLookup extends MessageLookupByLibrary { "whatsNew": MessageLookupByLibrary.simpleMessage("最新情報"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage("信頼する連絡先は、データの復旧が必要な際に役立ちます。"), - "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("年"), "yearly": MessageLookupByLibrary.simpleMessage("年額"), "yearsAgo": m116, diff --git a/mobile/apps/photos/lib/generated/intl/messages_km.dart b/mobile/apps/photos/lib/generated/intl/messages_km.dart index 6271e8d455..22d4231361 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_km.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_km.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'km'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_ko.dart b/mobile/apps/photos/lib/generated/intl/messages_ko.dart index 6f8a7f5a0c..e378d62fd9 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ko.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ko.dart @@ -20,8 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ko'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "accountWelcomeBack": @@ -43,7 +41,6 @@ class MessageLookup extends MessageLookupByLibrary { "invalidEmailAddress": MessageLookupByLibrary.simpleMessage("잘못된 이메일 주소"), "verify": MessageLookupByLibrary.simpleMessage("인증"), - "wishThemAHappyBirthday": m115, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("계정이 삭제되었습니다.") }; diff --git a/mobile/apps/photos/lib/generated/intl/messages_ku.dart b/mobile/apps/photos/lib/generated/intl/messages_ku.dart index 90ea2aeea1..61bda74819 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ku.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ku.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ku'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_lt.dart b/mobile/apps/photos/lib/generated/intl/messages_lt.dart index 501d17c409..2ff34d3ea2 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_lt.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_lt.dart @@ -319,7 +319,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Išsiuntėme laišką adresu ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "Palinkėkite ${name} su gimtadieniu! 🎉"; static String m116(count) => "${Intl.plural(count, one: 'prieš ${count} metus', other: 'prieš ${count} metų')}"; @@ -570,6 +570,9 @@ class MessageLookup extends MessageLookupByLibrary { "Kurti atsargines vaizdo įrašų kopijas"), "beach": MessageLookupByLibrary.simpleMessage("Smėlis ir jūra"), "birthday": MessageLookupByLibrary.simpleMessage("Gimtadienis"), + "birthdayNotifications": + MessageLookupByLibrary.simpleMessage("Gimtadienio pranešimai"), + "birthdays": MessageLookupByLibrary.simpleMessage("Gimtadieniai"), "blackFridaySale": MessageLookupByLibrary.simpleMessage( "Juodojo penktadienio išpardavimas"), "blog": MessageLookupByLibrary.simpleMessage("Tinklaraštis"), @@ -1095,6 +1098,8 @@ class MessageLookup extends MessageLookupByLibrary { "guestView": MessageLookupByLibrary.simpleMessage("Svečio peržiūra"), "guestViewEnablePreSteps": MessageLookupByLibrary.simpleMessage( "Kad įjungtumėte svečio peržiūrą, sistemos nustatymuose nustatykite įrenginio prieigos kodą arba ekrano užraktą."), + "happyBirthday": + MessageLookupByLibrary.simpleMessage("Su gimtadieniu! 🥳"), "hearUsExplanation": MessageLookupByLibrary.simpleMessage( "Mes nesekame programų diegimų. Mums padėtų, jei pasakytumėte, kur mus radote."), "hearUsWhereTitle": MessageLookupByLibrary.simpleMessage( @@ -1612,6 +1617,8 @@ class MessageLookup extends MessageLookupByLibrary { "reassignedToName": m69, "reassigningLoading": MessageLookupByLibrary.simpleMessage("Perskirstoma..."), + "receiveRemindersOnBirthdays": MessageLookupByLibrary.simpleMessage( + "Gaukite priminimus, kai yra kažkieno gimtadienis. Paliesdami pranešimą, pateksite į gimtadienio šventės asmens nuotraukas."), "recover": MessageLookupByLibrary.simpleMessage("Atkurti"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Atkurti paskyrą"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_lv.dart b/mobile/apps/photos/lib/generated/intl/messages_lv.dart index b91248b291..a4ef58ad94 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_lv.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_lv.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'lv'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_ml.dart b/mobile/apps/photos/lib/generated/intl/messages_ml.dart index 77bb5a5388..6a3eec447c 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ml.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ml.dart @@ -20,8 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ml'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "accountWelcomeBack": @@ -138,7 +136,6 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("സങ്കേതക്കുറി ദൃഢീകരിക്കുക"), "weakStrength": MessageLookupByLibrary.simpleMessage("ദുർബലം"), "welcomeBack": MessageLookupByLibrary.simpleMessage("വീണ്ടും സ്വാഗതം!"), - "wishThemAHappyBirthday": m115, "yearly": MessageLookupByLibrary.simpleMessage("പ്രതിവർഷം") }; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_nl.dart b/mobile/apps/photos/lib/generated/intl/messages_nl.dart index 906ac331cc..056448e5a0 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_nl.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_nl.dart @@ -322,7 +322,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "We hebben een e-mail gestuurd naar ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "Wens ${name} een fijne verjaardag! 🎉"; static String m116(count) => "${Intl.plural(count, other: '${count} jaar geleden')}"; @@ -425,6 +425,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Alle herinneringen bewaard"), "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( "Alle groepen voor deze persoon worden gereset, en je verliest alle suggesties die voor deze persoon zijn gedaan"), + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": + MessageLookupByLibrary.simpleMessage( + "Alle naamloze groepen worden samengevoegd met de geselecteerde persoon. Dit kan nog steeds ongedaan worden gemaakt vanuit het geschiedenisoverzicht van de persoon."), "allWillShiftRangeBasedOnFirst": MessageLookupByLibrary.simpleMessage( "Dit is de eerste in de groep. Andere geselecteerde foto\'s worden automatisch verschoven op basis van deze nieuwe datum"), "allow": MessageLookupByLibrary.simpleMessage("Toestaan"), @@ -477,6 +480,9 @@ class MessageLookup extends MessageLookupByLibrary { "archiveAlbum": MessageLookupByLibrary.simpleMessage("Album archiveren"), "archiving": MessageLookupByLibrary.simpleMessage("Archiveren..."), + "areThey": MessageLookupByLibrary.simpleMessage("Is dit "), + "areYouSureRemoveThisFaceFromPerson": MessageLookupByLibrary.simpleMessage( + "Weet je zeker dat je dit gezicht van deze persoon wilt verwijderen?"), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage( "Weet u zeker dat u het familie abonnement wilt verlaten?"), @@ -487,8 +493,16 @@ class MessageLookup extends MessageLookupByLibrary { "Weet u zeker dat u uw abonnement wilt wijzigen?"), "areYouSureYouWantToExit": MessageLookupByLibrary.simpleMessage( "Weet u zeker dat u wilt afsluiten?"), + "areYouSureYouWantToIgnoreThesePersons": + MessageLookupByLibrary.simpleMessage( + "Weet je zeker dat je deze personen wilt negeren?"), + "areYouSureYouWantToIgnoreThisPerson": + MessageLookupByLibrary.simpleMessage( + "Weet je zeker dat je deze persoon wilt negeren?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "Weet je zeker dat je wilt uitloggen?"), + "areYouSureYouWantToMergeThem": MessageLookupByLibrary.simpleMessage( + "Weet je zeker dat je ze wilt samenvoegen?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Weet u zeker dat u wilt verlengen?"), "areYouSureYouWantToResetThisPerson": @@ -569,6 +583,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Back-up video\'s"), "beach": MessageLookupByLibrary.simpleMessage("Zand en zee"), "birthday": MessageLookupByLibrary.simpleMessage("Verjaardag"), + "birthdayNotifications": + MessageLookupByLibrary.simpleMessage("Meldingen over verjaardagen"), + "birthdays": MessageLookupByLibrary.simpleMessage("Verjaardagen"), "blackFridaySale": MessageLookupByLibrary.simpleMessage("Black Friday-aanbieding"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), @@ -1096,6 +1113,8 @@ class MessageLookup extends MessageLookupByLibrary { "guestView": MessageLookupByLibrary.simpleMessage("Gasten weergave"), "guestViewEnablePreSteps": MessageLookupByLibrary.simpleMessage( "Om gasten weergave in te schakelen, moet u een toegangscode of schermvergrendeling instellen in uw systeeminstellingen."), + "happyBirthday": + MessageLookupByLibrary.simpleMessage("Fijne verjaardag! 🥳"), "hearUsExplanation": MessageLookupByLibrary.simpleMessage( "Wij gebruiken geen tracking. Het zou helpen als je ons vertelt waar je ons gevonden hebt!"), "hearUsWhereTitle": MessageLookupByLibrary.simpleMessage( @@ -1122,6 +1141,7 @@ class MessageLookup extends MessageLookupByLibrary { "iOSLockOut": MessageLookupByLibrary.simpleMessage( "Biometrische verificatie is uitgeschakeld. Vergrendel en ontgrendel uw scherm om het in te schakelen."), "iOSOkButton": MessageLookupByLibrary.simpleMessage("Oké"), + "ignore": MessageLookupByLibrary.simpleMessage("Negeren"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("Negeren"), "ignored": MessageLookupByLibrary.simpleMessage("genegeerd"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( @@ -1324,6 +1344,7 @@ class MessageLookup extends MessageLookupByLibrary { "Selecteer het soort herinneringen dat je wilt zien op je beginscherm."), "memoryCount": m50, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), + "merge": MessageLookupByLibrary.simpleMessage("Samenvoegen"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("Samenvoegen met bestaand"), "mergedPhotos": @@ -1463,6 +1484,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Of kies een bestaande"), "orPickFromYourContacts": MessageLookupByLibrary.simpleMessage("of kies uit je contacten"), + "otherDetectedFaces": MessageLookupByLibrary.simpleMessage( + "Andere gedetecteerde gezichten"), "pair": MessageLookupByLibrary.simpleMessage("Koppelen"), "pairWithPin": MessageLookupByLibrary.simpleMessage("Koppelen met PIN"), "pairingComplete": @@ -1594,6 +1617,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Publieke link aangemaakt"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("Publieke link ingeschakeld"), + "questionmark": MessageLookupByLibrary.simpleMessage("?"), "queued": MessageLookupByLibrary.simpleMessage("In wachtrij"), "quickLinks": MessageLookupByLibrary.simpleMessage("Snelle links"), "radius": MessageLookupByLibrary.simpleMessage("Straal"), @@ -1606,6 +1630,8 @@ class MessageLookup extends MessageLookupByLibrary { "reassignedToName": m69, "reassigningLoading": MessageLookupByLibrary.simpleMessage("Opnieuw toewijzen..."), + "receiveRemindersOnBirthdays": MessageLookupByLibrary.simpleMessage( + "Ontvang herinneringen wanneer iemand jarig is. Als je op de melding drukt, krijg je foto\'s van de jarige."), "recover": MessageLookupByLibrary.simpleMessage("Herstellen"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Account herstellen"), @@ -1708,6 +1734,7 @@ class MessageLookup extends MessageLookupByLibrary { "reportBug": MessageLookupByLibrary.simpleMessage("Fout melden"), "resendEmail": MessageLookupByLibrary.simpleMessage("E-mail opnieuw versturen"), + "reset": MessageLookupByLibrary.simpleMessage("Reset"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage("Reset genegeerde bestanden"), "resetPasswordTitle": @@ -1736,6 +1763,8 @@ class MessageLookup extends MessageLookupByLibrary { "safelyStored": MessageLookupByLibrary.simpleMessage("Veilig opgeslagen"), "save": MessageLookupByLibrary.simpleMessage("Opslaan"), + "saveAsAnotherPerson": + MessageLookupByLibrary.simpleMessage("Opslaan als ander persoon"), "saveChangesBeforeLeavingQuestion": MessageLookupByLibrary.simpleMessage( "Wijzigingen opslaan voor verlaten?"), @@ -1897,8 +1926,12 @@ class MessageLookup extends MessageLookupByLibrary { "sharing": MessageLookupByLibrary.simpleMessage("Delen..."), "shiftDatesAndTime": MessageLookupByLibrary.simpleMessage("Verschuif datum en tijd"), + "showLessFaces": + MessageLookupByLibrary.simpleMessage("Minder gezichten weergeven"), "showMemories": MessageLookupByLibrary.simpleMessage("Toon herinneringen"), + "showMoreFaces": + MessageLookupByLibrary.simpleMessage("Minder gezichten weergeven"), "showPerson": MessageLookupByLibrary.simpleMessage("Toon persoon"), "signOutFromOtherDevices": MessageLookupByLibrary.simpleMessage("Log uit op andere apparaten"), @@ -2021,6 +2054,10 @@ class MessageLookup extends MessageLookupByLibrary { "theLinkYouAreTryingToAccessHasExpired": MessageLookupByLibrary.simpleMessage( "De link die je probeert te openen is verlopen."), + "thePersonGroupsWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "De groepen worden niet meer getoond in de personen sectie. Foto\'s blijven ongemoeid."), + "thePersonWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "De persoon wordt niet meer getoond in de personen sectie. Foto\'s blijven ongemoeid."), "theRecoveryKeyYouEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( "De ingevoerde herstelsleutel is onjuist"), @@ -2219,6 +2256,7 @@ class MessageLookup extends MessageLookupByLibrary { "yesDelete": MessageLookupByLibrary.simpleMessage("Ja, verwijderen"), "yesDiscardChanges": MessageLookupByLibrary.simpleMessage("Ja, wijzigingen negeren"), + "yesIgnore": MessageLookupByLibrary.simpleMessage("Ja, negeer"), "yesLogout": MessageLookupByLibrary.simpleMessage("Ja, log uit"), "yesRemove": MessageLookupByLibrary.simpleMessage("Ja, verwijderen"), "yesRenew": MessageLookupByLibrary.simpleMessage("Ja, verlengen"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_or.dart b/mobile/apps/photos/lib/generated/intl/messages_or.dart index a55b91293d..2bbc1c314c 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_or.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_or.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'or'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_pl.dart b/mobile/apps/photos/lib/generated/intl/messages_pl.dart index f7b908a5a9..7354e9cb45 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_pl.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_pl.dart @@ -234,8 +234,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Wysłaliśmy wiadomość na adres ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, one: '${count} rok temu', other: '${count} lata temu')}"; @@ -1949,7 +1947,6 @@ class MessageLookup extends MessageLookupByLibrary { "whatsNew": MessageLookupByLibrary.simpleMessage("Co nowego"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage( "Zaufany kontakt może pomóc w odzyskaniu Twoich danych."), - "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("r"), "yearly": MessageLookupByLibrary.simpleMessage("Rocznie"), "yearsAgo": m116, diff --git a/mobile/apps/photos/lib/generated/intl/messages_pt_BR.dart b/mobile/apps/photos/lib/generated/intl/messages_pt_BR.dart index bbd4765118..0b2505fff2 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_pt_BR.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_pt_BR.dart @@ -316,7 +316,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Enviamos um e-mail à ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "Deseje um feliz aniversário a ${name}! 🎉"; static String m116(count) => "${Intl.plural(count, one: '${count} ano atrás', other: '${count} anos atrás')}"; @@ -420,6 +420,9 @@ class MessageLookup extends MessageLookupByLibrary { "Todas as memórias preservadas"), "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( "Todos os agrupamentos dessa pessoa serão redefinidos, e você perderá todas as sugestões feitas por essa pessoa."), + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": + MessageLookupByLibrary.simpleMessage( + "Todos os grupos sem nome serão mesclados numa pessoa selecionada. Isso ainda pode ser desfeito no histórico de sugestões da pessoa."), "allWillShiftRangeBasedOnFirst": MessageLookupByLibrary.simpleMessage( "Este é o primeiro do grupo. As outras fotos selecionadas serão automaticamente alteradas para esta nova data"), "allow": MessageLookupByLibrary.simpleMessage("Permitir"), @@ -471,6 +474,10 @@ class MessageLookup extends MessageLookupByLibrary { "archive": MessageLookupByLibrary.simpleMessage("Arquivo"), "archiveAlbum": MessageLookupByLibrary.simpleMessage("Arquivar álbum"), "archiving": MessageLookupByLibrary.simpleMessage("Arquivando..."), + "areThey": MessageLookupByLibrary.simpleMessage("Eles são "), + "areYouSureRemoveThisFaceFromPerson": + MessageLookupByLibrary.simpleMessage( + "Deseja mesmo remover o rosto desta pessoa?"), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage( "Você tem certeza que queira sair do plano familiar?"), @@ -480,8 +487,16 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Deseja trocar de plano?"), "areYouSureYouWantToExit": MessageLookupByLibrary.simpleMessage( "Tem certeza de que queira sair?"), + "areYouSureYouWantToIgnoreThesePersons": + MessageLookupByLibrary.simpleMessage( + "Você deseja mesmo ignorar estas pessoas?"), + "areYouSureYouWantToIgnoreThisPerson": + MessageLookupByLibrary.simpleMessage( + "Você deseja mesmo ignorar esta pessoa?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "Você tem certeza que quer encerrar sessão?"), + "areYouSureYouWantToMergeThem": MessageLookupByLibrary.simpleMessage( + "Você desejar mesmo mesclá-los?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage("Deseja renovar?"), "areYouSureYouWantToResetThisPerson": @@ -572,29 +587,28 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Promoção Black Friday"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), "cLDesc1": MessageLookupByLibrary.simpleMessage( - "Com a versão beta de streaming de vídeo e o trabalho em uploads e downloads resumíveis, agora aumentamos o limite de upload de arquivos para 10GB. Isso já está disponível nos aplicativos desktop e móvel."), + "De volta na transmissão de vídeo beta, e trabalhando em envios e downloads retomáveis, nós aumentamos o limite de envio de arquivos para 10 GB. Isso está disponível em ambos a versão móvel e a versão para desktop."), "cLDesc2": MessageLookupByLibrary.simpleMessage( - "Os uploads em segundo plano agora também são suportados no iOS, além dos dispositivos Android. Não é necessário abrir o aplicativo para fazer backup de suas fotos e vídeos mais recentes."), + "Envios de fundo agora são suportados no iOS também, para assemelhar-se aos dispositivos Android. Não precisa abrir o aplicativo para salvar em segurança as fotos e vídeos mais recentes."), "cLDesc3": MessageLookupByLibrary.simpleMessage( - "Fizemos melhorias significativas em nossa experiência de memórias, incluindo reprodução automática, deslizar para a próxima memória e muito mais."), + "Fizemos melhorias significantes para a experiência de memórias, incluindo reprodução automática, deslizar para a próxima memória e mais."), "cLDesc4": MessageLookupByLibrary.simpleMessage( - "Junto com várias melhorias internas, agora é muito mais fácil ver todos os rostos detectados, fornecer feedback sobre rostos similares e adicionar/remover rostos de uma única foto."), + "Ao lado de outras melhorias, agora ficou mais fácil para detectar rostos, fornecer comentários em rostos similares, e adicionar/remover rostos de uma foto."), "cLDesc5": MessageLookupByLibrary.simpleMessage( - "Agora você receberá uma notificação opcional para todos os aniversários que salvou no Ente, junto com uma coleção de suas melhores fotos."), + "Você receberá uma notificação opcional para todos os aniversários salvos no Ente, além de uma coleção de melhores fotos."), "cLDesc6": MessageLookupByLibrary.simpleMessage( - "Não é mais necessário esperar que uploads/downloads sejam concluídos antes de fechar o aplicativo. Todos os uploads e downloads agora podem ser pausados no meio do caminho e retomados de onde você parou."), + "Nada de esperar os envios/downloads terminarem para fechar o aplicativo. Todos os envios e downloads agora possuem a habilidade de ser pausado na metade do processo, e retomar de onde você parou."), "cLTitle1": MessageLookupByLibrary.simpleMessage( - "Upload de arquivos de vídeo grandes"), - "cLTitle2": - MessageLookupByLibrary.simpleMessage("Upload em segundo plano"), - "cLTitle3": MessageLookupByLibrary.simpleMessage( - "Reprodução automática de memórias"), + "Enviando arquivos de vídeo grandes"), + "cLTitle2": MessageLookupByLibrary.simpleMessage("Envio de fundo"), + "cLTitle3": + MessageLookupByLibrary.simpleMessage("Reproduzir memórias auto."), "cLTitle4": MessageLookupByLibrary.simpleMessage( - "Reconhecimento facial aprimorado"), + "Reconhecimento Facial Melhorado"), "cLTitle5": MessageLookupByLibrary.simpleMessage("Notificações de aniversário"), "cLTitle6": MessageLookupByLibrary.simpleMessage( - "Uploads e downloads resumíveis"), + "Envios e downloads retomáveis"), "cachedData": MessageLookupByLibrary.simpleMessage("Dados armazenados em cache"), "calculating": MessageLookupByLibrary.simpleMessage("Calculando..."), @@ -847,6 +861,7 @@ class MessageLookup extends MessageLookupByLibrary { "deviceNotFound": MessageLookupByLibrary.simpleMessage("Dispositivo não encontrado"), "didYouKnow": MessageLookupByLibrary.simpleMessage("Você sabia?"), + "different": MessageLookupByLibrary.simpleMessage("Diferente"), "disableAutoLock": MessageLookupByLibrary.simpleMessage( "Desativar bloqueio automático"), "disableDownloadWarningBody": MessageLookupByLibrary.simpleMessage( @@ -1140,6 +1155,7 @@ class MessageLookup extends MessageLookupByLibrary { "iOSLockOut": MessageLookupByLibrary.simpleMessage( "A autenticação biométrica está desativada. Bloqueie e desbloqueie sua tela para ativá-la."), "iOSOkButton": MessageLookupByLibrary.simpleMessage("OK"), + "ignore": MessageLookupByLibrary.simpleMessage("Ignorar"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("Ignorar"), "ignored": MessageLookupByLibrary.simpleMessage("ignorado"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( @@ -1159,6 +1175,8 @@ class MessageLookup extends MessageLookupByLibrary { "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage( "Chave de recuperação incorreta"), "indexedItems": MessageLookupByLibrary.simpleMessage("Itens indexados"), + "indexingPausedStatusDescription": MessageLookupByLibrary.simpleMessage( + "A indexação foi pausada. Ela retomará automaticamente quando o dispositivo estiver pronto. O dispositivo é considerado pronto quando o nível de bateria, saúde da bateria, e estado térmico estejam num alcance saudável."), "ineligible": MessageLookupByLibrary.simpleMessage("Inelegível"), "info": MessageLookupByLibrary.simpleMessage("Info"), "insecureDevice": @@ -1344,6 +1362,7 @@ class MessageLookup extends MessageLookupByLibrary { "Selecione os tipos de memórias que deseje vê-las na sua tela inicial."), "memoryCount": m50, "merchandise": MessageLookupByLibrary.simpleMessage("Produtos"), + "merge": MessageLookupByLibrary.simpleMessage("Mesclar"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("Juntar com o existente"), "mergedPhotos": MessageLookupByLibrary.simpleMessage("Fotos mescladas"), @@ -1483,6 +1502,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ou escolha um existente"), "orPickFromYourContacts": MessageLookupByLibrary.simpleMessage( "ou escolher dos seus contatos"), + "otherDetectedFaces": + MessageLookupByLibrary.simpleMessage("Outros rostos detectados"), "pair": MessageLookupByLibrary.simpleMessage("Parear"), "pairWithPin": MessageLookupByLibrary.simpleMessage("Parear com PIN"), "pairingComplete": @@ -1613,6 +1634,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Link público criado"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("Link público ativo"), + "questionmark": MessageLookupByLibrary.simpleMessage("?"), "queued": MessageLookupByLibrary.simpleMessage("Na fila"), "quickLinks": MessageLookupByLibrary.simpleMessage("Links rápidos"), "radius": MessageLookupByLibrary.simpleMessage("Raio"), @@ -1723,6 +1745,7 @@ class MessageLookup extends MessageLookupByLibrary { "reportABug": MessageLookupByLibrary.simpleMessage("Informar um erro"), "reportBug": MessageLookupByLibrary.simpleMessage("Informar erro"), "resendEmail": MessageLookupByLibrary.simpleMessage("Reenviar e-mail"), + "reset": MessageLookupByLibrary.simpleMessage("Redefinir"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage( "Redefinir arquivos ignorados"), "resetPasswordTitle": @@ -1752,7 +1775,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Girar para a direita"), "safelyStored": MessageLookupByLibrary.simpleMessage("Armazenado com segurança"), + "same": MessageLookupByLibrary.simpleMessage("Igual"), + "sameperson": MessageLookupByLibrary.simpleMessage("Mesma pessoa?"), "save": MessageLookupByLibrary.simpleMessage("Salvar"), + "saveAsAnotherPerson": + MessageLookupByLibrary.simpleMessage("Salvar como outra pessoa"), "saveChangesBeforeLeavingQuestion": MessageLookupByLibrary.simpleMessage( "Salvar mudanças antes de sair?"), @@ -1906,7 +1933,7 @@ class MessageLookup extends MessageLookupByLibrary { "sharedPhotoNotifications": MessageLookupByLibrary.simpleMessage("Novas fotos compartilhadas"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( - "Receber notificações quando alguém adicionar uma foto a um álbum compartilhado que você faz parte"), + "Receba notificações caso alguém adicione uma foto a um álbum compartilhado que você faz parte"), "sharedWith": m87, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Compartilhado comigo"), @@ -1915,8 +1942,12 @@ class MessageLookup extends MessageLookupByLibrary { "sharing": MessageLookupByLibrary.simpleMessage("Compartilhando..."), "shiftDatesAndTime": MessageLookupByLibrary.simpleMessage("Alterar as datas e horas"), + "showLessFaces": + MessageLookupByLibrary.simpleMessage("Exibir menos rostos"), "showMemories": MessageLookupByLibrary.simpleMessage("Mostrar memórias"), + "showMoreFaces": + MessageLookupByLibrary.simpleMessage("Exibir mais rostos"), "showPerson": MessageLookupByLibrary.simpleMessage("Mostrar pessoa"), "signOutFromOtherDevices": MessageLookupByLibrary.simpleMessage( "Sair da conta em outros dispositivos"), @@ -2041,6 +2072,10 @@ class MessageLookup extends MessageLookupByLibrary { "theLinkYouAreTryingToAccessHasExpired": MessageLookupByLibrary.simpleMessage( "O link que você está tentando acessar já expirou."), + "thePersonGroupsWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Os grupos de pessoa não serão exibidos na seção de pessoa. As fotos permanecerão intactas."), + "thePersonWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "A pessoa não será exibida na seção de pessoas. As fotos permanecerão intactas."), "theRecoveryKeyYouEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( "A chave de recuperação inserida está incorreta"), @@ -2237,6 +2272,7 @@ class MessageLookup extends MessageLookupByLibrary { "yesDelete": MessageLookupByLibrary.simpleMessage("Sim, excluir"), "yesDiscardChanges": MessageLookupByLibrary.simpleMessage("Sim, descartar alterações"), + "yesIgnore": MessageLookupByLibrary.simpleMessage("Sim, ignorar"), "yesLogout": MessageLookupByLibrary.simpleMessage("Sim, encerrar sessão"), "yesRemove": MessageLookupByLibrary.simpleMessage("Sim, excluir"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_pt_PT.dart b/mobile/apps/photos/lib/generated/intl/messages_pt_PT.dart index 34dd1d7283..a4bdd9f09b 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_pt_PT.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_pt_PT.dart @@ -317,7 +317,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Enviamos um e-mail para ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "Envie um \"Felicidades\" a ${name}! 🎉"; static String m116(count) => "${Intl.plural(count, one: '${count} ano atrás', other: '${count} anos atrás')}"; @@ -339,7 +339,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("A conta já está ajustada."), "accountOwnerPersonAppbarTitle": m0, "accountWelcomeBack": - MessageLookupByLibrary.simpleMessage("Bem-vindo de volta!"), + MessageLookupByLibrary.simpleMessage("Boas-vindas de volta!"), "ackPasswordLostWarning": MessageLookupByLibrary.simpleMessage( "Eu entendo que se eu perder a minha palavra-passe, posso perder os meus dados já que esses dados são encriptados de ponta a ponta."), "actionNotSupportedOnFavouritesAlbum": @@ -423,6 +423,9 @@ class MessageLookup extends MessageLookupByLibrary { "Todas as memórias preservadas"), "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( "Todos os agrupamentos para esta pessoa serão reiniciados e perderá todas as sugestões feitas para esta pessoa"), + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": + MessageLookupByLibrary.simpleMessage( + "Todos os grupos sem título serão fundidos na pessoa selecionada. Isso pode ser desfeito no histórico geral das sugestões da pessoa."), "allWillShiftRangeBasedOnFirst": MessageLookupByLibrary.simpleMessage( "Este é o primeiro neste grupo. Outras fotos selecionadas serão automaticamente alteradas para a nova data"), "allow": MessageLookupByLibrary.simpleMessage("Permitir"), @@ -437,7 +440,7 @@ class MessageLookup extends MessageLookupByLibrary { "allowPeopleToAddPhotos": MessageLookupByLibrary.simpleMessage( "Permitir que as pessoas adicionem fotos"), "allowPermBody": MessageLookupByLibrary.simpleMessage( - "Por favor, permita o acesso às suas fotos para que Ente possa mostrá-las e fazer backup na Fototeca."), + "Favor, permite acesso às fotos nas Definições para que Ente possa exibi-las e fazer backup na Fototeca."), "allowPermTitle": MessageLookupByLibrary.simpleMessage("Garanta acesso às fotos"), "androidBiometricHint": @@ -475,6 +478,10 @@ class MessageLookup extends MessageLookupByLibrary { "archive": MessageLookupByLibrary.simpleMessage("............"), "archiveAlbum": MessageLookupByLibrary.simpleMessage("Arquivar álbum"), "archiving": MessageLookupByLibrary.simpleMessage("Arquivar..."), + "areThey": MessageLookupByLibrary.simpleMessage("Eles são "), + "areYouSureRemoveThisFaceFromPerson": + MessageLookupByLibrary.simpleMessage( + "Tem a certeza que queira remover o rosto desta pessoa?"), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage( "Tem certeza que deseja sair do plano familiar?"), @@ -485,8 +492,16 @@ class MessageLookup extends MessageLookupByLibrary { "Tem a certeza de que pretende alterar o seu plano?"), "areYouSureYouWantToExit": MessageLookupByLibrary.simpleMessage( "Tem certeza de que deseja sair?"), + "areYouSureYouWantToIgnoreThesePersons": + MessageLookupByLibrary.simpleMessage( + "Tem a certeza que quer ignorar estas pessoas?"), + "areYouSureYouWantToIgnoreThisPerson": + MessageLookupByLibrary.simpleMessage( + "Tem a certeza que quer ignorar esta pessoa?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "Tem certeza que deseja terminar a sessão?"), + "areYouSureYouWantToMergeThem": MessageLookupByLibrary.simpleMessage( + "Tem a certeza que quer fundi-los?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Tem a certeza de que pretende renovar?"), "areYouSureYouWantToResetThisPerson": @@ -495,7 +510,7 @@ class MessageLookup extends MessageLookupByLibrary { "askCancelReason": MessageLookupByLibrary.simpleMessage( "A sua subscrição foi cancelada. Gostaria de partilhar o motivo?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( - "Qual o principal motivo pelo qual está a eliminar a conta?"), + "Por que quer eliminar a sua conta?"), "askYourLovedOnesToShare": MessageLookupByLibrary.simpleMessage( "Peça aos seus entes queridos para partilharem"), "atAFalloutShelter": @@ -576,27 +591,26 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Promoção Black Friday"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), "cLDesc1": MessageLookupByLibrary.simpleMessage( - "Na sequência da versão beta de transmissão de vídeo e do trabalho em envios e transferências retomáveis, agora aumentámos o limite de envio de ficheiros para 10GB. Isto está agora disponível tanto nas aplicações de computador como móveis."), + "De volta aos vídeos em direto (beta), e a trabalhar em envios e transferências retomáveis, nós aumentamos o limite de envio de ficheiros para 10 GB. Isto está disponível para dispositivos Móveis e para Desktop."), "cLDesc2": MessageLookupByLibrary.simpleMessage( - "Os envios em segundo plano agora também são suportados no iOS, além dos dispositivos Android. Não é necessário abrir a aplicação para fazer uma cópia de segurança das suas fotografias e vídeos mais recentes."), + "Envios de fundo agora fornecerem suporte ao iOS. Para combinar com os aparelhos Android. Não precisa abrir a aplicação para fazer backup das fotos e vídeos recentes."), "cLDesc3": MessageLookupByLibrary.simpleMessage( - "Fizemos melhorias significativas na nossa experiência de memórias, incluindo reprodução automática, deslizar para a próxima memória e muito mais."), + "Nós fizemos melhorias significativas para a experiência das memórias, incluindo revisão automática, arrastar até a próxima memória e muito mais."), "cLDesc4": MessageLookupByLibrary.simpleMessage( - "Juntamente com várias melhorias internas, agora é muito mais fácil ver todas as faces detectadas, fornecer comentários sobre faces similares e adicionar/remover faces de uma única fotografia."), + "Junto a outras mudanças, agora facilitou a maneira de ver todos os rostos detetados, fornecer comentários para rostos similares, e adicionar ou remover rostos de uma foto única."), "cLDesc5": MessageLookupByLibrary.simpleMessage( - "Agora receberá uma notificação opcional para todos os aniversários que guardou no Ente, juntamente com uma colecção das suas melhores fotografias."), + "Ganhará uma notificação para todos os aniversários que salvaste no Ente, além de uma coleção das melhores fotos."), "cLDesc6": MessageLookupByLibrary.simpleMessage( - "Já não é necessário esperar que os envios/transferências sejam concluídos antes de poder fechar a aplicação. Todos os envios e transferências têm agora a capacidade de serem pausados a meio e retomados de onde parou."), + "Sem mais aguardar até que os envios e transferências sejam concluídos para fechar a aplicação. Todos os envios e transferências podem ser pausados a qualquer momento, e retomar onde parou."), "cLTitle1": MessageLookupByLibrary.simpleMessage( - "Envio de ficheiros de vídeo grandes"), - "cLTitle2": - MessageLookupByLibrary.simpleMessage("Envio em segundo plano"), + "A Enviar Ficheiros de Vídeo Grandes"), + "cLTitle2": MessageLookupByLibrary.simpleMessage("Envio de Fundo"), "cLTitle3": MessageLookupByLibrary.simpleMessage( - "Reprodução automática de memórias"), + "Revisão automática de memórias"), "cLTitle4": MessageLookupByLibrary.simpleMessage( - "Reconhecimento facial melhorado"), + "Reconhecimento Facial Melhorado"), "cLTitle5": - MessageLookupByLibrary.simpleMessage("Notificações de aniversário"), + MessageLookupByLibrary.simpleMessage("Notificações de Felicidade"), "cLTitle6": MessageLookupByLibrary.simpleMessage( "Envios e transferências retomáveis"), "cachedData": MessageLookupByLibrary.simpleMessage("Dados em cache"), @@ -624,7 +638,7 @@ class MessageLookup extends MessageLookupByLibrary { "cannotAddMorePhotosAfterBecomingViewer": m13, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Não é possível eliminar ficheiros partilhados"), - "castAlbum": MessageLookupByLibrary.simpleMessage("Transfere Álbum"), + "castAlbum": MessageLookupByLibrary.simpleMessage("Transferir Álbum"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( "Certifique-se de estar na mesma rede que a TV."), "castIPMismatchTitle": @@ -647,7 +661,7 @@ class MessageLookup extends MessageLookupByLibrary { "checkForUpdates": MessageLookupByLibrary.simpleMessage("Procurar atualizações"), "checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage( - "Verifique a sua caixa de entrada (e spam) para concluir a verificação"), + "Revê a sua caixa de entrada (e de spam) para concluir a verificação"), "checkStatus": MessageLookupByLibrary.simpleMessage("Verificar status"), "checking": MessageLookupByLibrary.simpleMessage("A verificar..."), "checkingModels": @@ -708,11 +722,11 @@ class MessageLookup extends MessageLookupByLibrary { "confirm": MessageLookupByLibrary.simpleMessage("Confirmar"), "confirm2FADisable": MessageLookupByLibrary.simpleMessage( "Tem a certeza de que pretende desativar a autenticação de dois fatores?"), - "confirmAccountDeletion": MessageLookupByLibrary.simpleMessage( - "Confirmar eliminação de conta"), + "confirmAccountDeletion": + MessageLookupByLibrary.simpleMessage("Eliminar Conta"), "confirmAddingTrustedContact": m17, "confirmDeletePrompt": MessageLookupByLibrary.simpleMessage( - "Sim, pretendo apagar permanentemente esta conta e os respetivos dados em todas as aplicações."), + "Sim, quero permanentemente eliminar esta conta com os dados."), "confirmPassword": MessageLookupByLibrary.simpleMessage("Confirmar palavra-passe"), "confirmPlanChange": MessageLookupByLibrary.simpleMessage( @@ -757,7 +771,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Criar link colaborativo"), "createCollage": MessageLookupByLibrary.simpleMessage("Criar coleção"), "createNewAccount": - MessageLookupByLibrary.simpleMessage("Criar nova conta"), + MessageLookupByLibrary.simpleMessage("Criar conta nova"), "createOrSelectAlbum": MessageLookupByLibrary.simpleMessage("Criar ou selecionar álbum"), "createPublicLink": @@ -786,9 +800,9 @@ class MessageLookup extends MessageLookupByLibrary { "delete": MessageLookupByLibrary.simpleMessage("Apagar"), "deleteAccount": MessageLookupByLibrary.simpleMessage("Eliminar conta"), "deleteAccountFeedbackPrompt": MessageLookupByLibrary.simpleMessage( - "Lamentamos a sua partida. Indique-nos a razão para podermos melhorar o serviço."), + "Lamentável a sua ida. Favor, partilhe o seu comentário para ajudar-nos a aprimorar."), "deleteAccountPermanentlyButton": MessageLookupByLibrary.simpleMessage( - "Excluir conta permanentemente"), + "Eliminar Conta Permanentemente"), "deleteAlbum": MessageLookupByLibrary.simpleMessage("Apagar álbum"), "deleteAlbumDialog": MessageLookupByLibrary.simpleMessage( "Eliminar também as fotos (e vídeos) presentes neste álbum de all os outros álbuns de que fazem parte?"), @@ -798,7 +812,7 @@ class MessageLookup extends MessageLookupByLibrary { "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( "Esta conta está ligada a outras aplicações Ente, se utilizar alguma. Os seus dados carregados, em todas as aplicações Ente, serão agendados para eliminação e a sua conta será permanentemente eliminada."), "deleteEmailRequest": MessageLookupByLibrary.simpleMessage( - "Envie um e-mail para accountt-deletion@ente.io a partir do seu endereço de email registrado."), + "Favor, envie um e-mail a account-deletion@ente.io do e-mail registado."), "deleteEmptyAlbums": MessageLookupByLibrary.simpleMessage("Apagar álbuns vazios"), "deleteEmptyAlbumsWithQuestionMark": @@ -816,15 +830,15 @@ class MessageLookup extends MessageLookupByLibrary { "deletePhotos": MessageLookupByLibrary.simpleMessage("Apagar fotos"), "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( - "Falta uma funcionalidade-chave de que eu necessito"), + "Necessita uma funcionalidade-chave que quero"), "deleteReason2": MessageLookupByLibrary.simpleMessage( - "O aplicativo ou um determinado recurso não se comportou como era suposto"), + "A aplicação ou certa funcionalidade não comporta conforme o meu desejo"), "deleteReason3": MessageLookupByLibrary.simpleMessage( - "Encontrei outro serviço de que gosto mais"), + "Possuo outro serviço que acho melhor"), "deleteReason4": - MessageLookupByLibrary.simpleMessage("O motivo não está na lista"), + MessageLookupByLibrary.simpleMessage("A razão não está listada"), "deleteRequestSLAText": MessageLookupByLibrary.simpleMessage( - "O seu pedido será processado dentro de 72 horas."), + "O pedido será revisto dentre 72 horas."), "deleteSharedAlbum": MessageLookupByLibrary.simpleMessage( "Excluir álbum compartilhado?"), "deleteSharedAlbumDialogBody": MessageLookupByLibrary.simpleMessage( @@ -848,6 +862,7 @@ class MessageLookup extends MessageLookupByLibrary { "deviceNotFound": MessageLookupByLibrary.simpleMessage("Dispositivo não encontrado"), "didYouKnow": MessageLookupByLibrary.simpleMessage("Você sabia?"), + "different": MessageLookupByLibrary.simpleMessage("Diferente"), "disableAutoLock": MessageLookupByLibrary.simpleMessage( "Desativar bloqueio automático"), "disableDownloadWarningBody": MessageLookupByLibrary.simpleMessage( @@ -915,7 +930,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Edições para localização só serão vistas dentro do Ente"), "eligible": MessageLookupByLibrary.simpleMessage("elegível"), - "email": MessageLookupByLibrary.simpleMessage("Email"), + "email": MessageLookupByLibrary.simpleMessage("E-mail"), "emailAlreadyRegistered": MessageLookupByLibrary.simpleMessage("E-mail já em utilização."), "emailChangedTo": m29, @@ -954,7 +969,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Ente pode criptografar e preservar arquivos apenas se você conceder acesso a eles"), "entePhotosPerm": MessageLookupByLibrary.simpleMessage( - "Ente precisa de permissão para preservar suas fotos"), + "Ente precisa da permissão para preservar as suas fotos"), "enteSubscriptionPitch": MessageLookupByLibrary.simpleMessage( "O Ente preserva as suas memórias, para que estejam sempre disponíveis, mesmo que perca o seu dispositivo."), "enteSubscriptionShareWithFamily": MessageLookupByLibrary.simpleMessage( @@ -985,7 +1000,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Introduzir o código de 6 dígitos da\nsua aplicação de autenticação"), "enterValidEmail": MessageLookupByLibrary.simpleMessage( - "Por favor, insira um endereço de email válido."), + "Favor, introduz um e-mail válido."), "enterYourEmailAddress": MessageLookupByLibrary.simpleMessage("Introduza o seu e-mail"), "enterYourNewEmailAddress": @@ -993,7 +1008,7 @@ class MessageLookup extends MessageLookupByLibrary { "enterYourPassword": MessageLookupByLibrary.simpleMessage( "Introduza a sua palavra-passe"), "enterYourRecoveryKey": MessageLookupByLibrary.simpleMessage( - "Insira a sua chave de recuperação"), + "Introduz a sua chave de recuperação"), "error": MessageLookupByLibrary.simpleMessage("Erro"), "everywhere": MessageLookupByLibrary.simpleMessage("em todo o lado"), "exif": MessageLookupByLibrary.simpleMessage("EXIF"), @@ -1046,7 +1061,7 @@ class MessageLookup extends MessageLookupByLibrary { "faqs": MessageLookupByLibrary.simpleMessage("Perguntas frequentes"), "favorite": MessageLookupByLibrary.simpleMessage("Favorito"), "feastingWithThem": m34, - "feedback": MessageLookupByLibrary.simpleMessage("Opinião"), + "feedback": MessageLookupByLibrary.simpleMessage("Comentário"), "file": MessageLookupByLibrary.simpleMessage("Ficheiro"), "fileFailedToSaveToGallery": MessageLookupByLibrary.simpleMessage( "Falha ao guardar o ficheiro na galeria"), @@ -1073,8 +1088,8 @@ class MessageLookup extends MessageLookupByLibrary { "food": MessageLookupByLibrary.simpleMessage("Culinária saborosa"), "forYourMemories": MessageLookupByLibrary.simpleMessage("para suas memórias"), - "forgotPassword": MessageLookupByLibrary.simpleMessage( - "Esqueceu-se da palavra-passe"), + "forgotPassword": + MessageLookupByLibrary.simpleMessage("Não recordo a palavra-passe"), "foundFaces": MessageLookupByLibrary.simpleMessage("Rostos encontrados"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage( @@ -1141,6 +1156,7 @@ class MessageLookup extends MessageLookupByLibrary { "iOSLockOut": MessageLookupByLibrary.simpleMessage( "A autenticação biométrica está desativada. Por favor, bloqueie e desbloqueie o ecrã para ativá-la."), "iOSOkButton": MessageLookupByLibrary.simpleMessage("OK"), + "ignore": MessageLookupByLibrary.simpleMessage("Ignorar"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("Ignorar"), "ignored": MessageLookupByLibrary.simpleMessage("ignorado"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( @@ -1156,10 +1172,12 @@ class MessageLookup extends MessageLookupByLibrary { "incorrectRecoveryKey": MessageLookupByLibrary.simpleMessage( "Chave de recuperação incorreta"), "incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage( - "A chave de recuperação inserida está incorreta"), + "A chave de recuperação introduzida está incorreta"), "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage( "Chave de recuperação incorreta"), "indexedItems": MessageLookupByLibrary.simpleMessage("Itens indexados"), + "indexingPausedStatusDescription": MessageLookupByLibrary.simpleMessage( + "A indexação foi interrompida. Ele será retomado se o dispositivo estiver pronto. O dispositivo é considerado pronto se o nível de bateria, saúde da bateria, e estado térmico esteja num estado saudável."), "ineligible": MessageLookupByLibrary.simpleMessage("Inelegível"), "info": MessageLookupByLibrary.simpleMessage("Info"), "insecureDevice": @@ -1167,7 +1185,7 @@ class MessageLookup extends MessageLookupByLibrary { "installManually": MessageLookupByLibrary.simpleMessage("Instalar manualmente"), "invalidEmailAddress": - MessageLookupByLibrary.simpleMessage("Endereço de email inválido"), + MessageLookupByLibrary.simpleMessage("E-mail inválido"), "invalidEndpoint": MessageLookupByLibrary.simpleMessage("Endpoint inválido"), "invalidEndpointMessage": MessageLookupByLibrary.simpleMessage( @@ -1204,7 +1222,7 @@ class MessageLookup extends MessageLookupByLibrary { "keepPhotos": MessageLookupByLibrary.simpleMessage("Manter fotos"), "kiloMeterUnit": MessageLookupByLibrary.simpleMessage("km"), "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage( - "Por favor, ajude-nos com esta informação"), + "Ajude-nos com esta informação"), "language": MessageLookupByLibrary.simpleMessage("Idioma"), "lastTimeWithThem": m45, "lastUpdated": @@ -1346,6 +1364,7 @@ class MessageLookup extends MessageLookupByLibrary { "Seleciona os tipos de memórias que adoraria ver no seu ecrã inicial."), "memoryCount": m50, "merchandise": MessageLookupByLibrary.simpleMessage("Produtos"), + "merge": MessageLookupByLibrary.simpleMessage("Fundir"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("Juntar com o existente"), "mergedPhotos": @@ -1430,10 +1449,10 @@ class MessageLookup extends MessageLookupByLibrary { "Nenhuma foto encontrada aqui"), "noQuickLinksSelected": MessageLookupByLibrary.simpleMessage( "Nenhum link rápido selecionado"), - "noRecoveryKey": MessageLookupByLibrary.simpleMessage( - "Não tem chave de recuperação?"), + "noRecoveryKey": + MessageLookupByLibrary.simpleMessage("Sem chave de recuperação?"), "noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage( - "Devido à natureza do nosso protocolo de criptografia de ponta a ponta, os seus dados não podem ser descriptografados sem a sua palavra-passe ou a sua chave de recuperação"), + "Por conta da natureza do nosso protocolo de encriptação, os seus dados não podem ser desencriptados sem a sua palavra-passe ou chave de recuperação."), "noResults": MessageLookupByLibrary.simpleMessage("Nenhum resultado"), "noResultsFound": MessageLookupByLibrary.simpleMessage( "Não foram encontrados resultados"), @@ -1448,7 +1467,7 @@ class MessageLookup extends MessageLookupByLibrary { "nothingToSeeHere": MessageLookupByLibrary.simpleMessage("Nada para ver aqui! 👀"), "notifications": MessageLookupByLibrary.simpleMessage("Notificações"), - "ok": MessageLookupByLibrary.simpleMessage("Ok"), + "ok": MessageLookupByLibrary.simpleMessage("OK"), "onDevice": MessageLookupByLibrary.simpleMessage("No dispositivo"), "onEnte": MessageLookupByLibrary.simpleMessage( "Em ente"), @@ -1461,7 +1480,7 @@ class MessageLookup extends MessageLookupByLibrary { "Obtém lembretes de memórias deste dia em anos passados."), "onlyFamilyAdminCanChangeCode": m55, "onlyThem": MessageLookupByLibrary.simpleMessage("Apenas eles"), - "oops": MessageLookupByLibrary.simpleMessage("Oops"), + "oops": MessageLookupByLibrary.simpleMessage("Ops"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Oops, não foi possível guardar as edições"), "oopsSomethingWentWrong": @@ -1484,6 +1503,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ou escolha um já existente"), "orPickFromYourContacts": MessageLookupByLibrary.simpleMessage( "ou selecione dos seus contactos"), + "otherDetectedFaces": + MessageLookupByLibrary.simpleMessage("Outros rostos detetados"), "pair": MessageLookupByLibrary.simpleMessage("Emparelhar"), "pairWithPin": MessageLookupByLibrary.simpleMessage("Emparelhar com PIN"), @@ -1615,6 +1636,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Link público criado"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("Link público ativado"), + "questionmark": MessageLookupByLibrary.simpleMessage("?"), "queued": MessageLookupByLibrary.simpleMessage("Em fila"), "quickLinks": MessageLookupByLibrary.simpleMessage("Links rápidos"), "radius": MessageLookupByLibrary.simpleMessage("Raio"), @@ -1653,7 +1675,7 @@ class MessageLookup extends MessageLookupByLibrary { "A sua chave de recuperação é a única forma de recuperar as suas fotografias se se esquecer da sua palavra-passe. Pode encontrar a sua chave de recuperação em Definições > Conta.\n\n\nIntroduza aqui a sua chave de recuperação para verificar se a guardou corretamente."), "recoveryReady": m71, "recoverySuccessful": - MessageLookupByLibrary.simpleMessage("Recuperação bem sucedida!"), + MessageLookupByLibrary.simpleMessage("Recuperação com êxito!"), "recoveryWarning": MessageLookupByLibrary.simpleMessage( "Um contacto de confiança está a tentar acessar a sua conta"), "recoveryWarningBody": m72, @@ -1713,7 +1735,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeWithQuestionMark": MessageLookupByLibrary.simpleMessage("Remover?"), "removeYourselfAsTrustedContact": MessageLookupByLibrary.simpleMessage( - "Retirar convosco dos contactos de confiança"), + "Retirar-vos dos contactos de confiança"), "removingFromFavorites": MessageLookupByLibrary.simpleMessage("Removendo dos favoritos..."), "rename": MessageLookupByLibrary.simpleMessage("Renomear"), @@ -1725,6 +1747,7 @@ class MessageLookup extends MessageLookupByLibrary { "reportABug": MessageLookupByLibrary.simpleMessage("Reporte um bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Reportar bug"), "resendEmail": MessageLookupByLibrary.simpleMessage("Reenviar e-mail"), + "reset": MessageLookupByLibrary.simpleMessage("Redefinir"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage("Repor ficheiros ignorados"), "resetPasswordTitle": @@ -1754,7 +1777,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Rodar para a direita"), "safelyStored": MessageLookupByLibrary.simpleMessage("Armazenado com segurança"), + "same": MessageLookupByLibrary.simpleMessage("Igual"), + "sameperson": MessageLookupByLibrary.simpleMessage("A mesma pessoa?"), "save": MessageLookupByLibrary.simpleMessage("Guardar"), + "saveAsAnotherPerson": + MessageLookupByLibrary.simpleMessage("Guardar como outra pessoa"), "saveChangesBeforeLeavingQuestion": MessageLookupByLibrary.simpleMessage( "Guardar as alterações antes de sair?"), @@ -1817,7 +1844,7 @@ class MessageLookup extends MessageLookupByLibrary { "selectAll": MessageLookupByLibrary.simpleMessage("Selecionar tudo"), "selectAllShort": MessageLookupByLibrary.simpleMessage("Tudo"), "selectCoverPhoto": - MessageLookupByLibrary.simpleMessage("Selecione Foto para Capa"), + MessageLookupByLibrary.simpleMessage("Selecionar Foto para Capa"), "selectDate": MessageLookupByLibrary.simpleMessage("Selecionar data"), "selectFoldersForBackup": MessageLookupByLibrary.simpleMessage( "Selecionar pastas para cópia de segurança"), @@ -1835,8 +1862,7 @@ class MessageLookup extends MessageLookupByLibrary { "Selecionar uma data e hora a todos"), "selectPersonToLink": MessageLookupByLibrary.simpleMessage( "Selecione uma pessoa para ligar-se"), - "selectReason": - MessageLookupByLibrary.simpleMessage("Selecionar motivo"), + "selectReason": MessageLookupByLibrary.simpleMessage("Diz a razão"), "selectStartOfRange": MessageLookupByLibrary.simpleMessage( "Selecionar início de intervalo"), "selectTime": MessageLookupByLibrary.simpleMessage("Selecionar tempo"), @@ -1860,7 +1886,7 @@ class MessageLookup extends MessageLookupByLibrary { "selectedPhotosWithYours": m81, "selfiesWithThem": m82, "send": MessageLookupByLibrary.simpleMessage("Enviar"), - "sendEmail": MessageLookupByLibrary.simpleMessage("Enviar email"), + "sendEmail": MessageLookupByLibrary.simpleMessage("Enviar e-mail"), "sendInvite": MessageLookupByLibrary.simpleMessage("Enviar convite"), "sendLink": MessageLookupByLibrary.simpleMessage("Enviar link"), "serverEndpoint": @@ -1919,8 +1945,12 @@ class MessageLookup extends MessageLookupByLibrary { "sharing": MessageLookupByLibrary.simpleMessage("Partilhar..."), "shiftDatesAndTime": MessageLookupByLibrary.simpleMessage("Mude as Datas e Horas"), + "showLessFaces": + MessageLookupByLibrary.simpleMessage("Mostrar menos rostos"), "showMemories": MessageLookupByLibrary.simpleMessage("Mostrar memórias"), + "showMoreFaces": + MessageLookupByLibrary.simpleMessage("Mostrar mais rostos"), "showPerson": MessageLookupByLibrary.simpleMessage("Mostrar pessoa"), "signOutFromOtherDevices": MessageLookupByLibrary.simpleMessage( "Terminar sessão noutros dispositivos"), @@ -1952,7 +1982,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ocorreu um erro"), "somethingWentWrongPleaseTryAgain": MessageLookupByLibrary.simpleMessage( - "Ocorreu um erro. Tente novamente"), + "Algo correu mal. Favor, tentar de novo"), "sorry": MessageLookupByLibrary.simpleMessage("Desculpe"), "sorryBackupFailedDesc": MessageLookupByLibrary.simpleMessage( "Perdão, mas não podemos fazer backup deste ficheiro agora, tentaremos mais tarde."), @@ -2024,8 +2054,8 @@ class MessageLookup extends MessageLookupByLibrary { "syncing": MessageLookupByLibrary.simpleMessage("Sincronizando..."), "systemTheme": MessageLookupByLibrary.simpleMessage("Sistema"), "tapToCopy": MessageLookupByLibrary.simpleMessage("toque para copiar"), - "tapToEnterCode": - MessageLookupByLibrary.simpleMessage("Toque para inserir código"), + "tapToEnterCode": MessageLookupByLibrary.simpleMessage( + "Tocar para introduzir código"), "tapToUnlock": MessageLookupByLibrary.simpleMessage("Toque para desbloquear"), "tapToUpload": @@ -2033,9 +2063,9 @@ class MessageLookup extends MessageLookupByLibrary { "tapToUploadIsIgnoredDue": m98, "tempErrorContactSupportIfPersists": MessageLookupByLibrary.simpleMessage( "Parece que algo correu mal. Por favor, tente novamente mais tarde. Se o erro persistir, entre em contacto com a nossa equipa de suporte."), - "terminate": MessageLookupByLibrary.simpleMessage("Terminar"), + "terminate": MessageLookupByLibrary.simpleMessage("Desconectar"), "terminateSession": - MessageLookupByLibrary.simpleMessage("Terminar sessão?"), + MessageLookupByLibrary.simpleMessage("Desconectar?"), "terms": MessageLookupByLibrary.simpleMessage("Termos"), "termsOfServicesTitle": MessageLookupByLibrary.simpleMessage("Termos"), "thankYou": MessageLookupByLibrary.simpleMessage("Obrigado"), @@ -2046,6 +2076,10 @@ class MessageLookup extends MessageLookupByLibrary { "theLinkYouAreTryingToAccessHasExpired": MessageLookupByLibrary.simpleMessage( "A ligação que está a tentar acessar já expirou."), + "thePersonGroupsWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Os grupos de pessoa não aparecerão mais na secção de pessoas. As Fotos permanecerão intocadas."), + "thePersonWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "As pessoas não aparecerão mais na secção de pessoas. As fotos permanecerão intocadas."), "theRecoveryKeyYouEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( "A chave de recuperação inserida está incorreta"), @@ -2064,7 +2098,7 @@ class MessageLookup extends MessageLookupByLibrary { "thisCanBeUsedToRecoverYourAccountIfYou": MessageLookupByLibrary.simpleMessage( "Isto pode ser usado para recuperar sua conta se você perder seu segundo fator"), - "thisDevice": MessageLookupByLibrary.simpleMessage("Este dispositivo"), + "thisDevice": MessageLookupByLibrary.simpleMessage("Este aparelho"), "thisEmailIsAlreadyInUse": MessageLookupByLibrary.simpleMessage("Este email já está em uso"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( @@ -2079,9 +2113,9 @@ class MessageLookup extends MessageLookupByLibrary { "thisWeekXYearsAgo": m101, "thisWillLogYouOutOfTheFollowingDevice": MessageLookupByLibrary.simpleMessage( - "Irá desconectar a sua conta do seguinte dispositivo:"), + "Isto desconectará-vos dos aparelhos a seguir:"), "thisWillLogYouOutOfThisDevice": MessageLookupByLibrary.simpleMessage( - "Irá desconectar a sua conta do seu dispositivo!"), + "Isto desconectará-vos deste aparelho!"), "thisWillMakeTheDateAndTimeOfAllSelected": MessageLookupByLibrary.simpleMessage( "Isto fará a data e hora de todas as fotos o mesmo."), @@ -2095,7 +2129,7 @@ class MessageLookup extends MessageLookupByLibrary { "toHideAPhotoOrVideo": MessageLookupByLibrary.simpleMessage( "Para ocultar uma foto ou um vídeo"), "toResetVerifyEmail": MessageLookupByLibrary.simpleMessage( - "Para redefinir a sua palavra-passe, verifique primeiro o seu e-mail."), + "Para redefinir a palavra-passe, favor, verifique o seu e-mail."), "todaysLogs": MessageLookupByLibrary.simpleMessage("Logs de hoje"), "tooManyIncorrectAttempts": MessageLookupByLibrary.simpleMessage( "Muitas tentativas incorretas"), @@ -2178,7 +2212,7 @@ class MessageLookup extends MessageLookupByLibrary { "verificationId": MessageLookupByLibrary.simpleMessage("ID de Verificação"), "verify": MessageLookupByLibrary.simpleMessage("Verificar"), - "verifyEmail": MessageLookupByLibrary.simpleMessage("Verificar email"), + "verifyEmail": MessageLookupByLibrary.simpleMessage("Verificar e-mail"), "verifyEmailID": m111, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verificar"), "verifyPasskey": @@ -2241,6 +2275,7 @@ class MessageLookup extends MessageLookupByLibrary { "yesDelete": MessageLookupByLibrary.simpleMessage("Sim, apagar"), "yesDiscardChanges": MessageLookupByLibrary.simpleMessage("Sim, rejeitar alterações"), + "yesIgnore": MessageLookupByLibrary.simpleMessage("Sim, ignorar"), "yesLogout": MessageLookupByLibrary.simpleMessage("Sim, terminar sessão"), "yesRemove": MessageLookupByLibrary.simpleMessage("Sim, remover"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_ro.dart b/mobile/apps/photos/lib/generated/intl/messages_ro.dart index 90e2b190db..ea6407b424 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ro.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ro.dart @@ -232,8 +232,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Am trimis un e-mail la ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, one: 'acum ${count} an', other: 'acum ${count} de ani')}"; @@ -1969,7 +1967,6 @@ class MessageLookup extends MessageLookupByLibrary { "whatsNew": MessageLookupByLibrary.simpleMessage("Noutăți"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage( "Contactul de încredere vă poate ajuta la recuperarea datelor."), - "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("an"), "yearly": MessageLookupByLibrary.simpleMessage("Anual"), "yearsAgo": m116, diff --git a/mobile/apps/photos/lib/generated/intl/messages_ru.dart b/mobile/apps/photos/lib/generated/intl/messages_ru.dart index 17897c9095..3955a25e92 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ru.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ru.dart @@ -83,6 +83,9 @@ class MessageLookup extends MessageLookupByLibrary { static String m21(count) => "${Intl.plural(count, one: 'Удалить ${count} элемент', other: 'Удалить ${count} элементов')}"; + static String m22(count) => + "Также удалить фото (и видео), находящиеся в этих ${count} альбомах, из всех других альбомов, частью которых они являются?"; + static String m23(currentlyDeleting, totalCount) => "Удаление ${currentlyDeleting} / ${totalCount}"; @@ -98,6 +101,9 @@ class MessageLookup extends MessageLookupByLibrary { static String m27(count, formattedSize) => "${count} файлов, по ${formattedSize} каждый"; + static String m28(name) => + "Этот адрес электронной почты уже связан с ${name}."; + static String m29(newEmail) => "Электронная почта изменена на ${newEmail}"; static String m30(email) => "${email} не имеет аккаунта Ente."; @@ -222,6 +228,8 @@ class MessageLookup extends MessageLookupByLibrary { static String m78(snapshotLength, searchLength) => "Несоответствие длины разделов: ${snapshotLength} != ${searchLength}"; + static String m79(count) => "${count} выбрано"; + static String m80(count) => "${count} выбрано"; static String m81(count, yourCount) => @@ -304,12 +312,14 @@ class MessageLookup extends MessageLookupByLibrary { static String m111(email) => "Подтвердить ${email}"; + static String m112(name) => "Посмотреть ${name} для отмены привязки"; + static String m113(count) => "${Intl.plural(count, zero: 'Добавлено 0 зрителей', one: 'Добавлен 1 зритель', other: 'Добавлено ${count} зрителей')}"; static String m114(email) => "Мы отправили письмо на ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "Поздравляем ${name} с днем ​​рождения! 🎉"; static String m116(count) => "${Intl.plural(count, one: '${count} год назад', other: '${count} лет назад')}"; @@ -333,12 +343,17 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("С возвращением!"), "ackPasswordLostWarning": MessageLookupByLibrary.simpleMessage( "Я понимаю, что если я потеряю пароль, я могу потерять свои данные, так как они защищены сквозным шифрованием."), + "actionNotSupportedOnFavouritesAlbum": + MessageLookupByLibrary.simpleMessage( + "Действие не поддерживается в альбоме «Избранное»"), "activeSessions": MessageLookupByLibrary.simpleMessage("Активные сеансы"), "add": MessageLookupByLibrary.simpleMessage("Добавить"), "addAName": MessageLookupByLibrary.simpleMessage("Добавить имя"), "addANewEmail": MessageLookupByLibrary.simpleMessage( "Добавьте новую электронную почту"), + "addAlbumWidgetPrompt": MessageLookupByLibrary.simpleMessage( + "Добавьте виджет альбома на главный экран и вернитесь сюда, чтобы настроить его."), "addCollaborator": MessageLookupByLibrary.simpleMessage("Добавить соавтора"), "addCollaborators": m1, @@ -349,6 +364,8 @@ class MessageLookup extends MessageLookupByLibrary { "addLocation": MessageLookupByLibrary.simpleMessage("Добавить местоположение"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Добавить"), + "addMemoriesWidgetPrompt": MessageLookupByLibrary.simpleMessage( + "Добавьте виджет воспоминаний на главный экран и вернитесь сюда, чтобы настроить его."), "addMore": MessageLookupByLibrary.simpleMessage("Добавить ещё"), "addName": MessageLookupByLibrary.simpleMessage("Добавить имя"), "addNameOrMerge": @@ -360,6 +377,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Подробности дополнений"), "addOnValidTill": m3, "addOns": MessageLookupByLibrary.simpleMessage("Дополнения"), + "addParticipants": + MessageLookupByLibrary.simpleMessage("Добавить участников"), + "addPeopleWidgetPrompt": MessageLookupByLibrary.simpleMessage( + "Добавьте виджет людей на главный экран и вернитесь сюда, чтобы настроить его."), "addPhotos": MessageLookupByLibrary.simpleMessage("Добавить фото"), "addSelected": MessageLookupByLibrary.simpleMessage("Добавить выбранные"), @@ -391,11 +412,16 @@ class MessageLookup extends MessageLookupByLibrary { "albumTitle": MessageLookupByLibrary.simpleMessage("Название альбома"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Альбом обновлён"), "albums": MessageLookupByLibrary.simpleMessage("Альбомы"), + "albumsWidgetDesc": MessageLookupByLibrary.simpleMessage( + "Выберите альбомы, которые вы хотите видеть на главном экране."), "allClear": MessageLookupByLibrary.simpleMessage("✨ Всё чисто"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("Все воспоминания сохранены"), "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( "Все группы этого человека будут сброшены, и вы потеряете все предложения для него"), + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": + MessageLookupByLibrary.simpleMessage( + "Все неназванные группы будут объединены в выбранного человека. Это можно отменить в обзоре истории предложений для данного человека."), "allWillShiftRangeBasedOnFirst": MessageLookupByLibrary.simpleMessage( "Это первое фото в группе. Остальные выбранные фото автоматически сместятся на основе новой даты"), "allow": MessageLookupByLibrary.simpleMessage("Разрешить"), @@ -449,6 +475,10 @@ class MessageLookup extends MessageLookupByLibrary { "archiveAlbum": MessageLookupByLibrary.simpleMessage("Архивировать альбом"), "archiving": MessageLookupByLibrary.simpleMessage("Архивация..."), + "areThey": MessageLookupByLibrary.simpleMessage("Они "), + "areYouSureRemoveThisFaceFromPerson": + MessageLookupByLibrary.simpleMessage( + "Вы уверены, что хотите удалить лицо этого человека?"), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage( "Вы уверены, что хотите покинуть семейный тариф?"), @@ -459,8 +489,16 @@ class MessageLookup extends MessageLookupByLibrary { "Вы уверены, что хотите сменить тариф?"), "areYouSureYouWantToExit": MessageLookupByLibrary.simpleMessage( "Вы уверены, что хотите выйти?"), + "areYouSureYouWantToIgnoreThesePersons": + MessageLookupByLibrary.simpleMessage( + "Вы уверены, что хотите игнорировать этих людей?"), + "areYouSureYouWantToIgnoreThisPerson": + MessageLookupByLibrary.simpleMessage( + "Вы уверены, что хотите игнорировать этого человека?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "Вы уверены, что хотите выйти?"), + "areYouSureYouWantToMergeThem": MessageLookupByLibrary.simpleMessage( + "Вы уверены, что хотите их объединить?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Вы уверены, что хотите продлить?"), "areYouSureYouWantToResetThisPerson": @@ -542,21 +580,24 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Резервное копирование видео"), "beach": MessageLookupByLibrary.simpleMessage("Песок и море"), "birthday": MessageLookupByLibrary.simpleMessage("День рождения"), + "birthdayNotifications": + MessageLookupByLibrary.simpleMessage("Уведомления о днях рождения"), + "birthdays": MessageLookupByLibrary.simpleMessage("Дни рождения"), "blackFridaySale": MessageLookupByLibrary.simpleMessage( "Распродажа в \"Черную пятницу\""), "blog": MessageLookupByLibrary.simpleMessage("Блог"), "cLDesc1": MessageLookupByLibrary.simpleMessage( - "Вслед за бета-версией потокового видео и работой над возобновляемыми загрузками и скачиваниями, мы увеличили лимит загрузки файлов до 10ГБ. Это теперь доступно как в настольных, так и в мобильных приложениях."), + "В результате бета-тестирования потоковой передачи видео и работы над возобновляемыми загрузками и скачиваниями мы увеличили лимит загружаемых файлов до 10 ГБ. Теперь это доступно как в настольных, так и в мобильных приложениях."), "cLDesc2": MessageLookupByLibrary.simpleMessage( - "Фоновые загрузки теперь также поддерживаются на iOS, в дополнение к устройствам Android. Больше не нужно открывать приложение для резервного копирования ваших последних фото и видео."), + "Фоновая загрузка теперь поддерживается не только на устройствах Android, но и на iOS. Не нужно открывать приложение для резервного копирования последних фотографий и видео."), "cLDesc3": MessageLookupByLibrary.simpleMessage( - "Мы внесли значительные улучшения в наш опыт воспоминаний, включая автовоспроизведение, пролистывание к следующему воспоминанию и многое другое."), + "Мы внесли значительные улучшения в работу с воспоминаниями, включая автовоспроизведение, переход к следующему воспоминанию и многое другое."), "cLDesc4": MessageLookupByLibrary.simpleMessage( - "Наряду с множеством внутренних улучшений, теперь гораздо проще увидеть все обнаруженные лица, предоставить обратную связь о похожих лицах и добавить/удалить лица с одной фотографии."), + "Наряду с рядом внутренних улучшений теперь стало гораздо проще просматривать все обнаруженные лица, оставлять отзывы о похожих лицах, а также добавлять/удалять лица с одной фотографии."), "cLDesc5": MessageLookupByLibrary.simpleMessage( - "Теперь вы будете получать опциональные уведомления обо всех днях рождения, которые вы сохранили в Ente, вместе с коллекцией их лучших фотографий."), + "Теперь вы будете получать уведомления о всех днях рождениях, которые вы сохранили на Ente, а также коллекцию их лучших фотографий."), "cLDesc6": MessageLookupByLibrary.simpleMessage( - "Больше не нужно ждать завершения загрузок/скачиваний перед закрытием приложения. Все загрузки и скачивания теперь могут быть приостановлены на полпути и возобновлены с того места, где вы остановились."), + "Больше не нужно ждать завершения загрузки/скачивания, прежде чем закрыть приложение. Все загрузки и скачивания теперь можно приостановить и возобновить с того места, где вы остановились."), "cLTitle1": MessageLookupByLibrary.simpleMessage( "Загрузка больших видеофайлов"), "cLTitle2": MessageLookupByLibrary.simpleMessage("Фоновая загрузка"), @@ -640,6 +681,8 @@ class MessageLookup extends MessageLookupByLibrary { "click": MessageLookupByLibrary.simpleMessage("• Нажмите"), "clickOnTheOverflowMenu": MessageLookupByLibrary.simpleMessage( "• Нажмите на меню дополнительных действий"), + "clickToInstallOurBestVersionYet": MessageLookupByLibrary.simpleMessage( + "Нажмите, чтобы установить нашу лучшую версию"), "close": MessageLookupByLibrary.simpleMessage("Закрыть"), "clubByCaptureTime": MessageLookupByLibrary.simpleMessage( "Группировать по времени съёмки"), @@ -786,6 +829,7 @@ class MessageLookup extends MessageLookupByLibrary { "deleteItemCount": m21, "deleteLocation": MessageLookupByLibrary.simpleMessage("Удалить местоположение"), + "deleteMultipleAlbumDialog": m22, "deletePhotos": MessageLookupByLibrary.simpleMessage("Удалить фото"), "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( @@ -821,6 +865,7 @@ class MessageLookup extends MessageLookupByLibrary { "deviceNotFound": MessageLookupByLibrary.simpleMessage("Устройство не найдено"), "didYouKnow": MessageLookupByLibrary.simpleMessage("Знаете ли вы?"), + "different": MessageLookupByLibrary.simpleMessage("Разные"), "disableAutoLock": MessageLookupByLibrary.simpleMessage("Отключить автоблокировку"), "disableDownloadWarningBody": MessageLookupByLibrary.simpleMessage( @@ -873,6 +918,7 @@ class MessageLookup extends MessageLookupByLibrary { "duplicateFileCountWithStorageSaved": m26, "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Редактировать"), + "editEmailAlreadyLinked": m28, "editLocation": MessageLookupByLibrary.simpleMessage("Изменить местоположение"), "editLocationTagTitle": @@ -959,6 +1005,8 @@ class MessageLookup extends MessageLookupByLibrary { "Пожалуйста, введите действительный адрес электронной почты."), "enterYourEmailAddress": MessageLookupByLibrary.simpleMessage( "Введите адрес вашей электронной почты"), + "enterYourNewEmailAddress": MessageLookupByLibrary.simpleMessage( + "Введите ваш новый адрес электронной почты"), "enterYourPassword": MessageLookupByLibrary.simpleMessage("Введите ваш пароль"), "enterYourRecoveryKey": MessageLookupByLibrary.simpleMessage( @@ -1080,6 +1128,8 @@ class MessageLookup extends MessageLookupByLibrary { "guestView": MessageLookupByLibrary.simpleMessage("Гостевой просмотр"), "guestViewEnablePreSteps": MessageLookupByLibrary.simpleMessage( "Для включения гостевого просмотра, пожалуйста, настройте код или блокировку экрана в настройках устройства."), + "happyBirthday": + MessageLookupByLibrary.simpleMessage("С днём рождения! 🥳"), "hearUsExplanation": MessageLookupByLibrary.simpleMessage( "Мы не отслеживаем установки приложений. Нам поможет, если скажете, как вы нас нашли!"), "hearUsWhereTitle": MessageLookupByLibrary.simpleMessage( @@ -1107,6 +1157,7 @@ class MessageLookup extends MessageLookupByLibrary { "iOSLockOut": MessageLookupByLibrary.simpleMessage( "Биометрическая аутентификация отключена. Пожалуйста, заблокируйте и разблокируйте экран, чтобы включить её."), "iOSOkButton": MessageLookupByLibrary.simpleMessage("Хорошо"), + "ignore": MessageLookupByLibrary.simpleMessage("Игнорировать"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("Игнорировать"), "ignored": MessageLookupByLibrary.simpleMessage("игнорируется"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( @@ -1126,6 +1177,8 @@ class MessageLookup extends MessageLookupByLibrary { "Неверный ключ восстановления"), "indexedItems": MessageLookupByLibrary.simpleMessage("Проиндексированные элементы"), + "indexingPausedStatusDescription": MessageLookupByLibrary.simpleMessage( + "Индексирование приостановлено. Оно автоматически возобновится, когда устройство будет готово. Устройство считается готовым, когда уровень заряда батареи, её состояние и температура находятся в пределах нормы."), "ineligible": MessageLookupByLibrary.simpleMessage("Неподходящий"), "info": MessageLookupByLibrary.simpleMessage("Информация"), "insecureDevice": @@ -1220,6 +1273,8 @@ class MessageLookup extends MessageLookupByLibrary { "livePhotos": MessageLookupByLibrary.simpleMessage("Живые фото"), "loadMessage1": MessageLookupByLibrary.simpleMessage( "Вы можете поделиться подпиской с вашей семьёй"), + "loadMessage2": MessageLookupByLibrary.simpleMessage( + "На сегодняшний день мы сохранили более 200 миллионов воспоминаний"), "loadMessage3": MessageLookupByLibrary.simpleMessage( "Мы храним 3 копии ваших данных, одну из них — в бункере"), "loadMessage4": MessageLookupByLibrary.simpleMessage( @@ -1277,6 +1332,8 @@ class MessageLookup extends MessageLookupByLibrary { "Нажмите с удержанием на электронную почту для подтверждения сквозного шифрования."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( "Нажмите с удержанием на элемент для просмотра в полноэкранном режиме"), + "lookBackOnYourMemories": MessageLookupByLibrary.simpleMessage( + "Оглянитесь на ваши воспоминания 🌄"), "loopVideoOff": MessageLookupByLibrary.simpleMessage("Видео не зациклено"), "loopVideoOn": MessageLookupByLibrary.simpleMessage("Видео зациклено"), @@ -1305,8 +1362,12 @@ class MessageLookup extends MessageLookupByLibrary { "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), "me": MessageLookupByLibrary.simpleMessage("Я"), + "memories": MessageLookupByLibrary.simpleMessage("Воспоминания"), + "memoriesWidgetDesc": MessageLookupByLibrary.simpleMessage( + "Выберите, какие воспоминания вы хотите видеть на главном экране."), "memoryCount": m50, "merchandise": MessageLookupByLibrary.simpleMessage("Мерч"), + "merge": MessageLookupByLibrary.simpleMessage("Объединить"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("Объединить с существующим"), "mergedPhotos": @@ -1362,6 +1423,7 @@ class MessageLookup extends MessageLookupByLibrary { "newLocation": MessageLookupByLibrary.simpleMessage("Новое местоположение"), "newPerson": MessageLookupByLibrary.simpleMessage("Новый человек"), + "newPhotosEmoji": MessageLookupByLibrary.simpleMessage(" новая 📸"), "newRange": MessageLookupByLibrary.simpleMessage("Новый диапазон"), "newToEnte": MessageLookupByLibrary.simpleMessage("Впервые в Ente"), "newest": MessageLookupByLibrary.simpleMessage("Недавние"), @@ -1416,6 +1478,11 @@ class MessageLookup extends MessageLookupByLibrary { "onEnte": MessageLookupByLibrary.simpleMessage("В ente"), "onTheRoad": MessageLookupByLibrary.simpleMessage("Снова в пути"), + "onThisDay": MessageLookupByLibrary.simpleMessage("В этот день"), + "onThisDayMemories": + MessageLookupByLibrary.simpleMessage("В этот день воспоминания"), + "onThisDayNotificationExplanation": MessageLookupByLibrary.simpleMessage( + "Получайте напоминания о воспоминаниях, связанных с этим днем в прошлые годы."), "onlyFamilyAdminCanChangeCode": m55, "onlyThem": MessageLookupByLibrary.simpleMessage("Только он(а)"), "oops": MessageLookupByLibrary.simpleMessage("Ой"), @@ -1442,6 +1509,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Или выберите существующую"), "orPickFromYourContacts": MessageLookupByLibrary.simpleMessage( "или выберите из ваших контактов"), + "otherDetectedFaces": + MessageLookupByLibrary.simpleMessage("Другие найденные лица"), "pair": MessageLookupByLibrary.simpleMessage("Подключить"), "pairWithPin": MessageLookupByLibrary.simpleMessage("Подключить с PIN"), "pairingComplete": @@ -1462,6 +1531,8 @@ class MessageLookup extends MessageLookupByLibrary { "Надёжность пароля определяется его длиной, используемыми символами и присутствием среди 10000 самых популярных паролей"), "passwordWarning": MessageLookupByLibrary.simpleMessage( "Мы не храним этот пароль, поэтому, если вы его забудете, мы не сможем расшифровать ваши данные"), + "pastYearsMemories": + MessageLookupByLibrary.simpleMessage("Воспоминания прошлых лет"), "paymentDetails": MessageLookupByLibrary.simpleMessage("Платёжные данные"), "paymentFailed": @@ -1476,6 +1547,8 @@ class MessageLookup extends MessageLookupByLibrary { "people": MessageLookupByLibrary.simpleMessage("Люди"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage("Люди, использующие ваш код"), + "peopleWidgetDesc": MessageLookupByLibrary.simpleMessage( + "Выберите людей, которых вы хотите видеть на главном экране."), "permDeleteWarning": MessageLookupByLibrary.simpleMessage( "Все элементы в корзине будут удалены навсегда\n\nЭто действие нельзя отменить"), "permanentlyDelete": @@ -1571,6 +1644,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Публичная ссылка создана"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("Публичная ссылка включена"), + "questionmark": MessageLookupByLibrary.simpleMessage("?"), "queued": MessageLookupByLibrary.simpleMessage("В очереди"), "quickLinks": MessageLookupByLibrary.simpleMessage("Быстрые ссылки"), "radius": MessageLookupByLibrary.simpleMessage("Радиус"), @@ -1584,6 +1658,8 @@ class MessageLookup extends MessageLookupByLibrary { "reassignedToName": m69, "reassigningLoading": MessageLookupByLibrary.simpleMessage("Переназначение..."), + "receiveRemindersOnBirthdays": MessageLookupByLibrary.simpleMessage( + "Получайте напоминания, когда у кого-то день рождения. Нажатие на уведомление перенесет вас к фотографиям именинника."), "recover": MessageLookupByLibrary.simpleMessage("Восстановить"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Восстановить аккаунт"), @@ -1688,6 +1764,7 @@ class MessageLookup extends MessageLookupByLibrary { "reportBug": MessageLookupByLibrary.simpleMessage("Сообщить об ошибке"), "resendEmail": MessageLookupByLibrary.simpleMessage("Отправить письмо повторно"), + "reset": MessageLookupByLibrary.simpleMessage("Сбросить"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage("Сбросить игнорируемые файлы"), "resetPasswordTitle": @@ -1715,7 +1792,11 @@ class MessageLookup extends MessageLookupByLibrary { "rotateRight": MessageLookupByLibrary.simpleMessage("Повернуть вправо"), "safelyStored": MessageLookupByLibrary.simpleMessage("Надёжно сохранены"), + "same": MessageLookupByLibrary.simpleMessage("Такой же"), + "sameperson": MessageLookupByLibrary.simpleMessage("Тот же человек?"), "save": MessageLookupByLibrary.simpleMessage("Сохранить"), + "saveAsAnotherPerson": MessageLookupByLibrary.simpleMessage( + "Сохранить как другого человека"), "saveChangesBeforeLeavingQuestion": MessageLookupByLibrary.simpleMessage( "Сохранить изменения перед выходом?"), @@ -1805,6 +1886,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Выберите своё лицо"), "selectYourPlan": MessageLookupByLibrary.simpleMessage("Выберите тариф"), + "selectedAlbums": m79, "selectedFilesAreNotOnEnte": MessageLookupByLibrary.simpleMessage( "Выбранные файлы отсутствуют в Ente"), "selectedFoldersWillBeEncryptedAndBackedUp": @@ -1881,8 +1963,12 @@ class MessageLookup extends MessageLookupByLibrary { "sharing": MessageLookupByLibrary.simpleMessage("Отправка..."), "shiftDatesAndTime": MessageLookupByLibrary.simpleMessage("Сместить даты и время"), + "showLessFaces": + MessageLookupByLibrary.simpleMessage("Показывать меньше лиц"), "showMemories": MessageLookupByLibrary.simpleMessage("Показывать воспоминания"), + "showMoreFaces": + MessageLookupByLibrary.simpleMessage("Показывать больше лиц"), "showPerson": MessageLookupByLibrary.simpleMessage("Показать человека"), "signOutFromOtherDevices": MessageLookupByLibrary.simpleMessage("Выйти с других устройств"), @@ -1898,6 +1984,8 @@ class MessageLookup extends MessageLookupByLibrary { "singleFileInBothLocalAndRemote": m89, "singleFileInRemoteOnly": m90, "skip": MessageLookupByLibrary.simpleMessage("Пропустить"), + "smartMemories": + MessageLookupByLibrary.simpleMessage("Умные воспоминания"), "social": MessageLookupByLibrary.simpleMessage("Социальные сети"), "someItemsAreInBothEnteAndYourDevice": MessageLookupByLibrary.simpleMessage( "Некоторые элементы находятся как в Ente, так и на вашем устройстве."), @@ -1913,6 +2001,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Что-то пошло не так. Пожалуйста, попробуйте снова"), "sorry": MessageLookupByLibrary.simpleMessage("Извините"), + "sorryBackupFailedDesc": MessageLookupByLibrary.simpleMessage( + "К сожалению, мы не смогли сделать резервную копию этого файла сейчас, мы повторим попытку позже."), "sorryCouldNotAddToFavorites": MessageLookupByLibrary.simpleMessage( "Извините, не удалось добавить в избранное!"), "sorryCouldNotRemoveFromFavorites": @@ -1924,6 +2014,8 @@ class MessageLookup extends MessageLookupByLibrary { "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": MessageLookupByLibrary.simpleMessage( "К сожалению, мы не смогли сгенерировать безопасные ключи на этом устройстве.\n\nПожалуйста, зарегистрируйтесь с другого устройства."), + "sorryWeHadToPauseYourBackups": MessageLookupByLibrary.simpleMessage( + "Извините, нам пришлось приостановить резервное копирование"), "sort": MessageLookupByLibrary.simpleMessage("Сортировать"), "sortAlbumsBy": MessageLookupByLibrary.simpleMessage("Сортировать по"), "sortNewestFirst": @@ -2003,6 +2095,10 @@ class MessageLookup extends MessageLookupByLibrary { "theLinkYouAreTryingToAccessHasExpired": MessageLookupByLibrary.simpleMessage( "Срок действия ссылки, к которой вы обращаетесь, истёк."), + "thePersonGroupsWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Группы людей больше не будут отображаться в разделе людей. Фотографии останутся нетронутыми."), + "thePersonWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Человек больше не будет отображаться в разделе людей. Фотографии останутся нетронутыми."), "theRecoveryKeyYouEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( "Введённый вами ключ восстановления неверен"), @@ -2149,6 +2245,8 @@ class MessageLookup extends MessageLookupByLibrary { "Проверка ключа восстановления..."), "videoInfo": MessageLookupByLibrary.simpleMessage("Информация о видео"), "videoSmallCase": MessageLookupByLibrary.simpleMessage("видео"), + "videoStreaming": + MessageLookupByLibrary.simpleMessage("Потоковое видео"), "videos": MessageLookupByLibrary.simpleMessage("Видео"), "viewActiveSessions": MessageLookupByLibrary.simpleMessage("Просмотр активных сессий"), @@ -2161,6 +2259,7 @@ class MessageLookup extends MessageLookupByLibrary { "viewLargeFilesDesc": MessageLookupByLibrary.simpleMessage( "Узнайте, какие файлы занимают больше всего места."), "viewLogs": MessageLookupByLibrary.simpleMessage("Просмотреть логи"), + "viewPersonToUnlink": m112, "viewRecoveryKey": MessageLookupByLibrary.simpleMessage("Увидеть ключ восстановления"), "viewer": MessageLookupByLibrary.simpleMessage("Зритель"), @@ -2183,6 +2282,7 @@ class MessageLookup extends MessageLookupByLibrary { "whatsNew": MessageLookupByLibrary.simpleMessage("Что нового"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage( "Доверенный контакт может помочь в восстановлении ваших данных."), + "widgets": MessageLookupByLibrary.simpleMessage("Виджеты"), "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("год"), "yearly": MessageLookupByLibrary.simpleMessage("Ежегодно"), @@ -2194,6 +2294,7 @@ class MessageLookup extends MessageLookupByLibrary { "yesDelete": MessageLookupByLibrary.simpleMessage("Да, удалить"), "yesDiscardChanges": MessageLookupByLibrary.simpleMessage("Да, отменить изменения"), + "yesIgnore": MessageLookupByLibrary.simpleMessage("Да, игнорировать"), "yesLogout": MessageLookupByLibrary.simpleMessage("Да, выйти"), "yesRemove": MessageLookupByLibrary.simpleMessage("Да, удалить"), "yesRenew": MessageLookupByLibrary.simpleMessage("Да, продлить"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_sl.dart b/mobile/apps/photos/lib/generated/intl/messages_sl.dart index c3c41dfa40..d41d848b0f 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_sl.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_sl.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'sl'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_sr.dart b/mobile/apps/photos/lib/generated/intl/messages_sr.dart index d4c1e9dc57..baacea2a95 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_sr.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_sr.dart @@ -20,23 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'sr'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => { - "areThey": MessageLookupByLibrary.simpleMessage("Are they "), - "areYouSureRemoveThisFaceFromPerson": - MessageLookupByLibrary.simpleMessage( - "Are you sure you want to remove this face from this person?"), - "otherDetectedFaces": - MessageLookupByLibrary.simpleMessage("Other detected faces"), - "questionmark": MessageLookupByLibrary.simpleMessage("?"), - "saveAsAnotherPerson": - MessageLookupByLibrary.simpleMessage("Save as another person"), - "showLessFaces": - MessageLookupByLibrary.simpleMessage("Show less faces"), - "showMoreFaces": - MessageLookupByLibrary.simpleMessage("Show more faces"), - "wishThemAHappyBirthday": m115 - }; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_sv.dart b/mobile/apps/photos/lib/generated/intl/messages_sv.dart index 15748c8a64..46120eaaf9 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_sv.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_sv.dart @@ -101,8 +101,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Vi har skickat ett e-postmeddelande till ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, other: '${count} år sedan')}"; @@ -153,10 +151,6 @@ class MessageLookup extends MessageLookupByLibrary { "appVersion": m9, "apply": MessageLookupByLibrary.simpleMessage("Verkställ"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Använd kod"), - "areThey": MessageLookupByLibrary.simpleMessage("Are they "), - "areYouSureRemoveThisFaceFromPerson": - MessageLookupByLibrary.simpleMessage( - "Are you sure you want to remove this face from this person?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "Är du säker på att du vill logga ut?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -453,8 +447,6 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Oj, något gick fel"), "orPickAnExistingOne": MessageLookupByLibrary.simpleMessage("Eller välj en befintlig"), - "otherDetectedFaces": - MessageLookupByLibrary.simpleMessage("Other detected faces"), "passkey": MessageLookupByLibrary.simpleMessage("Nyckel"), "password": MessageLookupByLibrary.simpleMessage("Lösenord"), "passwordChangedSuccessfully": @@ -477,7 +469,6 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Integritetspolicy"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("Offentlig länk aktiverad"), - "questionmark": MessageLookupByLibrary.simpleMessage("?"), "rateUsOnStore": m68, "recover": MessageLookupByLibrary.simpleMessage("Återställ"), "recoverAccount": @@ -536,8 +527,6 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Återställ till standard"), "retry": MessageLookupByLibrary.simpleMessage("Försök igen"), "save": MessageLookupByLibrary.simpleMessage("Spara"), - "saveAsAnotherPerson": - MessageLookupByLibrary.simpleMessage("Save as another person"), "saveCopy": MessageLookupByLibrary.simpleMessage("Spara kopia"), "saveKey": MessageLookupByLibrary.simpleMessage("Spara nyckel"), "saveYourRecoveryKeyIfYouHaventAlready": @@ -589,11 +578,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Dela ditt första album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( "Skapa delade och samarbetande album med andra Ente användare, inklusive användare med gratisnivån."), - "showLessFaces": - MessageLookupByLibrary.simpleMessage("Show less faces"), "showMemories": MessageLookupByLibrary.simpleMessage("Visa minnen"), - "showMoreFaces": - MessageLookupByLibrary.simpleMessage("Show more faces"), "showPerson": MessageLookupByLibrary.simpleMessage("Visa person"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Jag samtycker till användarvillkoren och integritetspolicyn"), @@ -706,7 +691,6 @@ class MessageLookup extends MessageLookupByLibrary { "welcomeBack": MessageLookupByLibrary.simpleMessage("Välkommen tillbaka!"), "whatsNew": MessageLookupByLibrary.simpleMessage("Nyheter"), - "wishThemAHappyBirthday": m115, "yearsAgo": m116, "yes": MessageLookupByLibrary.simpleMessage("Ja"), "yesCancel": MessageLookupByLibrary.simpleMessage("Ja, avbryt"), diff --git a/mobile/apps/photos/lib/generated/intl/messages_ta.dart b/mobile/apps/photos/lib/generated/intl/messages_ta.dart index 9fad77b2a9..2255c71ef9 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ta.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ta.dart @@ -20,8 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ta'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "accountWelcomeBack": @@ -57,7 +55,6 @@ class MessageLookup extends MessageLookupByLibrary { "selectReason": MessageLookupByLibrary.simpleMessage( "காரணத்தைத் தேர்ந்தெடுக்கவும்"), "verify": MessageLookupByLibrary.simpleMessage("சரிபார்க்கவும்"), - "wishThemAHappyBirthday": m115, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("உங்கள் கணக்கு நீக்கப்பட்டது") }; diff --git a/mobile/apps/photos/lib/generated/intl/messages_te.dart b/mobile/apps/photos/lib/generated/intl/messages_te.dart index 9648051033..5e415c9da0 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_te.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_te.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'te'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_th.dart b/mobile/apps/photos/lib/generated/intl/messages_th.dart index 7a86a39c80..8fecb411bb 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_th.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_th.dart @@ -45,8 +45,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "เราได้ส่งจดหมายไปยัง ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "accountWelcomeBack": @@ -347,7 +345,6 @@ class MessageLookup extends MessageLookupByLibrary { "weakStrength": MessageLookupByLibrary.simpleMessage("อ่อน"), "welcomeBack": MessageLookupByLibrary.simpleMessage("ยินดีต้อนรับกลับมา!"), - "wishThemAHappyBirthday": m115, "you": MessageLookupByLibrary.simpleMessage("คุณ"), "youCanManageYourLinksInTheShareTab": MessageLookupByLibrary.simpleMessage( diff --git a/mobile/apps/photos/lib/generated/intl/messages_ti.dart b/mobile/apps/photos/lib/generated/intl/messages_ti.dart index a93a2e5b99..775cc78213 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_ti.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_ti.dart @@ -20,9 +20,6 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ti'; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => - {"wishThemAHappyBirthday": m115}; + static Map _notInlinedMessages(_) => {}; } diff --git a/mobile/apps/photos/lib/generated/intl/messages_tr.dart b/mobile/apps/photos/lib/generated/intl/messages_tr.dart index ef68a3c64f..b0070facc8 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_tr.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_tr.dart @@ -320,8 +320,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "E-postayı ${email} adresine gönderdik"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, other: '${count} yıl önce')}"; @@ -2161,7 +2159,6 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Tekrardan hoşgeldin!"), "whatsNew": MessageLookupByLibrary.simpleMessage("Yenilikler"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage("."), - "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("yıl"), "yearly": MessageLookupByLibrary.simpleMessage("Yıllık"), "yearsAgo": m116, diff --git a/mobile/apps/photos/lib/generated/intl/messages_uk.dart b/mobile/apps/photos/lib/generated/intl/messages_uk.dart index 0cd4753343..378559591a 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_uk.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_uk.dart @@ -226,8 +226,6 @@ class MessageLookup extends MessageLookupByLibrary { static String m114(email) => "Ми надіслали листа на ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; - static String m116(count) => "${Intl.plural(count, one: '${count} рік тому', other: '${count} років тому')}"; @@ -1933,7 +1931,6 @@ class MessageLookup extends MessageLookupByLibrary { "whatsNew": MessageLookupByLibrary.simpleMessage("Що нового"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage( "Довірений контакт може допомогти у відновленні ваших даних."), - "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("рік"), "yearly": MessageLookupByLibrary.simpleMessage("Щороку"), "yearsAgo": m116, diff --git a/mobile/apps/photos/lib/generated/intl/messages_vi.dart b/mobile/apps/photos/lib/generated/intl/messages_vi.dart index 68819cd716..cff3edf144 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_vi.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_vi.dart @@ -20,13 +20,26 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'vi'; + static String m0(title) => "${title} (Tôi)"; + + static String m1(count) => + "${Intl.plural(count, zero: 'Thêm cộng tác viên', one: 'Thêm cộng tác viên', other: 'Thêm cộng tác viên')}"; + + static String m2(count) => + "${Intl.plural(count, one: 'Thêm mục', other: 'Thêm các mục')}"; + static String m3(storageAmount, endDate) => - "Gói bổ sung ${storageAmount} của bạn có hiệu lực đến ${endDate}"; + "Gói bổ sung ${storageAmount} áp dụng đến ${endDate}"; + + static String m4(count) => + "${Intl.plural(count, zero: 'Thêm người xem', one: 'Thêm người xem', other: 'Thêm người xem')}"; static String m5(emailOrName) => "Được thêm bởi ${emailOrName}"; static String m6(albumName) => "Đã thêm thành công vào ${albumName}"; + static String m7(name) => "Ngưỡng mộ ${name}"; + static String m8(count) => "${Intl.plural(count, zero: 'Không có người tham gia', one: '1 người tham gia', other: '${count} Người tham gia')}"; @@ -35,88 +48,121 @@ class MessageLookup extends MessageLookupByLibrary { static String m10(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} còn trống"; + static String m11(name) => "Ngắm cảnh với ${name}"; + static String m12(paymentProvider) => - "Vui lòng hủy đăng ký hiện tại của bạn từ ${paymentProvider} trước"; + "Vui lòng hủy gói hiện tại của bạn từ ${paymentProvider} trước"; static String m13(user) => - "${user} sẽ không thể thêm ảnh mới vào album này\n\nHọ vẫn có thể xóa các ảnh đã thêm trước đó"; + "${user} sẽ không thể thêm ảnh vào album này\n\nHọ vẫn có thể xóa ảnh đã thêm bởi họ"; static String m14(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': - 'Gia đình bạn đã yêu cầu ${storageAmountInGb} GB cho đến nay', - 'false': 'Bạn đã yêu cầu ${storageAmountInGb} GB cho đến nay', - 'other': 'Bạn đã yêu cầu ${storageAmountInGb} GB cho đến nay!', + 'Gia đình bạn đã nhận thêm ${storageAmountInGb} GB tính đến hiện tại', + 'false': + 'Bạn đã nhận thêm ${storageAmountInGb} GB tính đến hiện tại', + 'other': + 'Bạn đã nhận thêm ${storageAmountInGb} GB tính đến hiện tại!', })}"; static String m15(albumName) => - "Liên kết hợp tác đã được tạo cho ${albumName}"; + "Liên kết cộng tác đã được tạo cho ${albumName}"; static String m16(count) => - "${Intl.plural(count, zero: 'Đã thêm 0 cộng tác viên', one: 'Đã thêm 1 cộng tác viên', other: 'Đã thêm ${count} cộng tác viên')}"; + "${Intl.plural(count, zero: 'Chưa có cộng tác viên', one: 'Đã thêm 1 cộng tác viên', other: 'Đã thêm ${count} cộng tác viên')}"; static String m17(email, numOfDays) => "Bạn sắp thêm ${email} làm liên hệ tin cậy. Họ sẽ có thể khôi phục tài khoản của bạn nếu bạn không hoạt động trong ${numOfDays} ngày."; static String m18(familyAdminEmail) => - "Vui lòng liên hệ với ${familyAdminEmail} để quản lý đăng ký của bạn"; + "Vui lòng liên hệ ${familyAdminEmail} để quản lý gói của bạn"; static String m19(provider) => - "Vui lòng liên hệ với chúng tôi tại support@ente.io để quản lý đăng ký ${provider} của bạn."; + "Vui lòng liên hệ với chúng tôi qua support@ente.io để quản lý gói ${provider} của bạn."; static String m20(endpoint) => "Đã kết nối với ${endpoint}"; static String m21(count) => "${Intl.plural(count, one: 'Xóa ${count} mục', other: 'Xóa ${count} mục')}"; + static String m22(count) => + "Xóa luôn các tấm ảnh (và video) có trong ${count} album khỏi toàn bộ album khác cũng đang chứa chúng?"; + static String m23(currentlyDeleting, totalCount) => "Đang xóa ${currentlyDeleting} / ${totalCount}"; static String m24(albumName) => - "Điều này sẽ xóa liên kết công khai để truy cập \"${albumName}\"."; + "Xóa liên kết công khai dùng để truy cập \"${albumName}\"."; static String m25(supportEmail) => "Vui lòng gửi email đến ${supportEmail} từ địa chỉ email đã đăng ký của bạn"; static String m26(count, storageSaved) => - "Bạn đã dọn dẹp ${Intl.plural(count, other: '${count} tệp trùng lặp')}, tiết kiệm (${storageSaved}!)"; + "Bạn đã dọn dẹp ${Intl.plural(count, other: '${count} tệp bị trùng lặp')}, lấy lại (${storageSaved}!)"; static String m27(count, formattedSize) => "${count} tệp, ${formattedSize} mỗi tệp"; - static String m29(newEmail) => "Email đã được thay đổi thành ${newEmail}"; + static String m28(name) => "Email này đã được liên kết với ${name} trước."; + + static String m29(newEmail) => "Email đã được đổi thành ${newEmail}"; + + static String m30(email) => "${email} chưa có tài khoản Ente."; static String m31(email) => - "${email} không có tài khoản Ente.\n\nGửi cho họ một lời mời để chia sẻ ảnh."; + "${email} không có tài khoản Ente.\n\nGửi họ một lời mời để chia sẻ ảnh."; - static String m33(text) => "Extra photos found for ${text}"; + static String m32(name) => "Yêu mến ${name}"; + + static String m33(text) => "Tìm thấy ảnh bổ sung cho ${text}"; + + static String m34(name) => "Tiệc tùng với ${name}"; static String m35(count, formattedNumber) => - "${Intl.plural(count, one: '1 tệp', other: '${formattedNumber} tệp')} trên thiết bị này đã được sao lưu an toàn"; + "${Intl.plural(count, other: '${formattedNumber} tệp')} trên thiết bị này đã được sao lưu an toàn"; static String m36(count, formattedNumber) => - "${Intl.plural(count, one: '1 tệp', other: '${formattedNumber} tệp')} trong album này đã được sao lưu an toàn"; + "${Intl.plural(count, other: '${formattedNumber} tệp')} trong album này đã được sao lưu an toàn"; static String m37(storageAmountInGB) => "${storageAmountInGB} GB mỗi khi ai đó đăng ký gói trả phí và áp dụng mã của bạn"; - static String m38(endDate) => "Dùng thử miễn phí có hiệu lực đến ${endDate}"; + static String m38(endDate) => "Dùng thử miễn phí áp dụng đến ${endDate}"; + + static String m39(count) => + "Bạn vẫn có thể truy cập ${Intl.plural(count, one: 'chúng', other: 'chúng')} trên Ente miễn là bạn có một gói đăng ký"; static String m40(sizeInMBorGB) => "Giải phóng ${sizeInMBorGB}"; static String m41(count, formattedSize) => - "${Intl.plural(count, one: 'Nó có thể được xóa khỏi thiết bị để giải phóng ${formattedSize}', other: 'Chúng có thể được xóa khỏi thiết bị để giải phóng ${formattedSize}')}"; + "${Intl.plural(count, one: 'Có thể xóa khỏi thiết bị để giải phóng ${formattedSize}', other: 'Có thể xóa khỏi thiết bị để giải phóng ${formattedSize}')}"; static String m42(currentlyProcessing, totalCount) => "Đang xử lý ${currentlyProcessing} / ${totalCount}"; + static String m43(name) => "Leo núi với ${name}"; + static String m44(count) => "${Intl.plural(count, other: '${count} mục')}"; + static String m45(name) => "Lần cuối với ${name}"; + static String m46(email) => "${email} đã mời bạn trở thành một liên hệ tin cậy"; static String m47(expiryTime) => "Liên kết sẽ hết hạn vào ${expiryTime}"; + static String m48(email) => "Liên kết người với ${email}"; + + static String m49(personName, email) => + "Việc này sẽ liên kết ${personName} với ${email}"; + + static String m50(count, formattedCount) => + "${Intl.plural(count, zero: 'chưa có ảnh', other: '${formattedCount} ảnh')}"; + + static String m51(count) => + "${Intl.plural(count, one: 'Di chuyển mục', other: 'Di chuyển các mục')}"; + static String m52(albumName) => "Đã di chuyển thành công đến ${albumName}"; static String m53(personName) => "Không có gợi ý cho ${personName}"; @@ -126,24 +172,40 @@ class MessageLookup extends MessageLookupByLibrary { static String m55(familyAdminEmail) => "Vui lòng liên hệ ${familyAdminEmail} để thay đổi mã của bạn."; + static String m56(name) => "Quẩy với ${name}"; + static String m57(passwordStrengthValue) => "Độ mạnh mật khẩu: ${passwordStrengthValue}"; static String m58(providerName) => - "Vui lòng nói chuyện với bộ phận hỗ trợ ${providerName} nếu bạn đã bị tính phí"; + "Vui lòng trao đổi với bộ phận hỗ trợ ${providerName} nếu bạn đã bị tính phí"; + + static String m59(name, age) => "${name} đã ${age} tuổi!"; + + static String m60(name, age) => "${name} sắp ${age} tuổi"; + + static String m61(count) => + "${Intl.plural(count, zero: 'Chưa có ảnh', one: '1 ảnh', other: '${count} ảnh')}"; + + static String m62(count) => + "${Intl.plural(count, zero: 'Chưa có ảnh', one: '1 ảnh', other: '${count} ảnh')}"; static String m63(endDate) => - "Dùng thử miễn phí có hiệu lực đến ${endDate}.\nBạn có thể chọn gói trả phí sau đó."; + "Dùng thử miễn phí áp dụng đến ${endDate}.\nBạn có thể chọn gói trả phí sau đó."; static String m64(toEmail) => "Vui lòng gửi email cho chúng tôi tại ${toEmail}"; - static String m65(toEmail) => "Vui lòng gửi nhật ký đến \n${toEmail}"; + static String m65(toEmail) => "Vui lòng gửi file log đến \n${toEmail}"; + + static String m66(name) => "Làm dáng với ${name}"; static String m67(folderName) => "Đang xử lý ${folderName}..."; static String m68(storeName) => "Đánh giá chúng tôi trên ${storeName}"; + static String m69(name) => "Đã chỉ định lại bạn thành ${name}"; + static String m70(days, email) => "Bạn có thể truy cập tài khoản sau ${days} ngày. Một thông báo sẽ được gửi đến ${email}."; @@ -154,12 +216,14 @@ class MessageLookup extends MessageLookupByLibrary { "${email} đang cố gắng khôi phục tài khoản của bạn."; static String m73(storageInGB) => - "3. Cả hai bạn đều nhận ${storageInGB} GB* miễn phí"; + "3. Cả hai nhận thêm ${storageInGB} GB* miễn phí"; static String m74(userEmail) => "${userEmail} sẽ bị xóa khỏi album chia sẻ này\n\nBất kỳ ảnh nào được thêm bởi họ cũng sẽ bị xóa khỏi album"; - static String m75(endDate) => "Đăng ký sẽ được gia hạn vào ${endDate}"; + static String m75(endDate) => "Gia hạn gói vào ${endDate}"; + + static String m76(name) => "Đi bộ với ${name}"; static String m77(count) => "${Intl.plural(count, other: '${count} kết quả được tìm thấy')}"; @@ -167,10 +231,14 @@ class MessageLookup extends MessageLookupByLibrary { static String m78(snapshotLength, searchLength) => "Độ dài các phần không khớp: ${snapshotLength} != ${searchLength}"; + static String m79(count) => "${count} đã chọn"; + static String m80(count) => "${count} đã chọn"; static String m81(count, yourCount) => - "${count} đã chọn (${yourCount} của bạn)"; + "${count} đã chọn (${yourCount} là của bạn)"; + + static String m82(name) => "Selfie với ${name}"; static String m83(verificationID) => "Đây là ID xác minh của tôi: ${verificationID} cho ente.io."; @@ -179,7 +247,7 @@ class MessageLookup extends MessageLookupByLibrary { "Chào, bạn có thể xác nhận rằng đây là ID xác minh ente.io của bạn: ${verificationID}"; static String m85(referralCode, referralStorageInGB) => - "Mã giới thiệu Ente: ${referralCode} \n\nÁp dụng nó trong Cài đặt → Chung → Giới thiệu để nhận ${referralStorageInGB} GB miễn phí sau khi bạn đăng ký gói trả phí\n\nhttps://ente.io"; + "Mã giới thiệu Ente: ${referralCode} \n\nÁp dụng nó trong Cài đặt → Chung → Giới thiệu để nhận thêm ${referralStorageInGB} GB miễn phí sau khi bạn đăng ký gói trả phí\n\nhttps://ente.io"; static String m86(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Chia sẻ với những người cụ thể', one: 'Chia sẻ với 1 người', other: 'Chia sẻ với ${numberOfPeople} người')}"; @@ -194,16 +262,20 @@ class MessageLookup extends MessageLookupByLibrary { static String m90(fileType) => "Tệp ${fileType} này sẽ bị xóa khỏi Ente."; + static String m91(name) => "Chơi thể thao với ${name}"; + + static String m92(name) => "Tập trung vào ${name}"; + static String m93(storageAmountInGB) => "${storageAmountInGB} GB"; static String m94( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => - "${usedAmount} ${usedStorageUnit} trong tổng số ${totalAmount} ${totalStorageUnit} đã sử dụng"; + "${usedAmount} ${usedStorageUnit} trên ${totalAmount} ${totalStorageUnit} đã sử dụng"; static String m95(id) => - "ID ${id} của bạn đã được liên kết với một tài khoản Ente khác.\nNếu bạn muốn sử dụng ID ${id} này với tài khoản này, vui lòng liên hệ với bộ phận hỗ trợ của chúng tôi."; + "ID ${id} của bạn đã được liên kết với một tài khoản Ente khác.\nNếu bạn muốn sử dụng ID ${id} này với tài khoản này, vui lòng liên hệ bộ phận hỗ trợ của chúng tôi."; - static String m96(endDate) => "Đăng ký của bạn sẽ bị hủy vào ${endDate}"; + static String m96(endDate) => "Gói của bạn sẽ bị hủy vào ${endDate}"; static String m97(completed, total) => "${completed}/${total} kỷ niệm đã được lưu giữ"; @@ -216,61 +288,87 @@ class MessageLookup extends MessageLookupByLibrary { static String m100(email) => "Đây là ID xác minh của ${email}"; + static String m101(count) => + "${Intl.plural(count, one: 'Tuần này, ${count} năm trước', other: 'Tuần này, ${count} năm trước')}"; + + static String m102(dateFormat) => "${dateFormat} qua các năm"; + static String m103(count) => - "${Intl.plural(count, zero: 'Soon', one: '1 day', other: '${count} days')}"; + "${Intl.plural(count, zero: 'Sắp tới', one: '1 ngày', other: '${count} ngày')}"; + + static String m104(year) => "Phượt năm ${year}"; + + static String m105(location) => "Phượt ở ${location}"; static String m106(email) => - "Bạn đã được mời làm người liên hệ thừa kế bởi ${email}."; + "Bạn đã được mời làm người thừa kế của ${email}."; static String m107(galleryType) => - "Loại thư viện ${galleryType} không được hỗ trợ để đổi tên"; + "Loại thư viện ${galleryType} không được hỗ trợ đổi tên"; static String m108(ignoreReason) => "Tải lên bị bỏ qua do ${ignoreReason}"; static String m109(count) => "Đang lưu giữ ${count} kỷ niệm..."; - static String m110(endDate) => "Có hiệu lực đến ${endDate}"; + static String m110(endDate) => "Áp dụng đến ${endDate}"; static String m111(email) => "Xác minh ${email}"; + static String m112(name) => "Xem ${name} để hủy liên kết"; + + static String m113(count) => + "${Intl.plural(count, zero: 'Chưa thêm người xem', one: 'Đã thêm 1 người xem', other: 'Đã thêm ${count} người xem')}"; + static String m114(email) => "Chúng tôi đã gửi một email đến ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "Chúc ${name} sinh nhật vui vẻ! 🎉"; static String m116(count) => "${Intl.plural(count, other: '${count} năm trước')}"; + static String m117(name) => "Bạn và ${name}"; + static String m118(storageSaved) => "Bạn đã giải phóng thành công ${storageSaved}!"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "aNewVersionOfEnteIsAvailable": - MessageLookupByLibrary.simpleMessage("Có phiên bản mới của Ente."), + MessageLookupByLibrary.simpleMessage("Ente có phiên bản mới."), "about": MessageLookupByLibrary.simpleMessage("Giới thiệu"), "acceptTrustInvite": MessageLookupByLibrary.simpleMessage("Chấp nhận lời mời"), "account": MessageLookupByLibrary.simpleMessage("Tài khoản"), "accountIsAlreadyConfigured": MessageLookupByLibrary.simpleMessage("Tài khoản đã được cấu hình."), + "accountOwnerPersonAppbarTitle": m0, "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("Chào mừng bạn trở lại!"), "ackPasswordLostWarning": MessageLookupByLibrary.simpleMessage( "Tôi hiểu rằng nếu tôi mất mật khẩu, tôi có thể mất dữ liệu của mình vì dữ liệu của tôi được mã hóa đầu cuối."), + "actionNotSupportedOnFavouritesAlbum": + MessageLookupByLibrary.simpleMessage( + "Hành động không áp dụng trong album Đã thích"), "activeSessions": MessageLookupByLibrary.simpleMessage("Phiên hoạt động"), "add": MessageLookupByLibrary.simpleMessage("Thêm"), "addAName": MessageLookupByLibrary.simpleMessage("Thêm một tên"), "addANewEmail": MessageLookupByLibrary.simpleMessage("Thêm một email mới"), + "addAlbumWidgetPrompt": MessageLookupByLibrary.simpleMessage( + "Thêm tiện ích album vào màn hình chính và quay lại đây để tùy chỉnh."), "addCollaborator": MessageLookupByLibrary.simpleMessage("Thêm cộng tác viên"), + "addCollaborators": m1, "addFiles": MessageLookupByLibrary.simpleMessage("Thêm tệp"), "addFromDevice": MessageLookupByLibrary.simpleMessage("Thêm từ thiết bị"), + "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("Thêm vị trí"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Thêm"), + "addMemoriesWidgetPrompt": MessageLookupByLibrary.simpleMessage( + "Thêm tiện ích kỷ niệm vào màn hình chính và quay lại đây để tùy chỉnh."), "addMore": MessageLookupByLibrary.simpleMessage("Thêm nữa"), "addName": MessageLookupByLibrary.simpleMessage("Thêm tên"), "addNameOrMerge": @@ -281,8 +379,12 @@ class MessageLookup extends MessageLookupByLibrary { "Chi tiết về tiện ích mở rộng"), "addOnValidTill": m3, "addOns": MessageLookupByLibrary.simpleMessage("Tiện ích mở rộng"), + "addParticipants": + MessageLookupByLibrary.simpleMessage("Thêm người tham gia"), + "addPeopleWidgetPrompt": MessageLookupByLibrary.simpleMessage( + "Thêm tiện ích người vào màn hình chính và quay lại đây để tùy chỉnh."), "addPhotos": MessageLookupByLibrary.simpleMessage("Thêm ảnh"), - "addSelected": MessageLookupByLibrary.simpleMessage("Thêm đã chọn"), + "addSelected": MessageLookupByLibrary.simpleMessage("Thêm mục đã chọn"), "addToAlbum": MessageLookupByLibrary.simpleMessage("Thêm vào album"), "addToEnte": MessageLookupByLibrary.simpleMessage("Thêm vào Ente"), "addToHiddenAlbum": @@ -290,6 +392,7 @@ class MessageLookup extends MessageLookupByLibrary { "addTrustedContact": MessageLookupByLibrary.simpleMessage("Thêm liên hệ tin cậy"), "addViewer": MessageLookupByLibrary.simpleMessage("Thêm người xem"), + "addViewers": m4, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage( "Thêm ảnh của bạn ngay bây giờ"), "addedAs": MessageLookupByLibrary.simpleMessage("Đã thêm như"), @@ -297,6 +400,7 @@ class MessageLookup extends MessageLookupByLibrary { "addedSuccessfullyTo": m6, "addingToFavorites": MessageLookupByLibrary.simpleMessage( "Đang thêm vào mục yêu thích..."), + "admiringThem": m7, "advanced": MessageLookupByLibrary.simpleMessage("Nâng cao"), "advancedSettings": MessageLookupByLibrary.simpleMessage("Nâng cao"), "after1Day": MessageLookupByLibrary.simpleMessage("Sau 1 ngày"), @@ -310,14 +414,21 @@ class MessageLookup extends MessageLookupByLibrary { "albumUpdated": MessageLookupByLibrary.simpleMessage("Album đã được cập nhật"), "albums": MessageLookupByLibrary.simpleMessage("Album"), - "allClear": MessageLookupByLibrary.simpleMessage("✨ Tất cả đã rõ"), + "albumsWidgetDesc": MessageLookupByLibrary.simpleMessage( + "Chọn những album bạn muốn thấy trên màn hình chính của mình."), + "allClear": MessageLookupByLibrary.simpleMessage("✨ Tất cả đã xong"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage( "Tất cả kỷ niệm đã được lưu giữ"), "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( - "Tất cả các nhóm cho người này sẽ được đặt lại, và bạn sẽ mất tất cả các gợi ý đã được đưa ra cho người này"), + "Tất cả nhóm của người này sẽ được đặt lại, và bạn sẽ mất tất cả các gợi ý đã được tạo ra cho người này"), + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": + MessageLookupByLibrary.simpleMessage( + "Tất cả nhóm không có tên sẽ được hợp nhất vào người đã chọn. Điều này vẫn có thể được hoàn tác từ tổng quan lịch sử đề xuất của người đó."), + "allWillShiftRangeBasedOnFirst": MessageLookupByLibrary.simpleMessage( + "Đây là ảnh đầu tiên trong nhóm. Các ảnh được chọn khác sẽ tự động thay đổi dựa theo ngày mới này"), "allow": MessageLookupByLibrary.simpleMessage("Cho phép"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( - "Cho phép người có liên kết cũng thêm ảnh vào album chia sẻ."), + "Cho phép người có liên kết thêm ảnh vào album chia sẻ."), "allowAddingPhotos": MessageLookupByLibrary.simpleMessage("Cho phép thêm ảnh"), "allowAppToOpenSharedAlbumLinks": MessageLookupByLibrary.simpleMessage( @@ -351,6 +462,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Android, iOS, Web, Desktop"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("Yêu cầu xác thực"), + "appIcon": MessageLookupByLibrary.simpleMessage("Biểu tượng ứng dụng"), "appLock": MessageLookupByLibrary.simpleMessage("Khóa ứng dụng"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Chọn giữa màn hình khóa mặc định của thiết bị và màn hình khóa tùy chỉnh với PIN hoặc mật khẩu."), @@ -359,63 +471,75 @@ class MessageLookup extends MessageLookupByLibrary { "apply": MessageLookupByLibrary.simpleMessage("Áp dụng"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Áp dụng mã"), "appstoreSubscription": - MessageLookupByLibrary.simpleMessage("Đăng ký AppStore"), + MessageLookupByLibrary.simpleMessage("Gói AppStore"), "archive": MessageLookupByLibrary.simpleMessage("Lưu trữ"), "archiveAlbum": MessageLookupByLibrary.simpleMessage("Lưu trữ album"), "archiving": MessageLookupByLibrary.simpleMessage("Đang lưu trữ..."), + "areThey": MessageLookupByLibrary.simpleMessage("Họ có phải là "), + "areYouSureRemoveThisFaceFromPerson": + MessageLookupByLibrary.simpleMessage( + "Bạn có chắc muốn xóa khuôn mặt này khỏi người này không?"), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn rời khỏi kế hoạch gia đình không?"), - "areYouSureYouWantToCancel": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn hủy không?"), + "Bạn có chắc muốn rời khỏi gói gia đình không?"), + "areYouSureYouWantToCancel": + MessageLookupByLibrary.simpleMessage("Bạn có chắc muốn hủy không?"), "areYouSureYouWantToChangeYourPlan": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn thay đổi gói của mình không?"), + "Bạn có chắc muốn thay đổi gói của mình không?"), "areYouSureYouWantToExit": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn thoát không?"), + "Bạn có chắc muốn thoát không?"), + "areYouSureYouWantToIgnoreThesePersons": + MessageLookupByLibrary.simpleMessage( + "Bạn có chắc muốn bỏ qua những người này?"), + "areYouSureYouWantToIgnoreThisPerson": + MessageLookupByLibrary.simpleMessage( + "Bạn có chắc muốn bỏ qua người này?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn đăng xuất không?"), + "Bạn có chắc muốn đăng xuất không?"), + "areYouSureYouWantToMergeThem": MessageLookupByLibrary.simpleMessage( + "Bạn có chắc muốn hợp nhất họ?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn gia hạn không?"), + "Bạn có chắc muốn gia hạn không?"), "areYouSureYouWantToResetThisPerson": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn đặt lại người này không?"), + "Bạn có chắc muốn đặt lại người này không?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( - "Đăng ký của bạn đã bị hủy. Bạn có muốn chia sẻ lý do không?"), + "Gói của bạn đã bị hủy. Bạn có muốn chia sẻ lý do không?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Lý do chính bạn xóa tài khoản là gì?"), "askYourLovedOnesToShare": MessageLookupByLibrary.simpleMessage( - "Hãy yêu cầu những người thân yêu của bạn chia sẻ"), + "Hãy gợi ý những người thân yêu của bạn chia sẻ"), "atAFalloutShelter": - MessageLookupByLibrary.simpleMessage("tại một nơi trú ẩn"), + MessageLookupByLibrary.simpleMessage("ở hầm trú ẩn hạt nhân"), "authToChangeEmailVerificationSetting": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để thay đổi cài đặt xác minh email"), + "Vui lòng xác thực để đổi cài đặt xác minh email"), "authToChangeLockscreenSetting": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để thay đổi cài đặt màn hình khóa"), + "Vui lòng xác thực để thay đổi cài đặt khóa màn hình"), "authToChangeYourEmail": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để thay đổi email của bạn"), + "Vui lòng xác thực để đổi email"), "authToChangeYourPassword": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để thay đổi mật khẩu của bạn"), + "Vui lòng xác thực để đổi mật khẩu"), "authToConfigureTwofactorAuthentication": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để cấu hình xác thực hai yếu tố"), + "Vui lòng xác thực để cấu hình xác thực 2 bước"), "authToInitiateAccountDeletion": MessageLookupByLibrary.simpleMessage( "Vui lòng xác thực để bắt đầu xóa tài khoản"), "authToManageLegacy": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để quản lý các liên hệ tin cậy của bạn"), + "Vui lòng xác thực để quản lý các liên hệ tin cậy"), "authToViewPasskey": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để xem khóa truy cập của bạn"), + "Vui lòng xác thực để xem khóa truy cập"), "authToViewTrashedFiles": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để xem các tệp đã xóa của bạn"), + "Vui lòng xác thực để xem các tệp đã xóa"), "authToViewYourActiveSessions": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để xem các phiên hoạt động của bạn"), + "Vui lòng xác thực để xem các phiên hoạt động"), "authToViewYourHiddenFiles": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để xem các tệp ẩn của bạn"), + "Vui lòng xác thực để xem các tệp ẩn"), "authToViewYourMemories": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để xem kỷ niệm của bạn"), + "Vui lòng xác thực để xem kỷ niệm"), "authToViewYourRecoveryKey": MessageLookupByLibrary.simpleMessage( - "Vui lòng xác thực để xem khóa khôi phục của bạn"), + "Vui lòng xác thực để xem mã khôi phục"), "authenticating": MessageLookupByLibrary.simpleMessage("Đang xác thực..."), "authenticationFailedPleaseTryAgain": @@ -426,10 +550,10 @@ class MessageLookup extends MessageLookupByLibrary { "autoCastDialogBody": MessageLookupByLibrary.simpleMessage( "Bạn sẽ thấy các thiết bị Cast có sẵn ở đây."), "autoCastiOSPermission": MessageLookupByLibrary.simpleMessage( - "Hãy chắc chắn rằng quyền Mạng cục bộ đã được bật cho ứng dụng Ente Photos, trong Cài đặt."), + "Hãy chắc rằng quyền Mạng cục bộ đã được bật cho ứng dụng Ente Photos, trong Cài đặt."), "autoLock": MessageLookupByLibrary.simpleMessage("Khóa tự động"), "autoLockFeatureDescription": MessageLookupByLibrary.simpleMessage( - "Thời gian sau đó ứng dụng sẽ khóa khi được đưa vào nền"), + "Sau thời gian này, ứng dụng sẽ khóa sau khi được chạy ở chế độ nền"), "autoLogoutMessage": MessageLookupByLibrary.simpleMessage( "Do sự cố kỹ thuật, bạn đã bị đăng xuất. Chúng tôi xin lỗi vì sự bất tiện."), "autoPair": MessageLookupByLibrary.simpleMessage("Ghép nối tự động"), @@ -439,12 +563,13 @@ class MessageLookup extends MessageLookupByLibrary { "availableStorageSpace": m10, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Thư mục đã sao lưu"), + "backgroundWithThem": m11, "backup": MessageLookupByLibrary.simpleMessage("Sao lưu"), "backupFailed": MessageLookupByLibrary.simpleMessage("Sao lưu thất bại"), - "backupFile": MessageLookupByLibrary.simpleMessage("Tệp sao lưu"), - "backupOverMobileData": - MessageLookupByLibrary.simpleMessage("Sao lưu qua dữ liệu di động"), + "backupFile": MessageLookupByLibrary.simpleMessage("Sao lưu tệp"), + "backupOverMobileData": MessageLookupByLibrary.simpleMessage( + "Sao lưu bằng dữ liệu di động"), "backupSettings": MessageLookupByLibrary.simpleMessage("Cài đặt sao lưu"), "backupStatus": @@ -452,15 +577,42 @@ class MessageLookup extends MessageLookupByLibrary { "backupStatusDescription": MessageLookupByLibrary.simpleMessage( "Các mục đã được sao lưu sẽ hiển thị ở đây"), "backupVideos": MessageLookupByLibrary.simpleMessage("Sao lưu video"), + "beach": MessageLookupByLibrary.simpleMessage("Cát và biển"), "birthday": MessageLookupByLibrary.simpleMessage("Sinh nhật"), + "birthdayNotifications": + MessageLookupByLibrary.simpleMessage("Thông báo sinh nhật"), + "birthdays": MessageLookupByLibrary.simpleMessage("Sinh nhật"), "blackFridaySale": MessageLookupByLibrary.simpleMessage("Giảm giá Black Friday"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), - "cachedData": MessageLookupByLibrary.simpleMessage("Dữ liệu đã lưu"), + "cLDesc1": MessageLookupByLibrary.simpleMessage( + "Sau bản beta phát trực tuyến video và làm việc trên các bản có thể tiếp tục tải lên và tải xuống, chúng tôi hiện đã tăng giới hạn tải lên tệp tới 10 GB. Tính năng này hiện khả dụng trên cả ứng dụng dành cho máy tính để bàn và di động."), + "cLDesc2": MessageLookupByLibrary.simpleMessage( + "Tải lên trong nền hiện đã hỗ trợ trên iOS và Android. Không cần phải mở ứng dụng để sao lưu ảnh và video mới nhất của bạn."), + "cLDesc3": MessageLookupByLibrary.simpleMessage( + "Chúng tôi đã có những cải tiến đáng kể cho trải nghiệm kỷ niệm, bao gồm phát tự động, vuốt đến kỷ niệm tiếp theo và nhiều tính năng khác."), + "cLDesc4": MessageLookupByLibrary.simpleMessage( + "Cùng với một loạt cải tiến nội bộ, giờ đây bạn có thể dễ dàng xem tất cả khuôn mặt đã phát hiện, cung cấp phản hồi về các khuôn mặt giống nhau và thêm/xóa khuôn mặt khỏi một bức ảnh."), + "cLDesc5": MessageLookupByLibrary.simpleMessage( + "Bây giờ bạn sẽ nhận được thông báo tùy-chọn cho tất cả các ngày sinh nhật mà bạn đã lưu trên Ente, cùng với bộ sưu tập những bức ảnh đẹp nhất của họ."), + "cLDesc6": MessageLookupByLibrary.simpleMessage( + "Không còn phải chờ tải lên/tải xuống xong mới có thể đóng ứng dụng. Tất cả các tải lên và tải xuống hiện có thể tạm dừng giữa chừng và tiếp tục từ nơi bạn đã dừng lại."), + "cLTitle1": + MessageLookupByLibrary.simpleMessage("Tải lên tệp video lớn"), + "cLTitle2": MessageLookupByLibrary.simpleMessage("Tải lên trong nền"), + "cLTitle3": + MessageLookupByLibrary.simpleMessage("Tự động phát kỷ niệm"), + "cLTitle4": MessageLookupByLibrary.simpleMessage( + "Cải thiện nhận diện khuôn mặt"), + "cLTitle5": MessageLookupByLibrary.simpleMessage("Thông báo sinh nhật"), + "cLTitle6": MessageLookupByLibrary.simpleMessage( + "Tiếp tục tải lên và tải xuống"), + "cachedData": MessageLookupByLibrary.simpleMessage( + "Dữ liệu đã lưu trong bộ nhớ đệm"), "calculating": MessageLookupByLibrary.simpleMessage("Đang tính toán..."), "canNotOpenBody": MessageLookupByLibrary.simpleMessage( - "Xin lỗi, album này không thể mở trong ứng dụng."), + "Rất tiếc, album này không thể mở trong ứng dụng."), "canNotOpenTitle": MessageLookupByLibrary.simpleMessage("Không thể mở album này"), "canNotUploadToAlbumsOwnedByOthers": @@ -475,23 +627,22 @@ class MessageLookup extends MessageLookupByLibrary { "cancelAccountRecovery": MessageLookupByLibrary.simpleMessage("Hủy khôi phục"), "cancelAccountRecoveryBody": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn hủy khôi phục không?"), + "Bạn có chắc muốn hủy khôi phục không?"), "cancelOtherSubscription": m12, - "cancelSubscription": - MessageLookupByLibrary.simpleMessage("Hủy đăng ký"), + "cancelSubscription": MessageLookupByLibrary.simpleMessage("Hủy gói"), "cannotAddMorePhotosAfterBecomingViewer": m13, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Không thể xóa các tệp đã chia sẻ"), "castAlbum": MessageLookupByLibrary.simpleMessage("Phát album"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( - "Vui lòng đảm bảo bạn đang ở trên cùng một mạng với TV."), + "Hãy chắc rằng bạn đang dùng chung mạng với TV."), "castIPMismatchTitle": MessageLookupByLibrary.simpleMessage("Không thể phát album"), "castInstruction": MessageLookupByLibrary.simpleMessage( "Truy cập cast.ente.io trên thiết bị bạn muốn ghép nối.\n\nNhập mã dưới đây để phát album trên TV của bạn."), "centerPoint": MessageLookupByLibrary.simpleMessage("Điểm trung tâm"), "change": MessageLookupByLibrary.simpleMessage("Thay đổi"), - "changeEmail": MessageLookupByLibrary.simpleMessage("Thay đổi email"), + "changeEmail": MessageLookupByLibrary.simpleMessage("Đổi email"), "changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage( "Thay đổi vị trí của các mục đã chọn?"), "changePassword": MessageLookupByLibrary.simpleMessage("Đổi mật khẩu"), @@ -508,41 +659,43 @@ class MessageLookup extends MessageLookupByLibrary { "checkStatus": MessageLookupByLibrary.simpleMessage("Kiểm tra trạng thái"), "checking": MessageLookupByLibrary.simpleMessage("Đang kiểm tra..."), - "checkingModels": MessageLookupByLibrary.simpleMessage( - "Đang kiểm tra các mô hình..."), - "claimFreeStorage": - MessageLookupByLibrary.simpleMessage("Yêu cầu lưu trữ miễn phí"), - "claimMore": MessageLookupByLibrary.simpleMessage("Yêu cầu thêm!"), - "claimed": MessageLookupByLibrary.simpleMessage("Đã yêu cầu"), + "checkingModels": + MessageLookupByLibrary.simpleMessage("Đang kiểm tra mô hình..."), + "city": MessageLookupByLibrary.simpleMessage("Trong thành phố"), + "claimFreeStorage": MessageLookupByLibrary.simpleMessage( + "Nhận thêm dung lượng miễn phí"), + "claimMore": MessageLookupByLibrary.simpleMessage("Nhận thêm!"), + "claimed": MessageLookupByLibrary.simpleMessage("Đã nhận"), "claimedStorageSoFar": m14, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Dọn dẹp chưa phân loại"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( - "Xóa tất cả các tệp từ chưa phân loại có mặt trong các album khác"), + "Xóa khỏi mục Chưa phân loại với tất cả tệp đang xuất hiện trong các album khác"), "clearCaches": MessageLookupByLibrary.simpleMessage("Xóa bộ nhớ cache"), "clearIndexes": MessageLookupByLibrary.simpleMessage("Xóa chỉ mục"), "click": MessageLookupByLibrary.simpleMessage("• Nhấn"), "clickOnTheOverflowMenu": - MessageLookupByLibrary.simpleMessage("• Nhấn vào menu thả xuống"), + MessageLookupByLibrary.simpleMessage("• Nhấn vào menu xổ xuống"), + "clickToInstallOurBestVersionYet": MessageLookupByLibrary.simpleMessage( + "Nhấn để cài đặt phiên bản tốt nhất"), "close": MessageLookupByLibrary.simpleMessage("Đóng"), "clubByCaptureTime": - MessageLookupByLibrary.simpleMessage("Nhóm theo thời gian chụp"), + MessageLookupByLibrary.simpleMessage("Xếp theo thời gian chụp"), "clubByFileName": - MessageLookupByLibrary.simpleMessage("Nhóm theo tên tệp"), + MessageLookupByLibrary.simpleMessage("Xếp theo tên tệp"), "clusteringProgress": MessageLookupByLibrary.simpleMessage("Tiến trình phân cụm"), "codeAppliedPageTitle": MessageLookupByLibrary.simpleMessage("Mã đã được áp dụng"), "codeChangeLimitReached": MessageLookupByLibrary.simpleMessage( - "Xin lỗi, bạn đã đạt giới hạn thay đổi mã."), + "Rất tiếc, bạn đã đạt hạn mức thay đổi mã."), "codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage( - "Mã đã được sao chép vào clipboard"), - "codeUsedByYou": - MessageLookupByLibrary.simpleMessage("Mã được sử dụng bởi bạn"), + "Mã đã được sao chép vào bộ nhớ tạm"), + "codeUsedByYou": MessageLookupByLibrary.simpleMessage("Mã bạn đã dùng"), "collabLinkSectionDescription": MessageLookupByLibrary.simpleMessage( "Tạo một liên kết để cho phép mọi người thêm và xem ảnh trong album chia sẻ của bạn mà không cần ứng dụng hoặc tài khoản Ente. Tuyệt vời để thu thập ảnh sự kiện."), "collaborativeLink": - MessageLookupByLibrary.simpleMessage("Liên kết hợp tác"), + MessageLookupByLibrary.simpleMessage("Liên kết cộng tác"), "collaborativeLinkCreatedFor": m15, "collaborator": MessageLookupByLibrary.simpleMessage("Cộng tác viên"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": @@ -562,20 +715,20 @@ class MessageLookup extends MessageLookupByLibrary { "configuration": MessageLookupByLibrary.simpleMessage("Cấu hình"), "confirm": MessageLookupByLibrary.simpleMessage("Xác nhận"), "confirm2FADisable": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn vô hiệu hóa xác thực hai yếu tố không?"), + "Bạn có chắc muốn tắt xác thực 2 bước không?"), "confirmAccountDeletion": MessageLookupByLibrary.simpleMessage("Xác nhận xóa tài khoản"), "confirmAddingTrustedContact": m17, "confirmDeletePrompt": MessageLookupByLibrary.simpleMessage( - "Có, tôi muốn xóa vĩnh viễn tài khoản này và dữ liệu của nó trên tất cả các ứng dụng."), + "Có, tôi muốn xóa vĩnh viễn tài khoản này và tất cả dữ liệu của nó."), "confirmPassword": MessageLookupByLibrary.simpleMessage("Xác nhận mật khẩu"), "confirmPlanChange": MessageLookupByLibrary.simpleMessage("Xác nhận thay đổi gói"), "confirmRecoveryKey": - MessageLookupByLibrary.simpleMessage("Xác nhận khóa khôi phục"), + MessageLookupByLibrary.simpleMessage("Xác nhận mã khôi phục"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( - "Xác nhận khóa khôi phục của bạn"), + "Xác nhận mã khôi phục của bạn"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Kết nối với thiết bị"), "contactFamilyAdmin": m18, @@ -594,19 +747,19 @@ class MessageLookup extends MessageLookupByLibrary { "copyLink": MessageLookupByLibrary.simpleMessage("Sao chép liên kết"), "copypasteThisCodentoYourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( - "Sao chép-dán mã này\ntới ứng dụng xác thực của bạn"), + "Chép & dán mã này\nvào ứng dụng xác thực của bạn"), "couldNotBackUpTryLater": MessageLookupByLibrary.simpleMessage( "Chúng tôi không thể sao lưu dữ liệu của bạn.\nChúng tôi sẽ thử lại sau."), "couldNotFreeUpSpace": MessageLookupByLibrary.simpleMessage( - "Không thể giải phóng không gian"), + "Không thể giải phóng dung lượng"), "couldNotUpdateSubscription": - MessageLookupByLibrary.simpleMessage("Không thể cập nhật đăng ký"), + MessageLookupByLibrary.simpleMessage("Không thể cập nhật gói"), "count": MessageLookupByLibrary.simpleMessage("Số lượng"), "crashReporting": MessageLookupByLibrary.simpleMessage("Báo cáo sự cố"), "create": MessageLookupByLibrary.simpleMessage("Tạo"), "createAccount": MessageLookupByLibrary.simpleMessage("Tạo tài khoản"), "createAlbumActionHint": MessageLookupByLibrary.simpleMessage( - "Nhấn giữ để chọn ảnh và nhấp + để tạo album"), + "Nhấn giữ để chọn ảnh và nhấn + để tạo album"), "createCollaborativeLink": MessageLookupByLibrary.simpleMessage("Tạo liên kết cộng tác"), "createCollage": MessageLookupByLibrary.simpleMessage("Tạo ảnh ghép"), @@ -621,8 +774,10 @@ class MessageLookup extends MessageLookupByLibrary { "criticalUpdateAvailable": MessageLookupByLibrary.simpleMessage("Cập nhật quan trọng có sẵn"), "crop": MessageLookupByLibrary.simpleMessage("Cắt xén"), + "curatedMemories": + MessageLookupByLibrary.simpleMessage("Ký ức lưu giữ"), "currentUsageIs": - MessageLookupByLibrary.simpleMessage("Sử dụng hiện tại là "), + MessageLookupByLibrary.simpleMessage("Dung lượng hiện tại "), "currentlyRunning": MessageLookupByLibrary.simpleMessage("đang chạy"), "custom": MessageLookupByLibrary.simpleMessage("Tùy chỉnh"), "customEndpoint": m20, @@ -635,7 +790,7 @@ class MessageLookup extends MessageLookupByLibrary { "decryptingVideo": MessageLookupByLibrary.simpleMessage("Đang giải mã video..."), "deduplicateFiles": - MessageLookupByLibrary.simpleMessage("Xóa trùng lặp tệp"), + MessageLookupByLibrary.simpleMessage("Xóa trùng lặp"), "delete": MessageLookupByLibrary.simpleMessage("Xóa"), "deleteAccount": MessageLookupByLibrary.simpleMessage("Xóa tài khoản"), "deleteAccountFeedbackPrompt": MessageLookupByLibrary.simpleMessage( @@ -644,12 +799,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Xóa tài khoản vĩnh viễn"), "deleteAlbum": MessageLookupByLibrary.simpleMessage("Xóa album"), "deleteAlbumDialog": MessageLookupByLibrary.simpleMessage( - "Cũng xóa các ảnh (và video) có trong album này từ tất cả các album khác mà chúng là một phần của?"), + "Xóa luôn các tấm ảnh (và video) có trong album này khỏi toàn bộ album khác cũng đang chứa chúng?"), "deleteAlbumsDialogBody": MessageLookupByLibrary.simpleMessage( - "Điều này sẽ xóa tất cả album trống. Điều này hữu ích khi bạn muốn giảm bớt sự lộn xộn trong danh sách album của mình."), + "Tất cả album trống sẽ bị xóa. Sẽ hữu ích khi bạn muốn giảm bớt sự lộn xộn trong danh sách album của mình."), "deleteAll": MessageLookupByLibrary.simpleMessage("Xóa tất cả"), "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( - "Tài khoản này được liên kết với các ứng dụng Ente khác, nếu bạn sử dụng bất kỳ. Dữ liệu bạn đã tải lên, trên tất cả các ứng dụng Ente, sẽ được lên lịch để xóa, và tài khoản của bạn sẽ bị xóa vĩnh viễn."), + "Tài khoản này được liên kết với các ứng dụng Ente khác, nếu bạn có dùng. Dữ liệu bạn đã tải lên, trên tất cả ứng dụng Ente, sẽ được lên lịch để xóa, và tài khoản của bạn sẽ bị xóa vĩnh viễn."), "deleteEmailRequest": MessageLookupByLibrary.simpleMessage( "Vui lòng gửi email đến account-deletion@ente.io từ địa chỉ email đã đăng ký của bạn."), "deleteEmptyAlbums": @@ -663,80 +818,81 @@ class MessageLookup extends MessageLookupByLibrary { "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Xóa khỏi Ente"), "deleteItemCount": m21, "deleteLocation": MessageLookupByLibrary.simpleMessage("Xóa vị trí"), + "deleteMultipleAlbumDialog": m22, "deletePhotos": MessageLookupByLibrary.simpleMessage("Xóa ảnh"), "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Nó thiếu một tính năng quan trọng mà tôi cần"), "deleteReason2": MessageLookupByLibrary.simpleMessage( - "Ứng dụng hoặc một tính năng nhất định không hoạt động như tôi nghĩ"), + "Ứng dụng hoặc một tính năng nhất định không hoạt động như tôi muốn"), "deleteReason3": MessageLookupByLibrary.simpleMessage( - "Tôi đã tìm thấy một dịch vụ khác mà tôi thích hơn"), + "Tôi tìm thấy một dịch vụ khác mà tôi thích hơn"), "deleteReason4": MessageLookupByLibrary.simpleMessage( - "Lý do của tôi không có trong danh sách"), + "Lý do không có trong danh sách"), "deleteRequestSLAText": MessageLookupByLibrary.simpleMessage( "Yêu cầu của bạn sẽ được xử lý trong vòng 72 giờ."), "deleteSharedAlbum": MessageLookupByLibrary.simpleMessage("Xóa album chia sẻ?"), "deleteSharedAlbumDialogBody": MessageLookupByLibrary.simpleMessage( - "Album sẽ bị xóa cho tất cả mọi người\n\nBạn sẽ mất quyền truy cập vào các ảnh chia sẻ trong album này mà thuộc sở hữu của người khác"), + "Album sẽ bị xóa với tất cả mọi người\n\nBạn sẽ mất quyền truy cập vào các ảnh chia sẻ trong album này mà thuộc sở hữu của người khác"), "deselectAll": MessageLookupByLibrary.simpleMessage("Bỏ chọn tất cả"), - "designedToOutlive": MessageLookupByLibrary.simpleMessage( - "Được thiết kế để tồn tại lâu hơn"), + "designedToOutlive": + MessageLookupByLibrary.simpleMessage("Được thiết kế để trường tồn"), "details": MessageLookupByLibrary.simpleMessage("Chi tiết"), "developerSettings": MessageLookupByLibrary.simpleMessage("Cài đặt Nhà phát triển"), "developerSettingsWarning": MessageLookupByLibrary.simpleMessage( - "Bạn có chắc chắn muốn thay đổi cài đặt Nhà phát triển không?"), + "Bạn có chắc muốn thay đổi cài đặt Nhà phát triển không?"), "deviceCodeHint": MessageLookupByLibrary.simpleMessage("Nhập mã"), "deviceFilesAutoUploading": MessageLookupByLibrary.simpleMessage( "Các tệp được thêm vào album thiết bị này sẽ tự động được tải lên Ente."), "deviceLock": MessageLookupByLibrary.simpleMessage("Khóa thiết bị"), "deviceLockExplanation": MessageLookupByLibrary.simpleMessage( - "Vô hiệu hóa khóa màn hình thiết bị khi Ente đang ở chế độ nền và có một bản sao lưu đang diễn ra. Điều này thường không cần thiết, nhưng có thể giúp các tải lên lớn và nhập khẩu ban đầu của các thư viện lớn hoàn thành nhanh hơn."), + "Vô hiệu hóa khóa màn hình thiết bị khi Ente đang ở chế độ nền và có một bản sao lưu đang diễn ra. Điều này thường không cần thiết, nhưng có thể giúp tải lên các tệp lớn và tệp nhập của các thư viện lớn xong nhanh hơn."), "deviceNotFound": MessageLookupByLibrary.simpleMessage("Không tìm thấy thiết bị"), "didYouKnow": MessageLookupByLibrary.simpleMessage("Bạn có biết?"), + "different": MessageLookupByLibrary.simpleMessage("Khác"), "disableAutoLock": MessageLookupByLibrary.simpleMessage("Vô hiệu hóa khóa tự động"), "disableDownloadWarningBody": MessageLookupByLibrary.simpleMessage( - "Người xem vẫn có thể chụp màn hình hoặc lưu bản sao ảnh của bạn bằng các công cụ bên ngoài"), + "Người xem vẫn có thể chụp ảnh màn hình hoặc sao chép ảnh của bạn bằng các công cụ bên ngoài"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Xin lưu ý"), "disableLinkMessage": m24, - "disableTwofactor": MessageLookupByLibrary.simpleMessage( - "Vô hiệu hóa xác thực hai yếu tố"), + "disableTwofactor": + MessageLookupByLibrary.simpleMessage("Tắt xác thực 2 bước"), "disablingTwofactorAuthentication": MessageLookupByLibrary.simpleMessage( - "Đang vô hiệu hóa xác thực hai yếu tố..."), + "Đang vô hiệu hóa xác thực 2 bước..."), "discord": MessageLookupByLibrary.simpleMessage("Discord"), "discover": MessageLookupByLibrary.simpleMessage("Khám phá"), - "discover_babies": MessageLookupByLibrary.simpleMessage("Trẻ em"), + "discover_babies": MessageLookupByLibrary.simpleMessage("Em bé"), "discover_celebrations": MessageLookupByLibrary.simpleMessage("Lễ kỷ niệm"), "discover_food": MessageLookupByLibrary.simpleMessage("Thức ăn"), "discover_greenery": MessageLookupByLibrary.simpleMessage("Cây cối"), "discover_hills": MessageLookupByLibrary.simpleMessage("Đồi"), - "discover_identity": MessageLookupByLibrary.simpleMessage("Danh tính"), - "discover_memes": MessageLookupByLibrary.simpleMessage("Hình ảnh chế"), + "discover_identity": MessageLookupByLibrary.simpleMessage("Nhận dạng"), + "discover_memes": MessageLookupByLibrary.simpleMessage("Meme"), "discover_notes": MessageLookupByLibrary.simpleMessage("Ghi chú"), "discover_pets": MessageLookupByLibrary.simpleMessage("Thú cưng"), "discover_receipts": MessageLookupByLibrary.simpleMessage("Biên lai"), "discover_screenshots": MessageLookupByLibrary.simpleMessage("Ảnh chụp màn hình"), - "discover_selfies": - MessageLookupByLibrary.simpleMessage("Ảnh tự sướng"), + "discover_selfies": MessageLookupByLibrary.simpleMessage("Selfie"), "discover_sunset": MessageLookupByLibrary.simpleMessage("Hoàng hôn"), - "discover_visiting_cards": - MessageLookupByLibrary.simpleMessage("Thẻ thăm"), + "discover_visiting_cards": MessageLookupByLibrary.simpleMessage("Thẻ"), "discover_wallpapers": MessageLookupByLibrary.simpleMessage("Hình nền"), "dismiss": MessageLookupByLibrary.simpleMessage("Bỏ qua"), "distanceInKMUnit": MessageLookupByLibrary.simpleMessage("km"), "doNotSignOut": MessageLookupByLibrary.simpleMessage("Không đăng xuất"), - "doThisLater": MessageLookupByLibrary.simpleMessage("Làm điều này sau"), + "doThisLater": MessageLookupByLibrary.simpleMessage("Để sau"), "doYouWantToDiscardTheEditsYouHaveMade": MessageLookupByLibrary.simpleMessage( - "Bạn có muốn bỏ qua các chỉnh sửa bạn đã thực hiện không?"), + "Bạn có muốn bỏ qua các chỉnh sửa đã thực hiện không?"), "done": MessageLookupByLibrary.simpleMessage("Xong"), + "dontSave": MessageLookupByLibrary.simpleMessage("Không lưu"), "doubleYourStorage": MessageLookupByLibrary.simpleMessage( "Gấp đôi dung lượng lưu trữ của bạn"), "download": MessageLookupByLibrary.simpleMessage("Tải xuống"), @@ -748,41 +904,45 @@ class MessageLookup extends MessageLookupByLibrary { "duplicateFileCountWithStorageSaved": m26, "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Chỉnh sửa"), + "editEmailAlreadyLinked": m28, "editLocation": MessageLookupByLibrary.simpleMessage("Chỉnh sửa vị trí"), "editLocationTagTitle": MessageLookupByLibrary.simpleMessage("Chỉnh sửa vị trí"), "editPerson": MessageLookupByLibrary.simpleMessage("Chỉnh sửa người"), + "editTime": MessageLookupByLibrary.simpleMessage("Chỉnh sửa thời gian"), "editsSaved": MessageLookupByLibrary.simpleMessage("Chỉnh sửa đã được lưu"), "editsToLocationWillOnlyBeSeenWithinEnte": MessageLookupByLibrary.simpleMessage( - "Các chỉnh sửa cho vị trí sẽ chỉ được thấy trong Ente"), + "Các chỉnh sửa vị trí sẽ chỉ thấy được trong Ente"), "eligible": MessageLookupByLibrary.simpleMessage("đủ điều kiện"), "email": MessageLookupByLibrary.simpleMessage("Email"), "emailAlreadyRegistered": - MessageLookupByLibrary.simpleMessage("Email đã được đăng kí."), + MessageLookupByLibrary.simpleMessage("Email đã được đăng ký."), "emailChangedTo": m29, + "emailDoesNotHaveEnteAccount": m30, "emailNoEnteAccount": m31, "emailNotRegistered": - MessageLookupByLibrary.simpleMessage("Email chưa được đăng kí."), + MessageLookupByLibrary.simpleMessage("Email chưa được đăng ký."), "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Xác minh email"), "emailYourLogs": - MessageLookupByLibrary.simpleMessage("Gửi nhật ký qua email"), + MessageLookupByLibrary.simpleMessage("Gửi log qua email"), + "embracingThem": m32, "emergencyContacts": MessageLookupByLibrary.simpleMessage("Liên hệ khẩn cấp"), - "empty": MessageLookupByLibrary.simpleMessage("Rỗng"), + "empty": MessageLookupByLibrary.simpleMessage("Xóa sạch"), "emptyTrash": - MessageLookupByLibrary.simpleMessage("Làm rỗng thùng rác?"), + MessageLookupByLibrary.simpleMessage("Xóa sạch thùng rác?"), "enable": MessageLookupByLibrary.simpleMessage("Bật"), "enableMLIndexingDesc": MessageLookupByLibrary.simpleMessage( - "Ente hỗ trợ học máy trên thiết bị cho nhận diện khuôn mặt, tìm kiếm ma thuật và các tính năng tìm kiếm nâng cao khác"), + "Ente hỗ trợ học máy trên-thiết-bị nhằm nhận diện khuôn mặt, tìm kiếm vi diệu và các tính năng tìm kiếm nâng cao khác"), "enableMachineLearningBanner": MessageLookupByLibrary.simpleMessage( - "Bật học máy cho tìm kiếm ma thuật và nhận diện khuôn mặt"), + "Bật học máy để tìm kiếm vi diệu và nhận diện khuôn mặt"), "enableMaps": MessageLookupByLibrary.simpleMessage("Kích hoạt Bản đồ"), "enableMapsDesc": MessageLookupByLibrary.simpleMessage( - "Điều này sẽ hiển thị ảnh của bạn trên bản đồ thế giới.\n\nBản đồ này được lưu trữ bởi Open Street Map, và vị trí chính xác của ảnh của bạn sẽ không bao giờ được chia sẻ.\n\nBạn có thể vô hiệu hóa tính năng này bất cứ lúc nào từ Cài đặt."), + "Ảnh của bạn sẽ hiển thị trên bản đồ thế giới.\n\nBản đồ được lưu trữ bởi OpenStreetMap, và vị trí chính xác ảnh của bạn không bao giờ được chia sẻ.\n\nBạn có thể tắt tính năng này bất cứ lúc nào từ Cài đặt."), "enabled": MessageLookupByLibrary.simpleMessage("Đã bật"), "encryptingBackup": MessageLookupByLibrary.simpleMessage("Đang mã hóa sao lưu..."), @@ -794,28 +954,28 @@ class MessageLookup extends MessageLookupByLibrary { "Mã hóa đầu cuối theo mặc định"), "enteCanEncryptAndPreserveFilesOnlyIfYouGrant": MessageLookupByLibrary.simpleMessage( - "Ente có thể mã hóa và lưu giữ tệp chỉ nếu bạn cấp quyền truy cập cho chúng"), + "Ente chỉ có thể mã hóa và lưu giữ tệp nếu bạn cấp quyền truy cập chúng"), "entePhotosPerm": MessageLookupByLibrary.simpleMessage( "Ente cần quyền để lưu giữ ảnh của bạn"), "enteSubscriptionPitch": MessageLookupByLibrary.simpleMessage( - "Ente lưu giữ kỷ niệm của bạn, vì vậy chúng luôn có sẵn cho bạn, ngay cả khi bạn mất thiết bị."), + "Ente lưu giữ kỷ niệm của bạn, vì vậy chúng luôn có sẵn, ngay cả khi bạn mất thiết bị."), "enteSubscriptionShareWithFamily": MessageLookupByLibrary.simpleMessage( - "Gia đình bạn cũng có thể được thêm vào gói của bạn."), + "Bạn có thể thêm gia đình vào gói của mình."), "enterAlbumName": MessageLookupByLibrary.simpleMessage("Nhập tên album"), "enterCode": MessageLookupByLibrary.simpleMessage("Nhập mã"), "enterCodeDescription": MessageLookupByLibrary.simpleMessage( - "Nhập mã do bạn bè cung cấp để nhận lưu trữ miễn phí cho cả hai bạn"), + "Nhập mã do bạn bè cung cấp để nhận thêm dung lượng miễn phí cho cả hai"), "enterDateOfBirth": MessageLookupByLibrary.simpleMessage("Sinh nhật (tùy chọn)"), "enterEmail": MessageLookupByLibrary.simpleMessage("Nhập email"), "enterFileName": MessageLookupByLibrary.simpleMessage("Nhập tên tệp"), "enterName": MessageLookupByLibrary.simpleMessage("Nhập tên"), "enterNewPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( - "Nhập mật khẩu mới mà chúng tôi có thể sử dụng để mã hóa dữ liệu của bạn"), + "Vui lòng nhập một mật khẩu mới để mã hóa dữ liệu của bạn"), "enterPassword": MessageLookupByLibrary.simpleMessage("Nhập mật khẩu"), "enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( - "Nhập mật khẩu mà chúng tôi có thể sử dụng để mã hóa dữ liệu của bạn"), + "Vui lòng nhập một mật khẩu dùng để mã hóa dữ liệu của bạn"), "enterPersonName": MessageLookupByLibrary.simpleMessage("Nhập tên người"), "enterPin": MessageLookupByLibrary.simpleMessage("Nhập PIN"), @@ -823,23 +983,25 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nhập mã giới thiệu"), "enterThe6digitCodeFromnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( - "Nhập mã 6 chữ số từ\ntới ứng dụng xác thực của bạn"), + "Nhập mã 6 chữ số từ\nứng dụng xác thực của bạn"), "enterValidEmail": MessageLookupByLibrary.simpleMessage( "Vui lòng nhập một địa chỉ email hợp lệ."), "enterYourEmailAddress": MessageLookupByLibrary.simpleMessage("Nhập địa chỉ email của bạn"), + "enterYourNewEmailAddress": MessageLookupByLibrary.simpleMessage( + "Nhập địa chỉ email mới của bạn"), "enterYourPassword": MessageLookupByLibrary.simpleMessage("Nhập mật khẩu của bạn"), "enterYourRecoveryKey": - MessageLookupByLibrary.simpleMessage("Nhập khóa khôi phục của bạn"), + MessageLookupByLibrary.simpleMessage("Nhập mã khôi phục của bạn"), "error": MessageLookupByLibrary.simpleMessage("Lỗi"), "everywhere": MessageLookupByLibrary.simpleMessage("mọi nơi"), - "exif": MessageLookupByLibrary.simpleMessage("EXIF"), + "exif": MessageLookupByLibrary.simpleMessage("Exif"), "existingUser": MessageLookupByLibrary.simpleMessage("Người dùng hiện tại"), "expiredLinkInfo": MessageLookupByLibrary.simpleMessage( "Liên kết này đã hết hạn. Vui lòng chọn thời gian hết hạn mới hoặc tắt tính năng hết hạn liên kết."), - "exportLogs": MessageLookupByLibrary.simpleMessage("Xuất nhật ký"), + "exportLogs": MessageLookupByLibrary.simpleMessage("Xuất file log"), "exportYourData": MessageLookupByLibrary.simpleMessage("Xuất dữ liệu của bạn"), "extraPhotosFound": @@ -850,6 +1012,7 @@ class MessageLookup extends MessageLookupByLibrary { "faceRecognition": MessageLookupByLibrary.simpleMessage("Nhận diện khuôn mặt"), "faces": MessageLookupByLibrary.simpleMessage("Khuôn mặt"), + "failed": MessageLookupByLibrary.simpleMessage("Không thành công"), "failedToApplyCode": MessageLookupByLibrary.simpleMessage("Không thể áp dụng mã"), "failedToCancel": @@ -867,19 +1030,20 @@ class MessageLookup extends MessageLookupByLibrary { "failedToPlayVideo": MessageLookupByLibrary.simpleMessage("Không thể phát video"), "failedToRefreshStripeSubscription": - MessageLookupByLibrary.simpleMessage("Không thể làm mới đăng ký"), + MessageLookupByLibrary.simpleMessage("Không thể làm mới gói"), "failedToRenew": MessageLookupByLibrary.simpleMessage("Gia hạn không thành công"), "failedToVerifyPaymentStatus": MessageLookupByLibrary.simpleMessage( "Không thể xác minh trạng thái thanh toán"), "familyPlanOverview": MessageLookupByLibrary.simpleMessage( - "Thêm 5 thành viên gia đình vào gói hiện tại của bạn mà không phải trả thêm phí.\n\nMỗi thành viên có không gian riêng tư của mình và không thể xem tệp của nhau trừ khi được chia sẻ.\n\nGói gia đình có sẵn cho khách hàng có đăng ký Ente trả phí.\n\nĐăng ký ngay để bắt đầu!"), + "Thêm 5 thành viên gia đình vào gói hiện tại của bạn mà không phải trả thêm phí.\n\nMỗi thành viên có không gian riêng tư của mình và không thể xem tệp của nhau trừ khi được chia sẻ.\n\nGói gia đình có sẵn cho người dùng Ente gói trả phí.\n\nĐăng ký ngay để bắt đầu!"), "familyPlanPortalTitle": MessageLookupByLibrary.simpleMessage("Gia đình"), "familyPlans": MessageLookupByLibrary.simpleMessage("Gói gia đình"), "faq": MessageLookupByLibrary.simpleMessage("Câu hỏi thường gặp"), "faqs": MessageLookupByLibrary.simpleMessage("Câu hỏi thường gặp"), - "favorite": MessageLookupByLibrary.simpleMessage("Yêu thích"), + "favorite": MessageLookupByLibrary.simpleMessage("Thích"), + "feastingWithThem": m34, "feedback": MessageLookupByLibrary.simpleMessage("Phản hồi"), "file": MessageLookupByLibrary.simpleMessage("Tệp"), "fileFailedToSaveToGallery": MessageLookupByLibrary.simpleMessage( @@ -898,52 +1062,57 @@ class MessageLookup extends MessageLookupByLibrary { "filesDeleted": MessageLookupByLibrary.simpleMessage("Tệp đã bị xóa"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage( "Các tệp đã được lưu vào thư viện"), - "findPeopleByName": MessageLookupByLibrary.simpleMessage( - "Tìm người nhanh chóng theo tên"), + "findPeopleByName": + MessageLookupByLibrary.simpleMessage("Tìm nhanh người theo tên"), "findThemQuickly": MessageLookupByLibrary.simpleMessage("Tìm họ nhanh chóng"), "flip": MessageLookupByLibrary.simpleMessage("Lật"), + "food": MessageLookupByLibrary.simpleMessage("Ăn chơi"), "forYourMemories": MessageLookupByLibrary.simpleMessage("cho những kỷ niệm của bạn"), "forgotPassword": MessageLookupByLibrary.simpleMessage("Quên mật khẩu"), "foundFaces": MessageLookupByLibrary.simpleMessage("Đã tìm thấy khuôn mặt"), "freeStorageClaimed": - MessageLookupByLibrary.simpleMessage("Lưu trữ miễn phí đã yêu cầu"), + MessageLookupByLibrary.simpleMessage("Dung lượng miễn phí đã nhận"), "freeStorageOnReferralSuccess": m37, "freeStorageUsable": MessageLookupByLibrary.simpleMessage( - "Lưu trữ miễn phí có thể sử dụng"), + "Dung lượng miễn phí có thể dùng"), "freeTrial": MessageLookupByLibrary.simpleMessage("Dùng thử miễn phí"), "freeTrialValidTill": m38, + "freeUpAccessPostDelete": m39, "freeUpAmount": m40, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( - "Giải phóng không gian thiết bị"), + "Giải phóng dung lượng thiết bị"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( - "Tiết kiệm không gian trên thiết bị của bạn bằng cách xóa các tệp đã được sao lưu."), + "Tiết kiệm dung lượng thiết bị của bạn bằng cách xóa các tệp đã được sao lưu."), "freeUpSpace": - MessageLookupByLibrary.simpleMessage("Giải phóng không gian"), + MessageLookupByLibrary.simpleMessage("Giải phóng dung lượng"), "freeUpSpaceSaving": m41, "gallery": MessageLookupByLibrary.simpleMessage("Thư viện"), "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( - "Tối đa 1000 kỷ niệm được hiển thị trong thư viện"), + "Mỗi thư viện chứa tối đa 1000 ảnh"), "general": MessageLookupByLibrary.simpleMessage("Chung"), "generatingEncryptionKeys": - MessageLookupByLibrary.simpleMessage("Đang tạo khóa mã hóa..."), + MessageLookupByLibrary.simpleMessage("Đang mã hóa..."), "genericProgress": m42, "goToSettings": MessageLookupByLibrary.simpleMessage("Đi đến cài đặt"), "googlePlayId": MessageLookupByLibrary.simpleMessage("ID Google Play"), "grantFullAccessPrompt": MessageLookupByLibrary.simpleMessage( "Vui lòng cho phép truy cập vào tất cả ảnh trong ứng dụng Cài đặt"), "grantPermission": MessageLookupByLibrary.simpleMessage("Cấp quyền"), + "greenery": MessageLookupByLibrary.simpleMessage("Cây cối"), "groupNearbyPhotos": - MessageLookupByLibrary.simpleMessage("Nhóm ảnh gần đó"), + MessageLookupByLibrary.simpleMessage("Nhóm ảnh gần nhau"), "guestView": MessageLookupByLibrary.simpleMessage("Chế độ khách"), "guestViewEnablePreSteps": MessageLookupByLibrary.simpleMessage( "Để bật chế độ khách, vui lòng thiết lập mã khóa thiết bị hoặc khóa màn hình trong cài đặt hệ thống của bạn."), + "happyBirthday": + MessageLookupByLibrary.simpleMessage("Chúc mừng sinh nhật! 🥳"), "hearUsExplanation": MessageLookupByLibrary.simpleMessage( - "Chúng tôi không theo dõi cài đặt ứng dụng. Sẽ rất hữu ích nếu bạn cho chúng tôi biết bạn đã tìm thấy chúng ở đâu!"), + "Chúng tôi không theo dõi cài đặt ứng dụng, nên nếu bạn bật mí bạn tìm thấy chúng tôi từ đâu sẽ rất hữu ích!"), "hearUsWhereTitle": MessageLookupByLibrary.simpleMessage( - "Bạn đã nghe về Ente từ đâu? (tùy chọn)"), + "Bạn biết Ente từ đâu? (tùy chọn)"), "help": MessageLookupByLibrary.simpleMessage("Trợ giúp"), "hidden": MessageLookupByLibrary.simpleMessage("Ẩn"), "hide": MessageLookupByLibrary.simpleMessage("Ẩn"), @@ -955,36 +1124,42 @@ class MessageLookup extends MessageLookupByLibrary { "hideSharedItemsFromHomeGallery": MessageLookupByLibrary.simpleMessage( "Ẩn các mục được chia sẻ khỏi thư viện chính"), "hiding": MessageLookupByLibrary.simpleMessage("Đang ẩn..."), + "hikingWithThem": m43, "hostedAtOsmFrance": MessageLookupByLibrary.simpleMessage("Được lưu trữ tại OSM Pháp"), "howItWorks": MessageLookupByLibrary.simpleMessage("Cách hoạt động"), "howToViewShareeVerificationID": MessageLookupByLibrary.simpleMessage( - "Vui lòng yêu cầu họ nhấn giữ địa chỉ email của họ trên màn hình cài đặt, và xác minh rằng các ID trên cả hai thiết bị khớp nhau."), + "Hãy chỉ họ nhấn giữ địa chỉ email của họ trên màn hình cài đặt, và xác minh rằng ID trên cả hai thiết bị khớp nhau."), "iOSGoToSettingsDescription": MessageLookupByLibrary.simpleMessage( - "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Vui lòng kích hoạt Touch ID hoặc Face ID trên điện thoại của bạn."), + "Xác thực sinh trắc học chưa được thiết lập trên thiết bị của bạn. Vui lòng kích hoạt Touch ID hoặc Face ID."), "iOSLockOut": MessageLookupByLibrary.simpleMessage( "Xác thực sinh trắc học đã bị vô hiệu hóa. Vui lòng khóa và mở khóa màn hình của bạn để kích hoạt lại."), "iOSOkButton": MessageLookupByLibrary.simpleMessage("OK"), + "ignore": MessageLookupByLibrary.simpleMessage("Bỏ qua"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("Bỏ qua"), "ignored": MessageLookupByLibrary.simpleMessage("bỏ qua"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( "Một số tệp trong album này bị bỏ qua khi tải lên vì chúng đã bị xóa trước đó từ Ente."), "imageNotAnalyzed": MessageLookupByLibrary.simpleMessage( "Hình ảnh chưa được phân tích"), - "immediately": MessageLookupByLibrary.simpleMessage("Ngay lập tức"), + "immediately": MessageLookupByLibrary.simpleMessage("Lập tức"), "importing": MessageLookupByLibrary.simpleMessage("Đang nhập...."), "incorrectCode": MessageLookupByLibrary.simpleMessage("Mã không chính xác"), "incorrectPasswordTitle": MessageLookupByLibrary.simpleMessage("Mật khẩu không chính xác"), "incorrectRecoveryKey": MessageLookupByLibrary.simpleMessage( - "Khóa khôi phục không chính xác"), + "Mã khôi phục không chính xác"), "incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage( - "Khóa khôi phục bạn nhập không chính xác"), + "Mã khôi phục bạn nhập không chính xác"), "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage( - "Khóa khôi phục không chính xác"), + "Mã khôi phục không chính xác"), "indexedItems": MessageLookupByLibrary.simpleMessage("Các mục đã lập chỉ mục"), + "indexingPausedStatusDescription": MessageLookupByLibrary.simpleMessage( + "Lập chỉ mục bị tạm dừng. Nó sẽ tự động tiếp tục khi thiết bị đã sẵn sàng. Thiết bị được coi là sẵn sàng khi mức pin, tình trạng pin và trạng thái nhiệt độ nằm trong phạm vi tốt."), + "ineligible": + MessageLookupByLibrary.simpleMessage("Không đủ điều kiện"), "info": MessageLookupByLibrary.simpleMessage("Thông tin"), "insecureDevice": MessageLookupByLibrary.simpleMessage("Thiết bị không an toàn"), @@ -996,59 +1171,68 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Điểm cuối không hợp lệ"), "invalidEndpointMessage": MessageLookupByLibrary.simpleMessage( "Xin lỗi, điểm cuối bạn nhập không hợp lệ. Vui lòng nhập một điểm cuối hợp lệ và thử lại."), - "invalidKey": MessageLookupByLibrary.simpleMessage("Khóa không hợp lệ"), + "invalidKey": MessageLookupByLibrary.simpleMessage("Mã không hợp lệ"), "invalidRecoveryKey": MessageLookupByLibrary.simpleMessage( - "Khóa khôi phục bạn nhập không hợp lệ. Vui lòng đảm bảo nó chứa 24 từ, và kiểm tra chính tả của từng từ.\n\nNếu bạn đã nhập mã khôi phục cũ, hãy đảm bảo nó dài 64 ký tự, và kiểm tra từng ký tự."), + "Mã khôi phục không hợp lệ. Vui lòng đảm bảo nó chứa 24 từ, và đúng chính tả từng từ.\n\nNếu bạn nhập loại mã khôi phục cũ, hãy đảm bảo nó dài 64 ký tự, và kiểm tra từng ký tự."), "invite": MessageLookupByLibrary.simpleMessage("Mời"), - "inviteToEnte": MessageLookupByLibrary.simpleMessage("Mời đến Ente"), + "inviteToEnte": + MessageLookupByLibrary.simpleMessage("Mời sử dụng Ente"), "inviteYourFriends": MessageLookupByLibrary.simpleMessage("Mời bạn bè của bạn"), "inviteYourFriendsToEnte": - MessageLookupByLibrary.simpleMessage("Mời bạn bè của bạn đến Ente"), + MessageLookupByLibrary.simpleMessage("Mời bạn bè dùng Ente"), "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Có vẻ như đã xảy ra sự cố. Vui lòng thử lại sau một thời gian. Nếu lỗi vẫn tiếp diễn, vui lòng liên hệ với đội ngũ hỗ trợ của chúng tôi."), "itemCount": m44, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( - "Các mục cho biết số ngày còn lại trước khi xóa vĩnh viễn"), + "Các mục hiện số ngày còn lại trước khi xóa vĩnh viễn"), "itemsWillBeRemovedFromAlbum": MessageLookupByLibrary.simpleMessage( "Các mục đã chọn sẽ bị xóa khỏi album này"), "join": MessageLookupByLibrary.simpleMessage("Tham gia"), "joinAlbum": MessageLookupByLibrary.simpleMessage("Tham gia album"), + "joinAlbumConfirmationDialogBody": MessageLookupByLibrary.simpleMessage( + "Tham gia một album sẽ khiến email của bạn hiển thị với những người tham gia khác."), "joinAlbumSubtext": MessageLookupByLibrary.simpleMessage("để xem và thêm ảnh của bạn"), - "joinAlbumSubtextViewer": - MessageLookupByLibrary.simpleMessage("thêm vào album được chia sẻ"), + "joinAlbumSubtextViewer": MessageLookupByLibrary.simpleMessage( + "để thêm vào album được chia sẻ"), "joinDiscord": MessageLookupByLibrary.simpleMessage("Tham gia Discord"), "keepPhotos": MessageLookupByLibrary.simpleMessage("Giữ ảnh"), "kiloMeterUnit": MessageLookupByLibrary.simpleMessage("km"), "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage( - "Vui lòng giúp chúng tôi với thông tin này"), + "Mong bạn giúp chúng tôi thông tin này"), "language": MessageLookupByLibrary.simpleMessage("Ngôn ngữ"), - "lastUpdated": - MessageLookupByLibrary.simpleMessage("Cập nhật lần cuối"), + "lastTimeWithThem": m45, + "lastUpdated": MessageLookupByLibrary.simpleMessage("Mới cập nhật"), + "lastYearsTrip": + MessageLookupByLibrary.simpleMessage("Phượt năm ngoái"), "leave": MessageLookupByLibrary.simpleMessage("Rời"), "leaveAlbum": MessageLookupByLibrary.simpleMessage("Rời khỏi album"), "leaveFamily": MessageLookupByLibrary.simpleMessage("Rời khỏi gia đình"), "leaveSharedAlbum": - MessageLookupByLibrary.simpleMessage("Rời khỏi album chia sẻ?"), + MessageLookupByLibrary.simpleMessage("Rời album được chia sẻ?"), "left": MessageLookupByLibrary.simpleMessage("Trái"), "legacy": MessageLookupByLibrary.simpleMessage("Thừa kế"), "legacyAccounts": MessageLookupByLibrary.simpleMessage("Tài khoản thừa kế"), "legacyInvite": m46, "legacyPageDesc": MessageLookupByLibrary.simpleMessage( - "Thừa kế cho phép các liên hệ tin cậy truy cập tài khoản của bạn khi bạn không hoạt động."), + "Thừa kế cho phép các liên hệ tin cậy truy cập tài khoản của bạn khi bạn qua đời."), "legacyPageDesc2": MessageLookupByLibrary.simpleMessage( "Các liên hệ tin cậy có thể khởi động quá trình khôi phục tài khoản, và nếu không bị chặn trong vòng 30 ngày, có thể đặt lại mật khẩu và truy cập tài khoản của bạn."), - "light": MessageLookupByLibrary.simpleMessage("Ánh sáng"), + "light": MessageLookupByLibrary.simpleMessage("Độ sáng"), "lightTheme": MessageLookupByLibrary.simpleMessage("Sáng"), + "link": MessageLookupByLibrary.simpleMessage("Liên kết"), "linkCopiedToClipboard": MessageLookupByLibrary.simpleMessage( - "Liên kết đã được sao chép vào clipboard"), + "Liên kết đã được sao chép vào bộ nhớ tạm"), "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("Giới hạn thiết bị"), + "linkEmail": MessageLookupByLibrary.simpleMessage("Liên kết email"), + "linkEmailToContactBannerCaption": + MessageLookupByLibrary.simpleMessage("để chia sẻ nhanh hơn"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Đã bật"), "linkExpired": MessageLookupByLibrary.simpleMessage("Hết hạn"), "linkExpiresOn": m47, @@ -1057,25 +1241,32 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Liên kết đã hết hạn"), "linkNeverExpires": MessageLookupByLibrary.simpleMessage("Không bao giờ"), - "livePhotos": MessageLookupByLibrary.simpleMessage("Ảnh trực tiếp"), + "linkPerson": MessageLookupByLibrary.simpleMessage("Liên kết người"), + "linkPersonCaption": MessageLookupByLibrary.simpleMessage( + "để trải nghiệm chia sẻ tốt hơn"), + "linkPersonToEmail": m48, + "linkPersonToEmailConfirmation": m49, + "livePhotos": MessageLookupByLibrary.simpleMessage("Ảnh Live"), "loadMessage1": MessageLookupByLibrary.simpleMessage( - "Bạn có thể chia sẻ đăng ký của mình với gia đình"), + "Bạn có thể chia sẻ gói của mình với gia đình"), + "loadMessage2": MessageLookupByLibrary.simpleMessage( + "Chúng tôi đã lưu giữ hơn 200 triệu kỷ niệm cho đến hiện tại"), "loadMessage3": MessageLookupByLibrary.simpleMessage( - "Chúng tôi giữ 3 bản sao dữ liệu của bạn, một trong nơi trú ẩn dưới lòng đất"), + "Chúng tôi giữ 3 bản sao dữ liệu của bạn, một cái lưu ở hầm trú ẩn hạt nhân"), "loadMessage4": MessageLookupByLibrary.simpleMessage( "Tất cả các ứng dụng của chúng tôi đều là mã nguồn mở"), "loadMessage5": MessageLookupByLibrary.simpleMessage( - "Mã nguồn và mật mã của chúng tôi đã được kiểm toán bên ngoài"), + "Mã nguồn và mã hóa của chúng tôi đã được kiểm nghiệm ngoại bộ"), "loadMessage6": MessageLookupByLibrary.simpleMessage( "Bạn có thể chia sẻ liên kết đến album của mình với những người thân yêu"), "loadMessage7": MessageLookupByLibrary.simpleMessage( - "Các ứng dụng di động của chúng tôi chạy ngầm để mã hóa và sao lưu bất kỳ ảnh mới nào bạn chụp"), + "Các ứng dụng di động của chúng tôi chạy ngầm để mã hóa và sao lưu bất kỳ ảnh nào bạn mới chụp"), "loadMessage8": MessageLookupByLibrary.simpleMessage( "web.ente.io có một trình tải lên mượt mà"), "loadMessage9": MessageLookupByLibrary.simpleMessage( - "Chúng tôi sử dụng Xchacha20Poly1305 để mã hóa dữ liệu của bạn một cách an toàn"), + "Chúng tôi sử dụng Xchacha20Poly1305 để mã hóa dữ liệu của bạn"), "loadingExifData": - MessageLookupByLibrary.simpleMessage("Đang tải dữ liệu EXIF..."), + MessageLookupByLibrary.simpleMessage("Đang tải thông số Exif..."), "loadingGallery": MessageLookupByLibrary.simpleMessage("Đang tải thư viện..."), "loadingMessage": @@ -1087,14 +1278,14 @@ class MessageLookup extends MessageLookupByLibrary { "localGallery": MessageLookupByLibrary.simpleMessage("Thư viện cục bộ"), "localIndexing": MessageLookupByLibrary.simpleMessage("Chỉ mục cục bộ"), "localSyncErrorMessage": MessageLookupByLibrary.simpleMessage( - "Có vẻ như có điều gì đó không ổn vì đồng bộ hóa ảnh cục bộ đang mất nhiều thời gian hơn mong đợi. Vui lòng liên hệ với đội ngũ hỗ trợ của chúng tôi"), + "Có vẻ như có điều gì đó không ổn vì đồng bộ hóa ảnh cục bộ đang mất nhiều thời gian hơn mong đợi. Vui lòng liên hệ đội ngũ hỗ trợ của chúng tôi"), "location": MessageLookupByLibrary.simpleMessage("Vị trí"), "locationName": MessageLookupByLibrary.simpleMessage("Tên vị trí"), "locationTagFeatureDescription": MessageLookupByLibrary.simpleMessage( - "Một thẻ vị trí nhóm tất cả các ảnh được chụp trong một bán kính nào đó của một bức ảnh"), + "Một thẻ vị trí sẽ chia nhóm tất cả các ảnh được chụp trong một bán kính nào đó của một bức ảnh"), "locations": MessageLookupByLibrary.simpleMessage("Vị trí"), "lockButtonLabel": MessageLookupByLibrary.simpleMessage("Khóa"), - "lockscreen": MessageLookupByLibrary.simpleMessage("Màn hình khóa"), + "lockscreen": MessageLookupByLibrary.simpleMessage("Khóa màn hình"), "logInLabel": MessageLookupByLibrary.simpleMessage("Đăng nhập"), "loggingOut": MessageLookupByLibrary.simpleMessage("Đang đăng xuất..."), "loginSessionExpired": @@ -1102,78 +1293,89 @@ class MessageLookup extends MessageLookupByLibrary { "loginSessionExpiredDetails": MessageLookupByLibrary.simpleMessage( "Phiên đăng nhập của bạn đã hết hạn. Vui lòng đăng nhập lại."), "loginTerms": MessageLookupByLibrary.simpleMessage( - "Bằng cách nhấp vào đăng nhập, tôi đồng ý với các điều khoản dịch vụchính sách bảo mật"), + "Nhấn vào đăng nhập, tôi đồng ý điều khoảnchính sách bảo mật"), "loginWithTOTP": - MessageLookupByLibrary.simpleMessage("Login with TOTP"), + MessageLookupByLibrary.simpleMessage("Đăng nhập bằng TOTP"), "logout": MessageLookupByLibrary.simpleMessage("Đăng xuất"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( - "Điều này sẽ gửi nhật ký để giúp chúng tôi gỡ lỗi vấn đề của bạn. Vui lòng lưu ý rằng tên tệp sẽ được bao gồm để giúp theo dõi các vấn đề với các tệp cụ thể."), + "Gửi file log để chúng tôi có thể phân tích lỗi mà bạn gặp. Lưu ý rằng, trong nhật ký lỗi sẽ bao gồm tên các tệp để giúp theo dõi vấn đề với từng tệp cụ thể."), "longPressAnEmailToVerifyEndToEndEncryption": MessageLookupByLibrary.simpleMessage( "Nhấn giữ một email để xác minh mã hóa đầu cuối."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( - "Nhấn và giữ vào một mục để xem toàn màn hình"), + "Nhấn giữ một mục để xem toàn màn hình"), + "lookBackOnYourMemories": + MessageLookupByLibrary.simpleMessage("Xem lại kỷ niệm của bạn 🌄"), "loopVideoOff": MessageLookupByLibrary.simpleMessage("Dừng phát video lặp lại"), "loopVideoOn": MessageLookupByLibrary.simpleMessage("Phát video lặp lại"), "lostDevice": MessageLookupByLibrary.simpleMessage("Mất thiết bị?"), "machineLearning": MessageLookupByLibrary.simpleMessage("Học máy"), - "magicSearch": - MessageLookupByLibrary.simpleMessage("Tìm kiếm ma thuật"), + "magicSearch": MessageLookupByLibrary.simpleMessage("Tìm kiếm vi diệu"), "magicSearchHint": MessageLookupByLibrary.simpleMessage( - "Tìm kiếm ma thuật cho phép tìm kiếm ảnh theo nội dung của chúng, ví dụ: \'hoa\', \'xe hơi đỏ\', \'tài liệu nhận dạng\'"), + "Tìm kiếm vi diệu cho phép tìm ảnh theo nội dung của chúng, ví dụ: \'xe hơi\', \'xe hơi đỏ\', \'Ferrari\'"), "manage": MessageLookupByLibrary.simpleMessage("Quản lý"), "manageDeviceStorage": MessageLookupByLibrary.simpleMessage( "Quản lý bộ nhớ đệm của thiết bị"), "manageDeviceStorageDesc": MessageLookupByLibrary.simpleMessage( - "Review and clear local cache storage."), + "Xem và xóa bộ nhớ đệm trên thiết bị."), "manageFamily": MessageLookupByLibrary.simpleMessage("Quản lý gia đình"), "manageLink": MessageLookupByLibrary.simpleMessage("Quản lý liên kết"), "manageParticipants": MessageLookupByLibrary.simpleMessage("Quản lý"), "manageSubscription": - MessageLookupByLibrary.simpleMessage("Quản lý đăng ký"), + MessageLookupByLibrary.simpleMessage("Quản lý gói"), "manualPairDesc": MessageLookupByLibrary.simpleMessage( "Ghép nối với PIN hoạt động với bất kỳ màn hình nào bạn muốn xem album của mình."), - "map": MessageLookupByLibrary.simpleMessage("Map"), + "map": MessageLookupByLibrary.simpleMessage("Bản đồ"), "maps": MessageLookupByLibrary.simpleMessage("Bản đồ"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), + "me": MessageLookupByLibrary.simpleMessage("Tôi"), + "memories": MessageLookupByLibrary.simpleMessage("Kỷ niệm"), + "memoriesWidgetDesc": MessageLookupByLibrary.simpleMessage( + "Chọn những loại kỷ niệm bạn muốn thấy trên màn hình chính của mình."), + "memoryCount": m50, + "merchandise": MessageLookupByLibrary.simpleMessage("Vật phẩm"), + "merge": MessageLookupByLibrary.simpleMessage("Hợp nhất"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("Hợp nhất với người đã có"), "mergedPhotos": MessageLookupByLibrary.simpleMessage("Hợp nhất ảnh"), - "mlConsent": MessageLookupByLibrary.simpleMessage("Kích hoạt học máy"), + "mlConsent": MessageLookupByLibrary.simpleMessage("Bật học máy"), "mlConsentConfirmation": MessageLookupByLibrary.simpleMessage( - "Tôi hiểu và muốn kích hoạt học máy"), + "Tôi hiểu và muốn bật học máy"), "mlConsentDescription": MessageLookupByLibrary.simpleMessage( - "Nếu bạn kích hoạt học máy, Ente sẽ trích xuất thông tin như hình dạng khuôn mặt từ các tệp, bao gồm cả những tệp được chia sẻ với bạn.\n\nĐiều này sẽ xảy ra trên thiết bị của bạn, và bất kỳ thông tin sinh trắc học nào được tạo ra sẽ được mã hóa đầu cuối."), + "Nếu bạn bật học máy, Ente sẽ trích xuất thông tin như hình dạng khuôn mặt từ các tệp, gồm cả những tệp mà bạn được chia sẻ.\n\nViệc này sẽ diễn ra trên thiết bị của bạn, với mọi thông tin sinh trắc học tạo ra đều được mã hóa đầu cuối."), "mlConsentPrivacy": MessageLookupByLibrary.simpleMessage( - "Vui lòng nhấp vào đây để biết thêm chi tiết về tính năng này trong chính sách quyền riêng tư của chúng tôi"), - "mlConsentTitle": - MessageLookupByLibrary.simpleMessage("Kích hoạt học máy?"), + "Vui lòng nhấn vào đây để biết thêm chi tiết về tính năng này trong chính sách quyền riêng tư của chúng tôi"), + "mlConsentTitle": MessageLookupByLibrary.simpleMessage("Bật học máy?"), "mlIndexingDescription": MessageLookupByLibrary.simpleMessage( - "Xin lưu ý rằng việc học máy sẽ dẫn đến việc sử dụng băng thông và pin cao hơn cho đến khi tất cả các mục được lập chỉ mục. Hãy xem xét việc sử dụng ứng dụng máy tính để bàn để lập chỉ mục nhanh hơn, tất cả kết quả sẽ được đồng bộ hóa tự động."), + "Lưu ý rằng việc học máy sẽ khiến tốn băng thông và pin nhiều hơn cho đến khi tất cả mục được lập chỉ mục. Hãy sử dụng ứng dụng máy tính để lập chỉ mục nhanh hơn. Mọi kết quả sẽ được tự động đồng bộ."), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("Di động, Web, Desktop"), - "moderateStrength": MessageLookupByLibrary.simpleMessage("Vừa phải"), + "moderateStrength": MessageLookupByLibrary.simpleMessage("Trung bình"), "modifyYourQueryOrTrySearchingFor": MessageLookupByLibrary.simpleMessage( - "Chỉnh sửa truy vấn của bạn, hoặc thử tìm kiếm cho"), + "Chỉnh sửa truy vấn của bạn, hoặc thử tìm kiếm"), "moments": MessageLookupByLibrary.simpleMessage("Khoảnh khắc"), "month": MessageLookupByLibrary.simpleMessage("tháng"), - "monthly": MessageLookupByLibrary.simpleMessage("Hàng tháng"), + "monthly": MessageLookupByLibrary.simpleMessage("Theo tháng"), + "moon": MessageLookupByLibrary.simpleMessage("Ánh trăng"), "moreDetails": MessageLookupByLibrary.simpleMessage("Thêm chi tiết"), "mostRecent": MessageLookupByLibrary.simpleMessage("Mới nhất"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Liên quan nhất"), + "mountains": MessageLookupByLibrary.simpleMessage("Đồi núi"), + "moveItem": m51, + "moveSelectedPhotosToOneDate": MessageLookupByLibrary.simpleMessage( + "Di chuyển ảnh đã chọn đến một ngày"), "moveToAlbum": MessageLookupByLibrary.simpleMessage("Chuyển đến album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Di chuyển đến album ẩn"), "movedSuccessfullyTo": m52, "movedToTrash": - MessageLookupByLibrary.simpleMessage("Đã chuyển vào thùng rác"), + MessageLookupByLibrary.simpleMessage("Đã cho vào thùng rác"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( "Đang di chuyển tệp vào album..."), "name": MessageLookupByLibrary.simpleMessage("Tên"), @@ -1187,21 +1389,25 @@ class MessageLookup extends MessageLookupByLibrary { "newAlbum": MessageLookupByLibrary.simpleMessage("Album mới"), "newLocation": MessageLookupByLibrary.simpleMessage("Vị trí mới"), "newPerson": MessageLookupByLibrary.simpleMessage("Người mới"), - "newToEnte": MessageLookupByLibrary.simpleMessage("Mới đến Ente"), + "newPhotosEmoji": MessageLookupByLibrary.simpleMessage(" mới 📸"), + "newRange": MessageLookupByLibrary.simpleMessage("Phạm vi mới"), + "newToEnte": MessageLookupByLibrary.simpleMessage("Mới dùng Ente"), "newest": MessageLookupByLibrary.simpleMessage("Mới nhất"), "next": MessageLookupByLibrary.simpleMessage("Tiếp theo"), "no": MessageLookupByLibrary.simpleMessage("Không"), - "noAlbumsSharedByYouYet": MessageLookupByLibrary.simpleMessage( - "Chưa có album nào được chia sẻ bởi bạn"), + "noAlbumsSharedByYouYet": + MessageLookupByLibrary.simpleMessage("Bạn chưa chia sẻ album nào"), "noDeviceFound": MessageLookupByLibrary.simpleMessage("Không tìm thấy thiết bị"), "noDeviceLimit": MessageLookupByLibrary.simpleMessage("Không có"), "noDeviceThatCanBeDeleted": MessageLookupByLibrary.simpleMessage( - "Bạn không có tệp nào trên thiết bị này có thể bị xóa"), + "Bạn không có tệp nào có thể xóa trên thiết bị này"), "noDuplicates": MessageLookupByLibrary.simpleMessage("✨ Không có trùng lặp"), + "noEnteAccountExclamation": + MessageLookupByLibrary.simpleMessage("Chưa có tài khoản Ente!"), "noExifData": - MessageLookupByLibrary.simpleMessage("Không có dữ liệu EXIF"), + MessageLookupByLibrary.simpleMessage("Không có thông số Exif"), "noFacesFound": MessageLookupByLibrary.simpleMessage("Không tìm thấy khuôn mặt"), "noHiddenPhotosOrVideos": @@ -1218,9 +1424,9 @@ class MessageLookup extends MessageLookupByLibrary { "noQuickLinksSelected": MessageLookupByLibrary.simpleMessage( "Không có liên kết nhanh nào được chọn"), "noRecoveryKey": - MessageLookupByLibrary.simpleMessage("Không có khóa khôi phục?"), + MessageLookupByLibrary.simpleMessage("Không có mã khôi phục?"), "noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage( - "Do tính chất của giao thức mã hóa đầu cuối của chúng tôi, dữ liệu của bạn không thể được giải mã mà không có mật khẩu hoặc khóa khôi phục của bạn"), + "Do tính chất của giao thức mã hóa đầu cuối, không thể giải mã dữ liệu của bạn mà không có mật khẩu hoặc mã khôi phục"), "noResults": MessageLookupByLibrary.simpleMessage("Không có kết quả"), "noResultsFound": MessageLookupByLibrary.simpleMessage("Không tìm thấy kết quả"), @@ -1228,22 +1434,31 @@ class MessageLookup extends MessageLookupByLibrary { "noSystemLockFound": MessageLookupByLibrary.simpleMessage( "Không tìm thấy khóa hệ thống"), "notPersonLabel": m54, - "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage( - "Chưa có gì được chia sẻ với bạn"), + "notThisPerson": + MessageLookupByLibrary.simpleMessage("Không phải người này?"), + "nothingSharedWithYouYet": + MessageLookupByLibrary.simpleMessage("Bạn chưa được chia sẻ gì"), "nothingToSeeHere": MessageLookupByLibrary.simpleMessage( - "Không có gì để xem ở đây! 👀"), + "Ở đây không có gì để xem! 👀"), "notifications": MessageLookupByLibrary.simpleMessage("Thông báo"), "ok": MessageLookupByLibrary.simpleMessage("Được"), "onDevice": MessageLookupByLibrary.simpleMessage("Trên thiết bị"), "onEnte": MessageLookupByLibrary.simpleMessage( "Trên ente"), + "onTheRoad": MessageLookupByLibrary.simpleMessage("Trên đường"), + "onThisDay": MessageLookupByLibrary.simpleMessage("Vào ngày này"), + "onThisDayMemories": + MessageLookupByLibrary.simpleMessage("Kỷ niệm hôm nay"), + "onThisDayNotificationExplanation": + MessageLookupByLibrary.simpleMessage( + "Nhắc về những kỷ niệm ngày này trong những năm trước."), "onlyFamilyAdminCanChangeCode": m55, "onlyThem": MessageLookupByLibrary.simpleMessage("Chỉ họ"), - "oops": MessageLookupByLibrary.simpleMessage("Ôi"), - "oopsCouldNotSaveEdits": - MessageLookupByLibrary.simpleMessage("Ôi, không thể lưu chỉnh sửa"), + "oops": MessageLookupByLibrary.simpleMessage("Ốiii!"), + "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( + "Ốiii, không thể lưu chỉnh sửa"), "oopsSomethingWentWrong": MessageLookupByLibrary.simpleMessage( - "Ôi, có điều gì đó không đúng"), + "Ốiii!, có điều gì đó không đúng"), "openAlbumInBrowser": MessageLookupByLibrary.simpleMessage("Mở album trong trình duyệt"), "openAlbumInBrowserTitle": MessageLookupByLibrary.simpleMessage( @@ -1251,24 +1466,29 @@ class MessageLookup extends MessageLookupByLibrary { "openFile": MessageLookupByLibrary.simpleMessage("Mở tệp"), "openSettings": MessageLookupByLibrary.simpleMessage("Mở Cài đặt"), "openTheItem": MessageLookupByLibrary.simpleMessage("• Mở mục"), - "openstreetmapContributors": - MessageLookupByLibrary.simpleMessage("Nhà đóng góp OpenStreetMap"), - "optionalAsShortAsYouLike": MessageLookupByLibrary.simpleMessage( - "Tùy chọn, ngắn như bạn muốn..."), + "openstreetmapContributors": MessageLookupByLibrary.simpleMessage( + "Người đóng góp OpenStreetMap"), + "optionalAsShortAsYouLike": + MessageLookupByLibrary.simpleMessage("Tùy chọn, ngắn dài tùy ý..."), "orMergeWithExistingPerson": MessageLookupByLibrary.simpleMessage("Hoặc hợp nhất với hiện có"), "orPickAnExistingOne": MessageLookupByLibrary.simpleMessage("Hoặc chọn một cái có sẵn"), + "orPickFromYourContacts": + MessageLookupByLibrary.simpleMessage("hoặc chọn từ danh bạ"), + "otherDetectedFaces": MessageLookupByLibrary.simpleMessage( + "Những khuôn mặt khác được phát hiện"), "pair": MessageLookupByLibrary.simpleMessage("Ghép nối"), "pairWithPin": MessageLookupByLibrary.simpleMessage("Ghép nối với PIN"), "pairingComplete": MessageLookupByLibrary.simpleMessage("Ghép nối hoàn tất"), - "panorama": MessageLookupByLibrary.simpleMessage("Toàn cảnh"), + "panorama": MessageLookupByLibrary.simpleMessage("Panorama"), + "partyWithThem": m56, "passKeyPendingVerification": MessageLookupByLibrary.simpleMessage("Xác minh vẫn đang chờ"), - "passkey": MessageLookupByLibrary.simpleMessage("Mã khóa"), + "passkey": MessageLookupByLibrary.simpleMessage("Khóa truy cập"), "passkeyAuthTitle": - MessageLookupByLibrary.simpleMessage("Xác minh mã khóa"), + MessageLookupByLibrary.simpleMessage("Xác minh khóa truy cập"), "password": MessageLookupByLibrary.simpleMessage("Mật khẩu"), "passwordChangedSuccessfully": MessageLookupByLibrary.simpleMessage( "Đã thay đổi mật khẩu thành công"), @@ -1278,13 +1498,15 @@ class MessageLookup extends MessageLookupByLibrary { "passwordStrengthInfo": MessageLookupByLibrary.simpleMessage( "Độ mạnh của mật khẩu được tính toán dựa trên độ dài của mật khẩu, các ký tự đã sử dụng và liệu mật khẩu có xuất hiện trong 10.000 mật khẩu được sử dụng nhiều nhất hay không"), "passwordWarning": MessageLookupByLibrary.simpleMessage( - "Chúng tôi không lưu trữ mật khẩu này, vì vậy nếu bạn quên, chúng tôi không thể giải mã dữ liệu của bạn"), + "Chúng tôi không lưu trữ mật khẩu này, nên nếu bạn quên, chúng tôi không thể giải mã dữ liệu của bạn"), + "pastYearsMemories": + MessageLookupByLibrary.simpleMessage("Kỷ niệm năm ngoái"), "paymentDetails": MessageLookupByLibrary.simpleMessage("Chi tiết thanh toán"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Thanh toán thất bại"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( - "Rất tiếc, thanh toán của bạn đã thất bại. Vui lòng liên hệ với bộ phận hỗ trợ và chúng tôi sẽ giúp bạn!"), + "Rất tiếc, bạn đã thanh toán không thành công. Vui lòng liên hệ hỗ trợ và chúng tôi sẽ giúp bạn!"), "paymentFailedTalkToProvider": m58, "pendingItems": MessageLookupByLibrary.simpleMessage("Các mục đang chờ"), @@ -1293,38 +1515,50 @@ class MessageLookup extends MessageLookupByLibrary { "people": MessageLookupByLibrary.simpleMessage("Người"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage("Người dùng mã của bạn"), + "peopleWidgetDesc": MessageLookupByLibrary.simpleMessage( + "Chọn những người bạn muốn thấy trên màn hình chính của mình."), "permDeleteWarning": MessageLookupByLibrary.simpleMessage( - "Tất cả các mục trong thùng rác sẽ bị xóa vĩnh viễn\n\nHành động này không thể hoàn tác"), + "Tất cả các mục trong thùng rác sẽ bị xóa vĩnh viễn\n\nKhông thể hoàn tác thao tác này"), "permanentlyDelete": MessageLookupByLibrary.simpleMessage("Xóa vĩnh viễn"), "permanentlyDeleteFromDevice": MessageLookupByLibrary.simpleMessage( "Xóa vĩnh viễn khỏi thiết bị?"), + "personIsAge": m59, "personName": MessageLookupByLibrary.simpleMessage("Tên người"), + "personTurningAge": m60, + "pets": MessageLookupByLibrary.simpleMessage("Thú cưng"), "photoDescriptions": MessageLookupByLibrary.simpleMessage("Mô tả ảnh"), "photoGridSize": MessageLookupByLibrary.simpleMessage("Kích thước lưới ảnh"), "photoSmallCase": MessageLookupByLibrary.simpleMessage("ảnh"), + "photocountPhotos": m61, "photos": MessageLookupByLibrary.simpleMessage("Ảnh"), "photosAddedByYouWillBeRemovedFromTheAlbum": MessageLookupByLibrary.simpleMessage( "Ảnh bạn đã thêm sẽ bị xóa khỏi album"), + "photosCount": m62, + "photosKeepRelativeTimeDifference": + MessageLookupByLibrary.simpleMessage( + "Ảnh giữ nguyên chênh lệch thời gian tương đối"), "pickCenterPoint": MessageLookupByLibrary.simpleMessage("Chọn điểm trung tâm"), "pinAlbum": MessageLookupByLibrary.simpleMessage("Ghim album"), "pinLock": MessageLookupByLibrary.simpleMessage("Khóa PIN"), "playOnTv": MessageLookupByLibrary.simpleMessage("Phát album trên TV"), + "playOriginal": MessageLookupByLibrary.simpleMessage("Phát tệp gốc"), "playStoreFreeTrialValidTill": m63, + "playStream": MessageLookupByLibrary.simpleMessage("Phát"), "playstoreSubscription": - MessageLookupByLibrary.simpleMessage("Đăng ký PlayStore"), + MessageLookupByLibrary.simpleMessage("Gói PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": MessageLookupByLibrary.simpleMessage( "Vui lòng kiểm tra kết nối internet của bạn và thử lại."), "pleaseContactSupportAndWeWillBeHappyToHelp": MessageLookupByLibrary.simpleMessage( - "Vui lòng liên hệ với support@ente.io và chúng tôi sẽ rất vui lòng giúp đỡ!"), + "Vui lòng liên hệ support@ente.io và chúng tôi rất sẵn sàng giúp đỡ!"), "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( - "Vui lòng liên hệ với bộ phận hỗ trợ nếu vấn đề vẫn tiếp diễn"), + "Vui lòng liên hệ bộ phận hỗ trợ nếu vấn đề vẫn tiếp diễn"), "pleaseEmailUsAt": m64, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Vui lòng cấp quyền"), @@ -1343,16 +1577,20 @@ class MessageLookup extends MessageLookupByLibrary { "Vui lòng chờ, đang xóa album"), "pleaseWaitForSometimeBeforeRetrying": MessageLookupByLibrary.simpleMessage( - "Vui lòng chờ một thời gian trước khi thử lại"), + "Vui lòng chờ một chút trước khi thử lại"), + "pleaseWaitThisWillTakeAWhile": MessageLookupByLibrary.simpleMessage( + "Vui lòng chờ, có thể mất một lúc."), + "posingWithThem": m66, "preparingLogs": - MessageLookupByLibrary.simpleMessage("Đang chuẩn bị nhật ký..."), + MessageLookupByLibrary.simpleMessage("Đang ghi log..."), "preserveMore": MessageLookupByLibrary.simpleMessage("Lưu giữ nhiều hơn"), "pressAndHoldToPlayVideo": - MessageLookupByLibrary.simpleMessage("Nhấn và giữ để phát video"), - "pressAndHoldToPlayVideoDetailed": MessageLookupByLibrary.simpleMessage( - "Nhấn và giữ vào hình ảnh để phát video"), - "privacy": MessageLookupByLibrary.simpleMessage("Quyền riêng tư"), + MessageLookupByLibrary.simpleMessage("Nhấn giữ để phát video"), + "pressAndHoldToPlayVideoDetailed": + MessageLookupByLibrary.simpleMessage("Nhấn giữ ảnh để phát video"), + "previous": MessageLookupByLibrary.simpleMessage("Trước"), + "privacy": MessageLookupByLibrary.simpleMessage("Bảo mật"), "privacyPolicyTitle": MessageLookupByLibrary.simpleMessage("Chính sách bảo mật"), "privateBackups": @@ -1361,17 +1599,29 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Chia sẻ riêng tư"), "proceed": MessageLookupByLibrary.simpleMessage("Tiếp tục"), "processed": MessageLookupByLibrary.simpleMessage("Đã xử lý"), + "processing": MessageLookupByLibrary.simpleMessage("Đang xử lý"), "processingImport": m67, + "processingVideos": + MessageLookupByLibrary.simpleMessage("Đang xử lý video"), "publicLinkCreated": MessageLookupByLibrary.simpleMessage( "Liên kết công khai đã được tạo"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage( - "Liên kết công khai đã được kích hoạt"), + "Liên kết công khai đã được bật"), + "questionmark": MessageLookupByLibrary.simpleMessage("?"), + "queued": MessageLookupByLibrary.simpleMessage("Đang chờ"), "quickLinks": MessageLookupByLibrary.simpleMessage("Liên kết nhanh"), "radius": MessageLookupByLibrary.simpleMessage("Bán kính"), - "raiseTicket": MessageLookupByLibrary.simpleMessage("Tạo vé"), + "raiseTicket": MessageLookupByLibrary.simpleMessage("Yêu cầu hỗ trợ"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Đánh giá ứng dụng"), "rateUs": MessageLookupByLibrary.simpleMessage("Đánh giá chúng tôi"), "rateUsOnStore": m68, + "reassignMe": + MessageLookupByLibrary.simpleMessage("Chỉ định lại \"Tôi\""), + "reassignedToName": m69, + "reassigningLoading": + MessageLookupByLibrary.simpleMessage("Đang chỉ định lại..."), + "receiveRemindersOnBirthdays": MessageLookupByLibrary.simpleMessage( + "Nhắc khi đến sinh nhật của ai đó. Chạm vào thông báo sẽ đưa bạn đến ảnh của người sinh nhật."), "recover": MessageLookupByLibrary.simpleMessage("Khôi phục"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Khôi phục tài khoản"), @@ -1381,19 +1631,19 @@ class MessageLookup extends MessageLookupByLibrary { "recoveryInitiated": MessageLookupByLibrary.simpleMessage( "Quá trình khôi phục đã được khởi động"), "recoveryInitiatedDesc": m70, - "recoveryKey": MessageLookupByLibrary.simpleMessage("Khóa khôi phục"), + "recoveryKey": MessageLookupByLibrary.simpleMessage("Mã khôi phục"), "recoveryKeyCopiedToClipboard": MessageLookupByLibrary.simpleMessage( - "Khóa khôi phục đã được sao chép vào clipboard"), + "Đã sao chép mã khôi phục vào bộ nhớ tạm"), "recoveryKeyOnForgotPassword": MessageLookupByLibrary.simpleMessage( - "Nếu bạn quên mật khẩu, cách duy nhất để khôi phục dữ liệu của bạn là với khóa này."), + "Nếu bạn quên mật khẩu, cách duy nhất để khôi phục dữ liệu của bạn là dùng mã này."), "recoveryKeySaveDescription": MessageLookupByLibrary.simpleMessage( - "Chúng tôi không lưu trữ khóa này, vui lòng lưu khóa 24 từ này ở một nơi an toàn."), + "Chúng tôi không lưu trữ mã này, nên hãy lưu nó ở một nơi an toàn."), "recoveryKeySuccessBody": MessageLookupByLibrary.simpleMessage( - "Tuyệt vời! Khóa khôi phục của bạn hợp lệ. Cảm ơn bạn đã xác minh.\n\nVui lòng nhớ giữ khóa khôi phục của bạn được sao lưu an toàn."), + "Tuyệt! Mã khôi phục của bạn hợp lệ. Cảm ơn đã xác minh.\n\nNhớ lưu giữ mã khôi phục của bạn ở nơi an toàn."), "recoveryKeyVerified": MessageLookupByLibrary.simpleMessage( - "Khóa khôi phục đã được xác minh"), + "Mã khôi phục đã được xác minh"), "recoveryKeyVerifyReason": MessageLookupByLibrary.simpleMessage( - "Khóa khôi phục của bạn là cách duy nhất để khôi phục ảnh của bạn nếu bạn quên mật khẩu. Bạn có thể tìm thấy khóa khôi phục của mình trong Cài đặt > Tài khoản.\n\nVui lòng nhập khóa khôi phục của bạn ở đây để xác minh rằng bạn đã lưu nó đúng cách."), + "Mã khôi phục là cách duy nhất để khôi phục ảnh của bạn nếu bạn quên mật khẩu. Bạn có thể xem mã khôi phục của mình trong Cài đặt > Tài khoản.\n\nVui lòng nhập mã khôi phục của bạn ở đây để xác minh rằng bạn đã lưu nó đúng cách."), "recoveryReady": m71, "recoverySuccessful": MessageLookupByLibrary.simpleMessage("Khôi phục thành công!"), @@ -1401,7 +1651,7 @@ class MessageLookup extends MessageLookupByLibrary { "Một liên hệ tin cậy đang cố gắng truy cập tài khoản của bạn"), "recoveryWarningBody": m72, "recreatePasswordBody": MessageLookupByLibrary.simpleMessage( - "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn, nhưng chúng tôi có thể tạo lại theo cách hoạt động với tất cả các thiết bị.\n\nVui lòng đăng nhập bằng khóa khôi phục của bạn và tạo lại mật khẩu (bạn có thể sử dụng lại mật khẩu cũ nếu muốn)."), + "Thiết bị hiện tại không đủ mạnh để xác minh mật khẩu của bạn, nhưng chúng tôi có thể tạo lại để nó hoạt động với tất cả thiết bị.\n\nVui lòng đăng nhập bằng mã khôi phục và tạo lại mật khẩu (bạn có thể dùng lại mật khẩu cũ nếu muốn)."), "recreatePasswordTitle": MessageLookupByLibrary.simpleMessage("Tạo lại mật khẩu"), "reddit": MessageLookupByLibrary.simpleMessage("Reddit"), @@ -1409,7 +1659,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nhập lại mật khẩu"), "reenterPin": MessageLookupByLibrary.simpleMessage("Nhập lại PIN"), "referFriendsAnd2xYourPlan": MessageLookupByLibrary.simpleMessage( - "Giới thiệu bạn bè và gấp đôi gói của bạn"), + "Giới thiệu bạn bè và ×2 gói của bạn"), "referralStep1": MessageLookupByLibrary.simpleMessage( "1. Đưa mã này cho bạn bè của bạn"), "referralStep2": @@ -1421,24 +1671,25 @@ class MessageLookup extends MessageLookupByLibrary { "rejectRecovery": MessageLookupByLibrary.simpleMessage("Từ chối khôi phục"), "remindToEmptyDeviceTrash": MessageLookupByLibrary.simpleMessage( - "Cũng hãy xóa \"Đã xóa gần đây\" từ \"Cài đặt\" -> \"Lưu trữ\" để chiếm không gian đã giải phóng"), + "Hãy xóa luôn \"Đã xóa gần đây\" từ \"Cài đặt\" -> \"Lưu trữ\" để lấy lại dung lượng đã giải phóng"), "remindToEmptyEnteTrash": MessageLookupByLibrary.simpleMessage( - "Cũng hãy xóa \"Thùng rác\" của bạn để chiếm không gian đã giải phóng"), - "remoteImages": MessageLookupByLibrary.simpleMessage("Hình ảnh từ xa"), + "Hãy xóa luôn \"Thùng rác\" của bạn để lấy lại dung lượng đã giải phóng"), + "remoteImages": + MessageLookupByLibrary.simpleMessage("Hình ảnh bên ngoài"), "remoteThumbnails": - MessageLookupByLibrary.simpleMessage("Hình thu nhỏ từ xa"), - "remoteVideos": MessageLookupByLibrary.simpleMessage("Video từ xa"), + MessageLookupByLibrary.simpleMessage("Hình thu nhỏ bên ngoài"), + "remoteVideos": MessageLookupByLibrary.simpleMessage("Video bên ngoài"), "remove": MessageLookupByLibrary.simpleMessage("Xóa"), "removeDuplicates": MessageLookupByLibrary.simpleMessage("Xóa trùng lặp"), "removeDuplicatesDesc": MessageLookupByLibrary.simpleMessage( - "Xem xét và xóa các tệp là bản sao chính xác."), + "Xem và xóa các tệp bị trùng lặp."), "removeFromAlbum": MessageLookupByLibrary.simpleMessage("Xóa khỏi album"), "removeFromAlbumTitle": MessageLookupByLibrary.simpleMessage("Xóa khỏi album?"), "removeFromFavorite": - MessageLookupByLibrary.simpleMessage("Xóa khỏi yêu thích"), + MessageLookupByLibrary.simpleMessage("Xóa khỏi mục đã thích"), "removeInvite": MessageLookupByLibrary.simpleMessage("Gỡ bỏ lời mời"), "removeLink": MessageLookupByLibrary.simpleMessage("Xóa liên kết"), "removeParticipant": @@ -1451,7 +1702,7 @@ class MessageLookup extends MessageLookupByLibrary { "removePublicLinks": MessageLookupByLibrary.simpleMessage("Xóa liên kết công khai"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( - "Một số mục bạn đang xóa đã được thêm bởi người khác, và bạn sẽ mất quyền truy cập vào chúng"), + "Vài mục mà bạn đang xóa được thêm bởi người khác, và bạn sẽ mất quyền truy cập vào chúng"), "removeWithQuestionMark": MessageLookupByLibrary.simpleMessage("Xóa?"), "removeYourselfAsTrustedContact": MessageLookupByLibrary.simpleMessage( "Gỡ bỏ bạn khỏi liên hệ tin cậy"), @@ -1461,81 +1712,88 @@ class MessageLookup extends MessageLookupByLibrary { "renameAlbum": MessageLookupByLibrary.simpleMessage("Đổi tên album"), "renameFile": MessageLookupByLibrary.simpleMessage("Đổi tên tệp"), "renewSubscription": - MessageLookupByLibrary.simpleMessage("Gia hạn đăng ký"), + MessageLookupByLibrary.simpleMessage("Gia hạn gói"), "renewsOn": m75, - "reportABug": MessageLookupByLibrary.simpleMessage("Báo cáo lỗi"), - "reportBug": MessageLookupByLibrary.simpleMessage("Báo cáo lỗi"), + "reportABug": MessageLookupByLibrary.simpleMessage("Báo lỗi"), + "reportBug": MessageLookupByLibrary.simpleMessage("Báo lỗi"), "resendEmail": MessageLookupByLibrary.simpleMessage("Gửi lại email"), + "reset": MessageLookupByLibrary.simpleMessage("Đặt lại"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage("Đặt lại các tệp bị bỏ qua"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Đặt lại mật khẩu"), - "resetPerson": MessageLookupByLibrary.simpleMessage("Đặt lại người"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Xóa"), "resetToDefault": - MessageLookupByLibrary.simpleMessage("Đặt lại về mặc định"), + MessageLookupByLibrary.simpleMessage("Đặt lại mặc định"), "restore": MessageLookupByLibrary.simpleMessage("Khôi phục"), "restoreToAlbum": MessageLookupByLibrary.simpleMessage("Khôi phục vào album"), "restoringFiles": MessageLookupByLibrary.simpleMessage("Đang khôi phục tệp..."), "resumableUploads": - MessageLookupByLibrary.simpleMessage("Tải lên có thể tiếp tục"), + MessageLookupByLibrary.simpleMessage("Cho phép tải lên tiếp tục"), "retry": MessageLookupByLibrary.simpleMessage("Thử lại"), "review": MessageLookupByLibrary.simpleMessage("Xem lại"), "reviewDeduplicateItems": MessageLookupByLibrary.simpleMessage( - "Vui lòng xem xét và xóa các mục mà bạn cho là trùng lặp."), - "reviewSuggestions": - MessageLookupByLibrary.simpleMessage("Xem xét gợi ý"), + "Vui lòng xem qua và xóa các mục mà bạn tin là trùng lặp."), + "reviewSuggestions": MessageLookupByLibrary.simpleMessage("Xem gợi ý"), "right": MessageLookupByLibrary.simpleMessage("Phải"), + "roadtripWithThem": m76, "rotate": MessageLookupByLibrary.simpleMessage("Xoay"), "rotateLeft": MessageLookupByLibrary.simpleMessage("Xoay trái"), "rotateRight": MessageLookupByLibrary.simpleMessage("Xoay phải"), "safelyStored": MessageLookupByLibrary.simpleMessage("Lưu trữ an toàn"), + "same": MessageLookupByLibrary.simpleMessage("Chính xác"), + "sameperson": MessageLookupByLibrary.simpleMessage("Cùng một người?"), "save": MessageLookupByLibrary.simpleMessage("Lưu"), + "saveAsAnotherPerson": + MessageLookupByLibrary.simpleMessage("Lưu như một người khác"), + "saveChangesBeforeLeavingQuestion": + MessageLookupByLibrary.simpleMessage("Lưu thay đổi trước khi rời?"), "saveCollage": MessageLookupByLibrary.simpleMessage("Lưu ảnh ghép"), "saveCopy": MessageLookupByLibrary.simpleMessage("Lưu bản sao"), - "saveKey": MessageLookupByLibrary.simpleMessage("Lưu khóa"), + "saveKey": MessageLookupByLibrary.simpleMessage("Lưu mã"), "savePerson": MessageLookupByLibrary.simpleMessage("Lưu người"), "saveYourRecoveryKeyIfYouHaventAlready": MessageLookupByLibrary.simpleMessage( - "Lưu khóa khôi phục của bạn nếu bạn chưa làm"), + "Lưu mã khôi phục của bạn nếu bạn chưa làm"), "saving": MessageLookupByLibrary.simpleMessage("Đang lưu..."), "savingEdits": MessageLookupByLibrary.simpleMessage("Đang lưu chỉnh sửa..."), "scanCode": MessageLookupByLibrary.simpleMessage("Quét mã"), "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( - "Quét mã vạch này bằng\ntới ứng dụng xác thực của bạn"), + "Quét mã vạch này bằng\nứng dụng xác thực của bạn"), "search": MessageLookupByLibrary.simpleMessage("Tìm kiếm"), "searchAlbumsEmptySection": MessageLookupByLibrary.simpleMessage("Album"), "searchByAlbumNameHint": MessageLookupByLibrary.simpleMessage("Tên album"), "searchByExamples": MessageLookupByLibrary.simpleMessage( - "• Tên album (ví dụ: \"Camera\")\n• Loại tệp (ví dụ: \"Video\", \".gif\")\n• Năm và tháng (ví dụ: \"2022\", \"Tháng Một\")\n• Ngày lễ (ví dụ: \"Giáng Sinh\")\n• Mô tả ảnh (ví dụ: “#vui”)"), + "• Tên album (vd: \"Camera\")\n• Loại tệp (vd: \"Video\", \".gif\")\n• Năm và tháng (vd: \"2022\", \"Tháng Một\")\n• Ngày lễ (vd: \"Giáng Sinh\")\n• Mô tả ảnh (vd: “#vui”)"), "searchCaptionEmptySection": MessageLookupByLibrary.simpleMessage( - "Thêm mô tả như \"#chuyến đi\" trong thông tin ảnh để nhanh chóng tìm thấy chúng ở đây"), + "Thêm mô tả như \"#phượt\" trong thông tin ảnh để tìm nhanh thấy chúng ở đây"), "searchDatesEmptySection": MessageLookupByLibrary.simpleMessage( "Tìm kiếm theo ngày, tháng hoặc năm"), "searchDiscoverEmptySection": MessageLookupByLibrary.simpleMessage( "Hình ảnh sẽ được hiển thị ở đây sau khi hoàn tất xử lý và đồng bộ"), "searchFaceEmptySection": MessageLookupByLibrary.simpleMessage( - "Người sẽ được hiển thị ở đây khi việc lập chỉ mục hoàn tất"), + "Người sẽ được hiển thị ở đây khi quá trình xử lý hoàn tất"), "searchFileTypesAndNamesEmptySection": MessageLookupByLibrary.simpleMessage("Loại tệp và tên"), "searchHint1": MessageLookupByLibrary.simpleMessage( "Tìm kiếm nhanh, trên thiết bị"), "searchHint2": - MessageLookupByLibrary.simpleMessage("Ngày tháng, mô tả ảnh"), + MessageLookupByLibrary.simpleMessage("Ngày chụp, mô tả ảnh"), "searchHint3": MessageLookupByLibrary.simpleMessage("Album, tên tệp và loại"), "searchHint4": MessageLookupByLibrary.simpleMessage("Vị trí"), "searchHint5": MessageLookupByLibrary.simpleMessage( - "Sắp có: Nhận diện khuôn mặt & tìm kiếm ma thuật ✨"), + "Sắp ra mắt: Nhận diện khuôn mặt & tìm kiếm vi diệu ✨"), "searchLocationEmptySection": MessageLookupByLibrary.simpleMessage( - "Nhóm ảnh được chụp trong một bán kính nào đó của một bức ảnh"), + "Ảnh nhóm được chụp trong một bán kính nào đó của một bức ảnh"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( - "Mời mọi người, và bạn sẽ thấy tất cả ảnh được chia sẻ bởi họ ở đây"), + "Mời mọi người, và bạn sẽ thấy tất cả ảnh mà họ chia sẻ ở đây"), "searchPersonsEmptySection": MessageLookupByLibrary.simpleMessage( "Người sẽ được hiển thị ở đây sau khi hoàn tất xử lý và đồng bộ"), "searchResultCount": m77, @@ -1552,6 +1810,7 @@ class MessageLookup extends MessageLookupByLibrary { "selectAllShort": MessageLookupByLibrary.simpleMessage("Tất cả"), "selectCoverPhoto": MessageLookupByLibrary.simpleMessage("Chọn ảnh bìa"), + "selectDate": MessageLookupByLibrary.simpleMessage("Chọn ngày"), "selectFoldersForBackup": MessageLookupByLibrary.simpleMessage("Chọn thư mục để sao lưu"), "selectItemsToAdd": @@ -1561,9 +1820,21 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Chọn ứng dụng email"), "selectMorePhotos": MessageLookupByLibrary.simpleMessage("Chọn thêm ảnh"), + "selectOneDateAndTime": + MessageLookupByLibrary.simpleMessage("Chọn một ngày và giờ"), + "selectOneDateAndTimeForAll": MessageLookupByLibrary.simpleMessage( + "Chọn một ngày và giờ cho tất cả"), + "selectPersonToLink": + MessageLookupByLibrary.simpleMessage("Chọn người để liên kết"), "selectReason": MessageLookupByLibrary.simpleMessage("Chọn lý do"), + "selectStartOfRange": + MessageLookupByLibrary.simpleMessage("Chọn phạm vi bắt đầu"), + "selectTime": MessageLookupByLibrary.simpleMessage("Chọn thời gian"), + "selectYourFace": + MessageLookupByLibrary.simpleMessage("Chọn khuôn mặt bạn"), "selectYourPlan": MessageLookupByLibrary.simpleMessage("Chọn gói của bạn"), + "selectedAlbums": m79, "selectedFilesAreNotOnEnte": MessageLookupByLibrary.simpleMessage( "Các tệp đã chọn không có trên Ente"), "selectedFoldersWillBeEncryptedAndBackedUp": @@ -1571,9 +1842,13 @@ class MessageLookup extends MessageLookupByLibrary { "Các thư mục đã chọn sẽ được mã hóa và sao lưu"), "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( - "Các mục đã chọn sẽ bị xóa khỏi tất cả các album và chuyển vào thùng rác."), + "Các tệp đã chọn sẽ bị xóa khỏi tất cả album và cho vào thùng rác."), + "selectedItemsWillBeRemovedFromThisPerson": + MessageLookupByLibrary.simpleMessage( + "Các mục đã chọn sẽ bị xóa khỏi người này, nhưng không bị xóa khỏi thư viện của bạn."), "selectedPhotos": m80, "selectedPhotosWithYours": m81, + "selfiesWithThem": m82, "send": MessageLookupByLibrary.simpleMessage("Gửi"), "sendEmail": MessageLookupByLibrary.simpleMessage("Gửi email"), "sendInvite": MessageLookupByLibrary.simpleMessage("Gửi lời mời"), @@ -1601,23 +1876,23 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Chia sẻ một liên kết"), "shareAlbumHint": MessageLookupByLibrary.simpleMessage( "Mở album và nhấn nút chia sẻ ở góc trên bên phải để chia sẻ."), - "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage( - "Chia sẻ một album ngay bây giờ"), + "shareAnAlbumNow": + MessageLookupByLibrary.simpleMessage("Chia sẻ ngay một album"), "shareLink": MessageLookupByLibrary.simpleMessage("Chia sẻ liên kết"), "shareMyVerificationID": m83, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( - "Chia sẻ chỉ với những người bạn muốn"), + "Chỉ chia sẻ với những người bạn muốn"), "shareTextConfirmOthersVerificationID": m84, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Tải Ente để chúng ta có thể dễ dàng chia sẻ ảnh và video chất lượng gốc\n\nhttps://ente.io"), "shareTextReferralCode": m85, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( - "Chia sẻ với người dùng không phải Ente"), + "Chia sẻ với người không dùng Ente"), "shareWithPeopleSectionTitle": m86, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Chia sẻ album đầu tiên của bạn"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( - "Tạo album chia sẻ và hợp tác với các người dùng Ente khác, bao gồm cả người dùng trên các gói miễn phí."), + "Tạo album chia sẻ và cộng tác với người dùng Ente khác, bao gồm cả người dùng các gói miễn phí."), "sharedByMe": MessageLookupByLibrary.simpleMessage("Chia sẻ bởi tôi"), "sharedByYou": MessageLookupByLibrary.simpleMessage("Được chia sẻ bởi bạn"), @@ -1629,25 +1904,32 @@ class MessageLookup extends MessageLookupByLibrary { "sharedWithMe": MessageLookupByLibrary.simpleMessage("Chia sẻ với tôi"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Được chia sẻ với bạn"), - "sharing": MessageLookupByLibrary.simpleMessage("Chia sẻ..."), - "showMemories": - MessageLookupByLibrary.simpleMessage("Hiển thị kỷ niệm"), + "sharing": MessageLookupByLibrary.simpleMessage("Đang chia sẻ..."), + "shiftDatesAndTime": + MessageLookupByLibrary.simpleMessage("Di chuyển ngày và giờ"), + "showLessFaces": + MessageLookupByLibrary.simpleMessage("Hiện ít khuôn mặt hơn"), + "showMemories": MessageLookupByLibrary.simpleMessage("Xem lại kỷ niệm"), + "showMoreFaces": + MessageLookupByLibrary.simpleMessage("Hiện nhiều khuôn mặt hơn"), "showPerson": MessageLookupByLibrary.simpleMessage("Hiện người"), "signOutFromOtherDevices": MessageLookupByLibrary.simpleMessage( - "Đăng xuất từ các thiết bị khác"), + "Đăng xuất khỏi các thiết bị khác"), "signOutOtherBody": MessageLookupByLibrary.simpleMessage( - "Nếu bạn nghĩ rằng ai đó có thể biết mật khẩu của bạn, bạn có thể buộc tất cả các thiết bị khác đang sử dụng tài khoản của bạn đăng xuất."), - "signOutOtherDevices": - MessageLookupByLibrary.simpleMessage("Đăng xuất các thiết bị khác"), + "Nếu bạn nghĩ rằng ai đó biết mật khẩu của bạn, hãy ép tài khoản của bạn đăng xuất khỏi tất cả thiết bị khác đang sử dụng."), + "signOutOtherDevices": MessageLookupByLibrary.simpleMessage( + "Đăng xuất khỏi các thiết bị khác"), "signUpTerms": MessageLookupByLibrary.simpleMessage( - "Tôi đồng ý với các điều khoản dịch vụchính sách bảo mật"), + "Tôi đồng ý điều khoảnchính sách bảo mật"), "singleFileDeleteFromDevice": m88, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( - "Nó sẽ bị xóa khỏi tất cả các album."), + "Nó sẽ bị xóa khỏi tất cả album."), "singleFileInBothLocalAndRemote": m89, "singleFileInRemoteOnly": m90, "skip": MessageLookupByLibrary.simpleMessage("Bỏ qua"), - "social": MessageLookupByLibrary.simpleMessage("Xã hội"), + "smartMemories": + MessageLookupByLibrary.simpleMessage("Gợi nhớ kỷ niệm"), + "social": MessageLookupByLibrary.simpleMessage("Mạng xã hội"), "someItemsAreInBothEnteAndYourDevice": MessageLookupByLibrary.simpleMessage( "Một số mục có trên cả Ente và thiết bị của bạn."), @@ -1663,6 +1945,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Có gì đó không ổn, vui lòng thử lại"), "sorry": MessageLookupByLibrary.simpleMessage("Xin lỗi"), + "sorryBackupFailedDesc": MessageLookupByLibrary.simpleMessage( + "Rất tiếc, không thể sao lưu tệp vào lúc này, chúng tôi sẽ thử lại sau."), "sorryCouldNotAddToFavorites": MessageLookupByLibrary.simpleMessage( "Xin lỗi, không thể thêm vào mục yêu thích!"), "sorryCouldNotRemoveFromFavorites": @@ -1670,10 +1954,12 @@ class MessageLookup extends MessageLookupByLibrary { "Xin lỗi, không thể xóa khỏi mục yêu thích!"), "sorryTheCodeYouveEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( - "Xin lỗi, mã bạn đã nhập không chính xác"), + "Rất tiếc, mã bạn nhập không chính xác"), "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": MessageLookupByLibrary.simpleMessage( - "Xin lỗi, chúng tôi không thể tạo khóa an toàn trên thiết bị này.\n\nVui lòng đăng ký từ một thiết bị khác."), + "Rất tiếc, chúng tôi không thể tạo khóa an toàn trên thiết bị này.\n\nVui lòng đăng ký từ một thiết bị khác."), + "sorryWeHadToPauseYourBackups": MessageLookupByLibrary.simpleMessage( + "Rất tiếc, chúng tôi phải dừng sao lưu cho bạn"), "sort": MessageLookupByLibrary.simpleMessage("Sắp xếp"), "sortAlbumsBy": MessageLookupByLibrary.simpleMessage("Sắp xếp theo"), "sortNewestFirst": @@ -1681,6 +1967,10 @@ class MessageLookup extends MessageLookupByLibrary { "sortOldestFirst": MessageLookupByLibrary.simpleMessage("Cũ nhất trước"), "sparkleSuccess": MessageLookupByLibrary.simpleMessage("✨ Thành công"), + "sportsWithThem": m91, + "spotlightOnThem": m92, + "spotlightOnYourself": + MessageLookupByLibrary.simpleMessage("Tập trung vào bản thân bạn"), "startAccountRecoveryTitle": MessageLookupByLibrary.simpleMessage("Bắt đầu khôi phục"), "startBackup": MessageLookupByLibrary.simpleMessage("Bắt đầu sao lưu"), @@ -1694,35 +1984,37 @@ class MessageLookup extends MessageLookupByLibrary { "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Bạn"), "storageInGB": m93, "storageLimitExceeded": - MessageLookupByLibrary.simpleMessage("Vượt quá giới hạn lưu trữ"), + MessageLookupByLibrary.simpleMessage("Đã vượt hạn mức lưu trữ"), "storageUsageInfo": m94, + "streamDetails": MessageLookupByLibrary.simpleMessage("Chi tiết phát"), "strongStrength": MessageLookupByLibrary.simpleMessage("Mạnh"), "subAlreadyLinkedErrMessage": m95, "subWillBeCancelledOn": m96, - "subscribe": MessageLookupByLibrary.simpleMessage("Đăng ký"), + "subscribe": MessageLookupByLibrary.simpleMessage("Đăng ký gói"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( - "Bạn cần một đăng ký trả phí hoạt động để kích hoạt chia sẻ."), - "subscription": MessageLookupByLibrary.simpleMessage("Đăng ký"), + "Bạn phải dùng gói trả phí mới có thể chia sẻ."), + "subscription": MessageLookupByLibrary.simpleMessage("Gói đăng ký"), "success": MessageLookupByLibrary.simpleMessage("Thành công"), "successfullyArchived": MessageLookupByLibrary.simpleMessage("Lưu trữ thành công"), "successfullyHid": MessageLookupByLibrary.simpleMessage("Đã ẩn thành công"), "successfullyUnarchived": - MessageLookupByLibrary.simpleMessage("Khôi phục thành công"), + MessageLookupByLibrary.simpleMessage("Bỏ lưu trữ thành công"), "successfullyUnhid": MessageLookupByLibrary.simpleMessage("Đã hiện thành công"), "suggestFeatures": - MessageLookupByLibrary.simpleMessage("Gợi ý tính năng"), + MessageLookupByLibrary.simpleMessage("Đề xuất tính năng"), + "sunrise": MessageLookupByLibrary.simpleMessage("Đường chân trời"), "support": MessageLookupByLibrary.simpleMessage("Hỗ trợ"), "syncProgress": m97, "syncStopped": MessageLookupByLibrary.simpleMessage("Đồng bộ hóa đã dừng"), "syncing": MessageLookupByLibrary.simpleMessage("Đang đồng bộ hóa..."), - "systemTheme": MessageLookupByLibrary.simpleMessage("Hệ thống"), - "tapToCopy": MessageLookupByLibrary.simpleMessage("chạm để sao chép"), + "systemTheme": MessageLookupByLibrary.simpleMessage("Giống hệ thống"), + "tapToCopy": MessageLookupByLibrary.simpleMessage("nhấn để sao chép"), "tapToEnterCode": - MessageLookupByLibrary.simpleMessage("Chạm để nhập mã"), + MessageLookupByLibrary.simpleMessage("Nhấn để nhập mã"), "tapToUnlock": MessageLookupByLibrary.simpleMessage("Nhấn để mở khóa"), "tapToUpload": MessageLookupByLibrary.simpleMessage("Nhấn để tải lên"), "tapToUploadIsIgnoredDue": m98, @@ -1736,61 +2028,76 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Điều khoản"), "thankYou": MessageLookupByLibrary.simpleMessage("Cảm ơn bạn"), "thankYouForSubscribing": - MessageLookupByLibrary.simpleMessage("Cảm ơn bạn đã đăng ký!"), + MessageLookupByLibrary.simpleMessage("Cảm ơn bạn đã đăng ký gói!"), "theDownloadCouldNotBeCompleted": MessageLookupByLibrary.simpleMessage( - "Tải xuống không thể hoàn tất"), + "Không thể hoàn tất tải xuống"), "theLinkYouAreTryingToAccessHasExpired": MessageLookupByLibrary.simpleMessage( - "Liên kết bạn đang cố gắng truy cập đã hết hạn."), + "Liên kết mà bạn truy cập đã hết hạn."), + "thePersonGroupsWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Nhóm người sẽ không được hiển thị trong phần người nữa. Ảnh sẽ vẫn được giữ nguyên."), + "thePersonWillNotBeDisplayed": MessageLookupByLibrary.simpleMessage( + "Người sẽ không được hiển thị trong phần người nữa. Ảnh sẽ vẫn được giữ nguyên."), "theRecoveryKeyYouEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( - "Khóa khôi phục bạn đã nhập không chính xác"), + "Mã khôi phục bạn nhập không chính xác"), "theme": MessageLookupByLibrary.simpleMessage("Chủ đề"), "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Các mục này sẽ bị xóa khỏi thiết bị của bạn."), "theyAlsoGetXGb": m99, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( - "Chúng sẽ bị xóa khỏi tất cả các album."), + "Nó sẽ bị xóa khỏi tất cả album."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( - "Hành động này không thể hoàn tác"), + "Không thể hoàn tác thao tác này"), "thisAlbumAlreadyHDACollaborativeLink": MessageLookupByLibrary.simpleMessage( - "Album này đã có một liên kết hợp tác"), + "Album này đã có một liên kết cộng tác"), "thisCanBeUsedToRecoverYourAccountIfYou": MessageLookupByLibrary.simpleMessage( - "Điều này có thể được sử dụng để khôi phục tài khoản của bạn nếu bạn mất yếu tố thứ hai"), + "Chúng có thể giúp khôi phục tài khoản của bạn nếu bạn mất xác thực 2 bước"), "thisDevice": MessageLookupByLibrary.simpleMessage("Thiết bị này"), "thisEmailIsAlreadyInUse": MessageLookupByLibrary.simpleMessage("Email này đã được sử dụng"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( - "Hình ảnh này không có dữ liệu exif"), + "Ảnh này không có thông số Exif"), + "thisIsMeExclamation": + MessageLookupByLibrary.simpleMessage("Đây là tôi!"), "thisIsPersonVerificationId": m100, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage("Đây là ID xác minh của bạn"), + "thisWeekThroughTheYears": + MessageLookupByLibrary.simpleMessage("Tuần này qua các năm"), + "thisWeekXYearsAgo": m101, "thisWillLogYouOutOfTheFollowingDevice": MessageLookupByLibrary.simpleMessage( - "Điều này sẽ đăng xuất bạn khỏi thiết bị sau:"), + "Bạn cũng sẽ đăng xuất khỏi những thiết bị sau:"), "thisWillLogYouOutOfThisDevice": MessageLookupByLibrary.simpleMessage( - "Điều này sẽ đăng xuất bạn khỏi thiết bị này!"), + "Bạn sẽ đăng xuất khỏi thiết bị này!"), + "thisWillMakeTheDateAndTimeOfAllSelected": + MessageLookupByLibrary.simpleMessage( + "Thao tác này sẽ làm cho ngày và giờ của tất cả ảnh được chọn đều giống nhau."), "thisWillRemovePublicLinksOfAllSelectedQuickLinks": MessageLookupByLibrary.simpleMessage( - "Điều này sẽ xóa liên kết công khai của tất cả các liên kết nhanh đã chọn."), + "Liên kết công khai của tất cả các liên kết nhanh đã chọn sẽ bị xóa."), + "throughTheYears": m102, "toEnableAppLockPleaseSetupDevicePasscodeOrScreen": MessageLookupByLibrary.simpleMessage( "Để bật khóa ứng dụng, vui lòng thiết lập mã khóa thiết bị hoặc khóa màn hình trong cài đặt hệ thống của bạn."), "toHideAPhotoOrVideo": MessageLookupByLibrary.simpleMessage("Để ẩn một ảnh hoặc video"), "toResetVerifyEmail": MessageLookupByLibrary.simpleMessage( - "Để đặt lại mật khẩu của bạn, vui lòng xác minh email của bạn trước."), - "todaysLogs": MessageLookupByLibrary.simpleMessage("Nhật ký hôm nay"), - "tooManyIncorrectAttempts": MessageLookupByLibrary.simpleMessage( - "Quá nhiều lần thử không chính xác"), + "Để đặt lại mật khẩu, vui lòng xác minh email của bạn trước."), + "todaysLogs": MessageLookupByLibrary.simpleMessage("Log hôm nay"), + "tooManyIncorrectAttempts": + MessageLookupByLibrary.simpleMessage("Thử sai nhiều lần"), "total": MessageLookupByLibrary.simpleMessage("tổng"), - "totalSize": MessageLookupByLibrary.simpleMessage("Tổng kích thước"), + "totalSize": MessageLookupByLibrary.simpleMessage("Tổng dung lượng"), "trash": MessageLookupByLibrary.simpleMessage("Thùng rác"), "trashDaysLeft": m103, "trim": MessageLookupByLibrary.simpleMessage("Cắt"), + "tripInYear": m104, + "tripToLocation": m105, "trustedContacts": MessageLookupByLibrary.simpleMessage("Liên hệ tin cậy"), "trustedInviteBody": m106, @@ -1799,34 +2106,33 @@ class MessageLookup extends MessageLookupByLibrary { "Bật sao lưu để tự động tải lên các tệp được thêm vào thư mục thiết bị này lên Ente."), "twitter": MessageLookupByLibrary.simpleMessage("Twitter"), "twoMonthsFreeOnYearlyPlans": MessageLookupByLibrary.simpleMessage( - "2 tháng miễn phí cho các gói hàng năm"), - "twofactor": - MessageLookupByLibrary.simpleMessage("Xác thực hai yếu tố"), + "Nhận 2 tháng miễn phí với các gói theo năm"), + "twofactor": MessageLookupByLibrary.simpleMessage("Xác thực 2 bước"), "twofactorAuthenticationHasBeenDisabled": MessageLookupByLibrary.simpleMessage( - "Xác thực hai yếu tố đã bị vô hiệu hóa"), + "Xác thực 2 bước đã bị vô hiệu hóa"), "twofactorAuthenticationPageTitle": - MessageLookupByLibrary.simpleMessage("Xác thực hai yếu tố"), + MessageLookupByLibrary.simpleMessage("Xác thực 2 bước"), "twofactorAuthenticationSuccessfullyReset": MessageLookupByLibrary.simpleMessage( - "Xác thực hai yếu tố đã được đặt lại thành công"), + "Xác thực 2 bước đã được đặt lại thành công"), "twofactorSetup": - MessageLookupByLibrary.simpleMessage("Cài đặt hai yếu tố"), + MessageLookupByLibrary.simpleMessage("Cài đặt xác minh 2 bước"), "typeOfGallerGallerytypeIsNotSupportedForRename": m107, - "unarchive": MessageLookupByLibrary.simpleMessage("Khôi phục"), + "unarchive": MessageLookupByLibrary.simpleMessage("Bỏ lưu trữ"), "unarchiveAlbum": - MessageLookupByLibrary.simpleMessage("Khôi phục album"), + MessageLookupByLibrary.simpleMessage("Bỏ lưu trữ album"), "unarchiving": - MessageLookupByLibrary.simpleMessage("Đang khôi phục..."), + MessageLookupByLibrary.simpleMessage("Đang bỏ lưu trữ..."), "unavailableReferralCode": MessageLookupByLibrary.simpleMessage( - "Xin lỗi, mã này không khả dụng."), + "Rất tiếc, mã này không khả dụng."), "uncategorized": MessageLookupByLibrary.simpleMessage("Chưa phân loại"), "unhide": MessageLookupByLibrary.simpleMessage("Hiện lại"), "unhideToAlbum": - MessageLookupByLibrary.simpleMessage("Hiện lại vào album"), + MessageLookupByLibrary.simpleMessage("Hiện lại trong album"), "unhiding": MessageLookupByLibrary.simpleMessage("Đang hiện..."), - "unhidingFilesToAlbum": - MessageLookupByLibrary.simpleMessage("Đang hiện lại tệp vào album"), + "unhidingFilesToAlbum": MessageLookupByLibrary.simpleMessage( + "Đang hiện lại tệp trong album"), "unlock": MessageLookupByLibrary.simpleMessage("Mở khóa"), "unpinAlbum": MessageLookupByLibrary.simpleMessage("Bỏ ghim album"), "unselectAll": MessageLookupByLibrary.simpleMessage("Bỏ chọn tất cả"), @@ -1843,20 +2149,20 @@ class MessageLookup extends MessageLookupByLibrary { "uploadingSingleMemory": MessageLookupByLibrary.simpleMessage("Đang lưu giữ 1 kỷ niệm..."), "upto50OffUntil4thDec": MessageLookupByLibrary.simpleMessage( - "Giảm tới 50%, đến ngày 4 tháng 12."), + "Giảm tới 50%, đến ngày 4 Tháng 12."), "usableReferralStorageInfo": MessageLookupByLibrary.simpleMessage( - "Lưu trữ có thể sử dụng bị giới hạn bởi gói hiện tại của bạn. Lưu trữ đã yêu cầu vượt quá sẽ tự động trở thành có thể sử dụng khi bạn nâng cấp gói của mình."), - "useAsCover": MessageLookupByLibrary.simpleMessage("Sử dụng làm bìa"), + "Dung lượng có thể dùng bị giới hạn bởi gói hiện tại của bạn. Dung lượng nhận thêm vượt hạn mức sẽ tự động có thể dùng khi bạn nâng cấp gói."), + "useAsCover": MessageLookupByLibrary.simpleMessage("Đặt làm ảnh bìa"), "useDifferentPlayerInfo": MessageLookupByLibrary.simpleMessage( - "Phát video gặp vấn đề? Ấn giữ tại đây để thử một trình phát khác."), - "usePublicLinksForPeopleNotOnEnte": MessageLookupByLibrary.simpleMessage( - "Sử dụng liên kết công khai cho những người không có trên Ente"), + "Phát video gặp vấn đề? Nhấn giữ tại đây để thử một trình phát khác."), + "usePublicLinksForPeopleNotOnEnte": + MessageLookupByLibrary.simpleMessage( + "Dùng liên kết công khai cho những người không dùng Ente"), "useRecoveryKey": - MessageLookupByLibrary.simpleMessage("Sử dụng khóa khôi phục"), + MessageLookupByLibrary.simpleMessage("Dùng mã khôi phục"), "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Sử dụng ảnh đã chọn"), - "usedSpace": - MessageLookupByLibrary.simpleMessage("Không gian đã sử dụng"), + "usedSpace": MessageLookupByLibrary.simpleMessage("Dung lượng đã dùng"), "validTill": m110, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( @@ -1867,14 +2173,16 @@ class MessageLookup extends MessageLookupByLibrary { "verifyEmailID": m111, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Xác minh"), "verifyPasskey": - MessageLookupByLibrary.simpleMessage("Xác minh mã khóa"), + MessageLookupByLibrary.simpleMessage("Xác minh khóa truy cập"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Xác minh mật khẩu"), "verifying": MessageLookupByLibrary.simpleMessage("Đang xác minh..."), "verifyingRecoveryKey": MessageLookupByLibrary.simpleMessage( - "Đang xác minh khóa khôi phục..."), + "Đang xác minh mã khôi phục..."), "videoInfo": MessageLookupByLibrary.simpleMessage("Thông tin video"), "videoSmallCase": MessageLookupByLibrary.simpleMessage("video"), + "videoStreaming": + MessageLookupByLibrary.simpleMessage("Video có thể phát"), "videos": MessageLookupByLibrary.simpleMessage("Video"), "viewActiveSessions": MessageLookupByLibrary.simpleMessage("Xem phiên hoạt động"), @@ -1882,16 +2190,18 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Xem tiện ích mở rộng"), "viewAll": MessageLookupByLibrary.simpleMessage("Xem tất cả"), "viewAllExifData": - MessageLookupByLibrary.simpleMessage("Xem tất cả dữ liệu EXIF"), + MessageLookupByLibrary.simpleMessage("Xem thông số Exif"), "viewLargeFiles": MessageLookupByLibrary.simpleMessage("Tệp lớn"), "viewLargeFilesDesc": MessageLookupByLibrary.simpleMessage( - "Xem các tệp đang tiêu tốn nhiều dung lượng lưu trữ nhất."), - "viewLogs": MessageLookupByLibrary.simpleMessage("Xem nhật ký"), + "Xem các tệp đang chiếm nhiều dung lượng nhất."), + "viewLogs": MessageLookupByLibrary.simpleMessage("Xem log"), + "viewPersonToUnlink": m112, "viewRecoveryKey": - MessageLookupByLibrary.simpleMessage("Xem khóa khôi phục"), + MessageLookupByLibrary.simpleMessage("Xem mã khôi phục"), "viewer": MessageLookupByLibrary.simpleMessage("Người xem"), + "viewersSuccessfullyAdded": m113, "visitWebToManage": MessageLookupByLibrary.simpleMessage( - "Vui lòng truy cập web.ente.io để quản lý đăng ký của bạn"), + "Vui lòng truy cập web.ente.io để quản lý gói đăng ký"), "waitingForVerification": MessageLookupByLibrary.simpleMessage("Đang chờ xác minh..."), "waitingForWifi": @@ -1901,7 +2211,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Chúng tôi là mã nguồn mở!"), "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( - "Chúng tôi không hỗ trợ chỉnh sửa ảnh và album mà bạn chưa sở hữu"), + "Chúng tôi chưa hỗ trợ chỉnh sửa ảnh và album không phải bạn sở hữu"), "weHaveSendEmailTo": m114, "weakStrength": MessageLookupByLibrary.simpleMessage("Yếu"), "welcomeBack": @@ -1909,9 +2219,10 @@ class MessageLookup extends MessageLookupByLibrary { "whatsNew": MessageLookupByLibrary.simpleMessage("Có gì mới"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage( "Liên hệ tin cậy có thể giúp khôi phục dữ liệu của bạn."), + "widgets": MessageLookupByLibrary.simpleMessage("Tiện ích"), "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("năm"), - "yearly": MessageLookupByLibrary.simpleMessage("Hàng năm"), + "yearly": MessageLookupByLibrary.simpleMessage("Theo năm"), "yearsAgo": m116, "yes": MessageLookupByLibrary.simpleMessage("Có"), "yesCancel": MessageLookupByLibrary.simpleMessage("Có, hủy"), @@ -1920,18 +2231,20 @@ class MessageLookup extends MessageLookupByLibrary { "yesDelete": MessageLookupByLibrary.simpleMessage("Có, xóa"), "yesDiscardChanges": MessageLookupByLibrary.simpleMessage("Có, bỏ qua thay đổi"), + "yesIgnore": MessageLookupByLibrary.simpleMessage("Có, bỏ qua"), "yesLogout": MessageLookupByLibrary.simpleMessage("Có, đăng xuất"), "yesRemove": MessageLookupByLibrary.simpleMessage("Có, xóa"), "yesRenew": MessageLookupByLibrary.simpleMessage("Có, Gia hạn"), "yesResetPerson": MessageLookupByLibrary.simpleMessage("Có, đặt lại người"), "you": MessageLookupByLibrary.simpleMessage("Bạn"), - "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage( - "Bạn đang ở trên một kế hoạch gia đình!"), + "youAndThem": m117, + "youAreOnAFamilyPlan": + MessageLookupByLibrary.simpleMessage("Bạn đang dùng gói gia đình!"), "youAreOnTheLatestVersion": MessageLookupByLibrary.simpleMessage( "Bạn đang sử dụng phiên bản mới nhất"), "youCanAtMaxDoubleYourStorage": MessageLookupByLibrary.simpleMessage( - "* Bạn có thể tối đa gấp đôi lưu trữ của mình"), + "* Bạn có thể tối đa ×2 dung lượng của mình"), "youCanManageYourLinksInTheShareTab": MessageLookupByLibrary.simpleMessage( "Bạn có thể quản lý các liên kết của mình trong tab chia sẻ."), @@ -1939,7 +2252,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Bạn có thể thử tìm kiếm một truy vấn khác."), "youCannotDowngradeToThisPlan": MessageLookupByLibrary.simpleMessage( - "Bạn không thể hạ cấp xuống gói này"), + "Bạn không thể đổi xuống gói này"), "youCannotShareWithYourself": MessageLookupByLibrary.simpleMessage( "Bạn không thể chia sẻ với chính mình"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( @@ -1950,24 +2263,27 @@ class MessageLookup extends MessageLookupByLibrary { "yourMap": MessageLookupByLibrary.simpleMessage("Bản đồ của bạn"), "yourPlanWasSuccessfullyDowngraded": MessageLookupByLibrary.simpleMessage( - "Kế hoạch của bạn đã được hạ cấp thành công"), + "Gói của bạn đã được hạ cấp thành công"), "yourPlanWasSuccessfullyUpgraded": MessageLookupByLibrary.simpleMessage( - "Kế hoạch của bạn đã được nâng cấp thành công"), - "yourPurchaseWasSuccessful": MessageLookupByLibrary.simpleMessage( - "Mua hàng của bạn đã thành công"), + "Gói của bạn đã được nâng cấp thành công"), + "yourPurchaseWasSuccessful": + MessageLookupByLibrary.simpleMessage("Bạn đã giao dịch thành công"), "yourStorageDetailsCouldNotBeFetched": MessageLookupByLibrary.simpleMessage( - "Chi tiết lưu trữ của bạn không thể được lấy"), + "Không thể lấy chi tiết dung lượng của bạn"), "yourSubscriptionHasExpired": - MessageLookupByLibrary.simpleMessage("Đăng ký của bạn đã hết hạn"), + MessageLookupByLibrary.simpleMessage("Gói của bạn đã hết hạn"), "yourSubscriptionWasUpdatedSuccessfully": MessageLookupByLibrary.simpleMessage( - "Đăng ký của bạn đã được cập nhật thành công"), + "Gói của bạn đã được cập nhật thành công"), "yourVerificationCodeHasExpired": MessageLookupByLibrary.simpleMessage( "Mã xác minh của bạn đã hết hạn"), + "youveNoDuplicateFilesThatCanBeCleared": + MessageLookupByLibrary.simpleMessage( + "Bạn không có tệp nào bị trùng để xóa"), "youveNoFilesInThisAlbumThatCanBeDeleted": MessageLookupByLibrary.simpleMessage( - "Bạn không có tệp nào trong album này có thể bị xóa"), + "Bạn không có tệp nào có thể xóa trong album này"), "zoomOutToSeePhotos": MessageLookupByLibrary.simpleMessage("Phóng to để xem ảnh") }; diff --git a/mobile/apps/photos/lib/generated/intl/messages_zh.dart b/mobile/apps/photos/lib/generated/intl/messages_zh.dart index dada82528f..335650b34d 100644 --- a/mobile/apps/photos/lib/generated/intl/messages_zh.dart +++ b/mobile/apps/photos/lib/generated/intl/messages_zh.dart @@ -80,6 +80,9 @@ class MessageLookup extends MessageLookupByLibrary { static String m21(count) => "${Intl.plural(count, one: '删除 ${count} 个项目', other: '删除 ${count} 个项目')}"; + static String m22(count) => + "也删除这${count}个相册中的照片(和视频)从它们所在的所有其他相册中?"; + static String m23(currentlyDeleting, totalCount) => "正在删除 ${currentlyDeleting} /共 ${totalCount}"; @@ -93,6 +96,8 @@ class MessageLookup extends MessageLookupByLibrary { static String m27(count, formattedSize) => "${count} 个文件,每个文件 ${formattedSize}"; + static String m28(name) => "此电子邮件已与${name}关联。"; + static String m29(newEmail) => "电子邮件已更改为 ${newEmail}"; static String m30(email) => "${email} 没有 Ente 账户。"; @@ -206,6 +211,8 @@ class MessageLookup extends MessageLookupByLibrary { static String m78(snapshotLength, searchLength) => "部分长度不匹配:${snapshotLength} != ${searchLength}"; + static String m79(count) => "已选择 ${count} 个"; + static String m80(count) => "已选择 ${count} 个"; static String m81(count, yourCount) => "选择了 ${count} 个 (您的 ${yourCount} 个)"; @@ -278,12 +285,14 @@ class MessageLookup extends MessageLookupByLibrary { static String m111(email) => "验证 ${email}"; + static String m112(name) => "查看${name}以解除关联"; + static String m113(count) => "${Intl.plural(count, zero: '已添加0个查看者', one: '已添加1个查看者', other: '已添加 ${count} 个查看者')}"; static String m114(email) => "我们已经发送邮件到 ${email}"; - static String m115(name) => "Wish \$${name} a happy birthday! 🎉"; + static String m115(name) => "祝 ${name} 生日快乐! 🎉"; static String m116(count) => "${Intl.plural(count, other: '${count} 年前')}"; @@ -304,10 +313,14 @@ class MessageLookup extends MessageLookupByLibrary { "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("欢迎回来!"), "ackPasswordLostWarning": MessageLookupByLibrary.simpleMessage( "我明白,如果我丢失密码,我可能会丢失我的数据,因为我的数据是 端到端加密的。"), + "actionNotSupportedOnFavouritesAlbum": + MessageLookupByLibrary.simpleMessage("收藏相册不支持此操作"), "activeSessions": MessageLookupByLibrary.simpleMessage("已登录的设备"), "add": MessageLookupByLibrary.simpleMessage("添加"), "addAName": MessageLookupByLibrary.simpleMessage("添加一个名称"), "addANewEmail": MessageLookupByLibrary.simpleMessage("添加新的电子邮件"), + "addAlbumWidgetPrompt": + MessageLookupByLibrary.simpleMessage("将相册小组件添加到您的主屏幕,然后返回此处进行自定义。"), "addCollaborator": MessageLookupByLibrary.simpleMessage("添加协作者"), "addCollaborators": m1, "addFiles": MessageLookupByLibrary.simpleMessage("添加文件"), @@ -315,6 +328,8 @@ class MessageLookup extends MessageLookupByLibrary { "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("添加地点"), "addLocationButton": MessageLookupByLibrary.simpleMessage("添加"), + "addMemoriesWidgetPrompt": + MessageLookupByLibrary.simpleMessage("将回忆小组件添加到您的主屏幕,然后返回此处进行自定义。"), "addMore": MessageLookupByLibrary.simpleMessage("添加更多"), "addName": MessageLookupByLibrary.simpleMessage("添加名称"), "addNameOrMerge": MessageLookupByLibrary.simpleMessage("添加名称或合并"), @@ -323,6 +338,9 @@ class MessageLookup extends MessageLookupByLibrary { "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("附加组件详情"), "addOnValidTill": m3, "addOns": MessageLookupByLibrary.simpleMessage("附加组件"), + "addParticipants": MessageLookupByLibrary.simpleMessage("添加参与者"), + "addPeopleWidgetPrompt": + MessageLookupByLibrary.simpleMessage("将人物小组件添加到您的主屏幕,然后返回此处进行自定义。"), "addPhotos": MessageLookupByLibrary.simpleMessage("添加照片"), "addSelected": MessageLookupByLibrary.simpleMessage("添加所选项"), "addToAlbum": MessageLookupByLibrary.simpleMessage("添加到相册"), @@ -349,11 +367,16 @@ class MessageLookup extends MessageLookupByLibrary { "albumTitle": MessageLookupByLibrary.simpleMessage("相册标题"), "albumUpdated": MessageLookupByLibrary.simpleMessage("相册已更新"), "albums": MessageLookupByLibrary.simpleMessage("相册"), + "albumsWidgetDesc": + MessageLookupByLibrary.simpleMessage("选择您希望在主屏幕上看到的相册。"), "allClear": MessageLookupByLibrary.simpleMessage("✨ 全部清除"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("所有回忆都已保存"), "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( "此人的所有分组都将被重设,并且您将丢失针对此人的所有建议"), + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": + MessageLookupByLibrary.simpleMessage( + "所有未命名组将合并到所选人物中。此操作仍可从该人物的建议历史概览中撤销。"), "allWillShiftRangeBasedOnFirst": MessageLookupByLibrary.simpleMessage( "这张照片是该组中的第一张。其他已选择的照片将根据此新日期自动调整。"), "allow": MessageLookupByLibrary.simpleMessage("允许"), @@ -397,6 +420,9 @@ class MessageLookup extends MessageLookupByLibrary { "archive": MessageLookupByLibrary.simpleMessage("存档"), "archiveAlbum": MessageLookupByLibrary.simpleMessage("存档相册"), "archiving": MessageLookupByLibrary.simpleMessage("正在存档..."), + "areThey": MessageLookupByLibrary.simpleMessage("他们是 "), + "areYouSureRemoveThisFaceFromPerson": + MessageLookupByLibrary.simpleMessage("您确定要从此人中移除这个人脸吗?"), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage("您确定要离开家庭计划吗?"), "areYouSureYouWantToCancel": @@ -405,8 +431,14 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("您确定要更改您的计划吗?"), "areYouSureYouWantToExit": MessageLookupByLibrary.simpleMessage("您确定要退出吗?"), + "areYouSureYouWantToIgnoreThesePersons": + MessageLookupByLibrary.simpleMessage("您确定要忽略这些人吗?"), + "areYouSureYouWantToIgnoreThisPerson": + MessageLookupByLibrary.simpleMessage("您确定要忽略此人吗?"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage("您确定要退出登录吗?"), + "areYouSureYouWantToMergeThem": + MessageLookupByLibrary.simpleMessage("您确定要合并他们吗?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage("您确定要续费吗?"), "areYouSureYouWantToResetThisPerson": @@ -477,8 +509,28 @@ class MessageLookup extends MessageLookupByLibrary { "backupVideos": MessageLookupByLibrary.simpleMessage("备份视频"), "beach": MessageLookupByLibrary.simpleMessage("沙滩与大海"), "birthday": MessageLookupByLibrary.simpleMessage("生日"), + "birthdayNotifications": MessageLookupByLibrary.simpleMessage("生日通知"), + "birthdays": MessageLookupByLibrary.simpleMessage("生日"), "blackFridaySale": MessageLookupByLibrary.simpleMessage("黑色星期五特惠"), "blog": MessageLookupByLibrary.simpleMessage("博客"), + "cLDesc1": MessageLookupByLibrary.simpleMessage( + "在视频流媒体测试版和可恢复上传与下载功能的基础上,我们现已将文件上传限制提高到10GB。此功能现已在桌面和移动应用程序中可用。"), + "cLDesc2": MessageLookupByLibrary.simpleMessage( + "现在 iOS 设备也支持后台上传,Android 设备早已支持。无需打开应用程序即可备份最新的照片和视频。"), + "cLDesc3": MessageLookupByLibrary.simpleMessage( + "我们对回忆体验进行了重大改进,包括自动播放、滑动到下一个回忆以及更多功能。"), + "cLDesc4": MessageLookupByLibrary.simpleMessage( + "除了多项底层改进外,现在可以更轻松地查看所有检测到的人脸,对相似人脸提供反馈,以及从单张照片中添加/删除人脸。"), + "cLDesc5": MessageLookupByLibrary.simpleMessage( + "您现在将收到 Ente 上保存的所有生日的可选退出通知,同时附上他们最佳照片的合集。"), + "cLDesc6": MessageLookupByLibrary.simpleMessage( + "无需等待上传/下载完成即可关闭应用程序。所有上传和下载现在都可以中途暂停,并从中断处继续。"), + "cLTitle1": MessageLookupByLibrary.simpleMessage("正在上传大型视频文件"), + "cLTitle2": MessageLookupByLibrary.simpleMessage("后台上传"), + "cLTitle3": MessageLookupByLibrary.simpleMessage("自动播放回忆"), + "cLTitle4": MessageLookupByLibrary.simpleMessage("改进的人脸识别"), + "cLTitle5": MessageLookupByLibrary.simpleMessage("生日通知"), + "cLTitle6": MessageLookupByLibrary.simpleMessage("可恢复的上传和下载"), "cachedData": MessageLookupByLibrary.simpleMessage("缓存数据"), "calculating": MessageLookupByLibrary.simpleMessage("正在计算..."), "canNotOpenBody": @@ -534,6 +586,8 @@ class MessageLookup extends MessageLookupByLibrary { "click": MessageLookupByLibrary.simpleMessage("• 点击"), "clickOnTheOverflowMenu": MessageLookupByLibrary.simpleMessage("• 点击溢出菜单"), + "clickToInstallOurBestVersionYet": + MessageLookupByLibrary.simpleMessage("点击安装我们迄今最好的版本"), "close": MessageLookupByLibrary.simpleMessage("关闭"), "clubByCaptureTime": MessageLookupByLibrary.simpleMessage("按拍摄时间分组"), "clubByFileName": MessageLookupByLibrary.simpleMessage("按文件名排序"), @@ -608,6 +662,7 @@ class MessageLookup extends MessageLookupByLibrary { "criticalUpdateAvailable": MessageLookupByLibrary.simpleMessage("可用的关键更新"), "crop": MessageLookupByLibrary.simpleMessage("裁剪"), + "curatedMemories": MessageLookupByLibrary.simpleMessage("精选回忆"), "currentUsageIs": MessageLookupByLibrary.simpleMessage("当前用量 "), "currentlyRunning": MessageLookupByLibrary.simpleMessage("目前正在运行"), "custom": MessageLookupByLibrary.simpleMessage("自定义"), @@ -643,14 +698,13 @@ class MessageLookup extends MessageLookupByLibrary { "deleteFromEnte": MessageLookupByLibrary.simpleMessage("从 Ente 中删除"), "deleteItemCount": m21, "deleteLocation": MessageLookupByLibrary.simpleMessage("删除位置"), + "deleteMultipleAlbumDialog": m22, "deletePhotos": MessageLookupByLibrary.simpleMessage("删除照片"), "deleteProgress": m23, - "deleteReason1": MessageLookupByLibrary.simpleMessage("找不到我想要的功能"), - "deleteReason2": - MessageLookupByLibrary.simpleMessage("应用或某个功能没有按我的预期运行"), - "deleteReason3": - MessageLookupByLibrary.simpleMessage("我找到了另一个我喜欢的更好的服务"), - "deleteReason4": MessageLookupByLibrary.simpleMessage("我的原因未被列出"), + "deleteReason1": MessageLookupByLibrary.simpleMessage("缺少我所需的关键功能"), + "deleteReason2": MessageLookupByLibrary.simpleMessage("应用或某项功能未按预期运行"), + "deleteReason3": MessageLookupByLibrary.simpleMessage("我发现另一个产品更好用"), + "deleteReason4": MessageLookupByLibrary.simpleMessage("其他原因"), "deleteRequestSLAText": MessageLookupByLibrary.simpleMessage("您的请求将在 72 小时内处理。"), "deleteSharedAlbum": MessageLookupByLibrary.simpleMessage("要删除共享相册吗?"), @@ -670,6 +724,7 @@ class MessageLookup extends MessageLookupByLibrary { "当 Ente 置于前台且正在进行备份时将禁用设备屏幕锁定。这通常是不需要的,但可能有助于更快地完成大型上传和大型库的初始导入。"), "deviceNotFound": MessageLookupByLibrary.simpleMessage("未发现设备"), "didYouKnow": MessageLookupByLibrary.simpleMessage("您知道吗?"), + "different": MessageLookupByLibrary.simpleMessage("不同"), "disableAutoLock": MessageLookupByLibrary.simpleMessage("禁用自动锁定"), "disableDownloadWarningBody": MessageLookupByLibrary.simpleMessage("查看者仍然可以使用外部工具截图或保存您的照片副本"), @@ -713,6 +768,7 @@ class MessageLookup extends MessageLookupByLibrary { "duplicateFileCountWithStorageSaved": m26, "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("编辑"), + "editEmailAlreadyLinked": m28, "editLocation": MessageLookupByLibrary.simpleMessage("编辑位置"), "editLocationTagTitle": MessageLookupByLibrary.simpleMessage("编辑位置"), "editPerson": MessageLookupByLibrary.simpleMessage("编辑人物"), @@ -782,6 +838,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("请输入一个有效的电子邮件地址。"), "enterYourEmailAddress": MessageLookupByLibrary.simpleMessage("请输入您的电子邮件地址"), + "enterYourNewEmailAddress": + MessageLookupByLibrary.simpleMessage("输入您的新电子邮件地址"), "enterYourPassword": MessageLookupByLibrary.simpleMessage("输入您的密码"), "enterYourRecoveryKey": MessageLookupByLibrary.simpleMessage("输入您的恢复密钥"), @@ -874,6 +932,7 @@ class MessageLookup extends MessageLookupByLibrary { "guestView": MessageLookupByLibrary.simpleMessage("访客视图"), "guestViewEnablePreSteps": MessageLookupByLibrary.simpleMessage("要启用访客视图,请在系统设置中设置设备密码或屏幕锁。"), + "happyBirthday": MessageLookupByLibrary.simpleMessage("生日快乐! 🥳"), "hearUsExplanation": MessageLookupByLibrary.simpleMessage( "我们不跟踪应用程序安装情况。如果您告诉我们您是在哪里找到我们的,将会有所帮助!"), "hearUsWhereTitle": @@ -899,6 +958,7 @@ class MessageLookup extends MessageLookupByLibrary { "iOSLockOut": MessageLookupByLibrary.simpleMessage("生物识别认证已禁用。请锁定并解锁您的屏幕以启用它。"), "iOSOkButton": MessageLookupByLibrary.simpleMessage("好的"), + "ignore": MessageLookupByLibrary.simpleMessage("忽略"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("忽略"), "ignored": MessageLookupByLibrary.simpleMessage("已忽略"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( @@ -915,6 +975,8 @@ class MessageLookup extends MessageLookupByLibrary { "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage("恢复密钥不正确"), "indexedItems": MessageLookupByLibrary.simpleMessage("已索引项目"), + "indexingPausedStatusDescription": MessageLookupByLibrary.simpleMessage( + "索引已暂停。待设备准备就绪后,索引将自动恢复。当设备的电池电量、电池健康度和温度状态处于健康范围内时,设备即被视为准备就绪。"), "ineligible": MessageLookupByLibrary.simpleMessage("不合格"), "info": MessageLookupByLibrary.simpleMessage("详情"), "insecureDevice": MessageLookupByLibrary.simpleMessage("设备不安全"), @@ -989,6 +1051,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkPersonToEmailConfirmation": m49, "livePhotos": MessageLookupByLibrary.simpleMessage("实况照片"), "loadMessage1": MessageLookupByLibrary.simpleMessage("您可以与家庭分享您的订阅"), + "loadMessage2": MessageLookupByLibrary.simpleMessage("我们至今已保存超过2亿个回忆"), "loadMessage3": MessageLookupByLibrary.simpleMessage("我们保存你的3个数据副本,其中一个在地下安全屋中"), "loadMessage4": MessageLookupByLibrary.simpleMessage("我们所有的应用程序都是开源的"), @@ -1035,6 +1098,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("长按电子邮件以验证端到端加密。"), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage("长按一个项目来全屏查看"), + "lookBackOnYourMemories": + MessageLookupByLibrary.simpleMessage("回顾你的回忆🌄"), "loopVideoOff": MessageLookupByLibrary.simpleMessage("循环播放视频关闭"), "loopVideoOn": MessageLookupByLibrary.simpleMessage("循环播放视频开启"), "lostDevice": MessageLookupByLibrary.simpleMessage("设备丢失?"), @@ -1057,8 +1122,12 @@ class MessageLookup extends MessageLookupByLibrary { "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), "me": MessageLookupByLibrary.simpleMessage("我"), + "memories": MessageLookupByLibrary.simpleMessage("回忆"), + "memoriesWidgetDesc": + MessageLookupByLibrary.simpleMessage("选择您希望在主屏幕上看到的回忆类型。"), "memoryCount": m50, "merchandise": MessageLookupByLibrary.simpleMessage("商品"), + "merge": MessageLookupByLibrary.simpleMessage("合并"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("与现有的合并"), "mergedPhotos": MessageLookupByLibrary.simpleMessage("已合并照片"), "mlConsent": MessageLookupByLibrary.simpleMessage("启用机器学习"), @@ -1103,6 +1172,7 @@ class MessageLookup extends MessageLookupByLibrary { "newAlbum": MessageLookupByLibrary.simpleMessage("新建相册"), "newLocation": MessageLookupByLibrary.simpleMessage("新位置"), "newPerson": MessageLookupByLibrary.simpleMessage("新人物"), + "newPhotosEmoji": MessageLookupByLibrary.simpleMessage(" 新 📸"), "newRange": MessageLookupByLibrary.simpleMessage("新起始图片"), "newToEnte": MessageLookupByLibrary.simpleMessage("初来 Ente"), "newest": MessageLookupByLibrary.simpleMessage("最新"), @@ -1146,6 +1216,10 @@ class MessageLookup extends MessageLookupByLibrary { "onEnte": MessageLookupByLibrary.simpleMessage( "在 ente 上"), "onTheRoad": MessageLookupByLibrary.simpleMessage("再次踏上旅途"), + "onThisDay": MessageLookupByLibrary.simpleMessage("这天"), + "onThisDayMemories": MessageLookupByLibrary.simpleMessage("这天的回忆"), + "onThisDayNotificationExplanation": + MessageLookupByLibrary.simpleMessage("接收关于往年这一天回忆的提醒。"), "onlyFamilyAdminCanChangeCode": m55, "onlyThem": MessageLookupByLibrary.simpleMessage("仅限他们"), "oops": MessageLookupByLibrary.simpleMessage("哎呀"), @@ -1169,6 +1243,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("或者选择一个现有的"), "orPickFromYourContacts": MessageLookupByLibrary.simpleMessage("或从您的联系人中选择"), + "otherDetectedFaces": MessageLookupByLibrary.simpleMessage("其他检测到的人脸"), "pair": MessageLookupByLibrary.simpleMessage("配对"), "pairWithPin": MessageLookupByLibrary.simpleMessage("用 PIN 配对"), "pairingComplete": MessageLookupByLibrary.simpleMessage("配对完成"), @@ -1187,6 +1262,7 @@ class MessageLookup extends MessageLookupByLibrary { "密码强度的计算考虑了密码的长度、使用的字符以及密码是否出现在最常用的 10,000 个密码中"), "passwordWarning": MessageLookupByLibrary.simpleMessage( "我们不储存这个密码,所以如果忘记, 我们将无法解密您的数据"), + "pastYearsMemories": MessageLookupByLibrary.simpleMessage("往年回忆"), "paymentDetails": MessageLookupByLibrary.simpleMessage("付款明细"), "paymentFailed": MessageLookupByLibrary.simpleMessage("支付失败"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( @@ -1196,6 +1272,8 @@ class MessageLookup extends MessageLookupByLibrary { "pendingSync": MessageLookupByLibrary.simpleMessage("正在等待同步"), "people": MessageLookupByLibrary.simpleMessage("人物"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage("使用您的代码的人"), + "peopleWidgetDesc": + MessageLookupByLibrary.simpleMessage("选择您希望在主屏幕上看到的人。"), "permDeleteWarning": MessageLookupByLibrary.simpleMessage("回收站中的所有项目将被永久删除\n\n此操作无法撤消"), "permanentlyDelete": MessageLookupByLibrary.simpleMessage("永久删除"), @@ -1266,6 +1344,7 @@ class MessageLookup extends MessageLookupByLibrary { "processingVideos": MessageLookupByLibrary.simpleMessage("正在处理视频"), "publicLinkCreated": MessageLookupByLibrary.simpleMessage("公共链接已创建"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("公开链接已启用"), + "questionmark": MessageLookupByLibrary.simpleMessage("?"), "queued": MessageLookupByLibrary.simpleMessage("已入列"), "quickLinks": MessageLookupByLibrary.simpleMessage("快速链接"), "radius": MessageLookupByLibrary.simpleMessage("半径"), @@ -1276,6 +1355,8 @@ class MessageLookup extends MessageLookupByLibrary { "reassignMe": MessageLookupByLibrary.simpleMessage("重新分配“我”"), "reassignedToName": m69, "reassigningLoading": MessageLookupByLibrary.simpleMessage("正在重新分配..."), + "receiveRemindersOnBirthdays": MessageLookupByLibrary.simpleMessage( + "接收某人生日时的提醒。点击通知将带您查看生日人物的照片。"), "recover": MessageLookupByLibrary.simpleMessage("恢复"), "recoverAccount": MessageLookupByLibrary.simpleMessage("恢复账户"), "recoverButton": MessageLookupByLibrary.simpleMessage("恢复"), @@ -1351,6 +1432,7 @@ class MessageLookup extends MessageLookupByLibrary { "reportABug": MessageLookupByLibrary.simpleMessage("报告错误"), "reportBug": MessageLookupByLibrary.simpleMessage("报告错误"), "resendEmail": MessageLookupByLibrary.simpleMessage("重新发送电子邮件"), + "reset": MessageLookupByLibrary.simpleMessage("重设"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage("重置忽略的文件"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("重置密码"), "resetPerson": MessageLookupByLibrary.simpleMessage("移除"), @@ -1370,7 +1452,10 @@ class MessageLookup extends MessageLookupByLibrary { "rotateLeft": MessageLookupByLibrary.simpleMessage("向左旋转"), "rotateRight": MessageLookupByLibrary.simpleMessage("向右旋转"), "safelyStored": MessageLookupByLibrary.simpleMessage("安全存储"), + "same": MessageLookupByLibrary.simpleMessage("相同"), + "sameperson": MessageLookupByLibrary.simpleMessage("是同一个人?"), "save": MessageLookupByLibrary.simpleMessage("保存"), + "saveAsAnotherPerson": MessageLookupByLibrary.simpleMessage("另存为其他人物"), "saveChangesBeforeLeavingQuestion": MessageLookupByLibrary.simpleMessage("离开之前要保存更改吗?"), "saveCollage": MessageLookupByLibrary.simpleMessage("保存拼贴"), @@ -1439,6 +1524,7 @@ class MessageLookup extends MessageLookupByLibrary { "selectTime": MessageLookupByLibrary.simpleMessage("选择时间"), "selectYourFace": MessageLookupByLibrary.simpleMessage("选择你的脸"), "selectYourPlan": MessageLookupByLibrary.simpleMessage("选择您的计划"), + "selectedAlbums": m79, "selectedFilesAreNotOnEnte": MessageLookupByLibrary.simpleMessage("所选文件不在 Ente 上"), "selectedFoldersWillBeEncryptedAndBackedUp": @@ -1497,7 +1583,9 @@ class MessageLookup extends MessageLookupByLibrary { "sharedWithYou": MessageLookupByLibrary.simpleMessage("已与您共享"), "sharing": MessageLookupByLibrary.simpleMessage("正在分享..."), "shiftDatesAndTime": MessageLookupByLibrary.simpleMessage("调整日期和时间"), + "showLessFaces": MessageLookupByLibrary.simpleMessage("显示较少人脸"), "showMemories": MessageLookupByLibrary.simpleMessage("显示回忆"), + "showMoreFaces": MessageLookupByLibrary.simpleMessage("显示更多人脸"), "showPerson": MessageLookupByLibrary.simpleMessage("显示人员"), "signOutFromOtherDevices": MessageLookupByLibrary.simpleMessage("从其他设备退出登录"), @@ -1512,6 +1600,7 @@ class MessageLookup extends MessageLookupByLibrary { "singleFileInBothLocalAndRemote": m89, "singleFileInRemoteOnly": m90, "skip": MessageLookupByLibrary.simpleMessage("跳过"), + "smartMemories": MessageLookupByLibrary.simpleMessage("智能回忆"), "social": MessageLookupByLibrary.simpleMessage("社交"), "someItemsAreInBothEnteAndYourDevice": MessageLookupByLibrary.simpleMessage("有些项目同时存在于 Ente 和您的设备中。"), @@ -1523,6 +1612,8 @@ class MessageLookup extends MessageLookupByLibrary { "somethingWentWrongPleaseTryAgain": MessageLookupByLibrary.simpleMessage("出了点问题,请重试"), "sorry": MessageLookupByLibrary.simpleMessage("抱歉"), + "sorryBackupFailedDesc": + MessageLookupByLibrary.simpleMessage("抱歉,我们目前无法备份此文件,我们将稍后重试。"), "sorryCouldNotAddToFavorites": MessageLookupByLibrary.simpleMessage("抱歉,无法添加到收藏!"), "sorryCouldNotRemoveFromFavorites": @@ -1532,6 +1623,8 @@ class MessageLookup extends MessageLookupByLibrary { "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": MessageLookupByLibrary.simpleMessage( "抱歉,我们无法在此设备上生成安全密钥。\n\n请使用其他设备注册。"), + "sorryWeHadToPauseYourBackups": + MessageLookupByLibrary.simpleMessage("抱歉,我们不得不暂停您的备份"), "sort": MessageLookupByLibrary.simpleMessage("排序"), "sortAlbumsBy": MessageLookupByLibrary.simpleMessage("排序方式"), "sortNewestFirst": MessageLookupByLibrary.simpleMessage("最新在前"), @@ -1592,6 +1685,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("未能完成下载"), "theLinkYouAreTryingToAccessHasExpired": MessageLookupByLibrary.simpleMessage("您尝试访问的链接已过期。"), + "thePersonGroupsWillNotBeDisplayed": + MessageLookupByLibrary.simpleMessage("人物组将不再显示在人物部分。照片将保持不变。"), + "thePersonWillNotBeDisplayed": + MessageLookupByLibrary.simpleMessage("该人将不再显示在人物部分。照片将保持不变。"), "theRecoveryKeyYouEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage("您输入的恢复密钥不正确"), "theme": MessageLookupByLibrary.simpleMessage("主题"), @@ -1710,6 +1807,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("正在验证恢复密钥..."), "videoInfo": MessageLookupByLibrary.simpleMessage("视频详情"), "videoSmallCase": MessageLookupByLibrary.simpleMessage("视频"), + "videoStreaming": MessageLookupByLibrary.simpleMessage("可流媒体播放的视频"), "videos": MessageLookupByLibrary.simpleMessage("视频"), "viewActiveSessions": MessageLookupByLibrary.simpleMessage("查看活动会话"), "viewAddOnButton": MessageLookupByLibrary.simpleMessage("查看附加组件"), @@ -1719,6 +1817,7 @@ class MessageLookup extends MessageLookupByLibrary { "viewLargeFilesDesc": MessageLookupByLibrary.simpleMessage("查看占用存储空间最多的文件。"), "viewLogs": MessageLookupByLibrary.simpleMessage("查看日志"), + "viewPersonToUnlink": m112, "viewRecoveryKey": MessageLookupByLibrary.simpleMessage("查看恢复密钥"), "viewer": MessageLookupByLibrary.simpleMessage("查看者"), "viewersSuccessfullyAdded": m113, @@ -1737,6 +1836,7 @@ class MessageLookup extends MessageLookupByLibrary { "whatsNew": MessageLookupByLibrary.simpleMessage("更新日志"), "whyAddTrustContact": MessageLookupByLibrary.simpleMessage("可信联系人可以帮助恢复您的数据。"), + "widgets": MessageLookupByLibrary.simpleMessage("小组件"), "wishThemAHappyBirthday": m115, "yearShort": MessageLookupByLibrary.simpleMessage("年"), "yearly": MessageLookupByLibrary.simpleMessage("每年"), @@ -1746,6 +1846,7 @@ class MessageLookup extends MessageLookupByLibrary { "yesConvertToViewer": MessageLookupByLibrary.simpleMessage("是的,转换为查看者"), "yesDelete": MessageLookupByLibrary.simpleMessage("是的, 删除"), "yesDiscardChanges": MessageLookupByLibrary.simpleMessage("是的,放弃更改"), + "yesIgnore": MessageLookupByLibrary.simpleMessage("是的,忽略"), "yesLogout": MessageLookupByLibrary.simpleMessage("是的,退出登陆"), "yesRemove": MessageLookupByLibrary.simpleMessage("是,移除"), "yesRenew": MessageLookupByLibrary.simpleMessage("是的,续费"), diff --git a/mobile/apps/photos/lib/generated/l10n.dart b/mobile/apps/photos/lib/generated/l10n.dart index 5a63f58f68..c0ee8710c1 100644 --- a/mobile/apps/photos/lib/generated/l10n.dart +++ b/mobile/apps/photos/lib/generated/l10n.dart @@ -12295,6 +12295,26 @@ class S { args: [], ); } + + /// `Unable to generate face thumbnails` + String get faceThumbnailGenerationFailed { + return Intl.message( + 'Unable to generate face thumbnails', + name: 'faceThumbnailGenerationFailed', + desc: '', + args: [], + ); + } + + /// `Unable to analyze file` + String get fileAnalysisFailed { + return Intl.message( + 'Unable to analyze file', + name: 'fileAnalysisFailed', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/mobile/apps/photos/lib/l10n/intl_en.arb b/mobile/apps/photos/lib/l10n/intl_en.arb index e9cd89b1f7..1ca8f23f95 100644 --- a/mobile/apps/photos/lib/l10n/intl_en.arb +++ b/mobile/apps/photos/lib/l10n/intl_en.arb @@ -1788,5 +1788,7 @@ "cLDesc5": "You will now receive an opt-out notification for all the birthdays your have saved on Ente, along with a collection of their best photos.", "cLTitle6": "Resumable Uploads and Downloads", "cLDesc6": "No more waiting for uploads/downloads to complete before you can close the app. All uploads and downloads now have the ability to be paused midway, and resume from where you left off.", - "indexingPausedStatusDescription": "Indexing is paused. It will automatically resume when the device is ready. The device is considered ready when its battery level, battery health, and thermal status are within a healthy range." + "indexingPausedStatusDescription": "Indexing is paused. It will automatically resume when the device is ready. The device is considered ready when its battery level, battery health, and thermal status are within a healthy range.", + "faceThumbnailGenerationFailed": "Unable to generate face thumbnails", + "fileAnalysisFailed": "Unable to analyze file" } diff --git a/mobile/apps/photos/lib/ui/viewer/file_details/file_info_faces_item_widget.dart b/mobile/apps/photos/lib/ui/viewer/file_details/file_info_faces_item_widget.dart index 4668bdc0d7..ed3ed9ac59 100644 --- a/mobile/apps/photos/lib/ui/viewer/file_details/file_info_faces_item_widget.dart +++ b/mobile/apps/photos/lib/ui/viewer/file_details/file_info_faces_item_widget.dart @@ -451,8 +451,8 @@ String getNoFaceReasonText(BuildContext context, NoFacesReason reason) { case NoFacesReason.noFacesFound: return S.of(context).noFacesFound; case NoFacesReason.faceThumbnailGenerationFailed: - return "Unable to generate face thumbnails"; + return S.of(context).faceThumbnailGenerationFailed; case NoFacesReason.fileAnalysisFailed: - return "File analysis failed"; + return S.of(context).fileAnalysisFailed; } } From 39558a27c918f64c205b688ca89324a81640467c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 16 Jul 2025 21:26:20 +0530 Subject: [PATCH 43/81] Inline --- web/apps/photos/src/components/FileList.tsx | 105 +++++++++----------- 1 file changed, 47 insertions(+), 58 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 1fe3022dff..f42bf29cb3 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -326,11 +326,9 @@ export const FileList: React.FC = ({ } } - if (!isSmallerLayout) { - items = mergeTimeStampList(items, columns); - } + if (!isSmallerLayout) items = mergeRowsWherePossible(items, columns); - if (annotatedFiles.length == 0) { + if (!annotatedFiles.length) { items.push({ height: height - 48, tag: "span", @@ -450,12 +448,8 @@ export const FileList: React.FC = ({ [setSelected, mode, user?.id, activeCollectionID, activePersonID], ); - const onHoverOver = (index: number) => () => { - setCurrentHover(index); - }; - const handleRangeSelect = (index: number) => () => { - if (typeof rangeStart != "undefined" && rangeStart !== index) { + if (rangeStart !== index) { const direction = (index - rangeStart!) / Math.abs(index - rangeStart!); let checked = true; @@ -500,46 +494,9 @@ export const FileList: React.FC = ({ }, []); useEffect(() => { - if (selected.count === 0) { - setRangeStart(null); - } + if (selected.count == 0) setRangeStart(null); }, [selected]); - const getThumbnail = ( - { file }: FileListAnnotatedFile, - index: number, - isScrolling: boolean, - ) => ( - onItemClick(index)} - selectable={selectable!} - onSelect={handleSelect(file, index)} - selected={ - (!mode - ? selected.collectionID === activeCollectionID - : mode == selected.context?.mode && - (selected.context.mode == "people" - ? selected.context.personID == activePersonID - : selected.context.collectionID == - activeCollectionID)) && !!selected[file.id] - } - selectOnClick={selected.count > 0} - onHover={onHoverOver(index)} - onRangeSelect={handleRangeSelect(index)} - isRangeSelectActive={isShiftKeyPressed && selected.count > 0} - isInsSelectRange={ - (index >= rangeStart! && index <= currentHover!) || - (index >= currentHover! && index <= rangeStart!) - } - activeCollectionID={activeCollectionID} - showPlaceholder={isScrolling} - isFav={favoriteFileIDs?.has(file.id)} - /> - ); - // eslint-disable-next-line react-hooks/exhaustive-deps const renderListItem = ( listItem: FileListItem, @@ -591,13 +548,45 @@ export const FileList: React.FC = ({ ); case "file": { - const ret = listItem.items!.map((item, idx) => - getThumbnail( - item, - listItem.itemStartIndex! + idx, - !!isScrolling, - ), - ); + const ret = listItem.items!.map(({ file }, i) => { + const index = listItem.itemStartIndex! + i; + return ( + onItemClick(index)} + selectable={selectable!} + onSelect={handleSelect(file, index)} + selected={ + (!mode + ? selected.collectionID === + activeCollectionID + : mode == selected.context?.mode && + (selected.context.mode == "people" + ? selected.context.personID == + activePersonID + : selected.context.collectionID == + activeCollectionID)) && + !!selected[file.id] + } + selectOnClick={selected.count > 0} + onHover={() => setCurrentHover(index)} + onRangeSelect={handleRangeSelect(index)} + isRangeSelectActive={ + isShiftKeyPressed && selected.count > 0 + } + isInsSelectRange={ + (index >= rangeStart! && + index <= currentHover!) || + (index >= currentHover! && index <= rangeStart!) + } + activeCollectionID={activeCollectionID} + showPlaceholder={!!isScrolling} + isFav={favoriteFileIDs?.has(file.id)} + /> + ); + }); if (listItem.groups) { let sum = 0; for (let i = 0; i < listItem.groups.length - 1; i++) { @@ -681,9 +670,9 @@ export const FileList: React.FC = ({ }; /** - * Checks and merge multiple dates into a single row. + * Merge multiple dates into a single row. */ -const mergeTimeStampList = ( +const mergeRowsWherePossible = ( items: FileListItem[], columns: number, ): FileListItem[] => { @@ -815,8 +804,8 @@ interface FileListItemData { layoutParams: ThumbnailGridLayoutParams; renderListItem: ( timeStampListItem: FileListItem, - isScrolling?: boolean, - ) => React.JSX.Element; + isScrolling: boolean | undefined, + ) => React.ReactNode; } const FileListRow = memo( From 49a8016786020b020552ca00a61d83ef0d5ce751 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 17 Jul 2025 05:48:08 +0530 Subject: [PATCH 44/81] Scope --- web/apps/photos/src/components/FileList.tsx | 24 +++++++-------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index f42bf29cb3..aa9e407bfb 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -244,16 +244,6 @@ export const FileList: React.FC = ({ [width], ); - const { - // containerWidth, - // isSmallerLayout, - // paddingInline, - columns, - // itemWidth, - // itemHeight, - // gap, - } = layoutParams; - useEffect(() => { // Since width and height are dependencies, there might be too many // updates to the list during a resize. The list computation too, while @@ -500,7 +490,8 @@ export const FileList: React.FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps const renderListItem = ( listItem: FileListItem, - isScrolling: boolean | undefined, + layoutParams: ThumbnailGridLayoutParams, + isScrolling: boolean, ) => { const haveSelection = selected.count > 0; switch (listItem.tag) { @@ -529,7 +520,7 @@ export const FileList: React.FC = ({ ]) .flat() ) : ( - + {haveSelection && ( = ({ (index >= currentHover! && index <= rangeStart!) } activeCollectionID={activeCollectionID} - showPlaceholder={!!isScrolling} + showPlaceholder={isScrolling} isFav={favoriteFileIDs?.has(file.id)} /> ); @@ -803,8 +794,9 @@ interface FileListItemData { items: FileListItem[]; layoutParams: ThumbnailGridLayoutParams; renderListItem: ( - timeStampListItem: FileListItem, - isScrolling: boolean | undefined, + listItem: FileListItem, + layoutParams: ThumbnailGridLayoutParams, + isScrolling: boolean, ) => React.ReactNode; } @@ -839,7 +831,7 @@ const FileListRow = memo( }, ]} > - {renderListItem(item, isScrolling)} + {renderListItem(item, layoutParams, !!isScrolling)} ); }, From 67e1a64e7f2dda98a87f5c065b4e2295ad3cf1f7 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 17 Jul 2025 06:38:52 +0530 Subject: [PATCH 45/81] Trace deps --- web/apps/photos/src/components/FileList.tsx | 357 ++++++++++-------- web/apps/photos/src/utils/photoFrame/index.ts | 9 +- 2 files changed, 199 insertions(+), 167 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index aa9e407bfb..940c25f5fa 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -227,17 +227,18 @@ export const FileList: React.FC = ({ const [_items, setItems] = useState([]); const items = useDeferredValue(_items); - const listRef = useRef(null); - + const [rangeStartIndex, setRangeStartIndex] = useState( + undefined, + ); + const [hoverIndex, setHoverIndex] = useState(undefined); + const [isShiftKeyPressed, setIsShiftKeyPressed] = useState(false); // Timeline date strings for which all photos have been selected. // // See: [Note: Timeline date string] const [checkedTimelineDateStrings, setCheckedTimelineDateStrings] = - useState(new Set()); + useState(new Set()); - const [rangeStart, setRangeStart] = useState(null); - const [currentHover, setCurrentHover] = useState(null); - const [isShiftKeyPressed, setIsShiftKeyPressed] = useState(false); + const listRef = useRef(null); const layoutParams = useMemo( () => computeThumbnailGridLayoutParams(width), @@ -397,33 +398,40 @@ export const FileList: React.FC = ({ }); }, [annotatedFiles, selected]); - const handleSelectMulti = handleSelectCreatorMulti( - setSelected, - mode, - user?.id, - activeCollectionID, - activePersonID, + const handleSelectMulti = useMemo( + () => + handleSelectCreatorMulti( + setSelected, + mode, + user?.id, + activeCollectionID, + activePersonID, + ), + [setSelected, mode, user?.id, activeCollectionID, activePersonID], ); - const onChangeSelectAllCheckBox = (date: string) => { - const next = new Set(checkedTimelineDateStrings); - let isDateSelected: boolean; - if (!next.has(date)) { - next.add(date); - isDateSelected = true; - } else { - next.delete(date); - isDateSelected = false; - } - setCheckedTimelineDateStrings(next); + const onChangeSelectAllCheckBox = useCallback( + (date: string) => { + const next = new Set(checkedTimelineDateStrings); + let isDateSelected: boolean; + if (!next.has(date)) { + next.add(date); + isDateSelected = true; + } else { + next.delete(date); + isDateSelected = false; + } + setCheckedTimelineDateStrings(next); - // All files on a checked/unchecked day. - const filesOnADay = annotatedFiles.filter( - (af) => af.timelineDateString === date, - ); + // All files on a checked/unchecked day. + const filesOnADay = annotatedFiles.filter( + (af) => af.timelineDateString === date, + ); - handleSelectMulti(filesOnADay.map((af) => af.file))(isDateSelected); - }; + handleSelectMulti(filesOnADay.map((af) => af.file))(isDateSelected); + }, + [annotatedFiles, checkedTimelineDateStrings, handleSelectMulti], + ); const handleSelect = useMemo( () => @@ -433,33 +441,36 @@ export const FileList: React.FC = ({ user?.id, activeCollectionID, activePersonID, - setRangeStart, + setRangeStartIndex, ), [setSelected, mode, user?.id, activeCollectionID, activePersonID], ); - const handleRangeSelect = (index: number) => () => { - if (rangeStart !== index) { - const direction = - (index - rangeStart!) / Math.abs(index - rangeStart!); + const handleRangeSelect = useCallback( + (index: number) => { + if (rangeStartIndex === undefined || rangeStartIndex == index) + return; + + const direction = index > rangeStartIndex ? 1 : -1; let checked = true; for ( - let i = rangeStart!; + let i = rangeStartIndex; (index - i) * direction >= 0; i += direction ) { checked = checked && !!selected[annotatedFiles[i]!.file.id]; } for ( - let i = rangeStart!; + let i = rangeStartIndex; (index - i) * direction > 0; i += direction ) { handleSelect(annotatedFiles[i]!.file)(!checked); } handleSelect(annotatedFiles[index]!.file, index)(!checked); - } - }; + }, + [annotatedFiles, selected, rangeStartIndex, handleSelect], + ); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { @@ -484,120 +495,146 @@ export const FileList: React.FC = ({ }, []); useEffect(() => { - if (selected.count == 0) setRangeStart(null); + if (selected.count == 0) setRangeStartIndex(undefined); }, [selected]); - // eslint-disable-next-line react-hooks/exhaustive-deps - const renderListItem = ( - listItem: FileListItem, - layoutParams: ThumbnailGridLayoutParams, - isScrolling: boolean, - ) => { - const haveSelection = selected.count > 0; - switch (listItem.tag) { - case "date": - return listItem.dates ? ( - listItem.dates - .map((item) => [ - - {haveSelection && ( - - onChangeSelectAllCheckBox(item.date) - } - size="small" - sx={{ pl: 0 }} - /> - )} - {item.date} - , -
, - ]) - .flat() - ) : ( - - {haveSelection && ( - - onChangeSelectAllCheckBox(listItem.date!) - } - size="small" - sx={{ pl: 0 }} - /> - )} - {listItem.date} - - ); - case "file": { - const ret = listItem.items!.map(({ file }, i) => { - const index = listItem.itemStartIndex! + i; - return ( - onItemClick(index)} - selectable={selectable!} - onSelect={handleSelect(file, index)} - selected={ - (!mode - ? selected.collectionID === - activeCollectionID - : mode == selected.context?.mode && - (selected.context.mode == "people" - ? selected.context.personID == - activePersonID - : selected.context.collectionID == - activeCollectionID)) && - !!selected[file.id] - } - selectOnClick={selected.count > 0} - onHover={() => setCurrentHover(index)} - onRangeSelect={handleRangeSelect(index)} - isRangeSelectActive={ - isShiftKeyPressed && selected.count > 0 - } - isInsSelectRange={ - (index >= rangeStart! && - index <= currentHover!) || - (index >= currentHover! && index <= rangeStart!) - } - activeCollectionID={activeCollectionID} - showPlaceholder={isScrolling} - isFav={favoriteFileIDs?.has(file.id)} - /> + const renderListItem = useCallback( + ( + listItem: FileListItem, + layoutParams: ThumbnailGridLayoutParams, + isScrolling: boolean, + ) => { + const haveSelection = selected.count > 0; + switch (listItem.tag) { + case "date": + return listItem.dates ? ( + listItem.dates + .map((item) => [ + + {haveSelection && ( + + onChangeSelectAllCheckBox( + item.date, + ) + } + size="small" + sx={{ pl: 0 }} + /> + )} + {item.date} + , +
, + ]) + .flat() + ) : ( + + {haveSelection && ( + + onChangeSelectAllCheckBox( + listItem.date!, + ) + } + size="small" + sx={{ pl: 0 }} + /> + )} + {listItem.date} + ); - }); - if (listItem.groups) { - let sum = 0; - for (let i = 0; i < listItem.groups.length - 1; i++) { - sum = sum + listItem.groups[i]!; - ret.splice( - sum, - 0, -
, + case "file": { + const ret = listItem.items!.map(({ file }, i) => { + const index = listItem.itemStartIndex! + i; + return ( + 0} + isRangeSelectActive={ + isShiftKeyPressed && selected.count > 0 + } + isInSelectRange={ + rangeStartIndex !== undefined && + hoverIndex !== undefined && + ((index >= rangeStartIndex && + index <= hoverIndex) || + (index >= hoverIndex && + index <= rangeStartIndex)) + } + activeCollectionID={activeCollectionID} + showPlaceholder={isScrolling} + isFav={!!favoriteFileIDs?.has(file.id)} + onClick={() => onItemClick(index)} + onSelect={handleSelect(file, index)} + onHover={() => setHoverIndex(index)} + onRangeSelect={() => handleRangeSelect(index)} + /> ); - sum += 1; + }); + if (listItem.groups) { + let sum = 0; + for (let i = 0; i < listItem.groups.length - 1; i++) { + sum = sum + listItem.groups[i]!; + ret.splice( + sum, + 0, +
, + ); + sum += 1; + } } + return ret; } - return ret; + default: + return listItem.component; } - default: - return listItem.component; - } - }; + }, + [ + activeCollectionID, + activePersonID, + checkedTimelineDateStrings, + emailByUserID, + favoriteFileIDs, + handleRangeSelect, + handleSelect, + hoverIndex, + isShiftKeyPressed, + mode, + onChangeSelectAllCheckBox, + onItemClick, + rangeStartIndex, + selectable, + selected, + user, + ], + ); const itemData = useMemo( () => ({ items, layoutParams, renderListItem }), @@ -840,36 +877,36 @@ const FileListRow = memo( type FileThumbnailProps = { file: EnteFile; - onClick: () => void; selectable: boolean; selected: boolean; + isRangeSelectActive: boolean; + selectOnClick: boolean; + isInSelectRange: boolean; + activeCollectionID: number; + showPlaceholder: boolean; + isFav: boolean; + onClick: () => void; onSelect: (checked: boolean) => void; onHover: () => void; onRangeSelect: () => void; - isRangeSelectActive: boolean; - selectOnClick: boolean; - isInsSelectRange: boolean; - activeCollectionID: number; - showPlaceholder: boolean; - isFav: boolean | undefined; } & Pick; const FileThumbnail: React.FC = ({ file, user, - onClick, selectable, selected, - onSelect, selectOnClick, - onHover, - onRangeSelect, isRangeSelectActive, - isInsSelectRange, + isInSelectRange, isFav, emailByUserID, activeCollectionID, showPlaceholder, + onClick, + onSelect, + onHover, + onRangeSelect, }) => { const [imageURL, setImageURL] = useState(undefined); const [isLongPressing, setIsLongPressing] = useState(false); @@ -953,7 +990,7 @@ const FileThumbnail: React.FC = ({ type="checkbox" checked={selected} onChange={handleSelect} - $active={isRangeSelectActive && isInsSelectRange} + $active={isRangeSelectActive && isInSelectRange} onClick={(e) => e.stopPropagation()} /> )} @@ -989,9 +1026,7 @@ const FileThumbnail: React.FC = ({ className="preview-card-hover-overlay" checked={selected} /> - {isRangeSelectActive && isInsSelectRange && ( - - )} + {isRangeSelectActive && isInSelectRange && } {deleteBy && ( diff --git a/web/apps/photos/src/utils/photoFrame/index.ts b/web/apps/photos/src/utils/photoFrame/index.ts index 5680bd0309..672c85d2b7 100644 --- a/web/apps/photos/src/utils/photoFrame/index.ts +++ b/web/apps/photos/src/utils/photoFrame/index.ts @@ -11,18 +11,15 @@ export const handleSelectCreator = userID: number | undefined, activeCollectionID: number, activePersonID: string | undefined, - // @ts-expect-error Need to add types - setRangeStart?, + setRangeStartIndex: (index: number | undefined) => void, ) => ({ id, ownerID }: { id: number; ownerID: number }, index?: number) => (checked: boolean) => { if (typeof index != "undefined") { if (checked) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - setRangeStart(index); + setRangeStartIndex(index); } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - setRangeStart(undefined); + setRangeStartIndex(undefined); } } setSelected((_selected) => { From 479f2188b64e9d53859bf25234d8d477b2f9d9fd Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 17 Jul 2025 08:39:52 +0530 Subject: [PATCH 46/81] Rename --- web/apps/photos/src/components/FileList.tsx | 22 ++++++++++--------- .../src/components/FileListWithViewer.tsx | 6 ++--- web/apps/photos/src/pages/gallery.tsx | 2 +- web/apps/photos/src/pages/shared-albums.tsx | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 940c25f5fa..61473c288e 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -171,7 +171,11 @@ export interface FileListProps { * This behaviour is used when showing magic search results. */ disableGrouping?: boolean; - selectable?: boolean; + /** + * If `true`, then the user can select files in the listing by clicking on + * their thumbnails (and other range selection mechanisms). + */ + enableSelect?: boolean; setSelected: ( selected: SelectedState | ((selected: SelectedState) => SelectedState), ) => void; @@ -215,7 +219,7 @@ export const FileList: React.FC = ({ user, annotatedFiles, disableGrouping, - selectable, + enableSelect, selected, setSelected, activeCollectionID, @@ -559,9 +563,8 @@ export const FileList: React.FC = ({ return ( = ({ onChangeSelectAllCheckBox, onItemClick, rangeStartIndex, - selectable, + enableSelect, selected, user, ], @@ -877,7 +880,6 @@ const FileListRow = memo( type FileThumbnailProps = { file: EnteFile; - selectable: boolean; selected: boolean; isRangeSelectActive: boolean; selectOnClick: boolean; @@ -889,12 +891,12 @@ type FileThumbnailProps = { onSelect: (checked: boolean) => void; onHover: () => void; onRangeSelect: () => void; -} & Pick; +} & Pick; const FileThumbnail: React.FC = ({ file, user, - selectable, + enableSelect, selected, selectOnClick, isRangeSelectActive, @@ -983,9 +985,9 @@ const FileThumbnail: React.FC = ({ onClick={handleClick} onMouseEnter={handleHover} disabled={!imageURL} - {...(selectable && longPressHandlers)} + {...(enableSelect && longPressHandlers)} > - {selectable && ( + {enableSelect && ( = ({ files, enableDownload, disableGrouping, - selectable, + enableSelect, selected, setSelected, activeCollectionID, @@ -188,7 +188,7 @@ export const FileListWithViewer: React.FC = ({ footer, user, disableGrouping, - selectable, + enableSelect, selected, setSelected, activeCollectionID, diff --git a/web/apps/photos/src/pages/gallery.tsx b/web/apps/photos/src/pages/gallery.tsx index bfd47be17a..635b9c303d 100644 --- a/web/apps/photos/src/pages/gallery.tsx +++ b/web/apps/photos/src/pages/gallery.tsx @@ -1166,7 +1166,7 @@ const Page: React.FC = () => { files={filteredFiles} enableDownload={true} disableGrouping={state.searchSuggestion?.type == "clip"} - selectable={true} + enableSelect={true} selected={selected} setSelected={setSelected} // TODO: Incorrect assertion, need to update the type diff --git a/web/apps/photos/src/pages/shared-albums.tsx b/web/apps/photos/src/pages/shared-albums.tsx index b366b64378..a1c6450d6a 100644 --- a/web/apps/photos/src/pages/shared-albums.tsx +++ b/web/apps/photos/src/pages/shared-albums.tsx @@ -499,7 +499,7 @@ export default function PublicCollectionGallery() { header={fileListHeader} footer={fileListFooter} enableDownload={downloadEnabled} - selectable={downloadEnabled} + enableSelect={downloadEnabled} selected={selected} setSelected={setSelected} activeCollectionID={PseudoCollectionID.all} From ec532ad2ac235521ecaeac47875b010702e15cf3 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 17 Jul 2025 10:37:02 +0530 Subject: [PATCH 47/81] New pathway --- web/apps/photos/src/components/FileList.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 61473c288e..f00acdb2b6 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -84,6 +84,18 @@ type FileListItem = { * behaviour. */ tag?: "date" | "file" | "span"; + /** + * Groups of items that are shown in the row. + * + * Each group spans multiple columns (the number of columns being given by + * the length of {@link annotatedFiles} or the {@link span}). Groups are + * separated by gaps. + */ + fGroups?: { + annotatedFiles: FileListAnnotatedFile[]; + annotatedFilesStartIndex: number; + }[]; + dGroups?: { date: string; span: number }[]; items?: FileListAnnotatedFile[]; itemStartIndex?: number; date?: string | null; @@ -319,10 +331,11 @@ export const FileList: React.FC = ({ }); } } + if (!isSmallerLayout) { + items = mergeRowsWherePossible(items, columns); + } } - if (!isSmallerLayout) items = mergeRowsWherePossible(items, columns); - if (!annotatedFiles.length) { items.push({ height: height - 48, From c95d3b8c0079c2a9b7e274c9e5f5d9706febd825 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 17 Jul 2025 11:09:38 +0530 Subject: [PATCH 48/81] Fgroups take 1 --- web/apps/photos/src/components/FileList.tsx | 148 ++++++++++++++++++-- 1 file changed, 134 insertions(+), 14 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index f00acdb2b6..132c518e5d 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -26,6 +26,7 @@ import { type ThumbnailGridLayoutParams, } from "ente-new/photos/components/utils/thumbnail-grid-layout"; import { PseudoCollectionID } from "ente-new/photos/services/collection-summary"; +import { batch } from "ente-utils/array"; import { t } from "i18next"; import React, { memo, @@ -92,10 +93,26 @@ type FileListItem = { * separated by gaps. */ fGroups?: { + /** + * The annotated files in this group. + */ annotatedFiles: FileListAnnotatedFile[]; + /** + * The index of the first annotated file in the component's global list + * of annotated files. + */ annotatedFilesStartIndex: number; }[]; - dGroups?: { date: string; span: number }[]; + dGroups?: { + /** + * The date string to show. + */ + date: string; + /** + * The number of columns to span. + */ + dateSpan: number; + }[]; items?: FileListAnnotatedFile[]; itemStartIndex?: number; date?: string | null; @@ -277,21 +294,20 @@ export const FileList: React.FC = ({ const { isSmallerLayout, columns } = layoutParams; const fileItemHeight = layoutParams.itemHeight + layoutParams.gap; if (disableGrouping) { - let listItemIndex = columns; - for (const [index, af] of annotatedFiles.entries()) { - if (listItemIndex < columns) { - items[items.length - 1]!.items!.push(af); - listItemIndex++; - } else { - listItemIndex = 1; - items.push({ + items = items.concat( + batch(annotatedFiles, columns).map( + (batchFiles, batchIndex) => ({ height: fileItemHeight, tag: "file", - items: [af], - itemStartIndex: index, - }); - } - } + fGroups: [ + { + annotatedFiles: batchFiles, + annotatedFilesStartIndex: batchIndex * columns, + }, + ], + }), + ), + ); } else { let listItemIndex = 0; let lastCreationTime: number | undefined; @@ -571,6 +587,107 @@ export const FileList: React.FC = ({ ); case "file": { + if (listItem.fGroups) { + return listItem.fGroups + .map( + ( + { + annotatedFiles, + annotatedFilesStartIndex, + }, + i, + ) => [ + ...annotatedFiles.map( + (annotatedFile, j) => { + const file = annotatedFile.file; + const index = + annotatedFilesStartIndex + j; + return ( + 0 + } + isRangeSelectActive={ + isShiftKeyPressed && + selected.count > 0 + } + isInSelectRange={ + rangeStartIndex !== + undefined && + hoverIndex !== + undefined && + ((index >= + rangeStartIndex && + index <= + hoverIndex) || + (index >= + hoverIndex && + index <= + rangeStartIndex)) + } + activeCollectionID={ + activeCollectionID + } + showPlaceholder={ + isScrolling + } + isFav={ + !!favoriteFileIDs?.has( + file.id, + ) + } + onClick={() => + onItemClick(index) + } + onSelect={handleSelect( + file, + index, + )} + onHover={() => + setHoverIndex(index) + } + onRangeSelect={() => + handleRangeSelect(index) + } + /> + ); + }, + ), +
, + ], + ) + .flat(); + } const ret = listItem.items!.map(({ file }, i) => { const index = listItem.itemStartIndex! + i; return ( @@ -668,6 +785,9 @@ export const FileList: React.FC = ({ case "date": return `${item.date ?? ""}-${index}`; case "file": + if (item.fGroups) { + return `file-group-${item.fGroups[0]!.annotatedFilesStartIndex}`; + } return `${item.items![0]!.file.id}-${ item.items!.slice(-1)[0]!.file.id }`; From d67dc4b76fae6f9136814674bcda976b2601ac9b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 17 Jul 2025 20:11:43 +0530 Subject: [PATCH 49/81] grouping take 2 - wip --- web/apps/photos/src/components/FileList.tsx | 122 +++++++++++++------- 1 file changed, 82 insertions(+), 40 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 132c518e5d..07ff92236d 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -309,47 +309,31 @@ export const FileList: React.FC = ({ ), ); } else { - let listItemIndex = 0; - let lastCreationTime: number | undefined; - for (const [index, af] of annotatedFiles.entries()) { - const creationTime = fileCreationTime(af.file) / 1000; - if ( - !lastCreationTime || - !isSameDay( - new Date(creationTime), - new Date(lastCreationTime), - ) - ) { - lastCreationTime = creationTime; - - items.push({ - height: dateListItemHeight, - tag: "date", - date: af.timelineDateString, - }); - items.push({ - height: fileItemHeight, - tag: "file", - items: [af], - itemStartIndex: index, - }); - listItemIndex = 1; - } else if (listItemIndex < columns) { - items[items.length - 1]!.items!.push(af); - listItemIndex++; - } else { - listItemIndex = 1; - items.push({ - height: fileItemHeight, - tag: "file", - items: [af], - itemStartIndex: index, - }); - } - } - if (!isSmallerLayout) { - items = mergeRowsWherePossible(items, columns); + let i = 0; + for (const split of splitByDate(annotatedFiles)) { + items.push({ + height: dateListItemHeight, + tag: "date", + dGroups: [ + { + date: split[0]!.timelineDateString, + dateSpan: split.length, + }, + ], + }); + items.push({ + height: fileItemHeight, + tag: "file", + fGroups: [ + { annotatedFiles: split, annotatedFilesStartIndex: i }, + ], + }); + i += split.length; } + // TODO(RE): + // if (!isSmallerLayout) { + // items = mergeRowsWherePossible(items, columns); + // } } if (!annotatedFiles.length) { @@ -540,6 +524,38 @@ export const FileList: React.FC = ({ const haveSelection = selected.count > 0; switch (listItem.tag) { case "date": + if (listItem.dGroups) { + return intersperseWithGaps( + listItem.dGroups, + ({ date, dateSpan }) => ( + + {haveSelection && ( + + onChangeSelectAllCheckBox(date) + } + size="small" + sx={{ pl: 0 }} + /> + )} + {date} + + ), + ({ date }) =>
, + ); + } return listItem.dates ? ( listItem.dates .map((item) => [ @@ -833,6 +849,22 @@ export const FileList: React.FC = ({ ); }; +/** + * Return a new array of splits, each split containing {@link annotatedFiles} + * which have the same {@link timelineDateString}. + */ +const splitByDate = (annotatedFiles: FileListAnnotatedFile[]) => + annotatedFiles.reduce( + (splits, annotatedFile) => ( + splits.at(-1)?.at(0)?.timelineDateString == + annotatedFile.timelineDateString + ? splits.at(-1)?.push(annotatedFile) + : splits.push([annotatedFile]), + splits + ), + new Array(), + ); + /** * Merge multiple dates into a single row. */ @@ -913,6 +945,16 @@ const mergeRowsWherePossible = ( return newList; }; +/** + * For each element of {@link xs}, obtain an element by applying {@link f}, + * then obtain a gap element by applying {@link g}. Return a flattened array + * containing all of these, except the trailing gap. + */ +const intersperseWithGaps = (xs: T[], f: (x: T) => U, g: (x: T) => U) => { + const ys = xs.map((x) => [f(x), g(x)]).flat(); + return ys.slice(0, ys.length - 1); +}; + /** * A list item container that spans the full width. */ From b6d797681d093ded00e676e7c1b60e1e34786839 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 17 Jul 2025 20:42:41 +0530 Subject: [PATCH 50/81] wip 2 --- web/apps/photos/src/components/FileList.tsx | 360 ++++++-------------- 1 file changed, 113 insertions(+), 247 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 07ff92236d..a84df68b57 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -7,12 +7,11 @@ import Avatar from "components/Avatar"; import type { LocalUser } from "ente-accounts/services/user"; import { assertionFailed } from "ente-base/assert"; import { Overlay } from "ente-base/components/containers"; -import { isSameDay } from "ente-base/date"; import { formattedDateRelative } from "ente-base/i18n-date"; import log from "ente-base/log"; import { downloadManager } from "ente-gallery/services/download"; import type { EnteFile } from "ente-media/file"; -import { fileCreationTime, fileDurationString } from "ente-media/file-metadata"; +import { fileDurationString } from "ente-media/file-metadata"; import { FileType } from "ente-media/file-type"; import { GAP_BTW_TILES } from "ente-new/photos/components/FileList"; import type { GalleryBarMode } from "ente-new/photos/components/gallery/reducer"; @@ -321,13 +320,20 @@ export const FileList: React.FC = ({ }, ], }); - items.push({ - height: fileItemHeight, - tag: "file", - fGroups: [ - { annotatedFiles: split, annotatedFilesStartIndex: i }, - ], - }); + + items = items.concat( + batch(split, columns).map((batchFiles, batchIndex) => ({ + height: fileItemHeight, + tag: "file", + fGroups: [ + { + annotatedFiles: batchFiles, + annotatedFilesStartIndex: + i + batchIndex * columns, + }, + ], + })), + ); i += split.length; } // TODO(RE): @@ -524,243 +530,99 @@ export const FileList: React.FC = ({ const haveSelection = selected.count > 0; switch (listItem.tag) { case "date": - if (listItem.dGroups) { - return intersperseWithGaps( - listItem.dGroups, - ({ date, dateSpan }) => ( - - {haveSelection && ( - - onChangeSelectAllCheckBox(date) - } - size="small" - sx={{ pl: 0 }} - /> - )} - {date} - - ), - ({ date }) =>
, - ); - } - return listItem.dates ? ( - listItem.dates - .map((item) => [ - - {haveSelection && ( - - onChangeSelectAllCheckBox( - item.date, - ) - } - size="small" - sx={{ pl: 0 }} - /> - )} - {item.date} - , -
, - ]) - .flat() - ) : ( - - {haveSelection && ( - - onChangeSelectAllCheckBox( - listItem.date!, - ) - } - size="small" - sx={{ pl: 0 }} - /> - )} - {listItem.date} - + return intersperseWithGaps( + listItem.dGroups!, + ({ date, dateSpan }) => [ + + {haveSelection && ( + + onChangeSelectAllCheckBox(date) + } + size="small" + sx={{ pl: 0 }} + /> + )} + {date} + , + ], + ({ date }) =>
, ); - case "file": { - if (listItem.fGroups) { - return listItem.fGroups - .map( - ( - { - annotatedFiles, - annotatedFilesStartIndex, - }, - i, - ) => [ - ...annotatedFiles.map( - (annotatedFile, j) => { - const file = annotatedFile.file; - const index = - annotatedFilesStartIndex + j; - return ( - 0 - } - isRangeSelectActive={ - isShiftKeyPressed && - selected.count > 0 - } - isInSelectRange={ - rangeStartIndex !== - undefined && - hoverIndex !== - undefined && - ((index >= - rangeStartIndex && - index <= - hoverIndex) || - (index >= - hoverIndex && - index <= - rangeStartIndex)) - } - activeCollectionID={ - activeCollectionID - } - showPlaceholder={ - isScrolling - } - isFav={ - !!favoriteFileIDs?.has( - file.id, - ) - } - onClick={() => - onItemClick(index) - } - onSelect={handleSelect( - file, - index, - )} - onHover={() => - setHoverIndex(index) - } - onRangeSelect={() => - handleRangeSelect(index) - } - /> - ); - }, - ), -
, - ], - ) - .flat(); - } - const ret = listItem.items!.map(({ file }, i) => { - const index = listItem.itemStartIndex! + i; - return ( - 0} - isRangeSelectActive={ - isShiftKeyPressed && selected.count > 0 - } - isInSelectRange={ - rangeStartIndex !== undefined && - hoverIndex !== undefined && - ((index >= rangeStartIndex && - index <= hoverIndex) || - (index >= hoverIndex && - index <= rangeStartIndex)) - } - activeCollectionID={activeCollectionID} - showPlaceholder={isScrolling} - isFav={!!favoriteFileIDs?.has(file.id)} - onClick={() => onItemClick(index)} - onSelect={handleSelect(file, index)} - onHover={() => setHoverIndex(index)} - onRangeSelect={() => handleRangeSelect(index)} + case "file": + return intersperseWithGaps( + listItem.fGroups!, + ({ annotatedFiles, annotatedFilesStartIndex }) => + annotatedFiles.map((annotatedFile, j) => { + const file = annotatedFile.file; + const index = annotatedFilesStartIndex + j; + return ( + 0} + isRangeSelectActive={ + isShiftKeyPressed && + selected.count > 0 + } + isInSelectRange={ + rangeStartIndex !== undefined && + hoverIndex !== undefined && + ((index >= rangeStartIndex && + index <= hoverIndex) || + (index >= hoverIndex && + index <= rangeStartIndex)) + } + activeCollectionID={activeCollectionID} + showPlaceholder={isScrolling} + isFav={!!favoriteFileIDs?.has(file.id)} + onClick={() => onItemClick(index)} + onSelect={handleSelect(file, index)} + onHover={() => setHoverIndex(index)} + onRangeSelect={() => + handleRangeSelect(index) + } + /> + ); + }), + ({ annotatedFilesStartIndex }) => ( +
- ); - }); - if (listItem.groups) { - let sum = 0; - for (let i = 0; i < listItem.groups.length - 1; i++) { - sum = sum + listItem.groups[i]!; - ret.splice( - sum, - 0, -
, - ); - sum += 1; - } - } - return ret; - } + ), + ); default: return listItem.component; } @@ -946,12 +808,16 @@ const mergeRowsWherePossible = ( }; /** - * For each element of {@link xs}, obtain an element by applying {@link f}, + * For each element of {@link xs}, obtain an array by applying {@link f}, * then obtain a gap element by applying {@link g}. Return a flattened array * containing all of these, except the trailing gap. */ -const intersperseWithGaps = (xs: T[], f: (x: T) => U, g: (x: T) => U) => { - const ys = xs.map((x) => [f(x), g(x)]).flat(); +const intersperseWithGaps = ( + xs: T[], + f: (x: T) => U[], + g: (x: T) => U, +) => { + const ys = xs.map((x) => [...f(x), g(x)]).flat(); return ys.slice(0, ys.length - 1); }; From 291368f7ba56ce0b584357eff5430fd42b85c34e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 17 Jul 2025 21:27:04 +0530 Subject: [PATCH 51/81] merge wip rework take 1 --- web/apps/photos/src/components/FileList.tsx | 124 +++++++++----------- 1 file changed, 53 insertions(+), 71 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index a84df68b57..0393350d0b 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -320,7 +320,6 @@ export const FileList: React.FC = ({ }, ], }); - items = items.concat( batch(split, columns).map((batchFiles, batchIndex) => ({ height: fileItemHeight, @@ -336,10 +335,9 @@ export const FileList: React.FC = ({ ); i += split.length; } - // TODO(RE): - // if (!isSmallerLayout) { - // items = mergeRowsWherePossible(items, columns); - // } + if (!isSmallerLayout) { + items = mergeRowsWherePossible(items, columns); + } } if (!annotatedFiles.length) { @@ -734,77 +732,61 @@ const mergeRowsWherePossible = ( items: FileListItem[], columns: number, ): FileListItem[] => { - const newList: FileListItem[] = []; - let index = 0; - let newIndex = 0; - while (index < items.length) { - const currItem = items[index]!; - // If the current item is of type time, then it is not part of an ongoing date. - // So, there is a possibility of merge. - if (currItem.tag == "date") { - // If new list pointer is not at the end of list then - // we can add more items to the same list. - if (newList[newIndex]) { - const SPACE_BTW_DATES_TO_IMAGE_CONTAINER_WIDTH_RATIO = 0.244; - // Check if items can be added to same list - if ( - newList[newIndex + 1]!.items!.length + - items[index + 1]!.items!.length + - Math.ceil( - newList[newIndex]!.dates!.length * - SPACE_BTW_DATES_TO_IMAGE_CONTAINER_WIDTH_RATIO, - ) <= - columns - ) { - newList[newIndex]!.dates!.push({ - date: currItem.date!, - span: items[index + 1]!.items!.length, - }); - newList[newIndex + 1]!.items = [ - ...newList[newIndex + 1]!.items!, - ...items[index + 1]!.items!, - ]; - index += 2; - } else { - // Adding items would exceed the number of columns. - // So, move new list pointer to the end. Hence, in next iteration, - // items will be added to a new list. - newIndex += 2; - } + const result: FileListItem[] = []; + let i = 0; + let j = 0; + while (i < items.length) { + const item = items[i]!; + if (i.tag !== "date") { + // Pass everything else through unchanged. + result.push(item); + i++; + j = result.length; + continue; + } + + // Current item is a date. It will be necessarily followed by one (or + // more) file items. There is a possibility of a merge. + const nextItem = items[i + 1]!; + + // If new list pointer is not at the end of list then + // we can add more items to the same list. + if (result[j]) { + const spaceBetweenDatesToImageContainerWidthRatio = 0.244; + const filledColumns = result[j + 1]!.fGroups!.reduce( + (a, g) => a + g.annotatedFiles.length, + 0, + ); + const incomingColumns = + items[i + 1]!.fGroups![0]?.annotatedFiles.length; + + // Check if items can be added to same list + if ( + filledColumns + + incomingColumns + + Math.ceil( + result[j]!.dGroups!.length * + spaceBetweenDatesToImageContainerWidthRatio, + ) <= + columns + ) { + result[j]!.dGroups!.push(item.dGroups![0]!); + result[j + 1]!.fGroups!.push(nextItem.fGroups![0]!); + i += 2; } else { - // New list pointer was at the end of list so simply add new items to the list. - newList.push({ - ...currItem, - date: null, - dates: [ - { - date: currItem.date!, - span: items[index + 1]!.items!.length, - }, - ], - }); - newList.push(items[index + 1]!); - index += 2; + // Adding items would exceed the number of columns. + // So, move new list pointer to the end. Hence, in next iteration, + // items will be added to a new list. + j += 2; } } else { - // Merge cannot happen. Simply add all items to new list - // and set new list point to the end of list. - newList.push(currItem); - index++; - newIndex = newList.length; + // New list pointer was at the end of list so simply add new items to the list. + result.push(item); + result.push(nextItem); + i += 2; } } - for (let i = 0; i < newList.length; i++) { - const currItem = newList[i]!; - const nextItem = newList[i + 1]!; - if (currItem.tag == "date") { - if (currItem.dates!.length > 1) { - currItem.groups = currItem.dates!.map((item) => item.span); - nextItem.groups = currItem.groups; - } - } - } - return newList; + return result; }; /** From 164da10772dd5b1bf926b42052908475972ac643 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 18 Jul 2025 06:51:18 +0530 Subject: [PATCH 52/81] Update merge logic for new schema - wip --- web/apps/photos/src/components/FileList.tsx | 151 +++++++++----------- 1 file changed, 66 insertions(+), 85 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 0393350d0b..23d2c00372 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -309,35 +309,80 @@ export const FileList: React.FC = ({ ); } else { let i = 0; - for (const split of splitByDate(annotatedFiles)) { + const pushItemsFromSplits = (splits: FileListAnnotatedFile[][]) => { items.push({ height: dateListItemHeight, tag: "date", - dGroups: [ - { - date: split[0]!.timelineDateString, - dateSpan: split.length, - }, - ], + dGroups: splits.map((s) => ({ + date: s[0]!.timelineDateString, + dateSpan: s.length, + })), }); - items = items.concat( - batch(split, columns).map((batchFiles, batchIndex) => ({ + if (splits.length > 1) { + // If we get here, the combined number of files across + // `thisRowSplits` is less than the number of columns. + items.push({ height: fileItemHeight, tag: "file", - fGroups: [ - { - annotatedFiles: batchFiles, - annotatedFilesStartIndex: - i + batchIndex * columns, - }, - ], - })), + fGroups: splits.map((s) => { + const group = { + annotatedFiles: s, + annotatedFilesStartIndex: i, + }; + i += s.length; + return group; + }), + }); + } else { + // A single group of files, but the number of such files + // might be more than what fits a single row. + const split = splits[0]!; + items = items.concat( + batch(split, columns).map((batchFiles, batchIndex) => ({ + height: fileItemHeight, + tag: "file", + fGroups: [ + { + annotatedFiles: batchFiles, + annotatedFilesStartIndex: + i + batchIndex * columns, + }, + ], + })), + ); + i += split.length; + } + }; + + const spaceBetweenDatesToImageContainerWidthRatio = 0.244; + + let thisRowSplits = new Array(); + for (const split of splitByDate(annotatedFiles)) { + const filledColumns = thisRowSplits.reduce( + (a, s) => a + s.length, + 0, ); - i += split.length; - } - if (!isSmallerLayout) { - items = mergeRowsWherePossible(items, columns); + const incomingColumns = split.length; + + // Check if items can be added to same list. + if ( + !isSmallerLayout && + filledColumns + + incomingColumns + + Math.ceil( + thisRowSplits.length * + spaceBetweenDatesToImageContainerWidthRatio, + ) <= + columns + ) { + thisRowSplits.push(split); + continue; + } + + if (thisRowSplits.length) pushItemsFromSplits(thisRowSplits); + thisRowSplits = [split]; } + pushItemsFromSplits(thisRowSplits); } if (!annotatedFiles.length) { @@ -725,70 +770,6 @@ const splitByDate = (annotatedFiles: FileListAnnotatedFile[]) => new Array(), ); -/** - * Merge multiple dates into a single row. - */ -const mergeRowsWherePossible = ( - items: FileListItem[], - columns: number, -): FileListItem[] => { - const result: FileListItem[] = []; - let i = 0; - let j = 0; - while (i < items.length) { - const item = items[i]!; - if (i.tag !== "date") { - // Pass everything else through unchanged. - result.push(item); - i++; - j = result.length; - continue; - } - - // Current item is a date. It will be necessarily followed by one (or - // more) file items. There is a possibility of a merge. - const nextItem = items[i + 1]!; - - // If new list pointer is not at the end of list then - // we can add more items to the same list. - if (result[j]) { - const spaceBetweenDatesToImageContainerWidthRatio = 0.244; - const filledColumns = result[j + 1]!.fGroups!.reduce( - (a, g) => a + g.annotatedFiles.length, - 0, - ); - const incomingColumns = - items[i + 1]!.fGroups![0]?.annotatedFiles.length; - - // Check if items can be added to same list - if ( - filledColumns + - incomingColumns + - Math.ceil( - result[j]!.dGroups!.length * - spaceBetweenDatesToImageContainerWidthRatio, - ) <= - columns - ) { - result[j]!.dGroups!.push(item.dGroups![0]!); - result[j + 1]!.fGroups!.push(nextItem.fGroups![0]!); - i += 2; - } else { - // Adding items would exceed the number of columns. - // So, move new list pointer to the end. Hence, in next iteration, - // items will be added to a new list. - j += 2; - } - } else { - // New list pointer was at the end of list so simply add new items to the list. - result.push(item); - result.push(nextItem); - i += 2; - } - } - return result; -}; - /** * For each element of {@link xs}, obtain an array by applying {@link f}, * then obtain a gap element by applying {@link g}. Return a flattened array From aa48543a983f97b6d30b89deaba97bcef42f58f5 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 18 Jul 2025 07:03:20 +0530 Subject: [PATCH 53/81] Adapt existing code --- web/apps/photos/src/components/FileList.tsx | 129 ++++++++++---------- 1 file changed, 63 insertions(+), 66 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 23d2c00372..a08a8de97f 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -308,81 +308,84 @@ export const FileList: React.FC = ({ ), ); } else { - let i = 0; + // A running counter of files that have been pushed into items, and + // a function to push them (incrementing the counter). + let fileIndex = 0; + const createFileItem = (splits: FileListAnnotatedFile[][]) => + ({ + height: fileItemHeight, + tag: "file", + fGroups: splits.map((split) => { + const group = { + annotatedFiles: split, + annotatedFilesStartIndex: fileIndex, + }; + fileIndex += split.length; + return group; + }), + }) satisfies FileListItem; + const pushItemsFromSplits = (splits: FileListAnnotatedFile[][]) => { - items.push({ - height: dateListItemHeight, - tag: "date", - dGroups: splits.map((s) => ({ - date: s[0]!.timelineDateString, - dateSpan: s.length, - })), - }); if (splits.length > 1) { // If we get here, the combined number of files across - // `thisRowSplits` is less than the number of columns. + // splits is less than the number of columns. items.push({ - height: fileItemHeight, - tag: "file", - fGroups: splits.map((s) => { - const group = { - annotatedFiles: s, - annotatedFilesStartIndex: i, - }; - i += s.length; - return group; - }), + height: dateListItemHeight, + tag: "date", + dGroups: splits.map((s) => ({ + date: s[0]!.timelineDateString, + dateSpan: s.length, + })), }); + items.push(createFileItem(splits)); } else { // A single group of files, but the number of such files // might be more than what fits a single row. - const split = splits[0]!; - items = items.concat( - batch(split, columns).map((batchFiles, batchIndex) => ({ - height: fileItemHeight, - tag: "file", - fGroups: [ - { - annotatedFiles: batchFiles, - annotatedFilesStartIndex: - i + batchIndex * columns, - }, - ], + items.push({ + height: dateListItemHeight, + tag: "date", + dGroups: splits.map((s) => ({ + date: s[0]!.timelineDateString, + dateSpan: columns, })), + }); + items = items.concat( + batch(splits[0]!, columns).map((batchFiles) => + createFileItem([batchFiles]), + ), ); - i += split.length; } }; const spaceBetweenDatesToImageContainerWidthRatio = 0.244; - let thisRowSplits = new Array(); + let pendingSplits = new Array(); for (const split of splitByDate(annotatedFiles)) { - const filledColumns = thisRowSplits.reduce( + const filledColumns = pendingSplits.reduce( (a, s) => a + s.length, 0, ); const incomingColumns = split.length; - // Check if items can be added to same list. + // Check if the files in this split can be added to same row. if ( !isSmallerLayout && filledColumns + incomingColumns + Math.ceil( - thisRowSplits.length * + pendingSplits.length * spaceBetweenDatesToImageContainerWidthRatio, ) <= columns ) { - thisRowSplits.push(split); + pendingSplits.push(split); continue; } - if (thisRowSplits.length) pushItemsFromSplits(thisRowSplits); - thisRowSplits = [split]; + if (pendingSplits.length) pushItemsFromSplits(pendingSplits); + pendingSplits = [split]; } - pushItemsFromSplits(thisRowSplits); + pushItemsFromSplits(pendingSplits); } if (!annotatedFiles.length) { @@ -576,14 +579,7 @@ export const FileList: React.FC = ({ return intersperseWithGaps( listItem.dGroups!, ({ date, dateSpan }) => [ - + {haveSelection && ( = ({ ); }), ({ annotatedFilesStartIndex }) => ( -
+
), ); default: @@ -704,16 +698,11 @@ export const FileList: React.FC = ({ const item = itemData.items[index]!; switch (item.tag) { case "date": - return `${item.date ?? ""}-${index}`; + return `date-${item.dGroups![0]!.date}-${index}`; case "file": - if (item.fGroups) { - return `file-group-${item.fGroups[0]!.annotatedFilesStartIndex}`; - } - return `${item.items![0]!.file.id}-${ - item.items!.slice(-1)[0]!.file.id - }`; + return `file-${item.fGroups![0]!.annotatedFilesStartIndex}-${index}`; default: - return `${index}`; + return `span-${index}`; } }, []); @@ -855,6 +844,16 @@ const FileListRow = memo( const { columns, itemWidth, paddingInline, gap } = layoutParams; const item = items[index]!; + const itemSpans = (() => { + switch (item.tag) { + case "date": + return item.dGroups!.map((g) => g.dateSpan); + case "file": + return item.fGroups!.map((g) => g.annotatedFiles.length); + default: + return []; + } + })(); return ( 0 && { display: "grid", - gridTemplateColumns: item.groups - ? item.groups - .map((x) => `repeat(${x}, ${itemWidth}px)`) - .join(" 44px ") - : `repeat(${columns}, ${itemWidth}px)`, + gridTemplateColumns: itemSpans + .map((x) => `repeat(${x}, ${itemWidth}px)`) + .join(" 44px "), columnGap: `${gap}px`, }, ]} From b5868468bd7dba23eed02c77d5100ac00ae915b1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 18 Jul 2025 08:07:28 +0530 Subject: [PATCH 54/81] Cleanup --- web/apps/photos/src/components/FileList.tsx | 23 ++++++++------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index a08a8de97f..aa3a61c2e0 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -385,7 +385,7 @@ export const FileList: React.FC = ({ if (pendingSplits.length) pushItemsFromSplits(pendingSplits); pendingSplits = [split]; } - pushItemsFromSplits(pendingSplits); + if (pendingSplits.length) pushItemsFromSplits(pendingSplits); } if (!annotatedFiles.length) { @@ -568,16 +568,12 @@ export const FileList: React.FC = ({ }, [selected]); const renderListItem = useCallback( - ( - listItem: FileListItem, - layoutParams: ThumbnailGridLayoutParams, - isScrolling: boolean, - ) => { + (item: FileListItem, isScrolling: boolean) => { const haveSelection = selected.count > 0; - switch (listItem.tag) { + switch (item.tag) { case "date": return intersperseWithGaps( - listItem.dGroups!, + item.dGroups!, ({ date, dateSpan }) => [ {haveSelection && ( @@ -601,7 +597,7 @@ export const FileList: React.FC = ({ ); case "file": return intersperseWithGaps( - listItem.fGroups!, + item.fGroups!, ({ annotatedFiles, annotatedFilesStartIndex }) => annotatedFiles.map((annotatedFile, j) => { const file = annotatedFile.file; @@ -661,7 +657,7 @@ export const FileList: React.FC = ({ ), ); default: - return listItem.component; + return item.component; } }, [ @@ -827,8 +823,7 @@ interface FileListItemData { items: FileListItem[]; layoutParams: ThumbnailGridLayoutParams; renderListItem: ( - listItem: FileListItem, - layoutParams: ThumbnailGridLayoutParams, + item: FileListItem, isScrolling: boolean, ) => React.ReactNode; } @@ -841,7 +836,7 @@ const FileListRow = memo( data, }: ListChildComponentProps) => { const { items, layoutParams, renderListItem } = data; - const { columns, itemWidth, paddingInline, gap } = layoutParams; + const { itemWidth, paddingInline, gap } = layoutParams; const item = items[index]!; const itemSpans = (() => { @@ -872,7 +867,7 @@ const FileListRow = memo( }, ]} > - {renderListItem(item, layoutParams, !!isScrolling)} + {renderListItem(item, !!isScrolling)} ); }, From 943a524ba9ab135905dfc8e1a255f118910b08ed Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 18 Jul 2025 15:22:36 +0530 Subject: [PATCH 55/81] Rename --- web/apps/photos/src/components/FileList.tsx | 4 +- .../new/photos/components/FileList.ts | 6 --- .../new/photos/components/gallery/BarImpl.tsx | 10 ++--- .../components/utils/thumbnail-grid-layout.ts | 38 ++++++++----------- 4 files changed, 23 insertions(+), 35 deletions(-) delete mode 100644 web/packages/new/photos/components/FileList.ts diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index aa3a61c2e0..400f125027 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -13,7 +13,6 @@ import { downloadManager } from "ente-gallery/services/download"; import type { EnteFile } from "ente-media/file"; import { fileDurationString } from "ente-media/file-metadata"; import { FileType } from "ente-media/file-type"; -import { GAP_BTW_TILES } from "ente-new/photos/components/FileList"; import type { GalleryBarMode } from "ente-new/photos/components/gallery/reducer"; import { LoadingThumbnail, @@ -22,6 +21,7 @@ import { import { TileBottomTextOverlay } from "ente-new/photos/components/Tiles"; import { computeThumbnailGridLayoutParams, + thumbnailGap, type ThumbnailGridLayoutParams, } from "ente-new/photos/components/utils/thumbnail-grid-layout"; import { PseudoCollectionID } from "ente-new/photos/services/collection-summary"; @@ -1040,7 +1040,7 @@ const FileThumbnail: React.FC = ({ const FileThumbnail_ = styled("div")<{ disabled: boolean }>` display: flex; width: fit-content; - margin-bottom: ${GAP_BTW_TILES}px; + margin-bottom: ${thumbnailGap}px; min-width: 100%; overflow: hidden; position: relative; diff --git a/web/packages/new/photos/components/FileList.ts b/web/packages/new/photos/components/FileList.ts deleted file mode 100644 index ce96218dad..0000000000 --- a/web/packages/new/photos/components/FileList.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const GAP_BTW_TILES = 4; -export const IMAGE_CONTAINER_MAX_HEIGHT = 180; -export const IMAGE_CONTAINER_MAX_WIDTH = 180; -export const MIN_COLUMNS = 4; - -// TODO: Move the FileList component here. diff --git a/web/packages/new/photos/components/gallery/BarImpl.tsx b/web/packages/new/photos/components/gallery/BarImpl.tsx index 757032f998..e7d6928f73 100644 --- a/web/packages/new/photos/components/gallery/BarImpl.tsx +++ b/web/packages/new/photos/components/gallery/BarImpl.tsx @@ -11,16 +11,16 @@ import { FilledIconButton } from "ente-base/components/mui"; import { Ellipsized2LineTypography } from "ente-base/components/Typography"; import { useIsSmallWidth } from "ente-base/components/utils/hooks"; import { CollectionsSortOptions } from "ente-new/photos/components/CollectionsSortOptions"; -import { - IMAGE_CONTAINER_MAX_WIDTH, - MIN_COLUMNS, -} from "ente-new/photos/components/FileList"; import { BarItemTile, ItemCard, TileTextOverlay, } from "ente-new/photos/components/Tiles"; import { FocusVisibleUnstyledButton } from "ente-new/photos/components/UnstyledButton"; +import { + thumbnailLayoutMinColumns, + thumbnailMaxWidth, +} from "ente-new/photos/components/utils/thumbnail-grid-layout"; import type { CollectionSummary, CollectionSummaryAttribute, @@ -300,7 +300,7 @@ export const GalleryBarImpl: React.FC = ({ const BarWrapper = styled("div")` padding-inline: 24px; - @media (max-width: ${IMAGE_CONTAINER_MAX_WIDTH * MIN_COLUMNS}px) { + @media (max-width: ${thumbnailMaxWidth * thumbnailLayoutMinColumns}px) { padding-inline: 4px; } margin-block-end: 16px; diff --git a/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts b/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts index 58f6f12612..5ab7f7935e 100644 --- a/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts +++ b/web/packages/new/photos/components/utils/thumbnail-grid-layout.ts @@ -1,3 +1,8 @@ +export const thumbnailGap = 4; +export const thumbnailMaxHeight = 180; +export const thumbnailMaxWidth = 180; +export const thumbnailLayoutMinColumns = 4; + export interface ThumbnailGridLayoutParams { /** * The overall width available to us. @@ -47,20 +52,20 @@ export const computeThumbnailGridLayoutParams = ( ): ThumbnailGridLayoutParams => { const isSmallerLayout = !( containerWidth > - MIN_COLUMNS * IMAGE_CONTAINER_MAX_WIDTH + thumbnailLayoutMinColumns * thumbnailMaxWidth ); const paddingInline = getGapFromScreenEdge(containerWidth); const fittableColumns = getFractionFittableColumns(containerWidth); let columns = Math.floor(fittableColumns); - if (columns < MIN_COLUMNS) { - columns = MIN_COLUMNS; + if (columns < thumbnailLayoutMinColumns) { + columns = thumbnailLayoutMinColumns; } const shrinkRatio = getShrinkRatio(containerWidth, columns); - const itemHeight = IMAGE_CONTAINER_MAX_HEIGHT * shrinkRatio; - const itemWidth = IMAGE_CONTAINER_MAX_WIDTH * shrinkRatio; - const gap = GAP_BTW_TILES; + const itemHeight = thumbnailMaxHeight * shrinkRatio; + const itemWidth = thumbnailMaxWidth * shrinkRatio; + const gap = thumbnailGap; return { containerWidth, @@ -73,24 +78,13 @@ export const computeThumbnailGridLayoutParams = ( }; }; -/* TODO: Some of this code is also duplicated elsewhere. See if those places can - reuse the same function as above, with some extra params if needed. - - So that the duplication is easier to identify, keeping the duplication - verbatim for now */ - -const GAP_BTW_TILES = 4; -const IMAGE_CONTAINER_MAX_HEIGHT = 180; -const IMAGE_CONTAINER_MAX_WIDTH = 180; -const MIN_COLUMNS = 4; - const getFractionFittableColumns = (width: number): number => - (width - 2 * getGapFromScreenEdge(width) + GAP_BTW_TILES) / - (IMAGE_CONTAINER_MAX_WIDTH + GAP_BTW_TILES); + (width - 2 * getGapFromScreenEdge(width) + thumbnailGap) / + (thumbnailMaxWidth + thumbnailGap); const getGapFromScreenEdge = (width: number) => - width > MIN_COLUMNS * IMAGE_CONTAINER_MAX_WIDTH ? 24 : 4; + width > thumbnailLayoutMinColumns * thumbnailMaxWidth ? 24 : 4; const getShrinkRatio = (width: number, columns: number) => - (width - 2 * getGapFromScreenEdge(width) - (columns - 1) * GAP_BTW_TILES) / - (columns * IMAGE_CONTAINER_MAX_WIDTH); + (width - 2 * getGapFromScreenEdge(width) - (columns - 1) * thumbnailGap) / + (columns * thumbnailMaxWidth); From 8a177bbe2c45c96b318ff3367b0f1ba9bf7760bc Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 18 Jul 2025 15:44:35 +0530 Subject: [PATCH 56/81] Cleanup --- web/apps/photos/src/components/FileList.tsx | 32 +++++++-------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 400f125027..3d5d382a7a 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -1,4 +1,3 @@ -// TODO: Audit this file import AlbumOutlinedIcon from "@mui/icons-material/AlbumOutlined"; import FavoriteRoundedIcon from "@mui/icons-material/FavoriteRounded"; import PlayCircleOutlineOutlinedIcon from "@mui/icons-material/PlayCircleOutlineOutlined"; @@ -79,11 +78,7 @@ type FileListItem = { * The height of the row that will render this item. */ height: number; - /** - * An optional tag that can be used to identify item types for conditional - * behaviour. - */ - tag?: "date" | "file" | "span"; + type: "date" | "file" | "span"; /** * Groups of items that are shown in the row. * @@ -112,11 +107,6 @@ type FileListItem = { */ dateSpan: number; }[]; - items?: FileListAnnotatedFile[]; - itemStartIndex?: number; - date?: string | null; - dates?: { date: string; span: number }[]; - groups?: number[]; /** * The React component that is the rendered representation of the item. */ @@ -297,7 +287,7 @@ export const FileList: React.FC = ({ batch(annotatedFiles, columns).map( (batchFiles, batchIndex) => ({ height: fileItemHeight, - tag: "file", + type: "file", fGroups: [ { annotatedFiles: batchFiles, @@ -314,7 +304,7 @@ export const FileList: React.FC = ({ const createFileItem = (splits: FileListAnnotatedFile[][]) => ({ height: fileItemHeight, - tag: "file", + type: "file", fGroups: splits.map((split) => { const group = { annotatedFiles: split, @@ -331,7 +321,7 @@ export const FileList: React.FC = ({ // splits is less than the number of columns. items.push({ height: dateListItemHeight, - tag: "date", + type: "date", dGroups: splits.map((s) => ({ date: s[0]!.timelineDateString, dateSpan: s.length, @@ -343,7 +333,7 @@ export const FileList: React.FC = ({ // might be more than what fits a single row. items.push({ height: dateListItemHeight, - tag: "date", + type: "date", dGroups: splits.map((s) => ({ date: s[0]!.timelineDateString, dateSpan: columns, @@ -391,7 +381,7 @@ export const FileList: React.FC = ({ if (!annotatedFiles.length) { items.push({ height: height - 48, - tag: "span", + type: "span", component: ( @@ -410,7 +400,7 @@ export const FileList: React.FC = ({ if (leftoverHeight > 0) { items.push({ height: leftoverHeight, - tag: "span", + type: "span", component: <>, }); } @@ -570,7 +560,7 @@ export const FileList: React.FC = ({ const renderListItem = useCallback( (item: FileListItem, isScrolling: boolean) => { const haveSelection = selected.count > 0; - switch (item.tag) { + switch (item.type) { case "date": return intersperseWithGaps( item.dGroups!, @@ -692,7 +682,7 @@ export const FileList: React.FC = ({ const itemKey = useCallback((index: number, itemData: FileListItemData) => { const item = itemData.items[index]!; - switch (item.tag) { + switch (item.type) { case "date": return `date-${item.dGroups![0]!.date}-${index}`; case "file": @@ -791,7 +781,7 @@ const asFullSpanFileListItem = ({ ...rest }: FileListHeaderOrFooter): FileListItem => ({ ...rest, - tag: "span", + type: "span", component: {component}, }); @@ -840,7 +830,7 @@ const FileListRow = memo( const item = items[index]!; const itemSpans = (() => { - switch (item.tag) { + switch (item.type) { case "date": return item.dGroups!.map((g) => g.dateSpan); case "file": From 69237fa6593b2a37327b92b7c30c536a49071975 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Fri, 18 Jul 2025 10:41:50 +0000 Subject: [PATCH 57/81] New Crowdin translations by GitHub Action --- .../metadata/android/ms/full_description.txt | 36 +++ .../metadata/android/ms/short_description.txt | 1 + .../fastlane/metadata/android/ms/title.txt | 1 + .../fastlane/metadata/ios/ms/description.txt | 33 ++ .../fastlane/metadata/ios/ms/keywords.txt | 1 + .../photos/fastlane/metadata/ios/ms/name.txt | 1 + .../fastlane/metadata/ios/ms/subtitle.txt | 1 + .../fastlane/metadata/ios/vi/description.txt | 12 +- .../playstore/ms/full_description.txt | 30 ++ .../playstore/ms/short_description.txt | 1 + .../fastlane/metadata/playstore/ms/title.txt | 1 + mobile/apps/photos/lib/l10n/intl_ar.arb | 38 +-- mobile/apps/photos/lib/l10n/intl_cs.arb | 74 +++++ mobile/apps/photos/lib/l10n/intl_de.arb | 4 +- mobile/apps/photos/lib/l10n/intl_es.arb | 67 +++- mobile/apps/photos/lib/l10n/intl_fr.arb | 16 +- mobile/apps/photos/lib/l10n/intl_he.arb | 8 +- mobile/apps/photos/lib/l10n/intl_hu.arb | 5 +- mobile/apps/photos/lib/l10n/intl_it.arb | 20 +- mobile/apps/photos/lib/l10n/intl_ja.arb | 8 +- mobile/apps/photos/lib/l10n/intl_lt.arb | 10 +- mobile/apps/photos/lib/l10n/intl_ms.arb | 3 + mobile/apps/photos/lib/l10n/intl_nl.arb | 4 +- mobile/apps/photos/lib/l10n/intl_no.arb | 4 +- mobile/apps/photos/lib/l10n/intl_pl.arb | 187 +++++++++++- mobile/apps/photos/lib/l10n/intl_pt_BR.arb | 4 +- mobile/apps/photos/lib/l10n/intl_pt_PT.arb | 10 +- mobile/apps/photos/lib/l10n/intl_ro.arb | 14 +- mobile/apps/photos/lib/l10n/intl_ru.arb | 4 +- mobile/apps/photos/lib/l10n/intl_sr.arb | 289 +++++++++++++++++- mobile/apps/photos/lib/l10n/intl_sv.arb | 8 +- mobile/apps/photos/lib/l10n/intl_tr.arb | 76 ++++- mobile/apps/photos/lib/l10n/intl_uk.arb | 6 +- mobile/apps/photos/lib/l10n/intl_vi.arb | 128 ++++---- mobile/apps/photos/lib/l10n/intl_zh.arb | 6 +- 35 files changed, 941 insertions(+), 170 deletions(-) create mode 100644 mobile/apps/photos/fastlane/metadata/android/ms/full_description.txt create mode 100644 mobile/apps/photos/fastlane/metadata/android/ms/short_description.txt create mode 100644 mobile/apps/photos/fastlane/metadata/android/ms/title.txt create mode 100644 mobile/apps/photos/fastlane/metadata/ios/ms/description.txt create mode 100644 mobile/apps/photos/fastlane/metadata/ios/ms/keywords.txt create mode 100644 mobile/apps/photos/fastlane/metadata/ios/ms/name.txt create mode 100644 mobile/apps/photos/fastlane/metadata/ios/ms/subtitle.txt create mode 100644 mobile/apps/photos/fastlane/metadata/playstore/ms/full_description.txt create mode 100644 mobile/apps/photos/fastlane/metadata/playstore/ms/short_description.txt create mode 100644 mobile/apps/photos/fastlane/metadata/playstore/ms/title.txt create mode 100644 mobile/apps/photos/lib/l10n/intl_ms.arb diff --git a/mobile/apps/photos/fastlane/metadata/android/ms/full_description.txt b/mobile/apps/photos/fastlane/metadata/android/ms/full_description.txt new file mode 100644 index 0000000000..9ba4fe3143 --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/android/ms/full_description.txt @@ -0,0 +1,36 @@ +ente is a simple app to backup and share your photos and videos. + +If you've been looking for a privacy-friendly alternative to Google Photos, you've come to the right place. With ente, they are stored end-to-end encrypted (e2ee). This means that only you can view them. + +We have open-source apps across Android, iOS, web and desktop, and your photos will seamlessly sync between all of them in an end-to-end encrypted (e2ee) manner. + +ente also makes it simple to share your albums with your loved ones, even if they aren't on ente. You can share publicly viewable links, where they can view your album and collaborate by adding photos to it, even without an account or app. + +Your encrypted data is replicated to 3 different locations, including a fall-out shelter in Paris. We take posterity seriously and make it easy to ensure that your memories outlive you. + +We are here to make the safest photos app ever, come join our journey! + +FEATURES +- Original quality backups, because every pixel is important +- Family plans, so you can share storage with your family +- Collaborative albums, so you can pool together photos after a trip +- Shared folders, in case you want your partner to enjoy your "Camera" clicks +- Album links, that can be protected with a password +- Ability to free up space, by removing files that have been safely backed up +- Human support, because you're worth it +- Descriptions, so you can caption your memories and find them easily +- Image editor, to add finishing touches +- Favorite, hide and relive your memories, for they are precious +- One-click import from Google, Apple, your hard drive and more +- Dark theme, because your photos look good in it +- 2FA, 3FA, biometric auth +- and a LOT more! + +PERMISSIONS +ente requests for certain permissions to serve the purpose of a photo storage provider, which can be reviewed here: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md + +PRICING +We don't offer forever free plans, because it is important to us that we remain sustainable and withstand the test of time. Instead we offer affordable plans that you can freely share with your family. You can find more information at ente.io. + +SUPPORT +We take pride in offering human support. If you are our paid customer, you can reach out to team@ente.io and expect a response from our team within 24 hours. diff --git a/mobile/apps/photos/fastlane/metadata/android/ms/short_description.txt b/mobile/apps/photos/fastlane/metadata/android/ms/short_description.txt new file mode 100644 index 0000000000..7a5fe973db --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/android/ms/short_description.txt @@ -0,0 +1 @@ +ente is an end-to-end encrypted photo storage app \ No newline at end of file diff --git a/mobile/apps/photos/fastlane/metadata/android/ms/title.txt b/mobile/apps/photos/fastlane/metadata/android/ms/title.txt new file mode 100644 index 0000000000..3a4fed48fe --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/android/ms/title.txt @@ -0,0 +1 @@ +ente - encrypted photo storage \ No newline at end of file diff --git a/mobile/apps/photos/fastlane/metadata/ios/ms/description.txt b/mobile/apps/photos/fastlane/metadata/ios/ms/description.txt new file mode 100644 index 0000000000..a98a74300a --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/ios/ms/description.txt @@ -0,0 +1,33 @@ +Ente is a simple app to automatically backup and organize your photos and videos. + +If you've been looking for a privacy-friendly alternative to preserve your memories, you've come to the right place. With Ente, they are stored end-to-end encrypted (e2ee). This means that only you can view them. + +We have apps across all platforms, and your photos will seamlessly sync between all your devices in an end-to-end encrypted (e2ee) manner. + +Ente also makes it simple to share your albums with your loved ones. You can either share them directly with other Ente users, end-to-end encrypted; or with publicly viewable links. + +Your encrypted data is stored across multiple locations, including a fall-out shelter in Paris. We take posterity seriously and make it easy to ensure that your memories outlive you. + +We are here to make the safest photos app ever, come join our journey! + +FEATURES +- Original quality backups, because every pixel is important +- Family plans, so you can share storage with your family +- Shared folders, in case you want your partner to enjoy your "Camera" clicks +- Album links, that can be protected with a password and set to expire +- Ability to free up space, by removing files that have been safely backed up +- Image editor, to add finishing touches +- Favorite, hide and relive your memories, for they are precious +- One-click import from all major storage providers +- Dark theme, because your photos look good in it +- 2FA, 3FA, biometric auth +- and a LOT more! + +PRICING +We don't offer forever free plans, because it is important to us that we remain sustainable and withstand the test of time. Instead we offer affordable plans that you can freely share with your family. You can find more information at ente.io. + +SUPPORT +We take pride in offering human support. If you are our paid customer, you can reach out to team@ente.io and expect a response from our team within 24 hours. + +TERMS +https://ente.io/terms diff --git a/mobile/apps/photos/fastlane/metadata/ios/ms/keywords.txt b/mobile/apps/photos/fastlane/metadata/ios/ms/keywords.txt new file mode 100644 index 0000000000..e1462baf51 --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/ios/ms/keywords.txt @@ -0,0 +1 @@ +photos,photography,family,privacy,cloud,backup,videos,photo,encryption,storage,album,alternative diff --git a/mobile/apps/photos/fastlane/metadata/ios/ms/name.txt b/mobile/apps/photos/fastlane/metadata/ios/ms/name.txt new file mode 100644 index 0000000000..3a991c4abc --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/ios/ms/name.txt @@ -0,0 +1 @@ +Ente Photos diff --git a/mobile/apps/photos/fastlane/metadata/ios/ms/subtitle.txt b/mobile/apps/photos/fastlane/metadata/ios/ms/subtitle.txt new file mode 100644 index 0000000000..958a35f1c9 --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/ios/ms/subtitle.txt @@ -0,0 +1 @@ +Encrypted photo storage diff --git a/mobile/apps/photos/fastlane/metadata/ios/vi/description.txt b/mobile/apps/photos/fastlane/metadata/ios/vi/description.txt index 38d80ff195..dc504b2d2d 100644 --- a/mobile/apps/photos/fastlane/metadata/ios/vi/description.txt +++ b/mobile/apps/photos/fastlane/metadata/ios/vi/description.txt @@ -1,4 +1,4 @@ -Ente là một ứng dụng đơn giản để sao lưu và sắp xếp ảnh/video của bạn. +Ente là ứng dụng đơn giản tự động sao lưu và sắp xếp ảnh/video của bạn. Nếu bạn đang tìm kiếm một giải pháp bảo mật-thân thiện để lưu giữ những kỷ niệm của mình, bạn đã tìm đúng. Ở Ente, chúng tôi lưu trữ mã hóa đầu cuối (e2ee). Điều này nghĩa là chỉ bạn mới có thể xem. @@ -8,26 +8,26 @@ Ente cũng giúp bạn dễ dàng chia sẻ album của mình với những ngư Dữ liệu mã hóa của bạn được lưu trữ ở nhiều địa điểm khác nhau, bao gồm một hầm trú ẩn hạt nhân ở Paris. Chúng tôi coi trọng sự trường tồn và giúp việc đảm bảo rằng những kỷ niệm của bạn sống lâu hơn bạn trở nên dễ dàng. -Chúng tôi ở đây để tạo ra ứng dụng ảnh an toàn nhất từ trước đến nay, hãy tham gia hành trình của chúng tôi! +Chúng tôi tạo ra ứng dụng ảnh an toàn nhất từ trước đến nay, hãy tham gia hành trình của chúng tôi! TÍNH NĂNG - Sao lưu chất lượng gốc, vì mỗi pixel đều quan trọng -- Gói gia đình, để bạn có thể chia sẻ dung lượng lưu trữ với gia đình +- Gói gia đình, để bạn có thể chia sẻ dung lượng lưu trữ với các thành viên - Thư mục chia sẻ, trong trường hợp bạn muốn đối tác của mình thưởng thức những bức ảnh "Camera" của bạn - Liên kết album, có thể bảo vệ bằng mật khẩu và đặt thời hạn - Khả năng giải phóng dung lượng, bằng cách xóa các tệp đã được sao lưu an toàn - Trình chỉnh sửa ảnh, để thêm những nét hoàn thiện - Thích, ẩn và khôi phục những kỷ niệm của bạn, vì chúng rất quý giá -- Một click nhập ngay từ tất cả các nhà cung cấp lưu trữ lớn +- Di chuyển ảnh/video từ các dịch vụ lưu trữ khác chỉ với một click - Chủ đề tối, vì ảnh của bạn trông đẹp trong đó - 2FA, 3FA, xác thực sinh trắc học -- và còn NHIỀU nữa! +- và nhiều hơn thế nữa! GIÁ CẢ Chúng tôi không cung cấp vĩnh viễn các gói miễn phí, vì điều quan trọng với chúng tôi là chúng tôi phải duy trì tính bền vững và chịu được thử thách của thời gian. Thay vào đó, chúng tôi cung cấp các gói giá cả phải chăng mà bạn có thể tự do chia sẻ với gia đình mình. Bạn có thể xem thêm thông tin tại ente.io. HỖ TRỢ -Chúng tôi tự hào cung cấp hỗ trợ người thật. Nếu bạn là khách hàng trả phí của chúng tôi, bạn có thể liên hệ với team@ente.io và đội ngũ của chúng tôi sẽ phản hồi trong vòng 24 giờ. +Chúng tôi tự hào với đội hỗ trợ người dùng thật. Nếu bạn là khách hàng trả phí của chúng tôi, bạn có thể liên hệ với team@ente.io và đội ngũ của chúng tôi sẽ phản hồi trong vòng 24 giờ. ĐIỀU KHOẢN https://ente.io/terms diff --git a/mobile/apps/photos/fastlane/metadata/playstore/ms/full_description.txt b/mobile/apps/photos/fastlane/metadata/playstore/ms/full_description.txt new file mode 100644 index 0000000000..ec999a783c --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/playstore/ms/full_description.txt @@ -0,0 +1,30 @@ +Ente is a simple app to automatically backup and organize your photos and videos. + +If you've been looking for a privacy-friendly alternative to preserve your memories, you've come to the right place. With Ente, they are stored end-to-end encrypted (e2ee). This means that only you can view them. + +We have apps across Android, iOS, web and Desktop, and your photos will seamlessly sync between all your devices in an end-to-end encrypted (e2ee) manner. + +Ente also makes it simple to share your albums with your loved ones. You can either share them directly with other Ente users, end-to-end encrypted; or with publicly viewable links. + +Your encrypted data is stored across multiple locations, including a fall-out shelter in Paris. We take posterity seriously and make it easy to ensure that your memories outlive you. + +We are here to make the safest photos app ever, come join our journey! + +✨ FEATURES +- Original quality backups, because every pixel is important +- Family plans, so you can share storage with your family +- Shared folders, in case you want your partner to enjoy your "Camera" clicks +- Album links, that can be protected with a password and set to expire +- Ability to free up space, by removing files that have been safely backed up +- Image editor, to add finishing touches +- Favorite, hide and relive your memories, for they are precious +- One-click import from Google, Apple, your hard drive and more +- Dark theme, because your photos look good in it +- 2FA, 3FA, biometric auth +- and a LOT more! + +💲 PRICING +We don't offer forever free plans, because it is important to us that we remain sustainable and withstand the test of time. Instead we offer affordable plans that you can freely share with your family. You can find more information at ente.io. + +🙋 SUPPORT +We take pride in offering human support. If you are our paid customer, you can reach out to team@ente.io and expect a response from our team within 24 hours. \ No newline at end of file diff --git a/mobile/apps/photos/fastlane/metadata/playstore/ms/short_description.txt b/mobile/apps/photos/fastlane/metadata/playstore/ms/short_description.txt new file mode 100644 index 0000000000..6c00229894 --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/playstore/ms/short_description.txt @@ -0,0 +1 @@ +Encrypted photo storage - backup, organize and share your photos and videos \ No newline at end of file diff --git a/mobile/apps/photos/fastlane/metadata/playstore/ms/title.txt b/mobile/apps/photos/fastlane/metadata/playstore/ms/title.txt new file mode 100644 index 0000000000..97fdef3be7 --- /dev/null +++ b/mobile/apps/photos/fastlane/metadata/playstore/ms/title.txt @@ -0,0 +1 @@ +Ente Photos \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_ar.arb b/mobile/apps/photos/lib/l10n/intl_ar.arb index cc05f76e82..a1d7713752 100644 --- a/mobile/apps/photos/lib/l10n/intl_ar.arb +++ b/mobile/apps/photos/lib/l10n/intl_ar.arb @@ -372,7 +372,7 @@ "deleteFromBoth": "الحذف من كليهما", "newAlbum": "ألبوم جديد", "albums": "الألبومات", - "memoryCount": "{count, plural, =0 {لا توجد ذكريات} one {ذكرى واحدة} two {ذكريتان} other {{formattedCount} ذكرى}}", + "memoryCount": "{count, plural, =0 {لا توجد ذكريات} one {ذكرى واحدة} two {ذكريتان} few {{formattedCount} ذكريات} many {{formattedCount} ذكرى} other {{formattedCount} ذكرى}}", "@memoryCount": { "description": "The text to display the number of memories", "type": "text", @@ -460,7 +460,7 @@ "skip": "تخط", "updatingFolderSelection": "جارٍ تحديث تحديد المجلد...", "itemCount": "{count, plural, one {{count} عُنْصُر} other {{count} عَنَاصِر}}", - "deleteItemCount": "{count, plural, =1 {حذف عنصر واحد} two {حذف عنصرين} other {حذف {count} عنصرًا}}", + "deleteItemCount": "{count, plural, =1 {حذف عنصر واحد} two {حذف عنصرين} few {حذف {count} عناصر} many {حذف {count} عنصرًا} other {حذف {count} عنصرًا}}", "duplicateItemsGroup": "{count} ملفات، {formattedSize} لكل منها", "@duplicateItemsGroup": { "description": "Display the number of duplicate files and their size", @@ -477,7 +477,7 @@ } }, "showMemories": "عرض الذكريات", - "yearsAgo": "{count, plural, one {قبل سنة} two {قبل سنتين} other {قبل {count} سنة}}", + "yearsAgo": "{count, plural, one {قبل سنة} two {قبل سنتين} few {قبل {count} سنوات} many {قبل {count} سنة} other {قبل {count} سنة}}", "backupSettings": "إعدادات النسخ الاحتياطي", "backupStatus": "حالة النسخ الاحتياطي", "backupStatusDescription": "ستظهر العناصر التي تم نسخها احتياطيًا هنا", @@ -543,7 +543,7 @@ }, "remindToEmptyEnteTrash": "تذكر أيضًا إفراغ \"سلة المهملات\" لاستعادة المساحة المحررة.", "sparkleSuccess": "✨ نجاح", - "duplicateFileCountWithStorageSaved": "لقد قمت بتنظيف {count, plural, one {ملف مكرر واحد} two {ملفين مكررين} other {{count} ملفًا مكررًا}}، مما وفر {storageSaved}!", + "duplicateFileCountWithStorageSaved": "لقد قمت بتنظيف {count, plural, one {ملف مكرر واحد} two {ملفين مكررين} few {{count} ملفات مكررة} many {{count} ملفًا مكررًا} other {{count} ملفًا مكررًا}}، مما وفر {storageSaved}!", "@duplicateFileCountWithStorageSaved": { "description": "The text to display when the user has successfully cleaned up duplicate files", "type": "text", @@ -794,11 +794,11 @@ "share": "مشاركة", "unhideToAlbum": "إظهار في الألبوم", "restoreToAlbum": "استعادة إلى الألبوم", - "moveItem": "{count, plural, =1 {نقل عنصر} two {نقل عنصرين} other {نقل {count} عنصرًا}}", + "moveItem": "{count, plural, =1 {نقل عنصر} two {نقل عنصرين} few {نقل {count} عناصر} many {نقل {count} عنصرًا} other {نقل {count} عنصرًا}}", "@moveItem": { "description": "Page title while moving one or more items to an album" }, - "addItem": "{count, plural, =1 {إضافة عنصر} two {إضافة عنصرين} other {إضافة {count} عنصرًا}}", + "addItem": "{count, plural, =1 {إضافة عنصر} two {إضافة عنصرين} few {إضافة {count} عناصر} many {إضافة {count} عنصرًا} other {إضافة {count} عنصرًا}}", "@addItem": { "description": "Page title while adding one or more items to album" }, @@ -826,7 +826,7 @@ "referFriendsAnd2xYourPlan": "أحِل الأصدقاء وضاعف خطتك مرتين", "shareAlbumHint": "افتح ألبومًا وانقر على زر المشاركة في الزاوية اليمنى العليا للمشاركة.", "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": "تعرض العناصر عدد الأيام المتبقية قبل الحذف الدائم.", - "trashDaysLeft": "{count, plural, =0 {قريبًا} =1 {يوم واحد} two {يومان} other {{count} يومًا}}", + "trashDaysLeft": "{count, plural, =0 {قريبًا} =1 {يوم واحد} two {يومان} few {{count} أيام} many {{count} يومًا} other {{count} يومًا}}", "@trashDaysLeft": { "description": "Text to indicate number of days remaining before permanent deletion", "placeholders": { @@ -899,8 +899,8 @@ "authToViewYourMemories": "يرجى المصادقة لعرض ذكرياتك.", "unlock": "فتح", "freeUpSpace": "تحرير المساحة", - "freeUpSpaceSaving": "{count, plural, =1 {يمكن حذفه من الجهاز لتحرير {formattedSize}} two {يمكن حذفهما من الجهاز لتحرير {formattedSize}} other {يمكن حذفها من الجهاز لتحرير {formattedSize}}}", - "filesBackedUpInAlbum": "{count, plural, one {ملف واحد} two {ملفان} other {{formattedNumber} ملفًا}} في هذا الألبوم تم نسخه احتياطيًا بأمان", + "freeUpSpaceSaving": "{count, plural, =1 {يمكن حذفه من الجهاز لتحرير {formattedSize}} two {يمكن حذفهما من الجهاز لتحرير {formattedSize}} few {يمكن حذفها من الجهاز لتحرير {formattedSize}} many {يمكن حذفها من الجهاز لتحرير {formattedSize}} other {يمكن حذفها من الجهاز لتحرير {formattedSize}}}", + "filesBackedUpInAlbum": "{count, plural, one {ملف واحد} two {ملفان} few {{formattedNumber} ملفات} many {{formattedNumber} ملفًا} other {{formattedNumber} ملفًا}} في هذا الألبوم تم نسخه احتياطيًا بأمان", "@filesBackedUpInAlbum": { "description": "Text to tell user how many files have been backed up in the album", "placeholders": { @@ -915,7 +915,7 @@ } } }, - "filesBackedUpFromDevice": "{count, plural, one {ملف واحد} two {ملفان} other {{formattedNumber} ملفًا}} على هذا الجهاز تم نسخه احتياطيًا بأمان", + "filesBackedUpFromDevice": "{count, plural, one {ملف واحد} two {ملفان} few {{formattedNumber} ملفات} many {{formattedNumber} ملفًا} other {{formattedNumber} ملفًا}} على هذا الجهاز تم نسخه احتياطيًا بأمان", "@filesBackedUpFromDevice": { "description": "Text to tell user how many files have been backed up from this device", "placeholders": { @@ -1217,7 +1217,7 @@ "searchHint4": "الموقع", "searchHint5": "قريبًا: الوجوه والبحث السحري ✨", "addYourPhotosNow": "أضف صورك الآن", - "searchResultCount": "{count, plural, other{{count} النتائج التي تم العثور عليها}}", + "searchResultCount": "{count, plural, one{{count} النتائج التي تم العثور عليها} other{{count} النتائج التي تم العثور عليها}}", "@searchResultCount": { "description": "Text to tell user how many results were found for their search query", "placeholders": { @@ -1269,8 +1269,8 @@ "description": "Subtitle to indicate that the user can find people quickly by name" }, "findPeopleByName": "البحث عن الأشخاص بسرعة بالاسم", - "addViewers": "{count, plural, =0 {إضافة مشاهد} =1 {إضافة مشاهد} two {إضافة مشاهدين} other {إضافة {count} مشاهدًا}}", - "addCollaborators": "{count, plural, =0 {إضافة متعاون} =1 {إضافة متعاون} two {إضافة متعاونين} other {إضافة {count} متعاونًا}}", + "addViewers": "{count, plural, =0 {إضافة مشاهد} =1 {إضافة مشاهد} two {إضافة مشاهدين} few {إضافة {count} مشاهدين} many {إضافة {count} مشاهدًا} other {إضافة {count} مشاهدًا}}", + "addCollaborators": "{count, plural, =0 {إضافة متعاون} =1 {إضافة متعاون} two {إضافة متعاونين} few {إضافة {count} متعاونين} many {إضافة {count} متعاونًا} other {إضافة {count} متعاونًا}}", "longPressAnEmailToVerifyEndToEndEncryption": "اضغط مطولاً على بريد إلكتروني للتحقق من التشفير من طرف إلى طرف.", "developerSettingsWarning": "هل أنت متأكد من رغبتك في تعديل إعدادات المطور؟", "developerSettings": "إعدادات المطور", @@ -1403,7 +1403,7 @@ "enableMachineLearningBanner": "قم بتمكين تعلم الآلة للبحث السحري والتعرف على الوجوه.", "searchDiscoverEmptySection": "سيتم عرض الصور هنا بمجرد اكتمال المعالجة والمزامنة.", "searchPersonsEmptySection": "سيتم عرض الأشخاص هنا بمجرد اكتمال المعالجة والمزامنة.", - "viewersSuccessfullyAdded": "{count, plural, =0 {تمت إضافة 0 مشاهدين} =1 {تمت إضافة مشاهد واحد} two {تمت إضافة مشاهدين} other {تمت إضافة {count} مشاهدًا}}", + "viewersSuccessfullyAdded": "{count, plural, =0 {تمت إضافة 0 مشاهدين} =1 {تمت إضافة مشاهد واحد} two {تمت إضافة مشاهدين} few {تمت إضافة {count} مشاهدين} many {تمت إضافة {count} مشاهدًا} other {تمت إضافة {count} مشاهدًا}}", "@viewersSuccessfullyAdded": { "placeholders": { "count": { @@ -1413,7 +1413,7 @@ }, "description": "Number of viewers that were successfully added to an album." }, - "collaboratorsSuccessfullyAdded": "{count, plural, =0 {تمت إضافة 0 متعاونين} =1 {تمت إضافة متعاون واحد} two {تمت إضافة متعاونين} other {تمت إضافة {count} متعاونًا}}", + "collaboratorsSuccessfullyAdded": "{count, plural, =0 {تمت إضافة 0 متعاونين} =1 {تمت إضافة متعاون واحد} two {تمت إضافة متعاونين} few {تمت إضافة {count} متعاونين} many {تمت إضافة {count} متعاونًا} other {تمت إضافة {count} متعاونًا}}", "@collaboratorsSuccessfullyAdded": { "placeholders": { "count": { @@ -1488,7 +1488,7 @@ }, "currentlyRunning": "قيد التشغيل حاليًا", "ignored": "تم التجاهل", - "photosCount": "{count, plural, =0 {لا توجد صور} =1 {صورة واحدة} two {صورتان} other {{count} صورة}}", + "photosCount": "{count, plural, =0 {لا توجد صور} =1 {صورة واحدة} two {صورتان} few {{count} صور} many {{count} صورة} other {{count} صورة}}", "@photosCount": { "placeholders": { "count": { @@ -1686,7 +1686,7 @@ "moveSelectedPhotosToOneDate": "نقل الصور المحددة إلى تاريخ واحد", "shiftDatesAndTime": "تغيير التواريخ والوقت", "photosKeepRelativeTimeDifference": "تحتفظ الصور بالفرق الزمني النسبي", - "photocountPhotos": "{count, plural, =0 {لا توجد صور} =1 {صورة واحدة} two {صورتان} other {{count} صورة}}", + "photocountPhotos": "{count, plural, =0 {لا توجد صور} =1 {صورة واحدة} two {صورتان} few {{count} صور} many {{count} صورة} other {{count} صورة}}", "@photocountPhotos": { "placeholders": { "count": { @@ -1700,7 +1700,7 @@ "selectedItemsWillBeRemovedFromThisPerson": "سيتم إزالة العناصر المحددة من هذا الشخص، ولكن لن يتم حذفها من مكتبتك.", "throughTheYears": "{dateFormat} عبر السنين", "thisWeekThroughTheYears": "هذا الأسبوع عبر السنين", - "thisWeekXYearsAgo": "{count, plural, =1 {هذا الأسبوع، قبل سنة} two {هذا الأسبوع، قبل سنتين} other {هذا الأسبوع، قبل {count} سنة}}", + "thisWeekXYearsAgo": "{count, plural, =1 {هذا الأسبوع، قبل سنة} two {هذا الأسبوع، قبل سنتين} few {هذا الأسبوع، قبل {count} سنوات} many {هذا الأسبوع، قبل {count} سنة} other {هذا الأسبوع، قبل {count} سنة}}", "youAndThem": "أنت و {name}", "admiringThem": "الإعجاب بـ {name}", "embracingThem": "معانقة {name}", @@ -1763,4 +1763,4 @@ "areYouSureYouWantToMergeThem": "هل أنت متأكد من رغبتك في دمجهم؟", "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": "سيتم دمج جميع المجموعات غير المسماة مع الشخص المحدد. يمكن التراجع عن هذا الإجراء لاحقًا من خلال نظرة عامة على سجل الاقتراحات التابع لهذا الشخص.", "yesIgnore": "نعم، تجاهل" -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_cs.arb b/mobile/apps/photos/lib/l10n/intl_cs.arb index fa046acab2..31707eba94 100644 --- a/mobile/apps/photos/lib/l10n/intl_cs.arb +++ b/mobile/apps/photos/lib/l10n/intl_cs.arb @@ -1,6 +1,7 @@ { "@@locale ": "en", "enterYourEmailAddress": "Zadejte svou e-mailovou adresu", + "enterYourNewEmailAddress": "Zadejte novou e-mailovou adresu", "accountWelcomeBack": "Vítejte zpět!", "emailAlreadyRegistered": "E-mail je již zaregistrován.", "emailNotRegistered": "E-mail není registrován.", @@ -11,8 +12,10 @@ "enterValidEmail": "Prosím, zadejte platnou e-mailovou adresu.", "deleteAccount": "Smazat účet", "askDeleteReason": "Jaký je váš hlavní důvod, proč mažete svůj účet?", + "deleteAccountFeedbackPrompt": "Je nám líto, že nás opouštíte. Prosím, dejte nám zpětnou vazbu, ať se můžeme zlepšit.", "feedback": "Zpětná vazba", "kindlyHelpUsWithThisInformation": "Pomozte nám s těmito informacemi", + "confirmDeletePrompt": "Ano, chci trvale smazat tento účet a jeho data napříč všemi aplikacemi.", "confirmAccountDeletion": "Potvrdit odstranění účtu", "deleteAccountPermanentlyButton": "Trvale smazat účet", "yourAccountHasBeenDeleted": "Váš účet byl smazán", @@ -23,12 +26,18 @@ "deleteReason4": "Můj důvod není uveden", "sendEmail": "Odeslat e-mail", "deleteRequestSLAText": "Váš požadavek bude zpracován do 72 hodin.", + "deleteEmailRequest": "Prosím, zašlete e-mail na account-deletion@ente.io ze schránky, se kterou jste se registrovali.", + "entePhotosPerm": "Ente potřebuje oprávnění k uchovávání vašich fotek", "ok": "Ok", "createAccount": "Vytvořit účet", "createNewAccount": "Vytvořit nový účet", "password": "Heslo", + "confirmPassword": "Potvrdte heslo", "activeSessions": "Aktivní relace", "oops": "Jejda", + "somethingWentWrongPleaseTryAgain": "Něco se pokazilo. Zkuste to, prosím, znovu", + "thisWillLogYouOutOfThisDevice": "Toto vás odhlásí z tohoto zařízení!", + "thisWillLogYouOutOfTheFollowingDevice": "Toto vás odhlásí z následujícího zařízení:", "terminateSession": "Ukončit relaci?", "terminate": "Ukončit", "thisDevice": "Toto zařízení", @@ -37,30 +46,95 @@ "decrypting": "Dešifrování...", "incorrectRecoveryKeyTitle": "Nesprávný obnovovací klíč", "incorrectRecoveryKeyBody": "", + "forgotPassword": "Zapomenuté heslo", "enterYourRecoveryKey": "Zadejte svůj obnovovací klíč", "noRecoveryKey": "Nemáte obnovovací klíč?", "sorry": "Omlouváme se", + "noRecoveryKeyNoDecryption": "Vzhledem k povaze našeho protokolu koncového šifrování nemohou být vaše data dešifrována bez vašeho hesla nebo obnovovacího klíče", "verifyEmail": "Ověřit e-mail", + "toResetVerifyEmail": "Pro reset vašeho hesla nejprve vyplňte vaší e-mailovou adresu prosím.", "checkInboxAndSpamFolder": "Zkontrolujte prosím svou doručenou poštu (a spam) pro dokončení ověření", + "tapToEnterCode": "Klepněte pro zadání kódu", "resendEmail": "Znovu odeslat e-mail", + "weHaveSendEmailTo": "Poslali jsme vám zprávu na {email}", + "@weHaveSendEmailTo": { + "description": "Text to indicate that we have sent a mail to the user", + "placeholders": { + "email": { + "description": "The email address of the user", + "type": "String", + "example": "example@ente.io" + } + } + }, + "setPasswordTitle": "Nastavit heslo", + "changePasswordTitle": "Změnit heslo", "resetPasswordTitle": "Obnovit heslo", "encryptionKeys": "Šifrovací klíče", + "passwordWarning": "Toto heslo neukládáme, takže pokud jej zapomenete, nemůžeme dešifrovat vaše data", + "enterPasswordToEncrypt": "Zadejte heslo, které můžeme použít k šifrování vašich dat", + "enterNewPasswordToEncrypt": "Zadejte nové heslo, které můžeme použít k šifrování vašich dat", "weakStrength": "Slabé", "strongStrength": "Silné", + "moderateStrength": "Střední", + "passwordStrength": "Síla hesla: {passwordStrengthValue}", + "@passwordStrength": { + "description": "Text to indicate the password strength", + "placeholders": { + "passwordStrengthValue": { + "description": "The strength of the password as a string", + "type": "String", + "example": "Weak or Moderate or Strong" + } + }, + "message": "Password Strength: {passwordStrengthText}" + }, "passwordChangedSuccessfully": "Heslo úspěšně změněno", "generatingEncryptionKeys": "Generování šifrovacích klíčů...", "pleaseWait": "Čekejte prosím...", "continueLabel": "Pokračovat", + "insecureDevice": "Nezabezpečené zařízení", + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Omlouváme se, nemohli jsme vygenerovat bezpečné klíče na tomto zařízení.\n\nProsíme, zaregistrujte se z jiného zařízení.", "howItWorks": "Jak to funguje", "encryption": "Šifrování", + "ackPasswordLostWarning": "Rozumím, že pokud zapomenu své heslo, mohu přijít o data, jelikož má data jsou koncově šifrována.", + "privacyPolicyTitle": "Zásady ochrany osobních údajů", + "termsOfServicesTitle": "Podmínky služby", + "signUpTerms": "Souhlasím s podmínkami služby a zásadami ochrany osobních údajů", "logInLabel": "Přihlásit se", + "loginTerms": "Kliknutím na přihlášení souhlasím s podmínkami služby a zásadami ochrany osobních údajů", "changeEmail": "Změnit e-mail", "enterYourPassword": "Zadejte své heslo", "welcomeBack": "Vítejte zpět!", "contactSupport": "Kontaktovat podporu", "incorrectPasswordTitle": "Nesprávné heslo", "pleaseTryAgain": "Zkuste to prosím znovu", + "recreatePasswordTitle": "Znovu vytvořit heslo", + "useRecoveryKey": "Použít obnovovací klíč", + "recreatePasswordBody": "Aktuální zařízení není dostatečně silné k ověření vašeho hesla, ale můžeme ho regenerovat způsobem, které funguje na všech zařízeních.\n\nProsím, přihlašte se pomocí vašeho obnovovacího klíče a regenerujte své heslo (můžete klidně znovu použít své aktuální heslo).", + "verifyPassword": "Ověřit heslo", + "recoveryKey": "Obnovovací klíč", + "recoveryKeyOnForgotPassword": "Tento klíč je jedinou cestou pro obnovení Vašich dat, pokud zapomenete heslo.", + "recoveryKeySaveDescription": "Tento 24-slovný klíč neuchováváme, uschovejte ho, prosím, na bezpečném místě.", + "doThisLater": "Udělat později", "saveKey": "Uložit klíč", + "recoveryKeyCopiedToClipboard": "Obnovovací klíč zkopírován do schránky", + "recoverAccount": "Obnovit účet", + "recover": "Obnovit", + "dropSupportEmail": "Prosíme, napiště e-mail na {supportEmail} ze schránky, kterou jste použili k registraci", + "@dropSupportEmail": { + "placeholders": { + "supportEmail": { + "description": "The support email address", + "type": "String", + "example": "support@ente.io" + } + } + }, + "twofactorSetup": "Nastavení dvoufaktorového ověřování", + "enterCode": "Zadat kód", + "scanCode": "Skenovat kód", + "codeCopiedToClipboard": "Kód zkopírován do schránky", "confirm": "Potvrdit", "lostDevice": "Ztratili jste zařízení?", "verifyingRecoveryKey": "Ověřování obnovovacího klíče...", diff --git a/mobile/apps/photos/lib/l10n/intl_de.arb b/mobile/apps/photos/lib/l10n/intl_de.arb index d824c9fa4d..28636c4b5d 100644 --- a/mobile/apps/photos/lib/l10n/intl_de.arb +++ b/mobile/apps/photos/lib/l10n/intl_de.arb @@ -1788,5 +1788,7 @@ "cLDesc5": "Du erhältst jetzt eine Opt-Out-Benachrichtigung für alle Geburtstage, die du bei Ente gespeichert hast, zusammen mit einer Sammlung der besten Fotos.", "cLTitle6": "Wiederaufnehmbares Hoch- und Herunterladen", "cLDesc6": "Kein Warten mehr auf das Hoch- oder Herunterladen, bevor du die App schließen kannst. Alle Übertragungen können jetzt mittendrin pausiert und fortgesetzt werden, wo du aufgehört hast.", - "indexingPausedStatusDescription": "Die Indizierung ist pausiert. Sie wird automatisch fortgesetzt, wenn das Gerät bereit ist. Das Gerät wird als bereit angesehen, wenn sich der Akkustand, die Akkugesundheit und der thermische Zustand in einem gesunden Bereich befinden." + "indexingPausedStatusDescription": "Die Indizierung ist pausiert. Sie wird automatisch fortgesetzt, wenn das Gerät bereit ist. Das Gerät wird als bereit angesehen, wenn sich der Akkustand, die Akkugesundheit und der thermische Zustand in einem gesunden Bereich befinden.", + "faceThumbnailGenerationFailed": "Vorschaubilder konnten nicht erstellt werden", + "fileAnalysisFailed": "Datei konnte nicht analysiert werden" } \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_es.arb b/mobile/apps/photos/lib/l10n/intl_es.arb index eb8bd29db7..d0cd66015e 100644 --- a/mobile/apps/photos/lib/l10n/intl_es.arb +++ b/mobile/apps/photos/lib/l10n/intl_es.arb @@ -1,6 +1,7 @@ { "@@locale ": "en", "enterYourEmailAddress": "Escribe tu correo electrónico", + "enterYourNewEmailAddress": "Introduce tu nueva dirección de correo electrónico", "accountWelcomeBack": "¡Bienvenido de nuevo!", "emailAlreadyRegistered": "Correo electrónico ya registrado.", "emailNotRegistered": "Correo electrónico no registrado.", @@ -721,6 +722,7 @@ "type": "text" }, "backupFailed": "La copia de seguridad ha fallado", + "sorryBackupFailedDesc": "Lo sentimos, no hemos podido hacer una copia de seguridad de este archivo, lo intentaremos más tarde.", "couldNotBackUpTryLater": "No pudimos hacer una copia de seguridad de tus datos.\nVolveremos a intentarlo más tarde.", "enteCanEncryptAndPreserveFilesOnlyIfYouGrant": "Ente puede cifrar y preservar archivos solo si concedes acceso a ellos", "pleaseGrantPermissions": "Por favor, concede permiso", @@ -1029,6 +1031,7 @@ "didYouKnow": "¿Sabías que?", "loadingMessage": "Cargando tus fotos...", "loadMessage1": "Puedes compartir tu suscripción con tu familia", + "loadMessage2": "Hasta ahora hemos conservado más de 200 millones de recuerdos", "loadMessage3": "Guardamos 3 copias de tus datos, una en un refugio subterráneo", "loadMessage4": "Todas nuestras aplicaciones son de código abierto", "loadMessage5": "Nuestro código fuente y criptografía han sido auditados externamente", @@ -1279,6 +1282,8 @@ "createCollaborativeLink": "Crear enlace colaborativo", "search": "Buscar", "enterPersonName": "Ingresar el nombre de una persona", + "editEmailAlreadyLinked": "Este correo electrónico ya está vinculado a {name}.", + "viewPersonToUnlink": "Ver {name} para desvincular", "enterName": "Introducir nombre", "savePerson": "Guardar persona", "editPerson": "Editar persona", @@ -1657,6 +1662,7 @@ "@linkPersonCaption": { "description": "Caption for the 'Link person' title. It should be a continuation of the 'Link person' title. Just like how 'Link person' + 'for better sharing experience' forms a proper sentence in English, the combination of these two strings should also be a proper sentence in other languages." }, + "videoStreaming": "Vídeos en streaming", "processingVideos": "Procesando vídeos", "streamDetails": "Detalles de la transmisión", "processing": "Procesando", @@ -1723,5 +1729,64 @@ "onTheRoad": "De nuevo en la carretera", "food": "Delicia culinaria", "pets": "Compañeros peludos", - "curatedMemories": "Memorias revisadas" + "curatedMemories": "Memorias revisadas", + "widgets": "Widgets", + "memories": "Recuerdos", + "peopleWidgetDesc": "Selecciona las personas que deseas ver en tu pantalla de inicio.", + "albumsWidgetDesc": "Seleccione los álbumes que desea ver en su pantalla de inicio.", + "memoriesWidgetDesc": "Seleccione el tipo de recuerdos que desea ver en su pantalla de inicio.", + "smartMemories": "Recuerdos inteligentes", + "pastYearsMemories": "Recuerdos de los últimos años", + "deleteMultipleAlbumDialog": "¿Quiere borrar también las fotos (y vídeos) presentes en estos {count} álbumes de todos los otros álbumes de los que forman parte?", + "addParticipants": "Añadir participantes", + "selectedAlbums": "{count} seleccionados", + "actionNotSupportedOnFavouritesAlbum": "Acción no compatible con el álbum de Favoritos", + "onThisDayMemories": "Recuerdos de un día como hoy", + "onThisDay": "Un día como hoy", + "lookBackOnYourMemories": "Revisa tus recuerdos 🌄", + "newPhotosEmoji": " nuevo 📸", + "sorryWeHadToPauseYourBackups": "Lo sentimos, tuvimos que pausar tus copias de seguridad", + "clickToInstallOurBestVersionYet": "Haz clic para instalar nuestra mejor versión hasta la fecha", + "onThisDayNotificationExplanation": "Recibe recordatorios sobre recuerdos de este día en años anteriores.", + "addMemoriesWidgetPrompt": "Añade un widget de recuerdos a tu pantalla de inicio y vuelve aquí para personalizarlo.", + "addAlbumWidgetPrompt": "Añade un widget de álbum a tu pantalla de inicio y vuelve aquí para personalizarlo.", + "addPeopleWidgetPrompt": "Añade un widget de personas a tu pantalla de inicio y vuelve aquí para personalizarlo.", + "birthdayNotifications": "Notificaciones de cumpleaños", + "receiveRemindersOnBirthdays": "Recibe recordatorios cuando es el cumpleaños de alguien. Pulsar en la notificación te llevará a las fotos de la persona que cumple años.", + "happyBirthday": "¡Feliz cumpleaños! 🥳", + "birthdays": "Cumpleaños", + "wishThemAHappyBirthday": "¡Desea a {name} un cumpleaños feliz! 🎉", + "areYouSureRemoveThisFaceFromPerson": "¿Estás seguro de que quieres eliminar esta cara de esta persona?", + "otherDetectedFaces": "Otras caras detectadas", + "areThey": "¿Son ellos", + "questionmark": "?", + "saveAsAnotherPerson": "Guardar como otra persona", + "showLessFaces": "Mostrar menos caras", + "showMoreFaces": "Mostrar más caras", + "ignore": "Ignorar", + "merge": "Combinar", + "reset": "Restablecer", + "areYouSureYouWantToIgnoreThisPerson": "¿Estás seguro de que quieres ignorar a esta persona?", + "areYouSureYouWantToIgnoreThesePersons": "¿Estás seguro de que quieres ignorar a estas personas?", + "thePersonGroupsWillNotBeDisplayed": "Los grupos de personas ya no se mostrarán en la sección de personas. Las fotos permanecerán intactas.", + "thePersonWillNotBeDisplayed": "La persona ya no se mostrará en la sección de personas. Las fotos permanecerán intactas.", + "areYouSureYouWantToMergeThem": "¿Estás seguro de que quieres combinarlas?", + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": "Todos los grupos sin nombre se combinarán en la persona seleccionada. Esto puede deshacerse desde el historial de sugerencias de la persona.", + "yesIgnore": "Sí, ignorar", + "same": "Igual", + "different": "Diferente", + "sameperson": "la misma persona?", + "cLTitle1": "Subiendo archivos de vídeo grandes", + "cLDesc1": "Dado el trabajo que hemos hecho en la versión beta de vídeos en streaming y en las cargas y descargas reanudables, hemos aumentado el límite de subida de archivos a 10 GB. Esto ya está disponible tanto en la aplicación de escritorio como en la móvil.", + "cLTitle2": "Subida en segundo plano", + "cLDesc2": "Las subidas en segundo plano ya están también soportadas en iOS, además de los dispositivos Android. No es necesario abrir la aplicación para hacer una copia de seguridad de tus fotos y vídeos más recientes.", + "cLTitle3": "Reproducción automática de recuerdos", + "cLDesc3": "Hemos hecho mejoras significativas en nuestra experiencia de recuerdos, incluyendo la reproducción automática, el deslizado a la memoria siguiente y mucho más.", + "cLTitle4": "Reconocimiento facial mejorado", + "cLDesc4": "Junto con un montón de mejoras adicionales, ahora es mucho más fácil ver todas las caras detectadas, proporcionar comentarios sobre caras similares, y añadir o quitar caras de una sola foto.", + "cLTitle5": "Notificación de cumpleaños", + "cLDesc5": "Ahora recibirás una notificación de exclusión voluntaria para todos los cumpleaños que hayas guardado en Ente, junto con una colección de sus mejores fotos.", + "cLTitle6": "Subidas y Descargas reanudables", + "cLDesc6": "Ya no tienes que esperar a que las subidas o descargas se completen para cerrar la aplicación. Ahora, todas las subidas y descargas se pueden pausar a mitad de proceso y reanudarse justo donde lo dejaste.", + "indexingPausedStatusDescription": "La indexación está pausada. Se reanudará automáticamente cuando el dispositivo esté listo. El dispositivo se considera listo cuando su nivel de batería, la salud de la batería y temperatura están en un rango saludable." } \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_fr.arb b/mobile/apps/photos/lib/l10n/intl_fr.arb index cb0534273e..b8d3c2b85a 100644 --- a/mobile/apps/photos/lib/l10n/intl_fr.arb +++ b/mobile/apps/photos/lib/l10n/intl_fr.arb @@ -899,7 +899,7 @@ "authToViewYourMemories": "Authentifiez-vous pour voir vos souvenirs", "unlock": "Déverrouiller", "freeUpSpace": "Libérer de l'espace", - "freeUpSpaceSaving": "{count, plural, =1 {Il peut être supprimé de l'appareil pour libérer {formattedSize}} other {Ils peuvent être supprimés de l'appareil pour libérer {formattedSize}}}", + "freeUpSpaceSaving": "{count, plural, one {}=1 {Il peut être supprimé de l'appareil pour libérer {formattedSize}} other {Ils peuvent être supprimés de l'appareil pour libérer {formattedSize}}}", "filesBackedUpInAlbum": "{count, plural, one {1 fichier dans cet album a été sauvegardé en toute sécurité} other {{formattedNumber} fichiers dans cet album ont été sauvegardés en toute sécurité}}", "@filesBackedUpInAlbum": { "description": "Text to tell user how many files have been backed up in the album", @@ -933,7 +933,7 @@ "@freeUpSpaceSaving": { "description": "Text to tell user how much space they can free up by deleting items from the device" }, - "freeUpAccessPostDelete": "Vous pouvez toujours {count, plural, =1 {l'} other {les}} accéder sur Ente tant que vous avez un abonnement actif", + "freeUpAccessPostDelete": "Vous pouvez toujours {count, plural, one {}=1 {l'} other {les}} accéder sur Ente tant que vous avez un abonnement actif", "@freeUpAccessPostDelete": { "placeholders": { "count": { @@ -1269,8 +1269,8 @@ "description": "Subtitle to indicate that the user can find people quickly by name" }, "findPeopleByName": "Trouver des personnes rapidement par leur nom", - "addViewers": "{count, plural, =0 {Ajouter un spectateur} =1 {Ajouter une spectateur} other {Ajouter des spectateurs}}", - "addCollaborators": "{count, plural, =0 {Ajouter un collaborateur} =1 {Ajouter un collaborateur} other {Ajouter des collaborateurs}}", + "addViewers": "{count, plural, one {}=0 {Ajouter un spectateur} =1 {Ajouter une spectateur} other {Ajouter des spectateurs}}", + "addCollaborators": "{count, plural, one {}=0 {Ajouter un collaborateur} =1 {Ajouter un collaborateur} other {Ajouter des collaborateurs}}", "longPressAnEmailToVerifyEndToEndEncryption": "Appuyez longuement sur un email pour vérifier le chiffrement de bout en bout.", "developerSettingsWarning": "Êtes-vous sûr de vouloir modifier les paramètres du développeur ?", "developerSettings": "Paramètres du développeur", @@ -1403,7 +1403,7 @@ "enableMachineLearningBanner": "Activer l'apprentissage automatique pour la reconnaissance des visages et la recherche magique", "searchDiscoverEmptySection": "Les images seront affichées ici une fois le traitement terminé", "searchPersonsEmptySection": "Les personnes seront affichées ici une fois le traitement terminé", - "viewersSuccessfullyAdded": "{count, plural, =0 {0 spectateur ajouté} =1 {Un spectateur ajouté} other {{count} spectateurs ajoutés}}", + "viewersSuccessfullyAdded": "{count, plural, one {}=0 {0 spectateur ajouté} =1 {Un spectateur ajouté} other {{count} spectateurs ajoutés}}", "@viewersSuccessfullyAdded": { "placeholders": { "count": { @@ -1788,5 +1788,7 @@ "cLDesc5": "Vous recevrez maintenant une notification de désinscription pour tous les anniversaires que vous avez enregistrés sur Ente, ainsi qu'une collection de leurs meilleures photos.", "cLTitle6": "Reprise des chargements et téléchargements", "cLDesc6": "Plus besoin d'attendre la fin des chargements/téléchargements avant de pouvoir fermer l'application. Tous peuvent maintenant être mis en pause en cours de route et reprendre à partir de là où ça s'est arrêté.", - "indexingPausedStatusDescription": "L'indexation est en pause. Elle reprendra automatiquement lorsque l'appareil sera prêt. Celui-ci est considéré comme prêt lorsque le niveau de batterie, sa santé et son état thermique sont dans une plage saine." -} + "indexingPausedStatusDescription": "L'indexation est en pause. Elle reprendra automatiquement lorsque l'appareil sera prêt. Celui-ci est considéré comme prêt lorsque le niveau de batterie, sa santé et son état thermique sont dans une plage saine.", + "faceThumbnailGenerationFailed": "Impossible de créer des miniatures de visage", + "fileAnalysisFailed": "Impossible d'analyser le fichier" +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_he.arb b/mobile/apps/photos/lib/l10n/intl_he.arb index ffa0137a25..c4232070a8 100644 --- a/mobile/apps/photos/lib/l10n/intl_he.arb +++ b/mobile/apps/photos/lib/l10n/intl_he.arb @@ -389,8 +389,8 @@ "selectAll": "בחר הכל", "skip": "דלג", "updatingFolderSelection": "מעדכן את בחירת התיקיות...", - "itemCount": "{count, plural, one{{count} פריט} other{{count} פריטים}}", - "deleteItemCount": "{count, plural, =1 {מחק {count} פריט} other {מחק {count} פריטים}}", + "itemCount": "{count, plural, one{{count} פריט} two {{count} פריטים} many {{count} פריטים} other{{count} פריטים}}", + "deleteItemCount": "{count, plural, =1 {מחק {count} פריט} two {מחק {count} פריטים} other {מחק {count} פריטים}}", "duplicateItemsGroup": "{count} קבצים, כל אחד {formattedSize}", "@duplicateItemsGroup": { "description": "Display the number of duplicate files and their size", @@ -407,7 +407,7 @@ } }, "showMemories": "הצג זכרונות", - "yearsAgo": "{count, plural, one{לפני {count} שנה} other{לפני {count} שנים}}", + "yearsAgo": "{count, plural, one{לפני {count} שנה} two {לפני {count} שנים} many {לפני {count} שנים} other{לפני {count} שנים}}", "backupSettings": "הגדרות גיבוי", "backupOverMobileData": "גבה על רשת סלולרית", "backupVideos": "גבה סרטונים", @@ -792,4 +792,4 @@ "create": "צור", "viewAll": "הצג הכל", "hiding": "מחביא..." -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_hu.arb b/mobile/apps/photos/lib/l10n/intl_hu.arb index 52a08cae0e..009e2e1325 100644 --- a/mobile/apps/photos/lib/l10n/intl_hu.arb +++ b/mobile/apps/photos/lib/l10n/intl_hu.arb @@ -264,7 +264,6 @@ } }, "verificationId": "Ellenőrző azonosító", - "verifyEmailID": "{email} ellenőrzése", "emailNoEnteAccount": "{email} címnek nincs Ente fiókja.\n\nKüldjön nekik meghívót fotók megosztására.", "shareMyVerificationID": "Itt az ellenőrző azonosítóm: {verificationID} az ente.io-hoz.", "shareTextConfirmOthersVerificationID": "Szia, meg tudnád erősíteni, hogy ez az ente.io ellenőrző azonosítód? {verificationID}", @@ -459,7 +458,7 @@ "selectAll": "Összes kijelölése", "skip": "Kihagyás", "updatingFolderSelection": "Mappakijelölés frissítése...", - "itemCount": "{count, plural, other{{count} elem}}", + "itemCount": "{count, plural, one{{count} elem} other{{count} elem}}", "deleteItemCount": "{count, plural, =1 {Elem {count} törlése} other {Elemek {count} törlése}}", "duplicateItemsGroup": "{count} fájl, {formattedSize} mindegyik", "@duplicateItemsGroup": { @@ -542,4 +541,4 @@ } }, "remindToEmptyEnteTrash": "Ürítsd ki a \"Kukát\" is, hogy visszaszerezd a felszabadult helyet." -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_it.arb b/mobile/apps/photos/lib/l10n/intl_it.arb index 379cfffa24..771094c3d8 100644 --- a/mobile/apps/photos/lib/l10n/intl_it.arb +++ b/mobile/apps/photos/lib/l10n/intl_it.arb @@ -794,11 +794,11 @@ "share": "Condividi", "unhideToAlbum": "Non nascondere l'album", "restoreToAlbum": "Ripristina l'album", - "moveItem": "{count, plural, =1 {Sposta elemento} other {Sposta elementi}}", + "moveItem": "{count, plural, one {}=1 {Sposta elemento} other {Sposta elementi}}", "@moveItem": { "description": "Page title while moving one or more items to an album" }, - "addItem": "{count, plural, =1 {Aggiungi elemento} other {Aggiungi elementi}}", + "addItem": "{count, plural, one {}=1 {Aggiungi elemento} other {Aggiungi elementi}}", "@addItem": { "description": "Page title while adding one or more items to album" }, @@ -899,7 +899,7 @@ "authToViewYourMemories": "Autenticati per visualizzare le tue foto", "unlock": "Sblocca", "freeUpSpace": "Libera spazio", - "freeUpSpaceSaving": "{count, plural, =1 {Può essere cancellato per liberare {formattedSize}} other {Possono essere cancellati per liberare {formattedSize}}}", + "freeUpSpaceSaving": "{count, plural, one {}=1 {Può essere cancellato per liberare {formattedSize}} other {Possono essere cancellati per liberare {formattedSize}}}", "filesBackedUpInAlbum": "{count, plural, one {1 file} other {{formattedNumber} file}} di quest'album sono stati salvati in modo sicuro", "@filesBackedUpInAlbum": { "description": "Text to tell user how many files have been backed up in the album", @@ -1260,8 +1260,8 @@ "description": "Subtitle to indicate that the user can find people quickly by name" }, "findPeopleByName": "Trova rapidamente le persone per nome", - "addViewers": "{count, plural, =0 {Aggiungi visualizzatore} =1 {Add viewer} other {Aggiungi visualizzatori}}", - "addCollaborators": "{count, plural, =0 {Aggiungi collaboratore} =1 {Aggiungi collaboratore} other {Aggiungi collaboratori}}", + "addViewers": "{count, plural, one {}=0 {Aggiungi visualizzatore} =1 {Add viewer} other {Aggiungi visualizzatori}}", + "addCollaborators": "{count, plural, one {}=0 {Aggiungi collaboratore} =1 {Aggiungi collaboratore} other {Aggiungi collaboratori}}", "longPressAnEmailToVerifyEndToEndEncryption": "Premi a lungo un'email per verificare la crittografia end to end.", "developerSettingsWarning": "Sei sicuro di voler modificare le Impostazioni sviluppatore?", "developerSettings": "Impostazioni sviluppatore", @@ -1394,7 +1394,7 @@ "enableMachineLearningBanner": "Abilita l'apprendimento automatico per la ricerca magica e il riconoscimento facciale", "searchDiscoverEmptySection": "Le immagini saranno mostrate qui una volta che l'elaborazione e la sincronizzazione saranno completate", "searchPersonsEmptySection": "Le persone saranno mostrate qui una volta che l'elaborazione e la sincronizzazione saranno completate", - "viewersSuccessfullyAdded": "{count, plural, =0 {Added 0 visualizzatori} =1 {Added 1 visualizzatore} other {Added {count} visualizzatori}}", + "viewersSuccessfullyAdded": "{count, plural, one {}=0 {Added 0 visualizzatori} =1 {Added 1 visualizzatore} other {Added {count} visualizzatori}}", "@viewersSuccessfullyAdded": { "placeholders": { "count": { @@ -1479,7 +1479,7 @@ }, "currentlyRunning": "attualmente in esecuzione", "ignored": "ignorato", - "photosCount": "{count, plural, =0 {0 foto} =1 {1 foto} other {{count} foto}}", + "photosCount": "{count, plural, one {}=0 {0 foto} =1 {1 foto} other {{count} foto}}", "@photosCount": { "placeholders": { "count": { @@ -1677,7 +1677,7 @@ "moveSelectedPhotosToOneDate": "Sposta foto selezionate in una data specifica", "shiftDatesAndTime": "Sposta date e orari", "photosKeepRelativeTimeDifference": "Le foto mantengono una differenza di tempo relativa", - "photocountPhotos": "{count, plural, =0 {Nessuna foto} =1 {1 foto} other {{count} foto}}", + "photocountPhotos": "{count, plural, one {}=0 {Nessuna foto} =1 {1 foto} other {{count} foto}}", "@photocountPhotos": { "placeholders": { "count": { @@ -1691,7 +1691,7 @@ "selectedItemsWillBeRemovedFromThisPerson": "Gli elementi selezionati verranno rimossi da questa persona, ma non eliminati dalla tua libreria.", "throughTheYears": "{dateFormat} negli anni", "thisWeekThroughTheYears": "Questa settimana negli anni", - "thisWeekXYearsAgo": "{count, plural, =1 {Questa settimana, {count} anno fa} other {Questa settimana, {count} anni fa}}", + "thisWeekXYearsAgo": "{count, plural, one {}=1 {Questa settimana, {count} anno fa} other {Questa settimana, {count} anni fa}}", "youAndThem": "Tu e {name}", "admiringThem": "Ammirando {name}", "embracingThem": "Abbracciando {name}", @@ -1746,4 +1746,4 @@ "receiveRemindersOnBirthdays": "Ricevi promemoria quando è il compleanno di qualcuno. Toccare la notifica ti porterà alle foto della persona che compie gli anni.", "happyBirthday": "Buon compleanno! 🥳", "birthdays": "Compleanni" -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_ja.arb b/mobile/apps/photos/lib/l10n/intl_ja.arb index 67b852af1f..5c7ae58646 100644 --- a/mobile/apps/photos/lib/l10n/intl_ja.arb +++ b/mobile/apps/photos/lib/l10n/intl_ja.arb @@ -461,7 +461,7 @@ } }, "showMemories": "思い出を表示", - "yearsAgo": "{count, plural, other{{count} 年前}}", + "yearsAgo": "{count, plural, one{{count} 年前} other{{count} 年前}}", "backupSettings": "バックアップ設定", "backupStatus": "バックアップの状態", "backupStatusDescription": "バックアップされたアイテムがここに表示されます", @@ -527,7 +527,7 @@ }, "remindToEmptyEnteTrash": "「ゴミ箱」も空にするとアカウントのストレージが解放されます", "sparkleSuccess": "成功✨", - "duplicateFileCountWithStorageSaved": "お掃除しました {count, plural, other{{count} 個の重複ファイル}}, ({storageSaved}が開放されます!)", + "duplicateFileCountWithStorageSaved": "お掃除しました {count, plural, one{{count} 個の重複ファイル} other{{count} 個の重複ファイル}}, ({storageSaved}が開放されます!)", "@duplicateFileCountWithStorageSaved": { "description": "The text to display when the user has successfully cleaned up duplicate files", "type": "text", @@ -1178,7 +1178,7 @@ "searchHint4": "場所", "searchHint5": "近日公開: フェイスとマジック検索 ✨", "addYourPhotosNow": "写真を今すぐ追加する", - "searchResultCount": "{count, plural, other{{count} 個の結果}}", + "searchResultCount": "{count, plural, one{{count} 個の結果} other{{count} 個の結果}}", "@searchResultCount": { "description": "Text to tell user how many results were found for their search query", "placeholders": { @@ -1666,4 +1666,4 @@ "onTheRoad": "再び道で", "food": "料理を楽しむ", "pets": "毛むくじゃらな仲間たち" -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_lt.arb b/mobile/apps/photos/lib/l10n/intl_lt.arb index 6d0f48c76d..704c8bc261 100644 --- a/mobile/apps/photos/lib/l10n/intl_lt.arb +++ b/mobile/apps/photos/lib/l10n/intl_lt.arb @@ -900,7 +900,7 @@ "unlock": "Atrakinti", "freeUpSpace": "Atlaisvinti vietos", "freeUpSpaceSaving": "{count, plural, =1 {Jį galima ištrinti iš įrenginio, kad atlaisvintų {formattedSize}} other {Jų galima ištrinti iš įrenginio, kad atlaisvintų {formattedSize}}}", - "filesBackedUpInAlbum": "{count, plural, one {{formattedNumber} failas šiame albume saugiai sukurta atsarginė kopija} other {{formattedNumber} failų šiame albume saugiai sukurta atsarginė kopija}}.", + "filesBackedUpInAlbum": "{count, plural, one {{formattedNumber} failas šiame albume saugiai sukurta atsarginė kopija} few {{formattedNumber} failai šiame albume saugiai sukurtos atsarginės kopijos} many {{formattedNumber} failo šiame albume saugiai sukurtos atsargines kopijos} other {{formattedNumber} failų šiame albume saugiai sukurta atsarginė kopija}}.", "@filesBackedUpInAlbum": { "description": "Text to tell user how many files have been backed up in the album", "placeholders": { @@ -915,7 +915,7 @@ } } }, - "filesBackedUpFromDevice": "{count, plural, one {{formattedNumber} failas šiame įrenginyje saugiai sukurta atsarginė kopija} other {{formattedNumber} failų šiame įrenginyje saugiai sukurta atsarginių kopijų}}.", + "filesBackedUpFromDevice": "{count, plural, one {{formattedNumber} failas šiame įrenginyje saugiai sukurta atsarginė kopija} few {{formattedNumber} failai šiame įrenginyje saugiai sukurtos atsarginės kopijos} many {{formattedNumber} failo šiame įrenginyje saugiai sukurtos atsargines kopijos} other {{formattedNumber} failų šiame įrenginyje saugiai sukurta atsarginių kopijų}}.", "@filesBackedUpFromDevice": { "description": "Text to tell user how many files have been backed up from this device", "placeholders": { @@ -1403,7 +1403,7 @@ "enableMachineLearningBanner": "Įjunkite mašininį mokymąsi magiškai paieškai ir veidų atpažinimui", "searchDiscoverEmptySection": "Vaizdai bus rodomi čia, kai bus užbaigtas apdorojimas ir sinchronizavimas.", "searchPersonsEmptySection": "Asmenys bus rodomi čia, kai bus užbaigtas apdorojimas ir sinchronizavimas.", - "viewersSuccessfullyAdded": "{count, plural, =0 {Įtraukta 0 žiūrėtojų} =1 {Įtrauktas 1 žiūrėtojas} other {Įtraukta {count} žiūrėtojų}}", + "viewersSuccessfullyAdded": "{count, plural, one {Įtrauktas {count} žiūrėtojas} few {Įtraukti {count} žiūrėtojai} many {Įtraukta {count} žiūrėtojo} =0 {Įtraukta 0 žiūrėtojų} =1 {Įtrauktas 1 žiūrėtojas} other {Įtraukta {count} žiūrėtojų}}", "@viewersSuccessfullyAdded": { "placeholders": { "count": { @@ -1488,7 +1488,7 @@ }, "currentlyRunning": "šiuo metu vykdoma", "ignored": "ignoruota", - "photosCount": "{count, plural, =0 {0 nuotraukų} =1 {1 nuotrauka} other {{count} nuotraukų}}", + "photosCount": "{count, plural, one {{count} nuotrauka} few {{count} nuotraukos} many {{count} nuotraukos} =0 {0 nuotraukų} =1 {1 nuotrauka} other {{count} nuotraukų}}", "@photosCount": { "placeholders": { "count": { @@ -1756,4 +1756,4 @@ "happyBirthday": "Su gimtadieniu! 🥳", "birthdays": "Gimtadieniai", "wishThemAHappyBirthday": "Palinkėkite {name} su gimtadieniu! 🎉" -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_ms.arb b/mobile/apps/photos/lib/l10n/intl_ms.arb new file mode 100644 index 0000000000..c8494661c6 --- /dev/null +++ b/mobile/apps/photos/lib/l10n/intl_ms.arb @@ -0,0 +1,3 @@ +{ + "@@locale ": "en" +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_nl.arb b/mobile/apps/photos/lib/l10n/intl_nl.arb index 70d7ac8c8c..13af940170 100644 --- a/mobile/apps/photos/lib/l10n/intl_nl.arb +++ b/mobile/apps/photos/lib/l10n/intl_nl.arb @@ -477,7 +477,7 @@ } }, "showMemories": "Toon herinneringen", - "yearsAgo": "{count, plural, other{{count} jaar geleden}}", + "yearsAgo": "{count, plural, one{{count} jaar geleden} other{{count} jaar geleden}}", "backupSettings": "Back-up instellingen", "backupStatus": "Back-up status", "backupStatusDescription": "Items die zijn geback-upt, worden hier getoond", @@ -1773,4 +1773,4 @@ "areYouSureYouWantToMergeThem": "Weet je zeker dat je ze wilt samenvoegen?", "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": "Alle naamloze groepen worden samengevoegd met de geselecteerde persoon. Dit kan nog steeds ongedaan worden gemaakt vanuit het geschiedenisoverzicht van de persoon.", "yesIgnore": "Ja, negeer" -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_no.arb b/mobile/apps/photos/lib/l10n/intl_no.arb index 0a45172728..a0003c7bf4 100644 --- a/mobile/apps/photos/lib/l10n/intl_no.arb +++ b/mobile/apps/photos/lib/l10n/intl_no.arb @@ -476,7 +476,7 @@ } }, "showMemories": "Vis minner", - "yearsAgo": "{count, plural, other{{count} år siden}}", + "yearsAgo": "{count, plural, one{{count} år siden} other{{count} år siden}}", "backupSettings": "Sikkerhetskopier innstillinger", "backupStatus": "Status for sikkerhetskopi", "backupStatusDescription": "Elementer som har blitt sikkerhetskopiert vil vises her", @@ -1689,4 +1689,4 @@ "onTheRoad": "På veien igjen", "food": "Kulinær glede", "pets": "Pelsvenner" -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_pl.arb b/mobile/apps/photos/lib/l10n/intl_pl.arb index 58adb38f02..7ad308c900 100644 --- a/mobile/apps/photos/lib/l10n/intl_pl.arb +++ b/mobile/apps/photos/lib/l10n/intl_pl.arb @@ -1,6 +1,7 @@ { "@@locale ": "en", "enterYourEmailAddress": "Podaj swój adres e-mail", + "enterYourNewEmailAddress": "Podaj swój nowy adres e-mail", "accountWelcomeBack": "Witaj ponownie!", "emailAlreadyRegistered": "Adres e-mail jest już zarejestrowany.", "emailNotRegistered": "Adres e-mail nie jest zarejestrowany.", @@ -443,8 +444,8 @@ "selectAll": "Zaznacz wszystko", "skip": "Pomiń", "updatingFolderSelection": "Aktualizowanie wyboru folderu...", - "itemCount": "{count, plural, one{{count} element} other{{count} elementu}}", - "deleteItemCount": "{count, plural, =1 {Usuń {count} element} other{Usuń {count} elementu}}", + "itemCount": "{count, plural, one{{count} element} few {{count} elementy} many {{count} elementów} other{{count} elementu}}", + "deleteItemCount": "{count, plural, =1 {Usuń {count} element} few {Usuń {count} elementy} many {Usuń {count} elementów} other{Usuń {count} elementu}}", "duplicateItemsGroup": "{count} plików, każdy po {formattedSize}", "@duplicateItemsGroup": { "description": "Display the number of duplicate files and their size", @@ -461,7 +462,7 @@ } }, "showMemories": "Pokaż wspomnienia", - "yearsAgo": "{count, plural, one{{count} rok temu} other{{count} lata temu}}", + "yearsAgo": "{count, plural, one{{count} rok temu} few {{count} lata temu} many {{count} lat temu} other{{count} lata temu}}", "backupSettings": "Ustawienia kopii zapasowej", "backupStatus": "Status kopii zapasowej", "backupStatusDescription": "Elementy, których kopia zapasowa została utworzona, zostaną wyświetlone w tym miejscu", @@ -510,6 +511,7 @@ "viewLargeFiles": "Duże pliki", "viewLargeFilesDesc": "Wyświetl pliki zużywające największą ilość pamięci.", "noDuplicates": "✨ Brak duplikatów", + "youveNoDuplicateFilesThatCanBeCleared": "Nie masz zduplikowanych plików, które można wyczyścić", "success": "Sukces", "rateUs": "Oceń nas", "remindToEmptyDeviceTrash": "Również opróżnij \"Ostatnio usunięte\" z \"Ustawienia\" -> \"Pamięć\", aby odebrać wolną przestrzeń", @@ -705,6 +707,7 @@ "type": "text" }, "backupFailed": "Tworzenie kopii zapasowej nie powiodło się", + "sorryBackupFailedDesc": "Przepraszamy, nie mogliśmy utworzyć kopii zapasowej tego pliku teraz, spróbujemy ponownie później.", "couldNotBackUpTryLater": "Nie można utworzyć kopii zapasowej Twoich danych.\nSpróbujemy ponownie później.", "enteCanEncryptAndPreserveFilesOnlyIfYouGrant": "Ente może zaszyfrować i zachować pliki tylko wtedy, gdy udzielisz do nich dostępu", "pleaseGrantPermissions": "Prosimy przyznać uprawnienia", @@ -800,7 +803,7 @@ "referFriendsAnd2xYourPlan": "Poleć znajomym i podwój swój plan", "shareAlbumHint": "Otwórz album i dotknij przycisk udostępniania w prawym górnym rogu, aby udostępnić.", "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": "Elementy pokazują liczbę dni pozostałych przed trwałym usunięciem", - "trashDaysLeft": "{count, plural, =0 {Wkrótce} =1{1 dzień} other{{count} dni}}", + "trashDaysLeft": "{count, plural, =0 {Wkrótce} =1{1 dzień} few {{count} dni} other{{count} dni}}", "@trashDaysLeft": { "description": "Text to indicate number of days remaining before permanent deletion", "placeholders": { @@ -992,6 +995,7 @@ "didYouKnow": "Czy wiedziałeś/aś?", "loadingMessage": "Wczytywanie Twoich zdjęć...", "loadMessage1": "Możesz udostępnić swoją subskrypcję swojej rodzinie", + "loadMessage2": "Do tej pory zachowaliśmy ponad 200 milionów wspomnień", "loadMessage3": "Przechowujemy 3 kopie Twoich danych, jedną w podziemnym schronie", "loadMessage4": "Wszystkie nasze aplikacje są otwarto źródłowe", "loadMessage5": "Nasz kod źródłowy i kryptografia zostały poddane zewnętrznemu audytowi", @@ -1177,7 +1181,7 @@ "searchHint4": "Lokalizacja", "searchHint5": "Wkrótce: Twarze i magiczne wyszukiwanie ✨", "addYourPhotosNow": "Dodaj swoje zdjęcia teraz", - "searchResultCount": "{count, plural, one{Znaleziono {count} wynik} other{Znaleziono {count} wyników}}", + "searchResultCount": "{count, plural, one{Znaleziono {count} wynik} few {Znaleziono {count} wyniki} other{Znaleziono {count} wyników}}", "@searchResultCount": { "description": "Text to tell user how many results were found for their search query", "placeholders": { @@ -1240,6 +1244,8 @@ "createCollaborativeLink": "Utwórz link współpracy", "search": "Szukaj", "enterPersonName": "Wprowadź imię osoby", + "editEmailAlreadyLinked": "Ten e-mail jest już powiązany z {name}.", + "viewPersonToUnlink": "Zobacz {name}, aby odłączyć", "enterName": "Wprowadź nazwę", "savePerson": "Zapisz osobę", "editPerson": "Edytuj osobę", @@ -1526,11 +1532,178 @@ "legacyInvite": "{email} zaprosił Cię do zostania zaufanym kontaktem", "authToManageLegacy": "Prosimy uwierzytelnić się, aby zarządzać zaufanymi kontaktami", "useDifferentPlayerInfo": "Masz problem z odtwarzaniem tego wideo? Przytrzymaj tutaj, aby spróbować innego odtwarzacza.", + "hideSharedItemsFromHomeGallery": "Ukryj współdzielone elementy w galerii głównej", "gallery": "Galeria", "joinAlbum": "Dołącz do albumu", "joinAlbumSubtext": "aby wyświetlić i dodać swoje zdjęcia", "joinAlbumSubtextViewer": "aby dodać to do udostępnionych albumów", "join": "Dołącz", "linkEmail": "Połącz adres e-mail", - "noEnteAccountExclamation": "Brak konta Ente!" -} + "noEnteAccountExclamation": "Brak konta Ente!", + "orPickFromYourContacts": "lub wybierz ze swoich kontaktów", + "emailDoesNotHaveEnteAccount": "{email} nie posiada konta Ente.", + "@emailDoesNotHaveEnteAccount": { + "description": "Shown when email doesn't have an Ente account", + "placeholders": { + "email": { + "type": "String" + } + } + }, + "accountOwnerPersonAppbarTitle": "{title} (Ja)", + "@accountOwnerPersonAppbarTitle": { + "description": "Title of appbar for account owner person", + "placeholders": { + "title": { + "type": "String" + } + } + }, + "me": "Ja", + "linkEmailToContactBannerCaption": "aby szybciej udostępniać", + "@linkEmailToContactBannerCaption": { + "description": "Caption for the 'Link email' title. It should be a continuation of the 'Link email' title. Just like how 'Link email' + 'for faster sharing' forms a proper sentence in English, the combination of these two strings should also be a proper sentence in other languages." + }, + "selectPersonToLink": "Wybierz osobę do powiązania", + "linkPersonToEmail": "Połącz osobę z {email}", + "@linkPersonToEmail": { + "placeholders": { + "email": { + "type": "String" + } + } + }, + "linkPersonToEmailConfirmation": "Spowoduje to powiązanie {personName} z {email}", + "@linkPersonToEmailConfirmation": { + "description": "Confirmation message when linking a person to an email", + "placeholders": { + "personName": { + "type": "String" + }, + "email": { + "type": "String" + } + } + }, + "selectYourFace": "Wybierz swoją twarz", + "reassignedToName": "Ponownie przypisano cię do {name}", + "@reassignedToName": { + "placeholders": { + "name": { + "type": "String" + } + } + }, + "saveChangesBeforeLeavingQuestion": "Zapisać zmiany przed wyjściem?", + "dontSave": "Nie zapisuj", + "thisIsMeExclamation": "To ja!", + "videoStreaming": "Streamowalne wideo", + "processingVideos": "Przetwarzanie wideo", + "processing": "Przetwarzanie", + "queued": "W kolejce", + "ineligible": "Nie kwalifikuje się", + "playOriginal": "Odtwórz oryginał", + "joinAlbumConfirmationDialogBody": "Dołączenie do albumu sprawi, że Twój e-mail będzie widoczny dla jego uczestników.", + "pleaseWaitThisWillTakeAWhile": "Prosimy czekać, to może zająć chwilę.", + "editTime": "Edytuj czas", + "selectTime": "Wybierz czas", + "selectDate": "Wybierz datę", + "previous": "Poprzedni", + "selectOneDateAndTimeForAll": "Wybierz jedną datę i czas dla wszystkich", + "selectStartOfRange": "Wybierz początek zakresu", + "thisWillMakeTheDateAndTimeOfAllSelected": "To sprawi, że data i czas wszystkich wybranych zdjęć będą takie same.", + "allWillShiftRangeBasedOnFirst": "To jest pierwsze w grupie. Inne wybrane zdjęcia zostaną automatycznie przesunięte w oparciu o tę nową datę", + "newRange": "Nowy zakres", + "selectOneDateAndTime": "Wybierz jedną datę i czas", + "moveSelectedPhotosToOneDate": "Przenieś wybrane zdjęcia na jedną datę", + "shiftDatesAndTime": "Zmień daty i czas", + "photosKeepRelativeTimeDifference": "Zdjęcia zachowują względną różnicę czasu", + "appIcon": "Ikona aplikacji", + "notThisPerson": "Nie ta osoba?", + "selectedItemsWillBeRemovedFromThisPerson": "Wybrane elementy zostaną usunięte z tej osoby, ale nie zostaną usunięte z Twojej biblioteki.", + "thisWeekThroughTheYears": "Ten tydzień przez lata", + "youAndThem": "Ty i {name}", + "admiringThem": "Podziwianie {name}", + "hikingWithThem": "Wędrówka z {name}", + "feastingWithThem": "Ucztowanie z {name}", + "selfiesWithThem": "Selfie z {name}", + "posingWithThem": "Pozowanie z {name}", + "backgroundWithThem": "Piękne widoki z {name}", + "sportsWithThem": "Sport z {name}", + "roadtripWithThem": "Wycieczka z {name}", + "spotlightOnYourself": "Uwaga na siebie", + "spotlightOnThem": "Uwaga na {name}", + "personIsAge": "{name} ma {age} lat!", + "personTurningAge": "{name} wkrótce będzie mieć {age} lat", + "lastTimeWithThem": "Ostatnio z {name}", + "tripInYear": "Podróż w {year}", + "lastYearsTrip": "Zeszłoroczna podróż", + "sunrise": "Na horyzoncie", + "mountains": "Na wzgórzach", + "greenery": "Zielone życie", + "beach": "Piasek i morze", + "city": "W mieście", + "moon": "W świetle księżyca", + "onTheRoad": "Znowu na drodze", + "food": "Kulinarna rozkosz", + "pets": "Futrzani towarzysze", + "curatedMemories": "Wyselekcjonowane wspomnienia", + "widgets": "Widżety", + "memories": "Wspomnienia", + "peopleWidgetDesc": "Wybierz osoby, które chcesz zobaczyć na ekranie głównym.", + "albumsWidgetDesc": "Wybierz albumy, które chcesz zobaczyć na ekranie głównym.", + "memoriesWidgetDesc": "Wybierz rodzaj wspomnień, które chcesz zobaczyć na ekranie głównym.", + "pastYearsMemories": "Wspomnienia z ubiegłych lat", + "deleteMultipleAlbumDialog": "Usunąć również zdjęcia (i filmy) obecne w tych albumach {count} z wszystkich innych albumów, których są częścią?", + "addParticipants": "Dodaj uczestników", + "selectedAlbums": "Wybrano {count}", + "actionNotSupportedOnFavouritesAlbum": "Akcja nie jest obsługiwana na Ulubionym albumie", + "onThisDayMemories": "Wspomnienia z tego dnia", + "onThisDay": "Tego dnia", + "lookBackOnYourMemories": "Spójrz ponownie na swoje wspomnienia 🌄", + "newPhotosEmoji": " nowe 📸", + "sorryWeHadToPauseYourBackups": "Przepraszamy, musieliśmy wstrzymać tworzenie kopii zapasowych", + "clickToInstallOurBestVersionYet": "Kliknij, aby zainstalować naszą najlepszą wersję", + "onThisDayNotificationExplanation": "Otrzymuj przypomnienia o wspomnieniach z tego dnia w poprzednich latach.", + "addMemoriesWidgetPrompt": "Dodaj widżet wspomnień do ekranu głównego i wróć tutaj, aby dostosować.", + "addAlbumWidgetPrompt": "Dodaj widżet albumu do ekranu głównego i wróć tutaj, aby dostosować.", + "addPeopleWidgetPrompt": "Dodaj widżet ludzi do ekranu głównego i wróć tutaj, aby dostosować.", + "birthdayNotifications": "Powiadomienia o urodzinach", + "receiveRemindersOnBirthdays": "Otrzymuj przypomnienia, kiedy są czyjeś urodziny. Naciskając na powiadomienie zabierze Cię do zdjęć osoby, która ma urodziny.", + "happyBirthday": "Wszystkiego najlepszego! 🥳", + "birthdays": "Urodziny", + "wishThemAHappyBirthday": "Życz {name} wszystkiego najlepszego! 🎉", + "areYouSureRemoveThisFaceFromPerson": "Czy na pewno chcesz usunąć tę twarz z tej osoby?", + "otherDetectedFaces": "Inne wykryte twarze", + "areThey": "Czy są ", + "questionmark": "?", + "saveAsAnotherPerson": "Zapisz jako inną osobę", + "showLessFaces": "Pokaż mniej twarzy", + "showMoreFaces": "Pokaż więcej twarzy", + "ignore": "Ignoruj", + "merge": "Scal", + "reset": "Zresetuj", + "areYouSureYouWantToIgnoreThisPerson": "Czy na pewno chcesz zignorować tę osobę?", + "areYouSureYouWantToIgnoreThesePersons": "Czy na pewno chcesz zignorować te osoby?", + "thePersonGroupsWillNotBeDisplayed": "Grupy osób nie będą już wyświetlane w sekcji ludzi. Zdjęcia pozostaną nienaruszone.", + "thePersonWillNotBeDisplayed": "Osoba nie będzie już wyświetlana w sekcji ludzi. Zdjęcia pozostaną nienaruszone.", + "areYouSureYouWantToMergeThem": "Czy na pewno chcesz je scalić?", + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": "Wszystkie nienazwane grupy zostaną scalone z wybraną osobą. To nadal może zostać cofnięte z przeglądu historii sugestii danej osoby.", + "yesIgnore": "Tak, ignoruj", + "same": "Identyczne", + "different": "Inne", + "sameperson": "Ta sama osoba?", + "cLTitle1": "Przesyłanie Dużych Plików Wideo", + "cLDesc1": "W związku z uruchomieniem wersji beta przesyłania strumieniowego wideo oraz pracami nad możliwością wznawiania przesyłania i pobierania plików, zwiększyliśmy limit przesyłanych plików do 10 GB. Jest to już dostępne zarówno w aplikacjach na komputery, jak i na urządzenia mobilne.", + "cLTitle2": "Przesyłanie w Tle", + "cLDesc2": "Funkcja przesyłania w tle jest teraz obsługiwana również na urządzeniach z systemem iOS, oprócz urządzeń z Androidem. Nie trzeba już otwierać aplikacji, aby utworzyć kopię zapasową najnowszych zdjęć i filmów.", + "cLTitle3": "Automatyczne Odtwarzanie Wspomnień", + "cLDesc3": "Wprowadziliśmy istotne ulepszenia w funkcji wspomnień, w tym automatyczne odtwarzanie, przesuwanie do kolejnego wspomnienia i wiele innych.", + "cLTitle4": "Ulepszone Rozpoznawanie Twarzy", + "cLDesc4": "Wraz z kilkoma ulepszeniami w mechanizmie teraz znacznie łatwiej jest widzieć wszystkie wykryte twarze, zapewniać informacje zwrotne o podobnych twarzach i dodawać/usuwać twarze z jednego zdjęcia.", + "cLTitle5": "Powiadomienia o Urodzinach", + "cLDesc5": "Od teraz otrzymasz powiadomienie z możliwością rezygnacji dotyczące wszystkich zapisanych urodzin w Ente, wraz z kolekcją najlepszych zdjęć danej osoby.", + "cLTitle6": "Wznawialne Przesyłanie i Pobieranie Danych", + "cLDesc6": "Nie musisz już czekać na zakończenie przesyłania ani pobierania, żeby móc zamknąć aplikację. Wszystkie operacje przesyłania i pobierania można teraz wstrzymać w dowolnym momencie i wznowić od miejsca, w którym zostały przerwane.", + "indexingPausedStatusDescription": "Indeksowanie zostało wstrzymane. Zostanie automatycznie wznowione, gdy urządzenie będzie gotowe. Urządzenie uznaje się za gotowe, gdy poziom baterii, stan jej zdrowia oraz status termiczny znajdują się w bezpiecznym zakresie." +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_pt_BR.arb b/mobile/apps/photos/lib/l10n/intl_pt_BR.arb index 2d8c750b9b..dca73651a8 100644 --- a/mobile/apps/photos/lib/l10n/intl_pt_BR.arb +++ b/mobile/apps/photos/lib/l10n/intl_pt_BR.arb @@ -1788,5 +1788,7 @@ "cLDesc5": "Você receberá uma notificação opcional para todos os aniversários salvos no Ente, além de uma coleção de melhores fotos.", "cLTitle6": "Envios e downloads retomáveis", "cLDesc6": "Nada de esperar os envios/downloads terminarem para fechar o aplicativo. Todos os envios e downloads agora possuem a habilidade de ser pausado na metade do processo, e retomar de onde você parou.", - "indexingPausedStatusDescription": "A indexação foi pausada. Ela retomará automaticamente quando o dispositivo estiver pronto. O dispositivo é considerado pronto quando o nível de bateria, saúde da bateria, e estado térmico estejam num alcance saudável." + "indexingPausedStatusDescription": "A indexação foi pausada. Ela retomará automaticamente quando o dispositivo estiver pronto. O dispositivo é considerado pronto quando o nível de bateria, saúde da bateria, e estado térmico estejam num alcance saudável.", + "faceThumbnailGenerationFailed": "Incapaz de gerar miniaturas de rosto", + "fileAnalysisFailed": "Incapaz de analisar rosto" } \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_pt_PT.arb b/mobile/apps/photos/lib/l10n/intl_pt_PT.arb index 0d1ac54c0a..6c4be05fd7 100644 --- a/mobile/apps/photos/lib/l10n/intl_pt_PT.arb +++ b/mobile/apps/photos/lib/l10n/intl_pt_PT.arb @@ -242,7 +242,7 @@ "publicLinkEnabled": "Link público ativado", "shareALink": "Partilhar um link", "sharedAlbumSectionDescription": "Criar álbuns compartilhados e colaborativos com outros usuários da Ente, incluindo usuários em planos gratuitos.", - "shareWithPeopleSectionTitle": "{numberOfPeople, plural, =0 {Compartilhe com pessoas específicas} =1 {Compartilhado com 1 pessoa} other {Compartilhado com {numberOfPeople} pessoas}}", + "shareWithPeopleSectionTitle": "{numberOfPeople, plural, one {}=0 {Compartilhe com pessoas específicas} =1 {Compartilhado com 1 pessoa} other {Compartilhado com {numberOfPeople} pessoas}}", "@shareWithPeopleSectionTitle": { "placeholders": { "numberOfPeople": { @@ -899,7 +899,7 @@ "authToViewYourMemories": "Por favor, autentique-se para ver suas memórias", "unlock": "Desbloquear", "freeUpSpace": "Libertar espaço", - "freeUpSpaceSaving": "{count, plural, =1 {Pode eliminá-lo do aparelho para esvaziar {formattedSize}} other {Pode eliminá-los do aparelho para esvaziar {formattedSize}}}", + "freeUpSpaceSaving": "{count, plural, one {}=1 {Pode eliminá-lo do aparelho para esvaziar {formattedSize}} other {Pode eliminá-los do aparelho para esvaziar {formattedSize}}}", "filesBackedUpInAlbum": "{count, plural, one {1 arquivo} other {{formattedNumber} arquivos}} neste álbum teve um backup seguro", "@filesBackedUpInAlbum": { "description": "Text to tell user how many files have been backed up in the album", @@ -1788,5 +1788,7 @@ "cLDesc5": "Ganhará uma notificação para todos os aniversários que salvaste no Ente, além de uma coleção das melhores fotos.", "cLTitle6": "Envios e transferências retomáveis", "cLDesc6": "Sem mais aguardar até que os envios e transferências sejam concluídos para fechar a aplicação. Todos os envios e transferências podem ser pausados a qualquer momento, e retomar onde parou.", - "indexingPausedStatusDescription": "A indexação foi interrompida. Ele será retomado se o dispositivo estiver pronto. O dispositivo é considerado pronto se o nível de bateria, saúde da bateria, e estado térmico esteja num estado saudável." -} + "indexingPausedStatusDescription": "A indexação foi interrompida. Ele será retomado se o dispositivo estiver pronto. O dispositivo é considerado pronto se o nível de bateria, saúde da bateria, e estado térmico esteja num estado saudável.", + "faceThumbnailGenerationFailed": "Impossível gerar thumbnails de rosto", + "fileAnalysisFailed": "Impossível analisar arquivo" +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_ro.arb b/mobile/apps/photos/lib/l10n/intl_ro.arb index 0e9a269da5..fafb080c6d 100644 --- a/mobile/apps/photos/lib/l10n/intl_ro.arb +++ b/mobile/apps/photos/lib/l10n/intl_ro.arb @@ -443,7 +443,7 @@ "selectAll": "Selectare totală", "skip": "Omiteți", "updatingFolderSelection": "Se actualizează selecția dosarelor...", - "itemCount": "{count, plural, one{{count} articol} other{{count} de articole}}", + "itemCount": "{count, plural, one{{count} articol} few {{count} articole} other{{count} de articole}}", "deleteItemCount": "{count, plural, =1 {Ștergeți {count} articol} other {Ștergeți {count} de articole}}", "duplicateItemsGroup": "{count} fișiere, {formattedSize} fiecare", "@duplicateItemsGroup": { @@ -461,7 +461,7 @@ } }, "showMemories": "Afișare amintiri", - "yearsAgo": "{count, plural, one{acum {count} an} other{acum {count} de ani}}", + "yearsAgo": "{count, plural, one{acum {count} an} few {acum {count} ani} other{acum {count} de ani}}", "backupSettings": "Setări copie de rezervă", "backupStatus": "Stare copie de rezervă", "backupStatusDescription": "Articolele care au fost salvate vor apărea aici", @@ -526,7 +526,7 @@ }, "remindToEmptyEnteTrash": "De asemenea, goliți „Coșul de gunoi” pentru a revendica spațiul eliberat", "sparkleSuccess": "✨ Succes", - "duplicateFileCountWithStorageSaved": "Ați curățat {count, plural, one{{count} dublură} other{{count} de dubluri}}, economisind ({storageSaved}!)", + "duplicateFileCountWithStorageSaved": "Ați curățat {count, plural, one{{count} dublură} few {{count} dubluri} other{{count} de dubluri}}, economisind ({storageSaved}!)", "@duplicateFileCountWithStorageSaved": { "description": "The text to display when the user has successfully cleaned up duplicate files", "type": "text", @@ -873,7 +873,7 @@ "authToViewYourMemories": "Vă rugăm să vă autentificați pentru a vă vizualiza amintirile", "unlock": "Deblocare", "freeUpSpace": "Eliberați spațiu", - "filesBackedUpInAlbum": "{count, plural, one {Un fișier din acest album a fost deja salvat în siguranță} other {{formattedNumber} de fișiere din acest album au fost deja salvate în siguranță}}", + "filesBackedUpInAlbum": "{count, plural, one {Un fișier din acest album a fost deja salvat în siguranță} few {{formattedNumber} fișiere din acest album au fost deja salvate în siguranță} other {{formattedNumber} de fișiere din acest album au fost deja salvate în siguranță}}", "@filesBackedUpInAlbum": { "description": "Text to tell user how many files have been backed up in the album", "placeholders": { @@ -888,7 +888,7 @@ } } }, - "filesBackedUpFromDevice": "{count, plural, one {Un fișier de pe acest dispozitiv a fost deja salvat în siguranță} other {{formattedNumber} de fișiere de pe acest dispozitiv fost deja salvate în siguranță}}", + "filesBackedUpFromDevice": "{count, plural, one {Un fișier de pe acest dispozitiv a fost deja salvat în siguranță} few {{formattedNumber} fișiere de pe acest dispozitiv au fost deja salvate în siguranță} other {{formattedNumber} de fișiere de pe acest dispozitiv fost deja salvate în siguranță}}", "@filesBackedUpFromDevice": { "description": "Text to tell user how many files have been backed up from this device", "placeholders": { @@ -1177,7 +1177,7 @@ "searchHint4": "Locație", "searchHint5": "În curând: chipuri și căutare magică ✨", "addYourPhotosNow": "Adăugați-vă fotografiile acum", - "searchResultCount": "{count, plural, one{{count} rezultat găsit} other{{count} de rezultate găsite}}", + "searchResultCount": "{count, plural, one{{count} rezultat găsit} few {{count} rezultate găsite} other{{count} de rezultate găsite}}", "@searchResultCount": { "description": "Text to tell user how many results were found for their search query", "placeholders": { @@ -1522,4 +1522,4 @@ "joinAlbumSubtext": "pentru a vedea și a adăuga fotografii", "joinAlbumSubtextViewer": "pentru a adăuga la albumele distribuite", "join": "Alăturare" -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_ru.arb b/mobile/apps/photos/lib/l10n/intl_ru.arb index 4d2c86bed6..99d7e093f3 100644 --- a/mobile/apps/photos/lib/l10n/intl_ru.arb +++ b/mobile/apps/photos/lib/l10n/intl_ru.arb @@ -477,7 +477,7 @@ } }, "showMemories": "Показывать воспоминания", - "yearsAgo": "{count, plural, one{{count} год назад} other{{count} лет назад}}", + "yearsAgo": "{count, plural, one{{count} год назад} few{{count} года назад} other{{count} лет назад}}", "backupSettings": "Настройки резервного копирования", "backupStatus": "Статус резервного копирования", "backupStatusDescription": "Элементы, сохранённые в резервной копии, появятся здесь", @@ -1789,4 +1789,4 @@ "cLTitle6": "Возобновляемые загрузки и скачивания", "cLDesc6": "Больше не нужно ждать завершения загрузки/скачивания, прежде чем закрыть приложение. Все загрузки и скачивания теперь можно приостановить и возобновить с того места, где вы остановились.", "indexingPausedStatusDescription": "Индексирование приостановлено. Оно автоматически возобновится, когда устройство будет готово. Устройство считается готовым, когда уровень заряда батареи, её состояние и температура находятся в пределах нормы." -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_sr.arb b/mobile/apps/photos/lib/l10n/intl_sr.arb index c8494661c6..e875286038 100644 --- a/mobile/apps/photos/lib/l10n/intl_sr.arb +++ b/mobile/apps/photos/lib/l10n/intl_sr.arb @@ -1,3 +1,290 @@ { - "@@locale ": "en" + "@@locale ": "en", + "enterYourEmailAddress": "Унесите Вашу е-пошту", + "enterYourNewEmailAddress": "Унесите Вашу нову е-пошту", + "accountWelcomeBack": "Добродошли назад!", + "emailAlreadyRegistered": "Е-пошта је већ регистрована.", + "emailNotRegistered": "Е-пошта није регистрована.", + "email": "Е-пошта", + "cancel": "Откажи", + "verify": "Верификуј", + "invalidEmailAddress": "Неисправна е-пошта", + "enterValidEmail": "Молимо унесите исправну адресу е-поште.", + "deleteAccount": "Обриши налог", + "askDeleteReason": "Који је главни разлог што бришете свој налог?", + "deleteAccountFeedbackPrompt": "Жао нам је што одлазите. Молимо вас да нам оставите повратне информације како бисмо могли да се побољшамо.", + "feedback": "Повратне информације", + "kindlyHelpUsWithThisInformation": "Љубазно вас молимо да нам помогнете са овим информацијама", + "confirmDeletePrompt": "Да, желим трајно да избришем овај налог и све његове податке у свим апликацијама.", + "confirmAccountDeletion": "Потврдите брисање налога", + "deleteAccountPermanentlyButton": "Трајно обриши налог", + "yourAccountHasBeenDeleted": "Ваш налог је обрисан", + "selectReason": "Одаберите разлог", + "deleteReason1": "Недостаје важна функција која ми је потребна", + "deleteReason2": "Апликација или одређена функција не ради онако како мислим да би требало", + "deleteReason3": "Пронашао/ла сам други сервис који ми више одговара", + "deleteReason4": "Мој разлог није на листи", + "sendEmail": "Пошаљи е-пошту", + "deleteRequestSLAText": "Ваш захтев ће бити обрађен у року од 72 сата.", + "deleteEmailRequest": "Молимо пошаљите имејл на account-deletion@ente.io са ваше регистроване адресе е-поште.", + "entePhotosPerm": "Енте-у је потребна дозвола да сачува ваше фотографије", + "ok": "Ок", + "createAccount": "Направи налог", + "createNewAccount": "Креирај нови налог", + "password": "Лозинка", + "confirmPassword": "Потврдите лозинку", + "activeSessions": "Активне сесије", + "oops": "Упс!", + "somethingWentWrongPleaseTryAgain": "Нешто је пошло наопако, покушајте поново", + "thisWillLogYouOutOfThisDevice": "Ово ће вас одјавити са овог уређаја!", + "thisWillLogYouOutOfTheFollowingDevice": "Ово ће вас одјавити са овог уређаја:", + "terminateSession": "Прекинути сесију?", + "terminate": "Прекини", + "thisDevice": "Овај уређај", + "recoverButton": "Опорави", + "recoverySuccessful": "Опоравак успешан!", + "decrypting": "Дешифровање...", + "incorrectRecoveryKeyTitle": "Нетачан кључ за опоравак", + "incorrectRecoveryKeyBody": "Унети кључ за опоравак је натачан", + "forgotPassword": "Заборавио сам лозинку", + "enterYourRecoveryKey": "Унесите Ваш кључ за опоравак", + "noRecoveryKey": "Немате кључ за опоравак?", + "sorry": "Извините", + "noRecoveryKeyNoDecryption": "Због природе нашег протокола за крај-до-крај енкрипцију, ваши подаци не могу бити дешифровани без ваше лозинке или кључа за опоравак", + "verifyEmail": "Верификуј е-пошту", + "toResetVerifyEmail": "Да бисте ресетовали лозинку, прво потврдите своју е-пошту.", + "checkInboxAndSpamFolder": "Молимо вас да проверите примљену пошту (и нежељену пошту) да бисте довршили верификацију", + "tapToEnterCode": "Пипните да бисте унели кôд", + "resendEmail": "Поново пошаљи е-пошту", + "weHaveSendEmailTo": "Послали смо е-попту на {email}", + "@weHaveSendEmailTo": { + "description": "Text to indicate that we have sent a mail to the user", + "placeholders": { + "email": { + "description": "The email address of the user", + "type": "String", + "example": "example@ente.io" + } + } + }, + "setPasswordTitle": "Постави лозинку", + "changePasswordTitle": "Промени лозинку", + "resetPasswordTitle": "Ресетуј лозинку", + "encryptionKeys": "Кључеви шифровања", + "passwordWarning": "Не чувамо ову лозинку, па ако је заборавите, не можемо дешифрирати ваше податке", + "enterPasswordToEncrypt": "Унесите лозинку коју можемо да користимо за шифровање ваших података", + "enterNewPasswordToEncrypt": "Унесите нову лозинку коју можемо да користимо за шифровање ваших података", + "weakStrength": "Слабо", + "strongStrength": "Јако", + "moderateStrength": "Средње", + "passwordStrength": "Снага лозинке: {passwordStrengthValue}", + "@passwordStrength": { + "description": "Text to indicate the password strength", + "placeholders": { + "passwordStrengthValue": { + "description": "The strength of the password as a string", + "type": "String", + "example": "Weak or Moderate or Strong" + } + }, + "message": "Password Strength: {passwordStrengthText}" + }, + "passwordChangedSuccessfully": "Лозинка је успешно промењена", + "generatingEncryptionKeys": "Генерисање кључева за шифровање...", + "pleaseWait": "Молимо сачекајте...", + "continueLabel": "Настави", + "insecureDevice": "Уређај није сигуран", + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Извините, не можемо да генеришемо сигурне кључеве на овом уређају.\n\nМолимо пријавите се са другог уређаја.", + "howItWorks": "Како ради", + "encryption": "Шифровање", + "ackPasswordLostWarning": "Разумем да ако изгубим лозинку, могу изгубити своје податке пошто су шифрирани од краја до краја.", + "privacyPolicyTitle": "Политика приватности", + "termsOfServicesTitle": "Услови", + "signUpTerms": "Прихватам услове сервиса и политику приватности", + "logInLabel": "Пријави се", + "loginTerms": "Кликом на пријаву, прихватам услове сервиса и политику приватности", + "changeEmail": "Промени е-пошту", + "enterYourPassword": "Унесите лозинку", + "welcomeBack": "Добродошли назад!", + "contactSupport": "Контактирати подршку", + "incorrectPasswordTitle": "Неисправна лозинка", + "pleaseTryAgain": "Пробајте поново", + "recreatePasswordTitle": "Рекреирај лозинку", + "useRecoveryKey": "Користи кључ за опоравак", + "recreatePasswordBody": "Тренутни уређај није довољно моћан да потврди вашу лозинку, али можемо регенерирати на начин који ради са свим уређајима.\n\nПријавите се помоћу кључа за опоравак и обновите своју лозинку (можете поново користити исту ако желите).", + "verifyPassword": "Верификујте лозинку", + "recoveryKey": "Кључ за опоравак", + "recoveryKeyOnForgotPassword": "Ако заборавите лозинку, једини начин на који можете повратити податке је са овим кључем.", + "recoveryKeySaveDescription": "Не чувамо овај кључ, молимо да сачувате кључ од 24 речи на сигурном месту.", + "doThisLater": "Уради ово касније", + "saveKey": "Сачувај кључ", + "recoveryKeyCopiedToClipboard": "Кључ за опоравак је копиран у међуспремник", + "recoverAccount": "Опоравак налога", + "recover": "Опорави", + "dropSupportEmail": "Молимо Вас да пошаљете имејл на {supportEmail} са Ваше регистроване адресе е-поште", + "@dropSupportEmail": { + "placeholders": { + "supportEmail": { + "description": "The support email address", + "type": "String", + "example": "support@ente.io" + } + } + }, + "twofactorSetup": "Постављање двофакторске аутентификације", + "enterCode": "Унесите кôд", + "scanCode": "Скенирајте кôд", + "codeCopiedToClipboard": "Копирано у међуспремник", + "copypasteThisCodentoYourAuthenticatorApp": "Копирајте и налепите овај код \nу своју апликацију за аутентификацију", + "tapToCopy": "питисните да копирате", + "scanThisBarcodeWithnyourAuthenticatorApp": "Скенирајте овај баркод \nсвојом апликацијом за аутентификацију", + "enterThe6digitCodeFromnyourAuthenticatorApp": "Унесите 6-цифрени кôд из\nапликације за аутентификацију", + "confirm": "Потврди", + "setupComplete": "Постављање завршено", + "removeLink": "Уклони везу", + "manageLink": "Управљај везом", + "linkExpiresOn": "Веза ће истећи {expiryTime}", + "albumUpdated": "Албум ажуриран", + "never": "Никад", + "custom": "Прилагођено", + "@custom": { + "description": "Label for setting custom value for link expiry" + }, + "after1Hour": "Након 1 сата", + "after1Day": "Након 1 дана", + "after1Week": "Након 1 недеље", + "after1Month": "Након 1 месеца", + "after1Year": "Након 1 године", + "manageParticipants": "Управљај", + "albumParticipantsCount": "{count, plural, =0 {Нека учесника} =1 {1 учесник} other {{count} учесника}}", + "@albumParticipantsCount": { + "placeholders": { + "count": { + "type": "int", + "example": "5" + } + }, + "description": "Number of participants in an album, including the album owner." + }, + "collabLinkSectionDescription": "Креирајте везу која омогућава људима да додају и прегледају фотографије у вашем дељеном албуму без потребе за Енте апликацијом или налогом. Одлично за прикупљање фотографија са догађаја.", + "collectPhotos": "Прикупи фотографије", + "collaborativeLink": "Сарадничка веза", + "shareWithNonenteUsers": "Пошаљи корисницима који немају Енте налог", + "createPublicLink": "Креирај јавну везу", + "sendLink": "Пошаљи везу", + "copyLink": "Копирај везу", + "linkHasExpired": "Веза је истекла", + "publicLinkEnabled": "Јавна веза је укључена", + "shareALink": "Подели везу", + "sharedAlbumSectionDescription": "Креирај дељене и заједничке албуме са другим Енте корисницима, укључујући и оне на бесплатним плановима.", + "shareWithPeopleSectionTitle": "{numberOfPeople, plural, =0 {Подели са одређеним особама} =1 {Подељено са 1 особом} other {Подељено са {numberOfPeople} особа}}", + "@shareWithPeopleSectionTitle": { + "placeholders": { + "numberOfPeople": { + "type": "int", + "example": "2" + } + } + }, + "thisIsYourVerificationId": "Ово је Ваш ИД за верификацију", + "someoneSharingAlbumsWithYouShouldSeeTheSameId": "Особе које деле албуме с тобом би требале да виде исти ИД на свом уређају.", + "howToViewShareeVerificationID": "Молимо их да дуго притисну своју адресу е-поште на екрану за подешавања и провере да ли се ИД-ови на оба уређаја поклапају.", + "thisIsPersonVerificationId": "Ово је ИД за верификацију корисника {email}", + "@thisIsPersonVerificationId": { + "placeholders": { + "email": { + "type": "String", + "example": "someone@ente.io" + } + } + }, + "verificationId": "ИД за верификацију", + "verifyEmailID": "Верификуј {email}", + "emailNoEnteAccount": "{email} нема Енте налог.\n\nПошаљи им позивницу за дељење фотографија.", + "shareMyVerificationID": "Ево мог ИД-а за верификацију: {verificationID} за ente.io.", + "shareTextConfirmOthersVerificationID": "Здраво, можеш ли да потврдиш да је ово твој ente.io ИД за верификацију: {verificationID}", + "somethingWentWrong": "Нешто није у реду", + "sendInvite": "Пошаљи позивницу", + "shareTextRecommendUsingEnte": "Преузми Енте да бисмо лако делили фотографије и видео записе у оригиналном квалитету\n\nhttps://ente.io", + "done": "Готово", + "applyCodeTitle": "Примени кôд", + "enterCodeDescription": "Унеси код који ти је дао пријатељ да бисте обоје добили бесплатан простор за складиштење", + "apply": "Примени", + "failedToApplyCode": "Грешка у примењивању кôда", + "enterReferralCode": "Унеси реферални код", + "codeAppliedPageTitle": "Кôд примењен", + "changeYourReferralCode": "Промени свој реферални код", + "change": "Измени", + "unavailableReferralCode": "Жао нам је, овај кôд није доступан.", + "codeChangeLimitReached": "Жао нам је, достигли сте максимум броја промена кôда.", + "onlyFamilyAdminCanChangeCode": "Молимо вас да контактирате {familyAdminEmail} да бисте променили свој код.", + "storageInGB": "{storageAmountInGB} ГБ", + "youCannotShareWithYourself": "Не можеш делити сам са собом", + "archive": "Архивирај", + "createAlbumActionHint": "Дуго притисните да бисте изабрали фотографије и кликните на + да бисте направили албум", + "importing": "Увоз....", + "failedToLoadAlbums": "Грешка при учитавању албума", + "hidden": "Скривено", + "authToViewYourHiddenFiles": "Молимо вас да се аутентификујете да бисте видели скривене датотеке", + "authToViewTrashedFiles": "Молимо вас да се аутентификујете да бисте видели датотеке у отпаду", + "trash": "Смеће", + "uncategorized": "Некатегоризовано", + "videoSmallCase": "видео", + "photoSmallCase": "слика", + "singleFileDeleteHighlight": "Биће обрисано из свих албума.", + "singleFileInBothLocalAndRemote": "Овај {fileType} се налази и у Енте-у и на Вашем уређају.", + "singleFileInRemoteOnly": "Овај {fileType} ће бити избрисан из Енте-а.", + "singleFileDeleteFromDevice": "Овај {fileType} ће бити избрисан са твог уређаја.", + "deleteFromEnte": "Обриши са Енте-а", + "yesDelete": "Да, обриши", + "movedToTrash": "Премештено у смеће", + "deleteFromDevice": "Обриши са уређаја", + "deleteFromBoth": "Обриши са оба", + "newAlbum": "Нови албум", + "albums": "Албуми", + "memoryCount": "{count, plural, =0{нема сећања} one{{formattedCount} сећање} other{{formattedCount} сећања}}", + "@memoryCount": { + "description": "The text to display the number of memories", + "type": "text", + "placeholders": { + "count": { + "example": "1", + "type": "int" + }, + "formattedCount": { + "type": "String", + "example": "11.513, 11,511" + } + } + }, + "selectedPhotos": "{count} изабрано", + "@selectedPhotos": { + "description": "Display the number of selected photos", + "type": "text", + "placeholders": { + "count": { + "example": "5", + "type": "int" + } + } + }, + "selectedPhotosWithYours": "{count} изабрано ({yourCount} Ваше)", + "@selectedPhotosWithYours": { + "description": "Display the number of selected photos, including the number of selected photos owned by the user", + "type": "text", + "placeholders": { + "count": { + "example": "12", + "type": "int" + }, + "yourCount": { + "example": "2", + "type": "int" + } + } + }, + "advancedSettings": "Напредно", + "@advancedSettings": { + "description": "The text to display in the advanced settings section" + } } \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_sv.arb b/mobile/apps/photos/lib/l10n/intl_sv.arb index 85c0af754f..ccc0d6f882 100644 --- a/mobile/apps/photos/lib/l10n/intl_sv.arb +++ b/mobile/apps/photos/lib/l10n/intl_sv.arb @@ -364,7 +364,7 @@ "selectAll": "Markera allt", "skip": "Hoppa över", "updatingFolderSelection": "Uppdaterar mappval...", - "itemCount": "{count, plural, other{{count} objekt}}", + "itemCount": "{count, plural, one{{count} objekt} other{{count} objekt}}", "deleteItemCount": "{count, plural, =1 {Radera {count} objekt} other {Radera {count} objekt}}", "duplicateItemsGroup": "{count} filer, {formattedSize} vardera", "@duplicateItemsGroup": { @@ -382,7 +382,7 @@ } }, "showMemories": "Visa minnen", - "yearsAgo": "{count, plural, other{{count} år sedan}}", + "yearsAgo": "{count, plural, one{{count} år sedan} other{{count} år sedan}}", "backupSettings": "Säkerhetskopieringsinställningar", "backupStatus": "Säkerhetskopieringsstatus", "about": "Om", @@ -496,7 +496,7 @@ "viewAll": "Visa alla", "inviteYourFriendsToEnte": "Bjud in dina vänner till Ente", "fileTypes": "Filtyper", - "searchResultCount": "{count, plural, other{{count} resultat hittades}}", + "searchResultCount": "{count, plural, one{{count} resultat hittades} other{{count} resultat hittades}}", "@searchResultCount": { "description": "Text to tell user how many results were found for their search query", "placeholders": { @@ -532,4 +532,4 @@ "newPerson": "Ny person", "addName": "Lägg till namn", "add": "Lägg till" -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_tr.arb b/mobile/apps/photos/lib/l10n/intl_tr.arb index 74ec917187..880797894b 100644 --- a/mobile/apps/photos/lib/l10n/intl_tr.arb +++ b/mobile/apps/photos/lib/l10n/intl_tr.arb @@ -3,13 +3,13 @@ "enterYourEmailAddress": "E-posta adresinizi girin", "enterYourNewEmailAddress": "Yeni e-posta adresinizi girin", "accountWelcomeBack": "Tekrar hoş geldiniz!", - "emailAlreadyRegistered": "Bu e-posta adresi zaten kayıtlı.", - "emailNotRegistered": "Bu e-posta adresi sistemde kayıtlı değil.", + "emailAlreadyRegistered": "E-posta zaten kayıtlı.", + "emailNotRegistered": "E-posta kayıtlı değil.", "email": "E-Posta", "cancel": "İptal et", "verify": "Doğrula", "invalidEmailAddress": "Geçersiz e-posta adresi", - "enterValidEmail": "Lütfen geçerli bir E-posta adresi girin.", + "enterValidEmail": "Lütfen geçerli bir e-posta adresi girin.", "deleteAccount": "Hesabı sil", "askDeleteReason": "Hesabınızı silme sebebiniz nedir?", "deleteAccountFeedbackPrompt": "Gittiğini gördüğümüze üzüldük. Lütfen gelişmemize yardımcı olmak için neden ayrıldığınızı açıklayın.", @@ -70,7 +70,7 @@ "setPasswordTitle": "Parola ayarlayın", "changePasswordTitle": "Parolanızı değiştirin", "resetPasswordTitle": "Parolanızı sıfırlayın", - "encryptionKeys": "Sifreleme anahtarı", + "encryptionKeys": "Şifreleme anahtarı", "passwordWarning": "Şifrelerinizi saklamıyoruz, bu yüzden unutursanız, verilerinizi deşifre edemeyiz", "enterPasswordToEncrypt": "Verilerinizi şifrelemek için kullanabileceğimiz bir şifre girin", "enterNewPasswordToEncrypt": "Verilerinizi şifrelemek için kullanabileceğimiz yeni bir şifre girin", @@ -109,7 +109,7 @@ "contactSupport": "Destek ile iletişim", "incorrectPasswordTitle": "Yanlış şifre", "pleaseTryAgain": "Lütfen tekrar deneyiniz", - "recreatePasswordTitle": "Sifrenizi tekrardan oluşturun", + "recreatePasswordTitle": "Şifrenizi tekrardan oluşturun", "useRecoveryKey": "Kurtarma anahtarını kullan", "recreatePasswordBody": "Cihazınız, şifrenizi doğrulamak için yeterli güce sahip değil, ancak tüm cihazlarda çalışacak şekilde yeniden oluşturabiliriz.\n\nLütfen kurtarma anahtarınızı kullanarak giriş yapın ve şifrenizi yeniden oluşturun (istediğiniz takdirde aynı şifreyi tekrar kullanabilirsiniz).", "verifyPassword": "Şifrenizi doğrulayın", @@ -372,7 +372,7 @@ "deleteFromBoth": "Her ikisinden de sil", "newAlbum": "Yeni albüm", "albums": "Albümler", - "memoryCount": "{count, plural, =0{hiç anı yok} other{{formattedCount} anı}}", + "memoryCount": "{count, plural, =0{hiç anı yok} one{{formattedCount} anı} other{{formattedCount} anı}}", "@memoryCount": { "description": "The text to display the number of memories", "type": "text", @@ -477,7 +477,7 @@ } }, "showMemories": "Anıları göster", - "yearsAgo": "{count, plural, other{{count} yıl önce}}", + "yearsAgo": "{count, plural, one{{count} yıl önce} other{{count} yıl önce}}", "backupSettings": "Yedekleme seçenekleri", "backupStatus": "Yedekleme durumu", "backupStatusDescription": "Eklenen öğeler burada görünecek", @@ -496,7 +496,7 @@ "account": "Hesap", "manageSubscription": "Abonelikleri yönet", "authToChangeYourEmail": "E-postanızı değiştirmek için lütfen kimlik doğrulaması yapın", - "changePassword": "Sifrenizi değiştirin", + "changePassword": "Şifrenizi değiştirin", "authToChangeYourPassword": "Şifrenizi değiştirmek için lütfen kimlik doğrulaması yapın", "emailVerificationToggle": "E-posta doğrulama", "authToChangeEmailVerificationSetting": "E-posta doğrulamasını değiştirmek için lütfen kimlik doğrulaması yapın", @@ -1217,7 +1217,7 @@ "searchHint4": "Konum", "searchHint5": "Çok yakında: Yüzler ve sihirli arama ✨", "addYourPhotosNow": "Fotoğraflarınızı şimdi ekleyin", - "searchResultCount": "{count, plural, other{{count} yıl önce}}", + "searchResultCount": "{count, plural, one{{count} yıl önce} other{{count} yıl önce}}", "@searchResultCount": { "description": "Text to tell user how many results were found for their search query", "placeholders": { @@ -1730,9 +1730,63 @@ "food": "Yemek keyfi", "pets": "Tüylü dostlar", "curatedMemories": "Seçilmiş anılar", + "widgets": "Widget'lar", + "memories": "Anılar", + "peopleWidgetDesc": "Ana ekranınızda görmek istediğiniz kişileri seçin.", + "albumsWidgetDesc": "Ana ekranınızda görmek istediğiniz albümleri seçin.", + "memoriesWidgetDesc": "Ana ekranınızda görmek istediğiniz anı türünü seçin.", + "smartMemories": "Akıllı anılar", + "pastYearsMemories": "Geçmiş yılların anıları", "deleteMultipleAlbumDialog": "Ayrıca bu {count} albümde bulunan fotoğrafları (ve videoları) parçası oldukları tüm diğer albümlerden silmek istiyor musunuz?", "addParticipants": "Katılımcı ekle", "selectedAlbums": "{count} seçildi", "actionNotSupportedOnFavouritesAlbum": "Favoriler albümünde eylem desteklenmiyor", - "onThisDay": "Bu günde" -} + "onThisDayMemories": "Bugün anılar", + "onThisDay": "Bu günde", + "lookBackOnYourMemories": "Anılarına bir bak 🌄", + "newPhotosEmoji": " yeni 📸", + "sorryWeHadToPauseYourBackups": "Üzgünüm, yedeklemenizi duraklatmak zorunda kaldık", + "clickToInstallOurBestVersionYet": "Bugüne kadarki en iyi sürümümüzü yüklemek için tıklayın", + "onThisDayNotificationExplanation": "Önceki yıllarda bu günden anılar hakkında hatırlatıcılar alın.", + "addMemoriesWidgetPrompt": "Ana ekranınıza bir anılar widget'ı ekleyin ve özelleştirmek için buraya geri dönün.", + "addAlbumWidgetPrompt": "Ana ekranınıza bir albüm widget'ı ekleyin ve özelleştirmek için buraya geri dönün.", + "addPeopleWidgetPrompt": "Ana ekranınıza bir kişiler widget'ı ekleyin ve özelleştirmek için buraya geri dönün.", + "birthdayNotifications": "Doğum günü bildirimleri", + "receiveRemindersOnBirthdays": "Birinin doğum günü olduğunda hatırlatıcılar alın. Bildirime dokunmak sizi doğum günü kişisinin fotoğraflarına götürecektir.", + "happyBirthday": "Doğum günün kutlu olsun! 🥳", + "birthdays": "Doğum Günleri", + "wishThemAHappyBirthday": "{name} doğum günü kutlu olsun! 🎉", + "areYouSureRemoveThisFaceFromPerson": "Bu yüzü bu kişiden çıkarmak istediğine emin misin?", + "otherDetectedFaces": "Tespit edilen diğer yüzler", + "areThey": "Onlar mı ", + "questionmark": "?", + "saveAsAnotherPerson": "Başka bir kişi olarak kaydet", + "showLessFaces": "Daha az yüz göster", + "showMoreFaces": "Daha fazla yüz göster", + "ignore": "Yoksay", + "merge": "Birleştir", + "reset": "Sıfırla", + "areYouSureYouWantToIgnoreThisPerson": "Bu kişiyi görmezden gelmek istediğine emin misin?", + "areYouSureYouWantToIgnoreThesePersons": "Bu insanları görmezden gelmek istediğine emin misiniz?", + "thePersonGroupsWillNotBeDisplayed": "Kişi grupları artık kişiler bölümünde görüntülenmeyecek. Fotoğraflar dokunulmadan kalacaktır.", + "thePersonWillNotBeDisplayed": "Kişi artık kişiler bölümünde görüntülenmeyecek. Fotoğraflar dokunulmadan kalacaktır.", + "areYouSureYouWantToMergeThem": "Onları birleştirmek istediğine emin misiniz?", + "allUnnamedGroupsWillBeMergedIntoTheSelectedPerson": "Tüm isimsiz gruplar seçilen kişiyle birleştirilecektir. Bu, kişinin öneri geçmişine genel bakışından hala geri alınabilir.", + "yesIgnore": "Evet, görmezden gel", + "same": "Aynı", + "different": "Farklı", + "sameperson": "Aynı kişi mi?", + "cLTitle1": "Büyük Video Dosyalarını Yükleme", + "cLDesc1": "Video akışı beta sürümünün arkasında ve devam ettirilebilir yüklemeler ve indirmeler üzerinde çalışırken, artık dosya yükleme sınırını 10 GB'a çıkardık. Bu artık hem masaüstü hem de mobil uygulamalarda kullanılabilir.", + "cLTitle2": "Arka Plan Yükleme", + "cLDesc2": "Arka plan yüklemeleri artık Android cihazlara ek olarak iOS'ta da destekleniyor. En son fotoğraflarınızı ve videolarınızı yedeklemek için uygulamayı açmanıza gerek yok.", + "cLTitle3": "Otomatik Oynatma Anıları", + "cLDesc3": "Otomatik oynatma, bir sonraki belleğe kaydırma ve çok daha fazlası dahil olmak üzere bellek deneyimimizde önemli iyileştirmeler yaptık.", + "cLTitle4": "Geliştirilmiş Yüz Tanıma", + "cLDesc4": "Bazı arka plandaki iyileştirmelere ek olarak, artık tespit edilen tüm yüzleri görmek, benzer yüzler hakkında geri bildirimde bulunmak ve tek bir fotoğraftan yüz ekleyip çıkarmak çok daha kolay.", + "cLTitle5": "Doğum Günü Bildirimleri", + "cLDesc5": "Ente’ye kaydettiğiniz tüm doğum günleri için artık en iyi fotoğraflarından oluşan bir koleksiyonla birlikte, devre dışı bırakabileceğiniz bir bildirim alacaksınız.", + "cLTitle6": "Devam Ettirilebilir Yüklemeler ve İndirmeler", + "cLDesc6": "Uygulamayı kapatmadan önce yüklemelerin / indirmelerin tamamlanmasını beklemenize gerek yok. Tüm yüklemeler ve indirmeler artık yarıda duraklatma ve kaldığınız yerden devam etme özelliğine sahip.", + "indexingPausedStatusDescription": "Dizin oluşturma duraklatıldı. Cihaz hazır olduğunda otomatik olarak devam edecektir. Cihaz, pil seviyesi, pil sağlığı ve termal durumu sağlıklı bir aralıkta olduğunda hazır kabul edilir." +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_uk.arb b/mobile/apps/photos/lib/l10n/intl_uk.arb index 687d2dce87..dede53ef0e 100644 --- a/mobile/apps/photos/lib/l10n/intl_uk.arb +++ b/mobile/apps/photos/lib/l10n/intl_uk.arb @@ -438,7 +438,7 @@ "selectAll": "Вибрати все", "skip": "Пропустити", "updatingFolderSelection": "Оновлення вибору теки...", - "itemCount": "{count, plural, one{{count} елемент} other{{count} елементів}}", + "itemCount": "{count, plural, one{{count} елемент} few {{count} елементи} many {{count} елементів} other{{count} елементів}}", "deleteItemCount": "{count, plural, =1 {Видалено {count} елемент} other {Видалено {count} елементів}}", "duplicateItemsGroup": "{count} файлів, кожен по {formattedSize}", "@duplicateItemsGroup": { @@ -1172,7 +1172,7 @@ "searchHint4": "Розташування", "searchHint5": "Незабаром: Обличчя і магічний пошук ✨", "addYourPhotosNow": "Додайте свої фотографії", - "searchResultCount": "{count, plural, one{Знайдено {count} результат} other{Знайдено {count} результати}}", + "searchResultCount": "{count, plural, one{Знайдено {count} результат} few {Знайдено {count} результати} many {Знайдено {count} результатів} other{Знайдено {count} результати}}", "@searchResultCount": { "description": "Text to tell user how many results were found for their search query", "placeholders": { @@ -1510,4 +1510,4 @@ "legacyInvite": "{email} запросив вас стати довіреною особою", "authToManageLegacy": "Авторизуйтесь, щоби керувати довіреними контактами", "useDifferentPlayerInfo": "Виникли проблеми з відтворенням цього відео? Натисніть і утримуйте тут, щоб спробувати інший плеєр." -} +} \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_vi.arb b/mobile/apps/photos/lib/l10n/intl_vi.arb index 71b8c7a80f..156d3e99b6 100644 --- a/mobile/apps/photos/lib/l10n/intl_vi.arb +++ b/mobile/apps/photos/lib/l10n/intl_vi.arb @@ -34,7 +34,7 @@ "password": "Mật khẩu", "confirmPassword": "Xác nhận mật khẩu", "activeSessions": "Phiên hoạt động", - "oops": "Ốiii!", + "oops": "Ốii!", "somethingWentWrongPleaseTryAgain": "Có gì đó không ổn, vui lòng thử lại", "thisWillLogYouOutOfThisDevice": "Bạn sẽ đăng xuất khỏi thiết bị này!", "thisWillLogYouOutOfTheFollowingDevice": "Bạn cũng sẽ đăng xuất khỏi những thiết bị sau:", @@ -95,19 +95,19 @@ "continueLabel": "Tiếp tục", "insecureDevice": "Thiết bị không an toàn", "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Rất tiếc, chúng tôi không thể tạo khóa an toàn trên thiết bị này.\n\nVui lòng đăng ký từ một thiết bị khác.", - "howItWorks": "Cách hoạt động", + "howItWorks": "Cách thức hoạt động", "encryption": "Mã hóa", - "ackPasswordLostWarning": "Tôi hiểu rằng nếu tôi mất mật khẩu, tôi có thể mất dữ liệu của mình vì dữ liệu của tôi được mã hóa đầu cuối.", + "ackPasswordLostWarning": "Tôi hiểu rằng nếu mất mật khẩu, dữ liệu của tôi sẽ mất vì nó được mã hóa đầu cuối.", "privacyPolicyTitle": "Chính sách bảo mật", "termsOfServicesTitle": "Điều khoản", - "signUpTerms": "Tôi đồng ý điều khoảnchính sách bảo mật", + "signUpTerms": "Tôi đồng ý với điều khoảnchính sách bảo mật", "logInLabel": "Đăng nhập", - "loginTerms": "Nhấn vào đăng nhập, tôi đồng ý điều khoảnchính sách bảo mật", + "loginTerms": "Nhấn vào đăng nhập, tôi đồng ý với điều khoảnchính sách bảo mật", "changeEmail": "Đổi email", "enterYourPassword": "Nhập mật khẩu của bạn", "welcomeBack": "Chào mừng trở lại!", "contactSupport": "Liên hệ hỗ trợ", - "incorrectPasswordTitle": "Mật khẩu không chính xác", + "incorrectPasswordTitle": "Mật khẩu không đúng", "pleaseTryAgain": "Vui lòng thử lại", "recreatePasswordTitle": "Tạo lại mật khẩu", "useRecoveryKey": "Dùng mã khôi phục", @@ -115,7 +115,7 @@ "verifyPassword": "Xác minh mật khẩu", "recoveryKey": "Mã khôi phục", "recoveryKeyOnForgotPassword": "Nếu bạn quên mật khẩu, cách duy nhất để khôi phục dữ liệu của bạn là dùng mã này.", - "recoveryKeySaveDescription": "Chúng tôi không lưu trữ mã này, nên hãy lưu nó ở một nơi an toàn.", + "recoveryKeySaveDescription": "Chúng tôi không lưu trữ mã này, nên hãy lưu nó ở nơi an toàn.", "doThisLater": "Để sau", "saveKey": "Lưu mã", "recoveryKeyCopiedToClipboard": "Đã sao chép mã khôi phục vào bộ nhớ tạm", @@ -167,7 +167,7 @@ }, "you": "Bạn", "collaborator": "Cộng tác viên", - "addMore": "Thêm nữa", + "addMore": "Thêm nhiều hơn", "@addMore": { "description": "Button text to add more collaborators/viewers" }, @@ -191,7 +191,7 @@ "canNotOpenTitle": "Không thể mở album này", "canNotOpenBody": "Rất tiếc, album này không thể mở trong ứng dụng.", "disableDownloadWarningTitle": "Xin lưu ý", - "disableDownloadWarningBody": "Người xem vẫn có thể chụp ảnh màn hình hoặc sao chép ảnh của bạn bằng các công cụ bên ngoài", + "disableDownloadWarningBody": "Người xem vẫn có thể chụp màn hình hoặc sao chép ảnh của bạn bằng các công cụ bên ngoài", "allowDownloads": "Cho phép tải xuống", "linkDeviceLimit": "Giới hạn thiết bị", "noDeviceLimit": "Không có", @@ -231,7 +231,7 @@ }, "description": "Number of participants in an album, including the album owner." }, - "collabLinkSectionDescription": "Tạo một liên kết để cho phép mọi người thêm và xem ảnh trong album chia sẻ của bạn mà không cần ứng dụng hoặc tài khoản Ente. Tuyệt vời để thu thập ảnh sự kiện.", + "collabLinkSectionDescription": "Tạo một liên kết cho phép mọi người thêm và xem ảnh trong album chia sẻ của bạn mà không cần ứng dụng hoặc tài khoản Ente. Phù hợp để thu thập ảnh sự kiện.", "collectPhotos": "Thu thập ảnh", "collaborativeLink": "Liên kết cộng tác", "shareWithNonenteUsers": "Chia sẻ với người không dùng Ente", @@ -268,7 +268,7 @@ "emailNoEnteAccount": "{email} không có tài khoản Ente.\n\nGửi họ một lời mời để chia sẻ ảnh.", "shareMyVerificationID": "Đây là ID xác minh của tôi: {verificationID} cho ente.io.", "shareTextConfirmOthersVerificationID": "Chào, bạn có thể xác nhận rằng đây là ID xác minh ente.io của bạn: {verificationID}", - "somethingWentWrong": "Có điều gì đó không đúng", + "somethingWentWrong": "Có gì đó không ổn", "sendInvite": "Gửi lời mời", "shareTextRecommendUsingEnte": "Tải Ente để chúng ta có thể dễ dàng chia sẻ ảnh và video chất lượng gốc\n\nhttps://ente.io", "done": "Xong", @@ -316,7 +316,7 @@ }, "faq": "Câu hỏi thường gặp", "help": "Trợ giúp", - "oopsSomethingWentWrong": "Ốiii!, có điều gì đó không đúng", + "oopsSomethingWentWrong": "Ốii!, có gì đó không ổn", "peopleUsingYourCode": "Người dùng mã của bạn", "eligible": "đủ điều kiện", "total": "tổng", @@ -337,7 +337,7 @@ "canOnlyRemoveFilesOwnedByYou": "Chỉ có thể xóa các tệp thuộc sở hữu của bạn", "deleteSharedAlbum": "Xóa album chia sẻ?", "deleteAlbum": "Xóa album", - "deleteAlbumDialog": "Xóa luôn các tấm ảnh (và video) có trong album này khỏi toàn bộ album khác cũng đang chứa chúng?", + "deleteAlbumDialog": "Xóa luôn ảnh (và video) trong album này khỏi toàn bộ album khác cũng đang chứa chúng?", "deleteSharedAlbumDialogBody": "Album sẽ bị xóa với tất cả mọi người\n\nBạn sẽ mất quyền truy cập vào các ảnh chia sẻ trong album này mà thuộc sở hữu của người khác", "yesRemove": "Có, xóa", "creatingLink": "Đang tạo liên kết...", @@ -372,7 +372,7 @@ "deleteFromBoth": "Xóa khỏi cả hai", "newAlbum": "Album mới", "albums": "Album", - "memoryCount": "{count, plural, =0{chưa có ảnh} other{{formattedCount} ảnh}}", + "memoryCount": "{count, plural, =0{chưa có kỷ niệm} other{{formattedCount} kỷ niệm}}", "@memoryCount": { "description": "The text to display the number of memories", "type": "text", @@ -436,7 +436,7 @@ "discover_receipts": "Biên lai", "discover_notes": "Ghi chú", "discover_memes": "Meme", - "discover_visiting_cards": "Thẻ", + "discover_visiting_cards": "Danh thiếp", "discover_babies": "Em bé", "discover_pets": "Thú cưng", "discover_selfies": "Selfie", @@ -481,7 +481,7 @@ "backupSettings": "Cài đặt sao lưu", "backupStatus": "Trạng thái sao lưu", "backupStatusDescription": "Các mục đã được sao lưu sẽ hiển thị ở đây", - "backupOverMobileData": "Sao lưu bằng dữ liệu di động", + "backupOverMobileData": "Sao lưu với dữ liệu di động", "backupVideos": "Sao lưu video", "disableAutoLock": "Vô hiệu hóa khóa tự động", "deviceLockExplanation": "Vô hiệu hóa khóa màn hình thiết bị khi Ente đang ở chế độ nền và có một bản sao lưu đang diễn ra. Điều này thường không cần thiết, nhưng có thể giúp tải lên các tệp lớn và tệp nhập của các thư viện lớn xong nhanh hơn.", @@ -899,8 +899,8 @@ "authToViewYourMemories": "Vui lòng xác thực để xem kỷ niệm", "unlock": "Mở khóa", "freeUpSpace": "Giải phóng dung lượng", - "freeUpSpaceSaving": "{count, plural, =1 {Có thể xóa khỏi thiết bị để giải phóng {formattedSize}} other {Có thể xóa khỏi thiết bị để giải phóng {formattedSize}}}", - "filesBackedUpInAlbum": "{count, plural, other {{formattedNumber} tệp}} trong album này đã được sao lưu an toàn", + "freeUpSpaceSaving": "{count, plural, =1 {Xóa chúng khỏi thiết bị để giải phóng {formattedSize}} other {Xóa chúng khỏi thiết bị để giải phóng {formattedSize}}}", + "filesBackedUpInAlbum": "{count, plural, other {{formattedNumber} tệp}} trong album đã được sao lưu an toàn", "@filesBackedUpInAlbum": { "description": "Text to tell user how many files have been backed up in the album", "placeholders": { @@ -915,7 +915,7 @@ } } }, - "filesBackedUpFromDevice": "{count, plural, other {{formattedNumber} tệp}} trên thiết bị này đã được sao lưu an toàn", + "filesBackedUpFromDevice": "{count, plural, other {{formattedNumber} tệp}} trên thiết bị đã được sao lưu an toàn", "@filesBackedUpFromDevice": { "description": "Text to tell user how many files have been backed up from this device", "placeholders": { @@ -933,7 +933,7 @@ "@freeUpSpaceSaving": { "description": "Text to tell user how much space they can free up by deleting items from the device" }, - "freeUpAccessPostDelete": "Bạn vẫn có thể truy cập {count, plural, =1 {chúng} other {chúng}} trên Ente miễn là bạn có một gói đăng ký", + "freeUpAccessPostDelete": "Bạn vẫn có thể truy cập {count, plural, =1 {chúng} other {chúng}} trên Ente, miễn là gói của bạn còn hiệu lực", "@freeUpAccessPostDelete": { "placeholders": { "count": { @@ -962,7 +962,7 @@ "disablingTwofactorAuthentication": "Đang vô hiệu hóa xác thực 2 bước...", "allMemoriesPreserved": "Tất cả kỷ niệm đã được lưu giữ", "loadingGallery": "Đang tải thư viện...", - "syncing": "Đang đồng bộ hóa...", + "syncing": "Đang đồng bộ...", "encryptingBackup": "Đang mã hóa sao lưu...", "syncStopped": "Đồng bộ hóa đã dừng", "syncProgress": "{completed}/{total} kỷ niệm đã được lưu giữ", @@ -1006,26 +1006,26 @@ "someItemsAreInBothEnteAndYourDevice": "Một số mục có trên cả Ente và thiết bị của bạn.", "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": "Các tệp đã chọn sẽ bị xóa khỏi tất cả album và cho vào thùng rác.", "theseItemsWillBeDeletedFromYourDevice": "Các mục này sẽ bị xóa khỏi thiết bị của bạn.", - "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Có vẻ như đã xảy ra sự cố. Vui lòng thử lại sau một thời gian. Nếu lỗi vẫn tiếp diễn, vui lòng liên hệ với đội ngũ hỗ trợ của chúng tôi.", + "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Có vẻ đã xảy ra sự cố. Vui lòng thử lại sau ít phút. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với đội ngũ hỗ trợ của chúng tôi.", "error": "Lỗi", - "tempErrorContactSupportIfPersists": "Có vẻ như đã xảy ra sự cố. Vui lòng thử lại sau một thời gian. Nếu lỗi vẫn tiếp diễn, vui lòng liên hệ với đội ngũ hỗ trợ.", + "tempErrorContactSupportIfPersists": "Có vẻ đã xảy ra sự cố. Vui lòng thử lại sau ít phút. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với đội ngũ hỗ trợ của chúng tôi.", "networkHostLookUpErr": "Không thể kết nối với Ente, vui lòng kiểm tra cài đặt mạng của bạn và liên hệ với bộ phận hỗ trợ nếu lỗi vẫn tiếp diễn.", - "networkConnectionRefusedErr": "Không thể kết nối với Ente, vui lòng thử lại sau một thời gian. Nếu lỗi vẫn tiếp diễn, vui lòng liên hệ với bộ phận hỗ trợ.", + "networkConnectionRefusedErr": "Không thể kết nối với Ente, vui lòng thử lại sau ít phút. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với bộ phận hỗ trợ.", "cachedData": "Dữ liệu đã lưu trong bộ nhớ đệm", "clearCaches": "Xóa bộ nhớ cache", - "remoteImages": "Hình ảnh bên ngoài", + "remoteImages": "Ảnh bên ngoài", "remoteVideos": "Video bên ngoài", - "remoteThumbnails": "Hình thu nhỏ bên ngoài", + "remoteThumbnails": "Ảnh thu nhỏ bên ngoài", "pendingSync": "Đồng bộ hóa đang chờ", "localGallery": "Thư viện cục bộ", - "todaysLogs": "Log hôm nay", - "viewLogs": "Xem log", - "logsDialogBody": "Gửi file log để chúng tôi có thể phân tích lỗi mà bạn gặp. Lưu ý rằng, trong nhật ký lỗi sẽ bao gồm tên các tệp để giúp theo dõi vấn đề với từng tệp cụ thể.", - "preparingLogs": "Đang ghi log...", - "emailYourLogs": "Gửi log qua email", - "pleaseSendTheLogsTo": "Vui lòng gửi file log đến \n{toEmail}", + "todaysLogs": "Nhật ký hôm nay", + "viewLogs": "Xem nhật ký", + "logsDialogBody": "Gửi file nhật ký để chúng tôi có thể phân tích lỗi mà bạn gặp. Lưu ý rằng, trong nhật ký lỗi sẽ bao gồm tên các tệp để giúp theo dõi vấn đề với từng tệp cụ thể.", + "preparingLogs": "Đang ghi nhật ký...", + "emailYourLogs": "Gửi nhật ký qua email", + "pleaseSendTheLogsTo": "Vui lòng gửi nhật ký đến \n{toEmail}", "copyEmailAddress": "Sao chép địa chỉ email", - "exportLogs": "Xuất file log", + "exportLogs": "Xuất nhật ký", "pleaseEmailUsAt": "Vui lòng gửi email cho chúng tôi tại {toEmail}", "dismiss": "Bỏ qua", "didYouKnow": "Bạn có biết?", @@ -1045,7 +1045,7 @@ "moments": "Khoảnh khắc", "searchFaceEmptySection": "Người sẽ được hiển thị ở đây khi quá trình xử lý hoàn tất", "searchDatesEmptySection": "Tìm kiếm theo ngày, tháng hoặc năm", - "searchLocationEmptySection": "Ảnh nhóm được chụp trong một bán kính nào đó của một bức ảnh", + "searchLocationEmptySection": "Xếp nhóm những ảnh được chụp gần kề nhau", "searchPeopleEmptySection": "Mời mọi người, và bạn sẽ thấy tất cả ảnh mà họ chia sẻ ở đây", "searchAlbumsEmptySection": "Album", "searchFileTypesAndNamesEmptySection": "Loại tệp và tên", @@ -1058,11 +1058,11 @@ "kiloMeterUnit": "km", "addLocationButton": "Thêm", "radius": "Bán kính", - "locationTagFeatureDescription": "Một thẻ vị trí sẽ chia nhóm tất cả các ảnh được chụp trong một bán kính nào đó của một bức ảnh", - "galleryMemoryLimitInfo": "Mỗi thư viện chứa tối đa 1000 ảnh", + "locationTagFeatureDescription": "Thẻ vị trí sẽ giúp xếp nhóm tất cả ảnh được chụp gần kề nhau", + "galleryMemoryLimitInfo": "Mỗi thư viện chứa tối đa 1000 ảnh và video", "save": "Lưu", - "centerPoint": "Điểm trung tâm", - "pickCenterPoint": "Chọn điểm trung tâm", + "centerPoint": "Tâm điểm", + "pickCenterPoint": "Chọn tâm điểm", "useSelectedPhoto": "Sử dụng ảnh đã chọn", "resetToDefault": "Đặt lại mặc định", "@resetToDefault": { @@ -1080,25 +1080,25 @@ "doYouWantToDiscardTheEditsYouHaveMade": "Bạn có muốn bỏ qua các chỉnh sửa đã thực hiện không?", "saving": "Đang lưu...", "editsSaved": "Chỉnh sửa đã được lưu", - "oopsCouldNotSaveEdits": "Ốiii, không thể lưu chỉnh sửa", + "oopsCouldNotSaveEdits": "Ốii!, không thể lưu chỉnh sửa", "distanceInKMUnit": "km", "@distanceInKMUnit": { "description": "Unit for distance in km" }, "dayToday": "Hôm nay", "dayYesterday": "Hôm qua", - "storage": "Lưu trữ", + "storage": "Dung lượng", "usedSpace": "Dung lượng đã dùng", "storageBreakupFamily": "Gia đình", "storageBreakupYou": "Bạn", "@storageBreakupYou": { "description": "Label to indicate how much storage you are using when you are part of a family plan" }, - "storageUsageInfo": "{usedAmount} {usedStorageUnit} trên {totalAmount} {totalStorageUnit} đã sử dụng", + "storageUsageInfo": "{usedAmount} {usedStorageUnit} / {totalAmount} {totalStorageUnit} đã dùng", "@storageUsageInfo": { "description": "Example: 1.2 GB of 2 GB used or 100 GB or 2TB used" }, - "availableStorageSpace": "{freeAmount} {storageUnit} còn trống", + "availableStorageSpace": "{freeAmount} {storageUnit} trống", "appVersion": "Phiên bản: {versionValue}", "verifyIDLabel": "Xác minh", "fileInfoAddDescHint": "Thêm mô tả...", @@ -1170,7 +1170,7 @@ }, "maps": "Bản đồ", "enableMaps": "Kích hoạt Bản đồ", - "enableMapsDesc": "Ảnh của bạn sẽ hiển thị trên bản đồ thế giới.\n\nBản đồ được lưu trữ bởi OpenStreetMap, và vị trí chính xác ảnh của bạn không bao giờ được chia sẻ.\n\nBạn có thể tắt tính năng này bất cứ lúc nào từ Cài đặt.", + "enableMapsDesc": "Ảnh của bạn sẽ hiển thị trên bản đồ thế giới.\n\nBản đồ được lưu trữ bởi OpenStreetMap và vị trí chính xác ảnh của bạn không bao giờ được chia sẻ.\n\nBạn có thể tắt tính năng này bất cứ lúc nào từ Cài đặt.", "quickLinks": "Liên kết nhanh", "selectItemsToAdd": "Chọn mục để thêm", "addSelected": "Thêm mục đã chọn", @@ -1178,7 +1178,7 @@ "addPhotos": "Thêm ảnh", "noPhotosFoundHere": "Không tìm thấy ảnh ở đây", "zoomOutToSeePhotos": "Phóng to để xem ảnh", - "noImagesWithLocation": "Không có hình ảnh với vị trí", + "noImagesWithLocation": "Không có ảnh ở vị trí này", "unpinAlbum": "Bỏ ghim album", "pinAlbum": "Ghim album", "create": "Tạo", @@ -1205,12 +1205,12 @@ "addOns": "Tiện ích mở rộng", "addOnPageSubtitle": "Chi tiết về tiện ích mở rộng", "yourMap": "Bản đồ của bạn", - "modifyYourQueryOrTrySearchingFor": "Chỉnh sửa truy vấn của bạn, hoặc thử tìm kiếm", + "modifyYourQueryOrTrySearchingFor": "Chỉnh sửa truy vấn của bạn, hoặc thử tìm", "blackFridaySale": "Giảm giá Black Friday", "upto50OffUntil4thDec": "Giảm tới 50%, đến ngày 4 Tháng 12.", "photos": "Ảnh", "videos": "Video", - "livePhotos": "Ảnh Live", + "livePhotos": "Ảnh động", "searchHint1": "Tìm kiếm nhanh, trên thiết bị", "searchHint2": "Ngày chụp, mô tả ảnh", "searchHint3": "Album, tên tệp và loại", @@ -1257,9 +1257,9 @@ "loginSessionExpiredDetails": "Phiên đăng nhập của bạn đã hết hạn. Vui lòng đăng nhập lại.", "verifyPasskey": "Xác minh khóa truy cập", "playOnTv": "Phát album trên TV", - "pair": "Ghép nối", + "pair": "Kết nối", "deviceNotFound": "Không tìm thấy thiết bị", - "castInstruction": "Truy cập cast.ente.io trên thiết bị bạn muốn ghép nối.\n\nNhập mã dưới đây để phát album trên TV của bạn.", + "castInstruction": "Truy cập cast.ente.io trên thiết bị bạn muốn kết nối.\n\nNhập mã dưới đây để phát album trên TV của bạn.", "deviceCodeHint": "Nhập mã", "joinDiscord": "Tham gia Discord", "locations": "Vị trí", @@ -1292,20 +1292,20 @@ "enterDateOfBirth": "Sinh nhật (tùy chọn)", "birthday": "Sinh nhật", "removePersonLabel": "Xóa nhãn người", - "autoPairDesc": "Ghép nối tự động chỉ hoạt động với các thiết bị hỗ trợ Chromecast.", - "manualPairDesc": "Ghép nối với PIN hoạt động với bất kỳ màn hình nào bạn muốn xem album của mình.", + "autoPairDesc": "Kết nối tự động chỉ hoạt động với các thiết bị hỗ trợ Chromecast.", + "manualPairDesc": "Kết nối bằng PIN hoạt động với bất kỳ màn hình nào bạn muốn.", "connectToDevice": "Kết nối với thiết bị", - "autoCastDialogBody": "Bạn sẽ thấy các thiết bị Cast có sẵn ở đây.", + "autoCastDialogBody": "Bạn sẽ thấy các thiết bị phát khả dụng ở đây.", "autoCastiOSPermission": "Hãy chắc rằng quyền Mạng cục bộ đã được bật cho ứng dụng Ente Photos, trong Cài đặt.", "noDeviceFound": "Không tìm thấy thiết bị", "stopCastingTitle": "Dừng phát", "stopCastingBody": "Bạn có muốn dừng phát không?", "castIPMismatchTitle": "Không thể phát album", "castIPMismatchBody": "Hãy chắc rằng bạn đang dùng chung mạng với TV.", - "pairingComplete": "Ghép nối hoàn tất", + "pairingComplete": "Kết nối hoàn tất", "savingEdits": "Đang lưu chỉnh sửa...", - "autoPair": "Ghép nối tự động", - "pairWithPin": "Ghép nối với PIN", + "autoPair": "Kết nối tự động", + "pairWithPin": "Kết nối bằng PIN", "faceRecognition": "Nhận diện khuôn mặt", "foundFaces": "Đã tìm thấy khuôn mặt", "clusteringProgress": "Tiến trình phân cụm", @@ -1329,7 +1329,7 @@ } }, "enable": "Bật", - "enabled": "Đã bật", + "enabled": "Bật", "moreDetails": "Thêm chi tiết", "enableMLIndexingDesc": "Ente hỗ trợ học máy trên-thiết-bị nhằm nhận diện khuôn mặt, tìm kiếm vi diệu và các tính năng tìm kiếm nâng cao khác", "magicSearchHint": "Tìm kiếm vi diệu cho phép tìm ảnh theo nội dung của chúng, ví dụ: 'xe hơi', 'xe hơi đỏ', 'Ferrari'", @@ -1368,7 +1368,7 @@ "authToViewPasskey": "Vui lòng xác thực để xem khóa truy cập", "loopVideoOn": "Phát video lặp lại", "loopVideoOff": "Dừng phát video lặp lại", - "localSyncErrorMessage": "Có vẻ như có điều gì đó không ổn vì đồng bộ hóa ảnh cục bộ đang mất nhiều thời gian hơn mong đợi. Vui lòng liên hệ đội ngũ hỗ trợ của chúng tôi", + "localSyncErrorMessage": "Có vẻ như có điều gì đó không ổn vì đồng bộ ảnh cục bộ đang tốn nhiều thời gian hơn mong đợi. Vui lòng liên hệ đội ngũ hỗ trợ của chúng tôi", "showPerson": "Hiện người", "sort": "Sắp xếp", "mostRecent": "Mới nhất", @@ -1401,7 +1401,7 @@ "onlyThem": "Chỉ họ", "checkingModels": "Đang kiểm tra mô hình...", "enableMachineLearningBanner": "Bật học máy để tìm kiếm vi diệu và nhận diện khuôn mặt", - "searchDiscoverEmptySection": "Hình ảnh sẽ được hiển thị ở đây sau khi hoàn tất xử lý và đồng bộ", + "searchDiscoverEmptySection": "Ảnh sẽ được hiển thị ở đây sau khi xử lý và đồng bộ hoàn tất", "searchPersonsEmptySection": "Người sẽ được hiển thị ở đây sau khi hoàn tất xử lý và đồng bộ", "viewersSuccessfullyAdded": "{count, plural, =0 {Chưa thêm người xem} =1 {Đã thêm 1 người xem} other {Đã thêm {count} người xem}}", "@viewersSuccessfullyAdded": { @@ -1662,14 +1662,14 @@ "@linkPersonCaption": { "description": "Caption for the 'Link person' title. It should be a continuation of the 'Link person' title. Just like how 'Link person' + 'for better sharing experience' forms a proper sentence in English, the combination of these two strings should also be a proper sentence in other languages." }, - "videoStreaming": "Video có thể phát", + "videoStreaming": "Phát trực tuyến video", "processingVideos": "Đang xử lý video", "streamDetails": "Chi tiết phát", "processing": "Đang xử lý", "queued": "Đang chờ", "ineligible": "Không đủ điều kiện", "failed": "Không thành công", - "playStream": "Phát", + "playStream": "Phát trực tiếp", "playOriginal": "Phát tệp gốc", "joinAlbumConfirmationDialogBody": "Tham gia một album sẽ khiến email của bạn hiển thị với những người tham gia khác.", "pleaseWaitThisWillTakeAWhile": "Vui lòng chờ, có thể mất một lúc.", @@ -1729,7 +1729,7 @@ "onTheRoad": "Trên đường", "food": "Ăn chơi", "pets": "Thú cưng", - "curatedMemories": "Ký ức lưu giữ", + "curatedMemories": "Kỷ niệm đáng nhớ", "widgets": "Tiện ích", "memories": "Kỷ niệm", "peopleWidgetDesc": "Chọn những người bạn muốn thấy trên màn hình chính của mình.", @@ -1737,7 +1737,7 @@ "memoriesWidgetDesc": "Chọn những loại kỷ niệm bạn muốn thấy trên màn hình chính của mình.", "smartMemories": "Gợi nhớ kỷ niệm", "pastYearsMemories": "Kỷ niệm năm ngoái", - "deleteMultipleAlbumDialog": "Xóa luôn các tấm ảnh (và video) có trong {count} album khỏi toàn bộ album khác cũng đang chứa chúng?", + "deleteMultipleAlbumDialog": "Xóa luôn ảnh (và video) trong {count} album này khỏi toàn bộ album khác cũng đang chứa chúng?", "addParticipants": "Thêm người tham gia", "selectedAlbums": "{count} đã chọn", "actionNotSupportedOnFavouritesAlbum": "Hành động không áp dụng trong album Đã thích", @@ -1781,12 +1781,14 @@ "cLTitle2": "Tải lên trong nền", "cLDesc2": "Tải lên trong nền hiện đã hỗ trợ trên iOS và Android. Không cần phải mở ứng dụng để sao lưu ảnh và video mới nhất của bạn.", "cLTitle3": "Tự động phát kỷ niệm", - "cLDesc3": "Chúng tôi đã có những cải tiến đáng kể cho trải nghiệm kỷ niệm, bao gồm phát tự động, vuốt đến kỷ niệm tiếp theo và nhiều tính năng khác.", + "cLDesc3": "Chúng tôi đã có những cải tiến đáng kể cho trải nghiệm kỷ niệm, bao gồm tự phát, vuốt xem kỷ niệm tiếp theo và nhiều tính năng khác.", "cLTitle4": "Cải thiện nhận diện khuôn mặt", "cLDesc4": "Cùng với một loạt cải tiến nội bộ, giờ đây bạn có thể dễ dàng xem tất cả khuôn mặt đã phát hiện, cung cấp phản hồi về các khuôn mặt giống nhau và thêm/xóa khuôn mặt khỏi một bức ảnh.", "cLTitle5": "Thông báo sinh nhật", "cLDesc5": "Bây giờ bạn sẽ nhận được thông báo tùy-chọn cho tất cả các ngày sinh nhật mà bạn đã lưu trên Ente, cùng với bộ sưu tập những bức ảnh đẹp nhất của họ.", "cLTitle6": "Tiếp tục tải lên và tải xuống", "cLDesc6": "Không còn phải chờ tải lên/tải xuống xong mới có thể đóng ứng dụng. Tất cả các tải lên và tải xuống hiện có thể tạm dừng giữa chừng và tiếp tục từ nơi bạn đã dừng lại.", - "indexingPausedStatusDescription": "Lập chỉ mục bị tạm dừng. Nó sẽ tự động tiếp tục khi thiết bị đã sẵn sàng. Thiết bị được coi là sẵn sàng khi mức pin, tình trạng pin và trạng thái nhiệt độ nằm trong phạm vi tốt." + "indexingPausedStatusDescription": "Lập chỉ mục bị tạm dừng. Nó sẽ tự động tiếp tục khi thiết bị đã sẵn sàng. Thiết bị được coi là sẵn sàng khi mức pin, tình trạng pin và trạng thái nhiệt độ nằm trong phạm vi tốt.", + "faceThumbnailGenerationFailed": "Không thể tạo ảnh thu nhỏ khuôn mặt", + "fileAnalysisFailed": "Không thể xác định tệp" } \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_zh.arb b/mobile/apps/photos/lib/l10n/intl_zh.arb index f96d61d305..a8db49277e 100644 --- a/mobile/apps/photos/lib/l10n/intl_zh.arb +++ b/mobile/apps/photos/lib/l10n/intl_zh.arb @@ -459,7 +459,7 @@ "selectAll": "全选", "skip": "跳过", "updatingFolderSelection": "正在更新文件夹选择...", - "itemCount": "{count, plural, other{{count} 个项目}}", + "itemCount": "{count, plural, one{{count} 个项目} other{{count} 个项目}}", "deleteItemCount": "{count, plural, =1 {删除 {count} 个项目} other {删除 {count} 个项目}}", "duplicateItemsGroup": "{count} 个文件,每个文件 {formattedSize}", "@duplicateItemsGroup": { @@ -477,7 +477,7 @@ } }, "showMemories": "显示回忆", - "yearsAgo": "{count, plural, other{{count} 年前}}", + "yearsAgo": "{count, plural, one{{count} 年前} other{{count} 年前}}", "backupSettings": "备份设置", "backupStatus": "备份状态", "backupStatusDescription": "已备份的项目将显示在此处", @@ -1789,4 +1789,4 @@ "cLTitle6": "可恢复的上传和下载", "cLDesc6": "无需等待上传/下载完成即可关闭应用程序。所有上传和下载现在都可以中途暂停,并从中断处继续。", "indexingPausedStatusDescription": "索引已暂停。待设备准备就绪后,索引将自动恢复。当设备的电池电量、电池健康度和温度状态处于健康范围内时,设备即被视为准备就绪。" -} +} \ No newline at end of file From 4a346c47d160ba4cf6c3973346f386850b3a6afa Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 18 Jul 2025 16:25:26 +0530 Subject: [PATCH 58/81] Complete --- web/apps/photos/src/components/FileList.tsx | 126 ++++++++++---------- 1 file changed, 65 insertions(+), 61 deletions(-) diff --git a/web/apps/photos/src/components/FileList.tsx b/web/apps/photos/src/components/FileList.tsx index 3d5d382a7a..3edf76e8d2 100644 --- a/web/apps/photos/src/components/FileList.tsx +++ b/web/apps/photos/src/components/FileList.tsx @@ -73,45 +73,55 @@ export interface FileListHeaderOrFooter { * Data needed to render each row in the variable size list that comprises the * file list. */ -type FileListItem = { - /** - * The height of the row that will render this item. - */ - height: number; - type: "date" | "file" | "span"; - /** - * Groups of items that are shown in the row. - * - * Each group spans multiple columns (the number of columns being given by - * the length of {@link annotatedFiles} or the {@link span}). Groups are - * separated by gaps. - */ - fGroups?: { - /** - * The annotated files in this group. - */ - annotatedFiles: FileListAnnotatedFile[]; - /** - * The index of the first annotated file in the component's global list - * of annotated files. - */ - annotatedFilesStartIndex: number; - }[]; - dGroups?: { - /** - * The date string to show. - */ - date: string; - /** - * The number of columns to span. - */ - dateSpan: number; - }[]; - /** - * The React component that is the rendered representation of the item. - */ - component?: React.ReactNode; -} & Pick; +type FileListItem = + | { + type: "file"; + /** + * The height of the row that will render this item. + */ + height: number; + /** + * Groups of items that are shown in the row. + * + * Each group spans multiple columns (the number of columns being given by + * the length of {@link annotatedFiles} or the {@link span}). Groups are + * separated by gaps. + */ + groups: { + /** + * The annotated files in this group. + */ + annotatedFiles: FileListAnnotatedFile[]; + /** + * The index of the first annotated file in the component's global list + * of annotated files. + */ + annotatedFilesStartIndex: number; + }[]; + } + | { + type: "date"; + height: number; + groups: { + /** + * The date string to show. + */ + date: string; + /** + * The number of columns to span. + */ + dateSpan: number; + }[]; + } + | { + type: "span"; + height: number; + /** + * The React component that is the rendered representation of the item. + */ + component: React.ReactNode; + extendToInlineEdges?: boolean; + }; export interface FileListAnnotatedFile { file: EnteFile; @@ -288,7 +298,7 @@ export const FileList: React.FC = ({ (batchFiles, batchIndex) => ({ height: fileItemHeight, type: "file", - fGroups: [ + groups: [ { annotatedFiles: batchFiles, annotatedFilesStartIndex: batchIndex * columns, @@ -305,7 +315,7 @@ export const FileList: React.FC = ({ ({ height: fileItemHeight, type: "file", - fGroups: splits.map((split) => { + groups: splits.map((split) => { const group = { annotatedFiles: split, annotatedFilesStartIndex: fileIndex, @@ -322,7 +332,7 @@ export const FileList: React.FC = ({ items.push({ height: dateListItemHeight, type: "date", - dGroups: splits.map((s) => ({ + groups: splits.map((s) => ({ date: s[0]!.timelineDateString, dateSpan: s.length, })), @@ -334,7 +344,7 @@ export const FileList: React.FC = ({ items.push({ height: dateListItemHeight, type: "date", - dGroups: splits.map((s) => ({ + groups: splits.map((s) => ({ date: s[0]!.timelineDateString, dateSpan: columns, })), @@ -423,8 +433,6 @@ export const FileList: React.FC = ({ listRef.current?.resetAfterIndex(0); }, [items]); - // TODO: Too many non-null assertions - useEffect(() => { const notSelectedFiles = annotatedFiles.filter( (af) => !selected[af.file.id], @@ -563,7 +571,7 @@ export const FileList: React.FC = ({ switch (item.type) { case "date": return intersperseWithGaps( - item.dGroups!, + item.groups, ({ date, dateSpan }) => [ {haveSelection && ( @@ -587,7 +595,7 @@ export const FileList: React.FC = ({ ); case "file": return intersperseWithGaps( - item.fGroups!, + item.groups, ({ annotatedFiles, annotatedFilesStartIndex }) => annotatedFiles.map((annotatedFile, j) => { const file = annotatedFile.file; @@ -646,7 +654,7 @@ export const FileList: React.FC = ({
), ); - default: + case "span": return item.component; } }, @@ -684,10 +692,10 @@ export const FileList: React.FC = ({ const item = itemData.items[index]!; switch (item.type) { case "date": - return `date-${item.dGroups![0]!.date}-${index}`; + return `date-${item.groups[0]!.date}-${index}`; case "file": - return `file-${item.fGroups![0]!.annotatedFilesStartIndex}-${index}`; - default: + return `file-${item.groups[0]!.annotatedFilesStartIndex}-${index}`; + case "span": return `span-${index}`; } }, []); @@ -713,9 +721,6 @@ export const FileList: React.FC = ({ } return ( - // TODO(RE): - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore { switch (item.type) { case "date": - return item.dGroups!.map((g) => g.dateSpan); + return item.groups.map((g) => g.dateSpan); case "file": - return item.fGroups!.map((g) => g.annotatedFiles.length); - default: + return item.groups.map((g) => g.annotatedFiles.length); + case "span": return []; } })(); + const px = + item.type == "span" && item.extendToInlineEdges ? 0 : paddingInline; return ( 0 && { display: "grid", gridTemplateColumns: itemSpans From efa82b7fb7c0b9fc062b5d92140bb10abfc82fc4 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 18 Jul 2025 17:42:16 +0530 Subject: [PATCH 59/81] Scaffold --- web/apps/locker/.env | 1 + web/apps/locker/eslint.config.mjs | 1 + web/apps/locker/next.config.js | 1 + web/apps/locker/package.json | 11 +++++++++ web/apps/locker/public/images/favicon.png | Bin 0 -> 1125 bytes web/apps/locker/src/pages/_app.tsx | 24 ++++++++++++++++++++ web/apps/locker/src/pages/index.tsx | 14 ++++++++++++ web/apps/locker/tsconfig.json | 13 +++++++++++ web/package.json | 2 ++ web/packages/accounts/services/redirect.ts | 1 + web/packages/base/app.ts | 10 +++++++- web/packages/base/components/utils/theme.ts | 13 ++++++++++- 12 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 web/apps/locker/.env create mode 100644 web/apps/locker/eslint.config.mjs create mode 100644 web/apps/locker/next.config.js create mode 100644 web/apps/locker/package.json create mode 100644 web/apps/locker/public/images/favicon.png create mode 100644 web/apps/locker/src/pages/_app.tsx create mode 100644 web/apps/locker/src/pages/index.tsx create mode 100644 web/apps/locker/tsconfig.json diff --git a/web/apps/locker/.env b/web/apps/locker/.env new file mode 100644 index 0000000000..3f3b1cc9ae --- /dev/null +++ b/web/apps/locker/.env @@ -0,0 +1 @@ +NEXT_TELEMETRY_DISABLED = 1 diff --git a/web/apps/locker/eslint.config.mjs b/web/apps/locker/eslint.config.mjs new file mode 100644 index 0000000000..641d994d1e --- /dev/null +++ b/web/apps/locker/eslint.config.mjs @@ -0,0 +1 @@ +export { default } from "ente-build-config/eslintrc-next-app.mjs"; diff --git a/web/apps/locker/next.config.js b/web/apps/locker/next.config.js new file mode 100644 index 0000000000..5a52794ab2 --- /dev/null +++ b/web/apps/locker/next.config.js @@ -0,0 +1 @@ +module.exports = require("ente-base/next.config.base.js"); diff --git a/web/apps/locker/package.json b/web/apps/locker/package.json new file mode 100644 index 0000000000..63a5218abb --- /dev/null +++ b/web/apps/locker/package.json @@ -0,0 +1,11 @@ +{ + "name": "locker", + "version": "0.0.0", + "private": true, + "dependencies": { + "ente-base": "*" + }, + "devDependencies": { + "ente-build-config": "*" + } +} diff --git a/web/apps/locker/public/images/favicon.png b/web/apps/locker/public/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..fcb8d1054bb23170d91f396130a78262fb261c84 GIT binary patch literal 1125 zcmV-r1e*JaP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G5V7|p|h4mL9B zgfT7-q9*DY49jCH7k8tQ_RjWv-4;z9yxWq?MJ21&H9&wE~r z;laD_hpByjl9xv=mwV1V=iKkP2w+6tT#BmF`eXJn4h;ePbA)+mL&{XnJgW#>#y{QO$Z_oCr|VML;_Tuh0+|;Vl8L9e@m%B*tP;_Cyie8%1~|sE@VQ+bFJ8 zu=uTn_g{-{mUHd^8O|I^;RJh|kqk}g@0Csi+46JD)$(wH5Xqg_>?UOgR$p^d!A(J8 zO!-sgy_gx_bgY5vh5IPBDu!{t>_ck&BzSNgpz!yTV_`Ql-ph+xeqbyaoZ`;sra>fORQ-_n(Bl@fRCf7)rI@Nc+!s2MTRMJju@WP$1Esa< zfCB=1vgJ8!C)^a6H5G;BpOn###J(7u!d1d@yM`-~B!(>uRFdZDgpmom# = ({ Component, pageProps }) => { + useSetupLogs({ disableDiskLogs: true }); + + // We don't provide BaseContext. Nothing in the cast app needs it yet. + + return ( + + + + + + ); +}; + +export default App; diff --git a/web/apps/locker/src/pages/index.tsx b/web/apps/locker/src/pages/index.tsx new file mode 100644 index 0000000000..348024e30f --- /dev/null +++ b/web/apps/locker/src/pages/index.tsx @@ -0,0 +1,14 @@ +import { Stack, Typography } from "@mui/material"; +import { EnteLogo } from "ente-base/components/EnteLogo"; +import React from "react"; + +const Page: React.FC = () => { + return ( + + + Coming soon + + ); +}; + +export default Page; diff --git a/web/apps/locker/tsconfig.json b/web/apps/locker/tsconfig.json new file mode 100644 index 0000000000..cd371d81f7 --- /dev/null +++ b/web/apps/locker/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "ente-build-config/tsconfig-next.json", + "compilerOptions": { + /* Set the base directory from which to resolve bare module names. */ + "baseUrl": "./src" + }, + "include": [ + "src", + "next-env.d.ts", + "../../packages/base/global-electron.d.ts", + "../../packages/base/components/utils/mui-theme.d.ts" + ] +} diff --git a/web/package.json b/web/package.json index bce3a8e7e9..54d327a93f 100644 --- a/web/package.json +++ b/web/package.json @@ -11,6 +11,7 @@ "build:accounts": "yarn workspace accounts next build", "build:auth": "yarn workspace auth next build", "build:cast": "yarn workspace cast next build", + "build:locker": "yarn workspace locker next build", "build:payments": "yarn workspace payments build", "build:photos": "yarn workspace photos next build", "dev": "yarn dev:photos", @@ -18,6 +19,7 @@ "dev:albums": "yarn workspace photos next dev -p 3002", "dev:auth": "yarn workspace auth next dev -p 3003", "dev:cast": "yarn workspace cast next dev -p 3004", + "dev:locker": "yarn workspace locker next dev -p 3005", "dev:payments": "yarn workspace payments dev", "dev:photos": "yarn workspace photos next dev -p 3000", "lint": "concurrently --names 'prettier,eslint,tsc' \"yarn prettier --check --log-level warn .\" \"yarn workspaces run eslint\" \"yarn workspaces run tsc\"", diff --git a/web/packages/accounts/services/redirect.ts b/web/packages/accounts/services/redirect.ts index 19791d2894..1277963018 100644 --- a/web/packages/accounts/services/redirect.ts +++ b/web/packages/accounts/services/redirect.ts @@ -9,6 +9,7 @@ export const appHomeRoute: string = { accounts: "/passkeys", auth: "/auth", cast: "/" /* The cast app doesn't use this, this is an arbitrary value. */, + locker: "/" /* The locker app also doesn't use this. */, photos: "/gallery", }[appName]; diff --git a/web/packages/base/app.ts b/web/packages/base/app.ts index e330e41a83..014ec98a76 100644 --- a/web/packages/base/app.ts +++ b/web/packages/base/app.ts @@ -1,4 +1,10 @@ -export const appNames = ["accounts", "auth", "cast", "photos"] as const; +export const appNames = [ + "accounts", + "auth", + "cast", + "locker", + "photos", +] as const; /** * Arbitrary names that we used as keys for indexing various constants @@ -56,6 +62,7 @@ export const staticAppTitle = { accounts: "Ente Accounts", auth: "Ente Auth", cast: "Ente Photos", + locker: "Ente Locker", photos: "Ente Photos", }[appName]; @@ -77,6 +84,7 @@ export const clientPackageName = (() => { accounts: "io.ente.accounts.web", auth: "io.ente.auth.web", cast: "io.ente.cast.web", + locker: "io.ente.locker.web", photos: "io.ente.photos.web", }[appName]; })(); diff --git a/web/packages/base/components/utils/theme.ts b/web/packages/base/components/utils/theme.ts index 2c1ea3aa14..0c79a7414e 100644 --- a/web/packages/base/components/utils/theme.ts +++ b/web/packages/base/components/utils/theme.ts @@ -125,7 +125,12 @@ const getColors = (appName: AppName) => ({ }, }, ...{ - accent: appName == "auth" ? _colors.accentAuth : _colors.accentPhotos, + accent: + appName == "auth" + ? _colors.accentAuth + : appName == "locker" + ? _colors.accentLocker + : _colors.accentPhotos, }, }); @@ -139,6 +144,7 @@ const getColors = (appName: AppName) => ({ const _colors = { accentPhotos: { dark: "#00b33c", main: "#1db954", light: "#01de4d" }, accentAuth: { dark: "#8e0fcb", main: "#9610d6", light: "#8e2de2" }, + accentLocker: { dark: "#615bff", main: "#5ba8ff", light: "#5bf9ff" }, fixed: { white: "#fff", black: "#000", @@ -764,3 +770,8 @@ export const authTheme = getTheme("auth"); * This is the same as the dark theme for the photos app. */ export const castTheme = getTheme("cast"); + +/** + * The MUI {@link Theme} to use for the locker app. + */ +export const lockerTheme = getTheme("locker"); From e08f97e543350472589c8d3211bb277df2f783ec Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 18 Jul 2025 18:36:30 +0530 Subject: [PATCH 60/81] Setup publish --- .github/workflows/web-deploy.yml | 10 ++++++++++ web/apps/locker/src/pages/index.tsx | 18 +++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.github/workflows/web-deploy.yml b/.github/workflows/web-deploy.yml index 32fee17ad4..6c2691ca35 100644 --- a/.github/workflows/web-deploy.yml +++ b/.github/workflows/web-deploy.yml @@ -93,3 +93,13 @@ jobs: accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} command: pages deploy --project-name=ente --commit-dirty=true --branch=deploy/payments web/apps/payments/dist + + - name: Build locker + run: yarn build:locker + + - name: Publish locker + uses: cloudflare/wrangler-action@v3 + with: + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + command: pages deploy --project-name=ente --commit-dirty=true --branch=deploy/locker web/apps/locker/out diff --git a/web/apps/locker/src/pages/index.tsx b/web/apps/locker/src/pages/index.tsx index 348024e30f..32f0bcde2a 100644 --- a/web/apps/locker/src/pages/index.tsx +++ b/web/apps/locker/src/pages/index.tsx @@ -4,9 +4,21 @@ import React from "react"; const Page: React.FC = () => { return ( - - - Coming soon + + + + Locker + + — Coming soon — ); }; From 087ba629e03c314a662e840f0bb41744fcc5b358 Mon Sep 17 00:00:00 2001 From: Sven Date: Fri, 18 Jul 2025 22:33:24 +0200 Subject: [PATCH 61/81] add MangaDex icon and metadata to custom icons --- mobile/apps/auth/assets/custom-icons/_data/custom-icons.json | 4 ++++ mobile/apps/auth/assets/custom-icons/icons/mangadex.svg | 1 + 2 files changed, 5 insertions(+) create mode 100644 mobile/apps/auth/assets/custom-icons/icons/mangadex.svg diff --git a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json index 8b36b7c252..703bd7419a 100644 --- a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json +++ b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json @@ -739,6 +739,10 @@ "lu.ma" ] }, + { + "title": "MangaDex", + "slug": "mangadex" + }, { "title": "Marketplace.tf", "slug": "marketplacedottf" diff --git a/mobile/apps/auth/assets/custom-icons/icons/mangadex.svg b/mobile/apps/auth/assets/custom-icons/icons/mangadex.svg new file mode 100644 index 0000000000..8c273d3679 --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/mangadex.svg @@ -0,0 +1 @@ + \ No newline at end of file From 054ad8b4806c03a5000687fdfe037b32cb3eb2ef Mon Sep 17 00:00:00 2001 From: Murad Khalil Date: Sun, 20 Jul 2025 23:15:27 +0200 Subject: [PATCH 62/81] add numerai and nasdaq icons --- .../apps/auth/assets/custom-icons/icons/nasdaq.svg | 12 ++++++++++++ .../apps/auth/assets/custom-icons/icons/numerai.svg | 1 + 2 files changed, 13 insertions(+) create mode 100644 mobile/apps/auth/assets/custom-icons/icons/nasdaq.svg create mode 100644 mobile/apps/auth/assets/custom-icons/icons/numerai.svg diff --git a/mobile/apps/auth/assets/custom-icons/icons/nasdaq.svg b/mobile/apps/auth/assets/custom-icons/icons/nasdaq.svg new file mode 100644 index 0000000000..761481e2b2 --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/nasdaq.svg @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/mobile/apps/auth/assets/custom-icons/icons/numerai.svg b/mobile/apps/auth/assets/custom-icons/icons/numerai.svg new file mode 100644 index 0000000000..d9bd424b93 --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/numerai.svg @@ -0,0 +1 @@ + \ No newline at end of file From 641dfdd11ea308a9d16e5204dd38ae4c820b587a Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 21 Jul 2025 00:45:09 +0000 Subject: [PATCH 63/81] New Crowdin translations by GitHub Action --- .../base/locales/es-ES/translation.json | 22 +++++++++---------- .../base/locales/pl-PL/translation.json | 4 ++-- .../base/locales/tr-TR/translation.json | 4 ++-- .../base/locales/zh-HK/translation.json | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index d1a4378a02..1d3d91cf93 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -32,7 +32,7 @@ "set_password": "Definir contraseña", "sign_in": "Ingresar", "incorrect_password": "Contraseña incorrecta", - "incorrect_password_or_no_account": "", + "incorrect_password_or_no_account": "Contraseña incorrecta o correo electrónico no registrado", "pick_password_hint": "Introducir una contraseña que podamos usar para cifrar sus datos", "pick_password_caution": "No guardamos su contraseña, así que si la olvida, no podremos ayudarte a recuperar tus datos sin una clave de recuperación.", "key_generation_in_progress": "Generando claves de encriptación...", @@ -40,7 +40,7 @@ "referral_source_hint": "¿Cómo conociste Ente? (opcional)", "referral_source_info": "No rastreamos la instalación de las aplicaciones. ¡Nos ayudaría si nos dijera dónde nos encontró!", "password_mismatch_error": "Las contraseñas no coinciden", - "show_or_hide_password": "", + "show_or_hide_password": "Mostrar u ocultar la contraseña", "welcome_to_ente_title": "Bienvenido a ", "welcome_to_ente_subtitle": "Almacenamiento y compartición de fotos cifradas de extremo a extremo", "new_album": "Nuevo álbum", @@ -162,7 +162,7 @@ "ok": "OK", "success": "Completado", "error": "Error", - "note": "", + "note": "Nota", "offline_message": "Estás desconectado, se están mostrando recuerdos en caché", "install": "Instalar", "install_mobile_app": "Instala nuestra aplicación Android o iOS para hacer una copia de seguridad automática de todas usted fotos", @@ -627,7 +627,7 @@ "faster_upload_description": "Enrutar subidas a través de servidores cercanos", "open_ente_on_startup": "Abrir ente al iniciar", "cast_album_to_tv": "Reproducir álbum en TV", - "cast_to_tv": "", + "cast_to_tv": "Reproducir en el televisor", "enter_cast_pin_code": "Introduce el código que ves en el televisor para emparejar este dispositivo.", "code": "Código", "pair_device_to_tv": "Emparejar dispositivos", @@ -679,11 +679,11 @@ "system": "Sistema", "light": "Claro", "dark": "Oscuro", - "streamable_videos": "", - "processing_videos_status": "", - "share_favorites": "", - "person_favorites": "", - "shared_favorites": "", - "added_by_name": "", - "unowned_files_not_processed": "" + "streamable_videos": "Vídeos en streaming", + "processing_videos_status": "Procesando vídeos...", + "share_favorites": "Compartir favoritos", + "person_favorites": "Los favoritos de {{name}}", + "shared_favorites": "Favoritos compartidos", + "added_by_name": "Añadido por {{name}}", + "unowned_files_not_processed": "Los archivos añadidos por otros usuarios no han sido procesados" } diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 0eb8b4c74d..ecbbff918f 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -59,7 +59,7 @@ "select_photos": "Wybierz zdjęcia", "file_upload": "Przesył plików", "preparing": "Przygotowywanie", - "processed_counts": "", + "processed_counts": "{{count, number}} / {{total, number}}", "upload_reading_metadata_files": "Czytanie plików metadanych", "upload_cancelling": "Anulowanie pozostałych przesłań", "upload_done": "", @@ -496,7 +496,7 @@ "yes_stop": "Tak, zatrzymaj", "change_folder": "Zmień Folder", "view_logs": "Wyświetl logi", - "view_logs_message": "", + "view_logs_message": "

Spowoduje to wyświetlenie logów debugowania, które możesz wysłać do nas na e-maila, aby pomóc w debugowaniu Twojego problemu.

Należy pamiętać, że nazwy plików będą dołączone, aby pomóc w śledzeniu problemów z konkretnymi plikami.

", "weak_device_hint": "Przeglądarka, której używasz nie jest wystarczająco silna, aby zaszyfrować Twoje zdjęcia. Prosimy zalogować się do Ente na Twoim komputerze lub pobierz aplikacje mobilną/komputerową Ente.", "drag_and_drop_hint": "Lub przeciągnij i upuść do okna Ente", "authenticate": "Uwierzytelnij się", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index b1cf846414..627ac8aa91 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -162,7 +162,7 @@ "ok": "Tamam", "success": "Başarılı", "error": "Hata", - "note": "", + "note": "Not", "offline_message": "Çevrimdışısın, önbelleğe alınmış anılar gösteriliyor", "install": "Kur", "install_mobile_app": "Tüm fotoğraflarını otomatik olarak yedeklemek için Android veya iOS uygulamamızı yükle", @@ -685,5 +685,5 @@ "person_favorites": "{{name}}'in favorileri", "shared_favorites": "Paylaşılan favoriler", "added_by_name": "{{name}} tarafından eklendi", - "unowned_files_not_processed": "" + "unowned_files_not_processed": "Diğer kullanıcılar tarafından eklenen dosyalar işlenmedi" } diff --git a/web/packages/base/locales/zh-HK/translation.json b/web/packages/base/locales/zh-HK/translation.json index 05fbcc6e4d..bdfed3f70f 100644 --- a/web/packages/base/locales/zh-HK/translation.json +++ b/web/packages/base/locales/zh-HK/translation.json @@ -77,7 +77,7 @@ "audio": "音訊", "more": "更多", "mouse_scroll": "", - "pan": "", + "pan": "橫移", "pinch": "", "drag": "拖曳", "tap_inside_image": "", From 2ff5058a3e9c3408898af5a066b853716f658bac Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 21 Jul 2025 01:05:20 +0000 Subject: [PATCH 64/81] New Crowdin translations by GitHub Action --- mobile/apps/photos/lib/l10n/intl_pl.arb | 6 +++++- mobile/apps/photos/lib/l10n/intl_ru.arb | 4 +++- mobile/apps/photos/lib/l10n/intl_vi.arb | 6 +++--- mobile/apps/photos/lib/l10n/intl_zh.arb | 4 +++- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/mobile/apps/photos/lib/l10n/intl_pl.arb b/mobile/apps/photos/lib/l10n/intl_pl.arb index 7ad308c900..cffa0d1a43 100644 --- a/mobile/apps/photos/lib/l10n/intl_pl.arb +++ b/mobile/apps/photos/lib/l10n/intl_pl.arb @@ -1602,6 +1602,7 @@ "processing": "Przetwarzanie", "queued": "W kolejce", "ineligible": "Nie kwalifikuje się", + "failed": "Nie powiodło się", "playOriginal": "Odtwórz oryginał", "joinAlbumConfirmationDialogBody": "Dołączenie do albumu sprawi, że Twój e-mail będzie widoczny dla jego uczestników.", "pleaseWaitThisWillTakeAWhile": "Prosimy czekać, to może zająć chwilę.", @@ -1621,6 +1622,7 @@ "appIcon": "Ikona aplikacji", "notThisPerson": "Nie ta osoba?", "selectedItemsWillBeRemovedFromThisPerson": "Wybrane elementy zostaną usunięte z tej osoby, ale nie zostaną usunięte z Twojej biblioteki.", + "throughTheYears": "{dateFormat} przez lata", "thisWeekThroughTheYears": "Ten tydzień przez lata", "youAndThem": "Ty i {name}", "admiringThem": "Podziwianie {name}", @@ -1705,5 +1707,7 @@ "cLDesc5": "Od teraz otrzymasz powiadomienie z możliwością rezygnacji dotyczące wszystkich zapisanych urodzin w Ente, wraz z kolekcją najlepszych zdjęć danej osoby.", "cLTitle6": "Wznawialne Przesyłanie i Pobieranie Danych", "cLDesc6": "Nie musisz już czekać na zakończenie przesyłania ani pobierania, żeby móc zamknąć aplikację. Wszystkie operacje przesyłania i pobierania można teraz wstrzymać w dowolnym momencie i wznowić od miejsca, w którym zostały przerwane.", - "indexingPausedStatusDescription": "Indeksowanie zostało wstrzymane. Zostanie automatycznie wznowione, gdy urządzenie będzie gotowe. Urządzenie uznaje się za gotowe, gdy poziom baterii, stan jej zdrowia oraz status termiczny znajdują się w bezpiecznym zakresie." + "indexingPausedStatusDescription": "Indeksowanie zostało wstrzymane. Zostanie automatycznie wznowione, gdy urządzenie będzie gotowe. Urządzenie uznaje się za gotowe, gdy poziom baterii, stan jej zdrowia oraz status termiczny znajdują się w bezpiecznym zakresie.", + "faceThumbnailGenerationFailed": "Nie można wygenerować miniaturek twarzy", + "fileAnalysisFailed": "Nie można przeanalizować pliku" } \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_ru.arb b/mobile/apps/photos/lib/l10n/intl_ru.arb index 99d7e093f3..6a0a4a65e7 100644 --- a/mobile/apps/photos/lib/l10n/intl_ru.arb +++ b/mobile/apps/photos/lib/l10n/intl_ru.arb @@ -1788,5 +1788,7 @@ "cLDesc5": "Теперь вы будете получать уведомления о всех днях рождениях, которые вы сохранили на Ente, а также коллекцию их лучших фотографий.", "cLTitle6": "Возобновляемые загрузки и скачивания", "cLDesc6": "Больше не нужно ждать завершения загрузки/скачивания, прежде чем закрыть приложение. Все загрузки и скачивания теперь можно приостановить и возобновить с того места, где вы остановились.", - "indexingPausedStatusDescription": "Индексирование приостановлено. Оно автоматически возобновится, когда устройство будет готово. Устройство считается готовым, когда уровень заряда батареи, её состояние и температура находятся в пределах нормы." + "indexingPausedStatusDescription": "Индексирование приостановлено. Оно автоматически возобновится, когда устройство будет готово. Устройство считается готовым, когда уровень заряда батареи, её состояние и температура находятся в пределах нормы.", + "faceThumbnailGenerationFailed": "Не удалось создать миниатюры лиц", + "fileAnalysisFailed": "Не удалось проанализировать файл" } \ No newline at end of file diff --git a/mobile/apps/photos/lib/l10n/intl_vi.arb b/mobile/apps/photos/lib/l10n/intl_vi.arb index 156d3e99b6..952bff39bb 100644 --- a/mobile/apps/photos/lib/l10n/intl_vi.arb +++ b/mobile/apps/photos/lib/l10n/intl_vi.arb @@ -825,8 +825,8 @@ "doubleYourStorage": "Gấp đôi dung lượng lưu trữ của bạn", "referFriendsAnd2xYourPlan": "Giới thiệu bạn bè và ×2 gói của bạn", "shareAlbumHint": "Mở album và nhấn nút chia sẻ ở góc trên bên phải để chia sẻ.", - "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": "Các mục hiện số ngày còn lại trước khi xóa vĩnh viễn", - "trashDaysLeft": "{count, plural, =0 {Sắp tới} =1 {1 ngày} other {{count} ngày}}", + "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": "Trên các mục là số ngày còn lại trước khi xóa vĩnh viễn", + "trashDaysLeft": "{count, plural, =0 {Sắp xóa} =1 {1 ngày} other {{count} ngày}}", "@trashDaysLeft": { "description": "Text to indicate number of days remaining before permanent deletion", "placeholders": { @@ -1178,7 +1178,7 @@ "addPhotos": "Thêm ảnh", "noPhotosFoundHere": "Không tìm thấy ảnh ở đây", "zoomOutToSeePhotos": "Phóng to để xem ảnh", - "noImagesWithLocation": "Không có ảnh ở vị trí này", + "noImagesWithLocation": "Không có ảnh với vị trí", "unpinAlbum": "Bỏ ghim album", "pinAlbum": "Ghim album", "create": "Tạo", diff --git a/mobile/apps/photos/lib/l10n/intl_zh.arb b/mobile/apps/photos/lib/l10n/intl_zh.arb index a8db49277e..e9ba03d3f0 100644 --- a/mobile/apps/photos/lib/l10n/intl_zh.arb +++ b/mobile/apps/photos/lib/l10n/intl_zh.arb @@ -1788,5 +1788,7 @@ "cLDesc5": "您现在将收到 Ente 上保存的所有生日的可选退出通知,同时附上他们最佳照片的合集。", "cLTitle6": "可恢复的上传和下载", "cLDesc6": "无需等待上传/下载完成即可关闭应用程序。所有上传和下载现在都可以中途暂停,并从中断处继续。", - "indexingPausedStatusDescription": "索引已暂停。待设备准备就绪后,索引将自动恢复。当设备的电池电量、电池健康度和温度状态处于健康范围内时,设备即被视为准备就绪。" + "indexingPausedStatusDescription": "索引已暂停。待设备准备就绪后,索引将自动恢复。当设备的电池电量、电池健康度和温度状态处于健康范围内时,设备即被视为准备就绪。", + "faceThumbnailGenerationFailed": "无法生成人脸缩略图", + "fileAnalysisFailed": "无法分析文件" } \ No newline at end of file From 1f0f240f97224ebb0fd88bc360055e3eaa2f5749 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 21 Jul 2025 01:18:10 +0000 Subject: [PATCH 65/81] New Crowdin translations by GitHub Action --- mobile/apps/auth/lib/l10n/arb/app_be.arb | 90 ++++++++++++++++++++++++ mobile/apps/auth/lib/l10n/arb/app_es.arb | 8 ++- mobile/apps/auth/lib/l10n/arb/app_et.arb | 25 ++++++- mobile/apps/auth/lib/l10n/arb/app_vi.arb | 2 +- 4 files changed, 122 insertions(+), 3 deletions(-) diff --git a/mobile/apps/auth/lib/l10n/arb/app_be.arb b/mobile/apps/auth/lib/l10n/arb/app_be.arb index 47168446a0..d1719f4549 100644 --- a/mobile/apps/auth/lib/l10n/arb/app_be.arb +++ b/mobile/apps/auth/lib/l10n/arb/app_be.arb @@ -78,6 +78,7 @@ "contactSupport": "Звярнуцца ў службу падтрымкі", "rateUsOnStore": "Ацаніць нас у {storeName}", "blog": "Блог", + "merchandise": "Тавары", "verifyPassword": "Праверыць пароль", "pleaseWait": "Пачакайце...", "generatingEncryptionKeysTitle": "Генерацыя ключоў шыфравання...", @@ -85,6 +86,9 @@ "useRecoveryKey": "Выкарыстоўваць ключ аднаўлення", "incorrectPasswordTitle": "Няправільны пароль", "welcomeBack": "З вяртаннем!", + "emailAlreadyRegistered": "Электронная пошта ўжо зарэгістравана.", + "emailNotRegistered": "Электронная пошта не зарэгістравана.", + "madeWithLoveAtPrefix": "зроблена з ❤️ у ", "changeEmail": "Змяніць адрас электроннай пошты", "changePassword": "Змяніць пароль", "data": "Даныя", @@ -94,9 +98,13 @@ "passwordForDecryptingExport": "Пароль для дэшыфроўкі экспартавання", "passwordEmptyError": "Пароль не можа быць пустым", "importFromApp": "Імпартаваць коды з {appName}", + "importSelectJsonFile": "Выбраць файл JSON", + "importSelectAppExport": "Выберыце файл экспартавання {appName}", "exportCodes": "Экспартаваць коды", "importLabel": "Імпарт", "selectFile": "Выбраць файл", + "emailVerificationToggle": "Праверка эл. пошты", + "authenticateGeneric": "Прайдзіце аўтэнтыфікацыю", "ok": "OK", "cancel": "Скасаваць", "yes": "Так", @@ -113,19 +121,29 @@ "enterYourPasswordHint": "Увядзіце ваш пароль", "forgotPassword": "Забылі пароль", "oops": "Вой", + "suggestFeatures": "Прапанаваць функцыю", "faq": "Частыя пытанні", "leaveFamily": "Пакінуць сямейны план", + "inFamilyPlanMessage": "Вы ўдзельнік сямейнага плана!", "scan": "Сканіраваць", "scanACode": "Сканіраваць код", "verify": "Праверыць", "verifyEmail": "Праверыць электронную пошту", "lostDeviceTitle": "Згубілі прыладу?", + "twoFactorAuthTitle": "Двухфактарная аўтэнтыфікацыя", + "passkeyAuthTitle": "Праверка ключа доступу", "verifyPasskey": "Праверыць ключ доступу", "loginWithTOTP": "Увайсці з TOTP", "recoverAccount": "Аднавіць уліковы запіс", + "enterRecoveryKeyHint": "Увядзіце свой ключ аднаўлення", "recover": "Аднавіць", "invalidQRCode": "Памылковы QR-код", + "noRecoveryKeyTitle": "Няма ключа аднаўлення?", + "enterEmailHint": "Увядзіце свой адрас электроннай пошты", + "enterNewEmailHint": "Увядзіце свой новы адрас электроннай пошты", + "invalidEmailTitle": "Памылковы адрас электроннай пошты", "deleteAccount": "Выдаліць уліковы запіс", + "yesSendFeedbackAction": "Так. Адправіць водгук", "noDeleteAccountAction": "Не, выдаліць уліковы запіс", "sendEmail": "Адправіць ліст", "createNewAccount": "Стварыць новы ўліковы запіс", @@ -140,16 +158,21 @@ "social": "Сацыяльныя сеткі", "security": "Бяспека", "lockscreen": "Экран блакіроўкі", + "viewActiveSessions": "Паглядзець актыўныя сеансы", "searchHint": "Пошук...", "search": "Пошук", "noResult": "Няма вынікаў", "addCode": "Дадаць код", "scanAQrCode": "Сканіраваць QR-код", + "enterDetailsManually": "Увесці падрабязнасці ўручную", "edit": "Рэдагаваць", "share": "Абагуліць", "shareCodes": "Абагуліць коды", "restore": "Аднавіць", + "copiedToClipboard": "Скапіявана ў буфер абмену", + "copiedNextToClipboard": "Скапіяваць наступны код у буфер абмену", "error": "Памылка", + "recoveryKeyCopiedToClipboard": "Ключ аднаўлення скапіяваны ў буфер абмену", "doThisLater": "Зрабіць гэта пазней", "saveKey": "Захаваць ключ", "save": "Захаваць", @@ -164,19 +187,27 @@ "changePasswordTitle": "Змяніць пароль", "resetPasswordTitle": "Скінуць пароль", "encryptionKeys": "Ключы шыфравання", + "passwordChangedSuccessfully": "Пароль паспяхова зменены", + "generatingEncryptionKeys": "Генерацыя ключоў шыфравання...", "continueLabel": "Працягнуць", "insecureDevice": "Небяспечная прылада", "howItWorks": "Як гэта працуе", "logInLabel": "Увайсці", "logout": "Выйсці", + "areYouSureYouWantToLogout": "Вы сапраўды хочаце выйсці?", "yesLogout": "Так, выйсці", "exit": "Выхад", "theme": "Тема", "lightTheme": "Светлая", "darkTheme": "Цёмная", "systemTheme": "Сістэманая", + "verifyingRecoveryKey": "Праверка ключа аднаўлення...", + "recoveryKeyVerified": "Ключ аднаўлення правераны", + "recreatePasswordTitle": "Стварыць пароль паўторна", "invalidKey": "Памылковы ключ", "tryAgain": "Паспрабуйце яшчэ раз", + "viewRecoveryKey": "Прагледзець ключ аднаўлення", + "confirmRecoveryKey": "Пацвердзіце ключ аднаўлення", "confirmYourRecoveryKey": "Пацвердзіце свой ключ аднаўлення", "confirm": "Пацвердзіць", "emailYourLogs": "Адправіць журналы", @@ -221,15 +252,22 @@ "pendingSyncs": "Папярэджанне", "pendingSyncsWarningBody": "Некаторыя вашы коды не былі зарэзерваваны.\n\nПераканайцеся, што ў вас ёсць іх рэзервовая копія перад выхадам з сістэмы.", "checkInboxAndSpamFolder": "Праверце свае ўваходныя лісты (і спам) для завяршэння праверкі", + "tapToEnterCode": "Націсніце, каб увесці код", "resendEmail": "Адправіць ліст яшчэ раз", "manualSort": "Карыстальніцкая", "editOrder": "Рэдагаваць заказ", "mostFrequentlyUsed": "Часта выкарыстоўваюцца", "mostRecentlyUsed": "Нядаўна выкарыстаныя", "activeSessions": "Актыўныя сеансы", + "terminateSession": "Перарваць сеанс?", "terminate": "Перарваць", "thisDevice": "Гэта прылада", + "thisEmailIsAlreadyInUse": "Гэта электронная пошта ўжо выкарыстоўваецца", + "yourVerificationCodeHasExpired": "Ваш праверачны код пратэрмінаваны", "incorrectCode": "Няправільны код", + "emailChangedTo": "Электронная пошта зменена на {newEmail}", + "authenticationSuccessful": "Аўтэнтыфікацыя паспяхова пройдзена!", + "incorrectRecoveryKey": "Няправільны ключ аднаўлення", "enterPassword": "Увядзіце пароль", "selectExportFormat": "Выберыце фармат экспартавання", "exportDialogDesc": "Зашыфраванае экспартаванне будзе абаронена паролем, які вы выберыце.", @@ -249,10 +287,18 @@ "focusOnSearchBar": "Сфакусіравацца на пошуку пры запуску праграмы", "confirmUpdatingkey": "Вы сапраўды хочаце абнавіць сакрэтны ключ?", "minimizeAppOnCopy": "Згортваць праграму пры капіяванні", + "editCodeAuthMessage": "Прайдзіце аўтэнтыфікацыю, каб рэдагаваць код", + "deleteCodeAuthMessage": "Прайдзіце аўтэнтыфікацыю, каб выдаліць код", + "showQRAuthMessage": "Прайдзіце аўтэнтыфікацыю, каб паказаць QR-код", + "confirmAccountDeleteTitle": "Пацвердзіце выдаленне ўліковага запісу", "androidBiometricHint": "Праверыць ідэнтыфікацыю", "@androidBiometricHint": { "description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters." }, + "androidBiometricNotRecognized": "Не распазнана. Паспрабуйце яшчэ раз.", + "@androidBiometricNotRecognized": { + "description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters." + }, "androidBiometricSuccess": "Паспяхова", "@androidBiometricSuccess": { "description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters." @@ -261,6 +307,22 @@ "@androidCancelButton": { "description": "Message showed on a button that the user can click to leave the current dialog. It is used on Android side. Maximum 30 characters." }, + "androidSignInTitle": "Патрабуецца аўтэнтыфікацыя", + "@androidSignInTitle": { + "description": "Message showed as a title in a dialog which indicates the user that they need to scan biometric to continue. It is used on Android side. Maximum 60 characters." + }, + "androidBiometricRequiredTitle": "Патрабуецца біяметрыя", + "@androidBiometricRequiredTitle": { + "description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters." + }, + "androidDeviceCredentialsRequiredTitle": "Патрабуюцца ўліковыя даныя прылады", + "@androidDeviceCredentialsRequiredTitle": { + "description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters." + }, + "androidDeviceCredentialsSetupDescription": "Патрабуюцца ўліковыя даныя прылады", + "@androidDeviceCredentialsSetupDescription": { + "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." + }, "goToSettings": "Перайсці ў налады", "@goToSettings": { "description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters." @@ -269,11 +331,24 @@ "@iOSOkButton": { "description": "Message showed on a button that the user can click to leave the current dialog. It is used on iOS side. Maximum 30 characters." }, + "noInternetConnection": "Адсутнічае падключэнне да інтэрнэту", + "signOutFromOtherDevices": "Выйсці з іншых прылад", + "signOutOtherDevices": "Выйсці на іншых прыладах", "doNotSignOut": "Не выходзіць", + "waitingForBrowserRequest": "Чаканне запыту браўзера...", + "waitingForVerification": "Чаканне праверкі...", "passkey": "Ключ доступу", + "passKeyPendingVerification": "Праверка пакуль яшчэ не завершана", "loginSessionExpired": "Сеанс завяршыўся", + "developerSettings": "Налады распрацоўшчыка", + "serverEndpoint": "Канцавы пункт сервера", + "invalidEndpoint": "Памылковы канцавы пункт", + "endpointUpdatedMessage": "Канцавы пункт паспяхова абноўлены", + "customEndpoint": "Падключана да {endpoint}", "pinText": "Замацаваць", "unpinText": "Адмацаваць", + "pinnedCodeMessage": "{code} быў замацаваны", + "unpinnedCodeMessage": "{code} быў адмацаваны", "pinned": "Замацавана", "tags": "Тэгі", "createNewTag": "Стварыць новы тэг", @@ -281,23 +356,38 @@ "create": "Стварыць", "editTag": "Рэдагаванне тэг", "deleteTagTitle": "Выдаліць тэг?", + "updateNotAvailable": "Абнаўленне недаступна", "viewRawCodes": "Паглядзець неапрацаваныя коды", "rawCodes": "Неапрацаваныя коды", "rawCodeData": "Неапрацаваныя даныя кода", "appLock": "Блакіроўка праграмы", + "noSystemLockFound": "Сістэма блакіроўкі не знойдзена", "autoLock": "Аўтаблакіроўка", "immediately": "Адразу", + "reEnterPassword": "Увядзіце пароль паўторна", "reEnterPin": "Увядзіце PIN-код яшчэ раз", "next": "Далей", + "tooManyIncorrectAttempts": "Занадта шмат няўдалых спроб", "tapToUnlock": "Націсніце для разблакіроўкі", + "setNewPassword": "Задаць новы пароль", "deviceLock": "Блакіроўка прылады", "hideContent": "Схаваць змест", "pinLock": "Блакіроўка PIN'ам", "enterPin": "Увядзіце PIN-код", "setNewPin": "Задаць новы PIN", + "appLockNotEnabled": "Блакіроўка праграмы не ўключана", + "duplicateCodes": "Дублікаты кадоў", + "noDuplicates": "✨ Няма дублікатаў", + "deduplicateCodes": "Дубліраваныя кады", "deselectAll": "Зняць выбар з усіх", "selectAll": "Выбраць усе", + "deleteDuplicates": "Выдаліць дублікаты", "plainHTML": "Звычайны HTML", + "tellUsWhatYouThink": "Раскажыце, што вы думаеце", + "dropReviewiOS": "Пакіньце водгук у App Store", + "dropReviewAndroid": "Пакіньце водгук у Play Store", + "giveUsAStarOnGithub": "Адзначце нас зоркай на Github", + "loginWithAuthAccount": "Увайдзіце з дапамогай уліковага запісу Auth", "advanced": "Пашыраныя", "algorithm": "Алгарытм", "type": "Тып", diff --git a/mobile/apps/auth/lib/l10n/arb/app_es.arb b/mobile/apps/auth/lib/l10n/arb/app_es.arb index d313140c40..db50d4f50e 100644 --- a/mobile/apps/auth/lib/l10n/arb/app_es.arb +++ b/mobile/apps/auth/lib/l10n/arb/app_es.arb @@ -173,6 +173,7 @@ "invalidQRCode": "Código QR no válido", "noRecoveryKeyTitle": "¿No tienes la clave de recuperación?", "enterEmailHint": "Introduce tu dirección de correo electrónico", + "enterNewEmailHint": "Introduce tu nueva dirección de correo electrónico", "invalidEmailTitle": "Dirección de correo electrónico no válida", "invalidEmailMessage": "Por favor, introduce una dirección de correo electrónico válida.", "deleteAccount": "Eliminar cuenta", @@ -513,5 +514,10 @@ "free5GB": "5 GB gratis en ente Fotos", "loginWithAuthAccount": "Inicia sesión con tu cuenta de Auth", "freeStorageOffer": "10% de descuento en ente fotos", - "freeStorageOfferDescription": "Usa el cupón \"AUTH\" para obtener un 10% de descuento en el primer año" + "freeStorageOfferDescription": "Usa el cupón \"AUTH\" para obtener un 10% de descuento en el primer año", + "advanced": "Avanzado", + "algorithm": "Algoritmo", + "type": "Tipo", + "period": "Periodo", + "digits": "Dígitos" } \ No newline at end of file diff --git a/mobile/apps/auth/lib/l10n/arb/app_et.arb b/mobile/apps/auth/lib/l10n/arb/app_et.arb index 57294fe402..020bf089c4 100644 --- a/mobile/apps/auth/lib/l10n/arb/app_et.arb +++ b/mobile/apps/auth/lib/l10n/arb/app_et.arb @@ -11,6 +11,7 @@ "setupFirstAccount": "Lisa oma esimene kasutajakonto", "importScanQrCode": "Skanneeri QR-koodi", "qrCode": "QR-kood", + "importEnterSetupKey": "Sisesta seadistusvõti", "importAccountPageTitle": "Sisesta kasutajakonto üksikasjad", "secretCanNotBeEmpty": "Saladus ei tohi jääda tühjaks", "bothIssuerAndAccountCanNotBeEmpty": "Nii kasutajakonto kui väljaandja ei tohi tühjaks jääda", @@ -32,6 +33,7 @@ } } }, + "codeAccountHint": "Kasutajakonto (sina@domeen.com)", "codeTagHint": "Silt", "accountKeyType": "Võtme tüüp", "sessionExpired": "Sessioon on aegunud", @@ -40,7 +42,12 @@ }, "pleaseLoginAgain": "Palun logi uuesti sisse", "loggingOut": "Väljalogimine...", + "timeBasedKeyType": "Ajapõhine (TOTP)", + "counterBasedKeyType": "Loenduripõhine (HOTP)", "saveAction": "Salvesta", + "nextTotpTitle": "järgmine", + "deleteCodeTitle": "Kas kustutame koodi?", + "deleteCodeMessage": "Kas sa oled kindel, et soovid selle koodi kustutada? Seda tegevust ei saa tagasi pöörata.", "trash": "Prügikast", "viewLogsAction": "Vaata logisid", "preparingLogsTitle": "Valmistan logisid ette...", @@ -56,7 +63,18 @@ "copyEmailAction": "Kopeeri e-posti aadress", "exportLogsAction": "Ekspordi logid", "reportABug": "Teata veast", - "contactSupport": "Võtke ühendust klienditoega", + "crashAndErrorReporting": "Teatamine vigadest ja kokkujooksmistest", + "reportBug": "Teata veast", + "emailUsMessage": "Saada meile e-kiri aadressile {email}", + "@emailUsMessage": { + "placeholders": { + "email": { + "type": "String" + } + } + }, + "contactSupport": "Võta ühendust klienditoega", + "rateUsOnStore": "Arvusta meid rakendustepoes: {storeName}", "blog": "Blogi", "verifyPassword": "Korda salasõna", "pleaseWait": "Palun oota...", @@ -70,8 +88,13 @@ "changeEmail": "Muuda e-posti aadressi", "changePassword": "Muuda salasõna", "data": "Andmed", + "importCodes": "Impordi koode", + "importTypePlainText": "Votmindamata tekstina", + "importTypeEnteEncrypted": "Ente krüptitud ekspordina", "passwordForDecryptingExport": "Salasõna eksporditud andmete dekrüptimiseks", "passwordEmptyError": "Salasõna väli ei saa olla tühi", + "importFromApp": "Impordi koodid rakendusest {appName}", + "selectFile": "Vali fail", "ok": "Sobib", "cancel": "Katkesta", "yes": "Jah", diff --git a/mobile/apps/auth/lib/l10n/arb/app_vi.arb b/mobile/apps/auth/lib/l10n/arb/app_vi.arb index 82f8bace1d..361f40f3d4 100644 --- a/mobile/apps/auth/lib/l10n/arb/app_vi.arb +++ b/mobile/apps/auth/lib/l10n/arb/app_vi.arb @@ -506,7 +506,7 @@ "selectAll": "Chọn tất cả", "deleteDuplicates": "Xóa trùng lặp", "plainHTML": "HTML thuần", - "tellUsWhatYouThink": "Hãy cho chúng tôi biết bạn nghĩ gì", + "tellUsWhatYouThink": "Cho biết bạn nghĩ gì", "dropReviewiOS": "Đánh giá ngay trên App Store", "dropReviewAndroid": "Đánh giá ngay trên Play Store", "supportEnte": "Hỗ trợ ente", From 5750d72c5af5a51eb9a92c7b8a35b7537860c645 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:48:10 +0530 Subject: [PATCH 66/81] [auth] Bump version --- mobile/apps/auth/linux/packaging/enteauth.appdata.xml | 1 + mobile/apps/auth/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mobile/apps/auth/linux/packaging/enteauth.appdata.xml b/mobile/apps/auth/linux/packaging/enteauth.appdata.xml index 6785961a91..899e7f8f7e 100644 --- a/mobile/apps/auth/linux/packaging/enteauth.appdata.xml +++ b/mobile/apps/auth/linux/packaging/enteauth.appdata.xml @@ -18,6 +18,7 @@ + diff --git a/mobile/apps/auth/pubspec.yaml b/mobile/apps/auth/pubspec.yaml index 74c48b251a..33ecf465ce 100644 --- a/mobile/apps/auth/pubspec.yaml +++ b/mobile/apps/auth/pubspec.yaml @@ -1,7 +1,7 @@ name: ente_auth description: ente two-factor authenticator -version: 4.4.1+441 +version: 4.4.2+442 publish_to: none environment: From ba56908d2da93b6cf0bb7f850a969c3a3716515c Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Mon, 21 Jul 2025 10:05:11 +0200 Subject: [PATCH 67/81] Fix duplicate people files --- mobile/apps/photos/lib/ui/viewer/people/people_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/apps/photos/lib/ui/viewer/people/people_page.dart b/mobile/apps/photos/lib/ui/viewer/people/people_page.dart index fbb529bd5c..419e95e8e9 100644 --- a/mobile/apps/photos/lib/ui/viewer/people/people_page.dart +++ b/mobile/apps/photos/lib/ui/viewer/people/people_page.dart @@ -108,7 +108,7 @@ class _PeoplePageState extends State { ); return []; } - final List resultFiles = []; + final Set resultFiles = {}; for (final e in result.entries) { resultFiles.addAll(e.value); } From ee0c7472a1299aae7e8ce33035559495aaae2009 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 21 Jul 2025 13:41:24 +0530 Subject: [PATCH 68/81] [auth][build] Fix appimage tool path --- .github/workflows/auth-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auth-release.yml b/.github/workflows/auth-release.yml index d8c9f4e1cc..4f730eb9fb 100644 --- a/.github/workflows/auth-release.yml +++ b/.github/workflows/auth-release.yml @@ -98,7 +98,7 @@ jobs: - name: Install appimagetool run: | - wget -O appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" + wget -O appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" chmod +x appimagetool mv appimagetool /usr/local/bin/ From 73b87950dec26f6416ac2cc938dd7de58be2e2a5 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 21 Jul 2025 13:42:23 +0530 Subject: [PATCH 69/81] Update version --- mobile/apps/auth/ios/Podfile.lock | 56 +++++++++---------- .../auth/linux/packaging/enteauth.appdata.xml | 1 + mobile/apps/auth/pubspec.yaml | 2 +- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/mobile/apps/auth/ios/Podfile.lock b/mobile/apps/auth/ios/Podfile.lock index def487fa15..6a2db70ea9 100644 --- a/mobile/apps/auth/ios/Podfile.lock +++ b/mobile/apps/auth/ios/Podfile.lock @@ -232,44 +232,44 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: - app_links: 3da4c36b46cac3bf24eb897f1a6ce80bda109874 - connectivity_plus: 3f6c9057f4cd64198dc826edfb0542892f825343 - cupertino_http: 94ac07f5ff090b8effa6c5e2c47871d48ab7c86c - device_info_plus: 335f3ce08d2e174b9fdc3db3db0f4e3b1f66bd89 + app_links: e7a6750a915a9e161c58d91bc610e8cd1d4d0ad0 + connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db + cupertino_http: 947a233f40cfea55167a49f2facc18434ea117ba + device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 - file_picker: 9b3292d7c8bc68c8a7bf8eb78f730e49c8efc517 - file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6 - fk_user_agent: 137145b086229251761678fe034da53753f4ce59 + file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655 + file_saver: 503e386464dbe118f630e17b4c2e1190fa0cf808 + fk_user_agent: 1f47ec39291e8372b1d692b50084b0d54103c545 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - flutter_email_sender: 2397f5e84aaacfb61af569637a963e7c687858d8 - flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 - flutter_local_authentication: 989278c681612f1ee0e36019e149137f114b9d7f - flutter_local_notifications: ad39620c743ea4c15127860f4b5641649a988100 - flutter_native_splash: 35ddbc7228eafcb3969dcc5f1fbbe27c1145a4f0 - flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13 - fluttertoast: 76fea30fcf04176325f6864c87306927bd7d2038 - local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391 - move_to_background: 155f7bfbd34d43ad847cb630d2d2d87c17199710 + flutter_email_sender: 10a22605f92809a11ef52b2f412db806c6082d40 + flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4 + flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb + flutter_local_notifications: 4cde75091f6327eb8517fa068a0a5950212d2086 + flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778 + flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 + fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c + local_auth_darwin: 66e40372f1c29f383a314c738c7446e2f7fdadc3 + move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb - objective_c: 89e720c30d716b036faf9c9684022048eee1eee2 + objective_c: 77e887b5ba1827970907e10e832eec1683f3431d OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 - package_info_plus: 580e9a5f1b6ca5594e7c9ed5f92d1dfb2a66b5e1 - path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 - privacy_screen: 3159a541f5d3a31bea916cfd4e58f9dc722b3fd4 - qr_code_scanner: d77f94ecc9abf96d9b9b8fc04ef13f611e5a147a + package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + privacy_screen: 1a131c052ceb3c3659934b003b0d397c2381a24e + qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854 - sentry_flutter: 27892878729f42701297c628eb90e7c6529f3684 - share_plus: 011d6fb4f9d2576b83179a3a5c5e323202cdabcf - shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 - sodium_libs: 6c6d0e83f4ee427c6464caa1f1bdc2abf3ca0b7f - sqflite: c35dad70033b8862124f8337cc994a809fcd9fa3 + sentry_flutter: 2df8b0aab7e4aba81261c230cbea31c82a62dd1b + share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad + shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + sodium_libs: 1faae17af662384acbd13e41867a0008cd2e2318 + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec sqlite3: 0bb0e6389d824e40296f531b858a2a0b71c0d2fb - sqlite3_flutter_libs: 9379996d65aa23dcda7585a5b58766cebe0aa042 + sqlite3_flutter_libs: c00457ebd31e59fa6bb830380ddba24d44fbcd3b SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e - url_launcher_ios: 694010445543906933d732453a59da0a173ae33d + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe PODFILE CHECKSUM: 78f002751f1a8f65042b8da97902ba4124271c5a diff --git a/mobile/apps/auth/linux/packaging/enteauth.appdata.xml b/mobile/apps/auth/linux/packaging/enteauth.appdata.xml index 899e7f8f7e..bdec6377f4 100644 --- a/mobile/apps/auth/linux/packaging/enteauth.appdata.xml +++ b/mobile/apps/auth/linux/packaging/enteauth.appdata.xml @@ -18,6 +18,7 @@ + diff --git a/mobile/apps/auth/pubspec.yaml b/mobile/apps/auth/pubspec.yaml index 33ecf465ce..ea666a5317 100644 --- a/mobile/apps/auth/pubspec.yaml +++ b/mobile/apps/auth/pubspec.yaml @@ -1,7 +1,7 @@ name: ente_auth description: ente two-factor authenticator -version: 4.4.2+442 +version: 4.4.3+443 publish_to: none environment: From 6b5db8d85b365ee5f7203d8ec02da6151dd72eb3 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Mon, 21 Jul 2025 13:53:21 +0530 Subject: [PATCH 70/81] Dedupe gallery on pick person avatar screen --- .../photos/lib/ui/viewer/gallery/hooks/pick_person_avatar.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/apps/photos/lib/ui/viewer/gallery/hooks/pick_person_avatar.dart b/mobile/apps/photos/lib/ui/viewer/gallery/hooks/pick_person_avatar.dart index 1adecdee72..7172825fcc 100644 --- a/mobile/apps/photos/lib/ui/viewer/gallery/hooks/pick_person_avatar.dart +++ b/mobile/apps/photos/lib/ui/viewer/gallery/hooks/pick_person_avatar.dart @@ -54,7 +54,7 @@ class PickPersonCoverPhotoWidget extends StatelessWidget { final result = await SearchService.instance .getClusterFilesForPersonID(personEntity.remoteID); - final List resultFiles = []; + final resultFiles = {}; for (final e in result.entries) { resultFiles.addAll(e.value); } From 868c45baa413613e70366443185cd17e24467c69 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 21 Jul 2025 15:02:27 +0530 Subject: [PATCH 71/81] fileData: Use primary bucket as preferred bucket to read --- server/pkg/controller/filedata/controller.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/server/pkg/controller/filedata/controller.go b/server/pkg/controller/filedata/controller.go index 65cbef0033..9c192d7495 100644 --- a/server/pkg/controller/filedata/controller.go +++ b/server/pkg/controller/filedata/controller.go @@ -22,6 +22,7 @@ import ( "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" "net/http" + "strings" "sync" gTime "time" ) @@ -264,12 +265,12 @@ func (c *Controller) getS3FileMetadataParallel(ctx *gin.Context, dbRows []fileDa func (c *Controller) fetchS3FileMetadata(ctx context.Context, row fileData.Row, ctxLogger *log.Entry) (*fileData.S3FileMetadata, error) { dc := row.LatestBucket - // :todo:neeraj make it configurable to - // specify preferred dc to read from - // and fallback logic to read from different bucket when we fail to read from preferred dc - if dc == "b5" { - if array.StringInList("b6", row.ReplicatedBuckets) { - dc = "b6" + preferredBucket := c.S3Config.GetBucketID(row.Type) + // If the current primary bucket is different from the latest bucket where data was written, + // check and use the preferred bucket if the data is replicated there. + if !strings.EqualFold(preferredBucket, dc) { + if array.StringInList(preferredBucket, row.ReplicatedBuckets) { + dc = preferredBucket } } opt := _defaultFetchConfig From f76fa34e5baa250211e80a3706ac556f8b1a7edd Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 21 Jul 2025 15:07:16 +0530 Subject: [PATCH 72/81] Add SmartAlbum entity type --- server/ente/userentity/entity.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/ente/userentity/entity.go b/server/ente/userentity/entity.go index 09f0ddfd46..ede9b8a0dd 100644 --- a/server/ente/userentity/entity.go +++ b/server/ente/userentity/entity.go @@ -11,14 +11,18 @@ type EntityType string const ( Location EntityType = "location" - Person EntityType = "person" + // Person entity is deprecated and will be removed in the future. + //Deprecated .. + Person EntityType = "person" // CGroup is a new version of Person entity, where the data is gzipped before encryption CGroup EntityType = "cgroup" + // SmartAlbum is a new entity type for storing smart album config data + SmartAlbum EntityType = "smart_album" ) func (et EntityType) IsValid() error { switch et { - case Location, Person, CGroup: + case Location, Person, CGroup, SmartAlbum: return nil } return ente.NewBadRequestWithMessage(fmt.Sprintf("Invalid EntityType: %s", et)) From 32efdf464e24c2c5475690d94317b0f1efe81165 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 21 Jul 2025 15:14:24 +0530 Subject: [PATCH 73/81] Use client provided entity id for smart album config --- server/ente/userentity/entity.go | 20 +++++++++++++++++++ server/pkg/api/userentity.go | 4 ---- .../pkg/controller/userentity/controller.go | 3 +++ server/pkg/repo/userentity/data.go | 15 +++++++++----- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/server/ente/userentity/entity.go b/server/ente/userentity/entity.go index ede9b8a0dd..904b846d1a 100644 --- a/server/ente/userentity/entity.go +++ b/server/ente/userentity/entity.go @@ -69,6 +69,26 @@ type EntityDataRequest struct { Type EntityType `json:"type" binding:"required"` EncryptedData string `json:"encryptedData" binding:"required"` Header string `json:"header" binding:"required"` + ID *string `json:"id"` // Optional ID, if not provided a new ID will be generated +} + +func (edr *EntityDataRequest) IsValid(userID int64) error { + if err := edr.Type.IsValid(); err != nil { + return err + } + switch edr.Type { + case SmartAlbum: + if edr.ID == nil { + return ente.NewBadRequestWithMessage("ID is required for SmartAlbum entity type") + } + // check if ID starts with sa_userid_ or not + if !strings.HasPrefix(*edr.ID, fmt.Sprintf("sa_%d_", userID)) { + return ente.NewBadRequestWithMessage(fmt.Sprintf("ID %s is not valid for SmartAlbum entity type", *edr.ID)) + } + return nil + default: + return nil + } } // UpdateEntityDataRequest updates the current entity diff --git a/server/pkg/api/userentity.go b/server/pkg/api/userentity.go index acda89a09e..e8aa043b5b 100644 --- a/server/pkg/api/userentity.go +++ b/server/pkg/api/userentity.go @@ -61,10 +61,6 @@ func (h *UserEntityHandler) CreateEntity(c *gin.Context) { stacktrace.Propagate(ente.ErrBadRequest, fmt.Sprintf("Request binding failed %s", err))) return } - if err := request.Type.IsValid(); err != nil { - handler.Error(c, stacktrace.Propagate(err, "Invalid EntityType")) - return - } resp, err := h.Controller.CreateEntity(c, request) if err != nil { handler.Error(c, stacktrace.Propagate(err, "Failed to create CreateEntityKey")) diff --git a/server/pkg/controller/userentity/controller.go b/server/pkg/controller/userentity/controller.go index f4fb1c8b9b..38b99fba22 100644 --- a/server/pkg/controller/userentity/controller.go +++ b/server/pkg/controller/userentity/controller.go @@ -32,6 +32,9 @@ func (c *Controller) GetKey(ctx *gin.Context, req model.GetEntityKeyRequest) (*m // CreateEntity stores entity data for the given type func (c *Controller) CreateEntity(ctx *gin.Context, req model.EntityDataRequest) (*model.EntityData, error) { userID := auth.GetUserID(ctx.Request.Header) + if err := req.IsValid(userID); err != nil { + return nil, stacktrace.Propagate(err, "invalid EntityDataRequest") + } id, err := c.Repo.Create(ctx, userID, req) if err != nil { return nil, stacktrace.Propagate(err, "failed to createEntity") diff --git a/server/pkg/repo/userentity/data.go b/server/pkg/repo/userentity/data.go index fa6457ebfa..45f59d3051 100644 --- a/server/pkg/repo/userentity/data.go +++ b/server/pkg/repo/userentity/data.go @@ -14,12 +14,17 @@ import ( // Create inserts a new entry func (r *Repository) Create(ctx context.Context, userID int64, entry model.EntityDataRequest) (string, error) { - idPrt, err := entry.Type.GetNewID() - if err != nil { - return "", stacktrace.Propagate(err, "failed to generate new id") + var id string + if entry.ID != nil { + id = *entry.ID + } else { + idPrt, err := entry.Type.GetNewID() + if err != nil { + return "", stacktrace.Propagate(err, "failed to generate new id") + } + id = *idPrt } - id := *idPrt - err = r.DB.QueryRow(`INSERT into entity_data( + err := r.DB.QueryRow(`INSERT into entity_data( id, user_id, type, From 24a30709cd20ed53276b46e1165718a3f612d441 Mon Sep 17 00:00:00 2001 From: slacker-treat-deferred-unbuckled-jiffy <66910769+slacker-treat-deferred-unbuckled-jiffy@users.noreply.github.com> Date: Mon, 21 Jul 2025 13:55:12 -0600 Subject: [PATCH 74/81] Update custom-icons.json --- .../custom-icons/_data/custom-icons.json | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json index 703bd7419a..7afc5da5a0 100644 --- a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json +++ b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json @@ -71,6 +71,9 @@ ], "hex": "fd4b2d" }, + { + "title": "availity" + }, { "title": "AzurHosts", "slug": "azurhosts", @@ -121,6 +124,13 @@ { "title": "Belo" }, + { + "title": "bestbuy", + "altNames": [ + "Best Buy", + "bestbuy.com" + ] + }, { "title": "Bethesda", "altNames": [ @@ -292,6 +302,23 @@ { "title": "CoinDCX" }, + { + "title": "colorado", + "altNames": [ + "Colorado.gov", + "Colorado Gov", + "Colorado Government", + "Colorado Official State Web Portal", + "Colorado State Web Portal", + "Colorado Web Portal", + "Colorado Portal", + "Colorado State", + "Colorado PEAK", + "myColorado", + "Colorado State Portal", + "Colorado Government Portal" + ] + }, { "title": "ConfigCat" }, @@ -403,6 +430,13 @@ "Murena" ] }, + { + "title": "emeritihealth", + "altNames": [ + "Emeriti Health", + "Emeriti Retirement Health", + ] + }, { "title": "eneba" }, @@ -706,6 +740,14 @@ { "title": "Letterboxd" }, + { + "title": "lincolnfinancial", + "altNames": [ + "Lincoln Financial", + "Lincoln Financial Group", + "LFG" + ] + }, { "title": "LinkedIn", "slug": "linkedin" From cacc7dc85ae0baa0e6780517637ae3dbe10ce512 Mon Sep 17 00:00:00 2001 From: slacker-treat-deferred-unbuckled-jiffy <66910769+slacker-treat-deferred-unbuckled-jiffy@users.noreply.github.com> Date: Mon, 21 Jul 2025 13:55:34 -0600 Subject: [PATCH 75/81] Add files via upload --- .../auth/assets/custom-icons/icons/availity.svg | 10 ++++++++++ .../auth/assets/custom-icons/icons/bestbuy.svg | 1 + .../auth/assets/custom-icons/icons/colorado.svg | 16 ++++++++++++++++ .../assets/custom-icons/icons/emeritihealth.svg | 11 +++++++++++ .../custom-icons/icons/lincolnfinancial.svg | 13 +++++++++++++ 5 files changed, 51 insertions(+) create mode 100644 mobile/apps/auth/assets/custom-icons/icons/availity.svg create mode 100644 mobile/apps/auth/assets/custom-icons/icons/bestbuy.svg create mode 100644 mobile/apps/auth/assets/custom-icons/icons/colorado.svg create mode 100644 mobile/apps/auth/assets/custom-icons/icons/emeritihealth.svg create mode 100644 mobile/apps/auth/assets/custom-icons/icons/lincolnfinancial.svg diff --git a/mobile/apps/auth/assets/custom-icons/icons/availity.svg b/mobile/apps/auth/assets/custom-icons/icons/availity.svg new file mode 100644 index 0000000000..31071124bc --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/availity.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/mobile/apps/auth/assets/custom-icons/icons/bestbuy.svg b/mobile/apps/auth/assets/custom-icons/icons/bestbuy.svg new file mode 100644 index 0000000000..3e582ef525 --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/bestbuy.svg @@ -0,0 +1 @@ +Best Buy Logo Vector \ No newline at end of file diff --git a/mobile/apps/auth/assets/custom-icons/icons/colorado.svg b/mobile/apps/auth/assets/custom-icons/icons/colorado.svg new file mode 100644 index 0000000000..b57991d11d --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/colorado.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/mobile/apps/auth/assets/custom-icons/icons/emeritihealth.svg b/mobile/apps/auth/assets/custom-icons/icons/emeritihealth.svg new file mode 100644 index 0000000000..9d557945ae --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/emeritihealth.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/mobile/apps/auth/assets/custom-icons/icons/lincolnfinancial.svg b/mobile/apps/auth/assets/custom-icons/icons/lincolnfinancial.svg new file mode 100644 index 0000000000..236eace52a --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/lincolnfinancial.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + From 88c9f4943b4a16be29471833f4f78280c9388824 Mon Sep 17 00:00:00 2001 From: Rafael Ieda <60272+iedame@users.noreply.github.com> Date: Mon, 21 Jul 2025 22:50:50 -0300 Subject: [PATCH 76/81] feat(ente-auth): Add custom icon for Pangolin --- .../custom-icons/_data/custom-icons.json | 4 ++++ .../assets/custom-icons/icons/pangolin.svg | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 mobile/apps/auth/assets/custom-icons/icons/pangolin.svg diff --git a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json index 703bd7419a..4a4c329298 100644 --- a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json +++ b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json @@ -956,6 +956,10 @@ "title": "Oracle Cloud", "slug": "oracle_cloud" }, + { + "title": "Pangolin", + "slug": "pangolin" + }, { "title": "Parqet", "slug": "parqet" diff --git a/mobile/apps/auth/assets/custom-icons/icons/pangolin.svg b/mobile/apps/auth/assets/custom-icons/icons/pangolin.svg new file mode 100644 index 0000000000..5e81a57f53 --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/pangolin.svg @@ -0,0 +1,22 @@ + + + + + + + + + From 09d7b82c08570d6bee7e34c019cb6ce21ccf3a46 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 22 Jul 2025 09:42:20 +0530 Subject: [PATCH 77/81] Simplify --- .github/ISSUE_TEMPLATE/bug_report.yml | 27 ++-------- CONTRIBUTING.md | 72 ++++++++------------------- 2 files changed, 27 insertions(+), 72 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e8fc6cbafc..c64165179a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,39 +1,22 @@ name: Report a bug -description: For regressions only (things that were working earlier) +description: Things that were working earlier but don't anymore labels: [] body: - type: markdown attributes: value: | - Before opening a new issue, **please** ensure - 1. You are on the latest version, - 2. You've searched for existing issues, - 3. It was working earlier (otherwise use [this](https://github.com/ente-io/ente/discussions/categories/enhancements)) - 4. It is not about self hosting (otherwise use [this](https://github.com/ente-io/ente/discussions/categories/q-a)) + **Checklist** + 1. You've searched existing [issues](https://github.com/search?q=repo%3Aente-io%2Fente+&type=issues) and [discussions](https://github.com/search?q=repo%3Aente-io%2Fente+&type=discussions) + 2. It was working earlier (otherwise use [enhancements](https://github.com/ente-io/ente/discussions/categories/enhancements)) + 3. It is not about self hosting (for those use [this](https://github.com/ente-io/ente/discussions/categories/q-a)) - type: textarea attributes: label: Description - description: > - Describe the bug and steps to reproduce the behaviour, and how it - differs from the previously working behaviour. - validations: - required: true - type: input attributes: label: Version description: The version can be seen at the bottom of settings. placeholder: e.g. v1.2.3 - - type: input - attributes: - label: Last working version - description: > - The version where things were last known to be working. It is fine - if you don't remember the exact version (mention roughly then), - but **if there just isn't a last working version, then please file - it as an - [enhancement](https://github.com/ente-io/ente/discussions/categories/enhancements))** - (where the community upvotes can be used to help prioritize). - placeholder: e.g. v1.2.3 - type: dropdown attributes: label: What product are you using? diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 242cc2b65c..f4b90454e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,54 +1,42 @@ # Contributing -First and foremost, thank you for your interest in contributing to Ente 🙏 - -There are many ways to contribute, and most of them don't require writing code. - -* [Spread the word](#spread-the-word) -* [Engage with the community](#engage-with-the-community) -* [Translate](#translate) -* [Document](#document) - +- [Spread the word](#spread-the-word) +- [Engage with the community](#engage-with-the-community) +- [Translate](#translate) +- [Document](#document) ## Spread the word -This is perhaps the most impactful contribution you can make. [Spread the -word](https://help.ente.io/photos/features/referral-program/). Online on your -favorite social media channels. Offline to your friends and family who are -looking for a privacy-friendly alternative to big tech. +**This is the most impactful contribution you can make**. + +[Spread the word](https://help.ente.io/photos/features/referral-program/). Online on your favorite social media channels. Offline to your friends and family who are looking for a privacy-friendly alternative to big tech. ## Engage with the community -Just hang around, enjoy the vibe. Answer someone's query on our -[Discord](https://discord.gg/z2YVKkycX3), or pile on in the sporadic #off-topic -rants there. Chuckle (or wince!) at our [Twitter](https://twitter.com/enteio) -memes. Suggest a new feature in our [Github -Discussions](https://github.com/ente-io/ente/discussions/new?category=enhancements), -or upvote the existing ones that you feel we should focus on first. Provide your -opinion on existing threads. +Just hang around, enjoy the vibe. The Ente community — the people who are building Ente, and the people who are using Ente — hang out at various places depending on their proclivity: -These might seem like small things, but it provides us energy. Knowing that -there is a community of people who care for what we are building. +- [Discord](https://discord.ente.io) +- [Mastodon](https://fosstodon.org/@ente) +- [X / Twitter](https://twitter.com/enteio) +- [Github Discussions](https://github.com/ente-io/ente/discussions) + +Just being around might seem a small thing, but it provides us energy. Knowing that there is a community of people who care for what we are building, **who want us to do better**. ## Translate -If you're interested in helping out with translation, please visit our Crowdin -projects to get started: - -| Project | | -| ------------- | ------------- | -| [Auth](https://crowdin.com/project/ente-authenticator-app) | [![Crowdin](https://badges.crowdin.net/ente-authenticator-app/localized.svg)](https://crowdin.com/project/ente-authenticator-app) | -| [Photos](https://crowdin.com/project/ente-photos-app) | [![Crowdin](https://badges.crowdin.net/ente-photos-app/localized.svg)](https://crowdin.com/project/ente-photos-app) | -| [Photos Web / Desktop](https://crowdin.com/project/ente-photos-web) | [![Crowdin](https://badges.crowdin.net/ente-photos-web/localized.svg)](https://crowdin.com/project/ente-photos-web) | +Visit our Crowdin projects to help with translations: +| Project | | +| ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| [Auth](https://crowdin.com/project/ente-authenticator-app) | [![Crowdin](https://badges.crowdin.net/ente-authenticator-app/localized.svg)](https://crowdin.com/project/ente-authenticator-app) | +| [Photos](https://crowdin.com/project/ente-photos-app) | [![Crowdin](https://badges.crowdin.net/ente-photos-app/localized.svg)](https://crowdin.com/project/ente-photos-app) | +| [Photos Web / Desktop](https://crowdin.com/project/ente-photos-web) | [![Crowdin](https://badges.crowdin.net/ente-photos-web/localized.svg)](https://crowdin.com/project/ente-photos-web) | If your language is not listed for translation, please [create a GitHub issue](https://github.com/ente-io/ente/issues/new?title=Request+for+New+Language+Translation&body=Language+name%3A+%0AProject%3A+auth%2Fphotos%2Fboth) to have it added. It is okay to have partial translations. Once ~90% of the strings in a language get translated, we will start surfacing it in the apps. -Thank you for your support. - ## Document The help guides and FAQs for users of Ente products are also open source, and @@ -60,25 +48,9 @@ See [docs/](docs/README.md) for how to edit these documents. ## Code contributions -Code is a small aspect of community, and the ways mentioned above are more -important in helping us. But if you'd _really_ like to contribute code, it is -best to start small. Consider some well-scoped changes, say like adding more -[custom icons to auth](auth/docs/adding-icons.md). +If you'd like to contribute code, it is best to start small. Consider some well-scoped changes, say like adding more [custom icons to auth](auth/docs/adding-icons.md), or fixing a specific bug. -Each of the individual product/platform specific directories in this repository -have instructions on setting up a dev environment. - -For anything beyond trivial bug fixes, please use -[discussions](https://github.com/ente-io/ente/discussions) instead of performing -code changes directly. - -> [!TIP] -> -> Please remember that code is a important, but small, part of the overall big -> picture that makes a product a joy to use. Something that's easy in code is -> not necessarily the right choice for the product as a whole. So we'll repeat - -> there are other ways to contribute than code that we'd request you to -> consider. +Code that changes the behaviour of the product might not get merged, at least not initially. The PR can serve as a discussion bed, but you might find it easier to just start a discussion instead, or post your perspective in the (likely) existing thread about the behaviour change or new feature you wish for. ## Leave a review or star From 304daf0b09dd2df24b49b72c07e8e0c6a31a06df Mon Sep 17 00:00:00 2001 From: Aman Raj Singh Mourya <146618155+AmanRajSinghMourya@users.noreply.github.com> Date: Tue, 22 Jul 2025 13:24:12 +0530 Subject: [PATCH 78/81] Minor Fix --- .../apps/auth/assets/custom-icons/_data/custom-icons.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json index 703bd7419a..06ccdabea9 100644 --- a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json +++ b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json @@ -842,6 +842,9 @@ "title": "Name.com", "slug": "name_com" }, + { + "title": "masdaq" + }, { "title": "Nextcloud", "slug": "nextcloud" @@ -926,6 +929,9 @@ { "title": "NuCommunity" }, + { + "title": "numerai" + }, { "title": "NVIDIA" }, From 55cc92e57d546ee2cb259a736addad591e948bee Mon Sep 17 00:00:00 2001 From: Murad Khalil Date: Tue, 22 Jul 2025 10:06:25 +0200 Subject: [PATCH 79/81] Update custom-icons.json fixed nasdaq entry --- mobile/apps/auth/assets/custom-icons/_data/custom-icons.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json index 545454f459..1f1a25bea1 100644 --- a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json +++ b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json @@ -885,7 +885,7 @@ "slug": "name_com" }, { - "title": "masdaq" + "title": "nasdaq" }, { "title": "Nextcloud", From c583fa474211abc3b3aff98cd36bdd1bce2926c9 Mon Sep 17 00:00:00 2001 From: slacker-treat-deferred-unbuckled-jiffy <66910769+slacker-treat-deferred-unbuckled-jiffy@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:10:35 -0600 Subject: [PATCH 80/81] Add files via upload --- .../auth/assets/custom-icons/icons/unitedhealthgroup.svg | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 mobile/apps/auth/assets/custom-icons/icons/unitedhealthgroup.svg diff --git a/mobile/apps/auth/assets/custom-icons/icons/unitedhealthgroup.svg b/mobile/apps/auth/assets/custom-icons/icons/unitedhealthgroup.svg new file mode 100644 index 0000000000..8dca1d8136 --- /dev/null +++ b/mobile/apps/auth/assets/custom-icons/icons/unitedhealthgroup.svg @@ -0,0 +1,8 @@ + + + + + + + + From 8d71a6bb588816d03fc2cddb39f2124349ab4f37 Mon Sep 17 00:00:00 2001 From: slacker-treat-deferred-unbuckled-jiffy <66910769+slacker-treat-deferred-unbuckled-jiffy@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:12:45 -0600 Subject: [PATCH 81/81] Update custom-icons.json --- .../custom-icons/_data/custom-icons.json | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json index 1f1a25bea1..129e14ca96 100644 --- a/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json +++ b/mobile/apps/auth/assets/custom-icons/_data/custom-icons.json @@ -308,15 +308,17 @@ "Colorado.gov", "Colorado Gov", "Colorado Government", + "Colorado Government Portal", + "Colorado COVES Death Certificates", + "Colorado COVES", "Colorado Official State Web Portal", "Colorado State Web Portal", + "Colorado State Portal", "Colorado Web Portal", "Colorado Portal", "Colorado State", "Colorado PEAK", - "myColorado", - "Colorado State Portal", - "Colorado Government Portal" + "myColorado" ] }, { @@ -1426,6 +1428,16 @@ "title": "Ubuntu One", "slug": "ubuntu_one" }, + { + "title": "unitedhealthgroup", + "altNames": [ + "Unitedhealth Group", + "United Healthgroup", + "UHG", + "uhg.com", + "unitedhealthgroup.com" + ] + }, { "title": "Unity", "hex": "858585"