From 939e76d696b207a45c2eacbb725bd732cdb1e6a6 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Sat, 2 Mar 2024 15:38:03 +0530 Subject: [PATCH 001/391] remove unnecessary mixin --- mobile/lib/ui/viewer/file/zoomable_image.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mobile/lib/ui/viewer/file/zoomable_image.dart b/mobile/lib/ui/viewer/file/zoomable_image.dart index 3329e6955d..05e4400959 100644 --- a/mobile/lib/ui/viewer/file/zoomable_image.dart +++ b/mobile/lib/ui/viewer/file/zoomable_image.dart @@ -41,8 +41,7 @@ class ZoomableImage extends StatefulWidget { State createState() => _ZoomableImageState(); } -class _ZoomableImageState extends State - with SingleTickerProviderStateMixin { +class _ZoomableImageState extends State { late Logger _logger; late EnteFile _photo; ImageProvider? _imageProvider; From b35d942eac9316e113f1182c68a7d6666a6b8794 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Mon, 4 Mar 2024 13:46:05 +0530 Subject: [PATCH 002/391] feat: auth passkeys --- auth/android/app/build.gradle | 10 +- auth/android/app/src/main/AndroidManifest.xml | 7 + auth/ios/Runner/Info.plist | 1 + auth/lib/core/network.dart | 4 +- auth/lib/l10n/arb/app_en.arb | 15 ++- auth/lib/services/passkey_service.dart | 33 +++++ auth/lib/services/user_service.dart | 65 +++++++-- auth/lib/store/offline_authenticator_db.dart | 13 +- auth/lib/ui/passkey_page.dart | 124 ++++++++++++++++++ .../ui/settings/account_section_widget.dart | 41 +++++- .../ui/settings/data/data_section_widget.dart | 1 - .../ui/settings/security_section_widget.dart | 33 +---- auth/pubspec.lock | 82 +++++++----- 13 files changed, 334 insertions(+), 95 deletions(-) create mode 100644 auth/lib/services/passkey_service.dart create mode 100644 auth/lib/ui/passkey_page.dart diff --git a/auth/android/app/build.gradle b/auth/android/app/build.gradle index 7462f4d36f..916e3b3c97 100644 --- a/auth/android/app/build.gradle +++ b/auth/android/app/build.gradle @@ -56,11 +56,11 @@ android { signingConfigs { release { - storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : file(System.getenv("SIGNING_KEY_PATH")) - keyAlias keystoreProperties['keyAlias'] ? keystoreProperties['keyAlias'] : System.getenv("SIGNING_KEY_ALIAS") - keyPassword keystoreProperties['keyPassword'] ? keystoreProperties['keyPassword'] : System.getenv("SIGNING_KEY_PASSWORD") - storePassword keystoreProperties['storePassword'] ? keystoreProperties['storePassword'] : System.getenv("SIGNING_STORE_PASSWORD") - } + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : System.getenv("SIGNING_KEY_PATH") ? file(System.getenv("SIGNING_KEY_PATH")) : null + keyAlias keystoreProperties['keyAlias'] ? keystoreProperties['keyAlias'] : System.getenv("SIGNING_KEY_ALIAS") + keyPassword keystoreProperties['keyPassword'] ? keystoreProperties['keyPassword'] : System.getenv("SIGNING_KEY_PASSWORD") + storePassword keystoreProperties['storePassword'] ? keystoreProperties['storePassword'] : System.getenv("SIGNING_STORE_PASSWORD") + } } flavorDimensions "default" diff --git a/auth/android/app/src/main/AndroidManifest.xml b/auth/android/app/src/main/AndroidManifest.xml index f2f1146ec2..abe72b5650 100644 --- a/auth/android/app/src/main/AndroidManifest.xml +++ b/auth/android/app/src/main/AndroidManifest.xml @@ -35,6 +35,13 @@ + + + + + + + 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 za ?j3-zrR4J7ukEq2S0p^!1%H`^&8(xXn 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 diff --git a/mobile/android/app/src/main/res/drawable-xxxhdpi/ic_home_widget_default.png b/mobile/android/app/src/main/res/drawable-xxxhdpi/ic_home_widget_default.png index 0143b9d38ffc10d607a4b0d1339dc85db01b6a58..ca010e9da5d53915c62419c42e1f0521a71e9c82 100644 GIT binary patch literal 351223 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 x!bm)s~?o|6++0*@B0Y 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 z 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 b%=EBBX;pV-@eeffAj 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 I50@wZ7vo30kN^Mx literal 88213 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%0DHSY|=VMFQzJ4qyeoSIqjjI z#Wd=(P~XMrw=ex$GrLIsn++yF<9xaAblt+E)HR-a9!Z%-V0C2olAGI8$C*zz?2A|o z>46ekFyULRcmETzKkZ~ENd)+&yGz%@y5tlTE^`W@hIA85v$C=-T+&i16TFID6<^Ko zVyJPMPe$pwI`i-wWmsJ*@1tfowH#Cd);}7vK{3FEW`l0!AswUb4={EQq&U?KzL$6sARf}{eG4IVX4oEhRH0tFC> zEx1ahyQbJIK+VzM^UpeObMBqyX26#W50nTu{>Q}dNYZI#{5Mh(YRlEm9;NIRfO60L^4bDcW0VpH`TLT%lG5$&zM}-%Y_lOI0ncutG3KwSdX=abioH zsDN@6I54_*Jv=5*F9LoKVDi${{`e%Ck)FO~ZJ&G6ZMkW?A3*dE`rh2^CH|CdER;zP zelo&UJVU>bb&E@ODYx!1&66vCjf(!{B6d6+P&KO=f@rPERH}>19g=wBh5WLW)6ry< zEI3?s#I}{N;Rcj`Yod7peU+u~dz^{+P2&Pz0D`RD=rwX{cM;VPUfYl`);<5Hm?aO0kGwnX4_Kw`~w4f=ZPz3FEp9s{$^hwJ?fgUu$K7Xa|)zQq?_&n z9CI!A{C)sK9OT0X??L$gE;J!Kq$I(>DGS&GMDF`uHDFx{&ul$~07^nL<{st~e&kzd zFpr~bz0M!vT;8mx`Ps$KzyD7u~(XBrrpKM*IzoUo3Sw4Wum3Ts&%s3as>< z=O9EhBhCfcuYID@`|(zXQpc{%J}5QS!m+wjeD69@;rEWwe)LP!IHC2B>)ZTtkIrU0 z>VBzVx{Ed!xHl&{Fp|E3s^UeE_1u^LJrGKlH4tdn&tJ}6xC21#akG9tt7(kT&Il(P zhqRbYoNm-^jvY9VUq>CN=h$|Fx7M;Qy<;k1AMepl1cL3-&n|g;aClU;k_W8 zwb>&5suz+C-*S8`rnkr~ehA6TRUXzsh`beBHdo+4b&U4Tp;tTnm!k5Wcq7dBNq;j# zFcEm}&7BowB8%9F627ISwcaGIhBEIX(b}`OxDhd#_3nmaoc8Z!dm#!)z2LBLgj*AR z@ygu{E{9yTss Function(String) runBackgroundTask; @@ -55,6 +62,46 @@ class _EnteAppState extends State with WidgetsBindingObserver { WidgetsBinding.instance.addObserver(this); } + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _checkForWidgetLaunch(); + hw.HomeWidget.widgetClicked.listen(_launchedFromWidget); + } + + void _checkForWidgetLaunch() { + hw.HomeWidget.initiallyLaunchedFromHomeWidget().then(_launchedFromWidget); + } + + Future _launchedFromWidget(Uri? uri) async { + if (uri == null) return; + final collectionID = + await FavoritesService.instance.getFavoriteCollectionID(); + if (collectionID == null) { + return; + } + final collection = CollectionsService.instance.getCollectionByID( + collectionID, + ); + if (collection == null) { + return; + } + unawaited(HomeWidgetService.instance.initHomeWidget()); + + final thumbnail = await CollectionsService.instance.getCover(collection); + unawaited( + routeToPage( + context, + CollectionPage( + CollectionWithThumbnail( + collection, + thumbnail, + ), + ), + ), + ); + } + setLocale(Locale newLocale) { setState(() { locale = newLocale; diff --git a/mobile/lib/core/configuration.dart b/mobile/lib/core/configuration.dart index f82486631a..cd6b5156e3 100644 --- a/mobile/lib/core/configuration.dart +++ b/mobile/lib/core/configuration.dart @@ -24,6 +24,7 @@ import 'package:photos/models/private_key_attributes.dart'; import 'package:photos/services/billing_service.dart'; import 'package:photos/services/collections_service.dart'; import 'package:photos/services/favorites_service.dart'; +import "package:photos/services/home_widget_service.dart"; import 'package:photos/services/ignored_files_service.dart'; import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart'; import 'package:photos/services/memories_service.dart'; @@ -31,7 +32,6 @@ import 'package:photos/services/search_service.dart'; import 'package:photos/services/sync_service.dart'; import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/file_uploader.dart'; -import "package:photos/utils/home_widget_util.dart"; import 'package:photos/utils/validator_util.dart'; import 'package:shared_preferences/shared_preferences.dart'; import "package:tuple/tuple.dart"; @@ -175,7 +175,7 @@ class Configuration { MemoriesService.instance.clearCache(); BillingService.instance.clearCache(); SearchService.instance.clearCache(); - unawaited(clearHomeWidget()); + unawaited(HomeWidgetService.instance.clearHomeWidget()); Bus.instance.fire(UserLoggedOutEvent()); } else { await _preferences.setBool("auto_logout", true); diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index e634ed12ff..49dbc01b11 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -27,6 +27,7 @@ import 'package:photos/services/collections_service.dart'; import "package:photos/services/entity_service.dart"; import 'package:photos/services/favorites_service.dart'; import 'package:photos/services/feature_flag_service.dart'; +import 'package:photos/services/home_widget_service.dart'; import 'package:photos/services/local_file_update_service.dart'; import 'package:photos/services/local_sync_service.dart'; import "package:photos/services/location_service.dart"; @@ -46,7 +47,6 @@ import 'package:photos/ui/tools/app_lock.dart'; import 'package:photos/ui/tools/lock_screen.dart'; import 'package:photos/utils/crypto_util.dart'; import 'package:photos/utils/file_uploader.dart'; -import "package:photos/utils/home_widget_util.dart"; import 'package:photos/utils/local_settings.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -110,8 +110,8 @@ ThemeMode _themeMode(AdaptiveThemeMode? savedThemeMode) { Future _homeWidgetSync() async { if (!Platform.isAndroid) return; try { - if (await countHomeWidgets() != 0) { - await initHomeWidget(); + if (await HomeWidgetService.instance.countHomeWidgets() != 0) { + await HomeWidgetService.instance.initHomeWidget(); } } catch (e, s) { _logger.severe("Error in initSlideshowWidget", e, s); @@ -210,6 +210,12 @@ Future _init(bool isBackground, {String via = ''}) async { LocalFileUpdateService.instance.init(preferences); SearchService.instance.init(); StorageBonusService.instance.init(preferences); + if (!isBackground && + Platform.isAndroid && + await HomeWidgetService.instance.countHomeWidgets() == 0) { + unawaited(HomeWidgetService.instance.initHomeWidget()); + } + if (Platform.isIOS) { // ignore: unawaited_futures PushService.instance.init().then((_) { @@ -275,9 +281,15 @@ Future _scheduleHeartBeat( } Future _scheduleFGHomeWidgetSync() async { + Future.delayed(kFGHomeWidgetSyncFrequency, () async { + unawaited(_homeWidgetSyncPeriodic()); + }); +} + +Future _homeWidgetSyncPeriodic() async { await _homeWidgetSync(); Future.delayed(kFGHomeWidgetSyncFrequency, () async { - unawaited(_scheduleFGHomeWidgetSync()); + unawaited(_homeWidgetSyncPeriodic()); }); } diff --git a/mobile/lib/services/home_widget_service.dart b/mobile/lib/services/home_widget_service.dart new file mode 100644 index 0000000000..1d6892bb81 --- /dev/null +++ b/mobile/lib/services/home_widget_service.dart @@ -0,0 +1,173 @@ +import "dart:math"; + +import "package:flutter/material.dart"; +import 'package:home_widget/home_widget.dart' as hw; +import "package:logging/logging.dart"; +import "package:photos/core/configuration.dart"; +import "package:photos/core/constants.dart"; +import "package:photos/db/files_db.dart"; +import "package:photos/models/file/file_type.dart"; +import "package:photos/services/favorites_service.dart"; +import "package:photos/utils/file_util.dart"; +import "package:photos/utils/preload_util.dart"; + +class HomeWidgetService { + final Logger _logger = Logger((HomeWidgetService).toString()); + + HomeWidgetService._privateConstructor(); + + static final HomeWidgetService instance = + HomeWidgetService._privateConstructor(); + + Future initHomeWidget() async { + final isLoggedIn = Configuration.instance.isLoggedIn(); + + if (!isLoggedIn) { + await clearHomeWidget(); + _logger.info("user not logged in"); + return; + } + + final collectionID = + await FavoritesService.instance.getFavoriteCollectionID(); + if (collectionID == null) { + await clearHomeWidget(); + _logger.info("Favorite collection not found"); + return; + } + + try { + await hw.HomeWidget.setAppGroupId(iOSGroupID); + final res = await FilesDB.instance.getFilesInCollection( + collectionID, + galleryLoadStartTime, + galleryLoadEndTime, + ); + + final previousGeneratedId = + await hw.HomeWidget.getWidgetData("home_widget_last_img"); + + if (res.files.length == 1 && + res.files[0].generatedID == previousGeneratedId) { + _logger + .info("Only one image found and it's the same as the previous one"); + return; + } + if (res.files.isEmpty) { + await clearHomeWidget(); + _logger.info("No images found"); + return; + } + final files = res.files.where( + (element) => + element.generatedID != previousGeneratedId && + element.fileType == FileType.image, + ); + + final randomNumber = Random().nextInt(files.length); + final randomFile = files.elementAt(randomNumber); + final fullImage = await getFileFromServer(randomFile); + if (fullImage == null) throw Exception("File not found"); + + final image = await decodeImageFromList(await fullImage.readAsBytes()); + final width = image.width.toDouble(); + final height = image.height.toDouble(); + final size = min(min(width, height), 1024.0); + final aspectRatio = width / height; + late final int cacheWidth; + late final int cacheHeight; + if (aspectRatio > 1) { + cacheWidth = 1024; + cacheHeight = (1024 / aspectRatio).round(); + } else if (aspectRatio < 1) { + cacheHeight = 1024; + cacheWidth = (1024 * aspectRatio).round(); + } else { + cacheWidth = 1024; + cacheHeight = 1024; + } + final Image img = Image.file( + fullImage, + fit: BoxFit.cover, + cacheWidth: cacheWidth, + cacheHeight: cacheHeight, + ); + + await PreloadImage.loadImage(img.image); + + final widget = ClipRRect( + borderRadius: BorderRadius.circular(32), + child: Container( + width: size, + height: size, + decoration: BoxDecoration( + color: Colors.black, + image: DecorationImage(image: img.image, fit: BoxFit.cover), + ), + ), + ); + + await hw.HomeWidget.renderFlutterWidget( + widget, + logicalSize: Size(size, size), + key: "slideshow", + ); + + if (randomFile.generatedID != null) { + await hw.HomeWidget.saveWidgetData( + "home_widget_last_img", + randomFile.generatedID!, + ); + } + + await hw.HomeWidget.updateWidget( + name: 'SlideshowWidgetProvider', + androidName: 'SlideshowWidgetProvider', + qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', + iOSName: 'SlideshowWidget', + ); + _logger.info( + ">>> OG size of SlideshowWidget image: ${width} x $height", + ); + _logger.info( + ">>> SlideshowWidget image rendered with size ${cacheWidth} x $cacheHeight", + ); + } catch (e) { + _logger.severe("Error rendering widget", e); + } + } + + Future countHomeWidgets() async { + return await hw.HomeWidget.getWidgetCount( + name: 'SlideshowWidgetProvider', + androidName: 'SlideshowWidgetProvider', + qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', + iOSName: 'SlideshowWidget', + ) ?? + 0; + } + + Future clearHomeWidget() async { + final previousGeneratedId = + await hw.HomeWidget.getWidgetData("home_widget_last_img"); + if (previousGeneratedId == null) return; + + _logger.info("Clearing SlideshowWidget"); + await hw.HomeWidget.saveWidgetData( + "slideshow", + null, + ); + + await hw.HomeWidget.updateWidget( + name: 'SlideshowWidgetProvider', + androidName: 'SlideshowWidgetProvider', + qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', + iOSName: 'SlideshowWidget', + ); + await hw.HomeWidget.saveWidgetData( + "home_widget_last_img", + null, + ); + _logger.info(">>> SlideshowWidget cleared"); + } +} diff --git a/mobile/lib/utils/home_widget_util.dart b/mobile/lib/utils/home_widget_util.dart deleted file mode 100644 index 7f1ff91e10..0000000000 --- a/mobile/lib/utils/home_widget_util.dart +++ /dev/null @@ -1,147 +0,0 @@ -import "dart:math"; - -import "package:flutter/material.dart"; -import 'package:home_widget/home_widget.dart' as hw; -import "package:logging/logging.dart"; -import "package:photos/core/configuration.dart"; -import "package:photos/core/constants.dart"; -import "package:photos/db/files_db.dart"; -import "package:photos/models/file/file_type.dart"; -import "package:photos/services/favorites_service.dart"; -import "package:photos/utils/file_util.dart"; -import "package:photos/utils/preload_util.dart"; - -Future countHomeWidgets() async { - return await hw.HomeWidget.getWidgetCount( - name: 'SlideshowWidgetProvider', - androidName: 'SlideshowWidgetProvider', - qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', - iOSName: 'SlideshowWidget', - ) ?? - 0; -} - -Future initHomeWidget() async { - final Logger logger = Logger("initHomeWidget"); - final user = Configuration.instance.getUserID(); - - if (user == null) { - await clearHomeWidget(); - throw Exception("User not found"); - } - - final collectionID = - await FavoritesService.instance.getFavoriteCollectionID(); - if (collectionID == null) { - await clearHomeWidget(); - throw Exception("Collection not found"); - } - - try { - await hw.HomeWidget.setAppGroupId(iOSGroupID); - final res = await FilesDB.instance.getFilesInCollection( - collectionID, - galleryLoadStartTime, - galleryLoadEndTime, - ); - - final previousGeneratedId = - await hw.HomeWidget.getWidgetData("home_widget_last_img"); - - if (res.files.length == 1 && - res.files[0].generatedID == previousGeneratedId) { - logger.info("Only one image found and it's the same as the previous one"); - return; - } - if (res.files.isEmpty) { - await clearHomeWidget(); - return; - } - final files = res.files.where( - (element) => - element.generatedID != previousGeneratedId && - element.fileType == FileType.image, - ); - - final randomNumber = Random().nextInt(files.length); - final randomFile = files.elementAt(randomNumber); - final fullImage = await getFileFromServer(randomFile); - if (fullImage == null) throw Exception("File not found"); - - Image img = Image.file(fullImage); - var imgProvider = img.image; - await PreloadImage.loadImage(imgProvider); - - img = Image.file(fullImage); - imgProvider = img.image; - - final image = await decodeImageFromList(await fullImage.readAsBytes()); - final width = image.width.toDouble(); - final height = image.height.toDouble(); - final size = min(min(width, height), 1024.0); - - final widget = ClipRRect( - borderRadius: BorderRadius.circular(32), - child: Container( - width: size, - height: size, - decoration: BoxDecoration( - color: Colors.black, - image: DecorationImage(image: imgProvider, fit: BoxFit.cover), - ), - ), - ); - - await hw.HomeWidget.renderFlutterWidget( - widget, - logicalSize: Size(size, size), - key: "slideshow", - ); - - await hw.HomeWidget.updateWidget( - name: 'SlideshowWidgetProvider', - androidName: 'SlideshowWidgetProvider', - qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', - iOSName: 'SlideshowWidget', - ); - - if (randomFile.generatedID != null) { - await hw.HomeWidget.saveWidgetData( - "home_widget_last_img", - randomFile.generatedID!, - ); - } - - logger.info( - ">>> SlideshowWidget rendered with size ${width}x$height", - ); - } catch (_) { - throw Exception("Error rendering widget"); - } -} - -Future clearHomeWidget() async { - final previousGeneratedId = - await hw.HomeWidget.getWidgetData("home_widget_last_img"); - if (previousGeneratedId == null) return; - - final Logger logger = Logger("clearHomeWidget"); - - logger.info("Clearing SlideshowWidget"); - await hw.HomeWidget.saveWidgetData( - "slideshow", - null, - ); - - await hw.HomeWidget.updateWidget( - name: 'SlideshowWidgetProvider', - androidName: 'SlideshowWidgetProvider', - qualifiedAndroidName: 'io.ente.photos.SlideshowWidgetProvider', - iOSName: 'SlideshowWidget', - ); - await hw.HomeWidget.saveWidgetData( - "home_widget_last_img", - null, - ); - logger.info(">>> SlideshowWidget cleared"); -} From cfa4077b5cbfa5ae1c9552d65ba1b8d914ed281c Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 12 Mar 2024 01:36:05 +0000 Subject: [PATCH 198/391] New Crowdin translations by GitHub Action --- .../public/locales/de-DE/translation.json | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/web/apps/photos/public/locales/de-DE/translation.json b/web/apps/photos/public/locales/de-DE/translation.json index 3fcd4c542d..b90548d6fc 100644 --- a/web/apps/photos/public/locales/de-DE/translation.json +++ b/web/apps/photos/public/locales/de-DE/translation.json @@ -176,7 +176,7 @@ "SUBSCRIPTION_CANCEL_FAILED": "Abonnement konnte nicht storniert werden", "SUBSCRIPTION_CANCEL_SUCCESS": "Abonnement erfolgreich beendet", "REACTIVATE_SUBSCRIPTION": "Abonnement reaktivieren", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Nach der Reaktivierung wird am {{date, dateTime}} abgerechnet", "SUBSCRIPTION_ACTIVATE_SUCCESS": "Abonnement erfolgreich aktiviert ", "SUBSCRIPTION_ACTIVATE_FAILED": "Reaktivierung der Abonnementverlängerung fehlgeschlagen", "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Vielen Dank", @@ -258,25 +258,25 @@ "SCAN_QR_CODE": "QR‐Code stattdessen scannen", "ENABLE_TWO_FACTOR": "Zwei-Faktor-Authentifizierung aktivieren", "ENABLE": "Aktivieren", - "LOST_DEVICE": "", + "LOST_DEVICE": "Zwei-Faktor-Gerät verloren", "INCORRECT_CODE": "Falscher Code", "TWO_FACTOR_INFO": "", "DISABLE_TWO_FACTOR_LABEL": "Deaktiviere die Zwei-Faktor-Authentifizierung", - "UPDATE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "Authentifizierungsgerät aktualisieren", "DISABLE": "Deaktivieren", "RECONFIGURE": "Neu einrichten", - "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR": "Zweiten Faktor aktualisieren", "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "UPDATE": "Aktualisierung", + "DISABLE_TWO_FACTOR": "Zweiten Faktor deaktivieren", + "DISABLE_TWO_FACTOR_MESSAGE": "Bist du sicher, dass du die Zwei-Faktor-Authentifizierung deaktivieren willst", + "TWO_FACTOR_DISABLE_FAILED": "Fehler beim Deaktivieren des zweiten Faktors, bitte versuchen Sie es erneut", "EXPORT_DATA": "Daten exportieren", "SELECT_FOLDER": "Ordner auswählen", "DESTINATION": "Zielort", "START": "Start", - "LAST_EXPORT_TIME": "", - "EXPORT_AGAIN": "", + "LAST_EXPORT_TIME": "Letztes Exportdatum", + "EXPORT_AGAIN": "Neusynchronisation", "LOCAL_STORAGE_NOT_ACCESSIBLE": "", "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", "SEND_OTT": "OTP senden", @@ -302,17 +302,17 @@ "TOO_LARGE_INFO": "Diese Dateien wurden nicht hochgeladen, da sie unsere maximale Dateigröße überschreiten", "THUMBNAIL_GENERATION_FAILED_INFO": "Diese Dateien wurden hochgeladen, aber leider konnten wir nicht die Thumbnails für sie generieren.", "UPLOAD_TO_COLLECTION": "In Album hochladen", - "UNCATEGORIZED": "", + "UNCATEGORIZED": "Unkategorisiert", "ARCHIVE": "Archiv", "FAVORITES": "Favoriten", "ARCHIVE_COLLECTION": "Album archivieren", "ARCHIVE_SECTION_NAME": "Archiv", "ALL_SECTION_NAME": "Alle", "MOVE_TO_COLLECTION": "Zum Album verschieben", - "UNARCHIVE": "", - "UNARCHIVE_COLLECTION": "", - "HIDE_COLLECTION": "", - "UNHIDE_COLLECTION": "", + "UNARCHIVE": "Dearchivieren", + "UNARCHIVE_COLLECTION": "Album dearchivieren", + "HIDE_COLLECTION": "Album ausblenden", + "UNHIDE_COLLECTION": "Album wieder einblenden", "MOVE": "Verschieben", "ADD": "Hinzufügen", "REMOVE": "Entfernen", @@ -334,14 +334,14 @@ "LEAVE_SHARED_ALBUM_MESSAGE": "", "NOT_FILE_OWNER": "Dateien in einem freigegebenen Album können nicht gelöscht werden", "CONFIRM_SELF_REMOVE_MESSAGE": "", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Einige der Elemente, die du entfernst, wurden von anderen Nutzern hinzugefügt und du wirst den Zugriff auf sie verlieren.", "SORT_BY_CREATION_TIME_ASCENDING": "Ältestem", "SORT_BY_UPDATION_TIME_DESCENDING": "Zuletzt aktualisiert", "SORT_BY_NAME": "Name", "COMPRESS_THUMBNAILS": "", "THUMBNAIL_REPLACED": "", "FIX_THUMBNAIL": "Komprimiere", - "FIX_THUMBNAIL_LATER": "", + "FIX_THUMBNAIL_LATER": "Später komprimieren", "REPLACE_THUMBNAIL_NOT_STARTED": "", "REPLACE_THUMBNAIL_COMPLETED": "", "REPLACE_THUMBNAIL_NOOP": "", @@ -380,25 +380,25 @@ "REMOVE_PARTICIPANT": "Entfernen?", "CONFIRM_REMOVE": "Ja, entfernen", "MANAGE": "Verwalten", - "ADDED_AS": "", - "COLLABORATOR_RIGHTS": "", + "ADDED_AS": "Hinzugefügt als", + "COLLABORATOR_RIGHTS": "Bearbeiter können Fotos & Videos zu dem geteilten Album hinzufügen", "REMOVE_PARTICIPANT_HEAD": "Teilnehmer entfernen", "OWNER": "Besitzer", "COLLABORATORS": "", - "ADD_MORE": "", + "ADD_MORE": "Mehr hinzufügen", "VIEWERS": "", - "OR_ADD_EXISTING": "", + "OR_ADD_EXISTING": "Oder eine Vorherige auswählen", "REMOVE_PARTICIPANT_MESSAGE": "", "NOT_FOUND": "404 - Nicht gefunden", "LINK_EXPIRED": "Link ist abgelaufen", "LINK_EXPIRED_MESSAGE": "Dieser Link ist abgelaufen oder wurde deaktiviert!", - "MANAGE_LINK": "", + "MANAGE_LINK": "Link verwalten", "LINK_TOO_MANY_REQUESTS": "Sorry, dieses Album wurde auf zu vielen Geräten angezeigt!", "FILE_DOWNLOAD": "Downloads erlauben", "LINK_PASSWORD_LOCK": "Passwort Sperre", - "PUBLIC_COLLECT": "", + "PUBLIC_COLLECT": "Hinzufügen von Fotos erlauben", "LINK_DEVICE_LIMIT": "Geräte Limit", - "NO_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "Keins", "LINK_EXPIRY": "Ablaufdatum des Links", "NEVER": "Niemals", "DISABLE_FILE_DOWNLOAD": "", @@ -412,7 +412,7 @@ "DISABLE_PASSWORD": "", "DISABLE_PASSWORD_MESSAGE": "", "PASSWORD_LOCK": "Passwort Sperre", - "LOCK": "", + "LOCK": "Sperren", "DOWNLOAD_UPLOAD_LOGS": "", "UPLOAD_FILES": "Datei", "UPLOAD_DIRS": "Ordner", From ddedaf2d0eb161eb67ffad3b80cad8126b2647c9 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Tue, 12 Mar 2024 01:46:37 +0530 Subject: [PATCH 199/391] bump up version to v0.8.67 --- mobile/CHANGELOG.md | 2 +- mobile/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/CHANGELOG.md b/mobile/CHANGELOG.md index 627fea5ad8..445bb9147f 100644 --- a/mobile/CHANGELOG.md +++ b/mobile/CHANGELOG.md @@ -1,7 +1,7 @@ # CHANGELOG -## v0.8.66 +## v0.8.67 ### Added * #### Home Widget ✨ diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index b457f0bc71..2ea9bb3cef 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.8.66+586 +version: 0.8.67+587 publish_to: none environment: From cb8738287a0a56f7db676c04ab4490f3ae76d0b8 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 09:10:13 +0530 Subject: [PATCH 200/391] [photosw] Enable passkey for internal users --- web/apps/photos/src/components/Sidebar/UtilitySection.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx index 3acd0326a6..bc0d0f5dd6 100644 --- a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx +++ b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx @@ -134,11 +134,13 @@ export default function UtilitySection({ closeSidebar }) { label={t("TWO_FACTOR")} /> + {isInternalUser() && ( + )} Date: Tue, 12 Mar 2024 09:11:31 +0530 Subject: [PATCH 201/391] [mob] gitignore android/.settings --- mobile/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/mobile/.gitignore b/mobile/.gitignore index 40821c9c1a..47e6ea41bf 100644 --- a/mobile/.gitignore +++ b/mobile/.gitignore @@ -34,6 +34,7 @@ lib/generated_plugin_registrant.dart android/key.properties android/app/.settings/* +android/.settings/ .env From 638de0a7693fb13ff0f5e75a6c36cb55223b4eef Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 09:21:14 +0530 Subject: [PATCH 202/391] [authw] Handle passkey finish redirect --- web/apps/auth/src/pages/passkeys/finish/index.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 web/apps/auth/src/pages/passkeys/finish/index.tsx diff --git a/web/apps/auth/src/pages/passkeys/finish/index.tsx b/web/apps/auth/src/pages/passkeys/finish/index.tsx new file mode 100644 index 0000000000..289f351de9 --- /dev/null +++ b/web/apps/auth/src/pages/passkeys/finish/index.tsx @@ -0,0 +1,11 @@ +import PasskeysFinishPage from "@ente/accounts/pages/passkeys/finish"; + +const PasskeysFinish = () => { + return ( + <> + + + ); +}; + +export default PasskeysFinish; From dbc50760af8912382bb3ef0564a3994d3961f46a Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 09:24:57 +0530 Subject: [PATCH 203/391] [web][passkey] Whitelist *.ente.sh redirect urls --- web/apps/accounts/src/pages/passkeys/flow/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/web/apps/accounts/src/pages/passkeys/flow/index.tsx b/web/apps/accounts/src/pages/passkeys/flow/index.tsx index 61c56a97cf..517777b9c5 100644 --- a/web/apps/accounts/src/pages/passkeys/flow/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/flow/index.tsx @@ -40,6 +40,7 @@ const PasskeysFlow = () => { redirect !== "" && !( redirectURL.host.endsWith(".ente.io") || + redirectURL.host.endsWith(".ente.sh") || redirectURL.host.endsWith("bada-frame.pages.dev") ) && redirectURL.protocol !== "ente:" && From 51f19cf2fd7a8668b1b058669cb70904bbd091f7 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 09:31:21 +0530 Subject: [PATCH 204/391] [web] Fix lint error --- .../photos/src/components/Sidebar/UtilitySection.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx index bc0d0f5dd6..bf9782e3bc 100644 --- a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx +++ b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx @@ -135,11 +135,11 @@ export default function UtilitySection({ closeSidebar }) { /> {isInternalUser() && ( - + )} Date: Tue, 12 Mar 2024 09:52:34 +0530 Subject: [PATCH 205/391] [web] Support preview deployments --- .github/workflows/web-preview.yml | 52 +++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/web-preview.yml diff --git a/.github/workflows/web-preview.yml b/.github/workflows/web-preview.yml new file mode 100644 index 0000000000..4727576730 --- /dev/null +++ b/.github/workflows/web-preview.yml @@ -0,0 +1,52 @@ +name: "Preview (web)" + +on: + workflow_dispatch: + inputs: + app: + description: "App to build and deploy" + type: choice + required: true + default: "photos" + options: + - "accounts" + - "auth" + - "cast" + - "photos" + +jobs: + deploy: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: web + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup node and enable yarn caching + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "yarn" + cache-dependency-path: "docs/yarn.lock" + + - name: Install dependencies + run: yarn install + + - name: Build accounts + run: yarn build:${{ inputs.app }} + + - name: Publish accounts + uses: cloudflare/pages-action@1 + with: + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + projectName: ente + branch: preview + directory: web/apps/${{ inputs.app }}/out + wranglerVersion: "3" From 6efe2cd5fd4659917d4ee82934a64f9be3e14cf5 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 09:53:49 +0530 Subject: [PATCH 206/391] Add a push trigger to register the workflow See https://stackoverflow.com/questions/63362126/github-actions-how-to-run-a-workflow-created-on-a-non-master-branch-from-the-wo --- .github/workflows/web-preview.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/web-preview.yml b/.github/workflows/web-preview.yml index 4727576730..1ecc2e052b 100644 --- a/.github/workflows/web-preview.yml +++ b/.github/workflows/web-preview.yml @@ -1,6 +1,7 @@ name: "Preview (web)" on: + push: # <- temporarily added so that we can register the action workflow_dispatch: inputs: app: From 8c23090abda1ace2a1b3eb6c8444d2f9936f5b38 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 09:56:07 +0530 Subject: [PATCH 207/391] Remove placeholders --- .github/workflows/web-preview.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/web-preview.yml b/.github/workflows/web-preview.yml index 1ecc2e052b..4e86d9a816 100644 --- a/.github/workflows/web-preview.yml +++ b/.github/workflows/web-preview.yml @@ -1,7 +1,6 @@ name: "Preview (web)" on: - push: # <- temporarily added so that we can register the action workflow_dispatch: inputs: app: @@ -39,10 +38,10 @@ jobs: - name: Install dependencies run: yarn install - - name: Build accounts + - name: Build ${{ inputs.app }} run: yarn build:${{ inputs.app }} - - name: Publish accounts + - name: Publish ${{ inputs.app }} to preview uses: cloudflare/pages-action@1 with: accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} From a9557df240d8b9102897ac9cbf58f6301a87b30b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 10:08:27 +0530 Subject: [PATCH 208/391] Add preview deployment docs --- web/docs/deploy.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/web/docs/deploy.md b/web/docs/deploy.md index 8e479db97f..c17de8ffa3 100644 --- a/web/docs/deploy.md +++ b/web/docs/deploy.md @@ -9,7 +9,11 @@ Cloudflare Pages. anything inside `docs/` gets merged to `main`. * Every night, all the web apps get automatically deployed to a nightly preview - URLs using the current code in main. + URLs (`*.ente.sh`) using the current code in main. + +* A preview deployment can be made by triggering the "Preview (web)" workflow. + This allows us to deploy a build of any of the apps from an arbitrary branch + to [preview.ente.sh](https://preview.ente.sh). Use the various `yarn deploy:*` commands to help with production deployments. For example, `yarn deploy:photos` will open a PR to merge the current `main` @@ -21,6 +25,7 @@ and publish to [web.ente.io](https://web.ente.io). > the merge commit. ## Deployments + Here is a list of all the deployments, whether or not they are production deployments, and the action that triggers them: @@ -36,6 +41,7 @@ deployments, and the action that triggers them: | [auth.ente.sh](https://auth.ente.sh) | Preview | Nightly deploy of `main` | | [cast.ente.sh](https://cast.ente.sh) | Preview | Nightly deploy of `main` | | [photos.ente.sh](https://photos.ente.sh) | Preview | Nightly deploy of `main` | +| [preview.ente.sh](https://preview.ente.sh) | Preview | Manually triggered | ### Other subdomains @@ -49,6 +55,19 @@ Apart from this, there are also some other deployments: - `payments.ente.io` and `family.ente.io` are currently in a separate repositories (Enhancement: bring them in here). +### Preview deployments + +To trigger a preview deployment, manually trigger the "Preview (web)" workflow +from the Actions tab on GitHub. You'll need to select the app to build, and the +branch to use. This'll then build the specified app (e.g. "photos") from that +branch, and deploy it to [preview.ente.sh](https://preview.ente.sh). + +The workflow can also be triggered using GitHub's CLI, gh. e.g. + +```sh +gh workflow run web-preview -F app=cast --ref my-branch +``` + --- ## Details From 2fc1a96c8bbdcee7206c48613234d8cd67e35360 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 11:51:09 +0530 Subject: [PATCH 209/391] [server] Fix uploads on self-hosted Docker when running on Windows On our Discord @Degos ran into an issue where their uploads to the self hosted docker compose cluster were failing. On debugging, it was found that the line-endings in `server/scripts/compose/minio-provision.sh` were set to CRLF, causing the script to fail when run inside Docker. The minIO buckets never got provisioned, and so the uploads would fail with NoSuchBucket The specified bucket does not exist To fix this, we add a new .gitattributes that enforces the LF for the scripts that run inside Docker. To (perhaps too preemptively) guard against similar issues in other scenarios, turn this on for all shell scripts. Refs: - https://stackoverflow.com/questions/29603737/bash-seamlessly-run-scripts-with-crlf-line-endings - https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings --- .gitattributes | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..57680f9dc4 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Set line endings of shell scripts to LF, even on Windows, otherwise execution +# within Docker fails. +*.sh text eol=lf From c0a2347b80ac38246437cc0340048c514eb52a88 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:58:20 +0530 Subject: [PATCH 210/391] [server] Refactor /user/plans --- server/ente/billing.go | 5 ----- server/pkg/controller/billing.go | 38 ++++++++------------------------ 2 files changed, 9 insertions(+), 34 deletions(-) diff --git a/server/ente/billing.go b/server/ente/billing.go index 4d8d3401d0..5a0ff08a86 100644 --- a/server/ente/billing.go +++ b/server/ente/billing.go @@ -176,11 +176,6 @@ type SubscriptionUpdateResponse struct { ClientSecret string `json:"clientSecret"` } -type StripeSubscriptionInfo struct { - PlanCountry string - AccountCountry StripeAccountCountry -} - type StripeEventLog struct { UserID int64 StripeSubscription stripe.Subscription diff --git a/server/pkg/controller/billing.go b/server/pkg/controller/billing.go index 228a3344bc..0d01aeeb9a 100644 --- a/server/pkg/controller/billing.go +++ b/server/pkg/controller/billing.go @@ -85,30 +85,27 @@ func (c *BillingController) GetPlansV2(countryCode string, stripeAccountCountry // GetStripeAccountCountry returns the stripe account country the user's existing plan is from // if he doesn't have a stripe subscription then ente.DefaultStripeAccountCountry is returned func (c *BillingController) GetStripeAccountCountry(userID int64) (ente.StripeAccountCountry, error) { - stipeSubInfo, hasStripeSub, err := c.GetUserStripeSubscriptionInfo(userID) + subscription, err := c.BillingRepo.GetUserSubscription(userID) if err != nil { return "", stacktrace.Propagate(err, "") } - if hasStripeSub { - return stipeSubInfo.AccountCountry, nil - } else { + if subscription.PaymentProvider != ente.Stripe { //if user doesn't have a stripe subscription, return the default stripe account country return ente.DefaultStripeAccountCountry, nil + } else { + return subscription.Attributes.StripeAccountCountry, nil } } // GetUserPlans returns the active plans for a user func (c *BillingController) GetUserPlans(ctx *gin.Context, userID int64) ([]ente.BillingPlan, error) { - stripeSubInfo, hasStripeSub, err := c.GetUserStripeSubscriptionInfo(userID) + stripeAccountCountry, err := c.GetStripeAccountCountry(userID) if err != nil { - return []ente.BillingPlan{}, stacktrace.Propagate(err, "Failed to get user's subscription country and stripe account") - } - if hasStripeSub { - return c.GetPlansV2(stripeSubInfo.PlanCountry, stripeSubInfo.AccountCountry), nil - } else { - // user doesn't have a stipe subscription, so return the default account plans for the country the user is from - return c.GetPlansV2(network.GetClientCountry(ctx), ente.DefaultStripeAccountCountry), nil + return []ente.BillingPlan{}, stacktrace.Propagate(err, "Failed to get user's country stripe account") } + // always return the plans based on the user's country determined by the IP + return c.GetPlansV2(network.GetClientCountry(ctx), stripeAccountCountry), nil + } // GetSubscription returns the current subscription for a user if any @@ -208,23 +205,6 @@ func (c *BillingController) HasActiveSelfOrFamilySubscription(userID int64) erro return nil } -func (c *BillingController) GetUserStripeSubscriptionInfo(userID int64) (ente.StripeSubscriptionInfo, bool, error) { - s, err := c.BillingRepo.GetUserSubscription(userID) - if err != nil { - return ente.StripeSubscriptionInfo{}, false, stacktrace.Propagate(err, "") - } - // skipping country code extraction for non-stripe subscriptions - // as they have same product id across countries and hence can't be distinquished - if s.PaymentProvider != ente.Stripe { - return ente.StripeSubscriptionInfo{}, false, nil - } - _, countryCode, err := c.getPlanWithCountry(s) - if err != nil { - return ente.StripeSubscriptionInfo{}, false, stacktrace.Propagate(err, "") - } - return ente.StripeSubscriptionInfo{PlanCountry: countryCode, AccountCountry: s.Attributes.StripeAccountCountry}, true, nil -} - // VerifySubscription verifies and returns the verified subscription func (c *BillingController) VerifySubscription( userID int64, From 70cddfdf0bab240095d9b2423ca28d0619a1515e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 12:23:15 +0530 Subject: [PATCH 211/391] [web] Remove Sentry Sentry has a measurable impact on page load, a metric that I'm keen to improve. Apparently by default it loses us 8-9 page speed points, though that can be reduced to 3-4 (https://github.com/getsentry/sentry-javascript/issues/9179). All of this is doable, but there are bigger tasks to deal with. This is not to say that Sentry won't be useful again at some point, when we have time to deal with it better. But right now, we discussed that it's just better to remove Sentry instead of piling on to the sunk cost. --- web/apps/accounts/sentry.client.config.ts | 3 - web/apps/accounts/sentry.edge.config.ts | 0 web/apps/accounts/sentry.properties | 6 - web/apps/accounts/sentry.server.config.ts | 0 web/apps/auth/next.config.js | 4 +- web/apps/auth/sentry.client.config.ts | 3 - web/apps/auth/sentry.edge.config.ts | 0 web/apps/auth/sentry.properties | 6 - web/apps/auth/sentry.server.config.ts | 0 web/apps/auth/src/pages/_error.tsx | 17 -- web/apps/cast/next.config.js | 4 +- web/apps/cast/sentry.client.config.ts | 3 - web/apps/cast/sentry.edge.config.ts | 0 web/apps/cast/sentry.properties | 6 - web/apps/cast/sentry.server.config.ts | 0 web/apps/cast/src/services/InMemoryStore.ts | 1 - web/apps/photos/.env.development | 1 - web/apps/photos/next.config.js | 4 +- web/apps/photos/sentry.client.config.ts | 3 - web/apps/photos/sentry.edge.config.ts | 0 web/apps/photos/sentry.properties | 6 - web/apps/photos/sentry.server.config.ts | 0 .../components/Sidebar/Preferences/index.tsx | 37 +-- web/apps/photos/src/pages/_error.tsx | 17 -- .../src/services/upload/thumbnailService.ts | 9 +- web/package.json | 1 - web/packages/next/next.config.base.js | 33 +- web/packages/shared/electron/service.ts | 10 +- web/packages/shared/electron/types.ts | 1 - web/packages/shared/electron/worker/client.ts | 5 - web/packages/shared/error/index.ts | 9 - web/packages/shared/logging/web.ts | 4 +- web/packages/shared/next/pages/_error.tsx | 17 -- web/packages/shared/package.json | 1 - .../sentry/config/sentry.config.base.ts | 38 --- web/packages/shared/sentry/index.ts | 52 +--- web/packages/shared/sentry/utils.ts | 46 --- web/packages/shared/storage/InMemoryStore.ts | 1 - .../shared/storage/localStorage/helpers.ts | 12 - .../shared/storage/localStorage/index.ts | 2 - web/packages/utils/logging.ts | 4 +- web/yarn.lock | 285 +----------------- 42 files changed, 37 insertions(+), 614 deletions(-) delete mode 100644 web/apps/accounts/sentry.client.config.ts delete mode 100644 web/apps/accounts/sentry.edge.config.ts delete mode 100644 web/apps/accounts/sentry.properties delete mode 100644 web/apps/accounts/sentry.server.config.ts delete mode 100644 web/apps/auth/sentry.client.config.ts delete mode 100644 web/apps/auth/sentry.edge.config.ts delete mode 100644 web/apps/auth/sentry.properties delete mode 100644 web/apps/auth/sentry.server.config.ts delete mode 100644 web/apps/auth/src/pages/_error.tsx delete mode 100644 web/apps/cast/sentry.client.config.ts delete mode 100644 web/apps/cast/sentry.edge.config.ts delete mode 100644 web/apps/cast/sentry.properties delete mode 100644 web/apps/cast/sentry.server.config.ts delete mode 100644 web/apps/photos/sentry.client.config.ts delete mode 100644 web/apps/photos/sentry.edge.config.ts delete mode 100644 web/apps/photos/sentry.properties delete mode 100644 web/apps/photos/sentry.server.config.ts delete mode 100644 web/apps/photos/src/pages/_error.tsx delete mode 100644 web/packages/shared/next/pages/_error.tsx delete mode 100644 web/packages/shared/sentry/config/sentry.config.base.ts delete mode 100644 web/packages/shared/sentry/utils.ts diff --git a/web/apps/accounts/sentry.client.config.ts b/web/apps/accounts/sentry.client.config.ts deleted file mode 100644 index c43273663f..0000000000 --- a/web/apps/accounts/sentry.client.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { initSentry } from "@ente/shared/sentry/config/sentry.config.base"; - -initSentry("https://0f7214c7feb9b1dd2fed5db09b42fa1b@sentry.ente.io/5"); diff --git a/web/apps/accounts/sentry.edge.config.ts b/web/apps/accounts/sentry.edge.config.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/apps/accounts/sentry.properties b/web/apps/accounts/sentry.properties deleted file mode 100644 index 27c3a286f1..0000000000 --- a/web/apps/accounts/sentry.properties +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used by the SentryWebpackPlugin to upload sourcemaps when the -# SENTRY_AUTH_TOKEN environment variable is defined. - -defaults.url = https://sentry.ente.io/ -defaults.org = ente -defaults.project = web-photos diff --git a/web/apps/accounts/sentry.server.config.ts b/web/apps/accounts/sentry.server.config.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/apps/auth/next.config.js b/web/apps/auth/next.config.js index eea88bf938..81a64d7ddf 100644 --- a/web/apps/auth/next.config.js +++ b/web/apps/auth/next.config.js @@ -1,3 +1 @@ -const nextConfigBase = require("@/next/next.config.base.js"); - -module.exports = nextConfigBase; +module.exports = require("@/next/next.config.base.js"); diff --git a/web/apps/auth/sentry.client.config.ts b/web/apps/auth/sentry.client.config.ts deleted file mode 100644 index 373718e8eb..0000000000 --- a/web/apps/auth/sentry.client.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { initSentry } from "@ente/shared/sentry/config/sentry.config.base"; - -initSentry("https://5d344112b570b1a368b6f5c1d0bb798b@sentry.ente.io/8"); diff --git a/web/apps/auth/sentry.edge.config.ts b/web/apps/auth/sentry.edge.config.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/apps/auth/sentry.properties b/web/apps/auth/sentry.properties deleted file mode 100644 index e9b0cad160..0000000000 --- a/web/apps/auth/sentry.properties +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used by the SentryWebpackPlugin to upload sourcemaps when the -# SENTRY_AUTH_TOKEN environment variable is defined. - -defaults.url = https://sentry.ente.io/ -defaults.org = ente -defaults.project = web-auth diff --git a/web/apps/auth/sentry.server.config.ts b/web/apps/auth/sentry.server.config.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/apps/auth/src/pages/_error.tsx b/web/apps/auth/src/pages/_error.tsx deleted file mode 100644 index bf1bb89be3..0000000000 --- a/web/apps/auth/src/pages/_error.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { APPS } from "@ente/shared/apps/constants"; -import ErrorPage from "@ente/shared/next/pages/_error"; -import { useRouter } from "next/router"; -import { AppContext } from "pages/_app"; -import { useContext } from "react"; - -export default function Error() { - const appContext = useContext(AppContext); - const router = useRouter(); - return ( - - ); -} diff --git a/web/apps/cast/next.config.js b/web/apps/cast/next.config.js index eea88bf938..81a64d7ddf 100644 --- a/web/apps/cast/next.config.js +++ b/web/apps/cast/next.config.js @@ -1,3 +1 @@ -const nextConfigBase = require("@/next/next.config.base.js"); - -module.exports = nextConfigBase; +module.exports = require("@/next/next.config.base.js"); diff --git a/web/apps/cast/sentry.client.config.ts b/web/apps/cast/sentry.client.config.ts deleted file mode 100644 index c43273663f..0000000000 --- a/web/apps/cast/sentry.client.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { initSentry } from "@ente/shared/sentry/config/sentry.config.base"; - -initSentry("https://0f7214c7feb9b1dd2fed5db09b42fa1b@sentry.ente.io/5"); diff --git a/web/apps/cast/sentry.edge.config.ts b/web/apps/cast/sentry.edge.config.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/apps/cast/sentry.properties b/web/apps/cast/sentry.properties deleted file mode 100644 index 27c3a286f1..0000000000 --- a/web/apps/cast/sentry.properties +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used by the SentryWebpackPlugin to upload sourcemaps when the -# SENTRY_AUTH_TOKEN environment variable is defined. - -defaults.url = https://sentry.ente.io/ -defaults.org = ente -defaults.project = web-photos diff --git a/web/apps/cast/sentry.server.config.ts b/web/apps/cast/sentry.server.config.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/apps/cast/src/services/InMemoryStore.ts b/web/apps/cast/src/services/InMemoryStore.ts index ded73faf05..88e77b8699 100644 --- a/web/apps/cast/src/services/InMemoryStore.ts +++ b/web/apps/cast/src/services/InMemoryStore.ts @@ -1,5 +1,4 @@ export enum MS_KEYS { - OPT_OUT_OF_CRASH_REPORTS = "optOutOfCrashReports", SRP_CONFIGURE_IN_PROGRESS = "srpConfigureInProgress", REDIRECT_URL = "redirectUrl", } diff --git a/web/apps/photos/.env.development b/web/apps/photos/.env.development index 045fffaee0..038f0237a9 100644 --- a/web/apps/photos/.env.development +++ b/web/apps/photos/.env.development @@ -22,7 +22,6 @@ # # - Logs go to the browser console (in addition to the log file) # - There is some additional logging -# - Sentry is not initialized # - ... (search for isDevBuild to see all impacts) # # Note that even in development build, the app still connects to the production diff --git a/web/apps/photos/next.config.js b/web/apps/photos/next.config.js index eea88bf938..81a64d7ddf 100644 --- a/web/apps/photos/next.config.js +++ b/web/apps/photos/next.config.js @@ -1,3 +1 @@ -const nextConfigBase = require("@/next/next.config.base.js"); - -module.exports = nextConfigBase; +module.exports = require("@/next/next.config.base.js"); diff --git a/web/apps/photos/sentry.client.config.ts b/web/apps/photos/sentry.client.config.ts deleted file mode 100644 index c43273663f..0000000000 --- a/web/apps/photos/sentry.client.config.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { initSentry } from "@ente/shared/sentry/config/sentry.config.base"; - -initSentry("https://0f7214c7feb9b1dd2fed5db09b42fa1b@sentry.ente.io/5"); diff --git a/web/apps/photos/sentry.edge.config.ts b/web/apps/photos/sentry.edge.config.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/apps/photos/sentry.properties b/web/apps/photos/sentry.properties deleted file mode 100644 index 27c3a286f1..0000000000 --- a/web/apps/photos/sentry.properties +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used by the SentryWebpackPlugin to upload sourcemaps when the -# SENTRY_AUTH_TOKEN environment variable is defined. - -defaults.url = https://sentry.ente.io/ -defaults.org = ente -defaults.project = web-photos diff --git a/web/apps/photos/sentry.server.config.ts b/web/apps/photos/sentry.server.config.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/web/apps/photos/src/components/Sidebar/Preferences/index.tsx b/web/apps/photos/src/components/Sidebar/Preferences/index.tsx index ec9d61a47e..04dc79a13c 100644 --- a/web/apps/photos/src/components/Sidebar/Preferences/index.tsx +++ b/web/apps/photos/src/components/Sidebar/Preferences/index.tsx @@ -1,17 +1,10 @@ import ChevronRight from "@mui/icons-material/ChevronRight"; import { Box, DialogProps, Stack } from "@mui/material"; import { EnteDrawer } from "components/EnteDrawer"; +import { EnteMenuItem } from "components/Menu/EnteMenuItem"; import Titlebar from "components/Titlebar"; import { t } from "i18next"; -import isElectron from "is-electron"; import { useState } from "react"; - -import ElectronAPIs from "@ente/shared/electron"; -import { useLocalState } from "@ente/shared/hooks/useLocalState"; -import { logError } from "@ente/shared/sentry"; -import InMemoryStore, { MS_KEYS } from "@ente/shared/storage/InMemoryStore"; -import { LS_KEYS } from "@ente/shared/storage/localStorage"; -import { EnteMenuItem } from "components/Menu/EnteMenuItem"; import AdvancedSettings from "../AdvancedSettings"; import MapSettings from "../MapSetting"; import { LanguageSelector } from "./LanguageSelector"; @@ -19,10 +12,6 @@ import { LanguageSelector } from "./LanguageSelector"; export default function Preferences({ open, onClose, onRootClose }) { const [advancedSettingsView, setAdvancedSettingsView] = useState(false); const [mapSettingsView, setMapSettingsView] = useState(false); - const [optOutOfCrashReports, setOptOutOfCrashReports] = useLocalState( - LS_KEYS.OPT_OUT_OF_CRASH_REPORTS, - false, - ); const openAdvancedSettings = () => setAdvancedSettingsView(true); const closeAdvancedSettings = () => setAdvancedSettingsView(false); @@ -43,23 +32,6 @@ export default function Preferences({ open, onClose, onRootClose }) { } }; - const toggleOptOutOfCrashReports = async () => { - try { - if (isElectron()) { - await ElectronAPIs.updateOptOutOfCrashReports( - !optOutOfCrashReports, - ); - } - setOptOutOfCrashReports(!optOutOfCrashReports); - InMemoryStore.set( - MS_KEYS.OPT_OUT_OF_CRASH_REPORTS, - !optOutOfCrashReports, - ); - } catch (e) { - logError(e, "toggleOptOutOfCrashReports failed"); - } - }; - return ( - - } diff --git a/web/apps/photos/src/pages/_error.tsx b/web/apps/photos/src/pages/_error.tsx deleted file mode 100644 index bf1bb89be3..0000000000 --- a/web/apps/photos/src/pages/_error.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { APPS } from "@ente/shared/apps/constants"; -import ErrorPage from "@ente/shared/next/pages/_error"; -import { useRouter } from "next/router"; -import { AppContext } from "pages/_app"; -import { useContext } from "react"; - -export default function Error() { - const appContext = useContext(AppContext); - const router = useRouter(); - return ( - - ); -} diff --git a/web/apps/photos/src/services/upload/thumbnailService.ts b/web/apps/photos/src/services/upload/thumbnailService.ts index 8b1cf7a617..74ce23f4ca 100644 --- a/web/apps/photos/src/services/upload/thumbnailService.ts +++ b/web/apps/photos/src/services/upload/thumbnailService.ts @@ -1,4 +1,4 @@ -import { CustomError, errorWithContext } from "@ente/shared/error"; +import { CustomError } from "@ente/shared/error"; import { addLogLine } from "@ente/shared/logging"; import { getFileNameSize } from "@ente/shared/logging/web"; import { logError } from "@ente/shared/sentry"; @@ -145,10 +145,9 @@ export async function generateImageThumbnailUsingCanvas( clearTimeout(timeout); resolve(null); } catch (e) { - const err = errorWithContext( - e, - `${CustomError.THUMBNAIL_GENERATION_FAILED} err: ${e}`, - ); + const err = new Error(CustomError.THUMBNAIL_GENERATION_FAILED, { + cause: e, + }); reject(err); } }; diff --git a/web/package.json b/web/package.json index bdbce0b429..f7e734651f 100644 --- a/web/package.json +++ b/web/package.json @@ -26,7 +26,6 @@ "lint-fix": "yarn prettier --write . && yarn workspaces run eslint --fix ." }, "resolutions": { - "@sentry/cli": "1.75.0", "libsodium": "0.7.9" }, "devDependencies": { diff --git a/web/packages/next/next.config.base.js b/web/packages/next/next.config.base.js index 5439c94431..ef7b65facf 100644 --- a/web/packages/next/next.config.base.js +++ b/web/packages/next/next.config.base.js @@ -10,7 +10,6 @@ * https://nextjs.org/docs/pages/api-reference/next-config-js */ -const { withSentryConfig } = require("@sentry/nextjs"); const cp = require("child_process"); const gitSHA = cp @@ -21,8 +20,7 @@ const gitSHA = cp .trimEnd(); /** - * The base Next.js config. Before exporting this, we wrap this in - * {@link withSentryConfig}. + * Configuration for the Next.js build * * @type {import("next").NextConfig} */ @@ -54,33 +52,6 @@ const nextConfig = { } return config; }, - - // Build time Sentry configuration - // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ - sentry: { - widenClientFileUpload: true, - disableServerWebpackPlugin: true, - }, -}; - -const sentryWebpackPluginOptions = { - // The same release value needs to be used both: - // 1. here to create a new release on Sentry and upload sourcemaps to it, - // 2. and when initializing Sentry in the browser (`Sentry.init`). - release: gitSHA, }; -// withSentryConfig extends the default Next.js usage of webpack to: -// -// 1. Initialize the SDK on client page load (See `sentry.client.config.ts`) -// -// 2. Upload sourcemaps, using the settings defined in `sentry.properties`. -// -// Sourcemaps are only uploaded to Sentry if SENTRY_AUTH_TOKEN is defined. Note -// that sourcemaps are always generated in the static export; the Sentry Webpack -// plugin behavies as if the `productionBrowserSourceMaps` Next.js configuration -// setting is `true`. -// -// Irritatingly, Sentry insists that we create empty sentry.server.config.ts and -// sentry.edge.config.ts files, even though we are not using those parts. -module.exports = withSentryConfig(nextConfig, sentryWebpackPluginOptions); +module.exports = nextConfig; diff --git a/web/packages/shared/electron/service.ts b/web/packages/shared/electron/service.ts index 2f00b42f45..8e035e6326 100644 --- a/web/packages/shared/electron/service.ts +++ b/web/packages/shared/electron/service.ts @@ -12,11 +12,7 @@ import { deserializeToResponse, serializeResponse } from "./worker/utils/proxy"; export interface LimitedElectronAPIs extends Pick< ElectronAPIsType, - | "openDiskCache" - | "deleteDiskCache" - | "getSentryUserID" - | "convertToJPEG" - | "logToDisk" + "openDiskCache" | "deleteDiskCache" | "convertToJPEG" | "logToDisk" > {} class WorkerSafeElectronServiceImpl implements LimitedElectronAPIs { @@ -56,10 +52,6 @@ class WorkerSafeElectronServiceImpl implements LimitedElectronAPIs { return await this.proxiedElectron.deleteDiskCache(cacheName); } - async getSentryUserID() { - await this.ready; - return this.proxiedElectron.getSentryUserID(); - } async convertToJPEG( inputFileData: Uint8Array, filename: string, diff --git a/web/packages/shared/electron/types.ts b/web/packages/shared/electron/types.ts index df5829ab05..6b1bff4aae 100644 --- a/web/packages/shared/electron/types.ts +++ b/web/packages/shared/electron/types.ts @@ -80,7 +80,6 @@ export interface ElectronAPIsType { ) => void; updateAndRestart: () => void; skipAppUpdate: (version: string) => void; - getSentryUserID: () => Promise; getAppVersion: () => Promise; runFFmpegCmd: ( cmd: string[], diff --git a/web/packages/shared/electron/worker/client.ts b/web/packages/shared/electron/worker/client.ts index 12b34a4e78..92db7d9725 100644 --- a/web/packages/shared/electron/worker/client.ts +++ b/web/packages/shared/electron/worker/client.ts @@ -9,7 +9,6 @@ export interface ProxiedLimitedElectronAPIs { cacheLimitInBytes?: number, ) => Promise; deleteDiskCache: (cacheName: string) => Promise; - getSentryUserID: () => Promise; convertToJPEG: ( inputFileData: Uint8Array, filename: string, @@ -42,10 +41,6 @@ export class WorkerSafeElectronClient implements ProxiedLimitedElectronAPIs { return await ElectronAPIs.deleteDiskCache(cacheName); } - async getSentryUserID() { - return await ElectronAPIs.getSentryUserID(); - } - async convertToJPEG( inputFileData: Uint8Array, filename: string, diff --git a/web/packages/shared/error/index.ts b/web/packages/shared/error/index.ts index 0463c96103..be8f10cead 100644 --- a/web/packages/shared/error/index.ts +++ b/web/packages/shared/error/index.ts @@ -109,15 +109,6 @@ export function handleUploadError(error: any): Error { return parsedError; } -export function errorWithContext(originalError: Error, context: string) { - const errorWithContext = new Error(context); - errorWithContext.stack = - errorWithContext.stack?.split("\n").slice(2, 4).join("\n") + - "\n" + - originalError.stack; - return errorWithContext; -} - export function parseUploadErrorCodes(error: any) { let parsedMessage = null; if (error instanceof ApiError) { diff --git a/web/packages/shared/logging/web.ts b/web/packages/shared/logging/web.ts index e0c36dc89a..4fee25258f 100644 --- a/web/packages/shared/logging/web.ts +++ b/web/packages/shared/logging/web.ts @@ -7,7 +7,6 @@ import { setData, } from "@ente/shared/storage/localStorage"; import { addLogLine } from "."; -import { getSentryUserID } from "../sentry/utils"; import { formatDateTimeShort } from "../time/format"; import { ElectronFile } from "../upload/types"; import type { User } from "../user/types"; @@ -75,10 +74,9 @@ export const logStartupMessage = async (appId: string) => { // TODO (MR): Remove the need to lowercase it, change the enum itself. const appIdL = appId.toLowerCase(); const userID = (getData(LS_KEYS.USER) as User)?.id; - const sentryID = await getSentryUserID(); const buildId = isDevBuild ? "dev" : `git ${process.env.GIT_SHA}`; - addLogLine(`ente-${appIdL}-web ${buildId} uid ${userID} sid ${sentryID}`); + addLogLine(`ente-${appIdL} ${buildId} uid ${userID}`); }; function getLogs(): Log[] { diff --git a/web/packages/shared/next/pages/_error.tsx b/web/packages/shared/next/pages/_error.tsx deleted file mode 100644 index c0fc2e39f2..0000000000 --- a/web/packages/shared/next/pages/_error.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as Sentry from "@sentry/nextjs"; -import NextErrorComponent from "next/error"; - -const CustomErrorComponent = (props) => ( - -); - -CustomErrorComponent.getInitialProps = async (contextData) => { - // In case this is running in a serverless function, await this in order to give Sentry - // time to send the error before the lambda exits - await Sentry.captureUnderscoreErrorException(contextData); - - // This will contain the status code of the response - return NextErrorComponent.getInitialProps(contextData); -}; - -export default CustomErrorComponent; diff --git a/web/packages/shared/package.json b/web/packages/shared/package.json index b4d4e1671a..807fdd7e69 100644 --- a/web/packages/shared/package.json +++ b/web/packages/shared/package.json @@ -5,7 +5,6 @@ "dependencies": { "@/next": "*", "@ente/eslint-config": "*", - "@sentry/nextjs": "7.77.0", "axios": "^1.6.7" } } diff --git a/web/packages/shared/sentry/config/sentry.config.base.ts b/web/packages/shared/sentry/config/sentry.config.base.ts deleted file mode 100644 index d37572de69..0000000000 --- a/web/packages/shared/sentry/config/sentry.config.base.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { isDevBuild } from "@/utils/env"; -import { runningInBrowser } from "@ente/shared/platform"; -import { getSentryUserID } from "@ente/shared/sentry/utils"; -import { getHasOptedOutOfCrashReports } from "@ente/shared/storage/localStorage/helpers"; -import * as Sentry from "@sentry/nextjs"; - -export const initSentry = async (dsn: string) => { - // Don't initialize Sentry for dev builds - if (isDevBuild) return; - - // Don't initialize Sentry if the user has opted out of crash reporting - if (optedOut()) return; - - Sentry.init({ - dsn, - release: process.env.GIT_SHA, - attachStacktrace: true, - autoSessionTracking: false, - tunnel: "https://sentry-reporter.ente.io", - beforeSend(event) { - event.request = event.request || {}; - const currentURL = new URL(document.location.href); - currentURL.hash = ""; - event.request.url = currentURL.href; - return event; - }, - integrations: function (i) { - return i.filter(function (i) { - return i.name !== "Breadcrumbs"; - }); - }, - }); - - Sentry.setUser({ id: await getSentryUserID() }); -}; - -/** Return true if the user has opted out of crash reporting */ -const optedOut = () => runningInBrowser() && getHasOptedOutOfCrashReports(); diff --git a/web/packages/shared/sentry/index.ts b/web/packages/shared/sentry/index.ts index 9279c1134f..2dae035b72 100644 --- a/web/packages/shared/sentry/index.ts +++ b/web/packages/shared/sentry/index.ts @@ -1,59 +1,27 @@ -import { ApiError, errorWithContext } from "@ente/shared/error"; -import { addLocalLog, addLogLine } from "@ente/shared/logging"; -import { - getSentryUserID, - isErrorUnnecessaryForSentry, -} from "@ente/shared/sentry/utils"; -import InMemoryStore, { MS_KEYS } from "@ente/shared/storage/InMemoryStore"; -import { getHasOptedOutOfCrashReports } from "@ente/shared/storage/localStorage/helpers"; -import * as Sentry from "@sentry/nextjs"; +import { ApiError } from "@ente/shared/error"; +import { addLogLine } from "@ente/shared/logging"; +/** Deprecated: Use `logError` from `@/utils/logging` */ export const logError = async ( error: any, msg: string, info?: Record, skipAddLogLine = false, ) => { - const err = errorWithContext(error, msg); - if (!skipAddLogLine) { - if (error instanceof ApiError) { - addLogLine(`error: ${error?.name} ${error?.message} + if (skipAddLogLine) return; + + if (error instanceof ApiError) { + addLogLine(`error: ${error?.name} ${error?.message} msg: ${msg} errorCode: ${JSON.stringify(error?.errCode)} httpStatusCode: ${JSON.stringify(error?.httpStatusCode)} ${ info ? `info: ${JSON.stringify(info)}` : "" } ${error?.stack}`); - } else { - addLogLine( - `error: ${error?.name} ${error?.message} + } else { + addLogLine( + `error: ${error?.name} ${error?.message} msg: ${msg} ${info ? `info: ${JSON.stringify(info)}` : ""} ${error?.stack}`, - ); - } - } - if (!InMemoryStore.has(MS_KEYS.OPT_OUT_OF_CRASH_REPORTS)) { - const optedOutOfCrashReports = getHasOptedOutOfCrashReports(); - InMemoryStore.set( - MS_KEYS.OPT_OUT_OF_CRASH_REPORTS, - optedOutOfCrashReports, ); } - if (InMemoryStore.get(MS_KEYS.OPT_OUT_OF_CRASH_REPORTS)) { - addLocalLog(() => `skipping sentry error: ${error?.name}`); - return; - } - if (isErrorUnnecessaryForSentry(error)) { - return; - } - - Sentry.captureException(err, { - level: "info", - user: { id: await getSentryUserID() }, - contexts: { - ...(info && { - info: info, - }), - rootCause: { message: error?.message, completeError: error }, - }, - }); }; diff --git a/web/packages/shared/sentry/utils.ts b/web/packages/shared/sentry/utils.ts deleted file mode 100644 index 258db570eb..0000000000 --- a/web/packages/shared/sentry/utils.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { WorkerSafeElectronService } from "@ente/shared/electron/service"; -import { - getLocalSentryUserID, - setLocalSentryUserID, -} from "@ente/shared/storage/localStorage/helpers"; -import { HttpStatusCode } from "axios"; -import isElectron from "is-electron"; -import { ApiError } from "../error"; - -export async function getSentryUserID() { - if (isElectron()) { - return await WorkerSafeElectronService.getSentryUserID(); - } else { - let anonymizeUserID = getLocalSentryUserID(); - if (!anonymizeUserID) { - anonymizeUserID = makeID(6); - setLocalSentryUserID(anonymizeUserID); - } - return anonymizeUserID; - } -} - -function makeID(length) { - let result = ""; - const characters = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - const charactersLength = characters.length; - for (let i = 0; i < length; i++) { - result += characters.charAt( - Math.floor(Math.random() * charactersLength), - ); - } - return result; -} - -export function isErrorUnnecessaryForSentry(error: any) { - if (error?.message?.includes("Network Error")) { - return true; - } else if ( - error instanceof ApiError && - error.httpStatusCode === HttpStatusCode.Unauthorized - ) { - return true; - } - return false; -} diff --git a/web/packages/shared/storage/InMemoryStore.ts b/web/packages/shared/storage/InMemoryStore.ts index ded73faf05..88e77b8699 100644 --- a/web/packages/shared/storage/InMemoryStore.ts +++ b/web/packages/shared/storage/InMemoryStore.ts @@ -1,5 +1,4 @@ export enum MS_KEYS { - OPT_OUT_OF_CRASH_REPORTS = "optOutOfCrashReports", SRP_CONFIGURE_IN_PROGRESS = "srpConfigureInProgress", REDIRECT_URL = "redirectUrl", } diff --git a/web/packages/shared/storage/localStorage/helpers.ts b/web/packages/shared/storage/localStorage/helpers.ts index d8092a56a4..95ae280e37 100644 --- a/web/packages/shared/storage/localStorage/helpers.ts +++ b/web/packages/shared/storage/localStorage/helpers.ts @@ -37,18 +37,6 @@ export function setLocalMapEnabled(value: boolean) { setData(LS_KEYS.MAP_ENABLED, { value }); } -export function getHasOptedOutOfCrashReports(): boolean { - return getData(LS_KEYS.OPT_OUT_OF_CRASH_REPORTS)?.value ?? false; -} - -export function getLocalSentryUserID() { - return getData(LS_KEYS.AnonymizedUserID)?.id; -} - -export function setLocalSentryUserID(id: string) { - setData(LS_KEYS.AnonymizedUserID, { id }); -} - export function getLocalReferralSource() { return getData(LS_KEYS.REFERRAL_SOURCE)?.source; } diff --git a/web/packages/shared/storage/localStorage/index.ts b/web/packages/shared/storage/localStorage/index.ts index e40b644577..14901fdd4d 100644 --- a/web/packages/shared/storage/localStorage/index.ts +++ b/web/packages/shared/storage/localStorage/index.ts @@ -12,7 +12,6 @@ export enum LS_KEYS { JUST_SIGNED_UP = "justSignedUp", SHOW_BACK_BUTTON = "showBackButton", EXPORT = "export", - AnonymizedUserID = "anonymizedUserID", THUMBNAIL_FIX_STATE = "thumbnailFixState", LIVE_PHOTO_INFO_SHOWN_COUNT = "livePhotoInfoShownCount", LOGS = "logs", @@ -26,7 +25,6 @@ export enum LS_KEYS { MAP_ENABLED = "mapEnabled", SRP_SETUP_ATTRIBUTES = "srpSetupAttributes", SRP_ATTRIBUTES = "srpAttributes", - OPT_OUT_OF_CRASH_REPORTS = "optOutOfCrashReports", CF_PROXY_DISABLED = "cfProxyDisabled", REFERRAL_SOURCE = "referralSource", CLIENT_PACKAGE = "clientPackage", diff --git a/web/packages/utils/logging.ts b/web/packages/utils/logging.ts index b3d7d85679..cd9c4b53bb 100644 --- a/web/packages/utils/logging.ts +++ b/web/packages/utils/logging.ts @@ -17,7 +17,7 @@ * * TODO (MR): Currently this is a placeholder function to funnel error logs * through. This needs to do what the existing logError in @ente/shared does, - * but it cannot have a direct Electron/Sentry dependency here. For now, we just + * but it cannot have a direct Electron dependency here. For now, we just * log on the console. */ export const logError = (message: string, e?: unknown) => { @@ -35,5 +35,7 @@ export const logError = (message: string, e?: unknown) => { // For the rest rare cases, use the default string serialization of e. es = String(e); } + + // TODO(MR): Use addLogLine console.error(`${message}: ${es}`); }; diff --git a/web/yarn.lock b/web/yarn.lock index be4cf6488f..2f5cbb105e 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -302,11 +302,6 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" -"@jridgewell/sourcemap-codec@^1.4.13": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - "@mui/base@5.0.0-beta.36": version "5.0.0-beta.36" resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.36.tgz#29ca2de9d387f6d3943b6f18a84415c43e5f206c" @@ -538,161 +533,11 @@ dependencies: dequal "^2.0.3" -"@rollup/plugin-commonjs@24.0.0": - version "24.0.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.0.tgz#fb7cf4a6029f07ec42b25daa535c75b05a43f75c" - integrity sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g== - dependencies: - "@rollup/pluginutils" "^5.0.1" - commondir "^1.0.1" - estree-walker "^2.0.2" - glob "^8.0.3" - is-reference "1.2.1" - magic-string "^0.27.0" - -"@rollup/pluginutils@^5.0.1": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0" - integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== - dependencies: - "@types/estree" "^1.0.0" - estree-walker "^2.0.2" - picomatch "^2.3.1" - "@rushstack/eslint-patch@^1.3.3": version "1.7.2" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz#2d4260033e199b3032a08b41348ac10de21c47e9" integrity sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA== -"@sentry-internal/tracing@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.77.0.tgz#f3d82486f8934a955b3dd2aa54c8d29586e42a37" - integrity sha512-8HRF1rdqWwtINqGEdx8Iqs9UOP/n8E0vXUu3Nmbqj4p5sQPA7vvCfq+4Y4rTqZFc7sNdFpDsRION5iQEh8zfZw== - dependencies: - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/browser@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.77.0.tgz#155440f1a0d3a1bbd5d564c28d6b0c9853a51d72" - integrity sha512-nJ2KDZD90H8jcPx9BysQLiQW+w7k7kISCWeRjrEMJzjtge32dmHA8G4stlUTRIQugy5F+73cOayWShceFP7QJQ== - dependencies: - "@sentry-internal/tracing" "7.77.0" - "@sentry/core" "7.77.0" - "@sentry/replay" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/cli@1.75.0", "@sentry/cli@^1.74.6": - version "1.75.0" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.75.0.tgz#4a5e71b5619cd4e9e6238cc77857c66f6b38d86a" - integrity sha512-vT8NurHy00GcN8dNqur4CMIYvFH3PaKdkX3qllVvi4syybKqjwoz+aWRCvprbYv0knweneFkLt1SmBWqazUMfA== - dependencies: - https-proxy-agent "^5.0.0" - mkdirp "^0.5.5" - node-fetch "^2.6.7" - progress "^2.0.3" - proxy-from-env "^1.1.0" - which "^2.0.2" - -"@sentry/core@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.77.0.tgz#21100843132beeeff42296c8370cdcc7aa1d8510" - integrity sha512-Tj8oTYFZ/ZD+xW8IGIsU6gcFXD/gfE+FUxUaeSosd9KHwBQNOLhZSsYo/tTVf/rnQI/dQnsd4onPZLiL+27aTg== - dependencies: - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/integrations@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-7.77.0.tgz#f2717e05cb7c69363316ccd34096b2ea07ae4c59" - integrity sha512-P055qXgBHeZNKnnVEs5eZYLdy6P49Zr77A1aWJuNih/EenzMy922GOeGy2mF6XYrn1YJSjEwsNMNsQkcvMTK8Q== - dependencies: - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - localforage "^1.8.1" - -"@sentry/nextjs@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/nextjs/-/nextjs-7.77.0.tgz#036b1c45dd106e01d44967c97985464e108922be" - integrity sha512-8tYPBt5luFjrng1sAMJqNjM9sq80q0jbt6yariADU9hEr7Zk8YqFaOI2/Q6yn9dZ6XyytIRtLEo54kk2AO94xw== - dependencies: - "@rollup/plugin-commonjs" "24.0.0" - "@sentry/core" "7.77.0" - "@sentry/integrations" "7.77.0" - "@sentry/node" "7.77.0" - "@sentry/react" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - "@sentry/vercel-edge" "7.77.0" - "@sentry/webpack-plugin" "1.20.0" - chalk "3.0.0" - resolve "1.22.8" - rollup "2.78.0" - stacktrace-parser "^0.1.10" - -"@sentry/node@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.77.0.tgz#a247452779a5bcb55724457707286e3e4a29dbbe" - integrity sha512-Ob5tgaJOj0OYMwnocc6G/CDLWC7hXfVvKX/ofkF98+BbN/tQa5poL+OwgFn9BA8ud8xKzyGPxGU6LdZ8Oh3z/g== - dependencies: - "@sentry-internal/tracing" "7.77.0" - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - https-proxy-agent "^5.0.0" - -"@sentry/react@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-7.77.0.tgz#9da14e4b21eae4b5a6306d39bb7c42ef0827d2c2" - integrity sha512-Q+htKzib5em0MdaQZMmPomaswaU3xhcVqmLi2CxqQypSjbYgBPPd+DuhrXKoWYLDDkkbY2uyfe4Lp3yLRWeXYw== - dependencies: - "@sentry/browser" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - hoist-non-react-statics "^3.3.2" - -"@sentry/replay@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.77.0.tgz#21d242c9cd70a7235237216174873fd140b6eb80" - integrity sha512-M9Ik2J5ekl+C1Och3wzLRZVaRGK33BlnBwfwf3qKjgLDwfKW+1YkwDfTHbc2b74RowkJbOVNcp4m8ptlehlSaQ== - dependencies: - "@sentry-internal/tracing" "7.77.0" - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/types@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.77.0.tgz#c5d00fe547b89ccde59cdea59143bf145cee3144" - integrity sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA== - -"@sentry/utils@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.77.0.tgz#1f88501f0b8777de31b371cf859d13c82ebe1379" - integrity sha512-NmM2kDOqVchrey3N5WSzdQoCsyDkQkiRxExPaNI2oKQ/jMWHs9yt0tSy7otPBcXs0AP59ihl75Bvm1tDRcsp5g== - dependencies: - "@sentry/types" "7.77.0" - -"@sentry/vercel-edge@7.77.0": - version "7.77.0" - resolved "https://registry.yarnpkg.com/@sentry/vercel-edge/-/vercel-edge-7.77.0.tgz#6a90a869878e4e78803c4331c30aea841fcc6a73" - integrity sha512-ffddPCgxVeAccPYuH5sooZeHBqDuJ9OIhIRYKoDi4TvmwAzWo58zzZWhRpkHqHgIQdQvhLVZ5F+FSQVWnYSOkw== - dependencies: - "@sentry/core" "7.77.0" - "@sentry/types" "7.77.0" - "@sentry/utils" "7.77.0" - -"@sentry/webpack-plugin@1.20.0": - version "1.20.0" - resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.20.0.tgz#e7add76122708fb6b4ee7951294b521019720e58" - integrity sha512-Ssj1mJVFsfU6vMCOM2d+h+KQR7QHSfeIP16t4l20Uq/neqWXZUQ2yvQfe4S3BjdbJXz/X4Rw8Hfy1Sd0ocunYw== - dependencies: - "@sentry/cli" "^1.74.6" - webpack-sources "^2.0.0 || ^3.0.0" - "@stripe/stripe-js@^1.13.2": version "1.54.2" resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.54.2.tgz#0665848e22cbda936cfd05256facdfbba121438d" @@ -764,11 +609,6 @@ "@types/node" "*" base-x "^3.0.6" -"@types/estree@*", "@types/estree@^1.0.0": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - "@types/geojson@*": version "7946.0.14" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" @@ -1127,13 +967,6 @@ acorn@^8.0.4, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== -agent-base@6: - version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" - integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== - dependencies: - debug "4" - ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1444,14 +1277,6 @@ caniuse-lite@^1.0.30001579: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz#7ad6dba4c9bf6561aec8291976402339dc157dfb" integrity sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg== -chalk@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1552,11 +1377,6 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1631,13 +1451,6 @@ debounce@^2.0.0: resolved "https://registry.yarnpkg.com/debounce/-/debounce-2.0.0.tgz#b2f914518a1481466f4edaee0b063e4d473ad549" integrity sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA== -debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1645,6 +1458,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -2100,11 +1920,6 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-walker@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -2382,17 +2197,6 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.3: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - globals@^13.19.0: version "13.24.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" @@ -2523,7 +2327,7 @@ heic-decode@^2.0.0: dependencies: libheif-js "^1.17.1" -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -2553,14 +2357,6 @@ html-tokenize@^2.0.0: readable-stream "~1.0.27-1" through2 "~0.4.1" -https-proxy-agent@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - i18next-http-backend@^2.5: version "2.5.0" resolved "https://registry.yarnpkg.com/i18next-http-backend/-/i18next-http-backend-2.5.0.tgz#8396a7df30bfe722eff7a65f629df32a61720414" @@ -2781,13 +2577,6 @@ is-plain-object@^5.0.0: resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== -is-reference@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" - integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== - dependencies: - "@types/estree" "*" - is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -3041,7 +2830,7 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -localforage@^1.8.1, localforage@^1.9.0: +localforage@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== @@ -3099,13 +2888,6 @@ lru-cache@^6.0.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== -magic-string@^0.27.0: - version "0.27.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" - integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" - "memoize-one@>=3.1.1 <6", memoize-one@^5.0.0: version "5.2.1" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" @@ -3155,13 +2937,6 @@ minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.5: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" @@ -3172,13 +2947,6 @@ minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.5: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== -mkdirp@^0.5.5: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - ml-array-max@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/ml-array-max/-/ml-array-max-1.2.4.tgz#2373e2b7e51c8807e456cc0ef364c5863713623b" @@ -3266,7 +3034,7 @@ next@^14.1: "@next/swc-win32-ia32-msvc" "14.1.0" "@next/swc-win32-x64-msvc" "14.1.0" -node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: +node-fetch@^2.6.1, node-fetch@^2.6.12: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -3549,11 +3317,6 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -progress@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - prop-types-extra@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" @@ -3852,7 +3615,7 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve@1.22.8, resolve@^1.19.0, resolve@^1.22.4: +resolve@^1.19.0, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -3887,13 +3650,6 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup@2.78.0: - version "2.78.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.78.0.tgz#00995deae70c0f712ea79ad904d5f6b033209d9e" - integrity sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg== - optionalDependencies: - fsevents "~2.3.2" - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -4081,13 +3837,6 @@ source-map@^0.5.7: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -stacktrace-parser@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" - integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== - dependencies: - type-fest "^0.7.1" - streamsearch@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" @@ -4356,11 +4105,6 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - type-fest@^2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" @@ -4503,11 +4247,6 @@ webpack-bundle-analyzer@4.10.1: sirv "^2.0.3" ws "^7.3.1" -"webpack-sources@^2.0.0 || ^3.0.0": - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -4566,7 +4305,7 @@ which-typed-array@^1.1.14, which-typed-array@^1.1.9: gopd "^1.0.1" has-tostringtag "^1.0.1" -which@^2.0.1, which@^2.0.2: +which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== From 9b6e47d2915a2a16c3a512d840dbde4612a8b99d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 13:28:06 +0530 Subject: [PATCH 212/391] [desktop] Remove sentry See 70cddfdf0bab240095d9b2423ca28d0619a1515e --- desktop/.github/workflows/build.yml | 3 - desktop/package.json | 2 - desktop/sentry.properties | 3 - desktop/src/api/common.ts | 7 +- desktop/src/api/electronStore.ts | 2 - desktop/src/config/index.ts | 20 -- desktop/src/main.ts | 17 -- desktop/src/preload.ts | 4 - desktop/src/services/fs.ts | 3 +- desktop/src/services/logging.ts | 8 - desktop/src/services/sentry.ts | 54 +---- desktop/src/services/userPreference.ts | 8 - desktop/src/stores/userPreferences.store.ts | 3 - desktop/src/types/index.ts | 1 - desktop/src/utils/ipcComms.ts | 11 +- desktop/src/utils/logging.ts | 18 +- desktop/src/utils/main.ts | 4 +- desktop/yarn.lock | 244 +------------------- 18 files changed, 19 insertions(+), 393 deletions(-) delete mode 100644 desktop/sentry.properties delete mode 100644 desktop/src/config/index.ts diff --git a/desktop/.github/workflows/build.yml b/desktop/.github/workflows/build.yml index c43dfcfdfe..acd744c056 100644 --- a/desktop/.github/workflows/build.yml +++ b/desktop/.github/workflows/build.yml @@ -52,7 +52,4 @@ jobs: # macOS notarization API key API_KEY_ID: ${{ secrets.api_key_id }} API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id}} - # setry crash reporting token - SENTRY_AUTH_TOKEN: ${{secrets.sentry_auth_token}} - NEXT_PUBLIC_DISABLE_SENTRY: ${{secrets.next_public_disable_sentry}} USE_HARD_LINKS: false diff --git a/desktop/package.json b/desktop/package.json index b0ea95b093..fe0b9b8ffe 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -18,7 +18,6 @@ "watch": "tsc -w" }, "dependencies": { - "@sentry/electron": "^2.5.1", "any-shell-escape": "^0.1.1", "auto-launch": "^5.0.5", "chokidar": "^3.5.3", @@ -38,7 +37,6 @@ "promise-fs": "^2.1.1" }, "devDependencies": { - "@sentry/cli": "^1.68.0", "@types/auto-launch": "^5.0.2", "@types/ffmpeg-static": "^3.0.1", "@types/get-folder-size": "^2.0.0", diff --git a/desktop/sentry.properties b/desktop/sentry.properties deleted file mode 100644 index d9303317cf..0000000000 --- a/desktop/sentry.properties +++ /dev/null @@ -1,3 +0,0 @@ -defaults.url=https://sentry.ente.io/ -defaults.org=ente -defaults.project=desktop-photos diff --git a/desktop/src/api/common.ts b/desktop/src/api/common.ts index 1c6281d489..f185069817 100644 --- a/desktop/src/api/common.ts +++ b/desktop/src/api/common.ts @@ -36,9 +36,4 @@ export const getPlatform = async (): Promise<"mac" | "windows" | "linux"> => { } }; -export { - getSentryUserID, - logToDisk, - openLogDirectory, - updateOptOutOfCrashReports, -} from "../services/logging"; +export { logToDisk, openLogDirectory } from "../services/logging"; diff --git a/desktop/src/api/electronStore.ts b/desktop/src/api/electronStore.ts index 9475134c69..5f84776e1a 100644 --- a/desktop/src/api/electronStore.ts +++ b/desktop/src/api/electronStore.ts @@ -2,7 +2,6 @@ import { logError } from "../services/logging"; import { keysStore } from "../stores/keys.store"; import { safeStorageStore } from "../stores/safeStorage.store"; import { uploadStatusStore } from "../stores/upload.store"; -import { userPreferencesStore } from "../stores/userPreferences.store"; import { watchStore } from "../stores/watch.store"; export const clearElectronStore = () => { @@ -11,7 +10,6 @@ export const clearElectronStore = () => { keysStore.clear(); safeStorageStore.clear(); watchStore.clear(); - userPreferencesStore.delete("optOutOfCrashReports"); } catch (e) { logError(e, "error while clearing electron store"); throw e; diff --git a/desktop/src/config/index.ts b/desktop/src/config/index.ts deleted file mode 100644 index a27de5aa24..0000000000 --- a/desktop/src/config/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -const PROD_HOST_URL: string = "ente://app"; -const RENDERER_OUTPUT_DIR: string = "./out"; -const LOG_FILENAME = "ente.log"; -const MAX_LOG_SIZE = 50 * 1024 * 1024; // 50MB - -const FILE_STREAM_CHUNK_SIZE: number = 4 * 1024 * 1024; - -const SENTRY_DSN = "https://759d8498487a81ac33a0c2efa2a42c4f@sentry.ente.io/9"; - -const RELEASE_VERSION = require("../../package.json").version; - -export { - PROD_HOST_URL, - RENDERER_OUTPUT_DIR, - FILE_STREAM_CHUNK_SIZE, - LOG_FILENAME, - MAX_LOG_SIZE, - SENTRY_DSN, - RELEASE_VERSION, -}; diff --git a/desktop/src/main.ts b/desktop/src/main.ts index 3663b7b8aa..c957930b30 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -1,7 +1,5 @@ import { app, BrowserWindow } from "electron"; import { initWatcher } from "./services/chokidar"; -import { initSentry } from "./services/sentry"; -import { getOptOutOfCrashReports } from "./services/userPreference"; import { isDev } from "./utils/common"; import { addAllowOriginHeader } from "./utils/cors"; import { createWindow } from "./utils/createWindow"; @@ -29,8 +27,6 @@ let appIsQuitting = false; let updateIsAvailable = false; -let optedOutOfCrashReports = false; - export const isAppQuitting = (): boolean => { return appIsQuitting; }; @@ -46,14 +42,6 @@ export const setIsUpdateAvailable = (value: boolean): void => { updateIsAvailable = value; }; -export const hasOptedOutOfCrashReports = (): boolean => { - return optedOutOfCrashReports; -}; - -export const updateOptOutOfCrashReports = (value: boolean): void => { - optedOutOfCrashReports = value; -}; - setupMainHotReload(); setupNextElectronServe(); @@ -83,11 +71,6 @@ if (!gotTheLock) { app.on("ready", async () => { logSystemInfo(); setupMainProcessStatsLogger(); - const hasOptedOutOfCrashReports = getOptOutOfCrashReports(); - updateOptOutOfCrashReports(hasOptedOutOfCrashReports); - if (!hasOptedOutOfCrashReports) { - initSentry(); - } mainWindow = await createWindow(); const tray = setupTrayItem(mainWindow); const watcher = initWatcher(mainWindow); diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index af4ef32227..b225e0d03f 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -8,12 +8,10 @@ import { computeImageEmbedding, computeTextEmbedding } from "./api/clip"; import { getAppVersion, getPlatform, - getSentryUserID, logToDisk, openDirectory, openLogDirectory, selectDirectory, - updateOptOutOfCrashReports, } from "./api/common"; import { clearElectronStore } from "./api/electronStore"; import { @@ -108,7 +106,6 @@ windowObject["ElectronAPIs"] = { registerUpdateEventListener, updateAndRestart, skipAppUpdate, - getSentryUserID, getAppVersion, runFFmpegCmd, muteUpdateNotification, @@ -120,7 +117,6 @@ windowObject["ElectronAPIs"] = { deleteFolder, rename, deleteFile, - updateOptOutOfCrashReports, computeImageEmbedding, computeTextEmbedding, getPlatform, diff --git a/desktop/src/services/fs.ts b/desktop/src/services/fs.ts index cbbe061467..5d1954211c 100644 --- a/desktop/src/services/fs.ts +++ b/desktop/src/services/fs.ts @@ -3,10 +3,11 @@ import StreamZip from "node-stream-zip"; import path from "path"; import * as fs from "promise-fs"; import { Readable } from "stream"; -import { FILE_STREAM_CHUNK_SIZE } from "../config"; import { ElectronFile } from "../types"; import { logError } from "./logging"; +const FILE_STREAM_CHUNK_SIZE: number = 4 * 1024 * 1024; + // https://stackoverflow.com/a/63111390 export const getDirFilePaths = async (dirPath: string) => { if (!(await fs.stat(dirPath)).isDirectory()) { diff --git a/desktop/src/services/logging.ts b/desktop/src/services/logging.ts index fa82492bcd..bcbacd9f56 100644 --- a/desktop/src/services/logging.ts +++ b/desktop/src/services/logging.ts @@ -12,11 +12,3 @@ export function openLogDirectory() { export function logError(error: Error, message: string, info?: string): void { ipcRenderer.invoke("log-error", error, message, info); } - -export function getSentryUserID(): Promise { - return ipcRenderer.invoke("get-sentry-id"); -} - -export function updateOptOutOfCrashReports(optOut: boolean) { - return ipcRenderer.invoke("update-opt-out-crash-reports", optOut); -} diff --git a/desktop/src/services/sentry.ts b/desktop/src/services/sentry.ts index 7adfcc255e..ae40b95b37 100644 --- a/desktop/src/services/sentry.ts +++ b/desktop/src/services/sentry.ts @@ -1,68 +1,18 @@ -import * as Sentry from "@sentry/electron/dist/main"; -import { RELEASE_VERSION, SENTRY_DSN } from "../config"; -import { hasOptedOutOfCrashReports } from "../main"; -import { keysStore } from "../stores/keys.store"; import { isDev } from "../utils/common"; -import { makeID } from "../utils/logging"; import { logToDisk } from "./logging"; -const ENV_DEVELOPMENT = "development"; - -const isDEVSentryENV = () => - process.env.NEXT_PUBLIC_SENTRY_ENV === ENV_DEVELOPMENT; - -export function initSentry(): void { - Sentry.init({ - dsn: SENTRY_DSN, - release: RELEASE_VERSION, - environment: isDev ? "development" : "production", - }); - Sentry.setUser({ id: getSentryUserID() }); -} - +/** Deprecated, but no alternative yet */ export function logErrorSentry( error: any, msg: string, info?: Record ) { - const err = errorWithContext(error, msg); logToDisk( `error: ${error?.name} ${error?.message} ${ error?.stack } msg: ${msg} info: ${JSON.stringify(info)}` ); - if (isDEVSentryENV()) { + if (isDev) { console.log(error, { msg, info }); } - if (hasOptedOutOfCrashReports()) { - return; - } - Sentry.captureException(err, { - level: Sentry.Severity.Info, - user: { id: getSentryUserID() }, - contexts: { - ...(info && { - info: info, - }), - rootCause: { message: error?.message }, - }, - }); -} - -function errorWithContext(originalError: Error, context: string) { - const errorWithContext = new Error(context); - errorWithContext.stack = - errorWithContext.stack.split("\n").slice(2, 4).join("\n") + - "\n" + - originalError.stack; - return errorWithContext; -} - -export function getSentryUserID() { - let anonymizeUserID = keysStore.get("AnonymizeUserID")?.id; - if (!anonymizeUserID) { - anonymizeUserID = makeID(6); - keysStore.set("AnonymizeUserID", { id: anonymizeUserID }); - } - return anonymizeUserID; } diff --git a/desktop/src/services/userPreference.ts b/desktop/src/services/userPreference.ts index 1c20e64da7..e3c6db2904 100644 --- a/desktop/src/services/userPreference.ts +++ b/desktop/src/services/userPreference.ts @@ -24,14 +24,6 @@ export function setMuteUpdateNotificationVersion(version: string) { userPreferencesStore.set("muteUpdateNotificationVersion", version); } -export function getOptOutOfCrashReports() { - return userPreferencesStore.get("optOutOfCrashReports") ?? false; -} - -export function setOptOutOfCrashReports(optOut: boolean) { - userPreferencesStore.set("optOutOfCrashReports", optOut); -} - export function clearSkipAppVersion() { userPreferencesStore.delete("skipAppVersion"); } diff --git a/desktop/src/stores/userPreferences.store.ts b/desktop/src/stores/userPreferences.store.ts index 546ca743e1..e6fec425ae 100644 --- a/desktop/src/stores/userPreferences.store.ts +++ b/desktop/src/stores/userPreferences.store.ts @@ -11,9 +11,6 @@ const userPreferencesSchema: Schema = { muteUpdateNotificationVersion: { type: "string", }, - optOutOfCrashReports: { - type: "boolean", - }, customCacheDirectory: { type: "string", }, diff --git a/desktop/src/types/index.ts b/desktop/src/types/index.ts index cd3ea8546b..208983826b 100644 --- a/desktop/src/types/index.ts +++ b/desktop/src/types/index.ts @@ -58,7 +58,6 @@ export interface UserPreferencesType { hideDockIcon: boolean; skipAppVersion: string; muteUpdateNotificationVersion: string; - optOutOfCrashReports: boolean; customCacheDirectory: string; } diff --git a/desktop/src/utils/ipcComms.ts b/desktop/src/utils/ipcComms.ts index 84b80fae1a..be41f72575 100644 --- a/desktop/src/utils/ipcComms.ts +++ b/desktop/src/utils/ipcComms.ts @@ -10,7 +10,6 @@ import { Tray, } from "electron"; import path from "path"; -import { updateOptOutOfCrashReports } from "../main"; import { getAppVersion, muteUpdateNotification, @@ -27,11 +26,10 @@ import { convertToJPEG, generateImageThumbnail, } from "../services/imageProcessor"; -import { getSentryUserID, logErrorSentry } from "../services/sentry"; +import { logErrorSentry } from "../services/sentry"; import { getCustomCacheDirectory, setCustomCacheDirectory, - setOptOutOfCrashReports, } from "../services/userPreference"; import { getPlatform } from "./common/platform"; import { createWindow } from "./createWindow"; @@ -146,9 +144,6 @@ export default function setupIpcComs( ipcMain.on("mute-update-notification", (_, version) => { muteUpdateNotification(version); }); - ipcMain.handle("get-sentry-id", () => { - return getSentryUserID(); - }); ipcMain.handle("get-app-version", () => { return getAppVersion(); @@ -179,10 +174,6 @@ export default function setupIpcComs( } ); - ipcMain.handle("update-opt-out-crash-reports", (_, optOut) => { - setOptOutOfCrashReports(optOut); - updateOptOutOfCrashReports(optOut); - }); ipcMain.handle("compute-image-embedding", (_, model, inputFilePath) => { return computeImageEmbedding(model, inputFilePath); }); diff --git a/desktop/src/utils/logging.ts b/desktop/src/utils/logging.ts index c843642f81..8a92006a87 100644 --- a/desktop/src/utils/logging.ts +++ b/desktop/src/utils/logging.ts @@ -1,9 +1,8 @@ import log from "electron-log"; -import { LOG_FILENAME, MAX_LOG_SIZE } from "../config"; export function setupLogging(isDev?: boolean) { - log.transports.file.fileName = LOG_FILENAME; - log.transports.file.maxSize = MAX_LOG_SIZE; + log.transports.file.fileName = "ente.log"; + log.transports.file.maxSize = 50 * 1024 * 1024; // 50MB; if (!isDev) { log.transports.console.level = false; } @@ -11,19 +10,6 @@ export function setupLogging(isDev?: boolean) { "[{y}-{m}-{d}T{h}:{i}:{s}{z}] [{level}]{scope} {text}"; } -export function makeID(length: number) { - let result = ""; - const characters = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - const charactersLength = characters.length; - for (let i = 0; i < length; i++) { - result += characters.charAt( - Math.floor(Math.random() * charactersLength) - ); - } - return result; -} - export function convertBytesToHumanReadable( bytes: number, precision = 2 diff --git a/desktop/src/utils/main.ts b/desktop/src/utils/main.ts index ebf466c038..8f850af79a 100644 --- a/desktop/src/utils/main.ts +++ b/desktop/src/utils/main.ts @@ -6,7 +6,6 @@ import os from "os"; import path from "path"; import { existsSync } from "promise-fs"; import util from "util"; -import { PROD_HOST_URL, RENDERER_OUTPUT_DIR } from "../config"; import { setupAutoUpdater } from "../services/appUpdater"; import autoLauncher from "../services/autoLauncher"; import { getHideDockIconPreference } from "../services/userPreference"; @@ -15,6 +14,9 @@ import { isPlatform } from "./common/platform"; import { buildContextMenu, buildMenuBar } from "./menu"; const execAsync = util.promisify(require("child_process").exec); +const PROD_HOST_URL: string = "ente://app"; +const RENDERER_OUTPUT_DIR: string = "./out"; + export async function handleUpdates(mainWindow: BrowserWindow) { const isInstalledViaBrew = await checkIfInstalledViaBrew(); if (!isDev && !isInstalledViaBrew) { diff --git a/desktop/yarn.lock b/desktop/yarn.lock index e5a7625d3f..740629dd3e 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -188,110 +188,6 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== -"@sentry/browser@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.7.1.tgz#e01144a08984a486ecc91d7922cc457e9c9bd6b7" - integrity sha512-R5PYx4TTvifcU790XkK6JVGwavKaXwycDU0MaAwfc4Vf7BLm5KCNJCsDySu1RPAap/017MVYf54p6dWvKiRviA== - dependencies: - "@sentry/core" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^1.9.3" - -"@sentry/cli@^1.68.0": - version "1.74.4" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.74.4.tgz#7df82f68045a155e1885bfcbb5d303e5259eb18e" - integrity sha512-BMfzYiedbModsNBJlKeBOLVYUtwSi99LJ8gxxE4Bp5N8hyjNIN0WVrozAVZ27mqzAuy6151Za3dpmOLO86YlGw== - dependencies: - https-proxy-agent "^5.0.0" - mkdirp "^0.5.5" - node-fetch "^2.6.7" - npmlog "^4.1.2" - progress "^2.0.3" - proxy-from-env "^1.1.0" - which "^2.0.2" - -"@sentry/core@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.7.1.tgz#c3aaa6415d06bec65ac446b13b84f073805633e3" - integrity sha512-VAv8OR/7INn2JfiLcuop4hfDcyC7mfL9fdPndQEhlacjmw8gRrgXjR7qyhnCTgzFLkHI7V5bcdIzA83TRPYQpA== - dependencies: - "@sentry/hub" "6.7.1" - "@sentry/minimal" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^1.9.3" - -"@sentry/electron@^2.5.1": - version "2.5.4" - resolved "https://registry.yarnpkg.com/@sentry/electron/-/electron-2.5.4.tgz#337b2f7e228e805a3e4eb3611c7b12c6cf87c618" - integrity sha512-tCCK+P581TmdjsDpHBQz7qYcldzGdUk1Fd6FPxPy1JKGzeY4uf/uSLKzR80Lzs5kTpEZFOwiMHSA8yjwFp5qoA== - dependencies: - "@sentry/browser" "6.7.1" - "@sentry/core" "6.7.1" - "@sentry/minimal" "6.7.1" - "@sentry/node" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^2.2.0" - -"@sentry/hub@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.7.1.tgz#d46d24deec67f0731a808ca16796e6765b371bc1" - integrity sha512-eVCTWvvcp6xa0A5GGNHMQEWslmKPlisE5rGmsV/kjvSUv3zSrI0eIDfb51ikdnCiBjHpK2NBWP8Vy8cZOEJegg== - dependencies: - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^1.9.3" - -"@sentry/minimal@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.7.1.tgz#babf85ee2f167e9dcf150d750d7a0b250c98449c" - integrity sha512-HDDPEnQRD6hC0qaHdqqKDStcdE1KhkFh0RCtJNMCDn0zpav8Dj9AteF70x6kLSlliAJ/JFwi6AmQrLz+FxPexw== - dependencies: - "@sentry/hub" "6.7.1" - "@sentry/types" "6.7.1" - tslib "^1.9.3" - -"@sentry/node@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-6.7.1.tgz#b09e2eca8e187168feba7bd865a23935bf0f5cc0" - integrity sha512-rtZo1O8ROv4lZwuljQz3iFZW89oXSlgXCG2VqkxQyRspPWu89abROpxLjYzsWwQ8djnur1XjFv51kOLDUTS6Qw== - dependencies: - "@sentry/core" "6.7.1" - "@sentry/hub" "6.7.1" - "@sentry/tracing" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - cookie "^0.4.1" - https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^1.9.3" - -"@sentry/tracing@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.7.1.tgz#b11f0c17a6c5dc14ef44733e5436afb686683268" - integrity sha512-wyS3nWNl5mzaC1qZ2AIp1hjXnfO9EERjMIJjCihs2LWBz1r3efxrHxJHs8wXlNWvrT3KLhq/7vvF5CdU82uPeQ== - dependencies: - "@sentry/hub" "6.7.1" - "@sentry/minimal" "6.7.1" - "@sentry/types" "6.7.1" - "@sentry/utils" "6.7.1" - tslib "^1.9.3" - -"@sentry/types@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.7.1.tgz#c8263e1886df5e815570c4668eb40a1cfaa1c88b" - integrity sha512-9AO7HKoip2MBMNQJEd6+AKtjj2+q9Ze4ooWUdEvdOVSt5drg7BGpK221/p9JEOyJAZwEPEXdcMd3VAIMiOb4MA== - -"@sentry/utils@6.7.1": - version "6.7.1" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.7.1.tgz#909184ad580f0f6375e1e4d4a6ffd33dfe64a4d1" - integrity sha512-Tq2otdbWlHAkctD+EWTYKkEx6BL1Qn3Z/imkO06/PvzpWvVhJWQ5qHAzz5XnwwqNHyV03KVzYB6znq1Bea9HuA== - dependencies: - "@sentry/types" "6.7.1" - tslib "^1.9.3" - "@sindresorhus/is@^4.0.0": version "4.6.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" @@ -662,19 +558,6 @@ applescript@^1.0.0: resolved "https://registry.yarnpkg.com/applescript/-/applescript-1.0.0.tgz#bb87af568cad034a4e48c4bdaf6067a3a2701317" integrity sha512-yvtNHdWvtbYEiIazXAdp/NY+BBb65/DAseqlNiJQjOx9DynuzOYDbVLBJvuc0ve0VL9x6B3OHF6eH52y9hCBtQ== -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.7" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" - integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1090,16 +973,6 @@ config-file-ts@^0.2.4: glob "^7.1.6" typescript "^4.0.2" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== - -cookie@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -1201,11 +1074,6 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== - detect-indent@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.1.tgz#cbb060a12842b9c4d333f1cac4aa4da1bb66bc25" @@ -1848,20 +1716,6 @@ gar@^1.0.4: resolved "https://registry.yarnpkg.com/gar/-/gar-1.0.4.tgz#f777bc7db425c0572fdeb52676172ca1ae9888b8" integrity sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg== - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -2033,11 +1887,6 @@ has-symbols@^1.0.3: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== - has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -2164,7 +2013,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@~2.0.1: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2249,11 +2098,6 @@ isarray@0.0.1: resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isbinaryfile@^4.0.8: version "4.0.10" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" @@ -2462,11 +2306,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lru_map@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== - matcher@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" @@ -2570,7 +2409,7 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mkdirp@^0.5.1, mkdirp@^0.5.5: +mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -2642,16 +2481,6 @@ normalize-url@^6.0.1: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== -npmlog@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - nugget@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.2.tgz#398b591377b740b3dd308fabecd5ea09cf3443da" @@ -2675,11 +2504,6 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== - object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -2883,11 +2707,6 @@ pretty-bytes@^4.0.2: resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9" integrity sha512-yJAF+AjbHKlxQ8eezMd/34Mnj/YTQ3i6kLzvVsH4l/BfIFtp444n0wVbnsn66JimZ9uBofv815aRp1zCppxlWw== -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - progress-stream@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77" @@ -2916,11 +2735,6 @@ promise-retry@^2.0.1: err-code "^2.0.2" retry "^0.12.0" -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -2995,19 +2809,6 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@^2.0.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - readable-stream@^3.0.2: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -3149,11 +2950,6 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -3207,11 +3003,6 @@ serialize-error@^7.0.1: dependencies: type-fest "^0.13.1" -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -3229,11 +3020,6 @@ shell-quote@^1.7.3: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== -signal-exit@^3.0.0: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - simple-update-notifier@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" @@ -3387,7 +3173,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -3408,14 +3194,7 @@ string_decoder@~0.10.x: resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: +strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== @@ -3587,12 +3366,12 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" -tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0, tslib@^2.2.0: +tslib@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== @@ -3695,7 +3474,7 @@ utf8-byte-length@^1.0.1: resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" integrity sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -3749,20 +3528,13 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -which@^2.0.1, which@^2.0.2: +which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" - integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== - dependencies: - string-width "^1.0.2 || 2 || 3 || 4" - winreg@1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.4.tgz#ba065629b7a925130e15779108cf540990e98d1b" From 206ad469508e9c3d88866623a0b7e47ab6ba773b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 13:57:48 +0530 Subject: [PATCH 213/391] Remove CRASH_REPORTING key --- web/apps/photos/public/locales/en-US/translation.json | 1 - web/packages/shared/electron/types.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/web/apps/photos/public/locales/en-US/translation.json b/web/apps/photos/public/locales/en-US/translation.json index 510471eaab..ea74f4f5ff 100644 --- a/web/apps/photos/public/locales/en-US/translation.json +++ b/web/apps/photos/public/locales/en-US/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Downloading {{name}}", "DOWNLOAD_FAILED": "Download failed", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", "CHRISTMAS": "Christmas", "CHRISTMAS_EVE": "Christmas Eve", "NEW_YEAR": "New Year", diff --git a/web/packages/shared/electron/types.ts b/web/packages/shared/electron/types.ts index 6b1bff4aae..34b8ee591b 100644 --- a/web/packages/shared/electron/types.ts +++ b/web/packages/shared/electron/types.ts @@ -100,7 +100,6 @@ export interface ElectronAPIsType { deleteFolder: (path: string) => Promise; deleteFile: (path: string) => void; rename: (oldPath: string, newPath: string) => Promise; - updateOptOutOfCrashReports: (optOut: boolean) => Promise; computeImageEmbedding: ( model: Model, imageData: Uint8Array, From 5d01931402a00459593b1ada88f6df8d9cd15e29 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 14:06:42 +0530 Subject: [PATCH 214/391] Retain -web suffix to allow disambiguating between main and renderer process --- web/packages/shared/logging/web.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/packages/shared/logging/web.ts b/web/packages/shared/logging/web.ts index 4fee25258f..2354067350 100644 --- a/web/packages/shared/logging/web.ts +++ b/web/packages/shared/logging/web.ts @@ -76,7 +76,7 @@ export const logStartupMessage = async (appId: string) => { const userID = (getData(LS_KEYS.USER) as User)?.id; const buildId = isDevBuild ? "dev" : `git ${process.env.GIT_SHA}`; - addLogLine(`ente-${appIdL} ${buildId} uid ${userID}`); + addLogLine(`ente-${appIdL}-web ${buildId} uid ${userID}`); }; function getLogs(): Log[] { From ee7d90e55ba8015315072823960a292286cfb53a Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 12 Mar 2024 08:38:32 +0000 Subject: [PATCH 215/391] New Crowdin translations by GitHub Action --- web/apps/photos/public/locales/bg-BG/translation.json | 1 - web/apps/photos/public/locales/de-DE/translation.json | 3 +-- web/apps/photos/public/locales/es-ES/translation.json | 1 - web/apps/photos/public/locales/fa-IR/translation.json | 1 - web/apps/photos/public/locales/fi-FI/translation.json | 1 - web/apps/photos/public/locales/fr-FR/translation.json | 1 - web/apps/photos/public/locales/it-IT/translation.json | 1 - web/apps/photos/public/locales/ko-KR/translation.json | 1 - web/apps/photos/public/locales/nl-NL/translation.json | 1 - web/apps/photos/public/locales/pt-BR/translation.json | 1 - web/apps/photos/public/locales/pt-PT/translation.json | 1 - web/apps/photos/public/locales/ru-RU/translation.json | 1 - web/apps/photos/public/locales/sv-SE/translation.json | 1 - web/apps/photos/public/locales/th-TH/translation.json | 1 - web/apps/photos/public/locales/tr-TR/translation.json | 1 - web/apps/photos/public/locales/zh-CN/translation.json | 1 - 16 files changed, 1 insertion(+), 17 deletions(-) diff --git a/web/apps/photos/public/locales/bg-BG/translation.json b/web/apps/photos/public/locales/bg-BG/translation.json index 6ca5bd9b00..6b02fae652 100644 --- a/web/apps/photos/public/locales/bg-BG/translation.json +++ b/web/apps/photos/public/locales/bg-BG/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/de-DE/translation.json b/web/apps/photos/public/locales/de-DE/translation.json index b90548d6fc..f5a6f13b3f 100644 --- a/web/apps/photos/public/locales/de-DE/translation.json +++ b/web/apps/photos/public/locales/de-DE/translation.json @@ -374,7 +374,7 @@ "PARTICIPANTS": "", "CHANGE_PERMISSIONS_TO_VIEWER": "", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", - "CONVERT_TO_VIEWER": "", + "CONVERT_TO_VIEWER": "Ja, zu \"Beobachter\" ändern", "CONVERT_TO_COLLABORATOR": "", "CHANGE_PERMISSION": "", "REMOVE_PARTICIPANT": "Entfernen?", @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/es-ES/translation.json b/web/apps/photos/public/locales/es-ES/translation.json index 839ad5b916..64c2849ebb 100644 --- a/web/apps/photos/public/locales/es-ES/translation.json +++ b/web/apps/photos/public/locales/es-ES/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/fa-IR/translation.json b/web/apps/photos/public/locales/fa-IR/translation.json index 29efad393d..68e1da3b97 100644 --- a/web/apps/photos/public/locales/fa-IR/translation.json +++ b/web/apps/photos/public/locales/fa-IR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/fi-FI/translation.json b/web/apps/photos/public/locales/fi-FI/translation.json index 89408ba557..fbc0b937a9 100644 --- a/web/apps/photos/public/locales/fi-FI/translation.json +++ b/web/apps/photos/public/locales/fi-FI/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/fr-FR/translation.json b/web/apps/photos/public/locales/fr-FR/translation.json index b53954188c..2d183c9eb2 100644 --- a/web/apps/photos/public/locales/fr-FR/translation.json +++ b/web/apps/photos/public/locales/fr-FR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Téléchargement de {{name}}", "DOWNLOAD_FAILED": "Échec du téléchargement", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} fichiers", - "CRASH_REPORTING": "Rapport de plantage", "CHRISTMAS": "Noël", "CHRISTMAS_EVE": "Réveillon de Noël", "NEW_YEAR": "Nouvel an", diff --git a/web/apps/photos/public/locales/it-IT/translation.json b/web/apps/photos/public/locales/it-IT/translation.json index a03c35f793..dd7afc1582 100644 --- a/web/apps/photos/public/locales/it-IT/translation.json +++ b/web/apps/photos/public/locales/it-IT/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/ko-KR/translation.json b/web/apps/photos/public/locales/ko-KR/translation.json index 24ac00c128..754fef8928 100644 --- a/web/apps/photos/public/locales/ko-KR/translation.json +++ b/web/apps/photos/public/locales/ko-KR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/nl-NL/translation.json b/web/apps/photos/public/locales/nl-NL/translation.json index 10374c7e0c..2b2aa11115 100644 --- a/web/apps/photos/public/locales/nl-NL/translation.json +++ b/web/apps/photos/public/locales/nl-NL/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "{{name}} downloaden", "DOWNLOAD_FAILED": "Download mislukt", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} bestanden", - "CRASH_REPORTING": "Foutenrapportering", "CHRISTMAS": "Kerst", "CHRISTMAS_EVE": "Kerstavond", "NEW_YEAR": "Nieuwjaar", diff --git a/web/apps/photos/public/locales/pt-BR/translation.json b/web/apps/photos/public/locales/pt-BR/translation.json index 99ffb2b4ac..4eaa398c4e 100644 --- a/web/apps/photos/public/locales/pt-BR/translation.json +++ b/web/apps/photos/public/locales/pt-BR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Transferindo {{name}}", "DOWNLOAD_FAILED": "Falha ao baixar", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} arquivos", - "CRASH_REPORTING": "Relatório de falhas", "CHRISTMAS": "Natal", "CHRISTMAS_EVE": "Véspera de Natal", "NEW_YEAR": "Ano Novo", diff --git a/web/apps/photos/public/locales/pt-PT/translation.json b/web/apps/photos/public/locales/pt-PT/translation.json index 8332af46a2..ac7d179688 100644 --- a/web/apps/photos/public/locales/pt-PT/translation.json +++ b/web/apps/photos/public/locales/pt-PT/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/ru-RU/translation.json b/web/apps/photos/public/locales/ru-RU/translation.json index c578832f52..0e97155633 100644 --- a/web/apps/photos/public/locales/ru-RU/translation.json +++ b/web/apps/photos/public/locales/ru-RU/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Загрузка {{name}}", "DOWNLOAD_FAILED": "Загрузка не удалась", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} файлов", - "CRASH_REPORTING": "Отчеты об ошибках", "CHRISTMAS": "Рождество", "CHRISTMAS_EVE": "Канун Рождества", "NEW_YEAR": "Новый год", diff --git a/web/apps/photos/public/locales/sv-SE/translation.json b/web/apps/photos/public/locales/sv-SE/translation.json index 49636cc35c..550780b444 100644 --- a/web/apps/photos/public/locales/sv-SE/translation.json +++ b/web/apps/photos/public/locales/sv-SE/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/th-TH/translation.json b/web/apps/photos/public/locales/th-TH/translation.json index 89408ba557..fbc0b937a9 100644 --- a/web/apps/photos/public/locales/th-TH/translation.json +++ b/web/apps/photos/public/locales/th-TH/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/tr-TR/translation.json b/web/apps/photos/public/locales/tr-TR/translation.json index 89408ba557..fbc0b937a9 100644 --- a/web/apps/photos/public/locales/tr-TR/translation.json +++ b/web/apps/photos/public/locales/tr-TR/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", diff --git a/web/apps/photos/public/locales/zh-CN/translation.json b/web/apps/photos/public/locales/zh-CN/translation.json index 0be918442a..6e513f24b9 100644 --- a/web/apps/photos/public/locales/zh-CN/translation.json +++ b/web/apps/photos/public/locales/zh-CN/translation.json @@ -588,7 +588,6 @@ "DOWNLOADING_COLLECTION": "正在下载 {{name}}", "DOWNLOAD_FAILED": "下载失败", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} 个文件", - "CRASH_REPORTING": "崩溃报告", "CHRISTMAS": "圣诞", "CHRISTMAS_EVE": "平安夜", "NEW_YEAR": "新年", From b15901df679ace69a0bde7c18dc0ef7a4c079ca1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 14:14:18 +0530 Subject: [PATCH 216/391] [workflows] Prevent duplicate runs of lint workflows after merging a PR --- .github/workflows/auth-lint.yml | 6 ++---- .github/workflows/mobile-lint.yml | 6 ++---- .github/workflows/server-lint.yml | 6 ++---- .github/workflows/web-lint.yml | 15 ++------------- 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/.github/workflows/auth-lint.yml b/.github/workflows/auth-lint.yml index fff7fb75f5..1b45a2d324 100644 --- a/.github/workflows/auth-lint.yml +++ b/.github/workflows/auth-lint.yml @@ -1,11 +1,9 @@ name: "Lint (auth)" on: - # Run on every push to branches (this also covers pull requests) + # Run on every push to a branch other than main that changes auth/ push: - # See: [Note: Specify branch when specifying a path filter] - branches: ["**"] - # Only run if something changes in these paths + branches-ignore: [main] paths: - "auth/**" - ".github/workflows/auth-lint.yml" diff --git a/.github/workflows/mobile-lint.yml b/.github/workflows/mobile-lint.yml index c2e54d38ae..7b5e5fbedb 100644 --- a/.github/workflows/mobile-lint.yml +++ b/.github/workflows/mobile-lint.yml @@ -1,11 +1,9 @@ name: "Lint (mobile)" on: - # Run on every push (this also covers pull requests) + # Run on every push to a branch other than main that changes mobile/ push: - # See: [Note: Specify branch when specifying a path filter] - branches: ["**"] - # Only run if something changes in these paths + branches-ignore: [main] paths: - "mobile/**" - ".github/workflows/mobile-lint.yml" diff --git a/.github/workflows/server-lint.yml b/.github/workflows/server-lint.yml index e23036a6ed..c051d02901 100644 --- a/.github/workflows/server-lint.yml +++ b/.github/workflows/server-lint.yml @@ -1,11 +1,9 @@ name: "Lint (server)" on: - # Run on every push (this also covers pull requests) + # Run on every push to a branch other than main that changes server/ push: - # See: [Note: Specify branch when specifying a path filter] - branches: ["**"] - # Only run if something changes in these paths + branches-ignore: [main] paths: - "server/**" - ".github/workflows/server-lint.yml" diff --git a/.github/workflows/web-lint.yml b/.github/workflows/web-lint.yml index a905069f67..7f5d270029 100644 --- a/.github/workflows/web-lint.yml +++ b/.github/workflows/web-lint.yml @@ -1,20 +1,9 @@ name: "Lint (web)" on: - # Run on every push (this also covers pull requests) + # Run on every push to a branch other than main that changes web/ push: - # [Note: Specify branch when specifying a path filter] - # - # Path filters are ignored for tag pushes, which causes this workflow to - # always run when we push a tag. Defining an explicit branch solves the - # issue. From GitHub's docs: - # - # > if you define both branches/branches-ignore and paths/paths-ignore, - # > the workflow will only run when both filters are satisfied. - # - # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions - branches: ["**"] - # Only run if something changes in these paths + branches-ignore: [main] paths: - "web/**" - ".github/workflows/web-lint.yml" From e219197e2fd39b4db0904d61a140616b106f92ab Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 15:07:06 +0530 Subject: [PATCH 217/391] Fix import --- desktop/src/utils/createWindow.ts | 2 +- desktop/src/utils/main.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/desktop/src/utils/createWindow.ts b/desktop/src/utils/createWindow.ts index b9e6a5b471..29fc785d23 100644 --- a/desktop/src/utils/createWindow.ts +++ b/desktop/src/utils/createWindow.ts @@ -1,13 +1,13 @@ import { app, BrowserWindow, nativeImage } from "electron"; import ElectronLog from "electron-log"; import * as path from "path"; -import { PROD_HOST_URL } from "../config"; import { isAppQuitting } from "../main"; import autoLauncher from "../services/autoLauncher"; import { logErrorSentry } from "../services/sentry"; import { getHideDockIconPreference } from "../services/userPreference"; import { isDev } from "./common"; import { isPlatform } from "./common/platform"; +import { PROD_HOST_URL } from "./main"; export async function createWindow(): Promise { const appImgPath = isDev diff --git a/desktop/src/utils/main.ts b/desktop/src/utils/main.ts index 8f850af79a..21bb3b9e7b 100644 --- a/desktop/src/utils/main.ts +++ b/desktop/src/utils/main.ts @@ -14,7 +14,7 @@ import { isPlatform } from "./common/platform"; import { buildContextMenu, buildMenuBar } from "./menu"; const execAsync = util.promisify(require("child_process").exec); -const PROD_HOST_URL: string = "ente://app"; +export const PROD_HOST_URL: string = "ente://app"; const RENDERER_OUTPUT_DIR: string = "./out"; export async function handleUpdates(mainWindow: BrowserWindow) { From d7cd2cecbc820e949ec5865f27bd63b3657dc3d4 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 15:32:57 +0530 Subject: [PATCH 218/391] Default buildResources is build --- desktop/.gitignore | 9 ++--- .../entitlements.mac.plist | 0 desktop/{resources => build}/error.html | 0 desktop/{resources => build}/ggmlclip-linux | Bin desktop/{resources => build}/ggmlclip-mac | Bin .../{resources => build}/ggmlclip-windows.exe | Bin desktop/{resources => build}/icon.icns | Bin desktop/{resources => build}/icon.png | Bin desktop/{resources => build}/image-magick | Bin desktop/{resources => build}/msvcp140d.dll | Bin desktop/{resources => build}/splash.html | 0 .../taskbar-icon-Template.png | Bin .../taskbar-icon-Template@2x.png | Bin .../taskbar-icon-Template@3x.png | Bin desktop/{resources => build}/taskbar-icon.png | Bin .../{resources => build}/taskbar-icon@2x.png | Bin .../{resources => build}/taskbar-icon@3x.png | Bin desktop/{resources => build}/ucrtbased.dll | Bin .../{resources => build}/vcruntime140_1d.dll | Bin .../{resources => build}/vcruntime140d.dll | Bin desktop/{resources => build}/version.html | 0 desktop/{resources => build}/window-icon.png | Bin desktop/package.json | 32 ++++++++---------- desktop/tsconfig.json | 4 +-- 24 files changed, 21 insertions(+), 24 deletions(-) rename desktop/{resources => build}/entitlements.mac.plist (100%) rename desktop/{resources => build}/error.html (100%) rename desktop/{resources => build}/ggmlclip-linux (100%) rename desktop/{resources => build}/ggmlclip-mac (100%) rename desktop/{resources => build}/ggmlclip-windows.exe (100%) rename desktop/{resources => build}/icon.icns (100%) rename desktop/{resources => build}/icon.png (100%) rename desktop/{resources => build}/image-magick (100%) rename desktop/{resources => build}/msvcp140d.dll (100%) rename desktop/{resources => build}/splash.html (100%) rename desktop/{resources => build}/taskbar-icon-Template.png (100%) rename desktop/{resources => build}/taskbar-icon-Template@2x.png (100%) rename desktop/{resources => build}/taskbar-icon-Template@3x.png (100%) rename desktop/{resources => build}/taskbar-icon.png (100%) rename desktop/{resources => build}/taskbar-icon@2x.png (100%) rename desktop/{resources => build}/taskbar-icon@3x.png (100%) rename desktop/{resources => build}/ucrtbased.dll (100%) rename desktop/{resources => build}/vcruntime140_1d.dll (100%) rename desktop/{resources => build}/vcruntime140d.dll (100%) rename desktop/{resources => build}/version.html (100%) rename desktop/{resources => build}/window-icon.png (100%) diff --git a/desktop/.gitignore b/desktop/.gitignore index b01288f0a9..9b7e0cc608 100644 --- a/desktop/.gitignore +++ b/desktop/.gitignore @@ -11,10 +11,11 @@ node_modules/ .env .env.*.local -# Generated code during build -# - tsc transpiles src/**/*.ts and emits the generated JS into build/app -# - The out dir from the photos web app is symlinked to build/out -build/ +# tsc transpiles src/**/*.ts and emits the generated JS into app +app/ + +# out is a symlink to the photos web app's dir +out # electron-builder dist/ diff --git a/desktop/resources/entitlements.mac.plist b/desktop/build/entitlements.mac.plist similarity index 100% rename from desktop/resources/entitlements.mac.plist rename to desktop/build/entitlements.mac.plist diff --git a/desktop/resources/error.html b/desktop/build/error.html similarity index 100% rename from desktop/resources/error.html rename to desktop/build/error.html diff --git a/desktop/resources/ggmlclip-linux b/desktop/build/ggmlclip-linux similarity index 100% rename from desktop/resources/ggmlclip-linux rename to desktop/build/ggmlclip-linux diff --git a/desktop/resources/ggmlclip-mac b/desktop/build/ggmlclip-mac similarity index 100% rename from desktop/resources/ggmlclip-mac rename to desktop/build/ggmlclip-mac diff --git a/desktop/resources/ggmlclip-windows.exe b/desktop/build/ggmlclip-windows.exe similarity index 100% rename from desktop/resources/ggmlclip-windows.exe rename to desktop/build/ggmlclip-windows.exe diff --git a/desktop/resources/icon.icns b/desktop/build/icon.icns similarity index 100% rename from desktop/resources/icon.icns rename to desktop/build/icon.icns diff --git a/desktop/resources/icon.png b/desktop/build/icon.png similarity index 100% rename from desktop/resources/icon.png rename to desktop/build/icon.png diff --git a/desktop/resources/image-magick b/desktop/build/image-magick similarity index 100% rename from desktop/resources/image-magick rename to desktop/build/image-magick diff --git a/desktop/resources/msvcp140d.dll b/desktop/build/msvcp140d.dll similarity index 100% rename from desktop/resources/msvcp140d.dll rename to desktop/build/msvcp140d.dll diff --git a/desktop/resources/splash.html b/desktop/build/splash.html similarity index 100% rename from desktop/resources/splash.html rename to desktop/build/splash.html diff --git a/desktop/resources/taskbar-icon-Template.png b/desktop/build/taskbar-icon-Template.png similarity index 100% rename from desktop/resources/taskbar-icon-Template.png rename to desktop/build/taskbar-icon-Template.png diff --git a/desktop/resources/taskbar-icon-Template@2x.png b/desktop/build/taskbar-icon-Template@2x.png similarity index 100% rename from desktop/resources/taskbar-icon-Template@2x.png rename to desktop/build/taskbar-icon-Template@2x.png diff --git a/desktop/resources/taskbar-icon-Template@3x.png b/desktop/build/taskbar-icon-Template@3x.png similarity index 100% rename from desktop/resources/taskbar-icon-Template@3x.png rename to desktop/build/taskbar-icon-Template@3x.png diff --git a/desktop/resources/taskbar-icon.png b/desktop/build/taskbar-icon.png similarity index 100% rename from desktop/resources/taskbar-icon.png rename to desktop/build/taskbar-icon.png diff --git a/desktop/resources/taskbar-icon@2x.png b/desktop/build/taskbar-icon@2x.png similarity index 100% rename from desktop/resources/taskbar-icon@2x.png rename to desktop/build/taskbar-icon@2x.png diff --git a/desktop/resources/taskbar-icon@3x.png b/desktop/build/taskbar-icon@3x.png similarity index 100% rename from desktop/resources/taskbar-icon@3x.png rename to desktop/build/taskbar-icon@3x.png diff --git a/desktop/resources/ucrtbased.dll b/desktop/build/ucrtbased.dll similarity index 100% rename from desktop/resources/ucrtbased.dll rename to desktop/build/ucrtbased.dll diff --git a/desktop/resources/vcruntime140_1d.dll b/desktop/build/vcruntime140_1d.dll similarity index 100% rename from desktop/resources/vcruntime140_1d.dll rename to desktop/build/vcruntime140_1d.dll diff --git a/desktop/resources/vcruntime140d.dll b/desktop/build/vcruntime140d.dll similarity index 100% rename from desktop/resources/vcruntime140d.dll rename to desktop/build/vcruntime140d.dll diff --git a/desktop/resources/version.html b/desktop/build/version.html similarity index 100% rename from desktop/resources/version.html rename to desktop/build/version.html diff --git a/desktop/resources/window-icon.png b/desktop/build/window-icon.png similarity index 100% rename from desktop/resources/window-icon.png rename to desktop/build/window-icon.png diff --git a/desktop/package.json b/desktop/package.json index fe0b9b8ffe..b3db86f735 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -4,14 +4,16 @@ "private": true, "description": "Desktop client for Ente Photos", "author": "Ente ", - "main": "build/app/main.js", + "main": "app/main.js", "scripts": { - "build": "mkdir -p build && yarn build-renderer && yarn build-main", - "build-main": "tsc && electron-builder --config.compression=store", - "build-renderer": "cd ../web && yarn install && yarn build:photos && cd ../desktop/build && rm -f out && ln -sf ../../web/apps/photos/out", + "build": "yarn build-renderer && yarn build-main", + "build-local": "yarn build-renderer && yarn build-main-local", + "build-main": "tsc && electron-builder", + "build-main-local": "tsc && electron-builder --config.compression=store", + "build-renderer": "cd ../web && yarn install && yarn build:photos && cd ../desktop && rm -f out && ln -sf ../web/apps/photos/out", "dev": "concurrently \"yarn dev-main\" \"yarn dev-renderer\"", "dev-main": "tsc && electron build/app/main.js", - "dev-renderer": "cd ../web && yarn install && yarn dev:photos && cd ../desktop/build && rm -f out && ln -sf ../../web/apps/photos/out", + "dev-renderer": "cd ../web && yarn install && yarn dev:photos", "postinstall": "electron-builder install-app-deps", "lint": "yarn prettier --check . && eslint \"src/**/*.ts\"", "lint-fix": "yarn prettier --write . && eslint --fix .", @@ -110,26 +112,20 @@ "x64ArchFiles": "Contents/Resources/ggmlclip-mac" }, "afterSign": "electron-builder-notarize", - "extraFiles": [ - { - "from": "resources", - "to": "resources", - "filter": [ - "**/*" - ] - } - ], "asarUnpack": [ "node_modules/ffmpeg-static/bin/${os}/${arch}/ffmpeg", "node_modules/ffmpeg-static/index.js", "node_modules/ffmpeg-static/package.json" ], - "files": [ - "build/app/**/*", + "extraFiles": [ { - "from": "build/out", - "to": "out" + "from": "build", + "to": "resources" } + ], + "files": [ + "app/**/*", + "out" ] }, "productName": "ente", diff --git a/desktop/tsconfig.json b/desktop/tsconfig.json index 1efdc3d01a..142c36005c 100644 --- a/desktop/tsconfig.json +++ b/desktop/tsconfig.json @@ -3,8 +3,8 @@ "target": "es2021", "module": "commonjs", "esModuleInterop": true, - /* Emit the generated JS into build/app */ - "outDir": "build/app", + /* Emit the generated JS into app */ + "outDir": "app", "noImplicitAny": true, "sourceMap": true, "baseUrl": "src", From c8b9b4cd8f871e8da3943354c784a0c9c98e65ec Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 16:31:16 +0530 Subject: [PATCH 219/391] Document better --- desktop/README.md | 34 +++++++++++++++++++--------------- desktop/docs/dev.md | 4 ++++ desktop/package.json | 4 ++-- desktop/src/utils/main.ts | 4 ++++ 4 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 desktop/docs/dev.md diff --git a/desktop/README.md b/desktop/README.md index 9d637de04f..e947e2a70a 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -10,12 +10,6 @@ To know more about Ente, see [our main README](../README.md) or visit ## Building from source -> [!CAUTION] -> -> We moved a few things around when switching to a monorepo recently, and the -> desktop app is not currently building with these instructions below. Hang -> tight, we're on it, and will fix soon. - Fetch submodules ```sh @@ -28,22 +22,32 @@ Install dependencies yarn install ``` -Run the app +Create a binary for your platform ```sh -yarn dev +yarn build ``` -To recompile automatically using electron-reload, run this in a separate -terminal: +## Developing -```bash -yarn watch +Instead of building, you can run the app in development mode + +```sh +yarn dev ``` -`yarn dev` is handy during development, but if you wish, you can also create a -binary for your platform by using +> [!CAUTION] +> +> `yarn dev` is currently not working (we'll fix soon). If you just want to +> build from source and use the generated binary, use `yarn build` as described +> above. + +This'll launch a development server to serve the pages loaded by the renderer +process, and will hot reload on changes. + +If you also want hot reload for the main process, run this in a separate +terminal: ```sh -yarn build +yarn watch ``` diff --git a/desktop/docs/dev.md b/desktop/docs/dev.md new file mode 100644 index 0000000000..4575188fd4 --- /dev/null +++ b/desktop/docs/dev.md @@ -0,0 +1,4 @@ +# Development tips + +* `yarn build:quick` is a variant of `yarn build` that uses the + `--config.compression=store` flag to (slightly) speed up electron-builder. diff --git a/desktop/package.json b/desktop/package.json index b3db86f735..a835b81c6c 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -7,10 +7,10 @@ "main": "app/main.js", "scripts": { "build": "yarn build-renderer && yarn build-main", - "build-local": "yarn build-renderer && yarn build-main-local", "build-main": "tsc && electron-builder", - "build-main-local": "tsc && electron-builder --config.compression=store", + "build-main:quick": "tsc && electron-builder --config.compression=store", "build-renderer": "cd ../web && yarn install && yarn build:photos && cd ../desktop && rm -f out && ln -sf ../web/apps/photos/out", + "build:quick": "yarn build-renderer && yarn build-main:quick", "dev": "concurrently \"yarn dev-main\" \"yarn dev-renderer\"", "dev-main": "tsc && electron build/app/main.js", "dev-renderer": "cd ../web && yarn install && yarn dev:photos", diff --git a/desktop/src/utils/main.ts b/desktop/src/utils/main.ts index 21bb3b9e7b..417e5cc483 100644 --- a/desktop/src/utils/main.ts +++ b/desktop/src/utils/main.ts @@ -79,6 +79,10 @@ export async function setupMainMenu(mainWindow: BrowserWindow) { } export function setupMainHotReload() { + // Hot reload the main process if anything changes in the source directory + // that we're running from. In particular, this gets triggered when `yarn + // watch` rebuilds JS files in the `app/` directory when we change the TS + // files in the `src/` directory. if (isDev) { electronReload(__dirname, {}); } From dff0af3397015c27259ec1382039a6d726a216cf Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 16:47:41 +0530 Subject: [PATCH 220/391] Fix path to main process entrypoint --- desktop/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop/package.json b/desktop/package.json index a835b81c6c..a93ee782aa 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -12,7 +12,7 @@ "build-renderer": "cd ../web && yarn install && yarn build:photos && cd ../desktop && rm -f out && ln -sf ../web/apps/photos/out", "build:quick": "yarn build-renderer && yarn build-main:quick", "dev": "concurrently \"yarn dev-main\" \"yarn dev-renderer\"", - "dev-main": "tsc && electron build/app/main.js", + "dev-main": "tsc && electron app/main.js", "dev-renderer": "cd ../web && yarn install && yarn dev:photos", "postinstall": "electron-builder install-app-deps", "lint": "yarn prettier --check . && eslint \"src/**/*.ts\"", From cde87716a165fabae13e6b64d0ac33b8f12a63ea Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 17:02:28 +0530 Subject: [PATCH 221/391] Remove the custom next-electron-server The only change this has in addition to next-electron-server seems to be https://github.com/ente-io/next-electron-server/pull/1/files, will try to test along the way to determine its impact. --- .gitmodules | 4 ---- desktop/thirdparty/next-electron-server | 1 - 2 files changed, 5 deletions(-) delete mode 160000 desktop/thirdparty/next-electron-server diff --git a/.gitmodules b/.gitmodules index a3a52e7be5..36834f2cd2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,10 +9,6 @@ [submodule "auth/assets/simple-icons"] path = auth/assets/simple-icons url = https://github.com/simple-icons/simple-icons.git -[submodule "desktop/thirdparty/next-electron-server"] - path = desktop/thirdparty/next-electron-server - url = https://github.com/ente-io/next-electron-server.git - branch = desktop [submodule "mobile/thirdparty/flutter"] path = mobile/thirdparty/flutter url = https://github.com/flutter/flutter.git diff --git a/desktop/thirdparty/next-electron-server b/desktop/thirdparty/next-electron-server deleted file mode 160000 index a88030295c..0000000000 --- a/desktop/thirdparty/next-electron-server +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a88030295c89dd8f43d9e3a45025678d95c78a45 From 685e75d97d967a99b51679828fe7b108f69bf325 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 17:38:39 +0530 Subject: [PATCH 222/391] Switch to upstream --- desktop/.prettierignore | 1 - desktop/docs/dependencies.md | 8 +++++++ desktop/package.json | 4 ++-- desktop/src/main.ts | 37 +++++++++++++++++++++++++++---- desktop/src/preload.ts | 2 -- desktop/src/utils/main.ts | 43 +++++++++--------------------------- desktop/src/utils/preload.ts | 16 -------------- desktop/yarn.lock | 14 +++++++----- 8 files changed, 62 insertions(+), 63 deletions(-) delete mode 100644 desktop/.prettierignore delete mode 100644 desktop/src/utils/preload.ts diff --git a/desktop/.prettierignore b/desktop/.prettierignore deleted file mode 100644 index c2ed1358c4..0000000000 --- a/desktop/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -thirdparty/ diff --git a/desktop/docs/dependencies.md b/desktop/docs/dependencies.md index 8703331a22..6b01967234 100644 --- a/desktop/docs/dependencies.md +++ b/desktop/docs/dependencies.md @@ -4,3 +4,11 @@ See [web/docs/dependencies.md](../../web/docs/dependencies.md) for general web specific dependencies. See [electron.md](electron.md) for our main dependency, Electron. The rest of this document describes the remaining, desktop specific dependencies that are used by the Photos desktop app. + +## Electron related + +### next-electron-server + +This spins up a server for serving files using a protocol handler inside our +Electron process. This allows us to directly use the output produced by `next +build` for loading into our renderer process. diff --git a/desktop/package.json b/desktop/package.json index a93ee782aa..aa0c92a21b 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -32,7 +32,7 @@ "get-folder-size": "^2.0.1", "html-entities": "^2.4.0", "jpeg-js": "^0.4.4", - "next-electron-server": "file:./thirdparty/next-electron-server", + "next-electron-server": "^1", "node-fetch": "^2.6.7", "node-stream-zip": "^1.15.0", "onnxruntime-node": "^1.16.3", @@ -55,7 +55,7 @@ "eslint": "^7.23.0", "eslint-config-google": "^0.14.0", "eslint-config-prettier": "^8.5.0", - "prettier": "2.5.1", + "prettier": "^3", "prettier-plugin-organize-imports": "^3.2", "prettier-plugin-packagejson": "^2.4", "typescript": "^4.2.3" diff --git a/desktop/src/main.ts b/desktop/src/main.ts index c957930b30..b42f40cead 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -1,4 +1,6 @@ import { app, BrowserWindow } from "electron"; +import electronReload from "electron-reload"; +import serveNextAt from "next-electron-server"; import { initWatcher } from "./services/chokidar"; import { isDev } from "./utils/common"; import { addAllowOriginHeader } from "./utils/cors"; @@ -14,9 +16,7 @@ import { handleUpdates, logSystemInfo, setupMacWindowOnDockIconClick, - setupMainHotReload, setupMainMenu, - setupNextElectronServe, setupTrayItem, } from "./utils/main"; import { setupMainProcessStatsLogger } from "./utils/processStats"; @@ -38,14 +38,43 @@ export const setIsAppQuitting = (value: boolean): void => { export const isUpdateAvailable = (): boolean => { return updateIsAvailable; }; + export const setIsUpdateAvailable = (value: boolean): void => { updateIsAvailable = value; }; -setupMainHotReload(); +/** + * Hot reload the main process if anything changes in the source directory that + * we're running from. + * + * In particular, this gets triggered when the `tsc -w` rebuilds JS files in the + * `app/` directory when we change the TS files in the `src/` directory. + */ +const setupMainHotReload = () => { + if (isDev) { + electronReload(__dirname, {}); + } +}; -setupNextElectronServe(); +/** + * next-electron-server allows up to directly use the output of `next build` in + * production mode and `next dev` in development mode, whilst keeping the rest + * of our code the same. + * + * It uses protocol handlers to serve files from the "next://app" protocol + * + * - In development this is proxied to http://localhost:3000 + * - In production it serves files from the `/out` directory + * + * For more details, see this comparison: + * https://github.com/HaNdTriX/next-electron-server/issues/5 + */ +const setupRendererServer = () => { + serveNextAt("next://app"); +}; +setupMainHotReload(); +setupRendererServer(); setupLogging(isDev); const gotTheLock = app.requestSingleInstanceLock(); diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index b225e0d03f..a602e76bbd 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -59,13 +59,11 @@ import { updateWatchMappingSyncedFiles, } from "./api/watch"; import { setupLogging } from "./utils/logging"; -import { fixHotReloadNext12 } from "./utils/preload"; import { logRendererProcessMemoryUsage, setupRendererProcessStatsLogger, } from "./utils/processStats"; -fixHotReloadNext12(); setupLogging(); setupRendererProcessStatsLogger(); diff --git a/desktop/src/utils/main.ts b/desktop/src/utils/main.ts index 417e5cc483..55ccaff809 100644 --- a/desktop/src/utils/main.ts +++ b/desktop/src/utils/main.ts @@ -1,7 +1,5 @@ import { app, BrowserWindow, Menu, nativeImage, Tray } from "electron"; import ElectronLog from "electron-log"; -import electronReload from "electron-reload"; -import serveNextAt from "next-electron-server"; import os from "os"; import path from "path"; import { existsSync } from "promise-fs"; @@ -14,9 +12,6 @@ import { isPlatform } from "./common/platform"; import { buildContextMenu, buildMenuBar } from "./menu"; const execAsync = util.promisify(require("child_process").exec); -export const PROD_HOST_URL: string = "ente://app"; -const RENDERER_OUTPUT_DIR: string = "./out"; - export async function handleUpdates(mainWindow: BrowserWindow) { const isInstalledViaBrew = await checkIfInstalledViaBrew(); if (!isDev && !isInstalledViaBrew) { @@ -46,6 +41,17 @@ export function handleDownloads(mainWindow: BrowserWindow) { }); } +export function handleExternalLinks(mainWindow: BrowserWindow) { + mainWindow.webContents.setWindowOpenHandler(({ url }) => { + if (!url.startsWith("next://app")) { + require("electron").shell.openExternal(url); + return { action: "deny" }; + } else { + return { action: "allow" }; + } + }); +} + export function getUniqueSavePath(filename: string, directory: string): string { let uniqueFileSavePath = path.join(directory, filename); const { name: filenameWithoutExtension, ext: extension } = @@ -78,22 +84,6 @@ export async function setupMainMenu(mainWindow: BrowserWindow) { Menu.setApplicationMenu(await buildMenuBar(mainWindow)); } -export function setupMainHotReload() { - // Hot reload the main process if anything changes in the source directory - // that we're running from. In particular, this gets triggered when `yarn - // watch` rebuilds JS files in the `app/` directory when we change the TS - // files in the `src/` directory. - if (isDev) { - electronReload(__dirname, {}); - } -} - -export function setupNextElectronServe() { - serveNextAt(PROD_HOST_URL, { - outputDir: RENDERER_OUTPUT_DIR, - }); -} - export async function handleDockIconHideOnAutoLaunch() { const shouldHideDockIcon = getHideDockIconPreference(); const wasAutoLaunched = await autoLauncher.wasAutoLaunched(); @@ -116,17 +106,6 @@ export function logSystemInfo() { ElectronLog.info({ appVersion }); } -export function handleExternalLinks(mainWindow: BrowserWindow) { - mainWindow.webContents.setWindowOpenHandler(({ url }) => { - if (!url.startsWith(PROD_HOST_URL)) { - require("electron").shell.openExternal(url); - return { action: "deny" }; - } else { - return { action: "allow" }; - } - }); -} - export async function checkIfInstalledViaBrew() { if (!isPlatform("mac")) { return false; diff --git a/desktop/src/utils/preload.ts b/desktop/src/utils/preload.ts deleted file mode 100644 index 8b36f8c3f8..0000000000 --- a/desktop/src/utils/preload.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { webFrame } from "electron"; - -export const fixHotReloadNext12 = () => { - webFrame.executeJavaScript(`Object.defineProperty(globalThis, 'WebSocket', { - value: new Proxy(WebSocket, { - construct: (Target, [url, protocols]) => { - if (url.endsWith('/_next/webpack-hmr')) { - // Fix the Next.js hmr client url - return new Target("ws://localhost:3000/_next/webpack-hmr", protocols) - } else { - return new Target(url, protocols) - } - } - }) - });`); -}; diff --git a/desktop/yarn.lock b/desktop/yarn.lock index 740629dd3e..c8080d23fd 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -2441,8 +2441,10 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -"next-electron-server@file:./thirdparty/next-electron-server": - version "0.0.8" +next-electron-server@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-electron-server/-/next-electron-server-1.0.0.tgz#03e133ed64a5ef671b6c6409f908c4901b1828cb" + integrity sha512-fTUaHwT0Jry2fbdUSIkAiIqgDAInI5BJFF4/j90/okvZCYlyx6yxpXB30KpzmOG6TN/ESwyvsFJVvS2WHT8PAA== node-addon-api@^1.6.3: version "1.7.2" @@ -2697,10 +2699,10 @@ prettier-plugin-packagejson@^2.4: sort-package-json "2.8.0" synckit "0.9.0" -prettier@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" - integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== +prettier@^3: + version "3.2.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== pretty-bytes@^4.0.2: version "4.0.2" From 2322b41f67fdb92ff6f953016ebac599a53495f2 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 17:44:15 +0530 Subject: [PATCH 223/391] Watch during dev --- desktop/README.md | 30 +++++++----------------------- desktop/package.json | 6 +++--- desktop/src/main.ts | 7 ++++++- desktop/src/utils/createWindow.ts | 6 +++--- desktop/src/utils/main.ts | 3 ++- 5 files changed, 21 insertions(+), 31 deletions(-) diff --git a/desktop/README.md b/desktop/README.md index e947e2a70a..da74b133ff 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -10,27 +10,13 @@ To know more about Ente, see [our main README](../README.md) or visit ## Building from source -Fetch submodules - -```sh -git submodule update --init --recursive -``` - Install dependencies ```sh yarn install ``` -Create a binary for your platform - -```sh -yarn build -``` - -## Developing - -Instead of building, you can run the app in development mode +Run in development mode (with hot reload) ```sh yarn dev @@ -39,15 +25,13 @@ yarn dev > [!CAUTION] > > `yarn dev` is currently not working (we'll fix soon). If you just want to -> build from source and use the generated binary, use `yarn build` as described -> above. +> build from source and use the generated binary, use `yarn build`. -This'll launch a development server to serve the pages loaded by the renderer -process, and will hot reload on changes. - -If you also want hot reload for the main process, run this in a separate -terminal: +Or create a binary for your platform ```sh -yarn watch +yarn build ``` + +That's the gist of it. For more development related documentation, see +[docs](docs/README.md). diff --git a/desktop/package.json b/desktop/package.json index aa0c92a21b..3eb87c6675 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -11,13 +11,13 @@ "build-main:quick": "tsc && electron-builder --config.compression=store", "build-renderer": "cd ../web && yarn install && yarn build:photos && cd ../desktop && rm -f out && ln -sf ../web/apps/photos/out", "build:quick": "yarn build-renderer && yarn build-main:quick", - "dev": "concurrently \"yarn dev-main\" \"yarn dev-renderer\"", + "dev": "concurrently --names 'main,rndr,tscw' \"yarn dev-main\" \"yarn dev-renderer\" \"yarn dev-main-watch\"", "dev-main": "tsc && electron app/main.js", + "dev-main-watch": "tsc --watch --preserveWatchOutput", "dev-renderer": "cd ../web && yarn install && yarn dev:photos", "postinstall": "electron-builder install-app-deps", "lint": "yarn prettier --check . && eslint \"src/**/*.ts\"", - "lint-fix": "yarn prettier --write . && eslint --fix .", - "watch": "tsc -w" + "lint-fix": "yarn prettier --write . && eslint --fix ." }, "dependencies": { "any-shell-escape": "^0.1.1", diff --git a/desktop/src/main.ts b/desktop/src/main.ts index b42f40cead..a280a9b59e 100644 --- a/desktop/src/main.ts +++ b/desktop/src/main.ts @@ -56,6 +56,11 @@ const setupMainHotReload = () => { } }; +/** + * The URL where the renderer HTML is being served from. + */ +export const rendererURL = "next://app"; + /** * next-electron-server allows up to directly use the output of `next build` in * production mode and `next dev` in development mode, whilst keeping the rest @@ -70,7 +75,7 @@ const setupMainHotReload = () => { * https://github.com/HaNdTriX/next-electron-server/issues/5 */ const setupRendererServer = () => { - serveNextAt("next://app"); + serveNextAt(rendererURL); }; setupMainHotReload(); diff --git a/desktop/src/utils/createWindow.ts b/desktop/src/utils/createWindow.ts index 29fc785d23..1fef1b5274 100644 --- a/desktop/src/utils/createWindow.ts +++ b/desktop/src/utils/createWindow.ts @@ -7,7 +7,7 @@ import { logErrorSentry } from "../services/sentry"; import { getHideDockIconPreference } from "../services/userPreference"; import { isDev } from "./common"; import { isPlatform } from "./common/platform"; -import { PROD_HOST_URL } from "./main"; +import { rendererURL } from "../main"; export async function createWindow(): Promise { const appImgPath = isDev @@ -41,14 +41,14 @@ export async function createWindow(): Promise { if (isDev) { splash.loadFile(`../resources/splash.html`); - mainWindow.loadURL(PROD_HOST_URL); + mainWindow.loadURL(rendererURL); // Open the DevTools. mainWindow.webContents.openDevTools(); } else { splash.loadURL( `file://${path.join(process.resourcesPath, "splash.html")}` ); - mainWindow.loadURL(PROD_HOST_URL); + mainWindow.loadURL(rendererURL); } mainWindow.webContents.on("did-fail-load", () => { splash.close(); diff --git a/desktop/src/utils/main.ts b/desktop/src/utils/main.ts index 55ccaff809..f38b27f7a0 100644 --- a/desktop/src/utils/main.ts +++ b/desktop/src/utils/main.ts @@ -4,6 +4,7 @@ import os from "os"; import path from "path"; import { existsSync } from "promise-fs"; import util from "util"; +import { rendererURL } from "../main"; import { setupAutoUpdater } from "../services/appUpdater"; import autoLauncher from "../services/autoLauncher"; import { getHideDockIconPreference } from "../services/userPreference"; @@ -43,7 +44,7 @@ export function handleDownloads(mainWindow: BrowserWindow) { export function handleExternalLinks(mainWindow: BrowserWindow) { mainWindow.webContents.setWindowOpenHandler(({ url }) => { - if (!url.startsWith("next://app")) { + if (!url.startsWith(rendererURL)) { require("electron").shell.openExternal(url); return { action: "deny" }; } else { From a5e6f0cc30050294787bb081d51ab8c0389db0b5 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 12 Mar 2024 18:00:19 +0530 Subject: [PATCH 224/391] Let Prettier 3 have a go at it --- desktop/CHANGELOG.md | 140 ++++++++++++------------ desktop/build/error.html | 2 +- desktop/build/splash.html | 2 +- desktop/build/version.html | 2 +- desktop/docs/dev.md | 4 +- desktop/docs/electron.md | 22 ++-- desktop/package.json | 2 +- desktop/src/api/cache.ts | 4 +- desktop/src/api/clip.ts | 8 +- desktop/src/api/export.ts | 2 +- desktop/src/api/ffmpeg.ts | 6 +- desktop/src/api/imageProcessor.ts | 12 +- desktop/src/api/safeStorage.ts | 4 +- desktop/src/api/system.ts | 2 +- desktop/src/api/upload.ts | 6 +- desktop/src/api/watch.ts | 16 +-- desktop/src/services/appUpdater.ts | 14 +-- desktop/src/services/clipService.ts | 26 ++--- desktop/src/services/diskCache.ts | 12 +- desktop/src/services/diskLRU.ts | 4 +- desktop/src/services/ffmpeg.ts | 8 +- desktop/src/services/fs.ts | 12 +- desktop/src/services/imageProcessor.ts | 28 ++--- desktop/src/services/sentry.ts | 4 +- desktop/src/services/upload.ts | 4 +- desktop/src/types/cache.ts | 2 +- desktop/src/utils/clip-bpe-ts/README.md | 17 +-- desktop/src/utils/clip-bpe-ts/mod.ts | 8 +- desktop/src/utils/common/index.ts | 4 +- desktop/src/utils/cors.ts | 2 +- desktop/src/utils/createWindow.ts | 9 +- desktop/src/utils/error.ts | 2 +- desktop/src/utils/ipcComms.ts | 8 +- desktop/src/utils/logging.ts | 2 +- desktop/src/utils/main.ts | 4 +- desktop/src/utils/menu.ts | 2 +- desktop/src/utils/processStats.ts | 74 ++++++------- desktop/src/utils/temp.ts | 2 +- desktop/src/utils/watch.ts | 4 +- 39 files changed, 243 insertions(+), 243 deletions(-) diff --git a/desktop/CHANGELOG.md b/desktop/CHANGELOG.md index 0a1602b94f..73aae2397d 100644 --- a/desktop/CHANGELOG.md +++ b/desktop/CHANGELOG.md @@ -4,128 +4,128 @@ ### New -- Option to select file download location. -- Add support for searching popular cities -- Sorted duplicates in desecending order of size -- Add Counter to upload section -- Display full name and collection name on hover on dedupe screen photos +- Option to select file download location. +- Add support for searching popular cities +- Sorted duplicates in desecending order of size +- Add Counter to upload section +- Display full name and collection name on hover on dedupe screen photos ### Bug Fixes -- Fix add to album padding issue -- Fix double uncategorized album issue -- Hide Hidden collection files from all section +- Fix add to album padding issue +- Fix double uncategorized album issue +- Hide Hidden collection files from all section ## v1.6.62 ### New -- Integrated onnx clip runner +- Integrated onnx clip runner ### Bug Fixes -- Fixes login button requiring double click issue -- Fixes Collection sort state not preserved issue -- Fixes continuous export causing app crash -- Improves ML related copies for better distinction from clip -- Added Better favicon for light mode -- Fixed face indexing issues -- Fixed thumbnail load issue +- Fixes login button requiring double click issue +- Fixes Collection sort state not preserved issue +- Fixes continuous export causing app crash +- Improves ML related copies for better distinction from clip +- Added Better favicon for light mode +- Fixed face indexing issues +- Fixed thumbnail load issue ## v1.6.60 ### Bug Fixes -- Fix Thumbnail Orientation issue -- Fix ML logging issue +- Fix Thumbnail Orientation issue +- Fix ML logging issue ## v1.6.59 ### New -- Added arm64 builds for linux +- Added arm64 builds for linux ### Bug Fixes -- Fix Editor file not loading issue -- Fix ML results missing thumbnail issue +- Fix Editor file not loading issue +- Fix ML results missing thumbnail issue ## v1.6.58 ### Bug Fixes -- Fix File load issue +- Fix File load issue ## v1.6.57 ### New Features -- Added encrypted Disk caching for files -- Added option to customize cache folder location +- Added encrypted Disk caching for files +- Added option to customize cache folder location ### Bug Fixes -- Fixed caching issue,causing multiple download of file during ml sync +- Fixed caching issue,causing multiple download of file during ml sync ## v1.6.55 ### Bug Fixes -- Added manage family portal option if add-on is active -- Fixed filename date parsing issue -- Fixed storage limit ui glitch -- Fixed dedupe page layout issue -- Fixed ElectronAPI refactoring issue -- Fixed Search related issues +- Added manage family portal option if add-on is active +- Fixed filename date parsing issue +- Fixed storage limit ui glitch +- Fixed dedupe page layout issue +- Fixed ElectronAPI refactoring issue +- Fixed Search related issues ## v1.6.54 ### New Features -- Added support for HEIC and raw image in photo editor +- Added support for HEIC and raw image in photo editor ### Bug Fixes -- Fixed 16bit HDR HEIC images support -- Fixed blocked login due safe storage issue -- Fixed Search related issues -- Fixed issue of watch folder not cleared on logout -- other under the hood ui/ux improvements +- Fixed 16bit HDR HEIC images support +- Fixed blocked login due safe storage issue +- Fixed Search related issues +- Fixed issue of watch folder not cleared on logout +- other under the hood ui/ux improvements ## v1.6.53 ### Bug Fixes -- Fixed watch folder disabled issue -- Fixed BF Add on related issues -- Fixed clip sync issue and added better logging -- Fixed mov file upload -- Fixed clip extraction related issue +- Fixed watch folder disabled issue +- Fixed BF Add on related issues +- Fixed clip sync issue and added better logging +- Fixed mov file upload +- Fixed clip extraction related issue ## v1.6.52 ### New Features -- Added Clip Desktop on windows +- Added Clip Desktop on windows ### Bug Fixes -- fixed google json matching issue -- other under-the-hood changes to improve performance and bug fixes +- fixed google json matching issue +- other under-the-hood changes to improve performance and bug fixes ## v1.6.50 ### New Features -- Added Clip desktop +- Added Clip desktop ### Bug Fixes -- Fixed desktop downloaded file had extra dot in the name -- Cleanup error messages -- fix the motion photo clustering issue -- Add option to disable cf proxy locally -- other under-the-hood changes to improve UX +- Fixed desktop downloaded file had extra dot in the name +- Cleanup error messages +- fix the motion photo clustering issue +- Add option to disable cf proxy locally +- other under-the-hood changes to improve UX ## v1.6.49 @@ -137,54 +137,54 @@ Check out our [blog](https://ente.io/blog/introducing-web-desktop-photo-editor/) ### Bug Fixes -- Fixed misaligned icons in photo-viewer -- Fixed issue with Motion photo upload -- Fixed issue with Live-photo upload -- other minor ux improvement +- Fixed misaligned icons in photo-viewer +- Fixed issue with Motion photo upload +- Fixed issue with Live-photo upload +- other minor ux improvement ## v1.6.46 ### Bug Fixes -- Fixes OOM crashes during file upload [#1379](https://github.com/ente-io/photos-web/pull/1379) +- Fixes OOM crashes during file upload [#1379](https://github.com/ente-io/photos-web/pull/1379) ## v1.6.45 ### Bug Fixes -- Fixed app keeps reloading issue [#235](https://github.com/ente-io/photos-desktop/pull/235) -- Fixed dng and arw preview issue [#1378](https://github.com/ente-io/photos-web/pull/1378) -- Added view crash report option (help menu) for user to share electron crash report locally +- Fixed app keeps reloading issue [#235](https://github.com/ente-io/photos-desktop/pull/235) +- Fixed dng and arw preview issue [#1378](https://github.com/ente-io/photos-web/pull/1378) +- Added view crash report option (help menu) for user to share electron crash report locally ## v1.6.44 -- Upgraded electron to get latest security patches and other improvements. +- Upgraded electron to get latest security patches and other improvements. ## v1.6.43 ### Added -- #### Check for update and changelog option +- #### Check for update and changelog option Added options to check for update manually and a view changelog via the app menubar -- #### Opt out of crash reporting +- #### Opt out of crash reporting Added option to out of a crash reporting, it can accessed from the settings -> preferences -> disable crash reporting -- #### Type search +- #### Type search Added new search option to search files based on file type i.e, image, video, live-photo. -- #### Manual Convert Button +- #### Manual Convert Button In case the video is not playable, Now there is a convert button which can be used to trigger conversion of the video to supported format. -- #### File Download Progress +- #### File Download Progress The file loader now also shows the exact percentage download progress, instead of just a simple loader. -- #### Bug fixes & other enhancements +- #### Bug fixes & other enhancements We have squashed a few pesky bugs that were reported by our community @@ -192,21 +192,21 @@ Check out our [blog](https://ente.io/blog/introducing-web-desktop-photo-editor/) ### Added -- #### Hidden albums +- #### Hidden albums You can now hide albums, just like individual memories. -- #### Email verification +- #### Email verification We have now made email verification optional, so you can sign in with just your email address and password, without waiting for a verification code. You can opt in / out of email verification from Settings > Security. -- #### Download Album +- #### Download Album You can now chose the download location for downloading albums. Along with that we have also added progress bar for album download. -- #### Bug fixes & other enhancements +- #### Bug fixes & other enhancements We have squashed a few pesky bugs that were reported by our community diff --git a/desktop/build/error.html b/desktop/build/error.html index 3291f7789b..cf1ea149d5 100644 --- a/desktop/build/error.html +++ b/desktop/build/error.html @@ -1,4 +1,4 @@ - + diff --git a/desktop/build/splash.html b/desktop/build/splash.html index 7d4a195e57..199c316010 100644 --- a/desktop/build/splash.html +++ b/desktop/build/splash.html @@ -1,4 +1,4 @@ - + diff --git a/desktop/build/version.html b/desktop/build/version.html index 03bf806a6b..b2038edd7a 100644 --- a/desktop/build/version.html +++ b/desktop/build/version.html @@ -1,4 +1,4 @@ - + Electron Updater Example diff --git a/desktop/docs/dev.md b/desktop/docs/dev.md index 4575188fd4..bfa80df690 100644 --- a/desktop/docs/dev.md +++ b/desktop/docs/dev.md @@ -1,4 +1,4 @@ # Development tips -* `yarn build:quick` is a variant of `yarn build` that uses the - `--config.compression=store` flag to (slightly) speed up electron-builder. +- `yarn build:quick` is a variant of `yarn build` that uses the + `--config.compression=store` flag to (slightly) speed up electron-builder. diff --git a/desktop/docs/electron.md b/desktop/docs/electron.md index e6c56b55bb..84c47e329b 100644 --- a/desktop/docs/electron.md +++ b/desktop/docs/electron.md @@ -7,15 +7,15 @@ Electron embeds Chromium and Node.js in the generated app's binary. The generated app thus consists of two separate processes - the _main_ process, and a _renderer_ process. -* The _main_ process is runs the embedded node. This process can deal with the - host OS - it is conceptually like a `node` repl running on your machine. In our - case, the TypeScript code (in the `src/` directory) gets transpiled by `tsc` - into JavaScript in the `build/app/` directory, which gets bundled in the - generated app's binary and is loaded by the node (main) process when the app - starts. +- The _main_ process is runs the embedded node. This process can deal with the + host OS - it is conceptually like a `node` repl running on your machine. In our + case, the TypeScript code (in the `src/` directory) gets transpiled by `tsc` + into JavaScript in the `build/app/` directory, which gets bundled in the + generated app's binary and is loaded by the node (main) process when the app + starts. -* The _renderer_ process is a regular web app that gets loaded into the embedded - Chromium. When the main process starts, it creates a new "window" that shows - this embedded Chromium. In our case, we build and bundle a static export of - the [Photos web app](../web/README.md) in the generated app. This gets loaded - by the embedded Chromium at runtime, acting as the app's UI. +- The _renderer_ process is a regular web app that gets loaded into the embedded + Chromium. When the main process starts, it creates a new "window" that shows + this embedded Chromium. In our case, we build and bundle a static export of + the [Photos web app](../web/README.md) in the generated app. This gets loaded + by the embedded Chromium at runtime, acting as the app's UI. diff --git a/desktop/package.json b/desktop/package.json index 3eb87c6675..8d90fca6e6 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -17,7 +17,7 @@ "dev-renderer": "cd ../web && yarn install && yarn dev:photos", "postinstall": "electron-builder install-app-deps", "lint": "yarn prettier --check . && eslint \"src/**/*.ts\"", - "lint-fix": "yarn prettier --write . && eslint --fix ." + "lint-fix": "yarn prettier --write . && eslint --fix src" }, "dependencies": { "any-shell-escape": "^0.1.1", diff --git a/desktop/src/api/cache.ts b/desktop/src/api/cache.ts index eabcef9808..86ba4378c3 100644 --- a/desktop/src/api/cache.ts +++ b/desktop/src/api/cache.ts @@ -22,7 +22,7 @@ const getCacheBucketDir = async (cacheName: string) => { export async function openDiskCache( cacheName: string, - cacheLimitInBytes?: number + cacheLimitInBytes?: number, ) { const cacheBucketDir = await getCacheBucketDir(cacheName); if (!existsSync(cacheBucketDir)) { @@ -42,7 +42,7 @@ export async function deleteDiskCache(cacheName: string) { } export async function setCustomCacheDirectory( - directory: string + directory: string, ): Promise { await ipcRenderer.invoke("set-custom-cache-directory", directory); } diff --git a/desktop/src/api/clip.ts b/desktop/src/api/clip.ts index 56772474d8..d2469e7b98 100644 --- a/desktop/src/api/clip.ts +++ b/desktop/src/api/clip.ts @@ -5,7 +5,7 @@ import { isExecError, parseExecError } from "../utils/error"; export async function computeImageEmbedding( model: Model, - imageData: Uint8Array + imageData: Uint8Array, ): Promise { let tempInputFilePath = null; try { @@ -15,7 +15,7 @@ export async function computeImageEmbedding( const embedding = await ipcRenderer.invoke( "compute-image-embedding", model, - tempInputFilePath + tempInputFilePath, ); return embedding; } catch (err) { @@ -34,13 +34,13 @@ export async function computeImageEmbedding( export async function computeTextEmbedding( model: Model, - text: string + text: string, ): Promise { try { const embedding = await ipcRenderer.invoke( "compute-text-embedding", model, - text + text, ); return embedding; } catch (err) { diff --git a/desktop/src/api/export.ts b/desktop/src/api/export.ts index f5eef4f59a..8adaa236fb 100644 --- a/desktop/src/api/export.ts +++ b/desktop/src/api/export.ts @@ -13,7 +13,7 @@ export const checkExistsAndCreateDir = async (dirPath: string) => { export const saveStreamToDisk = async ( filePath: string, - fileStream: ReadableStream + fileStream: ReadableStream, ) => { await writeStream(filePath, fileStream); }; diff --git a/desktop/src/api/ffmpeg.ts b/desktop/src/api/ffmpeg.ts index ef2e2291e0..9d11183a8c 100644 --- a/desktop/src/api/ffmpeg.ts +++ b/desktop/src/api/ffmpeg.ts @@ -8,7 +8,7 @@ export async function runFFmpegCmd( cmd: string[], inputFile: File | ElectronFile, outputFileName: string, - dontTimeout?: boolean + dontTimeout?: boolean, ) { let inputFilePath = null; let createdTempInputFile = null; @@ -16,7 +16,7 @@ export async function runFFmpegCmd( if (!existsSync(inputFile.path)) { const tempFilePath = await ipcRenderer.invoke( "get-temp-file-path", - inputFile.name + inputFile.name, ); await writeStream(tempFilePath, await inputFile.stream()); inputFilePath = tempFilePath; @@ -29,7 +29,7 @@ export async function runFFmpegCmd( cmd, inputFilePath, outputFileName, - dontTimeout + dontTimeout, ); return new File([outputFileData], outputFileName); } finally { diff --git a/desktop/src/api/imageProcessor.ts b/desktop/src/api/imageProcessor.ts index 84d447a54a..9d93aecd1b 100644 --- a/desktop/src/api/imageProcessor.ts +++ b/desktop/src/api/imageProcessor.ts @@ -8,7 +8,7 @@ import { isPlatform } from "../utils/common/platform"; export async function convertToJPEG( fileData: Uint8Array, - filename: string + filename: string, ): Promise { if (isPlatform("windows")) { throw Error(CustomErrors.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED); @@ -16,7 +16,7 @@ export async function convertToJPEG( const convertedFileData = await ipcRenderer.invoke( "convert-to-jpeg", fileData, - filename + filename, ); return convertedFileData; } @@ -24,20 +24,20 @@ export async function convertToJPEG( export async function generateImageThumbnail( inputFile: File | ElectronFile, maxDimension: number, - maxSize: number + maxSize: number, ): Promise { let inputFilePath = null; let createdTempInputFile = null; try { if (isPlatform("windows")) { throw Error( - CustomErrors.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED + CustomErrors.WINDOWS_NATIVE_IMAGE_PROCESSING_NOT_SUPPORTED, ); } if (!existsSync(inputFile.path)) { const tempFilePath = await ipcRenderer.invoke( "get-temp-file-path", - inputFile.name + inputFile.name, ); await writeStream(tempFilePath, await inputFile.stream()); inputFilePath = tempFilePath; @@ -49,7 +49,7 @@ export async function generateImageThumbnail( "generate-image-thumbnail", inputFilePath, maxDimension, - maxSize + maxSize, ); return thumbnail; } finally { diff --git a/desktop/src/api/safeStorage.ts b/desktop/src/api/safeStorage.ts index 89529013ad..64c4891950 100644 --- a/desktop/src/api/safeStorage.ts +++ b/desktop/src/api/safeStorage.ts @@ -6,7 +6,7 @@ export async function setEncryptionKey(encryptionKey: string) { try { const encryptedKey: Buffer = await ipcRenderer.invoke( "safeStorage-encrypt", - encryptionKey + encryptionKey, ); const b64EncryptedKey = Buffer.from(encryptedKey).toString("base64"); safeStorageStore.set("encryptionKey", b64EncryptedKey); @@ -21,7 +21,7 @@ export async function getEncryptionKey(): Promise { const b64EncryptedKey = safeStorageStore.get("encryptionKey"); if (b64EncryptedKey) { const keyBuffer = new Uint8Array( - Buffer.from(b64EncryptedKey, "base64") + Buffer.from(b64EncryptedKey, "base64"), ); return await ipcRenderer.invoke("safeStorage-decrypt", keyBuffer); } diff --git a/desktop/src/api/system.ts b/desktop/src/api/system.ts index 7a8635a9f1..a4dc91e054 100644 --- a/desktop/src/api/system.ts +++ b/desktop/src/api/system.ts @@ -9,7 +9,7 @@ export const reloadWindow = () => { }; export const registerUpdateEventListener = ( - showUpdateDialog: (updateInfo: AppUpdateInfo) => void + showUpdateDialog: (updateInfo: AppUpdateInfo) => void, ) => { ipcRenderer.removeAllListeners("show-update-dialog"); ipcRenderer.on("show-update-dialog", (_, updateInfo: AppUpdateInfo) => { diff --git a/desktop/src/api/upload.ts b/desktop/src/api/upload.ts index fc137452c1..280ff084ff 100644 --- a/desktop/src/api/upload.ts +++ b/desktop/src/api/upload.ts @@ -39,7 +39,7 @@ export const getPendingUploads = async () => { export const showUploadDirsDialog = async () => { try { const filePaths: string[] = await ipcRenderer.invoke( - "show-upload-dirs-dialog" + "show-upload-dirs-dialog", ); const files = await Promise.all(filePaths.map(getElectronFile)); return files; @@ -51,7 +51,7 @@ export const showUploadDirsDialog = async () => { export const showUploadFilesDialog = async () => { try { const filePaths: string[] = await ipcRenderer.invoke( - "show-upload-files-dialog" + "show-upload-files-dialog", ); const files = await Promise.all(filePaths.map(getElectronFile)); return files; @@ -63,7 +63,7 @@ export const showUploadFilesDialog = async () => { export const showUploadZipDialog = async () => { try { const filePaths: string[] = await ipcRenderer.invoke( - "show-upload-zip-dialog" + "show-upload-zip-dialog", ); let files: ElectronFile[] = []; diff --git a/desktop/src/api/watch.ts b/desktop/src/api/watch.ts index 9ebb5b4616..1b7a4ac3cf 100644 --- a/desktop/src/api/watch.ts +++ b/desktop/src/api/watch.ts @@ -9,7 +9,7 @@ import { isMappingPresent } from "../utils/watch"; export async function addWatchMapping( rootFolderName: string, folderPath: string, - uploadStrategy: number + uploadStrategy: number, ) { ElectronLog.log(`Adding watch mapping: ${folderPath}`); const watchMappings = getWatchMappings(); @@ -35,7 +35,7 @@ export async function addWatchMapping( export async function removeWatchMapping(folderPath: string) { let watchMappings = getWatchMappings(); const watchMapping = watchMappings.find( - (mapping) => mapping.folderPath === folderPath + (mapping) => mapping.folderPath === folderPath, ); if (!watchMapping) { @@ -47,7 +47,7 @@ export async function removeWatchMapping(folderPath: string) { }); watchMappings = watchMappings.filter( - (mapping) => mapping.folderPath !== watchMapping.folderPath + (mapping) => mapping.folderPath !== watchMapping.folderPath, ); setWatchMappings(watchMappings); @@ -55,11 +55,11 @@ export async function removeWatchMapping(folderPath: string) { export function updateWatchMappingSyncedFiles( folderPath: string, - files: WatchMapping["syncedFiles"] + files: WatchMapping["syncedFiles"], ): void { const watchMappings = getWatchMappings(); const watchMapping = watchMappings.find( - (mapping) => mapping.folderPath === folderPath + (mapping) => mapping.folderPath === folderPath, ); if (!watchMapping) { @@ -72,11 +72,11 @@ export function updateWatchMappingSyncedFiles( export function updateWatchMappingIgnoredFiles( folderPath: string, - files: WatchMapping["ignoredFiles"] + files: WatchMapping["ignoredFiles"], ): void { const watchMappings = getWatchMappings(); const watchMapping = watchMappings.find( - (mapping) => mapping.folderPath === folderPath + (mapping) => mapping.folderPath === folderPath, ); if (!watchMapping) { @@ -90,7 +90,7 @@ export function updateWatchMappingIgnoredFiles( export function registerWatcherFunctions( addFile: (file: ElectronFile) => Promise, removeFile: (path: string) => Promise, - removeFolder: (folderPath: string) => Promise + removeFolder: (folderPath: string) => Promise, ) { ipcRenderer.removeAllListeners("watch-add"); ipcRenderer.removeAllListeners("watch-change"); diff --git a/desktop/src/services/appUpdater.ts b/desktop/src/services/appUpdater.ts index c6af2541ae..2ddcef7047 100644 --- a/desktop/src/services/appUpdater.ts +++ b/desktop/src/services/appUpdater.ts @@ -25,7 +25,7 @@ export function setupAutoUpdater(mainWindow: BrowserWindow) { checkForUpdateAndNotify(mainWindow); setInterval( () => checkForUpdateAndNotify(mainWindow), - ONE_DAY_IN_MICROSECOND + ONE_DAY_IN_MICROSECOND, ); } @@ -47,7 +47,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) { if ( compareVersions( updateCheckResult.updateInfo.version, - app.getVersion() + app.getVersion(), ) <= 0 ) { log.debug("already at latest version"); @@ -60,7 +60,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) { ) { log.info( "user chose to skip version ", - updateCheckResult.updateInfo.version + updateCheckResult.updateInfo.version, ); return; } @@ -70,7 +70,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) { isPlatform("mac") && compareVersions( updateCheckResult.updateInfo.version, - desktopCutoffVersion + desktopCutoffVersion, ) > 0 ) { log.debug("auto update not possible due to key change"); @@ -91,7 +91,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) { ) { log.info( "user chose to mute update notification for version ", - updateCheckResult.updateInfo.version + updateCheckResult.updateInfo.version, ); return; } @@ -102,7 +102,7 @@ async function checkForUpdateAndNotify(mainWindow: BrowserWindow) { autoUpdatable: true, version: updateCheckResult.updateInfo.version, }), - FIVE_MIN_IN_MICROSECOND + FIVE_MIN_IN_MICROSECOND, ); }); autoUpdater.on("error", (error) => { @@ -152,7 +152,7 @@ async function getDesktopCutoffVersion() { function showUpdateDialog( mainWindow: BrowserWindow, - updateInfo: AppUpdateInfo + updateInfo: AppUpdateInfo, ) { mainWindow.webContents.send("show-update-dialog", updateInfo); } diff --git a/desktop/src/services/clipService.ts b/desktop/src/services/clipService.ts index 9e3a6a5b06..4a808d7a4e 100644 --- a/desktop/src/services/clipService.ts +++ b/desktop/src/services/clipService.ts @@ -103,7 +103,7 @@ export async function getClipImageModelPath(type: "ggml" | "onnx") { log.info("clip image model not found, downloading"); imageModelDownloadInProgress = downloadModel( modelSavePath, - IMAGE_MODEL_DOWNLOAD_URL[type] + IMAGE_MODEL_DOWNLOAD_URL[type], ); await imageModelDownloadInProgress; } else { @@ -111,11 +111,11 @@ export async function getClipImageModelPath(type: "ggml" | "onnx") { if (localFileSize !== IMAGE_MODEL_SIZE_IN_BYTES[type]) { log.info( "clip image model size mismatch, downloading again got:", - localFileSize + localFileSize, ); imageModelDownloadInProgress = downloadModel( modelSavePath, - IMAGE_MODEL_DOWNLOAD_URL[type] + IMAGE_MODEL_DOWNLOAD_URL[type], ); await imageModelDownloadInProgress; } @@ -150,7 +150,7 @@ export async function getClipTextModelPath(type: "ggml" | "onnx") { if (localFileSize !== TEXT_MODEL_SIZE_IN_BYTES[type]) { log.info( "clip text model size mismatch, downloading again got:", - localFileSize + localFileSize, ); textModelDownloadInProgress = true; downloadModel(modelSavePath, TEXT_MODEL_DOWNLOAD_URL[type]) @@ -212,7 +212,7 @@ function getTokenizer() { export async function computeImageEmbedding( model: Model, - inputFilePath: string + inputFilePath: string, ): Promise { if (!existsSync(inputFilePath)) { throw Error(CustomErrors.INVALID_FILE_PATH); @@ -227,7 +227,7 @@ export async function computeImageEmbedding( } export async function computeGGMLImageEmbedding( - inputFilePath: string + inputFilePath: string, ): Promise { try { const clipModelPath = await getClipImageModelPath("ggml"); @@ -263,7 +263,7 @@ export async function computeGGMLImageEmbedding( } export async function computeONNXImageEmbedding( - inputFilePath: string + inputFilePath: string, ): Promise { try { const imageSession = await getOnnxImageSession(); @@ -277,7 +277,7 @@ export async function computeONNXImageEmbedding( log.info( `onnx image embedding time: ${Date.now() - t1} ms (prep:${ t2 - t1 - } ms, extraction: ${Date.now() - t2} ms)` + } ms, extraction: ${Date.now() - t2} ms)`, ); const imageEmbedding = results["output"].data; // Float32Array return normalizeEmbedding(imageEmbedding); @@ -289,7 +289,7 @@ export async function computeONNXImageEmbedding( export async function computeTextEmbedding( model: Model, - text: string + text: string, ): Promise { if (model === Model.GGML_CLIP) { return await computeGGMLTextEmbedding(text); @@ -299,7 +299,7 @@ export async function computeTextEmbedding( } export async function computeGGMLTextEmbedding( - text: string + text: string, ): Promise { try { const clipModelPath = await getClipTextModelPath("ggml"); @@ -339,7 +339,7 @@ export async function computeGGMLTextEmbedding( } export async function computeONNXTextEmbedding( - text: string + text: string, ): Promise { try { const imageSession = await getOnnxTextSession(); @@ -354,7 +354,7 @@ export async function computeONNXTextEmbedding( log.info( `onnx text embedding time: ${Date.now() - t1} ms (prep:${ t2 - t1 - } ms, extraction: ${Date.now() - t2} ms)` + } ms, extraction: ${Date.now() - t2} ms)`, ); const textEmbedding = results["output"].data; // Float32Array return normalizeEmbedding(textEmbedding); @@ -444,7 +444,7 @@ async function getRGBData(inputFilePath: string) { export const computeClipMatchScore = async ( imageEmbedding: Float32Array, - textEmbedding: Float32Array + textEmbedding: Float32Array, ) => { if (imageEmbedding.length !== textEmbedding.length) { throw Error("imageEmbedding and textEmbedding length mismatch"); diff --git a/desktop/src/services/diskCache.ts b/desktop/src/services/diskCache.ts index be9199cbf9..6861bba9f8 100644 --- a/desktop/src/services/diskCache.ts +++ b/desktop/src/services/diskCache.ts @@ -11,7 +11,7 @@ const DEFAULT_CACHE_LIMIT = 1000 * 1000 * 1000; // 1GB export class DiskCache implements LimitedCache { constructor( private cacheBucketDir: string, - private cacheLimit = DEFAULT_CACHE_LIMIT + private cacheLimit = DEFAULT_CACHE_LIMIT, ) {} async put(cacheKey: string, response: Response): Promise { @@ -19,13 +19,13 @@ export class DiskCache implements LimitedCache { await writeStream(cachePath, response.body); DiskLRUService.enforceCacheSizeLimit( this.cacheBucketDir, - this.cacheLimit + this.cacheLimit, ); } async match( cacheKey: string, - { sizeInBytes }: { sizeInBytes?: number } = {} + { sizeInBytes }: { sizeInBytes?: number } = {}, ): Promise { const cachePath = path.join(this.cacheBucketDir, cacheKey); if (existsSync(cachePath)) { @@ -33,7 +33,7 @@ export class DiskCache implements LimitedCache { if (sizeInBytes && fileStats.size !== sizeInBytes) { logError( Error(), - "Cache key exists but size does not match. Deleting cache key." + "Cache key exists but size does not match. Deleting cache key.", ); unlink(cachePath).catch((e) => { if (e.code === "ENOENT") return; @@ -47,14 +47,14 @@ export class DiskCache implements LimitedCache { // add fallback for old cache keys const oldCachePath = getOldAssetCachePath( this.cacheBucketDir, - cacheKey + cacheKey, ); if (existsSync(oldCachePath)) { const fileStats = await stat(oldCachePath); if (sizeInBytes && fileStats.size !== sizeInBytes) { logError( Error(), - "Old cache key exists but size does not match. Deleting cache key." + "Old cache key exists but size does not match. Deleting cache key.", ); unlink(oldCachePath).catch((e) => { if (e.code === "ENOENT") return; diff --git a/desktop/src/services/diskLRU.ts b/desktop/src/services/diskLRU.ts index cf10b73510..44b05c0994 100644 --- a/desktop/src/services/diskLRU.ts +++ b/desktop/src/services/diskLRU.ts @@ -60,7 +60,7 @@ class DiskLRUService { if (e.code !== "ENOENT") { logError( e, - "Failed to evict least recently used" + "Failed to evict least recently used", ); } // ignoring the error, as it would get retried on the next run @@ -77,7 +77,7 @@ class DiskLRUService { private async findLeastRecentlyUsed( dir: string, - result?: LeastRecentlyUsedResult + result?: LeastRecentlyUsedResult, ): Promise { result = result || { atime: new Date(), path: "" }; diff --git a/desktop/src/services/ffmpeg.ts b/desktop/src/services/ffmpeg.ts index 6a76169b78..e0a9157909 100644 --- a/desktop/src/services/ffmpeg.ts +++ b/desktop/src/services/ffmpeg.ts @@ -24,7 +24,7 @@ export async function runFFmpegCmd( cmd: string[], inputFilePath: string, outputFileName: string, - dontTimeout = false + dontTimeout = false, ) { let tempOutputFilePath: string; try { @@ -49,7 +49,7 @@ export async function runFFmpegCmd( } else { await promiseWithTimeout( execAsync(escapedCmd), - FFMPEG_EXECUTION_WAIT_TIME + FFMPEG_EXECUTION_WAIT_TIME, ); } if (!existsSync(tempOutputFilePath)) { @@ -59,7 +59,7 @@ export async function runFFmpegCmd( "ffmpeg command execution time ", escapedCmd, Date.now() - startTime, - "ms" + "ms", ); const outputFile = await readFile(tempOutputFilePath); @@ -87,7 +87,7 @@ export async function deleteTempFile(tempFilePath: string) { if (!tempFilePath.startsWith(tempDirPath)) { logErrorSentry( Error("not a temp file"), - "tried to delete a non temp file" + "tried to delete a non temp file", ); } rmSync(tempFilePath, { force: true }); diff --git a/desktop/src/services/fs.ts b/desktop/src/services/fs.ts index 5d1954211c..06d413c1f0 100644 --- a/desktop/src/services/fs.ts +++ b/desktop/src/services/fs.ts @@ -38,7 +38,7 @@ export const getFileStream = async (filePath: string) => { buff, 0, FILE_STREAM_CHUNK_SIZE, - offset + offset, )) as unknown as number; offset += bytesRead; if (bytesRead === 0) { @@ -103,7 +103,7 @@ export const getValidPaths = (paths: string[]) => { export const getZipFileStream = async ( zip: StreamZip.StreamZipAsync, - filePath: string + filePath: string, ) => { const stream = await zip.stream(filePath); const done = { @@ -204,7 +204,7 @@ export async function isFolder(dirPath: string) { } export const convertBrowserStreamToNode = ( - fileStream: ReadableStream + fileStream: ReadableStream, ) => { const reader = fileStream.getReader(); const rs = new Readable(); @@ -229,7 +229,7 @@ export const convertBrowserStreamToNode = ( export async function writeNodeStream( filePath: string, - fileStream: NodeJS.ReadableStream + fileStream: NodeJS.ReadableStream, ) { const writeable = fs.createWriteStream(filePath); @@ -252,7 +252,7 @@ export async function writeNodeStream( export async function writeStream( filePath: string, - fileStream: ReadableStream + fileStream: ReadableStream, ) { const readable = convertBrowserStreamToNode(fileStream); await writeNodeStream(filePath, readable); @@ -267,7 +267,7 @@ export async function readTextFile(filePath: string) { export async function moveFile( sourcePath: string, - destinationPath: string + destinationPath: string, ): Promise { if (!existsSync(sourcePath)) { throw new Error("File does not exist"); diff --git a/desktop/src/services/imageProcessor.ts b/desktop/src/services/imageProcessor.ts index d9b3e45f03..cb6c7416d6 100644 --- a/desktop/src/services/imageProcessor.ts +++ b/desktop/src/services/imageProcessor.ts @@ -80,7 +80,7 @@ function getImageMagickStaticPath() { export async function convertToJPEG( fileData: Uint8Array, - filename: string + filename: string, ): Promise { let tempInputFilePath: string; let tempOutputFilePath: string; @@ -96,7 +96,7 @@ export async function convertToJPEG( throw new Error("heic convert output file not found"); } const convertedFileData = new Uint8Array( - await readFile(tempOutputFilePath) + await readFile(tempOutputFilePath), ); return convertedFileData; } catch (e) { @@ -118,11 +118,11 @@ export async function convertToJPEG( async function runConvertCommand( tempInputFilePath: string, - tempOutputFilePath: string + tempOutputFilePath: string, ) { const convertCmd = constructConvertCommand( tempInputFilePath, - tempOutputFilePath + tempOutputFilePath, ); const escapedCmd = shellescape(convertCmd); log.info("running convert command: " + escapedCmd); @@ -131,7 +131,7 @@ async function runConvertCommand( function constructConvertCommand( tempInputFilePath: string, - tempOutputFilePath: string + tempOutputFilePath: string, ) { let convertCmd: string[]; if (isPlatform("mac")) { @@ -157,7 +157,7 @@ function constructConvertCommand( return tempOutputFilePath; } return cmdPart; - } + }, ); } else { throw Error(CustomErrors.INVALID_OS(process.platform)); @@ -168,7 +168,7 @@ function constructConvertCommand( export async function generateImageThumbnail( inputFilePath: string, width: number, - maxSize: number + maxSize: number, ): Promise { let tempOutputFilePath: string; let quality = MAX_QUALITY; @@ -180,7 +180,7 @@ export async function generateImageThumbnail( inputFilePath, tempOutputFilePath, width, - quality + quality, ); if (!existsSync(tempOutputFilePath)) { @@ -206,14 +206,14 @@ async function runThumbnailGenerationCommand( inputFilePath: string, tempOutputFilePath: string, maxDimension: number, - quality: number + quality: number, ) { const thumbnailGenerationCmd: string[] = constructThumbnailGenerationCommand( inputFilePath, tempOutputFilePath, maxDimension, - quality + quality, ); const escapedCmd = shellescape(thumbnailGenerationCmd); log.info("running thumbnail generation command: " + escapedCmd); @@ -223,7 +223,7 @@ function constructThumbnailGenerationCommand( inputFilePath: string, tempOutputFilePath: string, maxDimension: number, - quality: number + quality: number, ) { let thumbnailGenerationCmd: string[]; if (isPlatform("mac")) { @@ -242,7 +242,7 @@ function constructThumbnailGenerationCommand( return quality.toString(); } return cmdPart; - } + }, ); } else if (isPlatform("linux")) { thumbnailGenerationCmd = @@ -259,13 +259,13 @@ function constructThumbnailGenerationCommand( if (cmdPart.includes(SAMPLE_SIZE_PLACEHOLDER)) { return cmdPart.replaceAll( SAMPLE_SIZE_PLACEHOLDER, - (2 * maxDimension).toString() + (2 * maxDimension).toString(), ); } if (cmdPart.includes(MAX_DIMENSION_PLACEHOLDER)) { return cmdPart.replaceAll( MAX_DIMENSION_PLACEHOLDER, - maxDimension.toString() + maxDimension.toString(), ); } if (cmdPart === QUALITY_PLACEHOLDER) { diff --git a/desktop/src/services/sentry.ts b/desktop/src/services/sentry.ts index ae40b95b37..4c5573152f 100644 --- a/desktop/src/services/sentry.ts +++ b/desktop/src/services/sentry.ts @@ -5,12 +5,12 @@ import { logToDisk } from "./logging"; export function logErrorSentry( error: any, msg: string, - info?: Record + info?: Record, ) { logToDisk( `error: ${error?.name} ${error?.message} ${ error?.stack - } msg: ${msg} info: ${JSON.stringify(info)}` + } msg: ${msg} info: ${JSON.stringify(info)}`, ); if (isDev) { console.log(error, { msg, info }); diff --git a/desktop/src/services/upload.ts b/desktop/src/services/upload.ts index e9db576a18..38a628c255 100644 --- a/desktop/src/services/upload.ts +++ b/desktop/src/services/upload.ts @@ -7,7 +7,7 @@ import { getValidPaths, getZipFileStream } from "./fs"; export const getSavedFilePaths = (type: FILE_PATH_TYPE) => { const paths = getValidPaths( - uploadStatusStore.get(FILE_PATH_KEYS[type]) as string[] + uploadStatusStore.get(FILE_PATH_KEYS[type]) as string[], ) ?? []; setToUploadFiles(type, paths); @@ -17,7 +17,7 @@ export const getSavedFilePaths = (type: FILE_PATH_TYPE) => { export async function getZipEntryAsElectronFile( zipName: string, zip: StreamZip.StreamZipAsync, - entry: StreamZip.ZipEntry + entry: StreamZip.ZipEntry, ): Promise { return { path: path diff --git a/desktop/src/types/cache.ts b/desktop/src/types/cache.ts index fde7dc0384..112716eea0 100644 --- a/desktop/src/types/cache.ts +++ b/desktop/src/types/cache.ts @@ -1,7 +1,7 @@ export interface LimitedCache { match: ( key: string, - options?: { sizeInBytes?: number } + options?: { sizeInBytes?: number }, ) => Promise; put: (key: string, data: Response) => Promise; delete: (key: string) => Promise; diff --git a/desktop/src/utils/clip-bpe-ts/README.md b/desktop/src/utils/clip-bpe-ts/README.md index dd171eb42c..ee052eb414 100644 --- a/desktop/src/utils/clip-bpe-ts/README.md +++ b/desktop/src/utils/clip-bpe-ts/README.md @@ -1,20 +1,21 @@ # CLIP Byte Pair Encoding JavaScript Port + A JavaScript port of [OpenAI's CLIP byte-pair-encoding tokenizer](https://github.com/openai/CLIP/blob/3bee28119e6b28e75b82b811b87b56935314e6a5/clip/simple_tokenizer.py). ```js import Tokenizer from "https://deno.land/x/clip_bpe@v0.0.6/mod.js"; let t = new Tokenizer(); -t.encode("hello") // [3306] -t.encode("magnificent") // [10724] -t.encode("magnificently") // [9725, 2922] -t.decode(t.encode("HELLO")) // "hello " -t.decode(t.encode("abc123")) // "abc 1 2 3 " -t.decode(st.encode("let's see here")) // "let 's see here " -t.encode("hello world!") // [3306, 1002, 256] +t.encode("hello"); // [3306] +t.encode("magnificent"); // [10724] +t.encode("magnificently"); // [9725, 2922] +t.decode(t.encode("HELLO")); // "hello " +t.decode(t.encode("abc123")); // "abc 1 2 3 " +t.decode(st.encode("let's see here")); // "let 's see here " +t.encode("hello world!"); // [3306, 1002, 256] // to encode for CLIP (trims to maximum of 77 tokens and adds start and end token, and pads with zeros if less than 77 tokens): -t.encodeForCLIP("hello world!") // [49406,3306,1002,256,49407,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] +t.encodeForCLIP("hello world!"); // [49406,3306,1002,256,49407,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ``` This encoder/decoder behaves differently to the the GPT-2/3 tokenizer (JavaScript version of that [here](https://github.com/latitudegames/GPT-3-Encoder)). For example, it doesn't preserve capital letters, as shown above. diff --git a/desktop/src/utils/clip-bpe-ts/mod.ts b/desktop/src/utils/clip-bpe-ts/mod.ts index 880d8b438f..6cdf246f75 100644 --- a/desktop/src/utils/clip-bpe-ts/mod.ts +++ b/desktop/src/utils/clip-bpe-ts/mod.ts @@ -75,7 +75,7 @@ export default class { constructor() { this.byteEncoder = bytesToUnicode(); this.byteDecoder = Object.fromEntries( - Object.entries(this.byteEncoder).map(([k, v]) => [v, Number(k)]) + Object.entries(this.byteEncoder).map(([k, v]) => [v, Number(k)]), ); let merges = bpeVocabData.text.split("\n"); merges = merges.slice(1, 49152 - 256 - 2 + 1); @@ -346,10 +346,10 @@ export default class { vocab.push("<|startoftext|>", "<|endoftext|>"); this.encoder = Object.fromEntries(vocab.map((v, i) => [v, i])); this.decoder = Object.fromEntries( - Object.entries(this.encoder).map(([k, v]) => [v, k]) + Object.entries(this.encoder).map(([k, v]) => [v, k]), ); this.bpeRanks = Object.fromEntries( - mergedMerges.map((v, i) => [v.join("·😎·"), i]) + mergedMerges.map((v, i) => [v.join("·😎·"), i]), ); // ·😎· because js doesn't yet have tuples this.cache = { "<|startoftext|>": "<|startoftext|>", @@ -436,7 +436,7 @@ export default class { bpeTokens.push( ...this.bpe(token) .split(" ") - .map((bpeToken: string) => this.encoder[bpeToken]) + .map((bpeToken: string) => this.encoder[bpeToken]), ); } return bpeTokens; diff --git a/desktop/src/utils/common/index.ts b/desktop/src/utils/common/index.ts index 61880bcda2..e970dfec41 100644 --- a/desktop/src/utils/common/index.ts +++ b/desktop/src/utils/common/index.ts @@ -4,7 +4,7 @@ export const isDev = !app.isPackaged; export const promiseWithTimeout = async ( request: Promise, - timeout: number + timeout: number, ): Promise => { const timeoutRef: { current: NodeJS.Timeout; @@ -12,7 +12,7 @@ export const promiseWithTimeout = async ( const rejectOnTimeout = new Promise((_, reject) => { timeoutRef.current = setTimeout( () => reject(Error(CustomErrors.WAIT_TIME_EXCEEDED)), - timeout + timeout, ); }); const requestWithTimeOutCancellation = async () => { diff --git a/desktop/src/utils/cors.ts b/desktop/src/utils/cors.ts index bec6560612..25f76211a3 100644 --- a/desktop/src/utils/cors.ts +++ b/desktop/src/utils/cors.ts @@ -16,6 +16,6 @@ export function addAllowOriginHeader(mainWindow: BrowserWindow) { callback({ responseHeaders: details.responseHeaders, }); - } + }, ); } diff --git a/desktop/src/utils/createWindow.ts b/desktop/src/utils/createWindow.ts index 1fef1b5274..c7d44e6c9a 100644 --- a/desktop/src/utils/createWindow.ts +++ b/desktop/src/utils/createWindow.ts @@ -1,13 +1,12 @@ import { app, BrowserWindow, nativeImage } from "electron"; import ElectronLog from "electron-log"; import * as path from "path"; -import { isAppQuitting } from "../main"; +import { isAppQuitting, rendererURL } from "../main"; import autoLauncher from "../services/autoLauncher"; import { logErrorSentry } from "../services/sentry"; import { getHideDockIconPreference } from "../services/userPreference"; import { isDev } from "./common"; import { isPlatform } from "./common/platform"; -import { rendererURL } from "../main"; export async function createWindow(): Promise { const appImgPath = isDev @@ -46,7 +45,7 @@ export async function createWindow(): Promise { mainWindow.webContents.openDevTools(); } else { splash.loadURL( - `file://${path.join(process.resourcesPath, "splash.html")}` + `file://${path.join(process.resourcesPath, "splash.html")}`, ); mainWindow.loadURL(rendererURL); } @@ -55,7 +54,7 @@ export async function createWindow(): Promise { isDev ? mainWindow.loadFile(`../resources/error.html`) : splash.loadURL( - `file://${path.join(process.resourcesPath, "error.html")}` + `file://${path.join(process.resourcesPath, "error.html")}`, ); mainWindow.maximize(); mainWindow.show(); @@ -76,7 +75,7 @@ export async function createWindow(): Promise { logErrorSentry( Error("render-process-gone"), "webContents event render-process-gone", - { details } + { details }, ); ElectronLog.log("webContents event render-process-gone", details); }); diff --git a/desktop/src/utils/error.ts b/desktop/src/utils/error.ts index aff17edb63..1922045a2c 100644 --- a/desktop/src/utils/error.ts +++ b/desktop/src/utils/error.ts @@ -9,7 +9,7 @@ export const parseExecError = (err: any) => { if (errMessage.includes("Bad CPU type in executable")) { return CustomErrors.UNSUPPORTED_PLATFORM( process.platform, - process.arch + process.arch, ); } else { return errMessage; diff --git a/desktop/src/utils/ipcComms.ts b/desktop/src/utils/ipcComms.ts index be41f72575..eec644aebb 100644 --- a/desktop/src/utils/ipcComms.ts +++ b/desktop/src/utils/ipcComms.ts @@ -38,7 +38,7 @@ import { generateTempFilePath } from "./temp"; export default function setupIpcComs( tray: Tray, mainWindow: BrowserWindow, - watcher: chokidar.FSWatcher + watcher: chokidar.FSWatcher, ): void { ipcMain.handle("select-dir", async () => { const result = await dialog.showOpenDialog({ @@ -156,9 +156,9 @@ export default function setupIpcComs( cmd, inputFilePath, outputFileName, - dontTimeout + dontTimeout, ); - } + }, ); ipcMain.handle("get-temp-file-path", (_, formatSuffix) => { return generateTempFilePath(formatSuffix); @@ -171,7 +171,7 @@ export default function setupIpcComs( "generate-image-thumbnail", (_, fileData, maxDimension, maxSize) => { return generateImageThumbnail(fileData, maxDimension, maxSize); - } + }, ); ipcMain.handle("compute-image-embedding", (_, model, inputFilePath) => { diff --git a/desktop/src/utils/logging.ts b/desktop/src/utils/logging.ts index 8a92006a87..351a1aef86 100644 --- a/desktop/src/utils/logging.ts +++ b/desktop/src/utils/logging.ts @@ -12,7 +12,7 @@ export function setupLogging(isDev?: boolean) { export function convertBytesToHumanReadable( bytes: number, - precision = 2 + precision = 2, ): string { if (bytes === 0 || isNaN(bytes)) { return "0 MB"; diff --git a/desktop/src/utils/main.ts b/desktop/src/utils/main.ts index f38b27f7a0..569752326e 100644 --- a/desktop/src/utils/main.ts +++ b/desktop/src/utils/main.ts @@ -25,7 +25,7 @@ export function setupTrayItem(mainWindow: BrowserWindow) { : "taskbar-icon.png"; const trayImgPath = path.join( isDev ? "build" : process.resourcesPath, - iconName + iconName, ); const trayIcon = nativeImage.createFromPath(trayImgPath); const tray = new Tray(trayIcon); @@ -37,7 +37,7 @@ export function setupTrayItem(mainWindow: BrowserWindow) { export function handleDownloads(mainWindow: BrowserWindow) { mainWindow.webContents.session.on("will-download", (_, item) => { item.setSavePath( - getUniqueSavePath(item.getFilename(), app.getPath("downloads")) + getUniqueSavePath(item.getFilename(), app.getPath("downloads")), ); }); } diff --git a/desktop/src/utils/menu.ts b/desktop/src/utils/menu.ts index 3c6a1b4e4f..c86786ff6f 100644 --- a/desktop/src/utils/menu.ts +++ b/desktop/src/utils/menu.ts @@ -64,7 +64,7 @@ export async function buildMenuBar(mainWindow: BrowserWindow): Promise

{ label: "View Changelog", click: () => { shell.openExternal( - "https://github.com/ente-io/ente/blob/main/desktop/CHANGELOG.md" + "https://github.com/ente-io/ente/blob/main/desktop/CHANGELOG.md", ); }, }, diff --git a/desktop/src/utils/processStats.ts b/desktop/src/utils/processStats.ts index 9f993288b4..b10238eeaa 100644 --- a/desktop/src/utils/processStats.ts +++ b/desktop/src/utils/processStats.ts @@ -16,11 +16,11 @@ const HIGH_RENDERER_MEMORY_USAGE_THRESHOLD_IN_KILOBYTES = 1024 * 1024; // 1 GB async function logMainProcessStats() { const processMemoryInfo = await getNormalizedProcessMemoryInfo( - await process.getProcessMemoryInfo() + await process.getProcessMemoryInfo(), ); const cpuUsage = process.getCPUUsage(); const heapStatistics = getNormalizedHeapStatistics( - process.getHeapStatistics() + process.getHeapStatistics(), ); ElectronLog.log("main process stats", { @@ -42,11 +42,11 @@ async function logSpikeMainMemoryUsage() { const processMemoryInfo = await process.getProcessMemoryInfo(); const currentMemoryUsage = Math.max( processMemoryInfo.residentSet ?? 0, - processMemoryInfo.private + processMemoryInfo.private, ); const previousMemoryUsage = Math.max( previousMainProcessMemoryInfo.residentSet ?? 0, - previousMainProcessMemoryInfo.private + previousMainProcessMemoryInfo.private, ); const isSpiking = currentMemoryUsage - previousMemoryUsage >= @@ -66,7 +66,7 @@ async function logSpikeMainMemoryUsage() { await getNormalizedProcessMemoryInfo(previousMainProcessMemoryInfo); const cpuUsage = process.getCPUUsage(); const heapStatistics = getNormalizedHeapStatistics( - process.getHeapStatistics() + process.getHeapStatistics(), ); ElectronLog.log("reporting main memory usage spike", { @@ -94,12 +94,12 @@ async function logSpikeRendererMemoryUsage() { const processMemoryInfo = await process.getProcessMemoryInfo(); const currentMemoryUsage = Math.max( processMemoryInfo.residentSet ?? 0, - processMemoryInfo.private + processMemoryInfo.private, ); const previousMemoryUsage = Math.max( previousRendererProcessMemoryInfo.private, - previousRendererProcessMemoryInfo.residentSet ?? 0 + previousRendererProcessMemoryInfo.residentSet ?? 0, ); const isSpiking = currentMemoryUsage - previousMemoryUsage >= @@ -117,11 +117,11 @@ async function logSpikeRendererMemoryUsage() { await getNormalizedProcessMemoryInfo(processMemoryInfo); const normalizedPreviousProcessMemoryInfo = await getNormalizedProcessMemoryInfo( - previousRendererProcessMemoryInfo + previousRendererProcessMemoryInfo, ); const cpuUsage = process.getCPUUsage(); const heapStatistics = getNormalizedHeapStatistics( - process.getHeapStatistics() + process.getHeapStatistics(), ); ElectronLog.log("reporting renderer memory usage spike", { @@ -140,11 +140,11 @@ async function logSpikeRendererMemoryUsage() { async function logRendererProcessStats() { const blinkMemoryInfo = getNormalizedBlinkMemoryInfo(); const heapStatistics = getNormalizedHeapStatistics( - process.getHeapStatistics() + process.getHeapStatistics(), ); const webFrameResourceUsage = getNormalizedWebFrameResourceUsage(); const processMemoryInfo = await getNormalizedProcessMemoryInfo( - await process.getProcessMemoryInfo() + await process.getProcessMemoryInfo(), ); ElectronLog.log("renderer process stats", { blinkMemoryInfo, @@ -157,7 +157,7 @@ async function logRendererProcessStats() { export function setupMainProcessStatsLogger() { setInterval( logSpikeMainMemoryUsage, - SPIKE_DETECTION_INTERVAL_IN_MICROSECONDS + SPIKE_DETECTION_INTERVAL_IN_MICROSECONDS, ); setInterval(logMainProcessStats, LOGGING_INTERVAL_IN_MICROSECONDS); } @@ -165,7 +165,7 @@ export function setupMainProcessStatsLogger() { export function setupRendererProcessStatsLogger() { setInterval( logSpikeRendererMemoryUsage, - SPIKE_DETECTION_INTERVAL_IN_MICROSECONDS + SPIKE_DETECTION_INTERVAL_IN_MICROSECONDS, ); setInterval(logRendererProcessStats, LOGGING_INTERVAL_IN_MICROSECONDS); } @@ -174,21 +174,21 @@ export async function logRendererProcessMemoryUsage(message: string) { const processMemoryInfo = await process.getProcessMemoryInfo(); const processMemory = Math.max( processMemoryInfo.private, - processMemoryInfo.residentSet ?? 0 + processMemoryInfo.residentSet ?? 0, ); ElectronLog.log( "renderer ProcessMemory", message, - convertBytesToHumanReadable(processMemory * 1024) + convertBytesToHumanReadable(processMemory * 1024), ); } const getNormalizedProcessMemoryInfo = async ( - processMemoryInfo: Electron.ProcessMemoryInfo + processMemoryInfo: Electron.ProcessMemoryInfo, ) => { return { residentSet: convertBytesToHumanReadable( - processMemoryInfo.residentSet * 1024 + processMemoryInfo.residentSet * 1024, ), private: convertBytesToHumanReadable(processMemoryInfo.private * 1024), shared: convertBytesToHumanReadable(processMemoryInfo.shared * 1024), @@ -199,40 +199,40 @@ const getNormalizedBlinkMemoryInfo = () => { const blinkMemoryInfo = process.getBlinkMemoryInfo(); return { allocated: convertBytesToHumanReadable( - blinkMemoryInfo.allocated * 1024 + blinkMemoryInfo.allocated * 1024, ), total: convertBytesToHumanReadable(blinkMemoryInfo.total * 1024), }; }; const getNormalizedHeapStatistics = ( - heapStatistics: Electron.HeapStatistics + heapStatistics: Electron.HeapStatistics, ) => { return { totalHeapSize: convertBytesToHumanReadable( - heapStatistics.totalHeapSize * 1024 + heapStatistics.totalHeapSize * 1024, ), totalHeapSizeExecutable: convertBytesToHumanReadable( - heapStatistics.totalHeapSizeExecutable * 1024 + heapStatistics.totalHeapSizeExecutable * 1024, ), totalPhysicalSize: convertBytesToHumanReadable( - heapStatistics.totalPhysicalSize * 1024 + heapStatistics.totalPhysicalSize * 1024, ), totalAvailableSize: convertBytesToHumanReadable( - heapStatistics.totalAvailableSize * 1024 + heapStatistics.totalAvailableSize * 1024, ), usedHeapSize: convertBytesToHumanReadable( - heapStatistics.usedHeapSize * 1024 + heapStatistics.usedHeapSize * 1024, ), heapSizeLimit: convertBytesToHumanReadable( - heapStatistics.heapSizeLimit * 1024 + heapStatistics.heapSizeLimit * 1024, ), mallocedMemory: convertBytesToHumanReadable( - heapStatistics.mallocedMemory * 1024 + heapStatistics.mallocedMemory * 1024, ), peakMallocedMemory: convertBytesToHumanReadable( - heapStatistics.peakMallocedMemory * 1024 + heapStatistics.peakMallocedMemory * 1024, ), doesZapGarbage: heapStatistics.doesZapGarbage, }; @@ -244,51 +244,51 @@ const getNormalizedWebFrameResourceUsage = () => { images: { count: webFrameResourceUsage.images.count, size: convertBytesToHumanReadable( - webFrameResourceUsage.images.size + webFrameResourceUsage.images.size, ), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.images.liveSize + webFrameResourceUsage.images.liveSize, ), }, scripts: { count: webFrameResourceUsage.scripts.count, size: convertBytesToHumanReadable( - webFrameResourceUsage.scripts.size + webFrameResourceUsage.scripts.size, ), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.scripts.liveSize + webFrameResourceUsage.scripts.liveSize, ), }, cssStyleSheets: { count: webFrameResourceUsage.cssStyleSheets.count, size: convertBytesToHumanReadable( - webFrameResourceUsage.cssStyleSheets.size + webFrameResourceUsage.cssStyleSheets.size, ), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.cssStyleSheets.liveSize + webFrameResourceUsage.cssStyleSheets.liveSize, ), }, xslStyleSheets: { count: webFrameResourceUsage.xslStyleSheets.count, size: convertBytesToHumanReadable( - webFrameResourceUsage.xslStyleSheets.size + webFrameResourceUsage.xslStyleSheets.size, ), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.xslStyleSheets.liveSize + webFrameResourceUsage.xslStyleSheets.liveSize, ), }, fonts: { count: webFrameResourceUsage.fonts.count, size: convertBytesToHumanReadable(webFrameResourceUsage.fonts.size), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.fonts.liveSize + webFrameResourceUsage.fonts.liveSize, ), }, other: { count: webFrameResourceUsage.other.count, size: convertBytesToHumanReadable(webFrameResourceUsage.other.size), liveSize: convertBytesToHumanReadable( - webFrameResourceUsage.other.liveSize + webFrameResourceUsage.other.liveSize, ), }, }; diff --git a/desktop/src/utils/temp.ts b/desktop/src/utils/temp.ts index f8e5978701..91496ce139 100644 --- a/desktop/src/utils/temp.ts +++ b/desktop/src/utils/temp.ts @@ -21,7 +21,7 @@ function generateTempName(length: number) { const charactersLength = CHARACTERS.length; for (let i = 0; i < length; i++) { result += CHARACTERS.charAt( - Math.floor(Math.random() * charactersLength) + Math.floor(Math.random() * charactersLength), ); } return result; diff --git a/desktop/src/utils/watch.ts b/desktop/src/utils/watch.ts index 41a8e71e4d..d8575ebd7c 100644 --- a/desktop/src/utils/watch.ts +++ b/desktop/src/utils/watch.ts @@ -2,10 +2,10 @@ import { WatchMapping } from "../types"; export function isMappingPresent( watchMappings: WatchMapping[], - folderPath: string + folderPath: string, ) { const watchMapping = watchMappings?.find( - (mapping) => mapping.folderPath === folderPath + (mapping) => mapping.folderPath === folderPath, ); return !!watchMapping; } From 55e0ec39ede4b1f1d22ac63e7cbe2ba5b5fa4238 Mon Sep 17 00:00:00 2001 From: Quentin Bramas Date: Tue, 12 Mar 2024 15:14:35 +0100 Subject: [PATCH 225/391] add guide for self-hosting server + webapp with external S3 storage --- docs/docs/self-hosting/guides/index.md | 232 +++++++++++++++++++++++++ 1 file changed, 232 insertions(+) diff --git a/docs/docs/self-hosting/guides/index.md b/docs/docs/self-hosting/guides/index.md index 9f3cd8f5e5..ad3b607da3 100644 --- a/docs/docs/self-hosting/guides/index.md +++ b/docs/docs/self-hosting/guides/index.md @@ -7,3 +7,235 @@ description: Guides for self hosting Ente Photos and/or Ente Auth If you've figured out how to do something, help others out by adding walkthroughs, tutorials and other FAQ pages in this directory. + +This guide is for self hosting the server and the web application of Ente Photos using docker compose and an external S3 bucket. So we assume that you already have the keys and secrets for the S3 bucket. +The plan is as follows: + +1. create a `compose.yaml` file +1. set up the `.credentials.env` file +1. run `docker-compose up` +1. create an account and increase storage quota +1. fix potential CORS issue with your bucket + +## 1. Create a `compose.yaml` file + +After cloning the main repository with +```bash +git clone git@github.com:ente-io/ente.git +cd ente +``` +create a `compose.yaml` file at the root of the project with the following content (there is nothing to change here): + +```yaml +version: '3' +services: + museum: + build: + context: server + args: + GIT_COMMIT: local + ports: + - 8080:8080 # API + - 2112:2112 # Prometheus metrics + depends_on: + postgres: + condition: service_healthy + + # Wait for museum to ping pong before starting the webapp. + healthcheck: + test: + [ + "CMD", + "echo", + "1" # I don't know what to put here + ] + environment: + # no need to touch these + ENTE_DB_HOST: postgres + ENTE_DB_PORT: 5432 + ENTE_DB_NAME: ente_db + ENTE_DB_USER: pguser + ENTE_DB_PASSWORD: pgpass + env_file: + - ./.credentials.env + volumes: + - custom-logs:/var/logs + networks: + - internal + + web: + build: + context: web + args: + GIT_SHA: local + ports: + - 8081:80 + - 8082:80 + depends_on: + museum: + condition: service_healthy + env_file: + - ./.credentials.env + + postgres: + image: postgres:12 + ports: + - 5432:5432 + environment: + POSTGRES_USER: pguser + POSTGRES_PASSWORD: pgpass + POSTGRES_DB: ente_db + # Wait for postgres to be accept connections before starting museum. + healthcheck: + test: + [ + "CMD", + "pg_isready", + "-q", + "-d", + "ente_db", + "-U", + "pguser" + ] + interval: 1s + timeout: 5s + retries: 20 + volumes: + - postgres-data:/var/lib/postgresql/data + networks: + - internal +volumes: + custom-logs: + postgres-data: +networks: + internal: +``` + +It maybe be added in the future, but if it does not exist, create a `Dockerfile` in the `web` directory with the following content: + +```Dockerfile + +# syntax=docker/dockerfile:1 +FROM node:21-bookworm-slim as ente-builder +WORKDIR /app +RUN apt update && apt install -y ca-certificates && rm -rf /var/lib/apt/lists/* +COPY . . +RUN yarn install +ARG GIT_SHA=local +ENV GIT_SHA=$GIT_SHA +ENV NEXT_PUBLIC_ENTE_ENDPOINT=DOCKER_RUNTIME_REPLACE_ENDPOINT +ENV NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=DOCKER_RUNTIME_REPLACE_ALBUMS_ENDPOINT +RUN yarn build + + +FROM nginx:1.25-alpine-slim +COPY --from=ente-builder /app/apps/photos/out /usr/share/nginx/html +COPY < Date: Tue, 12 Mar 2024 13:56:34 -0400 Subject: [PATCH 226/391] feat: use encryption key for more entropy in reset secret --- web/apps/photos/src/components/Sidebar/UtilitySection.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx index 781e2bf371..8e00873c76 100644 --- a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx +++ b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx @@ -18,7 +18,10 @@ import { import { APPS, CLIENT_PACKAGE_NAMES } from "@ente/shared/apps/constants"; import ThemeSwitcher from "@ente/shared/components/ThemeSwitcher"; import { getRecoveryKey } from "@ente/shared/crypto/helpers"; -import { encryptToB64 } from "@ente/shared/crypto/internal/libsodium"; +import { + encryptToB64, + generateEncryptionKey, +} from "@ente/shared/crypto/internal/libsodium"; import { getAccountsURL } from "@ente/shared/network/api"; import { logError } from "@ente/shared/sentry"; import { THEME_COLOR } from "@ente/shared/themes/constants"; @@ -28,7 +31,6 @@ import isElectron from "is-electron"; import { getAccountsToken } from "services/userService"; import { getDownloadAppMessage } from "utils/ui"; import { isInternalUser } from "utils/user"; -import { v4 as uuidv4 } from "uuid"; import Preferences from "./Preferences"; export default function UtilitySection({ closeSidebar }) { @@ -85,7 +87,7 @@ export default function UtilitySection({ closeSidebar }) { // let's create the necessary recovery information const recoveryKey = await getRecoveryKey(); - const resetSecret = uuidv4(); + const resetSecret = await generateEncryptionKey(); const encryptionResult = await encryptToB64( resetSecret, From 609e4d1207f1a2eafcfa45ff545d3a69fe978315 Mon Sep 17 00:00:00 2001 From: httpjamesm Date: Tue, 12 Mar 2024 13:56:59 -0400 Subject: [PATCH 227/391] feat: open accounts portal in a new tab --- .../photos/src/components/Sidebar/UtilitySection.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx index 8e00873c76..454ef55bfe 100644 --- a/web/apps/photos/src/components/Sidebar/UtilitySection.tsx +++ b/web/apps/photos/src/components/Sidebar/UtilitySection.tsx @@ -103,11 +103,13 @@ export default function UtilitySection({ closeSidebar }) { const accountsToken = await getAccountsToken(); - window.location.href = `${getAccountsURL()}${ - ACCOUNTS_PAGES.ACCOUNT_HANDOFF - }?package=${CLIENT_PACKAGE_NAMES.get( - APPS.PHOTOS, - )}&token=${accountsToken}`; + window.open( + `${getAccountsURL()}${ + ACCOUNTS_PAGES.ACCOUNT_HANDOFF + }?package=${CLIENT_PACKAGE_NAMES.get( + APPS.PHOTOS, + )}&token=${accountsToken}`, + ); } catch (e) { logError(e, "failed to redirect to accounts page"); } From cfb7c61c63b4cc3d311057a9576829e2532759cb Mon Sep 17 00:00:00 2001 From: httpjamesm Date: Tue, 12 Mar 2024 13:57:20 -0400 Subject: [PATCH 228/391] fix: lock file --- yarn.lock | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000000..fb57ccd13a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + From 260a7fbcaac24070c0e6f72005f79dfae8ec9514 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:19:59 +0530 Subject: [PATCH 229/391] [cli] Allow switching API host based on config --- cli/internal/api/files.go | 13 ++++++++++++- cli/main.go | 24 +++++++++++++++++++++--- cli/utils/constants/constants.go | 1 + 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/cli/internal/api/files.go b/cli/internal/api/files.go index 2e4af77015..b0f82f692a 100644 --- a/cli/internal/api/files.go +++ b/cli/internal/api/files.go @@ -2,19 +2,30 @@ package api import ( "context" + "github.com/ente-io/cli/utils/constants" + "github.com/spf13/viper" "strconv" + "strings" ) var ( downloadHost = "https://files.ente.io/?fileID=" ) +func downloadUrl(fileID int64) string { + apiEndpoint := viper.GetString("endpoint.api") + if apiEndpoint == "" || strings.Compare(apiEndpoint, constants.EnteApiUrl) == 0 { + return downloadHost + strconv.FormatInt(fileID, 10) + } + return apiEndpoint + "/files/download/" + strconv.FormatInt(fileID, 10) +} + func (c *Client) DownloadFile(ctx context.Context, fileID int64, absolutePath string) error { req := c.downloadClient.R(). SetContext(ctx). SetOutput(absolutePath) attachToken(req) - r, err := req.Get(downloadHost + strconv.FormatInt(fileID, 10)) + r, err := req.Get(downloadUrl(fileID)) if r.IsError() { return &ApiError{ StatusCode: r.StatusCode(), diff --git a/cli/main.go b/cli/main.go index 2147afde91..5da45f0360 100644 --- a/cli/main.go +++ b/cli/main.go @@ -8,6 +8,7 @@ import ( "github.com/ente-io/cli/pkg" "github.com/ente-io/cli/pkg/secrets" "github.com/ente-io/cli/utils/constants" + "github.com/spf13/viper" "log" "os" "path/filepath" @@ -23,10 +24,10 @@ func main() { log.Fatalf("Please mount a volume to %s to persist cli data\n%v\n", cliDBPath, err) } } - if err != nil { log.Fatalf("Could not create cli config path\n%v\n", err) } + initConfig(cliDBPath) newCliPath := fmt.Sprintf("%s/ente-cli.db", cliDBPath) if !strings.HasPrefix(cliDBPath, "/") { oldCliPath := fmt.Sprintf("%sente-cli.db", cliDBPath) @@ -48,8 +49,8 @@ func main() { } ctrl := pkg.ClICtrl{ Client: api.NewClient(api.Params{ - Debug: false, - //Host: "http://localhost:8080", + Debug: viper.GetBool("log.http"), + Host: viper.GetString("endpoint.api"), }), DB: db, KeyHolder: secrets.NewKeyHolder(secrets.GetOrCreateClISecret()), @@ -66,6 +67,23 @@ func main() { cmd.Execute(&ctrl) } +func initConfig(cliConfigPath string) { + viper.SetConfigName("config") // name of config file (without extension) + viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name + viper.AddConfigPath(cliConfigPath + "/") // path to look for the config file in + viper.AddConfigPath(".") // optionally look for config in the working directory + + viper.SetDefault("endpoint.api", constants.EnteApiUrl) + viper.SetDefault("log.http", false) + if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + log.Printf("Config file not found; using defaults %s", cliConfigPath) + } else { + // Config file was found but another error was produced + } + } +} + // GetCLIConfigPath returns the path to the .ente-cli folder and creates it if it doesn't exist. func GetCLIConfigPath() (string, error) { if os.Getenv("ENTE_CLI_CONFIG_PATH") != "" { diff --git a/cli/utils/constants/constants.go b/cli/utils/constants/constants.go index 7209d6466a..e6147ae9a6 100644 --- a/cli/utils/constants/constants.go +++ b/cli/utils/constants/constants.go @@ -1,3 +1,4 @@ package constants const CliDataPath = "/cli-data/" +const EnteApiUrl = "https://api.ente.io" From d7d42b6854f7cfae16066d116b5e9274a4005bcd Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:23:52 +0530 Subject: [PATCH 230/391] [cli] Add example config file --- cli/config.yaml.example | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 cli/config.yaml.example diff --git a/cli/config.yaml.example b/cli/config.yaml.example new file mode 100644 index 0000000000..efd92c545c --- /dev/null +++ b/cli/config.yaml.example @@ -0,0 +1,10 @@ +# You can put this configuration file in the following locations: +# - $HOME/.ente/config.yaml +# - config.yaml in the current working directory +# - $ENTE_CLI_CONFIG_PATH/config.yaml + +endpoint: + api: "https://api.ente.io" + +log: + http: false # log http requests and responses \ No newline at end of file From 063e98028030e3bca83c8b8aab0ce634c78a9c9e Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:35:16 +0530 Subject: [PATCH 231/391] [cli] Add command to get-token --- cli/cmd/account.go | 43 +++++++++++++++++++++++++++++++++++++--- cli/pkg/account.go | 24 +++++++++++++++++++++- cli/pkg/model/account.go | 7 ++++++- 3 files changed, 69 insertions(+), 5 deletions(-) diff --git a/cli/cmd/account.go b/cli/cmd/account.go index 72e719e62c..a4c78fb10e 100644 --- a/cli/cmd/account.go +++ b/cli/cmd/account.go @@ -62,7 +62,7 @@ var updateAccCmd = &cobra.Command{ fmt.Printf("invalid app. Accepted values are 'photos', 'locker', 'auth'") } - err := ctrl.UpdateAccount(context.Background(), model.UpdateAccountParams{ + err := ctrl.UpdateAccount(context.Background(), model.AccountCommandParams{ Email: email, App: api.StringToApp(app), ExportDir: &exportDir, @@ -73,12 +73,49 @@ var updateAccCmd = &cobra.Command{ }, } +// Subcommand for 'account update' +var getTokenCmd = &cobra.Command{ + Use: "get-token", + Short: "Get token for an account for a specific app", + Run: func(cmd *cobra.Command, args []string) { + recoverWithLog() + app, _ := cmd.Flags().GetString("app") + email, _ := cmd.Flags().GetString("email") + if email == "" { + + fmt.Println("email must be specified, use --help for more information") + // print help + return + } + + validApps := map[string]bool{ + "photos": true, + "locker": true, + "auth": true, + } + + if !validApps[app] { + fmt.Printf("invalid app. Accepted values are 'photos', 'locker', 'auth'") + + } + err := ctrl.GetToken(context.Background(), model.AccountCommandParams{ + Email: email, + App: api.StringToApp(app), + }) + if err != nil { + fmt.Printf("Error updating account: %v\n", err) + } + }, +} + func init() { // Add 'config' subcommands to the root command rootCmd.AddCommand(accountCmd) // Add 'config' subcommands to the 'config' command updateAccCmd.Flags().String("dir", "", "update export directory") - updateAccCmd.Flags().String("email", "", "email address of the account to update") + updateAccCmd.Flags().String("email", "", "email address of the account") updateAccCmd.Flags().String("app", "photos", "Specify the app, default is 'photos'") - accountCmd.AddCommand(listAccCmd, addAccCmd, updateAccCmd) + getTokenCmd.Flags().String("email", "", "email address of the account") + getTokenCmd.Flags().String("app", "photos", "Specify the app, default is 'photos'") + accountCmd.AddCommand(listAccCmd, addAccCmd, updateAccCmd, getTokenCmd) } diff --git a/cli/pkg/account.go b/cli/pkg/account.go index df45f3239a..9363e2f80b 100644 --- a/cli/pkg/account.go +++ b/cli/pkg/account.go @@ -142,7 +142,7 @@ func (c *ClICtrl) ListAccounts(cxt context.Context) error { return nil } -func (c *ClICtrl) UpdateAccount(ctx context.Context, params model.UpdateAccountParams) error { +func (c *ClICtrl) UpdateAccount(ctx context.Context, params model.AccountCommandParams) error { accounts, err := c.GetAccounts(ctx) if err != nil { return err @@ -177,5 +177,27 @@ func (c *ClICtrl) UpdateAccount(ctx context.Context, params model.UpdateAccountP return b.Put([]byte(accountKey), accInfoBytes) }) return err +} +func (c *ClICtrl) GetToken(ctx context.Context, params model.AccountCommandParams) error { + accounts, err := c.GetAccounts(ctx) + if err != nil { + return err + } + var acc *model.Account + for _, a := range accounts { + if a.Email == params.Email && a.App == params.App { + acc = &a + break + } + } + if acc == nil { + return fmt.Errorf("account not found, use `account list` to list accounts") + } + secretInfo, err := c.KeyHolder.LoadSecrets(*acc) + if err != nil { + return err + } + fmt.Println(secretInfo.TokenStr()) + return nil } diff --git a/cli/pkg/model/account.go b/cli/pkg/model/account.go index 7e18a9f66a..31f7866abf 100644 --- a/cli/pkg/model/account.go +++ b/cli/pkg/model/account.go @@ -1,6 +1,7 @@ package model import ( + "encoding/base64" "fmt" "github.com/ente-io/cli/internal/api" ) @@ -17,7 +18,7 @@ type Account struct { ExportDir string `json:"exportDir"` } -type UpdateAccountParams struct { +type AccountCommandParams struct { Email string App api.App ExportDir *string @@ -37,3 +38,7 @@ type AccSecretInfo struct { Token []byte PublicKey []byte } + +func (a *AccSecretInfo) TokenStr() string { + return base64.URLEncoding.EncodeToString(a.Token) +} From f21a627a7172b9dd5d364146bd2ceac8ffb32cb5 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Fri, 8 Mar 2024 18:48:38 +0530 Subject: [PATCH 232/391] Add cli generated docs inside docs/generated --- cli/README.md | 9 ++++++- cli/cmd/root.go | 5 ++++ cli/docs/generated/ente.md | 27 ++++++++++++++++++++ cli/docs/generated/ente_account.md | 19 ++++++++++++++ cli/docs/generated/ente_account_add.md | 19 ++++++++++++++ cli/docs/generated/ente_account_get-token.md | 21 +++++++++++++++ cli/docs/generated/ente_account_list.md | 19 ++++++++++++++ cli/docs/generated/ente_account_update.md | 22 ++++++++++++++++ cli/docs/generated/ente_auth.md | 16 ++++++++++++ cli/docs/generated/ente_auth_decrypt.md | 19 ++++++++++++++ cli/docs/generated/ente_export.md | 19 ++++++++++++++ cli/docs/generated/ente_version.md | 19 ++++++++++++++ cli/go.mod | 2 ++ cli/go.sum | 2 ++ cli/main.go | 9 +++++++ 15 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 cli/docs/generated/ente.md create mode 100644 cli/docs/generated/ente_account.md create mode 100644 cli/docs/generated/ente_account_add.md create mode 100644 cli/docs/generated/ente_account_get-token.md create mode 100644 cli/docs/generated/ente_account_list.md create mode 100644 cli/docs/generated/ente_account_update.md create mode 100644 cli/docs/generated/ente_auth.md create mode 100644 cli/docs/generated/ente_auth_decrypt.md create mode 100644 cli/docs/generated/ente_export.md create mode 100644 cli/docs/generated/ente_version.md diff --git a/cli/README.md b/cli/README.md index fc241cb6d8..5a4097a46e 100644 --- a/cli/README.md +++ b/cli/README.md @@ -64,7 +64,14 @@ ente account update --email email@domain.com --dir ~/photos ente export ``` ---- +### CLI Docs +You can view more cli documents at [docs](docs/generated/ente.md). +To update the docs, run the following command: + +```shell +go run main.go docs +``` + ## Docker diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 5b7c1c6f36..0b53f41622 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" "github.com/ente-io/cli/pkg" + "github.com/spf13/cobra/doc" "os" "runtime" @@ -27,6 +28,10 @@ var rootCmd = &cobra.Command{ }, } +func GenerateDocs() error { + return doc.GenMarkdownTree(rootCmd, "./docs/generated") +} + // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute(controller *pkg.ClICtrl) { diff --git a/cli/docs/generated/ente.md b/cli/docs/generated/ente.md new file mode 100644 index 0000000000..91e71e3797 --- /dev/null +++ b/cli/docs/generated/ente.md @@ -0,0 +1,27 @@ +## ente + +CLI tool for exporting your photos from ente.io + +### Synopsis + +Start by creating a config file in your home directory: + +``` +ente [flags] +``` + +### Options + +``` + -h, --help help for ente + -t, --toggle Help message for toggle +``` + +### SEE ALSO + +* [ente account](ente_account.md) - Manage account settings +* [ente auth](ente_auth.md) - Authenticator commands +* [ente export](ente_export.md) - Starts the export process +* [ente version](ente_version.md) - Prints the current version + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/docs/generated/ente_account.md b/cli/docs/generated/ente_account.md new file mode 100644 index 0000000000..402a1e2d2f --- /dev/null +++ b/cli/docs/generated/ente_account.md @@ -0,0 +1,19 @@ +## ente account + +Manage account settings + +### Options + +``` + -h, --help help for account +``` + +### SEE ALSO + +* [ente](ente.md) - CLI tool for exporting your photos from ente.io +* [ente account add](ente_account_add.md) - Add a new account +* [ente account get-token](ente_account_get-token.md) - Get token for an account for a specific app +* [ente account list](ente_account_list.md) - list configured accounts +* [ente account update](ente_account_update.md) - Update an existing account's export directory + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/docs/generated/ente_account_add.md b/cli/docs/generated/ente_account_add.md new file mode 100644 index 0000000000..b3c5194d30 --- /dev/null +++ b/cli/docs/generated/ente_account_add.md @@ -0,0 +1,19 @@ +## ente account add + +Add a new account + +``` +ente account add [flags] +``` + +### Options + +``` + -h, --help help for add +``` + +### SEE ALSO + +* [ente account](ente_account.md) - Manage account settings + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/docs/generated/ente_account_get-token.md b/cli/docs/generated/ente_account_get-token.md new file mode 100644 index 0000000000..35baec9788 --- /dev/null +++ b/cli/docs/generated/ente_account_get-token.md @@ -0,0 +1,21 @@ +## ente account get-token + +Get token for an account for a specific app + +``` +ente account get-token [flags] +``` + +### Options + +``` + --app string Specify the app, default is 'photos' (default "photos") + --email string email address of the account + -h, --help help for get-token +``` + +### SEE ALSO + +* [ente account](ente_account.md) - Manage account settings + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/docs/generated/ente_account_list.md b/cli/docs/generated/ente_account_list.md new file mode 100644 index 0000000000..f9e0afb591 --- /dev/null +++ b/cli/docs/generated/ente_account_list.md @@ -0,0 +1,19 @@ +## ente account list + +list configured accounts + +``` +ente account list [flags] +``` + +### Options + +``` + -h, --help help for list +``` + +### SEE ALSO + +* [ente account](ente_account.md) - Manage account settings + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/docs/generated/ente_account_update.md b/cli/docs/generated/ente_account_update.md new file mode 100644 index 0000000000..22801c8054 --- /dev/null +++ b/cli/docs/generated/ente_account_update.md @@ -0,0 +1,22 @@ +## ente account update + +Update an existing account's export directory + +``` +ente account update [flags] +``` + +### Options + +``` + --app string Specify the app, default is 'photos' (default "photos") + --dir string update export directory + --email string email address of the account + -h, --help help for update +``` + +### SEE ALSO + +* [ente account](ente_account.md) - Manage account settings + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/docs/generated/ente_auth.md b/cli/docs/generated/ente_auth.md new file mode 100644 index 0000000000..69ac6e5ba0 --- /dev/null +++ b/cli/docs/generated/ente_auth.md @@ -0,0 +1,16 @@ +## ente auth + +Authenticator commands + +### Options + +``` + -h, --help help for auth +``` + +### SEE ALSO + +* [ente](ente.md) - CLI tool for exporting your photos from ente.io +* [ente auth decrypt](ente_auth_decrypt.md) - Decrypt authenticator export + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/docs/generated/ente_auth_decrypt.md b/cli/docs/generated/ente_auth_decrypt.md new file mode 100644 index 0000000000..cdeb16364e --- /dev/null +++ b/cli/docs/generated/ente_auth_decrypt.md @@ -0,0 +1,19 @@ +## ente auth decrypt + +Decrypt authenticator export + +``` +ente auth decrypt [input] [output] [flags] +``` + +### Options + +``` + -h, --help help for decrypt +``` + +### SEE ALSO + +* [ente auth](ente_auth.md) - Authenticator commands + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/docs/generated/ente_export.md b/cli/docs/generated/ente_export.md new file mode 100644 index 0000000000..ab06c646ad --- /dev/null +++ b/cli/docs/generated/ente_export.md @@ -0,0 +1,19 @@ +## ente export + +Starts the export process + +``` +ente export [flags] +``` + +### Options + +``` + -h, --help help for export +``` + +### SEE ALSO + +* [ente](ente.md) - CLI tool for exporting your photos from ente.io + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/docs/generated/ente_version.md b/cli/docs/generated/ente_version.md new file mode 100644 index 0000000000..57c520e9b7 --- /dev/null +++ b/cli/docs/generated/ente_version.md @@ -0,0 +1,19 @@ +## ente version + +Prints the current version + +``` +ente version [flags] +``` + +### Options + +``` + -h, --help help for version +``` + +### SEE ALSO + +* [ente](ente.md) - CLI tool for exporting your photos from ente.io + +###### Auto generated by spf13/cobra on 8-Mar-2024 diff --git a/cli/go.mod b/cli/go.mod index 090185f647..d643e8b26c 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -12,10 +12,12 @@ require ( require ( github.com/alessio/shellescape v1.4.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/danieljoos/wincred v1.2.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect ) require ( diff --git a/cli/go.sum b/cli/go.sum index 914c2284a2..bcf5fa3199 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -48,6 +48,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/danieljoos/wincred v1.2.0 h1:ozqKHaLK0W/ii4KVbbvluM91W2H3Sh0BncbUNPS7jLE= github.com/danieljoos/wincred v1.2.0/go.mod h1:FzQLLMKBFdvu+osBrnFODiv32YGwCfx0SkRa/eYHgec= @@ -168,6 +169,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= diff --git a/cli/main.go b/cli/main.go index 5da45f0360..957669f9d4 100644 --- a/cli/main.go +++ b/cli/main.go @@ -64,6 +64,15 @@ func main() { panic(err) } }() + + if len(os.Args) == 2 && os.Args[1] == "docs" { + log.Println("Generating docs") + err = cmd.GenerateDocs() + if err != nil { + log.Fatal(err) + } + return + } cmd.Execute(&ctrl) } From ddd89aa1d1b8f74dd326ca7e4e2cfcb0cf724dca Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 14:32:41 +0530 Subject: [PATCH 233/391] [cli] Log query params in debug mode --- cli/internal/api/log.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cli/internal/api/log.go b/cli/internal/api/log.go index ba97c0d861..b02f2a043a 100644 --- a/cli/internal/api/log.go +++ b/cli/internal/api/log.go @@ -30,6 +30,13 @@ func logRequest(req *resty.Request) { } } } + // log query params if present + if len(req.QueryParam) > 0 { + fmt.Println(color.GreenString("Query Params:")) + for k, v := range req.QueryParam { + fmt.Printf("%s: %s\n", color.CyanString(k), color.YellowString(strings.Join(v, ","))) + } + } } func logResponse(resp *resty.Response) { From 51d3238a52f062561a866befa5615957f9b79cf3 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 14:33:32 +0530 Subject: [PATCH 234/391] [cli] Log query params in debug mode --- cli/internal/api/log.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/internal/api/log.go b/cli/internal/api/log.go index b02f2a043a..31ce404df0 100644 --- a/cli/internal/api/log.go +++ b/cli/internal/api/log.go @@ -34,6 +34,9 @@ func logRequest(req *resty.Request) { if len(req.QueryParam) > 0 { fmt.Println(color.GreenString("Query Params:")) for k, v := range req.QueryParam { + if k == TokenQuery { + v = []string{"REDACTED"} + } fmt.Printf("%s: %s\n", color.CyanString(k), color.YellowString(strings.Join(v, ","))) } } From 0d383467220025499d34ba52bb5ed83eb2d274f2 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 15:54:07 +0530 Subject: [PATCH 235/391] [cli] Add admin API to bump up storage for free users --- cli/cmd/admin.go | 83 +++++++++++++++++++ cli/internal/api/admin.go | 57 +++++++++++++ cli/internal/api/models/user_details.go | 16 ++++ cli/internal/promt.go | 78 +++++++++++++++++- cli/main.go | 1 - cli/pkg/admin_actions.go | 104 ++++++++++++++++++++++++ cli/pkg/model/admin.go | 6 ++ cli/utils/convert.go | 31 +++++++ cli/utils/time.go | 14 ---- 9 files changed, 373 insertions(+), 17 deletions(-) create mode 100644 cli/cmd/admin.go create mode 100644 cli/internal/api/admin.go create mode 100644 cli/internal/api/models/user_details.go create mode 100644 cli/pkg/admin_actions.go create mode 100644 cli/pkg/model/admin.go create mode 100644 cli/utils/convert.go diff --git a/cli/cmd/admin.go b/cli/cmd/admin.go new file mode 100644 index 0000000000..153736624c --- /dev/null +++ b/cli/cmd/admin.go @@ -0,0 +1,83 @@ +package cmd + +import ( + "context" + "fmt" + "github.com/ente-io/cli/pkg/model" + "github.com/spf13/cobra" + "github.com/spf13/pflag" +) + +var _adminCmd = &cobra.Command{ + Use: "admin", + Short: "Commands for admin actions", + Long: "Commands for admin actions like disable or enabling 2fa, bumping up the storage limit, etc.", +} + +var _userDetailsCmd = &cobra.Command{ + Use: "get-user-id", + Short: "Get user id", + RunE: func(cmd *cobra.Command, args []string) error { + recoverWithLog() + var flags = &model.AdminActionForUser{} + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if f.Name == "admin-user" { + flags.AdminEmail = f.Value.String() + } + if f.Name == "user" { + flags.UserEmail = f.Value.String() + } + }) + return ctrl.GetUserId(context.Background(), *flags) + }, +} + +var _disable2faCmd = &cobra.Command{ + Use: "disable-2fa", + Short: "Disable 2fa for a user", + RunE: func(cmd *cobra.Command, args []string) error { + recoverWithLog() + var flags = &model.AdminActionForUser{} + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if f.Name == "admin-user" { + flags.AdminEmail = f.Value.String() + } + if f.Name == "user" { + flags.UserEmail = f.Value.String() + } + }) + fmt.Println("Not supported yet") + return nil + }, +} + +var _updateFreeUserStorage = &cobra.Command{ + Use: "update-subscription", + Short: "Update subscription for the free user", + RunE: func(cmd *cobra.Command, args []string) error { + recoverWithLog() + var flags = &model.AdminActionForUser{} + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if f.Name == "admin-user" { + flags.AdminEmail = f.Value.String() + } + if f.Name == "user" { + flags.UserEmail = f.Value.String() + } + }) + return ctrl.UpdateFreeStorage(context.Background(), *flags) + }, +} + +func init() { + rootCmd.AddCommand(_adminCmd) + _ = _userDetailsCmd.MarkFlagRequired("admin-user") + _ = _userDetailsCmd.MarkFlagRequired("user") + _userDetailsCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") + _userDetailsCmd.Flags().StringP("user", "u", "", "The email of the user to fetch details for. (required)") + _disable2faCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") + _disable2faCmd.Flags().StringP("user", "u", "", "The email of the user to disable 2FA for. (required)") + _updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") + _updateFreeUserStorage.Flags().StringP("user", "u", "", "The email of the user to update subscription for. (required)") + _adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage) +} diff --git a/cli/internal/api/admin.go b/cli/internal/api/admin.go new file mode 100644 index 0000000000..1c0b2c50af --- /dev/null +++ b/cli/internal/api/admin.go @@ -0,0 +1,57 @@ +package api + +import ( + "context" + "fmt" + "github.com/ente-io/cli/internal/api/models" + "time" +) + +func (c *Client) GetUserIdFromEmail(ctx context.Context, email string) (*models.UserDetails, error) { + var res models.UserDetails + r, err := c.restClient.R(). + SetContext(ctx). + SetResult(&res). + SetQueryParam("email", email). + Get("/admin/user/") + if err != nil { + return nil, err + } + if r.IsError() { + return nil, &ApiError{ + StatusCode: r.StatusCode(), + Message: r.String(), + } + } + return &res, nil +} +func (c *Client) UpdateFreePlanSub(ctx context.Context, userDetails *models.UserDetails, storageInBytes int64, expiryTimeInMicro int64) error { + var res interface{} + if userDetails.Subscription.ProductID != "free" { + return fmt.Errorf("user is not on free plan") + } + payload := map[string]interface{}{ + "userID": userDetails.User.ID, + "expiryTime": expiryTimeInMicro, + "transactionID": fmt.Sprintf("cli-on-%d", time.Now().Unix()), + "productID": "free", + "paymentProvider": "", + "storage": storageInBytes, + } + r, err := c.restClient.R(). + SetContext(ctx). + SetResult(&res). + SetBody(payload). + Put("/admin/user/subscription") + if err != nil { + return err + } + if r.IsError() { + return &ApiError{ + StatusCode: r.StatusCode(), + Message: r.String(), + } + } + return nil + +} diff --git a/cli/internal/api/models/user_details.go b/cli/internal/api/models/user_details.go new file mode 100644 index 0000000000..259ff972b6 --- /dev/null +++ b/cli/internal/api/models/user_details.go @@ -0,0 +1,16 @@ +package models + +type UserDetails struct { + User struct { + ID int64 `json:"id"` + } `json:"user"` + Usage int64 `json:"usage"` + Email string `json:"email"` + + Subscription struct { + ExpiryTime int64 `json:"expiryTime"` + Storage int64 `json:"storage"` + ProductID string `json:"productID"` + PaymentProvider string `json:"paymentProvider"` + } `json:"subscription"` +} diff --git a/cli/internal/promt.go b/cli/internal/promt.go index 2e988ac243..fe2f61bde0 100644 --- a/cli/internal/promt.go +++ b/cli/internal/promt.go @@ -5,11 +5,12 @@ import ( "errors" "fmt" "github.com/ente-io/cli/internal/api" + "golang.org/x/term" "log" "os" + "regexp" + "strconv" "strings" - - "golang.org/x/term" ) func GetSensitiveField(label string) (string, error) { @@ -81,6 +82,79 @@ func GetCode(promptText string, length int) (string, error) { } } +// parseStorageSize parses a string representing a storage size (e.g., "500MB", "2GB") into bytes. +func parseStorageSize(input string) (int64, error) { + units := map[string]int64{ + "MB": 1 << 20, + "GB": 1 << 30, + "TB": 1 << 40, + } + re := regexp.MustCompile(`(?i)^(\d+(?:\.\d+)?)(MB|GB|TB)$`) + matches := re.FindStringSubmatch(input) + + if matches == nil { + return 0, errors.New("invalid format") + } + + number, err := strconv.ParseFloat(matches[1], 64) + if err != nil { + return 0, fmt.Errorf("invalid number: %s", matches[1]) + } + + unit := strings.ToUpper(matches[2]) + bytes := int64(number * float64(units[unit])) + + return bytes, nil +} + +func ConfirmAction(promptText string) (bool, error) { + for { + input, err := GetUserInput(promptText) + if err != nil { + return false, err + } + if input == "" { + log.Fatal("No input entered") + return false, errors.New("invalid input. Please enter 'y' or 'n'") + } + if input == "c" { + return false, errors.New("cancelled") + } + if input == "y" { + return true, nil + } + if input == "n" { + return false, nil + } + fmt.Println("Invalid input. Please enter 'y' or 'n'.") + } +} + +// GetStorageSize prompts the user for a storage size and returns the size in bytes. +func GetStorageSize(promptText string) (int64, error) { + for { + input, err := GetUserInput(promptText) + if err != nil { + return 0, err + } + if input == "" { + log.Fatal("No storage size entered") + return 0, errors.New("no storage size entered") + } + if input == "c" { + return 0, errors.New("storage size entry cancelled") + } + + bytes, err := parseStorageSize(input) + if err != nil { + fmt.Println("Invalid storage size format. Please use a valid format like '500MB', '2GB'.") + continue + } + + return bytes, nil + } +} + func GetExportDir() string { for { exportDir, err := GetUserInput("Enter export directory") diff --git a/cli/main.go b/cli/main.go index 957669f9d4..f9ad0fa067 100644 --- a/cli/main.go +++ b/cli/main.go @@ -86,7 +86,6 @@ func initConfig(cliConfigPath string) { viper.SetDefault("log.http", false) if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { - log.Printf("Config file not found; using defaults %s", cliConfigPath) } else { // Config file was found but another error was produced } diff --git a/cli/pkg/admin_actions.go b/cli/pkg/admin_actions.go new file mode 100644 index 0000000000..74152e5c54 --- /dev/null +++ b/cli/pkg/admin_actions.go @@ -0,0 +1,104 @@ +package pkg + +import ( + "context" + "fmt" + "github.com/ente-io/cli/internal" + "github.com/ente-io/cli/pkg/model" + "github.com/ente-io/cli/utils" + "log" + "strings" + "time" +) + +func (c *ClICtrl) GetUserId(ctx context.Context, params model.AdminActionForUser) error { + accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) + if err != nil { + return err + } + id, err := c.Client.GetUserIdFromEmail(accountCtx, params.UserEmail) + if err != nil { + return err + } + fmt.Println(id.User.ID) + return nil +} + +func (c *ClICtrl) UpdateFreeStorage(ctx context.Context, params model.AdminActionForUser) error { + accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) + if err != nil { + return err + } + userDetails, err := c.Client.GetUserIdFromEmail(accountCtx, params.UserEmail) + if err != nil { + return err + } + storageSize, err := internal.GetStorageSize("Enter a storage size (e.g.'5MB', '10GB', '2Tb'): ") + if err != nil { + log.Fatalf("Error: %v", err) + } + dateStr, err := internal.GetUserInput("Enter sub expiry date in YYYY-MM-DD format (e.g.'2040-12-31')") + if err != nil { + log.Fatalf("Error: %v", err) + } + date, err := _parseDateOrDateTime(dateStr) + if err != nil { + return err + } + + fmt.Printf("Updating storage for user %s to %s (old %s) with new expirty %s (old %s) \n", + params.UserEmail, + utils.ByteCountDecimalGIB(storageSize), utils.ByteCountDecimalGIB(userDetails.Subscription.Storage), + date.Format("2006-01-02"), + time.UnixMicro(userDetails.Subscription.ExpiryTime).Format("2006-01-02")) + // press y to confirm + confirmed, _ := internal.ConfirmAction("Are you sure you want to update the storage ('y' or 'n')?") + if !confirmed { + return nil + } else { + err := c.Client.UpdateFreePlanSub(accountCtx, userDetails, storageSize, date.UnixMicro()) + if err != nil { + return err + } else { + fmt.Println("Successfully updated storage and expiry date for user") + } + } + + return nil +} + +func (c *ClICtrl) buildAdminContext(ctx context.Context, adminEmail string) (context.Context, error) { + accounts, err := c.GetAccounts(ctx) + if err != nil { + return nil, err + } + var acc *model.Account + for _, a := range accounts { + if a.Email == adminEmail { + acc = &a + break + } + } + if acc == nil { + return nil, fmt.Errorf("account not found for %s, use `account list` to list accounts", adminEmail) + } + secretInfo, err := c.KeyHolder.LoadSecrets(*acc) + if err != nil { + return nil, err + } + accountCtx := c.buildRequestContext(ctx, *acc) + c.Client.AddToken(acc.AccountKey(), secretInfo.TokenStr()) + return accountCtx, nil +} + +func _parseDateOrDateTime(input string) (time.Time, error) { + var layout string + if strings.Contains(input, " ") { + // If the input contains a space, assume it's a date-time format + layout = "2006-01-02 15:04:05" + } else { + // If there's no space, assume it's just a date + layout = "2006-01-02" + } + return time.Parse(layout, input) +} diff --git a/cli/pkg/model/admin.go b/cli/pkg/model/admin.go new file mode 100644 index 0000000000..e4d14d75c2 --- /dev/null +++ b/cli/pkg/model/admin.go @@ -0,0 +1,6 @@ +package model + +type AdminActionForUser struct { + UserEmail string + AdminEmail string +} diff --git a/cli/utils/convert.go b/cli/utils/convert.go new file mode 100644 index 0000000000..5bd7c8026e --- /dev/null +++ b/cli/utils/convert.go @@ -0,0 +1,31 @@ +package utils + +import ( + "fmt" +) + +func ByteCountDecimal(b int64) string { + const unit = 1000 + if b < unit { + return fmt.Sprintf("%d B", b) + } + div, exp := int64(unit), 0 + for n := b / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp]) +} + +func ByteCountDecimalGIB(b int64) string { + const unit = 1024 + if b < unit { + return fmt.Sprintf("%d B", b) + } + div, exp := int64(unit), 0 + for n := b / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp]) +} diff --git a/cli/utils/time.go b/cli/utils/time.go index a86a9fc9f3..fcb61f8422 100644 --- a/cli/utils/time.go +++ b/cli/utils/time.go @@ -1,7 +1,6 @@ package utils import ( - "fmt" "log" "time" ) @@ -10,16 +9,3 @@ func TimeTrack(start time.Time, name string) { elapsed := time.Since(start) log.Printf("%s took %s", name, elapsed) } - -func ByteCountDecimal(b int64) string { - const unit = 1000 - if b < unit { - return fmt.Sprintf("%d B", b) - } - div, exp := int64(unit), 0 - for n := b / unit; n >= unit; n /= unit { - div *= unit - exp++ - } - return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp]) -} From b164b0df21f3653fccc682730ecdebead586fffd Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:08:19 +0530 Subject: [PATCH 236/391] [cli] By default, update sub to high storage & expiry --- cli/cmd/admin.go | 9 ++++++++- cli/config.yaml.example | 4 ++-- cli/pkg/admin_actions.go | 12 +++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/cli/cmd/admin.go b/cli/cmd/admin.go index 153736624c..7836528787 100644 --- a/cli/cmd/admin.go +++ b/cli/cmd/admin.go @@ -6,6 +6,7 @@ import ( "github.com/ente-io/cli/pkg/model" "github.com/spf13/cobra" "github.com/spf13/pflag" + "strings" ) var _adminCmd = &cobra.Command{ @@ -57,6 +58,7 @@ var _updateFreeUserStorage = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { recoverWithLog() var flags = &model.AdminActionForUser{} + noLimit := false cmd.Flags().VisitAll(func(f *pflag.Flag) { if f.Name == "admin-user" { flags.AdminEmail = f.Value.String() @@ -64,8 +66,11 @@ var _updateFreeUserStorage = &cobra.Command{ if f.Name == "user" { flags.UserEmail = f.Value.String() } + if f.Name == "no-limit" { + noLimit = strings.ToLower(f.Value.String()) == "true" + } }) - return ctrl.UpdateFreeStorage(context.Background(), *flags) + return ctrl.UpdateFreeStorage(context.Background(), *flags, noLimit) }, } @@ -79,5 +84,7 @@ func init() { _disable2faCmd.Flags().StringP("user", "u", "", "The email of the user to disable 2FA for. (required)") _updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") _updateFreeUserStorage.Flags().StringP("user", "u", "", "The email of the user to update subscription for. (required)") + // add a flag with no value --no-limit + _updateFreeUserStorage.Flags().String("no-limit", "True", "Set the storage limit to 100TB unlimited with 100 year expiry") _adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage) } diff --git a/cli/config.yaml.example b/cli/config.yaml.example index efd92c545c..a004036568 100644 --- a/cli/config.yaml.example +++ b/cli/config.yaml.example @@ -4,7 +4,7 @@ # - $ENTE_CLI_CONFIG_PATH/config.yaml endpoint: - api: "https://api.ente.io" + api: "http://localhost:8080" log: - http: false # log http requests and responses \ No newline at end of file + http: false # log status code & time taken by requests diff --git a/cli/pkg/admin_actions.go b/cli/pkg/admin_actions.go index 74152e5c54..c9ec006675 100644 --- a/cli/pkg/admin_actions.go +++ b/cli/pkg/admin_actions.go @@ -24,7 +24,7 @@ func (c *ClICtrl) GetUserId(ctx context.Context, params model.AdminActionForUser return nil } -func (c *ClICtrl) UpdateFreeStorage(ctx context.Context, params model.AdminActionForUser) error { +func (c *ClICtrl) UpdateFreeStorage(ctx context.Context, params model.AdminActionForUser, noLimit bool) error { accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) if err != nil { return err @@ -33,6 +33,16 @@ func (c *ClICtrl) UpdateFreeStorage(ctx context.Context, params model.AdminActio if err != nil { return err } + if noLimit { + // set storage to 100TB and expiry to + 100 years + err := c.Client.UpdateFreePlanSub(accountCtx, userDetails, 100*1024*1024*1024*1024, time.Now().AddDate(100, 0, 0).UnixMicro()) + if err != nil { + return err + } else { + fmt.Println("Successfully updated storage and expiry date for user") + } + return nil + } storageSize, err := internal.GetStorageSize("Enter a storage size (e.g.'5MB', '10GB', '2Tb'): ") if err != nil { log.Fatalf("Error: %v", err) From 0678e3129af8663b2b0aed05d79156ad7ced3f9c Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:09:03 +0530 Subject: [PATCH 237/391] [cli] generated docs --- cli/docs/generated/ente.md | 3 ++- cli/docs/generated/ente_account.md | 2 +- cli/docs/generated/ente_account_add.md | 2 +- cli/docs/generated/ente_account_get-token.md | 2 +- cli/docs/generated/ente_account_list.md | 2 +- cli/docs/generated/ente_account_update.md | 2 +- cli/docs/generated/ente_admin.md | 22 +++++++++++++++++++ cli/docs/generated/ente_admin_disable-2fa.md | 21 ++++++++++++++++++ cli/docs/generated/ente_admin_get-user-id.md | 21 ++++++++++++++++++ .../ente_admin_update-subscription.md | 22 +++++++++++++++++++ cli/docs/generated/ente_auth.md | 2 +- cli/docs/generated/ente_auth_decrypt.md | 2 +- cli/docs/generated/ente_export.md | 2 +- cli/docs/generated/ente_version.md | 2 +- 14 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 cli/docs/generated/ente_admin.md create mode 100644 cli/docs/generated/ente_admin_disable-2fa.md create mode 100644 cli/docs/generated/ente_admin_get-user-id.md create mode 100644 cli/docs/generated/ente_admin_update-subscription.md diff --git a/cli/docs/generated/ente.md b/cli/docs/generated/ente.md index 91e71e3797..4af6e2b5cf 100644 --- a/cli/docs/generated/ente.md +++ b/cli/docs/generated/ente.md @@ -20,8 +20,9 @@ ente [flags] ### SEE ALSO * [ente account](ente_account.md) - Manage account settings +* [ente admin](ente_admin.md) - Commands for admin actions * [ente auth](ente_auth.md) - Authenticator commands * [ente export](ente_export.md) - Starts the export process * [ente version](ente_version.md) - Prints the current version -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_account.md b/cli/docs/generated/ente_account.md index 402a1e2d2f..b30f748f02 100644 --- a/cli/docs/generated/ente_account.md +++ b/cli/docs/generated/ente_account.md @@ -16,4 +16,4 @@ Manage account settings * [ente account list](ente_account_list.md) - list configured accounts * [ente account update](ente_account_update.md) - Update an existing account's export directory -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_account_add.md b/cli/docs/generated/ente_account_add.md index b3c5194d30..b77362db91 100644 --- a/cli/docs/generated/ente_account_add.md +++ b/cli/docs/generated/ente_account_add.md @@ -16,4 +16,4 @@ ente account add [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_account_get-token.md b/cli/docs/generated/ente_account_get-token.md index 35baec9788..bacabbe0d2 100644 --- a/cli/docs/generated/ente_account_get-token.md +++ b/cli/docs/generated/ente_account_get-token.md @@ -18,4 +18,4 @@ ente account get-token [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_account_list.md b/cli/docs/generated/ente_account_list.md index f9e0afb591..a6ec1a0650 100644 --- a/cli/docs/generated/ente_account_list.md +++ b/cli/docs/generated/ente_account_list.md @@ -16,4 +16,4 @@ ente account list [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_account_update.md b/cli/docs/generated/ente_account_update.md index 22801c8054..680267362c 100644 --- a/cli/docs/generated/ente_account_update.md +++ b/cli/docs/generated/ente_account_update.md @@ -19,4 +19,4 @@ ente account update [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_admin.md b/cli/docs/generated/ente_admin.md new file mode 100644 index 0000000000..2bbc8ac128 --- /dev/null +++ b/cli/docs/generated/ente_admin.md @@ -0,0 +1,22 @@ +## ente admin + +Commands for admin actions + +### Synopsis + +Commands for admin actions like disable or enabling 2fa, bumping up the storage limit, etc. + +### Options + +``` + -h, --help help for admin +``` + +### SEE ALSO + +* [ente](ente.md) - CLI tool for exporting your photos from ente.io +* [ente admin disable-2fa](ente_admin_disable-2fa.md) - Disable 2fa for a user +* [ente admin get-user-id](ente_admin_get-user-id.md) - Get user id +* [ente admin update-subscription](ente_admin_update-subscription.md) - Update subscription for the free user + +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_admin_disable-2fa.md b/cli/docs/generated/ente_admin_disable-2fa.md new file mode 100644 index 0000000000..5ce2f4ff6f --- /dev/null +++ b/cli/docs/generated/ente_admin_disable-2fa.md @@ -0,0 +1,21 @@ +## ente admin disable-2fa + +Disable 2fa for a user + +``` +ente admin disable-2fa [flags] +``` + +### Options + +``` + -a, --admin-user string The email of the admin user. (required) + -h, --help help for disable-2fa + -u, --user string The email of the user to disable 2FA for. (required) +``` + +### SEE ALSO + +* [ente admin](ente_admin.md) - Commands for admin actions + +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_admin_get-user-id.md b/cli/docs/generated/ente_admin_get-user-id.md new file mode 100644 index 0000000000..8262beece4 --- /dev/null +++ b/cli/docs/generated/ente_admin_get-user-id.md @@ -0,0 +1,21 @@ +## ente admin get-user-id + +Get user id + +``` +ente admin get-user-id [flags] +``` + +### Options + +``` + -a, --admin-user string The email of the admin user. (required) + -h, --help help for get-user-id + -u, --user string The email of the user to fetch details for. (required) +``` + +### SEE ALSO + +* [ente admin](ente_admin.md) - Commands for admin actions + +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_admin_update-subscription.md b/cli/docs/generated/ente_admin_update-subscription.md new file mode 100644 index 0000000000..25f19359ce --- /dev/null +++ b/cli/docs/generated/ente_admin_update-subscription.md @@ -0,0 +1,22 @@ +## ente admin update-subscription + +Update subscription for the free user + +``` +ente admin update-subscription [flags] +``` + +### Options + +``` + -a, --admin-user string The email of the admin user. (required) + -h, --help help for update-subscription + --no-limit string Set the storage limit to 100TB unlimited with 100 year expiry (default "True") + -u, --user string The email of the user to update subscription for. (required) +``` + +### SEE ALSO + +* [ente admin](ente_admin.md) - Commands for admin actions + +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_auth.md b/cli/docs/generated/ente_auth.md index 69ac6e5ba0..694b6d369a 100644 --- a/cli/docs/generated/ente_auth.md +++ b/cli/docs/generated/ente_auth.md @@ -13,4 +13,4 @@ Authenticator commands * [ente](ente.md) - CLI tool for exporting your photos from ente.io * [ente auth decrypt](ente_auth_decrypt.md) - Decrypt authenticator export -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_auth_decrypt.md b/cli/docs/generated/ente_auth_decrypt.md index cdeb16364e..0a867292af 100644 --- a/cli/docs/generated/ente_auth_decrypt.md +++ b/cli/docs/generated/ente_auth_decrypt.md @@ -16,4 +16,4 @@ ente auth decrypt [input] [output] [flags] * [ente auth](ente_auth.md) - Authenticator commands -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_export.md b/cli/docs/generated/ente_export.md index ab06c646ad..6258087117 100644 --- a/cli/docs/generated/ente_export.md +++ b/cli/docs/generated/ente_export.md @@ -16,4 +16,4 @@ ente export [flags] * [ente](ente.md) - CLI tool for exporting your photos from ente.io -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 diff --git a/cli/docs/generated/ente_version.md b/cli/docs/generated/ente_version.md index 57c520e9b7..8dbc9bfc88 100644 --- a/cli/docs/generated/ente_version.md +++ b/cli/docs/generated/ente_version.md @@ -16,4 +16,4 @@ ente version [flags] * [ente](ente.md) - CLI tool for exporting your photos from ente.io -###### Auto generated by spf13/cobra on 8-Mar-2024 +###### Auto generated by spf13/cobra on 12-Mar-2024 From 4326409046911012e53d31583ebca57aba1a060d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 13 Mar 2024 10:21:58 +0530 Subject: [PATCH 238/391] [docs] Move the self hosting using external S3 buckets guide to independent page See: https://github.com/ente-io/ente/pull/1066 --- docs/docs/.vitepress/sidebar.ts | 4 + docs/docs/self-hosting/guides/external-s3.md | 239 +++++++++++++++++++ docs/docs/self-hosting/guides/index.md | 233 +----------------- 3 files changed, 248 insertions(+), 228 deletions(-) create mode 100644 docs/docs/self-hosting/guides/external-s3.md diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index 2145844d4a..78a6733f41 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -97,6 +97,10 @@ export const sidebar = [ text: "System requirements", link: "/self-hosting/guides/system-requirements", }, + { + text: "Using external S3", + link: "/self-hosting/guides/external-s3", + }, ], }, { diff --git a/docs/docs/self-hosting/guides/external-s3.md b/docs/docs/self-hosting/guides/external-s3.md new file mode 100644 index 0000000000..b56e1fa594 --- /dev/null +++ b/docs/docs/self-hosting/guides/external-s3.md @@ -0,0 +1,239 @@ +--- +title: External S3 buckets +description: + Self hosting Ente's server and photos web app when using an external S3 + bucket +--- + +# Hosting server and web app using external S3 + +This guide is for self hosting the server and the web application of Ente Photos +using docker compose and an external S3 bucket. So we assume that you already +have the keys and secrets for the S3 bucket. The plan is as follows: + +1. Create a `compose.yaml` file +2. Set up the `.credentials.env` file +3. Run `docker-compose up` +4. Create an account and increase storage quota +5. Fix potential CORS issue with your bucket + +## 1. Create a `compose.yaml` file + +After cloning the main repository with + +```bash +git clone https://github.com/ente-io/ente.git +# Or git clone git@github.com:ente-io/ente.git +cd ente +``` + +Create a `compose.yaml` file at the root of the project with the following +content (there is nothing to change here): + +```yaml +version: "3" +services: + museum: + build: + context: server + args: + GIT_COMMIT: local + ports: + - 8080:8080 # API + - 2112:2112 # Prometheus metrics + depends_on: + postgres: + condition: service_healthy + + # Wait for museum to ping pong before starting the webapp. + healthcheck: + test: [ + "CMD", + "echo", + "1", # I don't know what to put here + ] + environment: + # no need to touch these + ENTE_DB_HOST: postgres + ENTE_DB_PORT: 5432 + ENTE_DB_NAME: ente_db + ENTE_DB_USER: pguser + ENTE_DB_PASSWORD: pgpass + env_file: + - ./.credentials.env + volumes: + - custom-logs:/var/logs + networks: + - internal + + web: + build: + context: web + args: + GIT_SHA: local + ports: + - 8081:80 + - 8082:80 + depends_on: + museum: + condition: service_healthy + env_file: + - ./.credentials.env + + postgres: + image: postgres:12 + ports: + - 5432:5432 + environment: + POSTGRES_USER: pguser + POSTGRES_PASSWORD: pgpass + POSTGRES_DB: ente_db + # Wait for postgres to be accept connections before starting museum. + healthcheck: + test: ["CMD", "pg_isready", "-q", "-d", "ente_db", "-U", "pguser"] + interval: 1s + timeout: 5s + retries: 20 + volumes: + - postgres-data:/var/lib/postgresql/data + networks: + - internal +volumes: + custom-logs: + postgres-data: +networks: + internal: +``` + +It maybe be added in the future, but if it does not exist, create a `Dockerfile` +in the `web` directory with the following content: + +```Dockerfile +# syntax=docker/dockerfile:1 +FROM node:21-bookworm-slim as ente-builder +WORKDIR /app +RUN apt update && apt install -y ca-certificates && rm -rf /var/lib/apt/lists/* +COPY . . +RUN yarn install +ARG GIT_SHA=local +ENV GIT_SHA=$GIT_SHA +ENV NEXT_PUBLIC_ENTE_ENDPOINT=DOCKER_RUNTIME_REPLACE_ENDPOINT +ENV NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=DOCKER_RUNTIME_REPLACE_ALBUMS_ENDPOINT +RUN yarn build + + +FROM nginx:1.25-alpine-slim +COPY --from=ente-builder /app/apps/photos/out /usr/share/nginx/html +COPY < Date: Wed, 13 Mar 2024 11:12:06 +0530 Subject: [PATCH 239/391] Remove unused code for app-updates --- auth/ios/Podfile.lock | 6 - auth/lib/ui/settings/app_update_dialog.dart | 120 -------------------- auth/pubspec.lock | 8 -- auth/pubspec.yaml | 2 - 4 files changed, 136 deletions(-) diff --git a/auth/ios/Podfile.lock b/auth/ios/Podfile.lock index dc7d8d0436..9e781fd489 100644 --- a/auth/ios/Podfile.lock +++ b/auth/ios/Podfile.lock @@ -71,8 +71,6 @@ PODS: - move_to_background (0.0.1): - Flutter - MTBBarcodeScanner (5.0.11) - - open_filex (0.0.2): - - Flutter - OrderedSet (5.0.0) - package_info_plus (0.4.5): - Flutter @@ -126,7 +124,6 @@ DEPENDENCIES: - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`) - move_to_background (from `.symlinks/plugins/move_to_background/ios`) - - open_filex (from `.symlinks/plugins/open_filex/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - privacy_screen (from `.symlinks/plugins/privacy_screen/ios`) @@ -183,8 +180,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/local_auth_ios/ios" move_to_background: :path: ".symlinks/plugins/move_to_background/ios" - open_filex: - :path: ".symlinks/plugins/open_filex/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: @@ -226,7 +221,6 @@ SPEC CHECKSUMS: local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605 move_to_background: 39a5b79b26d577b0372cbe8a8c55e7aa9fcd3a2d MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb - open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4 OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 diff --git a/auth/lib/ui/settings/app_update_dialog.dart b/auth/lib/ui/settings/app_update_dialog.dart index 5d05dddc5c..12049017c2 100644 --- a/auth/lib/ui/settings/app_update_dialog.dart +++ b/auth/lib/ui/settings/app_update_dialog.dart @@ -1,14 +1,7 @@ -import 'dart:io'; - -import 'package:ente_auth/core/configuration.dart'; -import 'package:ente_auth/core/network.dart'; -import 'package:ente_auth/ente_theme_data.dart'; import 'package:ente_auth/l10n/l10n.dart'; import 'package:ente_auth/services/update_service.dart'; import 'package:ente_auth/theme/ente_theme.dart'; import 'package:flutter/material.dart'; -import 'package:logging/logging.dart'; -import 'package:open_filex/open_filex.dart'; import 'package:url_launcher/url_launcher_string.dart'; class AppUpdateDialog extends StatefulWidget { @@ -114,116 +107,3 @@ class _AppUpdateDialogState extends State { ); } } - -class ApkDownloaderDialog extends StatefulWidget { - final LatestVersionInfo? versionInfo; - - const ApkDownloaderDialog(this.versionInfo, {Key? key}) : super(key: key); - - @override - State createState() => _ApkDownloaderDialogState(); -} - -class _ApkDownloaderDialogState extends State { - String? _saveUrl; - double? _downloadProgress; - - @override - void initState() { - super.initState(); - _saveUrl = Configuration.instance.getTempDirectory() + - "ente-" + - widget.versionInfo!.name! + - ".apk"; - _downloadApk(); - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async => false, - child: AlertDialog( - title: const Text( - "Downloading...", - style: TextStyle( - fontSize: 16, - ), - textAlign: TextAlign.center, - ), - content: LinearProgressIndicator( - value: _downloadProgress, - valueColor: AlwaysStoppedAnimation( - Theme.of(context).colorScheme.alternativeColor, - ), - ), - ), - ); - } - - Future _downloadApk() async { - try { - if (!File(_saveUrl!).existsSync()) { - await Network.instance.getDio().download( - widget.versionInfo!.url!, - _saveUrl, - onReceiveProgress: (count, _) { - setState(() { - _downloadProgress = count / widget.versionInfo!.size!; - }); - }, - ); - } - Navigator.of(context, rootNavigator: true).pop('dialog'); - // ignore: unawaited_futures - OpenFilex.open(_saveUrl); - } catch (e) { - Logger("ApkDownloader").severe(e); - final AlertDialog alert = AlertDialog( - title: const Text("Sorry"), - content: const Text("The download could not be completed"), - actions: [ - TextButton( - child: const Text( - "Ignore", - style: TextStyle( - color: Colors.white, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - Navigator.of(context, rootNavigator: true).pop('dialog'); - }, - ), - TextButton( - child: Text( - "Retry", - style: TextStyle( - color: Theme.of(context).colorScheme.alternativeColor, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - Navigator.of(context, rootNavigator: true).pop('dialog'); - showDialog( - context: context, - builder: (BuildContext context) { - return ApkDownloaderDialog(widget.versionInfo); - }, - barrierDismissible: false, - ); - }, - ), - ], - ); - // ignore: unawaited_futures - showDialog( - context: context, - builder: (BuildContext context) { - return alert; - }, - barrierColor: Colors.black87, - ); - return; - } - } -} diff --git a/auth/pubspec.lock b/auth/pubspec.lock index 7f0c7cf0b4..4514e503ca 100644 --- a/auth/pubspec.lock +++ b/auth/pubspec.lock @@ -879,14 +879,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" - open_filex: - dependency: "direct main" - description: - name: open_filex - sha256: "854aefd72dfd74219dc8c8d1767c34ec1eae64b8399a5be317bddb1ec2108915" - url: "https://pub.dev" - source: hosted - version: "4.3.2" otp: dependency: "direct main" description: diff --git a/auth/pubspec.yaml b/auth/pubspec.yaml index 042e78512a..5e78084078 100644 --- a/auth/pubspec.yaml +++ b/auth/pubspec.yaml @@ -54,13 +54,11 @@ dependencies: intl: ^0.18.0 json_annotation: ^4.5.0 local_auth: ^2.1.7 - local_auth_android: ^1.0.31 local_auth_ios: ^1.1.3 logging: ^1.0.1 modal_bottom_sheet: ^3.0.0-pre move_to_background: ^1.0.2 - open_filex: ^4.3.2 otp: ^3.1.1 package_info_plus: ^4.1.0 password_strength: ^0.2.0 From 26b162c8dc12bdd65a098b7d601a8aa78083bf1f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 13 Mar 2024 10:58:01 +0530 Subject: [PATCH 240/391] [web] Allow running the build outside of a git repository This was found useful by @Bramas when building a Dockerfile of the web app itself. See https://github.com/ente-io/ente/pull/1065. Now, the GIT_SHA environment variable can just be undefined if we're not in a git repository, and the code using it deals with that case explicitly. **Tested by** Temporarily inverted the isDevBuild flag, tehn 1. Ran the build normally and verified that the SHA continued to appear in the logs. 2. Ran the build after copying to a standalone folder without an associated git repository and verified that the SHA was skipped without causing the build to fail. --- docs/docs/self-hosting/guides/external-s3.md | 4 ---- web/packages/next/next.config.base.js | 24 ++++++++++++++------ web/packages/shared/logging/web.ts | 5 ++-- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/docs/docs/self-hosting/guides/external-s3.md b/docs/docs/self-hosting/guides/external-s3.md index b56e1fa594..6f7e3c4482 100644 --- a/docs/docs/self-hosting/guides/external-s3.md +++ b/docs/docs/self-hosting/guides/external-s3.md @@ -69,8 +69,6 @@ services: web: build: context: web - args: - GIT_SHA: local ports: - 8081:80 - 8082:80 @@ -115,8 +113,6 @@ WORKDIR /app RUN apt update && apt install -y ca-certificates && rm -rf /var/lib/apt/lists/* COPY . . RUN yarn install -ARG GIT_SHA=local -ENV GIT_SHA=$GIT_SHA ENV NEXT_PUBLIC_ENTE_ENDPOINT=DOCKER_RUNTIME_REPLACE_ENDPOINT ENV NEXT_PUBLIC_ENTE_ALBUMS_ENDPOINT=DOCKER_RUNTIME_REPLACE_ALBUMS_ENDPOINT RUN yarn build diff --git a/web/packages/next/next.config.base.js b/web/packages/next/next.config.base.js index ef7b65facf..1f96ee3b75 100644 --- a/web/packages/next/next.config.base.js +++ b/web/packages/next/next.config.base.js @@ -12,12 +12,22 @@ const cp = require("child_process"); -const gitSHA = cp - .execSync("git rev-parse --short HEAD", { - cwd: __dirname, - encoding: "utf8", - }) - .trimEnd(); +/** + * Return the current commit ID if we're running inside a git repository. + */ +const gitSHA = () => { + // Allow the command to fail. gitSHA will be an empty string in such cases. + // This allows us to run the build even when we're outside of a git context. + const result = cp + .execSync("git rev-parse --short HEAD 2>/dev/null || true", { + cwd: __dirname, + encoding: "utf8", + }) + .trimEnd(); + // Convert empty strings (e.g. when the `|| true` part of the above execSync + // comes into play) to undefined. + return result ? result : undefined; +}; /** * Configuration for the Next.js build @@ -42,7 +52,7 @@ const nextConfig = { // Add environment variables to the JavaScript bundle. They will be // available as `process.env.VAR_NAME` to our code. env: { - GIT_SHA: gitSHA, + GIT_SHA: gitSHA(), }, // https://dev.to/marcinwosinek/how-to-add-resolve-fallback-to-webpack-5-in-nextjs-10-i6j diff --git a/web/packages/shared/logging/web.ts b/web/packages/shared/logging/web.ts index 2354067350..7c9e7e2ed9 100644 --- a/web/packages/shared/logging/web.ts +++ b/web/packages/shared/logging/web.ts @@ -74,9 +74,10 @@ export const logStartupMessage = async (appId: string) => { // TODO (MR): Remove the need to lowercase it, change the enum itself. const appIdL = appId.toLowerCase(); const userID = (getData(LS_KEYS.USER) as User)?.id; - const buildId = isDevBuild ? "dev" : `git ${process.env.GIT_SHA}`; + const sha = process.env.GIT_SHA; + const buildId = isDevBuild ? "dev " : sha ? `git ${sha} ` : ""; - addLogLine(`ente-${appIdL}-web ${buildId} uid ${userID}`); + addLogLine(`ente-${appIdL}-web ${buildId}uid ${userID}`); }; function getLogs(): Log[] { From d5164693ff923b0b02744ba40f788dbf9bbcae26 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 13 Mar 2024 11:17:53 +0530 Subject: [PATCH 241/391] Fix vitepress warning Change the syntax highlighting of the `env` code block from `env` to `sh` because currently vite press doesn't support the env language and instead complains > The language 'env' is not loaded, falling back to 'txt' for syntax highlighting. --- docs/docs/self-hosting/guides/external-s3.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/docs/self-hosting/guides/external-s3.md b/docs/docs/self-hosting/guides/external-s3.md index 6f7e3c4482..40b4017247 100644 --- a/docs/docs/self-hosting/guides/external-s3.md +++ b/docs/docs/self-hosting/guides/external-s3.md @@ -160,7 +160,10 @@ RUN chmod +x /docker-entrypoint.d/replace_ente_endpoints.sh Create a `.credentials.env` file at the root of the project with the following content (here you need to set the correct value of each variable): -```env + + +```sh # run `go run tools/gen-random-keys/main.go` in the server directory to generate the keys ENTE_KEY_ENCRYPTION= ENTE_KEY_HASH= From 773f4cdca2cd21fe537bba7536075b3dfd067b86 Mon Sep 17 00:00:00 2001 From: Ashil <77285023+ashilkn@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:20:20 +0530 Subject: [PATCH 242/391] [mobile][photos] Fix missing hero animation (#1064) ## Description Sometimes, when opening an image from gallery, the hero animation fails to happen. This PR fixes this issue. https://github.com/ente-io/ente/assets/77285023/2ee40ec8-58d0-4ca1-82fb-1be96581137b ## Tests - [x] Didn't break hero animations of videos, it almost stays the same. --- mobile/lib/ui/viewer/file/zoomable_image.dart | 34 +++++++++++++++++++ .../component/gallery_file_widget.dart | 8 +++++ 2 files changed, 42 insertions(+) diff --git a/mobile/lib/ui/viewer/file/zoomable_image.dart b/mobile/lib/ui/viewer/file/zoomable_image.dart index ef28a98ee5..933ff748a3 100644 --- a/mobile/lib/ui/viewer/file/zoomable_image.dart +++ b/mobile/lib/ui/viewer/file/zoomable_image.dart @@ -104,6 +104,40 @@ class _ZoomableImageState extends State { tag: widget.tagPrefix! + _photo.tag, ), backgroundDecoration: widget.backgroundDecoration as BoxDecoration?, + loadingBuilder: (context, event) { + // This is to make sure the hero anitmation animates and fits in the + //dimensions of the image on screen. + final screenDimensions = MediaQuery.sizeOf(context); + late final double screenRelativeImageWidth; + late final double screenRelativeImageHeight; + final screenWidth = screenDimensions.width; + final screenHeight = screenDimensions.height; + + final aspectRatioOfScreen = screenWidth / screenHeight; + final aspectRatioOfImage = _photo.width / _photo.height; + + if (aspectRatioOfImage > aspectRatioOfScreen) { + screenRelativeImageWidth = screenWidth; + screenRelativeImageHeight = screenWidth / aspectRatioOfImage; + } else if (aspectRatioOfImage < aspectRatioOfScreen) { + screenRelativeImageHeight = screenHeight; + screenRelativeImageWidth = screenHeight * aspectRatioOfImage; + } else { + screenRelativeImageWidth = screenWidth; + screenRelativeImageHeight = screenHeight; + } + + return Center( + child: SizedBox( + width: screenRelativeImageWidth, + height: screenRelativeImageHeight, + child: Hero( + tag: widget.tagPrefix! + _photo.tag, + child: const EnteLoadingWidget(), + ), + ), + ); + }, ), ); } else { diff --git a/mobile/lib/ui/viewer/gallery/component/gallery_file_widget.dart b/mobile/lib/ui/viewer/gallery/component/gallery_file_widget.dart index 142f4427c4..c6b89de0b9 100644 --- a/mobile/lib/ui/viewer/gallery/component/gallery_file_widget.dart +++ b/mobile/lib/ui/viewer/gallery/component/gallery_file_widget.dart @@ -73,6 +73,14 @@ class GalleryFileWidget extends StatelessWidget { borderRadius: BorderRadius.circular(1), child: Hero( tag: heroTag, + flightShuttleBuilder: ( + flightContext, + animation, + flightDirection, + fromHeroContext, + toHeroContext, + ) => + thumbnailWidget, transitionOnUserGestures: true, child: isFileSelected ? ColorFiltered( From 0c1c0ad4007453d316028a6adf9f58b5b369d5b6 Mon Sep 17 00:00:00 2001 From: Ashil <77285023+ashilkn@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:20:50 +0530 Subject: [PATCH 243/391] [mobile][photos] Home widget UI tweaks (#1060) --- mobile/lib/services/home_widget_service.dart | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/mobile/lib/services/home_widget_service.dart b/mobile/lib/services/home_widget_service.dart index 1d6892bb81..c8082b448a 100644 --- a/mobile/lib/services/home_widget_service.dart +++ b/mobile/lib/services/home_widget_service.dart @@ -1,6 +1,8 @@ import "dart:math"; +import "package:figma_squircle/figma_squircle.dart"; import "package:flutter/material.dart"; +import "package:flutter/scheduler.dart"; import 'package:home_widget/home_widget.dart' as hw; import "package:logging/logging.dart"; import "package:photos/core/configuration.dart"; @@ -95,13 +97,18 @@ class HomeWidgetService { await PreloadImage.loadImage(img.image); - final widget = ClipRRect( - borderRadius: BorderRadius.circular(32), + final platformBrightness = + SchedulerBinding.instance.platformDispatcher.platformBrightness; + + final widget = ClipSmoothRect( + radius: SmoothBorderRadius(cornerRadius: 32, cornerSmoothing: 1), child: Container( width: size, height: size, decoration: BoxDecoration( - color: Colors.black, + color: platformBrightness == Brightness.light + ? const Color.fromRGBO(251, 251, 251, 1) + : const Color.fromRGBO(27, 27, 27, 1), image: DecorationImage(image: img.image, fit: BoxFit.cover), ), ), From be3b4dc7bab9dc7392763e6a07bf01e55dcb5b3c Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 11:21:36 +0530 Subject: [PATCH 244/391] Open the link to Github APK instead of downloading it in-app --- mobile/lib/ui/settings/app_update_dialog.dart | 143 +----------------- mobile/pubspec.yaml | 2 - 2 files changed, 4 insertions(+), 141 deletions(-) diff --git a/mobile/lib/ui/settings/app_update_dialog.dart b/mobile/lib/ui/settings/app_update_dialog.dart index 124b87927c..8038b7fa58 100644 --- a/mobile/lib/ui/settings/app_update_dialog.dart +++ b/mobile/lib/ui/settings/app_update_dialog.dart @@ -1,8 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:logging/logging.dart'; -import 'package:photos/core/configuration.dart'; -import 'package:photos/core/network/network.dart'; -import 'package:photos/ente_theme_data.dart'; import "package:photos/generated/l10n.dart"; import 'package:photos/services/update_service.dart'; import 'package:photos/theme/ente_theme.dart'; @@ -66,16 +62,12 @@ class _AppUpdateDialogState extends State { const Padding(padding: EdgeInsets.all(8)), ButtonWidget( buttonType: ButtonType.primary, - labelText: S.of(context).update, + labelText: S.of(context).download, onTap: () async { - Navigator.pop(context); // ignore: unawaited_futures - showDialog( - context: context, - builder: (BuildContext context) { - return ApkDownloaderDialog(widget.latestVersionInfo); - }, - barrierDismissible: false, + launchUrlString( + widget.latestVersionInfo!.url, + mode: LaunchMode.externalApplication, ); }, ), @@ -87,22 +79,6 @@ class _AppUpdateDialogState extends State { Navigator.of(context).pop(); }, ), - const Padding(padding: EdgeInsets.all(8)), - Center( - child: InkWell( - child: Text( - S.of(context).installManually, - style: Theme.of(context) - .textTheme - .bodySmall! - .copyWith(decoration: TextDecoration.underline), - ), - onTap: () => launchUrlString( - widget.latestVersionInfo!.url, - mode: LaunchMode.externalApplication, - ), - ), - ), ], ); final shouldForceUpdate = @@ -135,114 +111,3 @@ class _AppUpdateDialogState extends State { ); } } - -class ApkDownloaderDialog extends StatefulWidget { - final LatestVersionInfo? versionInfo; - - const ApkDownloaderDialog(this.versionInfo, {Key? key}) : super(key: key); - - @override - State createState() => _ApkDownloaderDialogState(); -} - -class _ApkDownloaderDialogState extends State { - String? _saveUrl; - double? _downloadProgress; - - @override - void initState() { - super.initState(); - _saveUrl = Configuration.instance.getTempDirectory() + - "ente-" + - widget.versionInfo!.name + - ".apk"; - _downloadApk(); - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async => false, - child: AlertDialog( - title: Text( - S.of(context).downloading, - style: const TextStyle( - fontSize: 16, - ), - textAlign: TextAlign.center, - ), - content: LinearProgressIndicator( - value: _downloadProgress, - valueColor: AlwaysStoppedAnimation( - Theme.of(context).colorScheme.greenAlternative, - ), - ), - ), - ); - } - - Future _downloadApk() async { - try { - await NetworkClient.instance.getDio().download( - widget.versionInfo!.url, - _saveUrl, - onReceiveProgress: (count, _) { - setState(() { - _downloadProgress = count / widget.versionInfo!.size; - }); - }, - ); - Navigator.of(context, rootNavigator: true).pop('dialog'); - // OpenFile.open(_saveUrl); - } catch (e) { - Logger("ApkDownloader").severe(e); - final AlertDialog alert = AlertDialog( - title: Text(S.of(context).sorry), - content: Text(S.of(context).theDownloadCouldNotBeCompleted), - actions: [ - TextButton( - child: Text( - S.of(context).ignoreUpdate, - style: const TextStyle( - color: Colors.white, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - Navigator.of(context, rootNavigator: true).pop('dialog'); - }, - ), - TextButton( - child: Text( - S.of(context).retry, - style: TextStyle( - color: Theme.of(context).colorScheme.greenAlternative, - ), - ), - onPressed: () { - Navigator.of(context, rootNavigator: true).pop('dialog'); - Navigator.of(context, rootNavigator: true).pop('dialog'); - showDialog( - context: context, - builder: (BuildContext context) { - return ApkDownloaderDialog(widget.versionInfo); - }, - barrierDismissible: false, - ); - }, - ), - ], - ); - - // ignore: unawaited_futures - showDialog( - context: context, - builder: (BuildContext context) { - return alert; - }, - barrierColor: Colors.black87, - ); - return; - } - } -} diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 2ea9bb3cef..ccee2aae9c 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -122,8 +122,6 @@ dependencies: motionphoto: git: "https://github.com/ente-io/motionphoto.git" move_to_background: ^1.0.2 - - # open_file: ^3.2.1 onnxruntime: git: url: https://github.com/ente-io/onnxruntime.git From 8f525cb88d899d84e513d618fdce050bc8be798b Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 11:27:24 +0530 Subject: [PATCH 245/391] Update Github Action for Photos --- .github/workflows/mobile-release.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mobile-release.yml b/.github/workflows/mobile-release.yml index 3868da64a2..fc910fbb89 100644 --- a/.github/workflows/mobile-release.yml +++ b/.github/workflows/mobile-release.yml @@ -39,7 +39,9 @@ jobs: encodedString: ${{ secrets.SIGNING_KEY_PHOTOS }} - name: Build independent APK - run: flutter build apk --release --flavor independent && mv build/app/outputs/flutter-apk/app-independent-release.apk build/app/outputs/flutter-apk/ente.apk + run: | + flutter build apk --release --flavor independent + mv build/app/outputs/flutter-apk/app-independent-release.apk build/app/outputs/flutter-apk/ente-${{ github.ref_name }}.apk env: SIGNING_KEY_PATH: "/home/runner/work/_temp/keystore/ente_photos_key.jks" SIGNING_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS_PHOTOS }} @@ -52,5 +54,5 @@ jobs: - name: Create a draft GitHub release uses: ncipollo/release-action@v1 with: - artifacts: "mobile/build/app/outputs/flutter-apk/ente.apk,mobile/build/app/outputs/flutter-apk/sha256sum" + artifacts: "mobile/build/app/outputs/flutter-apk/ente-${{ github.ref_name }}.apk,mobile/build/app/outputs/flutter-apk/sha256sum" draft: true From f7077c2b11af9d78c0a25802517c0db6b5518284 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Wed, 13 Mar 2024 10:42:51 +0530 Subject: [PATCH 246/391] [docs] Update guide to build mobile app --- docs/docs/self-hosting/guides/mobile-build.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/docs/self-hosting/guides/mobile-build.md b/docs/docs/self-hosting/guides/mobile-build.md index 597f27db1a..32bba3aa7a 100644 --- a/docs/docs/self-hosting/guides/mobile-build.md +++ b/docs/docs/self-hosting/guides/mobile-build.md @@ -24,9 +24,14 @@ As a short summary, you can install Flutter and build the Photos app this way: cd ente/mobile git submodule update --init --recursive flutter pub get +# Android +flutter run --dart-define=endpoint=http://localhost:8080 --flavor independent --debug -t lib/main.dart +# iOS flutter run --dart-define=endpoint=http://localhost:8080 ``` + + Or for the auth app: ```sh @@ -34,4 +39,16 @@ cd ente/auth git submodule update --init --recursive flutter pub get flutter run --dart-define=endpoint=http://localhost:8080 +# Android +flutter run --dart-define=endpoint=http://localhost:8080 --flavor independent --debug -t lib/main.dart +# iOS +flutter run --dart-define=endpoint=http://localhost:8080 ``` + +## How to build non-debug builds +For building APK, [setup your + keystore](https://docs.flutter.dev/deployment/android#create-an-upload-keystore) + and run +```sh +flutter build apk --release --flavor independent -t lib/main.dart + ``` From c7d7d436c37886a90bbc4ad00474b2108e37c18d Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:03:23 +0530 Subject: [PATCH 247/391] [docs] Add guide to connect CLI to self-hosted instance --- .../guides/custom-server/index.md | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/docs/self-hosting/guides/custom-server/index.md b/docs/docs/self-hosting/guides/custom-server/index.md index a2409642a1..276cb51954 100644 --- a/docs/docs/self-hosting/guides/custom-server/index.md +++ b/docs/docs/self-hosting/guides/custom-server/index.md @@ -17,3 +17,29 @@ configure the endpoint the app should be connecting to. > > This is only supported by the Ente Auth app currently. We'll add this same > functionality to the Ente Photos app soon. + +--- + +# CLI + +Define a config.yaml and put it either in the same directory as CLI or path defined in env variable `ENTE_CLI_CONFIG_PATH` + +```yaml +endpoint: + api: "http://localhost:8080" +``` + +You should be able to [add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), and subsequently increase the [storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) using the CLI. + +For the admin actions, you can create `server/museum.yaml`, and whitelist add the admin userID `internal.admins`. See [local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1) in the server source code for details about how to define this. + +You can use [account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md) command to find the user id of any account. + +```yaml +.... +internal: + admins: + # - 1580559962386440 + +.... +``` \ No newline at end of file From 4325de6fdea136c6778f4d38740c3f9b79528bf3 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:05:29 +0530 Subject: [PATCH 248/391] [mob] Remove .env.example --- mobile/.env.example | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 mobile/.env.example diff --git a/mobile/.env.example b/mobile/.env.example deleted file mode 100644 index 329eacea7d..0000000000 --- a/mobile/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -endpoint=https://api.ente.io/ -urltemplate=YOUR_URL_TEMPLATE -apikey=YOUR_API_KEY From 2711a227fc8eb6872b10713c162e5eb2d8c56727 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:31:56 +0530 Subject: [PATCH 249/391] [cli] Update gen docs + add docs/selfhost.md --- cli/cmd/admin.go | 2 +- cli/docs/generated/ente.md | 2 +- cli/docs/generated/ente_account.md | 2 +- cli/docs/generated/ente_account_add.md | 2 +- cli/docs/generated/ente_account_get-token.md | 2 +- cli/docs/generated/ente_account_list.md | 2 +- cli/docs/generated/ente_account_update.md | 2 +- cli/docs/generated/ente_admin.md | 2 +- cli/docs/generated/ente_admin_disable-2fa.md | 2 +- cli/docs/generated/ente_admin_get-user-id.md | 2 +- .../ente_admin_update-subscription.md | 4 +-- cli/docs/generated/ente_auth.md | 2 +- cli/docs/generated/ente_auth_decrypt.md | 2 +- cli/docs/generated/ente_export.md | 2 +- cli/docs/generated/ente_version.md | 2 +- cli/docs/selfhost.md | 27 +++++++++++++++++++ 16 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 cli/docs/selfhost.md diff --git a/cli/cmd/admin.go b/cli/cmd/admin.go index 7836528787..0e41bbfe2c 100644 --- a/cli/cmd/admin.go +++ b/cli/cmd/admin.go @@ -85,6 +85,6 @@ func init() { _updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") _updateFreeUserStorage.Flags().StringP("user", "u", "", "The email of the user to update subscription for. (required)") // add a flag with no value --no-limit - _updateFreeUserStorage.Flags().String("no-limit", "True", "Set the storage limit to 100TB unlimited with 100 year expiry") + _updateFreeUserStorage.Flags().String("no-limit", "True", "When true, sets 100TB as storage limit, and expiry to current date + 100 years") _adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage) } diff --git a/cli/docs/generated/ente.md b/cli/docs/generated/ente.md index 4af6e2b5cf..6d0263ce42 100644 --- a/cli/docs/generated/ente.md +++ b/cli/docs/generated/ente.md @@ -25,4 +25,4 @@ ente [flags] * [ente export](ente_export.md) - Starts the export process * [ente version](ente_version.md) - Prints the current version -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_account.md b/cli/docs/generated/ente_account.md index b30f748f02..ec26f95577 100644 --- a/cli/docs/generated/ente_account.md +++ b/cli/docs/generated/ente_account.md @@ -16,4 +16,4 @@ Manage account settings * [ente account list](ente_account_list.md) - list configured accounts * [ente account update](ente_account_update.md) - Update an existing account's export directory -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_account_add.md b/cli/docs/generated/ente_account_add.md index b77362db91..74b2c23f9c 100644 --- a/cli/docs/generated/ente_account_add.md +++ b/cli/docs/generated/ente_account_add.md @@ -16,4 +16,4 @@ ente account add [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_account_get-token.md b/cli/docs/generated/ente_account_get-token.md index bacabbe0d2..58ef3e7cd2 100644 --- a/cli/docs/generated/ente_account_get-token.md +++ b/cli/docs/generated/ente_account_get-token.md @@ -18,4 +18,4 @@ ente account get-token [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_account_list.md b/cli/docs/generated/ente_account_list.md index a6ec1a0650..3fc6fbc2e8 100644 --- a/cli/docs/generated/ente_account_list.md +++ b/cli/docs/generated/ente_account_list.md @@ -16,4 +16,4 @@ ente account list [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_account_update.md b/cli/docs/generated/ente_account_update.md index 680267362c..04c4418e70 100644 --- a/cli/docs/generated/ente_account_update.md +++ b/cli/docs/generated/ente_account_update.md @@ -19,4 +19,4 @@ ente account update [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_admin.md b/cli/docs/generated/ente_admin.md index 2bbc8ac128..91e70324d0 100644 --- a/cli/docs/generated/ente_admin.md +++ b/cli/docs/generated/ente_admin.md @@ -19,4 +19,4 @@ Commands for admin actions like disable or enabling 2fa, bumping up the storage * [ente admin get-user-id](ente_admin_get-user-id.md) - Get user id * [ente admin update-subscription](ente_admin_update-subscription.md) - Update subscription for the free user -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_admin_disable-2fa.md b/cli/docs/generated/ente_admin_disable-2fa.md index 5ce2f4ff6f..19183fdfe6 100644 --- a/cli/docs/generated/ente_admin_disable-2fa.md +++ b/cli/docs/generated/ente_admin_disable-2fa.md @@ -18,4 +18,4 @@ ente admin disable-2fa [flags] * [ente admin](ente_admin.md) - Commands for admin actions -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_admin_get-user-id.md b/cli/docs/generated/ente_admin_get-user-id.md index 8262beece4..0151a3ec85 100644 --- a/cli/docs/generated/ente_admin_get-user-id.md +++ b/cli/docs/generated/ente_admin_get-user-id.md @@ -18,4 +18,4 @@ ente admin get-user-id [flags] * [ente admin](ente_admin.md) - Commands for admin actions -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_admin_update-subscription.md b/cli/docs/generated/ente_admin_update-subscription.md index 25f19359ce..30339acf20 100644 --- a/cli/docs/generated/ente_admin_update-subscription.md +++ b/cli/docs/generated/ente_admin_update-subscription.md @@ -11,7 +11,7 @@ ente admin update-subscription [flags] ``` -a, --admin-user string The email of the admin user. (required) -h, --help help for update-subscription - --no-limit string Set the storage limit to 100TB unlimited with 100 year expiry (default "True") + --no-limit string When true, sets 100TB as storage limit, and expiry to current date + 100 years (default "True") -u, --user string The email of the user to update subscription for. (required) ``` @@ -19,4 +19,4 @@ ente admin update-subscription [flags] * [ente admin](ente_admin.md) - Commands for admin actions -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_auth.md b/cli/docs/generated/ente_auth.md index 694b6d369a..4a64a944dd 100644 --- a/cli/docs/generated/ente_auth.md +++ b/cli/docs/generated/ente_auth.md @@ -13,4 +13,4 @@ Authenticator commands * [ente](ente.md) - CLI tool for exporting your photos from ente.io * [ente auth decrypt](ente_auth_decrypt.md) - Decrypt authenticator export -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_auth_decrypt.md b/cli/docs/generated/ente_auth_decrypt.md index 0a867292af..1203319e9c 100644 --- a/cli/docs/generated/ente_auth_decrypt.md +++ b/cli/docs/generated/ente_auth_decrypt.md @@ -16,4 +16,4 @@ ente auth decrypt [input] [output] [flags] * [ente auth](ente_auth.md) - Authenticator commands -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_export.md b/cli/docs/generated/ente_export.md index 6258087117..fb4cc6541b 100644 --- a/cli/docs/generated/ente_export.md +++ b/cli/docs/generated/ente_export.md @@ -16,4 +16,4 @@ ente export [flags] * [ente](ente.md) - CLI tool for exporting your photos from ente.io -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/generated/ente_version.md b/cli/docs/generated/ente_version.md index 8dbc9bfc88..0254e2ebd2 100644 --- a/cli/docs/generated/ente_version.md +++ b/cli/docs/generated/ente_version.md @@ -16,4 +16,4 @@ ente version [flags] * [ente](ente.md) - CLI tool for exporting your photos from ente.io -###### Auto generated by spf13/cobra on 12-Mar-2024 +###### Auto generated by spf13/cobra on 13-Mar-2024 diff --git a/cli/docs/selfhost.md b/cli/docs/selfhost.md new file mode 100644 index 0000000000..d38f0325a5 --- /dev/null +++ b/cli/docs/selfhost.md @@ -0,0 +1,27 @@ +## Self Hosting +If you are self-hosting the server, you can still configure CLI to export data & perform basic admin actions. + +To do this, first configure the CLI to point to your server. +Define a config.yaml and put it either in the same directory as CLI binary or path defined in env variable `ENTE_CLI_CONFIG_PATH` + +```yaml +endpoint: + api: "http://localhost:8080" +``` + +You should be able to [add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), and subsequently increase the [storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) using the CLI. + + +For the admin actions, you first need to whitelist admin users. You can create `server/museum.yaml`, and whitelist add the admin userID `internal.admins`. See [local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1) in the server source code for details about how to define this. + +You can use [account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md) command to find the user id of any account. + +```yaml +# .... + +internal: + admins: + # - 1580559962386440 + +# .... +``` \ No newline at end of file From e42422407ccd13e7136092965e1003ab73e6c745 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:38:30 +0530 Subject: [PATCH 250/391] [cli] Pick version from the github tag --- cli/cmd/root.go | 5 +++-- cli/cmd/version.go | 2 +- cli/main.go | 4 +++- cli/release.sh | 13 ++++++++++++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 0b53f41622..e7f3378a44 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -12,7 +12,7 @@ import ( "github.com/spf13/cobra" ) -const AppVersion = "0.1.11" +var version string var ctrl *pkg.ClICtrl @@ -34,8 +34,9 @@ func GenerateDocs() error { // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute(controller *pkg.ClICtrl) { +func Execute(controller *pkg.ClICtrl, ver string) { ctrl = controller + version = ver err := rootCmd.Execute() if err != nil { os.Exit(1) diff --git a/cli/cmd/version.go b/cli/cmd/version.go index 9d5194bc77..3431bcfc31 100644 --- a/cli/cmd/version.go +++ b/cli/cmd/version.go @@ -12,7 +12,7 @@ var versionCmd = &cobra.Command{ Short: "Prints the current version", Long: ``, Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Version %s\n", AppVersion) + fmt.Printf("Version %s\n", version) }, } diff --git a/cli/main.go b/cli/main.go index f9ad0fa067..157c11fd87 100644 --- a/cli/main.go +++ b/cli/main.go @@ -15,6 +15,8 @@ import ( "strings" ) +var AppVersion = "0.1.12" + func main() { cliDBPath, err := GetCLIConfigPath() if secrets.IsRunningInContainer() { @@ -73,7 +75,7 @@ func main() { } return } - cmd.Execute(&ctrl) + cmd.Execute(&ctrl, AppVersion) } func initConfig(cliConfigPath string) { diff --git a/cli/release.sh b/cli/release.sh index ac0106bd07..b3946c3810 100755 --- a/cli/release.sh +++ b/cli/release.sh @@ -1,5 +1,16 @@ #!/bin/bash +# Fetch the latest tag that starts with "cli-" +# shellcheck disable=SC2046 +# shellcheck disable=SC2006 +LATEST_TAG=$(git describe --tags `git rev-list --tags='cli-*' --max-count=1`) + +# Check if the LATEST_TAG variable is empty +if [ -z "$LATEST_TAG" ]; then + echo "No 'cli-' tag found. Exiting..." + exit 1 +fi +VERSION=${LATEST_TAG#cli-} # Create a "bin" directory if it doesn't exist mkdir -p bin @@ -29,7 +40,7 @@ do fi # Build the binary and place it in the "bin" directory - go build -ldflags="-s -w" -trimpath -o "bin/$BINARY_NAME" main.go + go build -ldflags="-X main.AppVersion=${VERSION} -s -w" -trimpath -o "bin/$BINARY_NAME" main.go # Print a message indicating the build is complete for the current OS and architecture echo "Built for $OS ($ARCH) as bin/$BINARY_NAME" From 077ba04664d255012290240de38035f42d1ba308 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:42:03 +0530 Subject: [PATCH 251/391] [cli-release.yml] Pass release version in build flag --- .github/workflows/cli-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cli-release.yml b/.github/workflows/cli-release.yml index 1efa805d44..e1793fa8df 100644 --- a/.github/workflows/cli-release.yml +++ b/.github/workflows/cli-release.yml @@ -49,6 +49,6 @@ jobs: project_path: "./cli" pre_command: export CGO_ENABLED=0 build_flags: "-trimpath" - ldflags: "-s -w" + ldflags: "-X main.AppVersion=${{ github.ref_name }} -s -w" md5sum: false sha256sum: true From 518b947808bde6d4d9afdffa11a6bc38c00d67ad Mon Sep 17 00:00:00 2001 From: Ashil <77285023+ashilkn@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:43:31 +0530 Subject: [PATCH 252/391] [mobile][photos] Make scrollbar in log file viewer interactive (#1075) --- mobile/lib/ui/tools/debug/log_file_viewer.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mobile/lib/ui/tools/debug/log_file_viewer.dart b/mobile/lib/ui/tools/debug/log_file_viewer.dart index 9e3e00789d..e41561c0e8 100644 --- a/mobile/lib/ui/tools/debug/log_file_viewer.dart +++ b/mobile/lib/ui/tools/debug/log_file_viewer.dart @@ -43,6 +43,9 @@ class _LogFileViewerState extends State { return Container( padding: const EdgeInsets.only(left: 12, top: 8, right: 12), child: Scrollbar( + interactive: true, + thickness: 4, + radius: const Radius.circular(2), child: SingleChildScrollView( child: Text( _logs!, From bc4fa44edd48e0daf6dcf6da72fb6aeca4bb997f Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 11:47:25 +0530 Subject: [PATCH 253/391] v0.8.68 --- mobile/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index ccee2aae9c..0e603076e2 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.8.67+587 +version: 0.8.68+588 publish_to: none environment: From 7543dc6b57b8db31f5753524ee30eee2e86026de Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Wed, 13 Mar 2024 12:02:36 +0530 Subject: [PATCH 254/391] [docs] Update custom server section for cli --- docs/docs/self-hosting/guides/custom-server/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/self-hosting/guides/custom-server/index.md b/docs/docs/self-hosting/guides/custom-server/index.md index 276cb51954..51a9b6c2fe 100644 --- a/docs/docs/self-hosting/guides/custom-server/index.md +++ b/docs/docs/self-hosting/guides/custom-server/index.md @@ -22,6 +22,10 @@ configure the endpoint the app should be connecting to. # CLI +> [!WARNING] +> The new version of CLI that supports connecting to custom server is still in beta. +> You can download the beta version from [here](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0&expanded=true) + Define a config.yaml and put it either in the same directory as CLI or path defined in env variable `ENTE_CLI_CONFIG_PATH` ```yaml From f8d956d47fb76d5bd970f53a3ea3c038abbc70df Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 12:22:11 +0530 Subject: [PATCH 255/391] Fix path to APK --- .github/workflows/mobile-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mobile-release.yml b/.github/workflows/mobile-release.yml index fc910fbb89..3ce4db8d2e 100644 --- a/.github/workflows/mobile-release.yml +++ b/.github/workflows/mobile-release.yml @@ -49,7 +49,7 @@ jobs: SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD_PHOTOS }} - name: Checksum - run: sha256sum build/app/outputs/flutter-apk/ente.apk > build/app/outputs/flutter-apk/sha256sum + run: sha256sum build/app/outputs/flutter-apk/ente-${{ github.ref_name }}.apk > build/app/outputs/flutter-apk/sha256sum - name: Create a draft GitHub release uses: ncipollo/release-action@v1 From a3c80556d28722d680be52eab158e4a2d87d80a9 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 12:43:31 +0530 Subject: [PATCH 256/391] v0.8.70 --- mobile/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 0e603076e2..fdf00a1d21 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.8.68+588 +version: 0.8.70+590 publish_to: none environment: From 124ef8605428e00d448beb1ecb57d75f1dc6488b Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 13:45:44 +0530 Subject: [PATCH 257/391] Remove flutter as a submodule --- .gitmodules | 4 ---- mobile/thirdparty/flutter | 1 - 2 files changed, 5 deletions(-) delete mode 160000 mobile/thirdparty/flutter diff --git a/.gitmodules b/.gitmodules index 36834f2cd2..c3aa69517c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,10 +9,6 @@ [submodule "auth/assets/simple-icons"] path = auth/assets/simple-icons url = https://github.com/simple-icons/simple-icons.git -[submodule "mobile/thirdparty/flutter"] - path = mobile/thirdparty/flutter - url = https://github.com/flutter/flutter.git - branch = stable [submodule "mobile/plugins/clip_ggml"] path = mobile/plugins/clip_ggml url = https://github.com/ente-io/clip-ggml.git diff --git a/mobile/thirdparty/flutter b/mobile/thirdparty/flutter deleted file mode 160000 index 367f9ea16b..0000000000 --- a/mobile/thirdparty/flutter +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 367f9ea16bfae1ca451b9cc27c1366870b187ae2 From 163c5de1cc8dc408e29fdf0ceac984a1bdac8299 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 13:46:59 +0530 Subject: [PATCH 258/391] Remove Isar as a submodule --- .gitmodules | 3 --- mobile/thirdparty/isar | 1 - 2 files changed, 4 deletions(-) delete mode 160000 mobile/thirdparty/isar diff --git a/.gitmodules b/.gitmodules index c3aa69517c..cfea8359b6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,9 +12,6 @@ [submodule "mobile/plugins/clip_ggml"] path = mobile/plugins/clip_ggml url = https://github.com/ente-io/clip-ggml.git -[submodule "mobile/thirdparty/isar"] - path = mobile/thirdparty/isar - url = https://github.com/isar/isar [submodule "web/apps/photos/thirdparty/ffmpeg-wasm"] path = web/apps/photos/thirdparty/ffmpeg-wasm url = https://github.com/abhinavkgrd/ffmpeg.wasm.git diff --git a/mobile/thirdparty/isar b/mobile/thirdparty/isar deleted file mode 160000 index 6643d064ab..0000000000 --- a/mobile/thirdparty/isar +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6643d064abf22606b6c6a741ea873e4781115ef4 From b96e7341e350ebd2f1d2b567627b261b419591fc Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 13:47:33 +0530 Subject: [PATCH 259/391] Remove thirdparty dependency on transistor-background-fetch --- .../transistor-background-fetch/.gitignore | 63 --- .../transistor-background-fetch/LICENSE | 19 - .../transistor-background-fetch/README.md | 22 -- .../TSBackgroundFetch.podspec | 28 -- .../android/.gitignore | 9 - .../android/app/.gitignore | 1 - .../android/app/build.gradle | 29 -- .../android/app/proguard-rules.pro | 21 - .../ExampleInstrumentedTest.java | 27 -- .../android/app/src/main/AndroidManifest.xml | 11 - .../drawable-v24/ic_launcher_foreground.xml | 34 -- .../res/drawable/ic_launcher_background.xml | 170 -------- .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 - .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3056 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 5024 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2096 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2858 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4569 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 7098 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 6464 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 10676 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 9250 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 15523 -> 0 bytes .../app/src/main/res/values/colors.xml | 6 - .../app/src/main/res/values/strings.xml | 3 - .../app/src/main/res/values/styles.xml | 11 - .../backgroundfetch/ExampleUnitTest.java | 17 - .../android/build.gradle | 34 -- .../android/gradle.properties | 23 -- .../android/gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - .../android/gradlew | 160 -------- .../android/gradlew.bat | 90 ----- .../android/settings.gradle | 1 - .../android/tsbackgroundfetch/.gitignore | 1 - .../android/tsbackgroundfetch/build.gradle | 136 ------- .../tsbackgroundfetch/proguard-rules.pro | 21 - .../ExampleInstrumentedTest.java | 26 -- .../src/main/AndroidManifest.xml | 17 - .../tsbackgroundfetch/BGTask.java | 279 -------------- .../tsbackgroundfetch/BackgroundFetch.java | 306 --------------- .../BackgroundFetchConfig.java | 362 ------------------ .../tsbackgroundfetch/BootReceiver.java | 24 -- .../tsbackgroundfetch/FetchAlarmReceiver.java | 40 -- .../tsbackgroundfetch/FetchJobService.java | 50 --- .../src/main/res/values/strings.xml | 3 - .../tsbackgroundfetch/ExampleUnitTest.java | 17 - 48 files changed, 2078 deletions(-) delete mode 100644 mobile/thirdparty/transistor-background-fetch/.gitignore delete mode 100644 mobile/thirdparty/transistor-background-fetch/LICENSE delete mode 100644 mobile/thirdparty/transistor-background-fetch/README.md delete mode 100644 mobile/thirdparty/transistor-background-fetch/TSBackgroundFetch.podspec delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/.gitignore delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/.gitignore delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/build.gradle delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/proguard-rules.pro delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/androidTest/java/com/transistorsoft/backgroundfetch/ExampleInstrumentedTest.java delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/AndroidManifest.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/colors.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/strings.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/styles.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/app/src/test/java/com/transistorsoft/backgroundfetch/ExampleUnitTest.java delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/build.gradle delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/gradle.properties delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/gradle/wrapper/gradle-wrapper.jar delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/gradle/wrapper/gradle-wrapper.properties delete mode 100755 mobile/thirdparty/transistor-background-fetch/android/gradlew delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/gradlew.bat delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/settings.gradle delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/.gitignore delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/build.gradle delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/proguard-rules.pro delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/androidTest/java/com/transistorsoft/tsbackgroundfetch/ExampleInstrumentedTest.java delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/AndroidManifest.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BGTask.java delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetch.java delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetchConfig.java delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BootReceiver.java delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/FetchAlarmReceiver.java delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/FetchJobService.java delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/res/values/strings.xml delete mode 100644 mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/test/java/com/transistorsoft/tsbackgroundfetch/ExampleUnitTest.java diff --git a/mobile/thirdparty/transistor-background-fetch/.gitignore b/mobile/thirdparty/transistor-background-fetch/.gitignore deleted file mode 100644 index 296d68a8fe..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/.gitignore +++ /dev/null @@ -1,63 +0,0 @@ -# Eclipse -.metadata - -# Xcode -# -.DS_Store -build/ -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata -*.xccheckout -*.moved-aside -DerivedData -*.hmap -*.ipa -*.xcuserstate - -# CocoaPods -# -# We recommend against adding the Pods directory to your .gitignore. However -# you should judge for yourself, the pros and cons are mentioned at: -# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control -# -#Pods/ - -# Eclipse - -# built application files -*.apk -*.ap_ - -# files for the dex VM -*.dex - -# Java class files -*.class - -# generated files -bin/ -gen/ - -# Local configuration file (sdk path, etc) -local.properties - -# Eclipse project files -.classpath -.project - -# Proguard folder generated by Eclipse -proguard/ - -# Intellij project files -*.iml -*.ipr -*.iws -.idea/ - diff --git a/mobile/thirdparty/transistor-background-fetch/LICENSE b/mobile/thirdparty/transistor-background-fetch/LICENSE deleted file mode 100644 index 526bbac983..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2017 Transistor Software - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/mobile/thirdparty/transistor-background-fetch/README.md b/mobile/thirdparty/transistor-background-fetch/README.md deleted file mode 100644 index 418370978a..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/README.md +++ /dev/null @@ -1,22 +0,0 @@ -Transistor Background Fetch -=========================================================================== - -Copyright (c) 2017 Transistor Software - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/mobile/thirdparty/transistor-background-fetch/TSBackgroundFetch.podspec b/mobile/thirdparty/transistor-background-fetch/TSBackgroundFetch.podspec deleted file mode 100644 index 1967bd2e9b..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/TSBackgroundFetch.podspec +++ /dev/null @@ -1,28 +0,0 @@ -# -# Be sure to run `pod lib lint TSBackgroundFetch.podspec' to ensure this is a -# valid spec before submitting. -# -# Any lines starting with a # are optional, but their use is encouraged -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html -# - -Pod::Spec.new do |s| - s.name = 'TSBackgroundFetch' - s.version = '0.0.1' - s.summary = 'iOS Background Fetch API Manager' - - s.description = <<-DESC -iOS Background Fetch API Manager with ability to handle multiple listeners. - DESC - - s.homepage = 'http://www.transistorsoft.com' - s.license = { :type => 'MIT', :file => 'LICENSE' } - s.author = { 'christocracy' => 'christocracy@gmail.com' } - s.source = { :git => 'https://github.com/transistorsoft/transistor-background-fetch.git', :tag => s.version.to_s } - s.social_media_url = 'https://twitter.com/christocracy' - - s.ios.deployment_target = '8.0' - - s.source_files = 'ios/TSBackgroundFetch/TSBackgroundFetch/*.{h,m}' - s.vendored_frameworks = 'ios/TSBackgroundFetch/TSBackgroundFetch.framework' -end diff --git a/mobile/thirdparty/transistor-background-fetch/android/.gitignore b/mobile/thirdparty/transistor-background-fetch/android/.gitignore deleted file mode 100644 index 39fb081a42..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures -.externalNativeBuild diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/.gitignore b/mobile/thirdparty/transistor-background-fetch/android/app/.gitignore deleted file mode 100644 index 796b96d1c4..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/build.gradle b/mobile/thirdparty/transistor-background-fetch/android/app/build.gradle deleted file mode 100644 index 93a4040d2b..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 26 - defaultConfig { - applicationId "com.transistorsoft.backgroundfetch" - minSdkVersion 16 - targetSdkVersion 26 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' - - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:26.1.0' - -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/proguard-rules.pro b/mobile/thirdparty/transistor-background-fetch/android/app/proguard-rules.pro deleted file mode 100644 index f1b424510d..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/androidTest/java/com/transistorsoft/backgroundfetch/ExampleInstrumentedTest.java b/mobile/thirdparty/transistor-background-fetch/android/app/src/androidTest/java/com/transistorsoft/backgroundfetch/ExampleInstrumentedTest.java deleted file mode 100644 index 983348763b..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/androidTest/java/com/transistorsoft/backgroundfetch/ExampleInstrumentedTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.transistorsoft.backgroundfetch; - -import android.content.Context; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.transistorsoft.backgroundfetch", appContext.getPackageName()); - } -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/AndroidManifest.xml b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index b22ee9b637..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd8..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/drawable/ic_launcher_background.xml b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index d5fccc538c..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index eca70cfe52..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index eca70cfe52..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f5908281d070150700378b64a84c7db1f97aa1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3056 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 axPAxe%7rDusX+w*00006jj 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⁣ zwiG+x#%j}{0gU~J8;<|!B1@-XaB@{KORFwrYg_8rOv({b0EO#DbeQRm;B6_9=mXGf z-x|VL{zd`)#@yN}HkCSJbjbNlE|zL3Wm9Q8HY`sV)}3%pgN>cL^67{Z;PPL(*wT8N zUjXU{@|*hvm}({wsAC=x0^ok0%UAz0;sogW{B!nDqk|JJ5x~4NfTDgP49^zeu`csl?5mY@JdQdISc zFs!E{^grmkLnUk9 zny~m)1vws@5BFI<-0Tuo2JWX(0v`W|t(wg;s--L47WTvTMz-8l#TL^=OJNRS2?_Qj z3AKT+gvbyBi#H*-tJ%tWD|>EV3wy|8qxfzS!5RW;Jpl5*zo&^UBU=fG#2}UvRyNkK zA06Dy9;K1ca@r2T>yThYgI!ont$(G{6q#2QT+00r_x0(b)gsE`lBB?2gr55gq^D3Fi&p%E(p9>U%bv zkg1Jco(RbyTX7FDHOnl7-O@ zI$AaIl?9NJKPm(WiBP`1-#CB1QzU>&hKm)fpa5DKE{2$X0hGz-0uZ?cyTk(YC!Y&| zL=1VrNERSA5NA2jq7FACfX4JfPyj5XXl1yv0>~s;eF7L2$>&oMqeTFT2m$y7FlkON z_yurD1yIOvA;5C6016pyxBznGUt0kJ&k5r#;&>Jow`r)sp9R~PmK~lz$3xH%LT*1U zJdOyABZ3!FvNoR*vN$5ykHS8f`jA4zV+|L}i1C4`B2c{R0;UdYxaU|H)2avz@ z=mEYc|2S<+(B2Tj+FkX+2D+yFI!k9lWMA61DJ{)e;lum$(;O87?vGJJe!KtK04+N_ zI*P~t@dUb>9Xh{dbyl{-ZQ(UMgz7$|QfL5XSPkskt^NgctYC#;4WcZB1@%@wy@2t3 z2z0DI7&%b$*Aw~abe?GxE`ez@+6hOh-6*8fHRV{1os$EL@}uUZeG4h1&Be`98q*7j z=3-v+lhIjfWVo12!<>%V^a6lTgW3+_#W6n|p*~==zOH7z$0{LSZk(Tpd7EaD04hnA zL;#fxS0aD{`5^&D`}>0Uq?byDD-l2=!wm_bLcUl4gc(% za1p|itVANvFF>hghAS07Im1;IK;|b*W)}VDyI;BIp2=K*yu2a)j?B|f<44NI$NbmJ z#dE0>jI$fMr&@>4kN8MLFb4&2O9fEKaQg%(QO$4_1rVQywG^CmBLh#}_7gKW3vd?| z2?1^&KWq8}8I^_S0|)MowU_pw$q@nl@Nkn$z>BQq_KA^9yaR`(R3u{{Ig;cwt z@AJ^{ODQCm^neroM9nKNUAXi9RCK`OsP_LuR0PUR(YZCCX5dNF6VzcoK&=b^r`W?ltt|*F zpkoae%ZT{C1h~EcFui~b7fF`vb<<~j_VquuUA$}QqIKYELPp#;{u?q8Dz}WAG-(3; zjrm$i%7UbyZMM(Y{>!uJ#vNB?R~B{6Htp=>e*<{fQQ5W7V(1coCWlOON!MzZxhum| ztZBQpGR z;~#ur^&PockKdV{Q6R>o`Pl{0x!DEbpZ7y9Y;*ZvE!*gU`V1W3znva{f=?WO5I&>B z&hw6}tjECtaghm5z|C#%M;Yf_*pI^};h}Vl=^r9EN=tVDj86D;C$jIJ?K7VP+00000NkvXXu0mjf D5i!M* diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d3ae0d3943ab44cdc27feef9256dc6d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7098 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 diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe024be86e868d14e91120a6902f8e88ac6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6464 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 B0*L?s diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a1b15ff180f3dacac19395fe3046cdec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10676 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 diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c239cb67b8a2134ddd5f325db1d2d5bee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15523 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 BIP(Ai diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/colors.xml b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/colors.xml deleted file mode 100644 index 3ab3e9cbce..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - #3F51B5 - #303F9F - #FF4081 - diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/strings.xml b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/strings.xml deleted file mode 100644 index 89ece41f65..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - BackgroundFetch - diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/styles.xml b/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/styles.xml deleted file mode 100644 index 5885930df6..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/mobile/thirdparty/transistor-background-fetch/android/app/src/test/java/com/transistorsoft/backgroundfetch/ExampleUnitTest.java b/mobile/thirdparty/transistor-background-fetch/android/app/src/test/java/com/transistorsoft/backgroundfetch/ExampleUnitTest.java deleted file mode 100644 index 6536d1cd3b..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/app/src/test/java/com/transistorsoft/backgroundfetch/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.transistorsoft.backgroundfetch; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/mobile/thirdparty/transistor-background-fetch/android/build.gradle b/mobile/thirdparty/transistor-background-fetch/android/build.gradle deleted file mode 100644 index c46c347b14..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' - - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} - -ext { - compileSdkVersion = 29 - targetSdkVersion = 29 - buildToolsVersion = "29.0.6" - appCompatVersion = "1.1.0" -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/gradle.properties b/mobile/thirdparty/transistor-background-fetch/android/gradle.properties deleted file mode 100644 index 85104bf955..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/gradle.properties +++ /dev/null @@ -1,23 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true - -VERSION_NAME=0.5.0 -VERSION_CODE=15 - -android.useAndroidX=true -android.enableJetifier=true diff --git a/mobile/thirdparty/transistor-background-fetch/android/gradle/wrapper/gradle-wrapper.jar b/mobile/thirdparty/transistor-background-fetch/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 13372aef5e24af05341d49695ee84e5f9b594659..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53636 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ⅅ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 H-+%o-(+5aQ diff --git a/mobile/thirdparty/transistor-background-fetch/android/gradle/wrapper/gradle-wrapper.properties b/mobile/thirdparty/transistor-background-fetch/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 7a8c57bad8..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -#Thu Feb 09 18:40:48 IST 2023 -distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip -distributionPath=wrapper/dists -zipStorePath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -distributionSha256Sum=10065868c78f1207afb3a92176f99a37d753a513dff453abb6b5cceda4058cda diff --git a/mobile/thirdparty/transistor-background-fetch/android/gradlew b/mobile/thirdparty/transistor-background-fetch/android/gradlew deleted file mode 100755 index 9d82f78915..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/gradlew +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/mobile/thirdparty/transistor-background-fetch/android/gradlew.bat b/mobile/thirdparty/transistor-background-fetch/android/gradlew.bat deleted file mode 100644 index 8a0b282aa6..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/mobile/thirdparty/transistor-background-fetch/android/settings.gradle b/mobile/thirdparty/transistor-background-fetch/android/settings.gradle deleted file mode 100644 index 8b053e2ccc..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':app', ':tsbackgroundfetch' diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/.gitignore b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/.gitignore deleted file mode 100644 index 796b96d1c4..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/build.gradle b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/build.gradle deleted file mode 100644 index d64e6cfddc..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/build.gradle +++ /dev/null @@ -1,136 +0,0 @@ -apply plugin: 'com.android.library' -apply plugin: 'maven' -apply plugin: 'maven-publish' - -android { - compileSdkVersion rootProject.compileSdkVersion - defaultConfig { - minSdkVersion 16 - targetSdkVersion rootProject.targetSdkVersion - versionCode 1 - versionName "1.0" - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - publishing { - publications { - tslocationmanager(MavenPublication) { - groupId 'com.transistorsoft' - artifactId 'tsbackgroundfetch' - version VERSION_NAME - artifact("$buildDir/outputs/aar/tsbackgroundfetch-release.aar") - - } - } - repositories { - mavenLocal() - } - } -} - -dependencies { - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.2.0' - - implementation fileTree(dir: 'libs', include: ['*.jar']) - - //implementation "androidx.appcompat:appcompat:$rootProject.appCompatVersion" - -} - -// Build Release -task buildRelease { task -> - task.dependsOn 'cordovaRelease' - task.dependsOn 'reactNativeRelease' - task.dependsOn 'nativeScriptRelease' - task.dependsOn 'flutterRelease' -} - -// Publish Release. -task publishRelease { task -> - task.dependsOn 'assembleRelease' -} -tasks["publishRelease"].mustRunAfter("assembleRelease") -tasks["publishRelease"].finalizedBy("publish") - -def WORKSPACE_PATH = "/Volumes/Glyph2TB/Users/chris/workspace" - -// Build local maven repo. -def LIBRARY_PATH = "com/transistorsoft/tsbackgroundfetch" -task buildLocalRepository { task -> - task.dependsOn 'publishRelease' - doLast { - delete "$buildDir/repo-local" - copy { - from "$buildDir/repo/$LIBRARY_PATH/$VERSION_NAME" - into "$buildDir/repo-local/$LIBRARY_PATH/$VERSION_NAME" - } - copy { - from("$buildDir/repo/$LIBRARY_PATH/maven-metadata.xml") - into("$buildDir/repo-local/$LIBRARY_PATH") - } - } -} - -def cordovaDir = "$WORKSPACE_PATH/cordova/background-geolocation/cordova-plugin-background-fetch" -task cordovaRelease { task -> - task.dependsOn 'buildLocalRepository' - doLast { - delete "$cordovaDir/src/android/libs" - copy { - // Maven repo format. - from("$buildDir/repo-local") - into("$cordovaDir/src/android/libs") - // OLD FORMAT - //from("$buildDir/outputs/aar/tsbackgroundfetch-release.aar") - //into("$cordovaDir/src/android/libs/tsbackgroundfetch") - //rename(/(.*)-release/, '$1-' + VERSION_NAME) - } - } -} - -def reactNativeDir = "$WORKSPACE_PATH/react/background-geolocation/react-native-background-fetch" -task reactNativeRelease { task -> - task.dependsOn 'buildLocalRepository' - doLast { - delete "$reactNativeDir/android/libs" - copy { - // Maven repo format. - from("$buildDir/repo-local") - into("$reactNativeDir/android/libs") - // OLD format. - //from("$buildDir/outputs/aar/tsbackgroundfetch-release.aar") - //into("$reactNativeDir/android/libs") - //rename(/(.*)-release/, '$1-' + VERSION_NAME) - } - } -} - -def flutterDir = "$WORKSPACE_PATH/background-geolocation/flutter/flutter_background_fetch" -task flutterRelease { task -> - task.dependsOn 'buildLocalRepository' - doLast { - delete "$flutterDir/android/libs" - copy { - // Maven repo format. - from("$buildDir/repo-local") - into("$flutterDir/android/libs") - // OLD format. - //from("$buildDir/outputs/aar/tsbackgroundfetch-release.aar") - //into("$flutterDir/android/libs") - //rename(/(.*)-release/, '$1-' + VERSION_NAME) - } - } -} - -task nativeScriptRelease(type: Copy) { - from('./build/outputs/aar/tsbackgroundfetch-release.aar') - into("$WORKSPACE_PATH/NativeScript/background-geolocation/nativescript-background-fetch/src/platforms/android/libs") - rename('tsbackgroundfetch-release.aar', 'tsbackgroundfetch.aar') -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/proguard-rules.pro b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/proguard-rules.pro deleted file mode 100644 index f1b424510d..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/androidTest/java/com/transistorsoft/tsbackgroundfetch/ExampleInstrumentedTest.java b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/androidTest/java/com/transistorsoft/tsbackgroundfetch/ExampleInstrumentedTest.java deleted file mode 100644 index 2bb391be3a..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/androidTest/java/com/transistorsoft/tsbackgroundfetch/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.transistorsoft.tsbackgroundfetch; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.transistorsoft.tsbackgroundfetch.test", appContext.getPackageName()); - } -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/AndroidManifest.xml b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/AndroidManifest.xml deleted file mode 100644 index 1cd70cd57d..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/AndroidManifest.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BGTask.java b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BGTask.java deleted file mode 100644 index a858dcf591..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BGTask.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.transistorsoft.tsbackgroundfetch; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.app.job.JobInfo; -import android.app.job.JobScheduler; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import android.os.PersistableBundle; -import android.util.Log; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -public class BGTask { - static int MAX_TIME = 60000; - - private static final List mTasks = new ArrayList<>(); - - static BGTask getTask(String taskId) { - synchronized (mTasks) { - for (BGTask task : mTasks) { - if (task.hasTaskId(taskId)) return task; - } - } - return null; - } - - static void addTask(BGTask task) { - synchronized (mTasks) { - mTasks.add(task); - } - } - - static void removeTask(String taskId) { - synchronized (mTasks) { - BGTask found = null; - for (BGTask task : mTasks) { - if (task.hasTaskId(taskId)) { - found = task; - break; - } - } - if (found != null) { - mTasks.remove(found); - } - } - } - - static void clear() { - synchronized (mTasks) { - mTasks.clear(); - } - } - - private FetchJobService.CompletionHandler mCompletionHandler; - private String mTaskId; - private int mJobId; - private Runnable mTimeoutTask; - private boolean mTimedout = false; - - BGTask(final Context context, String taskId, FetchJobService.CompletionHandler handler, int jobId) { - mTaskId = taskId; - mCompletionHandler = handler; - mJobId = jobId; - - mTimeoutTask = new Runnable() { - @Override public void run() { - onTimeout(context); - } - }; - BackgroundFetch.getUiHandler().postDelayed(mTimeoutTask, MAX_TIME); - } - - public boolean getTimedOut() { - return mTimedout; - } - - public String getTaskId() { return mTaskId; } - - int getJobId() { return mJobId; } - - boolean hasTaskId(String taskId) { - return ((mTaskId != null) && mTaskId.equalsIgnoreCase(taskId)); - } - - void setCompletionHandler(FetchJobService.CompletionHandler handler) { - mCompletionHandler = handler; - } - - void finish() { - if (mCompletionHandler != null) { - mCompletionHandler.finish(); - } - if (mTimeoutTask != null) { - BackgroundFetch.getUiHandler().removeCallbacks(mTimeoutTask); - } - mCompletionHandler = null; - removeTask(mTaskId); - } - - static void schedule(Context context, BackgroundFetchConfig config) { - Log.d(BackgroundFetch.TAG, config.toString()); - - long interval = (config.isFetchTask()) ? (TimeUnit.MINUTES.toMillis(config.getMinimumFetchInterval())) : config.getDelay(); - - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !config.getForceAlarmManager()) { - // API 21+ uses new JobScheduler API - - JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); - JobInfo.Builder builder = new JobInfo.Builder(config.getJobId(), new ComponentName(context, FetchJobService.class)) - .setRequiredNetworkType(config.getRequiredNetworkType()) - .setRequiresDeviceIdle(config.getRequiresDeviceIdle()) - .setRequiresCharging(config.getRequiresCharging()) - .setPersisted(config.getStartOnBoot() && !config.getStopOnTerminate()); - - if (config.getPeriodic()) { - if (android.os.Build.VERSION.SDK_INT >= 24) { - builder.setPeriodic(interval, interval); - } else { - builder.setPeriodic(interval); - } - } else { - builder.setMinimumLatency(interval); - } - PersistableBundle extras = new PersistableBundle(); - extras.putString(BackgroundFetchConfig.FIELD_TASK_ID, config.getTaskId()); - builder.setExtras(extras); - - if (android.os.Build.VERSION.SDK_INT >= 26) { - builder.setRequiresStorageNotLow(config.getRequiresStorageNotLow()); - builder.setRequiresBatteryNotLow(config.getRequiresBatteryNotLow()); - } - if (jobScheduler != null) { - jobScheduler.schedule(builder.build()); - } - } else { - // Everyone else get AlarmManager - AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - if (alarmManager != null) { - PendingIntent pi = getAlarmPI(context, config.getTaskId()); - long delay = System.currentTimeMillis() + interval; - if (config.getPeriodic()) { - alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, delay, interval, pi); - } else { - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, delay, pi); - } else if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - alarmManager.setExact(AlarmManager.RTC_WAKEUP, delay, pi); - } else { - alarmManager.set(AlarmManager.RTC_WAKEUP, delay, pi); - } - } - } - } - } - - void onTimeout(Context context) { - mTimedout = true; - Log.d(BackgroundFetch.TAG, "[BGTask] timeout: " + mTaskId); - - BackgroundFetch adapter = BackgroundFetch.getInstance(context); - - if (adapter.isMainActivityActive()) { - BackgroundFetch.Callback callback = adapter.getFetchCallback(); - if (callback != null) { - callback.onTimeout(mTaskId); - } - } else { - BackgroundFetchConfig config = adapter.getConfig(mTaskId); - if (config != null) { - if (config.getJobService() != null) { - fireHeadlessEvent(context, config); - } else { - adapter.finish(mTaskId); - } - } else { - Log.e(BackgroundFetch.TAG, "[BGTask] failed to load config for taskId: " + mTaskId); - adapter.finish(mTaskId); - } - } - } - - // Fire a headless background-fetch event by reflecting an instance of Config.jobServiceClass. - // Will attempt to reflect upon two different forms of Headless class: - // 1: new HeadlessTask(context, taskId) - // or - // 2: new HeadlessTask().onFetch(context, taskId); - // - void fireHeadlessEvent(Context context, BackgroundFetchConfig config) throws Error { - try { - // Get class via reflection. - Class HeadlessClass = Class.forName(config.getJobService()); - Class[] types = { Context.class, BGTask.class }; - Object[] params = { context, this}; - try { - // 1: new HeadlessTask(context, taskId); - Constructor constructor = HeadlessClass.getDeclaredConstructor(types); - constructor.newInstance(params); - } catch (NoSuchMethodException e) { - // 2: new HeadlessTask().onFetch(context, taskId); - Constructor constructor = HeadlessClass.getConstructor(); - Object instance = constructor.newInstance(); - Method onFetch = instance.getClass().getDeclaredMethod("onFetch", types); - onFetch.invoke(instance, params); - } - } catch (ClassNotFoundException e) { - throw new Error(e.getMessage()); - } catch (NoSuchMethodException e) { - throw new Error(e.getMessage()); - } catch (IllegalAccessException e) { - throw new Error(e.getMessage()); - } catch (InstantiationException e) { - throw new Error(e.getMessage()); - } catch (InvocationTargetException e) { - throw new Error(e.getMessage()); - } - } - - static void cancel(Context context, String taskId, int jobId) { - Log.i(BackgroundFetch.TAG, "- cancel taskId=" + taskId + ", jobId=" + jobId); - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && (jobId != 0)) { - JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); - if (jobScheduler != null) { - jobScheduler.cancel(jobId); - } - } else { - AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - if (alarmManager != null) { - alarmManager.cancel(BGTask.getAlarmPI(context, taskId)); - } - } - } - - static PendingIntent getAlarmPI(Context context, String taskId) { - Intent intent = new Intent(context, FetchAlarmReceiver.class); - intent.setAction(taskId); - return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); - } - - public String toString() { - return "[BGTask taskId=" + mTaskId + "]"; - } - - public Map toMap() { - Map map = new HashMap<>(); - map.put("taskId", mTaskId); - map.put("timeout", mTimedout); - return map; - } - - public JSONObject toJson() { - JSONObject json = new JSONObject(); - try { - json.put("taskId", mTaskId); - json.put("timeout", mTimedout); - } catch (JSONException e) { - e.printStackTrace(); - } - return json; - } - - static class Error extends RuntimeException { - public Error(String msg) { - super(msg); - } - } -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetch.java b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetch.java deleted file mode 100644 index 8c374c65cd..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetch.java +++ /dev/null @@ -1,306 +0,0 @@ -package com.transistorsoft.tsbackgroundfetch; - -import android.annotation.TargetApi; -import android.app.ActivityManager; - -import android.content.Context; -import android.os.Build; -import android.os.Handler; -import android.os.Looper; - -import android.util.Log; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Created by chris on 2018-01-11. - */ - -public class BackgroundFetch { - public static final String TAG = "TSBackgroundFetch"; - - public static final String ACTION_CONFIGURE = "configure"; - public static final String ACTION_START = "start"; - public static final String ACTION_STOP = "stop"; - public static final String ACTION_FINISH = "finish"; - public static final String ACTION_STATUS = "status"; - public static final String ACTION_FORCE_RELOAD = TAG + "-forceReload"; - - public static final String EVENT_FETCH = ".event.BACKGROUND_FETCH"; - - public static final int STATUS_AVAILABLE = 2; - - private static BackgroundFetch mInstance = null; - - private static ExecutorService sThreadPool; - - private static Handler uiHandler; - - @SuppressWarnings({"WeakerAccess"}) - public static Handler getUiHandler() { - if (uiHandler == null) { - uiHandler = new Handler(Looper.getMainLooper()); - } - return uiHandler; - } - - @SuppressWarnings({"WeakerAccess"}) - public static ExecutorService getThreadPool() { - if (sThreadPool == null) { - sThreadPool = Executors.newCachedThreadPool(); - } - return sThreadPool; - } - - @SuppressWarnings({"WeakerAccess"}) - public static BackgroundFetch getInstance(Context context) { - if (mInstance == null) { - mInstance = getInstanceSynchronized(context.getApplicationContext()); - } - return mInstance; - } - - private static synchronized BackgroundFetch getInstanceSynchronized(Context context) { - if (mInstance == null) mInstance = new BackgroundFetch(context.getApplicationContext()); - return mInstance; - } - - private Context mContext; - private BackgroundFetch.Callback mFetchCallback; - - private final Map mConfig = new HashMap<>(); - - private BackgroundFetch(Context context) { - mContext = context; - } - - @SuppressWarnings({"unused"}) - public void configure(BackgroundFetchConfig config, BackgroundFetch.Callback callback) { - Log.d(TAG, "- " + ACTION_CONFIGURE); - mFetchCallback = callback; - - synchronized (mConfig) { - mConfig.put(config.getTaskId(), config); - } - start(config.getTaskId()); - } - - void onBoot() { - BackgroundFetchConfig.load(mContext, new BackgroundFetchConfig.OnLoadCallback() { - @Override public void onLoad(List result) { - for (BackgroundFetchConfig config : result) { - if (!config.getStartOnBoot() || config.getStopOnTerminate()) { - config.destroy(mContext); - continue; - } - synchronized (mConfig) { - mConfig.put(config.getTaskId(), config); - } - if ((android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) || config.getForceAlarmManager()) { - if (config.isFetchTask()) { - start(config.getTaskId()); - } else { - scheduleTask(config); - } - } - } - } - }); - } - - @SuppressWarnings({"WeakerAccess"}) - @TargetApi(21) - public void start(String fetchTaskId) { - Log.d(TAG, "- " + ACTION_START); - - BGTask task = BGTask.getTask(fetchTaskId); - if (task != null) { - Log.e(TAG, "[" + TAG + " start] Task " + fetchTaskId + " already registered"); - return; - } - registerTask(fetchTaskId); - } - - @SuppressWarnings({"WeakerAccess"}) - public void stop(String taskId) { - String msg = "- " + ACTION_STOP; - if (taskId != null) { - msg += ": " + taskId; - } - Log.d(TAG, msg); - - if (taskId == null) { - synchronized (mConfig) { - for (BackgroundFetchConfig config : mConfig.values()) { - BGTask task = BGTask.getTask(config.getTaskId()); - if (task != null) { - task.finish(); - BGTask.removeTask(config.getTaskId()); - } - BGTask.cancel(mContext, config.getTaskId(), config.getJobId()); - config.destroy(mContext); - } - BGTask.clear(); - } - } else { - BGTask task = BGTask.getTask(taskId); - if (task != null) { - task.finish(); - BGTask.removeTask(task.getTaskId()); - } - BackgroundFetchConfig config = getConfig(taskId); - if (config != null) { - config.destroy(mContext); - BGTask.cancel(mContext, config.getTaskId(), config.getJobId()); - } - } - } - - @SuppressWarnings({"WeakerAccess"}) - public void scheduleTask(BackgroundFetchConfig config) { - synchronized (mConfig) { - if (mConfig.containsKey(config.getTaskId())) { - // This BackgroundFetchConfig already exists? Should we halt any existing Job/Alarm here? - } - config.save(mContext); - mConfig.put(config.getTaskId(), config); - } - String taskId = config.getTaskId(); - registerTask(taskId); - } - - @SuppressWarnings({"WeakerAccess"}) - public void finish(String taskId) { - Log.d(TAG, "- " + ACTION_FINISH + ": " + taskId); - - BGTask task = BGTask.getTask(taskId); - if (task != null) { - task.finish(); - } - - BackgroundFetchConfig config = getConfig(taskId); - - if ((config != null) && !config.getPeriodic()) { - config.destroy(mContext); - synchronized (mConfig) { - mConfig.remove(taskId); - } - } - } - - public int status() { - return STATUS_AVAILABLE; - } - - BackgroundFetch.Callback getFetchCallback() { - return mFetchCallback; - } - - void onFetch(final BGTask task) { - BGTask.addTask(task); - Log.d(TAG, "- Background Fetch event received: " + task.getTaskId()); - synchronized (mConfig) { - if (mConfig.isEmpty()) { - BackgroundFetchConfig.load(mContext, new BackgroundFetchConfig.OnLoadCallback() { - @Override - public void onLoad(List result) { - synchronized (mConfig) { - for (BackgroundFetchConfig config : result) { - mConfig.put(config.getTaskId(), config); - } - } - doFetch(task); - } - }); - - return; - } - } - doFetch(task); - } - - private void registerTask(String taskId) { - Log.d(TAG, "- registerTask: " + taskId); - - BackgroundFetchConfig config = getConfig(taskId); - - if (config == null) { - Log.e(TAG, "- registerTask failed to find BackgroundFetchConfig for taskId " + taskId); - return; - } - config.save(mContext); - - BGTask.schedule(mContext, config); - } - - private void doFetch(BGTask task) { - BackgroundFetchConfig config = getConfig(task.getTaskId()); - - if (config == null) { - BGTask.cancel(mContext, task.getTaskId(), task.getJobId()); - return; - } - - if (isMainActivityActive()) { - if (mFetchCallback != null) { - mFetchCallback.onFetch(task.getTaskId()); - } - } else if (config.getStopOnTerminate()) { - Log.d(TAG, "- Stopping on terminate"); - stop(task.getTaskId()); - } else if (config.getJobService() != null) { - try { - task.fireHeadlessEvent(mContext, config); - } catch (BGTask.Error e) { - Log.e(TAG, "Headless task error: " + e.getMessage()); - e.printStackTrace(); - } - } else { - // {stopOnTerminate: false, forceReload: false} with no Headless JobService?? Don't know what else to do here but stop - Log.w(TAG, "- BackgroundFetch event has occurred while app is terminated but there's no jobService configured to handle the event. BackgroundFetch will terminate."); - finish(task.getTaskId()); - stop(task.getTaskId()); - } - } - - @SuppressWarnings({"WeakerAccess", "deprecation"}) - public Boolean isMainActivityActive() { - Boolean isActive = false; - - if (mContext == null || mFetchCallback == null) { - return false; - } - ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); - try { - List tasks = activityManager.getRunningTasks(Integer.MAX_VALUE); - for (ActivityManager.RunningTaskInfo task : tasks) { - if (mContext.getPackageName().equalsIgnoreCase(task.baseActivity.getPackageName())) { - isActive = true; - break; - } - } - } catch (java.lang.SecurityException e) { - Log.w(TAG, "TSBackgroundFetch attempted to determine if MainActivity is active but was stopped due to a missing permission. Please add the permission 'android.permission.GET_TASKS' to your AndroidManifest. See Installation steps for more information"); - throw e; - } - return isActive; - } - - BackgroundFetchConfig getConfig(String taskId) { - synchronized (mConfig) { - return (mConfig.containsKey(taskId)) ? mConfig.get(taskId) : null; - } - } - - /** - * @interface BackgroundFetch.Callback - */ - public interface Callback { - void onFetch(String taskId); - void onTimeout(String taskId); - } -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetchConfig.java b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetchConfig.java deleted file mode 100644 index 5ff655fe91..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BackgroundFetchConfig.java +++ /dev/null @@ -1,362 +0,0 @@ -package com.transistorsoft.tsbackgroundfetch; - -import android.app.job.JobInfo; -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Build; -import android.util.Log; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Created by chris on 2018-01-11. - */ - -public class BackgroundFetchConfig { - private Builder config; - - private static final int MINIMUM_FETCH_INTERVAL = 1; - private static final int DEFAULT_FETCH_INTERVAL = 15; - - public static final String FIELD_TASK_ID = "taskId"; - public static final String FIELD_MINIMUM_FETCH_INTERVAL = "minimumFetchInterval"; - public static final String FIELD_START_ON_BOOT = "startOnBoot"; - public static final String FIELD_REQUIRED_NETWORK_TYPE = "requiredNetworkType"; - public static final String FIELD_REQUIRES_BATTERY_NOT_LOW = "requiresBatteryNotLow"; - public static final String FIELD_REQUIRES_CHARGING = "requiresCharging"; - public static final String FIELD_REQUIRES_DEVICE_IDLE = "requiresDeviceIdle"; - public static final String FIELD_REQUIRES_STORAGE_NOT_LOW = "requiresStorageNotLow"; - public static final String FIELD_STOP_ON_TERMINATE = "stopOnTerminate"; - public static final String FIELD_JOB_SERVICE = "jobService"; - public static final String FIELD_FORCE_ALARM_MANAGER = "forceAlarmManager"; - public static final String FIELD_PERIODIC = "periodic"; - public static final String FIELD_DELAY = "delay"; - public static final String FIELD_IS_FETCH_TASK = "isFetchTask"; - - public static class Builder { - private String taskId; - private int minimumFetchInterval = DEFAULT_FETCH_INTERVAL; - private long delay = -1; - private boolean periodic = false; - private boolean forceAlarmManager = false; - private boolean stopOnTerminate = true; - private boolean startOnBoot = false; - private int requiredNetworkType = 0; - private boolean requiresBatteryNotLow = false; - private boolean requiresCharging = false; - private boolean requiresDeviceIdle = false; - private boolean requiresStorageNotLow = false; - private boolean isFetchTask = false; - - private String jobService = null; - - public Builder setTaskId(String taskId) { - this.taskId = taskId; - return this; - } - - public Builder setIsFetchTask(boolean value) { - this.isFetchTask = value; - return this; - } - - public Builder setMinimumFetchInterval(int fetchInterval) { - if (fetchInterval >= MINIMUM_FETCH_INTERVAL) { - this.minimumFetchInterval = fetchInterval; - } - return this; - } - - public Builder setStopOnTerminate(boolean stopOnTerminate) { - this.stopOnTerminate = stopOnTerminate; - return this; - } - - public Builder setStartOnBoot(boolean startOnBoot) { - this.startOnBoot = startOnBoot; - return this; - } - - public Builder setRequiredNetworkType(int networkType) { - - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - if ( - (networkType != JobInfo.NETWORK_TYPE_ANY) && - (networkType != JobInfo.NETWORK_TYPE_CELLULAR) && - (networkType != JobInfo.NETWORK_TYPE_NONE) && - (networkType != JobInfo.NETWORK_TYPE_NOT_ROAMING) && - (networkType != JobInfo.NETWORK_TYPE_UNMETERED) - ) { - Log.e(BackgroundFetch.TAG, "[ERROR] Invalid " + FIELD_REQUIRED_NETWORK_TYPE + ": " + networkType + "; Defaulting to NETWORK_TYPE_NONE"); - networkType = JobInfo.NETWORK_TYPE_NONE; - } - this.requiredNetworkType = networkType; - } - return this; - } - - public Builder setRequiresBatteryNotLow(boolean value) { - this.requiresBatteryNotLow = value; - return this; - } - - public Builder setRequiresCharging(boolean value) { - this.requiresCharging = value; - return this; - } - - public Builder setRequiresDeviceIdle(boolean value) { - this.requiresDeviceIdle = value; - return this; - } - - public Builder setRequiresStorageNotLow(boolean value) { - this.requiresStorageNotLow = value; - return this; - } - - public Builder setJobService(String className) { - this.jobService = className; - return this; - } - - public Builder setForceAlarmManager(boolean value) { - this.forceAlarmManager = value; - return this; - } - - public Builder setPeriodic(boolean value) { - this.periodic = value; - return this; - } - - public Builder setDelay(long value) { - this.delay = value; - return this; - } - - public BackgroundFetchConfig build() { - return new BackgroundFetchConfig(this); - } - - public BackgroundFetchConfig load(Context context, String taskId) { - SharedPreferences preferences = context.getSharedPreferences(BackgroundFetch.TAG + ":" + taskId, 0); - if (preferences.contains(FIELD_TASK_ID)) { - setTaskId(preferences.getString(FIELD_TASK_ID, taskId)); - } - if (preferences.contains(FIELD_IS_FETCH_TASK)) { - setIsFetchTask(preferences.getBoolean(FIELD_IS_FETCH_TASK, isFetchTask)); - } - if (preferences.contains(FIELD_MINIMUM_FETCH_INTERVAL)) { - setMinimumFetchInterval(preferences.getInt(FIELD_MINIMUM_FETCH_INTERVAL, minimumFetchInterval)); - } - if (preferences.contains(FIELD_STOP_ON_TERMINATE)) { - setStopOnTerminate(preferences.getBoolean(FIELD_STOP_ON_TERMINATE, stopOnTerminate)); - } - if (preferences.contains(FIELD_REQUIRED_NETWORK_TYPE)) { - setRequiredNetworkType(preferences.getInt(FIELD_REQUIRED_NETWORK_TYPE, requiredNetworkType)); - } - if (preferences.contains(FIELD_REQUIRES_BATTERY_NOT_LOW)) { - setRequiresBatteryNotLow(preferences.getBoolean(FIELD_REQUIRES_BATTERY_NOT_LOW, requiresBatteryNotLow)); - } - if (preferences.contains(FIELD_REQUIRES_CHARGING)) { - setRequiresCharging(preferences.getBoolean(FIELD_REQUIRES_CHARGING, requiresCharging)); - } - if (preferences.contains(FIELD_REQUIRES_DEVICE_IDLE)) { - setRequiresDeviceIdle(preferences.getBoolean(FIELD_REQUIRES_DEVICE_IDLE, requiresDeviceIdle)); - } - if (preferences.contains(FIELD_REQUIRES_STORAGE_NOT_LOW)) { - setRequiresStorageNotLow(preferences.getBoolean(FIELD_REQUIRES_STORAGE_NOT_LOW, requiresStorageNotLow)); - } - if (preferences.contains(FIELD_START_ON_BOOT)) { - setStartOnBoot(preferences.getBoolean(FIELD_START_ON_BOOT, startOnBoot)); - } - if (preferences.contains(FIELD_JOB_SERVICE)) { - setJobService(preferences.getString(FIELD_JOB_SERVICE, null)); - } - if (preferences.contains(FIELD_FORCE_ALARM_MANAGER)) { - setForceAlarmManager(preferences.getBoolean(FIELD_FORCE_ALARM_MANAGER, forceAlarmManager)); - } - if (preferences.contains(FIELD_PERIODIC)) { - setPeriodic(preferences.getBoolean(FIELD_PERIODIC, periodic)); - } - if (preferences.contains(FIELD_DELAY)) { - setDelay(preferences.getLong(FIELD_DELAY, delay)); - } - return new BackgroundFetchConfig(this); - } - } - - private BackgroundFetchConfig(Builder builder) { - config = builder; - // Validate config - if (config.jobService == null) { - if (!config.stopOnTerminate) { - Log.w(BackgroundFetch.TAG, "- Configuration error: In order to use stopOnTerminate: false, you must set enableHeadless: true"); - config.setStopOnTerminate(true); - } - if (config.startOnBoot) { - Log.w(BackgroundFetch.TAG, "- Configuration error: In order to use startOnBoot: true, you must enableHeadless: true"); - config.setStartOnBoot(false); - } - } - } - - void save(Context context) { - SharedPreferences preferences = context.getSharedPreferences(BackgroundFetch.TAG, 0); - Set taskIds = preferences.getStringSet("tasks", new HashSet()); - if (taskIds == null) { - taskIds = new HashSet<>(); - } - if (!taskIds.contains(config.taskId)) { - Set newIds = new HashSet<>(taskIds); - newIds.add(config.taskId); - - SharedPreferences.Editor editor = preferences.edit(); - editor.putStringSet("tasks", newIds); - editor.apply(); - } - - SharedPreferences.Editor editor = context.getSharedPreferences(BackgroundFetch.TAG + ":" + config.taskId, 0).edit(); - - editor.putString(FIELD_TASK_ID, config.taskId); - editor.putBoolean(FIELD_IS_FETCH_TASK, config.isFetchTask); - editor.putInt(FIELD_MINIMUM_FETCH_INTERVAL, config.minimumFetchInterval); - editor.putBoolean(FIELD_STOP_ON_TERMINATE, config.stopOnTerminate); - editor.putBoolean(FIELD_START_ON_BOOT, config.startOnBoot); - editor.putInt(FIELD_REQUIRED_NETWORK_TYPE, config.requiredNetworkType); - editor.putBoolean(FIELD_REQUIRES_BATTERY_NOT_LOW, config.requiresBatteryNotLow); - editor.putBoolean(FIELD_REQUIRES_CHARGING, config.requiresCharging); - editor.putBoolean(FIELD_REQUIRES_DEVICE_IDLE, config.requiresDeviceIdle); - editor.putBoolean(FIELD_REQUIRES_STORAGE_NOT_LOW, config.requiresStorageNotLow); - editor.putString(FIELD_JOB_SERVICE, config.jobService); - editor.putBoolean(FIELD_FORCE_ALARM_MANAGER, config.forceAlarmManager); - editor.putBoolean(FIELD_PERIODIC, config.periodic); - editor.putLong(FIELD_DELAY, config.delay); - - editor.apply(); - } - - void destroy(Context context) { - SharedPreferences preferences = context.getSharedPreferences(BackgroundFetch.TAG, 0); - Set taskIds = preferences.getStringSet("tasks", new HashSet()); - if (taskIds == null) { - taskIds = new HashSet<>(); - } - if (taskIds.contains(config.taskId)) { - Set newIds = new HashSet<>(taskIds); - newIds.remove(config.taskId); - SharedPreferences.Editor editor = preferences.edit(); - editor.putStringSet("tasks", newIds); - editor.apply(); - } - if (!config.isFetchTask) { - SharedPreferences.Editor editor = context.getSharedPreferences(BackgroundFetch.TAG + ":" + config.taskId, 0).edit(); - editor.clear(); - editor.apply(); - } - } - - static int FETCH_JOB_ID = 999; - - boolean isFetchTask() { - return config.isFetchTask; - } - - public String getTaskId() { return config.taskId; } - public int getMinimumFetchInterval() { - return config.minimumFetchInterval; - } - - public int getRequiredNetworkType() { return config.requiredNetworkType; } - public boolean getRequiresBatteryNotLow() { return config.requiresBatteryNotLow; } - public boolean getRequiresCharging() { return config.requiresCharging; } - public boolean getRequiresDeviceIdle() { return config.requiresDeviceIdle; } - public boolean getRequiresStorageNotLow() { return config.requiresStorageNotLow; } - public boolean getStopOnTerminate() { - return config.stopOnTerminate; - } - public boolean getStartOnBoot() { - return config.startOnBoot; - } - - public String getJobService() { return config.jobService; } - - public boolean getForceAlarmManager() { - return config.forceAlarmManager; - } - - public boolean getPeriodic() { - return config.periodic || isFetchTask(); - } - - public long getDelay() { - return config.delay; - } - - int getJobId() { - if (config.forceAlarmManager) { - return 0; - } else { - return (isFetchTask()) ? FETCH_JOB_ID : config.taskId.hashCode(); - } - } - - public String toString() { - JSONObject output = new JSONObject(); - try { - output.put(FIELD_TASK_ID, config.taskId); - output.put(FIELD_IS_FETCH_TASK, config.isFetchTask); - output.put(FIELD_MINIMUM_FETCH_INTERVAL, config.minimumFetchInterval); - output.put(FIELD_STOP_ON_TERMINATE, config.stopOnTerminate); - output.put(FIELD_REQUIRED_NETWORK_TYPE, config.requiredNetworkType); - output.put(FIELD_REQUIRES_BATTERY_NOT_LOW, config.requiresBatteryNotLow); - output.put(FIELD_REQUIRES_CHARGING, config.requiresCharging); - output.put(FIELD_REQUIRES_DEVICE_IDLE, config.requiresDeviceIdle); - output.put(FIELD_REQUIRES_STORAGE_NOT_LOW, config.requiresStorageNotLow); - output.put(FIELD_START_ON_BOOT, config.startOnBoot); - output.put(FIELD_JOB_SERVICE, config.jobService); - output.put(FIELD_FORCE_ALARM_MANAGER, config.forceAlarmManager); - output.put(FIELD_PERIODIC, getPeriodic()); - output.put(FIELD_DELAY, config.delay); - - return output.toString(2); - } catch (JSONException e) { - e.printStackTrace(); - return output.toString(); - } - } - - static void load(final Context context, final OnLoadCallback callback) { - BackgroundFetch.getThreadPool().execute(new Runnable() { - @Override - public void run() { - final List result = new ArrayList<>(); - - SharedPreferences preferences = context.getSharedPreferences(BackgroundFetch.TAG, 0); - Set taskIds = preferences.getStringSet("tasks", new HashSet()); - - if (taskIds != null) { - for (String taskId : taskIds) { - result.add(new BackgroundFetchConfig.Builder().load(context, taskId)); - } - } - BackgroundFetch.getUiHandler().post(new Runnable() { - @Override public void run() { - callback.onLoad(result); - } - }); - } - }); - } - - interface OnLoadCallback { - void onLoad(Listconfig); - } -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BootReceiver.java b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BootReceiver.java deleted file mode 100644 index b161c082e3..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/BootReceiver.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.transistorsoft.tsbackgroundfetch; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; - -/** - * Created by chris on 2018-01-15. - */ - -public class BootReceiver extends BroadcastReceiver { - - @Override - public void onReceive(final Context context, Intent intent) { - String action = intent.getAction(); - Log.d(BackgroundFetch.TAG, "BootReceiver: " + action); - BackgroundFetch.getThreadPool().execute(new Runnable() { - @Override public void run() { - BackgroundFetch.getInstance(context.getApplicationContext()).onBoot(); - } - }); - } -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/FetchAlarmReceiver.java b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/FetchAlarmReceiver.java deleted file mode 100644 index afcb900dd1..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/FetchAlarmReceiver.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.transistorsoft.tsbackgroundfetch; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.PowerManager; -import android.util.Log; - -import static android.content.Context.POWER_SERVICE; - -/** - * Created by chris on 2018-01-11. - */ - -public class FetchAlarmReceiver extends BroadcastReceiver { - - @Override - public void onReceive(final Context context, Intent intent) { - PowerManager powerManager = (PowerManager) context.getSystemService(POWER_SERVICE); - final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, BackgroundFetch.TAG + "::" + intent.getAction()); - // WakeLock expires in MAX_TIME + 4s buffer. - wakeLock.acquire((BGTask.MAX_TIME + 4000)); - - final String taskId = intent.getAction(); - - final FetchJobService.CompletionHandler completionHandler = new FetchJobService.CompletionHandler() { - @Override - public void finish() { - if (wakeLock.isHeld()) { - wakeLock.release(); - Log.d(BackgroundFetch.TAG, "- FetchAlarmReceiver finish"); - } - } - }; - - BGTask task = new BGTask(context, taskId, completionHandler, 0); - - BackgroundFetch.getInstance(context.getApplicationContext()).onFetch(task); - } -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/FetchJobService.java b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/FetchJobService.java deleted file mode 100644 index 0938d53560..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/java/com/transistorsoft/tsbackgroundfetch/FetchJobService.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.transistorsoft.tsbackgroundfetch; - -import android.annotation.TargetApi; -import android.app.job.JobParameters; -import android.app.job.JobService; -import android.os.PersistableBundle; -import android.util.Log; - -/** - * Created by chris on 2018-01-11. - */ -@TargetApi(21) -public class FetchJobService extends JobService { - @Override - public boolean onStartJob(final JobParameters params) { - PersistableBundle extras = params.getExtras(); - final String taskId = extras.getString(BackgroundFetchConfig.FIELD_TASK_ID); - - CompletionHandler completionHandler = new CompletionHandler() { - @Override - public void finish() { - Log.d(BackgroundFetch.TAG, "- jobFinished"); - jobFinished(params, false); - } - }; - BGTask task = new BGTask(this, taskId, completionHandler, params.getJobId()); - BackgroundFetch.getInstance(getApplicationContext()).onFetch(task); - - return true; - } - - @Override - public boolean onStopJob(final JobParameters params) { - Log.d(BackgroundFetch.TAG, "- onStopJob"); - - PersistableBundle extras = params.getExtras(); - final String taskId = extras.getString(BackgroundFetchConfig.FIELD_TASK_ID); - - BGTask task = BGTask.getTask(taskId); - if (task != null) { - task.onTimeout(getApplicationContext()); - } - jobFinished(params, false); - return true; - } - - public interface CompletionHandler { - void finish(); - } -} diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/res/values/strings.xml b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/res/values/strings.xml deleted file mode 100644 index 17b4bbaa07..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - TSBackgroundFetch - diff --git a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/test/java/com/transistorsoft/tsbackgroundfetch/ExampleUnitTest.java b/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/test/java/com/transistorsoft/tsbackgroundfetch/ExampleUnitTest.java deleted file mode 100644 index 99449e071f..0000000000 --- a/mobile/thirdparty/transistor-background-fetch/android/tsbackgroundfetch/src/test/java/com/transistorsoft/tsbackgroundfetch/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.transistorsoft.tsbackgroundfetch; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file From 1c1c9bb0d74e7e03132a55a44ddc895fe7e3e22a Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 13:51:20 +0530 Subject: [PATCH 260/391] Update docs --- mobile/README.md | 3 +-- mobile/docs/vscode/settings.json | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 mobile/docs/vscode/settings.json diff --git a/mobile/README.md b/mobile/README.md index f9383ce77b..114a3ab38a 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -45,8 +45,7 @@ You can alternatively install the build from PlayStore or F-Droid. ## 🧑‍💻 Building from source -1. [Install Flutter v3.13.4](https://flutter.dev/docs/get-started/install) or - set the Path of Flutter SDK to `thirdparty/flutter/bin`. +1. [Install Flutter v3.13.4](https://flutter.dev/docs/get-started/install). 2. Pull in all submodules with `git submodule update --init --recursive` diff --git a/mobile/docs/vscode/settings.json b/mobile/docs/vscode/settings.json deleted file mode 100644 index b6a9a3c02c..0000000000 --- a/mobile/docs/vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "dart.flutterSdkPath": "thirdparty/flutter/bin" -} From 6ef1da68e078edd3805aa4028e5f9eec78b959af Mon Sep 17 00:00:00 2001 From: Ashil <77285023+ashilkn@users.noreply.github.com> Date: Wed, 13 Mar 2024 13:52:03 +0530 Subject: [PATCH 261/391] [photos][mobile] Performance improvement (#1080) ## Description Stack has `clipBehaviour = Clip.hardEdge` by default. This is necessary if content inside the stack is overflowing it's boundary and it has to be clipped. Clipping is expensive so it's worth removing it when it makes sense. In this case of `GalleryFileWidget`, content doesn't overflow the Stack's boundary so the clip operation can be removed by setting `clipBehaviour = Clip.none`. --- mobile/lib/ui/viewer/gallery/component/gallery_file_widget.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/mobile/lib/ui/viewer/gallery/component/gallery_file_widget.dart b/mobile/lib/ui/viewer/gallery/component/gallery_file_widget.dart index c6b89de0b9..5f1ce7cbfa 100644 --- a/mobile/lib/ui/viewer/gallery/component/gallery_file_widget.dart +++ b/mobile/lib/ui/viewer/gallery/component/gallery_file_widget.dart @@ -68,6 +68,7 @@ class GalleryFileWidget extends StatelessWidget { : _onLongPressNoSelectionLimit(context, file); }, child: Stack( + clipBehavior: Clip.none, children: [ ClipRRect( borderRadius: BorderRadius.circular(1), From 5db0da9aaf7de7fcb9b3a519c677c5c97a1b2238 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Wed, 13 Mar 2024 02:03:48 +0000 Subject: [PATCH 262/391] New Crowdin translations by GitHub Action --- auth/lib/l10n/arb/app_bg.arb | 1 + auth/lib/l10n/arb/app_de.arb | 13 ++++++++++++- auth/lib/l10n/arb/app_ja.arb | 13 ++++++++++++- auth/lib/l10n/arb/app_pt.arb | 13 ++++++++++++- auth/lib/l10n/arb/app_sv.arb | 14 +++++++++++++- auth/lib/l10n/arb/app_zh.arb | 9 ++++++++- 6 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 auth/lib/l10n/arb/app_bg.arb diff --git a/auth/lib/l10n/arb/app_bg.arb b/auth/lib/l10n/arb/app_bg.arb new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/auth/lib/l10n/arb/app_bg.arb @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/auth/lib/l10n/arb/app_de.arb b/auth/lib/l10n/arb/app_de.arb index 6f9382540d..a05c7ca0d5 100644 --- a/auth/lib/l10n/arb/app_de.arb +++ b/auth/lib/l10n/arb/app_de.arb @@ -144,6 +144,7 @@ "enterCodeHint": "Geben Sie den 6-stelligen Code \naus Ihrer Authentifikator-App ein.", "lostDeviceTitle": "Gerät verloren?", "twoFactorAuthTitle": "Zwei-Faktor-Authentifizierung", + "passkeyAuthTitle": "Passkey Authentifizierung", "recoverAccount": "Konto wiederherstellen", "enterRecoveryKeyHint": "Geben Sie Ihren Wiederherstellungsschlüssel ein", "recover": "Wiederherstellen", @@ -404,5 +405,15 @@ "signOutOtherDevices": "Andere Geräte abmelden", "doNotSignOut": "Nicht abmelden", "hearUsWhereTitle": "Wie hast du von Ente erfahren? (optional)", - "hearUsExplanation": "Wir tracken keine App-Installationen. Es würde uns jedoch helfen, wenn du uns mitteilst, wie du von uns erfahren hast!" + "hearUsExplanation": "Wir tracken keine App-Installationen. Es würde uns jedoch helfen, wenn du uns mitteilst, wie du von uns erfahren hast!", + "waitingForBrowserRequest": "Warten auf Browseranfrage...", + "launchPasskeyUrlAgain": "Passwort-URL erneut starten", + "passkey": "Passkey", + "developerSettingsWarning": "Sind Sie sicher, dass Sie die Entwicklereinstellungen ändern möchten?", + "developerSettings": "Entwicklereinstellungen", + "serverEndpoint": "Server Endpunkt", + "invalidEndpoint": "Ungültiger Endpunkt", + "invalidEndpointMessage": "Der eingegebene Endpunkt ist ungültig. Bitte geben Sie einen gültigen Endpunkt ein und versuchen Sie es erneut.", + "endpointUpdatedMessage": "Endpunkt erfolgreich aktualisiert", + "customEndpoint": "Mit {endpoint} verbunden" } \ No newline at end of file diff --git a/auth/lib/l10n/arb/app_ja.arb b/auth/lib/l10n/arb/app_ja.arb index 104da4a226..ed1786f714 100644 --- a/auth/lib/l10n/arb/app_ja.arb +++ b/auth/lib/l10n/arb/app_ja.arb @@ -144,6 +144,7 @@ "enterCodeHint": "認証アプリに表示された 6 桁のコードを入力してください", "lostDeviceTitle": "デバイスを紛失しましたか?", "twoFactorAuthTitle": "2 要素認証", + "passkeyAuthTitle": "パスキー認証", "recoverAccount": "アカウントを回復", "enterRecoveryKeyHint": "回復キーを入力", "recover": "回復", @@ -404,5 +405,15 @@ "signOutOtherDevices": "他のデバイスからサインアウトする", "doNotSignOut": "サインアウトしない", "hearUsWhereTitle": "Ente についてどのようにお聞きになりましたか?(任意)", - "hearUsExplanation": "私たちはアプリのインストールを追跡していません。私たちをお知りになった場所を教えてください!" + "hearUsExplanation": "私たちはアプリのインストールを追跡していません。私たちをお知りになった場所を教えてください!", + "waitingForBrowserRequest": "ブラウザのリクエストを待っています...", + "launchPasskeyUrlAgain": "パスキーのURLを再度起動する", + "passkey": "パスキー", + "developerSettingsWarning": "開発者向け設定を変更してもよろしいですか?", + "developerSettings": "開発者向け設定", + "serverEndpoint": "サーバーエンドポイント", + "invalidEndpoint": "無効なエンドポイントです", + "invalidEndpointMessage": "入力されたエンドポイントは無効です。有効なエンドポイントを入力して再試行してください。", + "endpointUpdatedMessage": "エンドポイントの更新に成功しました", + "customEndpoint": "{endpoint} に接続しました" } \ No newline at end of file diff --git a/auth/lib/l10n/arb/app_pt.arb b/auth/lib/l10n/arb/app_pt.arb index a3f5262e7a..10c34ab296 100644 --- a/auth/lib/l10n/arb/app_pt.arb +++ b/auth/lib/l10n/arb/app_pt.arb @@ -144,6 +144,7 @@ "enterCodeHint": "Digite o código de 6 dígitos de\nseu aplicativo autenticador", "lostDeviceTitle": "Perdeu seu dispositivo?", "twoFactorAuthTitle": "Autenticação de dois fatores", + "passkeyAuthTitle": "Autenticação via Chave de acesso", "recoverAccount": "Recuperar conta", "enterRecoveryKeyHint": "Digite sua chave de recuperação", "recover": "Recuperar", @@ -404,5 +405,15 @@ "signOutOtherDevices": "Terminar sessão em outros dispositivos", "doNotSignOut": "Não encerrar sessão", "hearUsWhereTitle": "Como você ouviu sobre o Ente? (opcional)", - "hearUsExplanation": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!" + "hearUsExplanation": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!", + "waitingForBrowserRequest": "Aguardando solicitação do navegador...", + "launchPasskeyUrlAgain": "Iniciar a URL de chave de acesso novamente", + "passkey": "Chave de acesso", + "developerSettingsWarning": "Tem certeza de que deseja modificar as configurações de Desenvolvedor?", + "developerSettings": "Configurações de desenvolvedor", + "serverEndpoint": "Endpoint do servidor", + "invalidEndpoint": "Endpoint inválido", + "invalidEndpointMessage": "Desculpe, o endpoint que você inseriu é inválido. Por favor, insira um endpoint válido e tente novamente.", + "endpointUpdatedMessage": "Endpoint atualizado com sucesso", + "customEndpoint": "Conectado a {endpoint}" } \ No newline at end of file diff --git a/auth/lib/l10n/arb/app_sv.arb b/auth/lib/l10n/arb/app_sv.arb index faaff39cb2..d99ed5f5f3 100644 --- a/auth/lib/l10n/arb/app_sv.arb +++ b/auth/lib/l10n/arb/app_sv.arb @@ -131,6 +131,16 @@ "about": "Om", "terms": "Villkor", "warning": "Varning", + "importSuccessDesc": "Du har importerat {count} koder!", + "@importSuccessDesc": { + "placeholders": { + "count": { + "description": "The number of codes imported", + "type": "int", + "example": "1" + } + } + }, "pendingSyncs": "Varning", "activeSessions": "Aktiva sessioner", "enterPassword": "Ange lösenord", @@ -143,5 +153,7 @@ "iOSOkButton": "OK", "@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": "Ingen internetanslutning", + "pleaseCheckYourInternetConnectionAndTryAgain": "Kontrollera din internetanslutning och försök igen." } \ No newline at end of file diff --git a/auth/lib/l10n/arb/app_zh.arb b/auth/lib/l10n/arb/app_zh.arb index 6d30306b0b..b6d4ed244f 100644 --- a/auth/lib/l10n/arb/app_zh.arb +++ b/auth/lib/l10n/arb/app_zh.arb @@ -408,5 +408,12 @@ "hearUsExplanation": "我们不跟踪应用程序安装情况。如果您告诉我们您是在哪里找到我们的,将会有所帮助!", "waitingForBrowserRequest": "正在等待浏览器请求...", "launchPasskeyUrlAgain": "再次启动 通行密钥 URL", - "passkey": "通行密钥" + "passkey": "通行密钥", + "developerSettingsWarning": "您确定要修改开发者设置吗?", + "developerSettings": "开发者设置", + "serverEndpoint": "服务器端点", + "invalidEndpoint": "端点无效", + "invalidEndpointMessage": "抱歉,您输入的端点无效。请输入有效的端点,然后重试。", + "endpointUpdatedMessage": "端点更新成功", + "customEndpoint": "已连接至 {endpoint}" } \ No newline at end of file From 83aa3db795a85bb181cb8d54454eec00db8b362f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 13:55:47 +0530 Subject: [PATCH 263/391] [mobile] New translations (#740) New translations from [Crowdin](https://crowdin.com/project/ente-photos-app) Co-authored-by: Crowdin Bot --- .../metadata/android/pt/full_description.txt | 2 +- .../metadata/android/zh/full_description.txt | 10 ++++---- .../fastlane/metadata/ios/pt/description.txt | 2 +- .../playstore/pt/full_description.txt | 2 +- mobile/lib/l10n/intl_de.arb | 25 ++++++++++++++++--- mobile/lib/l10n/intl_pt.arb | 9 ++++--- mobile/lib/l10n/intl_zh.arb | 9 ++++--- 7 files changed, 40 insertions(+), 19 deletions(-) diff --git a/mobile/fastlane/metadata/android/pt/full_description.txt b/mobile/fastlane/metadata/android/pt/full_description.txt index 6719156c65..2bd26df1ec 100644 --- a/mobile/fastlane/metadata/android/pt/full_description.txt +++ b/mobile/fastlane/metadata/android/pt/full_description.txt @@ -1,6 +1,6 @@ ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos. -Se você está procurando uma alternativa ao Google Photos com foco em privacidade, veio ao lugar certo. Com ente, eles são armazenados com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-los. +Se você está procurando uma alternativa ao Google Fotos com foco em privacidade, você veio ao lugar certo. Com ente, eles são armazenados com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-los. Temos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos irão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee). diff --git a/mobile/fastlane/metadata/android/zh/full_description.txt b/mobile/fastlane/metadata/android/zh/full_description.txt index 6eddd122d9..301c5bd352 100644 --- a/mobile/fastlane/metadata/android/zh/full_description.txt +++ b/mobile/fastlane/metadata/android/zh/full_description.txt @@ -1,12 +1,12 @@ ente 是一个简单的应用程序来备份和分享您的照片和视频。 -如果你一直在寻找一个隐私友好的Google Photos替代品,那么你就来对地方了。 使用 Ente,它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。 +如果你一直在寻找一个隐私友好的Google Photos替代品,那么你就来对地方了。 使用 Ente,它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。 使用 Ente,它们以端到端加密 (e2ee) 的方式存储。 这意味着只有您可以查看它们。 我们在Android、iOS、web 和桌面上有开源应用, 和您的照片将以端到端加密方式 (e2ee) 无缝同步。 -ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他们可能并不使用ente。 您可以分享可公开查看的链接,使他们可以查看您的相册,并通过添加照片来协作而不需要注册账户或下载app。 +ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他们可能并不使用ente。 您可以分享可公开查看的链接,使他们可以查看您的相册,并通过添加照片来协作而不需要注册账户或下载app。 权限 -您的加密数据已复制到三个不同的地点,包括巴黎的一个安全屋。 我们认真对待子孙后代,并确保您的回忆比您长寿。 +您的加密数据已复制到三个不同的地点,包括巴黎的一个安全屋。 我们认真对待子孙后代,并确保您的回忆比您长寿。 我们认真对待子孙后代,并确保您的回忆比您长寿。 我们来这里是为了打造有史以来最安全的照片应用,来和我们一起前行! @@ -30,7 +30,7 @@ ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他 ente需要特定权限以执行作为图像存储提供商的职责,相关内容可以在此链接查阅:https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md 价格 -我们不会提供永久免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 +我们不会提供永久免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 支持 -我们对提供真人支持感到自豪。 如果您是我们的付费客户,您可以联系 team@ente.io 并在24小时内收到来自我们团队的回复。 +我们对提供真人支持感到自豪。 我们对提供真人支持感到自豪。 如果您是我们的付费客户,您可以联系 team@ente.io 并在24小时内收到来自我们团队的回复。 diff --git a/mobile/fastlane/metadata/ios/pt/description.txt b/mobile/fastlane/metadata/ios/pt/description.txt index c2c44ed89d..3d948a2b2c 100644 --- a/mobile/fastlane/metadata/ios/pt/description.txt +++ b/mobile/fastlane/metadata/ios/pt/description.txt @@ -1,6 +1,6 @@ Ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos. -Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com ente, eles são armazenados com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-los. +Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com Ente, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las. Temos aplicativos de código aberto em Android, iOS, web e desktop, e suas fotos irão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee). diff --git a/mobile/fastlane/metadata/playstore/pt/full_description.txt b/mobile/fastlane/metadata/playstore/pt/full_description.txt index 18fa7675f7..fc02bad108 100644 --- a/mobile/fastlane/metadata/playstore/pt/full_description.txt +++ b/mobile/fastlane/metadata/playstore/pt/full_description.txt @@ -1,6 +1,6 @@ Ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos. -Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com ente, eles são armazenados com criptografados de ponta a ponta (e2ee). Isso significa que só você pode vê-los. +Se você esteve procurando uma alternativa amigável à privacidade para preservar suas memórias, você veio ao lugar certo. Com Ente, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las. Temos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos irão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee). diff --git a/mobile/lib/l10n/intl_de.arb b/mobile/lib/l10n/intl_de.arb index 117cd799e7..50a4a1b219 100644 --- a/mobile/lib/l10n/intl_de.arb +++ b/mobile/lib/l10n/intl_de.arb @@ -406,6 +406,15 @@ }, "photoGridSize": "Fotorastergröße", "manageDeviceStorage": "Gerätespeicher verwalten", + "machineLearning": "Maschinelles Lernen", + "magicSearch": "Magische Suche", + "magicSearchDescription": "Bitte beachten Sie, dass dies mehr Bandbreite nutzt und zu einem höheren Akkuverbrauch führt, bis alle Elemente indiziert sind.", + "loadingModel": "Lade Modelle herunter...", + "waitingForWifi": "Warte auf WLAN...", + "status": "Status", + "indexedItems": "Indizierte Elemente", + "pendingItems": "Ausstehende Elemente", + "clearIndexes": "Indexe löschen", "selectFoldersForBackup": "Ordner für Sicherung auswählen", "selectedFoldersWillBeEncryptedAndBackedUp": "Ausgewählte Ordner werden verschlüsselt und gesichert", "unselectAll": "Alle demarkieren", @@ -1178,7 +1187,17 @@ "changeLocationOfSelectedItems": "Standort der gewählten Elemente ändern?", "editsToLocationWillOnlyBeSeenWithinEnte": "Änderungen des Standorts werden nur in ente sichtbar sein", "cleanUncategorized": "Unkategorisiert leeren", - "joinDiscord": "Join Discord", - "locations": "Locations", - "descriptions": "Descriptions" + "cleanUncategorizedDescription": "Entferne alle Dateien von \"Unkategorisiert\" die in anderen Alben vorhanden sind", + "waitingForVerification": "Warte auf Bestätigung...", + "passkey": "Passkey", + "passkeyAuthTitle": "Passkey-Verifizierung", + "verifyPasskey": "Passkey verifizieren", + "playOnTv": "Album auf dem Fernseher wiedergeben", + "pair": "Koppeln", + "deviceNotFound": "Gerät nicht gefunden", + "castInstruction": "Besuche cast.ente.io auf dem Gerät, das du verbinden möchtest.\n\nGib den unten angegebenen Code ein, um das Album auf deinem Fernseher abzuspielen.", + "deviceCodeHint": "Code eingeben", + "joinDiscord": "Discord beitreten", + "locations": "Orte", + "descriptions": "Beschreibungen" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_pt.arb b/mobile/lib/l10n/intl_pt.arb index ccbe1b69df..bf0e534097 100644 --- a/mobile/lib/l10n/intl_pt.arb +++ b/mobile/lib/l10n/intl_pt.arb @@ -1187,16 +1187,17 @@ "changeLocationOfSelectedItems": "Alterar o local dos itens selecionados?", "editsToLocationWillOnlyBeSeenWithinEnte": "Edições para local só serão vistas dentro do Ente", "cleanUncategorized": "Limpar Sem Categoria", - "waitingForBrowserRequest": "Aguardando solicitação do navegador...", - "launchPasskeyUrlAgain": "Iniciar a URL de chave de acesso novamente", + "cleanUncategorizedDescription": "Remover todos os arquivos de Não Categorizados que estão presentes em outros álbuns", + "waitingForVerification": "Esperando por verificação...", "passkey": "Chave de acesso", "passkeyAuthTitle": "Autenticação via Chave de acesso", + "verifyPasskey": "Verificar chave de acesso", "playOnTv": "Reproduzir álbum na TV", "pair": "Parear", "deviceNotFound": "Dispositivo não encontrado", "castInstruction": "Visite cast.ente.io no dispositivo que você deseja parear.\n\ndigite o código abaixo para reproduzir o álbum em sua TV.", "deviceCodeHint": "Insira o código", "joinDiscord": "Junte-se ao Discord", - "locations": "Locations", - "descriptions": "Descriptions" + "locations": "Locais", + "descriptions": "Descrições" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_zh.arb b/mobile/lib/l10n/intl_zh.arb index 7519a9aa4a..4e9e9e4eb1 100644 --- a/mobile/lib/l10n/intl_zh.arb +++ b/mobile/lib/l10n/intl_zh.arb @@ -1187,16 +1187,17 @@ "changeLocationOfSelectedItems": "确定要更改所选项目的位置吗?", "editsToLocationWillOnlyBeSeenWithinEnte": "对位置的编辑只能在 Ente 内看到", "cleanUncategorized": "清除未分类的", - "waitingForBrowserRequest": "正在等待浏览器请求...", - "launchPasskeyUrlAgain": "再次启动 通行密钥 URL", + "cleanUncategorizedDescription": "从“未分类”中删除其他相册中存在的所有文件", + "waitingForVerification": "等待验证...", "passkey": "通行密钥", "passkeyAuthTitle": "通行密钥认证", + "verifyPasskey": "验证通行密钥", "playOnTv": "在电视上播放相册", "pair": "配对", "deviceNotFound": "未发现设备", "castInstruction": "在您要配对的设备上访问 cast.ente.io。\n输入下面的代码即可在电视上播放相册。", "deviceCodeHint": "输入代码", "joinDiscord": "加入 Discord", - "locations": "Locations", - "descriptions": "Descriptions" + "locations": "位置", + "descriptions": "描述" } \ No newline at end of file From 2faef37f4b211b8c3faa86343301f93fd9a01f96 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 13 Mar 2024 14:25:07 +0530 Subject: [PATCH 264/391] Fix the upload tests The current approach wasn't working. Not sure what caused it to stop working, but anyway that was an hacky import, as evidenced by the ungainly warning webpack would print on `yarn dev`. So instead of taking the path, we just take the JSON contents directly, sidestepping all that. **Tested by** Rerunning the upload tests --- web/apps/photos/.env.development | 11 ++++++++--- web/apps/photos/tests/upload.test.ts | 8 ++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/web/apps/photos/.env.development b/web/apps/photos/.env.development index 038f0237a9..548e5bbfb1 100644 --- a/web/apps/photos/.env.development +++ b/web/apps/photos/.env.development @@ -68,7 +68,12 @@ # # NEXT_PUBLIC_ENTE_FAMILY_PORTAL_ENDPOINT = http://localhost:3003 -# The path of the JSON file which contains the expected results of our -# integration tests. See `upload.test.ts` for more details. +# The JSON which describes the expected results of our integration tests. See +# `upload.test.ts` for more details of the expected format. # -# NEXT_PUBLIC_ENTE_TEST_EXPECTED_JSON_PATH = /path/to/dataset/expected.json +# This is perhaps easier to specify as an environment variable, since then we +# can directly read from the source file when running `yarn dev`. For example, +# +# NEXT_PUBLIC_ENTE_TEST_EXPECTED_JSON=`cat path/to/expected.json` yarn dev +# +# NEXT_PUBLIC_ENTE_TEST_EXPECTED_JSON = {} diff --git a/web/apps/photos/tests/upload.test.ts b/web/apps/photos/tests/upload.test.ts index dcd16db3c0..6e58cf0c2d 100644 --- a/web/apps/photos/tests/upload.test.ts +++ b/web/apps/photos/tests/upload.test.ts @@ -100,13 +100,13 @@ const FILE_NAME_TO_JSON_NAME = [ ]; export async function testUpload() { - const jsonPath = process.env.NEXT_PUBLIC_ENTE_TEST_EXPECTED_JSON_PATH; - if (!jsonPath) { + const jsonString = process.env.NEXT_PUBLIC_ENTE_TEST_EXPECTED_JSON; + if (!jsonString) { throw Error( - "Please specify the NEXT_PUBLIC_ENTE_TEST_EXPECTED_JSON_PATH to run the upload tests", + "Please specify the NEXT_PUBLIC_ENTE_TEST_EXPECTED_JSON to run the upload tests", ); } - const expectedState = await import(jsonPath); + const expectedState = JSON.parse(jsonString); if (!expectedState) { throw Error("upload test failed expectedState missing"); } From df316463ef9b8289b0e775073c73c011464d2d44 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 14:57:19 +0530 Subject: [PATCH 265/391] Ignore linter on the f-droid branch --- .github/workflows/mobile-lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mobile-lint.yml b/.github/workflows/mobile-lint.yml index 7b5e5fbedb..cbbbbcfbbf 100644 --- a/.github/workflows/mobile-lint.yml +++ b/.github/workflows/mobile-lint.yml @@ -3,7 +3,7 @@ name: "Lint (mobile)" on: # Run on every push to a branch other than main that changes mobile/ push: - branches-ignore: [main] + branches-ignore: [main, f-droid] paths: - "mobile/**" - ".github/workflows/mobile-lint.yml" From 77276d8d6cac4a4c615454a47abef9dbadae4812 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 17:31:38 +0530 Subject: [PATCH 266/391] [server] Add admin API to change email address --- server/cmd/museum/main.go | 1 + server/ente/admin.go | 5 +++++ server/pkg/api/admin.go | 19 +++++++++++++++++++ server/pkg/controller/user/userauth.go | 9 +++++++-- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 9403efaa5a..14ceb3e3bd 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -620,6 +620,7 @@ func main() { adminAPI.POST("/user/disable-2fa", adminHandler.DisableTwoFactor) adminAPI.POST("/user/disable-passkeys", adminHandler.RemovePasskeys) adminAPI.POST("/user/close-family", adminHandler.CloseFamily) + adminAPI.PUT("/user/change-email", adminHandler.ChangeEmail) adminAPI.DELETE("/user/delete", adminHandler.DeleteUser) adminAPI.POST("/user/recover", adminHandler.RecoverAccount) adminAPI.GET("/email-hash", adminHandler.GetEmailHash) diff --git a/server/ente/admin.go b/server/ente/admin.go index 66ad277411..c56e48e5bd 100644 --- a/server/ente/admin.go +++ b/server/ente/admin.go @@ -46,6 +46,11 @@ type UpdateSubscriptionRequest struct { Attributes SubscriptionAttributes `json:"attributes"` } +type ChangeEmailRequest struct { + UserID int64 `json:"userID" binding:"required"` + Email string `json:"email" binding:"required"` +} + type AddOnAction string const ( diff --git a/server/pkg/api/admin.go b/server/pkg/api/admin.go index 90c9fd3e63..b153e19bb1 100644 --- a/server/pkg/api/admin.go +++ b/server/pkg/api/admin.go @@ -306,6 +306,25 @@ func (h *AdminHandler) UpdateSubscription(c *gin.Context) { c.JSON(http.StatusOK, gin.H{}) } +func (h *AdminHandler) ChangeEmail(c *gin.Context) { + var r ente.ChangeEmailRequest + if err := c.ShouldBindJSON(&r); err != nil { + handler.Error(c, stacktrace.Propagate(ente.ErrBadRequest, "Bad request")) + return + } + adminID := auth.GetUserID(c.Request.Header) + go h.DiscordController.NotifyAdminAction( + fmt.Sprintf("Admin (%d) updating email for user: %d", adminID, r.UserID)) + err := h.UserController.UpdateEmail(c, r.UserID, r.Email) + if err != nil { + logrus.WithError(err).Error("Failed to update email") + handler.Error(c, stacktrace.Propagate(err, "")) + return + } + logrus.Info("Updated email") + c.JSON(http.StatusOK, gin.H{}) +} + func (h *AdminHandler) ReQueueItem(c *gin.Context) { var r ente.ReQueueItemRequest if err := c.ShouldBindJSON(&r); err != nil { diff --git a/server/pkg/controller/user/userauth.go b/server/pkg/controller/user/userauth.go index bf092cb147..bbc9942de2 100644 --- a/server/pkg/controller/user/userauth.go +++ b/server/pkg/controller/user/userauth.go @@ -197,7 +197,13 @@ func (c *UserController) ChangeEmail(ctx *gin.Context, request ente.EmailVerific if err != nil { return stacktrace.Propagate(err, "") } - _, err = c.UserRepo.GetUserIDWithEmail(email) + + return c.UpdateEmail(ctx, auth.GetUserID(ctx.Request.Header), email) +} + +// UpdateEmail updates the email address of the user with the provided userID +func (c *UserController) UpdateEmail(ctx *gin.Context, userID int64, email string) error { + _, err := c.UserRepo.GetUserIDWithEmail(email) if err == nil { // email already owned by a user return stacktrace.Propagate(ente.ErrPermissionDenied, "") @@ -206,7 +212,6 @@ func (c *UserController) ChangeEmail(ctx *gin.Context, request ente.EmailVerific // unknown error, rethrow return stacktrace.Propagate(err, "") } - userID := auth.GetUserID(ctx.Request.Header) user, err := c.UserRepo.Get(userID) if err != nil { return stacktrace.Propagate(err, "") From 8d8591cf60f742310b77f4fa1dd20db812734395 Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:44:44 +0100 Subject: [PATCH 267/391] Update authy.md --- auth/migration-guides/authy.md | 85 +++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/auth/migration-guides/authy.md b/auth/migration-guides/authy.md index 4fbc7377fc..9d88ef3821 100644 --- a/auth/migration-guides/authy.md +++ b/auth/migration-guides/authy.md @@ -1,30 +1,68 @@ # Migrating from Authy A guide written by Green, an ente.io lover +> [!WARNING] +> Authy will soon be dropping support for its desktop apps in the near future. If you are looking to switch to ente Authenticator from Authy, I heavily recommend you export your codes as soon as you can. --- -Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. But do not fear, as there is a much simpler way to migrate from Authy to ente! +Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. But do not fear, as there are much simpler ways to migrate from Authy to ente! -A user on GitHub has written a guide to export our data from Authy (morpheus on Discord found this and showed it to us), so we are going to be using that for the migration. +> [!CAUTION] +> There is **NO GUARANTEE** that these methods will export ALL of your codes. Make sure that all your accounts have been imported successfully before deleting any codes from your Authy account! + +--- + +To export your codes from your Authy account, you can use one of these methods, or any other method you fancy that I haven't provided a guide for if you got it to work. + +# Method 1: Use Neeraj's export tool +One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify things and skip directly to importing to ente Authenticator. + +**Who should use this?** General users who want to save time by skipping the hard (and rather technical) parts of the process. ## Exporting from Authy -To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). This will create a new JSON file with all your Authy TOTP data in it. **Do not share this file with anyone!** +To export from Authy, download the tool for your specific OS, then type the following in your terminal: +``` +./ +``` + +So assuming you didn't change the filename of the binary and you've changed the working directory to the location of the binary, you should type this for MacOS: +> [!NOTE] +> On Apple Silicon devices, Rosetta 2 may be required to run the binary. +``` +./authy-export-darwin-amd64 authy_codes.txt +``` + +For Linux: +``` +./authy-export-linux-amd64 authy_codes.txt +``` -Or, you can [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify things and skip directly to importing to ente Authenticator. -### *Do note that these tools may not export ALL of your codes. Make sure that all your accounts have been imported successfully before deleting any codes from your Authy account!* +For Windows: +``` +./authy-export-windows-amd64.exe authy_codes.txt +``` -## Converting the export for ente Authenticator -### Update: You can now directly import from Bitwarden JSON export, meaning you can skip this step! If it doesn't work for some reason, though, then continue with this step. -So now that you have the JSON file, does that mean it can be imported into ente Authenticator? Yes, but if it doesn't work for some reason, then nope. (If you have a TXT file in the format ente Authenticator asked you for instead, then you probably used Neeraj's tool, so you can skip this step.) +This will generate a text file called `authy_codes.txt`, which contains your Authy codes in ente's plaintext export format. You can now import this to ente Authenticator! -This is because the code in the guide exports your Authy data for Bitwarden, not ente Authenticator. If you have opened the JSON file, you might have noticed that the file created is not in a format that ente Authenticator asks for: +# Method 2: Use the GitHub guide +A user on GitHub has written a guide to export our data from Authy (morpheus on Discord found this and showed it to us), so we are going to be using that for the migration. -ente Authenticator Screenshot +**Who should use this?** Power users who have spare time on their hands and prefer a more "known and established" solution to exporting Authy codes. -So, this means that even if you try to import this file, nothing will happen. But don't worry, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use! (It's definitely not written **professionaly**, but hey it gets the job done so I'm happy with that.) +## Exporting from Authy +To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). This will create a new JSON file with all your Authy TOTP data in it. **Do not share this file with anyone!** -You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py). Or if you **really like making life hard**, then you can make a new Python file and copy this code to it: +This will create a JSON file called `authy-to-bitwarden-export.json`, which contains your Authy codes in Bitwarden's export format. You can now import this to ente Authenticator! +# Method 2.1: If the export worked, but the import didn't +> [!NOTE] +> This is intended only for users who successfully exported their codes using the guide, but couldn't import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. +> +> If the export itself failed, try using method 1 instead. + +Usually, you should be able to import Bitwarden exports directly into ente Authenticator. In case this didn't work for whatever reason, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use! + +You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py). Or, you can copy and paste this code (it's the exact same code), if you prefer that more for whatever reason: ```py import json import os @@ -47,16 +85,27 @@ To convert the file with this program, you will need to install [Python](https:/ Before you run the program, make sure that both the Python program and the JSON file are in the same directory, otherwise this will not work! -To run the Python program, open it in IDLE and press F5, or open your terminal and type `python3 authy_to_ente.py` or `py -3 authy_to_ente.py`, depending on which OS you have. Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator! +To run the Python program, open it in your IDE and run the program, or open your terminal and type `python3 authy_to_ente.py` (MacOS/Linux/whatever that uses bash or similar) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator! -## Importing to ente Authenticator -Now that we have the TXT file, let's import it. This should be the easiest part of the entire migration process. +--- +We're in the homestretch now! Now that we have the TXT or JSON file, let's import it. This should be the easiest part of the entire migration process. +# Importing to ente Authenticator (Method 1, method 2.1) 1. Copy the TXT file to one of your devices with ente Authenticator. -2. Log in to your account (if you haven't already). +2. Log in to your account (if you haven't already), or press "Use without backups". 3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes". -4. Select the TXT file that was made earlier. +4. Select the "Plain text" option. +5. Select the TXT file that was made earlier. + +# Importing to ente Authenticator (method 2) +1. Copy the JSON file to one of your devices with ente Authenticator. +2. Log in to your account (if you haven't already), or press "Use without backups". +3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes". +4. Select the "Bitwarden" option. +5. Select the JSON file that was made earlier. + +If this didn't work, refer to [**method 2.1**](#method-21-if-the-export-worked-but-the-import-didnt). And that's it! You have now successfully migrated from Authy to ente Authenticator. -Just one more thing: Now that your secrets are safely stored, I recommend you delete the unencrypted JSON and TXT files that were made during the migration process for security. +Now that your secrets are safely stored, I recommend you delete the unencrypted JSON and TXT files that were made during the migration process for security. From 4ccab22c3f17c87be78553fc61e55ae4b97e27a3 Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:46:53 +0100 Subject: [PATCH 268/391] Update authy.md --- auth/migration-guides/authy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/migration-guides/authy.md b/auth/migration-guides/authy.md index 9d88ef3821..ed5194ad6d 100644 --- a/auth/migration-guides/authy.md +++ b/auth/migration-guides/authy.md @@ -58,7 +58,7 @@ This will create a JSON file called `authy-to-bitwarden-export.json`, which cont > [!NOTE] > This is intended only for users who successfully exported their codes using the guide, but couldn't import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. > -> If the export itself failed, try using method 1 instead. +> If the export itself failed, try using [**method 1**](#method-1-use-neerajs-export-tool) instead. Usually, you should be able to import Bitwarden exports directly into ente Authenticator. In case this didn't work for whatever reason, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use! From f4acb980448854710ab5de9d27419a777bc29485 Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:53:57 +0100 Subject: [PATCH 269/391] Update authy.md --- auth/migration-guides/authy.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/auth/migration-guides/authy.md b/auth/migration-guides/authy.md index ed5194ad6d..fcc37c1ebd 100644 --- a/auth/migration-guides/authy.md +++ b/auth/migration-guides/authy.md @@ -7,19 +7,20 @@ A guide written by Green, an ente.io lover Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. But do not fear, as there are much simpler ways to migrate from Authy to ente! -> [!CAUTION] -> There is **NO GUARANTEE** that these methods will export ALL of your codes. Make sure that all your accounts have been imported successfully before deleting any codes from your Authy account! +> [!CAUTION] +> Under any circumstances, do **NOT** share any JSON and TXT files generated using this guide, as they contain your **unencrypted** TOTP secrets! +> +> Also, there is **NO GUARANTEE** that these methods will export ALL of your codes. Make sure that all your accounts have been imported successfully before deleting any codes from your Authy account! --- To export your codes from your Authy account, you can use one of these methods, or any other method you fancy that I haven't provided a guide for if you got it to work. # Method 1: Use Neeraj's export tool -One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify things and skip directly to importing to ente Authenticator. +**Who should use this?** General users who want to save time by skipping the hard (and rather technical) parts of the process.

-**Who should use this?** General users who want to save time by skipping the hard (and rather technical) parts of the process. +One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify things and skip directly to importing to ente Authenticator. -## Exporting from Authy To export from Authy, download the tool for your specific OS, then type the following in your terminal: ``` ./ @@ -44,13 +45,12 @@ For Windows: This will generate a text file called `authy_codes.txt`, which contains your Authy codes in ente's plaintext export format. You can now import this to ente Authenticator! -# Method 2: Use the GitHub guide -A user on GitHub has written a guide to export our data from Authy (morpheus on Discord found this and showed it to us), so we are going to be using that for the migration. +# Method 2: Use gboudreau's GitHub guide +**Who should use this?** Power users who have spare time on their hands and prefer a more "known and established" solution to exporting Authy codes.

-**Who should use this?** Power users who have spare time on their hands and prefer a more "known and established" solution to exporting Authy codes. +A user on GitHub (gboudreau) wrote a guide to export codes from Authy (morpheus on Discord found this and showed it to us), so we are going to be using that for the migration. -## Exporting from Authy -To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). This will create a new JSON file with all your Authy TOTP data in it. **Do not share this file with anyone!** +To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). This will create a JSON file called `authy-to-bitwarden-export.json`, which contains your Authy codes in Bitwarden's export format. You can now import this to ente Authenticator! @@ -97,14 +97,14 @@ We're in the homestretch now! Now that we have the TXT or JSON file, let's impor 4. Select the "Plain text" option. 5. Select the TXT file that was made earlier. -# Importing to ente Authenticator (method 2) +# Importing to ente Authenticator (Method 2) 1. Copy the JSON file to one of your devices with ente Authenticator. 2. Log in to your account (if you haven't already), or press "Use without backups". 3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes". 4. Select the "Bitwarden" option. 5. Select the JSON file that was made earlier. -If this didn't work, refer to [**method 2.1**](#method-21-if-the-export-worked-but-the-import-didnt). +If this didn't work, refer to [**method 2.1**](#method-21-if-the-export-worked-but-the-import-didnt).

And that's it! You have now successfully migrated from Authy to ente Authenticator. From a4a1ee93f8ec04068ac01369c639dfb07b34ee31 Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:58:08 +0100 Subject: [PATCH 270/391] Update authy.md --- auth/migration-guides/authy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/migration-guides/authy.md b/auth/migration-guides/authy.md index fcc37c1ebd..2f1e2b2360 100644 --- a/auth/migration-guides/authy.md +++ b/auth/migration-guides/authy.md @@ -56,7 +56,7 @@ This will create a JSON file called `authy-to-bitwarden-export.json`, which cont # Method 2.1: If the export worked, but the import didn't > [!NOTE] -> This is intended only for users who successfully exported their codes using the guide, but couldn't import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. +> This is intended only for users who successfully exported their codes using the guide in method 2, but couldn't import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. > > If the export itself failed, try using [**method 1**](#method-1-use-neerajs-export-tool) instead. From 38c36d203a9f9d4dd60d38cad65a801577c562f5 Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:11:33 +0100 Subject: [PATCH 271/391] Create authy.md --- docs/docs/auth/migration-guides/authy.md | 111 +++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 docs/docs/auth/migration-guides/authy.md diff --git a/docs/docs/auth/migration-guides/authy.md b/docs/docs/auth/migration-guides/authy.md new file mode 100644 index 0000000000..2f1e2b2360 --- /dev/null +++ b/docs/docs/auth/migration-guides/authy.md @@ -0,0 +1,111 @@ +# Migrating from Authy +A guide written by Green, an ente.io lover +> [!WARNING] +> Authy will soon be dropping support for its desktop apps in the near future. If you are looking to switch to ente Authenticator from Authy, I heavily recommend you export your codes as soon as you can. + +--- + +Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. But do not fear, as there are much simpler ways to migrate from Authy to ente! + +> [!CAUTION] +> Under any circumstances, do **NOT** share any JSON and TXT files generated using this guide, as they contain your **unencrypted** TOTP secrets! +> +> Also, there is **NO GUARANTEE** that these methods will export ALL of your codes. Make sure that all your accounts have been imported successfully before deleting any codes from your Authy account! + +--- + +To export your codes from your Authy account, you can use one of these methods, or any other method you fancy that I haven't provided a guide for if you got it to work. + +# Method 1: Use Neeraj's export tool +**Who should use this?** General users who want to save time by skipping the hard (and rather technical) parts of the process.

+ +One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify things and skip directly to importing to ente Authenticator. + +To export from Authy, download the tool for your specific OS, then type the following in your terminal: +``` +./ +``` + +So assuming you didn't change the filename of the binary and you've changed the working directory to the location of the binary, you should type this for MacOS: +> [!NOTE] +> On Apple Silicon devices, Rosetta 2 may be required to run the binary. +``` +./authy-export-darwin-amd64 authy_codes.txt +``` + +For Linux: +``` +./authy-export-linux-amd64 authy_codes.txt +``` + +For Windows: +``` +./authy-export-windows-amd64.exe authy_codes.txt +``` + +This will generate a text file called `authy_codes.txt`, which contains your Authy codes in ente's plaintext export format. You can now import this to ente Authenticator! + +# Method 2: Use gboudreau's GitHub guide +**Who should use this?** Power users who have spare time on their hands and prefer a more "known and established" solution to exporting Authy codes.

+ +A user on GitHub (gboudreau) wrote a guide to export codes from Authy (morpheus on Discord found this and showed it to us), so we are going to be using that for the migration. + +To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). + +This will create a JSON file called `authy-to-bitwarden-export.json`, which contains your Authy codes in Bitwarden's export format. You can now import this to ente Authenticator! + +# Method 2.1: If the export worked, but the import didn't +> [!NOTE] +> This is intended only for users who successfully exported their codes using the guide in method 2, but couldn't import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. +> +> If the export itself failed, try using [**method 1**](#method-1-use-neerajs-export-tool) instead. + +Usually, you should be able to import Bitwarden exports directly into ente Authenticator. In case this didn't work for whatever reason, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use! + +You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py). Or, you can copy and paste this code (it's the exact same code), if you prefer that more for whatever reason: +```py +import json +import os + +totp = [] + +accounts = json.load(open('authy-to-bitwarden-export.json','r',encoding='utf-8')) + +for account in accounts['items']: + totp.append(account['login']['totp']+'\n') + +writer = open('auth_codes.txt','w+',encoding='utf-8') +writer.writelines(totp) +writer.close() + +print('Saved to ' + os.getcwd() + '/auth_codes.txt') +``` + +To convert the file with this program, you will need to install [Python](https://www.python.org/downloads/) on your computer. + +Before you run the program, make sure that both the Python program and the JSON file are in the same directory, otherwise this will not work! + +To run the Python program, open it in your IDE and run the program, or open your terminal and type `python3 authy_to_ente.py` (MacOS/Linux/whatever that uses bash or similar) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator! + +--- +We're in the homestretch now! Now that we have the TXT or JSON file, let's import it. This should be the easiest part of the entire migration process. + +# Importing to ente Authenticator (Method 1, method 2.1) +1. Copy the TXT file to one of your devices with ente Authenticator. +2. Log in to your account (if you haven't already), or press "Use without backups". +3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes". +4. Select the "Plain text" option. +5. Select the TXT file that was made earlier. + +# Importing to ente Authenticator (Method 2) +1. Copy the JSON file to one of your devices with ente Authenticator. +2. Log in to your account (if you haven't already), or press "Use without backups". +3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes". +4. Select the "Bitwarden" option. +5. Select the JSON file that was made earlier. + +If this didn't work, refer to [**method 2.1**](#method-21-if-the-export-worked-but-the-import-didnt).

+ +And that's it! You have now successfully migrated from Authy to ente Authenticator. + +Now that your secrets are safely stored, I recommend you delete the unencrypted JSON and TXT files that were made during the migration process for security. From d65daba103a6d588d47b5070f60ba80cbd01ac90 Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:16:52 +0100 Subject: [PATCH 272/391] Update sidebar.ts --- docs/docs/.vitepress/sidebar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index 78a6733f41..0b09bc1b98 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -71,7 +71,7 @@ export const sidebar = [ text: "Migration guides", collapsed: true, items: [ - { text: "Introduction", link: "/auth/migration-guides/" }, + { text: "From Authy", link: "/auth/authy/" }, ], }, ], From 190357fe64bcb6d31d640f0d77ab6349ff132ada Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:17:50 +0100 Subject: [PATCH 273/391] Rename docs/docs/auth/migration-guides/authy.md to docs/docs/auth/migration-guides/authy/index.md --- docs/docs/auth/migration-guides/{authy.md => authy/index.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/docs/auth/migration-guides/{authy.md => authy/index.md} (100%) diff --git a/docs/docs/auth/migration-guides/authy.md b/docs/docs/auth/migration-guides/authy/index.md similarity index 100% rename from docs/docs/auth/migration-guides/authy.md rename to docs/docs/auth/migration-guides/authy/index.md From 4731f2c43b27a086998e8ce5a07a3c9da49656bd Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:22:25 +0100 Subject: [PATCH 274/391] Update sidebar.ts --- docs/docs/.vitepress/sidebar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index 0b09bc1b98..8d50827390 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -71,7 +71,7 @@ export const sidebar = [ text: "Migration guides", collapsed: true, items: [ - { text: "From Authy", link: "/auth/authy/" }, + { text: "From Authy", link: "/auth/migration-guides/authy/" }, ], }, ], From 20a6b81b05a4ec96c8436b0d3f2d3eb5bba64cfa Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:30:54 +0100 Subject: [PATCH 275/391] Update index.md More formal language to make it more wiki-esque --- docs/docs/auth/migration-guides/authy/index.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/docs/auth/migration-guides/authy/index.md b/docs/docs/auth/migration-guides/authy/index.md index 2f1e2b2360..4a0ad936b1 100644 --- a/docs/docs/auth/migration-guides/authy/index.md +++ b/docs/docs/auth/migration-guides/authy/index.md @@ -5,7 +5,7 @@ A guide written by Green, an ente.io lover --- -Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. But do not fear, as there are much simpler ways to migrate from Authy to ente! +Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. However, easier ways exist to export your codes out of Authy. This guide will cover two of the most used methods for mograting from Authy to ente Authenticator. > [!CAUTION] > Under any circumstances, do **NOT** share any JSON and TXT files generated using this guide, as they contain your **unencrypted** TOTP secrets! @@ -14,19 +14,17 @@ Migrating from Authy can be tiring, as you cannot export your 2FA codes through --- -To export your codes from your Authy account, you can use one of these methods, or any other method you fancy that I haven't provided a guide for if you got it to work. - # Method 1: Use Neeraj's export tool **Who should use this?** General users who want to save time by skipping the hard (and rather technical) parts of the process.

-One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify things and skip directly to importing to ente Authenticator. +One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify the process and skip directly to importing to ente Authenticator. To export from Authy, download the tool for your specific OS, then type the following in your terminal: ``` ./ ``` -So assuming you didn't change the filename of the binary and you've changed the working directory to the location of the binary, you should type this for MacOS: +Assuming the filename of the binary remains unmodified and the working directory of the terminal is the location of the binary, you should type this for MacOS: > [!NOTE] > On Apple Silicon devices, Rosetta 2 may be required to run the binary. ``` @@ -56,13 +54,13 @@ This will create a JSON file called `authy-to-bitwarden-export.json`, which cont # Method 2.1: If the export worked, but the import didn't > [!NOTE] -> This is intended only for users who successfully exported their codes using the guide in method 2, but couldn't import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. +> This is intended only for users who successfully exported their codes using the guide in method 2, but could not import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. > > If the export itself failed, try using [**method 1**](#method-1-use-neerajs-export-tool) instead. -Usually, you should be able to import Bitwarden exports directly into ente Authenticator. In case this didn't work for whatever reason, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use! +Usually, you should be able to import Bitwarden exports directly into ente Authenticator. In case this didn't work for whatever reason, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use, so you can try importing using plain text import instead. -You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py). Or, you can copy and paste this code (it's the exact same code), if you prefer that more for whatever reason: +You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py), or you can copy the program below: ```py import json import os @@ -85,10 +83,10 @@ To convert the file with this program, you will need to install [Python](https:/ Before you run the program, make sure that both the Python program and the JSON file are in the same directory, otherwise this will not work! -To run the Python program, open it in your IDE and run the program, or open your terminal and type `python3 authy_to_ente.py` (MacOS/Linux/whatever that uses bash or similar) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator! +To run the Python program, open it in your IDE and run the program, or open your terminal and type `python3 authy_to_ente.py` (MacOS/Linux, or any other OS that uses bash) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator! --- -We're in the homestretch now! Now that we have the TXT or JSON file, let's import it. This should be the easiest part of the entire migration process. +You should now have a TXT file (method 1, method 2.1) or a JSON file (method 2) that countains your TOTP secrets, which can now be imported into ente Authenticator. To import your codes, please follow one of the steps below, depending on which method you used to export your codes. # Importing to ente Authenticator (Method 1, method 2.1) 1. Copy the TXT file to one of your devices with ente Authenticator. From 1cacefa1fdfe2fff6fa4f1e40da5339f95fadf9a Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Wed, 13 Mar 2024 21:56:48 +0530 Subject: [PATCH 276/391] v0.8.71 --- mobile/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index fdf00a1d21..3adcf3ca32 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -12,7 +12,7 @@ description: ente photos application # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 0.8.70+590 +version: 0.8.71+591 publish_to: none environment: From 0b96b1afe6a8c2c8f54464fc4af4f8224267f1ef Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:05:52 +0100 Subject: [PATCH 277/391] Use same style as wiki --- auth/migration-guides/authy.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/auth/migration-guides/authy.md b/auth/migration-guides/authy.md index 2f1e2b2360..4a0ad936b1 100644 --- a/auth/migration-guides/authy.md +++ b/auth/migration-guides/authy.md @@ -5,7 +5,7 @@ A guide written by Green, an ente.io lover --- -Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. But do not fear, as there are much simpler ways to migrate from Authy to ente! +Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. However, easier ways exist to export your codes out of Authy. This guide will cover two of the most used methods for mograting from Authy to ente Authenticator. > [!CAUTION] > Under any circumstances, do **NOT** share any JSON and TXT files generated using this guide, as they contain your **unencrypted** TOTP secrets! @@ -14,19 +14,17 @@ Migrating from Authy can be tiring, as you cannot export your 2FA codes through --- -To export your codes from your Authy account, you can use one of these methods, or any other method you fancy that I haven't provided a guide for if you got it to work. - # Method 1: Use Neeraj's export tool **Who should use this?** General users who want to save time by skipping the hard (and rather technical) parts of the process.

-One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify things and skip directly to importing to ente Authenticator. +One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify the process and skip directly to importing to ente Authenticator. To export from Authy, download the tool for your specific OS, then type the following in your terminal: ``` ./ ``` -So assuming you didn't change the filename of the binary and you've changed the working directory to the location of the binary, you should type this for MacOS: +Assuming the filename of the binary remains unmodified and the working directory of the terminal is the location of the binary, you should type this for MacOS: > [!NOTE] > On Apple Silicon devices, Rosetta 2 may be required to run the binary. ``` @@ -56,13 +54,13 @@ This will create a JSON file called `authy-to-bitwarden-export.json`, which cont # Method 2.1: If the export worked, but the import didn't > [!NOTE] -> This is intended only for users who successfully exported their codes using the guide in method 2, but couldn't import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. +> This is intended only for users who successfully exported their codes using the guide in method 2, but could not import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. > > If the export itself failed, try using [**method 1**](#method-1-use-neerajs-export-tool) instead. -Usually, you should be able to import Bitwarden exports directly into ente Authenticator. In case this didn't work for whatever reason, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use! +Usually, you should be able to import Bitwarden exports directly into ente Authenticator. In case this didn't work for whatever reason, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use, so you can try importing using plain text import instead. -You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py). Or, you can copy and paste this code (it's the exact same code), if you prefer that more for whatever reason: +You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py), or you can copy the program below: ```py import json import os @@ -85,10 +83,10 @@ To convert the file with this program, you will need to install [Python](https:/ Before you run the program, make sure that both the Python program and the JSON file are in the same directory, otherwise this will not work! -To run the Python program, open it in your IDE and run the program, or open your terminal and type `python3 authy_to_ente.py` (MacOS/Linux/whatever that uses bash or similar) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator! +To run the Python program, open it in your IDE and run the program, or open your terminal and type `python3 authy_to_ente.py` (MacOS/Linux, or any other OS that uses bash) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator! --- -We're in the homestretch now! Now that we have the TXT or JSON file, let's import it. This should be the easiest part of the entire migration process. +You should now have a TXT file (method 1, method 2.1) or a JSON file (method 2) that countains your TOTP secrets, which can now be imported into ente Authenticator. To import your codes, please follow one of the steps below, depending on which method you used to export your codes. # Importing to ente Authenticator (Method 1, method 2.1) 1. Copy the TXT file to one of your devices with ente Authenticator. From 3b10c7e93f747219c47d95ec1caa2b0461814768 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 09:20:17 +0530 Subject: [PATCH 278/391] [meta] Reintroduce .vscode in the mobile gitignores The intent had always been to have the individual project gitignores be self contained. In my previous PR (https://github.com/ente-io/ente/pull/516) I'd for some reason not followed this: correcting my mistake now. .vscode is gitignored both at the top level and at the individual project levels (as it was originally). --- auth/.gitignore | 3 +++ mobile/.gitignore | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/auth/.gitignore b/auth/.gitignore index b909f8341f..3d6f77b840 100644 --- a/auth/.gitignore +++ b/auth/.gitignore @@ -9,6 +9,9 @@ .history .svn/ +# Editors +.vscode/ + # IntelliJ related *.iml *.ipr diff --git a/mobile/.gitignore b/mobile/.gitignore index 47e6ea41bf..b6ee5c6161 100644 --- a/mobile/.gitignore +++ b/mobile/.gitignore @@ -9,6 +9,9 @@ .history .svn/ +# Editors +.vscode/ + # IntelliJ related *.iml *.ipr @@ -25,7 +28,6 @@ .pub/ /build/ - # Web related lib/generated_plugin_registrant.dart @@ -37,6 +39,5 @@ android/app/.settings/* android/.settings/ .env - fastlane/report.xml TensorFlowLiteC.framework From 1abf7edb99dbc55164665bb47e19388f290891ed Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 09:29:40 +0530 Subject: [PATCH 279/391] [meta] Reduce the frequency of the sync translations cron Every day is too much noise - we really only need this - When a string gets changed in the source translation, in which case this workflow gets triggered automatically anyway. - Before we do a new release (this doesn't automatically happen, but the workflow can be triggered manually if needed). For now, reduce the frequency of the daily job to pull new translations from Crowdin: now it'll only happen on Tuesdays and Fridays (just an arbitrary choice). --- .github/workflows/auth-crowdin.yml | 4 ++-- .github/workflows/mobile-crowdin.yml | 4 ++-- .github/workflows/web-crowdin.yml | 10 ++++++++-- .github/workflows/web-nightly.yml | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/auth-crowdin.yml b/.github/workflows/auth-crowdin.yml index d472cf594a..f269a8c8df 100644 --- a/.github/workflows/auth-crowdin.yml +++ b/.github/workflows/auth-crowdin.yml @@ -9,8 +9,8 @@ on: - ".github/workflows/auth-crowdin.yml" branches: [main] schedule: - # See: [Note: Run every 24 hours] - - cron: "50 1 * * *" + # See: [Note: Run workflow on specific days of the week] + - cron: "50 1 * * 2,5" # Also allow manually running the workflow workflow_dispatch: diff --git a/.github/workflows/mobile-crowdin.yml b/.github/workflows/mobile-crowdin.yml index e12ab9aac7..35b4c38769 100644 --- a/.github/workflows/mobile-crowdin.yml +++ b/.github/workflows/mobile-crowdin.yml @@ -9,8 +9,8 @@ on: - ".github/workflows/mobile-crowdin.yml" branches: [main] schedule: - # See: [Note: Run every 24 hours] - - cron: "40 1 * * *" + # See: [Note: Run workflow on specific days of the week] + - cron: "40 1 * * 2,5" # Also allow manually running the workflow workflow_dispatch: diff --git a/.github/workflows/web-crowdin.yml b/.github/workflows/web-crowdin.yml index c8acb23223..8733167d65 100644 --- a/.github/workflows/web-crowdin.yml +++ b/.github/workflows/web-crowdin.yml @@ -9,8 +9,14 @@ on: - ".github/workflows/web-crowdin.yml" branches: [main] schedule: - # See: [Note: Run every 24 hours] - - cron: "20 1 * * *" + # [Note: Run workflow on specific days of the week] + # + # The last (5th) component of the cron syntax denotes the day of the + # week, with 0 == SUN and 6 == SAT. So, for example, to run on every TUE + # and FRI, this can be set to `2,5`. + # + # See also: [Note: Run workflow every 24 hours] + - cron: "20 1 * * 2,5" # Also allow manually running the workflow workflow_dispatch: diff --git a/.github/workflows/web-nightly.yml b/.github/workflows/web-nightly.yml index 3672b8b487..a800a4b736 100644 --- a/.github/workflows/web-nightly.yml +++ b/.github/workflows/web-nightly.yml @@ -2,7 +2,7 @@ name: "Nightly (web)" on: schedule: - # [Note: Run every 24 hours] + # [Note: Run workflow every 24 hours] # # Run every 24 hours - First field is minute, second is hour of the day # This runs 23:15 UTC everyday - 1 and 15 are just arbitrary offset to From 7fabb3a03cbf58a35d95e2555bb768b50dd1a8b9 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 09:47:12 +0530 Subject: [PATCH 280/391] [meta] Document the tag format, and call out the need to keep tag == title Related: https://github.com/ente-io/ente/discussions/1087#discussioncomment-8775807 --- auth/docs/release.md | 16 ++++++++++++++-- cli/docs/release.md | 5 +++++ mobile/docs/release.md | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 mobile/docs/release.md diff --git a/auth/docs/release.md b/auth/docs/release.md index afc80076aa..4b31c72f0a 100644 --- a/auth/docs/release.md +++ b/auth/docs/release.md @@ -1,7 +1,14 @@ # Releases -Create a PR to bump up the version in `pubspec.yaml`. Once that is merged, tag -main, and push the tag. +Create a PR to bump up the version in `pubspec.yaml`. + +> [!NOTE] +> +> Use [semver](https://semver.org/) for the tags, with `auth-` as a prefix. +> Multiple beta releases for the same upcoming version can be done by adding +> build metadata at the end, e.g. `auth-v1.2.3-beta+3`. + +Once that is merged, tag main, and push the tag. ```sh git tag auth-v1.2.3 @@ -16,6 +23,11 @@ This'll trigger a GitHub workflow that: * Creates a new release in the internal track on Play Store. Once the workflow completes, go to the draft GitHub release that was created. + +> [!NOTE] +> +> Keep the title of the release same as the tag. + Set "Previous tag" to the last release of auth and press "Generate release notes". The generated release note will contain all PRs and new contributors from all the releases in the monorepo, so you'll need to filter them to keep diff --git a/cli/docs/release.md b/cli/docs/release.md index a539e7e5d5..dce097eafe 100644 --- a/cli/docs/release.md +++ b/cli/docs/release.md @@ -2,6 +2,11 @@ Tag main, and push the tag. +> [!NOTE] +> +> See [auth/docs/release](../../auth/docs/release.md) for more details about the +> tag format. The prefix for cli releases should be `cli-`. + ```sh git tag cli-v1.2.3 git push origin cli-v1.2.3 diff --git a/mobile/docs/release.md b/mobile/docs/release.md new file mode 100644 index 0000000000..c7b4f50819 --- /dev/null +++ b/mobile/docs/release.md @@ -0,0 +1,32 @@ +# Releases + +Create a PR to bump up the version in `pubspec.yaml`. + +> [!NOTE] +> +> Use [semver](https://semver.org/) for the tags, with `photos-` as a prefix. +> Multiple beta releases for the same upcoming version can be done by adding +> build metadata at the end, e.g. `photos-v1.2.3-beta+3`. + +Once that is merged, tag main, and push the tag. + +```sh +git tag photos-v1.2.3 +git push origin photos-v1.2.3 +``` + +This'll trigger a GitHub workflow that: + +* Creates a new draft GitHub release and attaches the build artifacts to it + (mobile APKs), + +Once the workflow completes, go to the draft GitHub release that was created. + +> [!NOTE] +> +> Keep the title of the release same as the tag. + +Set "Previous tag" to the last release of auth and press "Generate release +notes". The generated release note will contain all PRs and new contributors +from all the releases in the monorepo, so you'll need to filter them to keep +only the things that relate to the Photos mobile app. From 419f562aedf192632e70ddcbed367b1e9086f875 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Thu, 14 Mar 2024 04:22:53 +0000 Subject: [PATCH 281/391] New Crowdin translations by GitHub Action --- .../public/locales/de-DE/translation.json | 20 +-- .../public/locales/ko-KR/translation.json | 144 +++++++++--------- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/web/apps/photos/public/locales/de-DE/translation.json b/web/apps/photos/public/locales/de-DE/translation.json index f5a6f13b3f..a515e7366b 100644 --- a/web/apps/photos/public/locales/de-DE/translation.json +++ b/web/apps/photos/public/locales/de-DE/translation.json @@ -277,7 +277,7 @@ "START": "Start", "LAST_EXPORT_TIME": "Letztes Exportdatum", "EXPORT_AGAIN": "Neusynchronisation", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Lokaler Speicher nicht zugänglich", "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", "SEND_OTT": "OTP senden", "EMAIl_ALREADY_OWNED": "Diese E-Mail wird bereits verwendet", @@ -356,22 +356,22 @@ "DATE_TIME_ORIGINAL": "", "DATE_TIME_DIGITIZED": "", "METADATA_DATE": "", - "CUSTOM_TIME": "", + "CUSTOM_TIME": "Benutzerdefinierte Zeit", "REOPEN_PLAN_SELECTOR_MODAL": "", "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", "INSTALL": "Installieren", "SHARING_DETAILS": "Details teilen", - "MODIFY_SHARING": "", - "ADD_COLLABORATORS": "", - "ADD_NEW_EMAIL": "", + "MODIFY_SHARING": "Freigabe ändern", + "ADD_COLLABORATORS": "Bearbeiter hinzufügen", + "ADD_NEW_EMAIL": "Neue E-Mail-Adresse hinzufügen", "shared_with_people_zero": "", - "shared_with_people_one": "", + "shared_with_people_one": "Geteilt mit einer Person", "shared_with_people_other": "", - "participants_zero": "", - "participants_one": "", + "participants_zero": "Keine Teilnehmer", + "participants_one": "1 Teilnehmer", "participants_other": "", - "ADD_VIEWERS": "", - "PARTICIPANTS": "", + "ADD_VIEWERS": "Betrachter hinzufügen", + "PARTICIPANTS": "Teilnehmer", "CHANGE_PERMISSIONS_TO_VIEWER": "", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", "CONVERT_TO_VIEWER": "Ja, zu \"Beobachter\" ändern", diff --git a/web/apps/photos/public/locales/ko-KR/translation.json b/web/apps/photos/public/locales/ko-KR/translation.json index 754fef8928..7482dd3979 100644 --- a/web/apps/photos/public/locales/ko-KR/translation.json +++ b/web/apps/photos/public/locales/ko-KR/translation.json @@ -2,80 +2,80 @@ "HERO_SLIDE_1_TITLE": "추억을 안전하게 백업하세요", "HERO_SLIDE_1": "종단간 암호화가 기본지원입니다", "HERO_SLIDE_2_TITLE": "낙진대피소에 안전하게 보관됩니다", - "HERO_SLIDE_2": "", - "HERO_SLIDE_3_TITLE": "", - "HERO_SLIDE_3": "", - "LOGIN": "", - "SIGN_UP": "", - "NEW_USER": "", - "EXISTING_USER": "", - "ENTER_NAME": "", - "PUBLIC_UPLOADER_NAME_MESSAGE": "", - "ENTER_EMAIL": "", - "EMAIL_ERROR": "", - "REQUIRED": "", - "EMAIL_SENT": "", - "CHECK_INBOX": "", - "ENTER_OTT": "", - "RESEND_MAIL": "", - "VERIFY": "", - "UNKNOWN_ERROR": "", - "INVALID_CODE": "", - "EXPIRED_CODE": "", - "SENDING": "", - "SENT": "", - "PASSWORD": "", - "LINK_PASSWORD": "", - "RETURN_PASSPHRASE_HINT": "", - "SET_PASSPHRASE": "", - "VERIFY_PASSPHRASE": "", - "INCORRECT_PASSPHRASE": "", - "ENTER_ENC_PASSPHRASE": "", - "PASSPHRASE_DISCLAIMER": "", - "WELCOME_TO_ENTE_HEADING": "", - "WELCOME_TO_ENTE_SUBHEADING": "", - "WHERE_YOUR_BEST_PHOTOS_LIVE": "", - "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", - "PASSPHRASE_HINT": "", - "CONFIRM_PASSPHRASE": "", - "REFERRAL_CODE_HINT": "", - "REFERRAL_INFO": "", - "PASSPHRASE_MATCH_ERROR": "", - "CREATE_COLLECTION": "", - "ENTER_ALBUM_NAME": "", - "CLOSE_OPTION": "", - "ENTER_FILE_NAME": "", - "CLOSE": "", - "NO": "", - "NOTHING_HERE": "", - "UPLOAD": "", - "IMPORT": "", - "ADD_PHOTOS": "", - "ADD_MORE_PHOTOS": "", - "add_photos_one": "", - "add_photos_other": "", - "SELECT_PHOTOS": "", - "FILE_UPLOAD": "", + "HERO_SLIDE_2": "오랫동안 보존할 수 있도록한 설계", + "HERO_SLIDE_3_TITLE": "
어디에서나
이용가능
", + "HERO_SLIDE_3": "안드로이드, iOS, 웹, 데스크탑", + "LOGIN": "로그인", + "SIGN_UP": "회원가입", + "NEW_USER": "ente의 새소식", + "EXISTING_USER": "기존 사용자", + "ENTER_NAME": "이름 입력", + "PUBLIC_UPLOADER_NAME_MESSAGE": "친구들이 이 멋진 사진에 대해 고마워할 수 있도록 이름을 추가하세요!", + "ENTER_EMAIL": "이메일 주소를 입력하세요", + "EMAIL_ERROR": "올바른 이메일을 입력하세요", + "REQUIRED": "필수", + "EMAIL_SENT": "{{email}} 로 인증 코드가 전송되었습니다", + "CHECK_INBOX": "인증을 완료하기 위해 당신의 메일 수신함(그리고 스팸 수신함)을 확인하세요.", + "ENTER_OTT": "인증 코드", + "RESEND_MAIL": "코드 재전송하기", + "VERIFY": "인증", + "UNKNOWN_ERROR": "문제가 생긴 것 같아요. 다시 시도하세요", + "INVALID_CODE": "잘못된 인증 코드", + "EXPIRED_CODE": "입력한 인증 코드가 만료되었습니다", + "SENDING": "전송 중...", + "SENT": "발송 완료!", + "PASSWORD": "비밀번호", + "LINK_PASSWORD": "앨범 잠금해제를 위해 비밀번호를 입력하세요", + "RETURN_PASSPHRASE_HINT": "비밀번호", + "SET_PASSPHRASE": "비밀번호 설정", + "VERIFY_PASSPHRASE": "로그인", + "INCORRECT_PASSPHRASE": "잘못된 비밀번호입니다", + "ENTER_ENC_PASSPHRASE": "당신의 데이터를 암호화하는 데 사용할 수 있는 비밀번호를 입력하세요", + "PASSPHRASE_DISCLAIMER": "우리는 귀하의 비밀번호를 저장하지 않습니다. 만약 비밀번호를 잊어버린 경우 복구 키 없다면 데이터 복구를 도와드릴 수 없습니다.", + "WELCOME_TO_ENTE_HEADING": "환영합니다 ", + "WELCOME_TO_ENTE_SUBHEADING": "End-to-End 암호화된 사진 저장 및 공유", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "당신 최고의 사진이 있는 곳", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "암호 키 생성 중...", + "PASSPHRASE_HINT": "비밀번호", + "CONFIRM_PASSPHRASE": "비밀번호 확인", + "REFERRAL_CODE_HINT": "어떻게 Ente에 대해 들으셨나요? (선택사항)", + "REFERRAL_INFO": "우리는 앱 설치를 추적하지 않습니다. 우리를 알게 된 곳을 남겨주시면 우리에게 도움이 될꺼에요!", + "PASSPHRASE_MATCH_ERROR": "비밀번호가 일치하지 않습니다", + "CREATE_COLLECTION": "새 앨범", + "ENTER_ALBUM_NAME": "앨범 이름", + "CLOSE_OPTION": "닫기 (Esc)", + "ENTER_FILE_NAME": "파일 이름", + "CLOSE": "닫기", + "NO": "아니오", + "NOTHING_HERE": "아직 볼 수 있는 것이 없어요 👀", + "UPLOAD": "업로드", + "IMPORT": "가져오기", + "ADD_PHOTOS": "사진 추가", + "ADD_MORE_PHOTOS": "사진 더 추가하기", + "add_photos_one": "아이템 하나 추가", + "add_photos_other": "아이템 {{count, number}} 개 추가하기", + "SELECT_PHOTOS": "사진 선택하기", + "FILE_UPLOAD": "파일 업로드", "UPLOAD_STAGE_MESSAGE": { - "0": "", - "1": "", - "2": "", - "3": "", - "4": "", - "5": "" + "0": "업로드 준비중", + "1": "구글 메타데이타 파일들 읽는중", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} 파일 메타데이터가 추출되었습니다", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} 파일이 처리되었습니다", + "4": "남은 업로드 취소중", + "5": "백업 완료" }, - "FILE_NOT_UPLOADED_LIST": "", - "SUBSCRIPTION_EXPIRED": "", - "SUBSCRIPTION_EXPIRED_MESSAGE": "", - "STORAGE_QUOTA_EXCEEDED": "", - "INITIAL_LOAD_DELAY_WARNING": "", - "USER_DOES_NOT_EXIST": "", - "NO_ACCOUNT": "", - "ACCOUNT_EXISTS": "", - "CREATE": "", - "DOWNLOAD": "", - "DOWNLOAD_OPTION": "", - "DOWNLOAD_FAVORITES": "", + "FILE_NOT_UPLOADED_LIST": "아래 파일들은 업로드 되지 않았습니다", + "SUBSCRIPTION_EXPIRED": "구독 만료", + "SUBSCRIPTION_EXPIRED_MESSAGE": "당신 구독이 만료되었으니, 구독을 갱신해주세요", + "STORAGE_QUOTA_EXCEEDED": "스토리지 제한이 초과되었습니다", + "INITIAL_LOAD_DELAY_WARNING": "처음 로딩시 다소 시간이 걸릴 수 있습니다", + "USER_DOES_NOT_EXIST": "죄송합니다. 해당 이메일을 사용하는 사용자를 찾을 수 없습니다", + "NO_ACCOUNT": "계정이 없습니다", + "ACCOUNT_EXISTS": "이미 계정이 있습니다", + "CREATE": "만들기", + "DOWNLOAD": "다운로드", + "DOWNLOAD_OPTION": "다운로드 (D)", + "DOWNLOAD_FAVORITES": "즐겨찾기 다운로드", "DOWNLOAD_UNCATEGORIZED": "", "DOWNLOAD_HIDDEN_ITEMS": "", "COPY_OPTION": "", From bb0f584e91dce7f9c5f4cb7bd1ca0379927e00b7 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 10:30:43 +0530 Subject: [PATCH 282/391] [docs][auth] Move the migration guides to the help docs Keep the old files, adding redirection notices to them. --- auth/migration-guides/README.md | 4 + auth/migration-guides/authy.md | 111 +----------------- auth/migration-guides/encrypted_export.md | 65 +--------- docs/docs/.vitepress/sidebar.ts | 11 +- .../docs/auth/migration-guides/authy/index.md | 10 +- docs/docs/auth/migration-guides/export.md | 63 ++++++++++ docs/docs/auth/migration-guides/index.md | 10 +- 7 files changed, 89 insertions(+), 185 deletions(-) create mode 100644 auth/migration-guides/README.md create mode 100644 docs/docs/auth/migration-guides/export.md diff --git a/auth/migration-guides/README.md b/auth/migration-guides/README.md new file mode 100644 index 0000000000..56d8983d07 --- /dev/null +++ b/auth/migration-guides/README.md @@ -0,0 +1,4 @@ +Migration guides have moved to the [help +docs](https://help.ente.io/auth/migration-guides/). This folder just contains +redirects for old links. + diff --git a/auth/migration-guides/authy.md b/auth/migration-guides/authy.md index 4a0ad936b1..630bc83c7f 100644 --- a/auth/migration-guides/authy.md +++ b/auth/migration-guides/authy.md @@ -1,109 +1,2 @@ -# Migrating from Authy -A guide written by Green, an ente.io lover -> [!WARNING] -> Authy will soon be dropping support for its desktop apps in the near future. If you are looking to switch to ente Authenticator from Authy, I heavily recommend you export your codes as soon as you can. - ---- - -Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. However, easier ways exist to export your codes out of Authy. This guide will cover two of the most used methods for mograting from Authy to ente Authenticator. - -> [!CAUTION] -> Under any circumstances, do **NOT** share any JSON and TXT files generated using this guide, as they contain your **unencrypted** TOTP secrets! -> -> Also, there is **NO GUARANTEE** that these methods will export ALL of your codes. Make sure that all your accounts have been imported successfully before deleting any codes from your Authy account! - ---- - -# Method 1: Use Neeraj's export tool -**Who should use this?** General users who want to save time by skipping the hard (and rather technical) parts of the process.

- -One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify the process and skip directly to importing to ente Authenticator. - -To export from Authy, download the tool for your specific OS, then type the following in your terminal: -``` -./ -``` - -Assuming the filename of the binary remains unmodified and the working directory of the terminal is the location of the binary, you should type this for MacOS: -> [!NOTE] -> On Apple Silicon devices, Rosetta 2 may be required to run the binary. -``` -./authy-export-darwin-amd64 authy_codes.txt -``` - -For Linux: -``` -./authy-export-linux-amd64 authy_codes.txt -``` - -For Windows: -``` -./authy-export-windows-amd64.exe authy_codes.txt -``` - -This will generate a text file called `authy_codes.txt`, which contains your Authy codes in ente's plaintext export format. You can now import this to ente Authenticator! - -# Method 2: Use gboudreau's GitHub guide -**Who should use this?** Power users who have spare time on their hands and prefer a more "known and established" solution to exporting Authy codes.

- -A user on GitHub (gboudreau) wrote a guide to export codes from Authy (morpheus on Discord found this and showed it to us), so we are going to be using that for the migration. - -To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). - -This will create a JSON file called `authy-to-bitwarden-export.json`, which contains your Authy codes in Bitwarden's export format. You can now import this to ente Authenticator! - -# Method 2.1: If the export worked, but the import didn't -> [!NOTE] -> This is intended only for users who successfully exported their codes using the guide in method 2, but could not import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. -> -> If the export itself failed, try using [**method 1**](#method-1-use-neerajs-export-tool) instead. - -Usually, you should be able to import Bitwarden exports directly into ente Authenticator. In case this didn't work for whatever reason, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use, so you can try importing using plain text import instead. - -You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py), or you can copy the program below: -```py -import json -import os - -totp = [] - -accounts = json.load(open('authy-to-bitwarden-export.json','r',encoding='utf-8')) - -for account in accounts['items']: - totp.append(account['login']['totp']+'\n') - -writer = open('auth_codes.txt','w+',encoding='utf-8') -writer.writelines(totp) -writer.close() - -print('Saved to ' + os.getcwd() + '/auth_codes.txt') -``` - -To convert the file with this program, you will need to install [Python](https://www.python.org/downloads/) on your computer. - -Before you run the program, make sure that both the Python program and the JSON file are in the same directory, otherwise this will not work! - -To run the Python program, open it in your IDE and run the program, or open your terminal and type `python3 authy_to_ente.py` (MacOS/Linux, or any other OS that uses bash) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator! - ---- -You should now have a TXT file (method 1, method 2.1) or a JSON file (method 2) that countains your TOTP secrets, which can now be imported into ente Authenticator. To import your codes, please follow one of the steps below, depending on which method you used to export your codes. - -# Importing to ente Authenticator (Method 1, method 2.1) -1. Copy the TXT file to one of your devices with ente Authenticator. -2. Log in to your account (if you haven't already), or press "Use without backups". -3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes". -4. Select the "Plain text" option. -5. Select the TXT file that was made earlier. - -# Importing to ente Authenticator (Method 2) -1. Copy the JSON file to one of your devices with ente Authenticator. -2. Log in to your account (if you haven't already), or press "Use without backups". -3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes". -4. Select the "Bitwarden" option. -5. Select the JSON file that was made earlier. - -If this didn't work, refer to [**method 2.1**](#method-21-if-the-export-worked-but-the-import-didnt).

- -And that's it! You have now successfully migrated from Authy to ente Authenticator. - -Now that your secrets are safely stored, I recommend you delete the unencrypted JSON and TXT files that were made during the migration process for security. +Moved to +[help.ente.io/auth/migration-guides/authy](https://help.ente.io/auth/migration-guides/authy/) diff --git a/auth/migration-guides/encrypted_export.md b/auth/migration-guides/encrypted_export.md index b4e64134e4..80a844c858 100644 --- a/auth/migration-guides/encrypted_export.md +++ b/auth/migration-guides/encrypted_export.md @@ -1,63 +1,2 @@ -# Auth Encrypted Export format - -## Overview - -When we export the auth codes, the data is encrypted using a key derived from the user's password. -This document describes the JSON structure used to organize exported data, including versioning and key derivation -parameters. - -## Export JSON Sample - -```json -{ - "version": 1, - "kdfParams": { - "memLimit": 4096, - "opsLimit": 3, - "salt": "example_salt" - }, - "encryptedData": "encrypted_data_here", - "encryptionNonce": "nonce_here" -} -``` - -The main object used to represent the export data. It contains the following key-value pairs: - -- `version`: The version of the export format. -- `kdfParams`: Key derivation function parameters. -- `encryptedData"`: The encrypted authentication data. -- `encryptionNonce`: The nonce used for encryption. - -### Version - -Export version is used to identify the format of the export data. - -#### Ver: 1 - -* KDF Algorithm: `ARGON2ID` -* Decrypted data format: `otpauth://totp/...`, separated by a new line. -* Encryption Algo: `XChaCha20-Poly1305` - -#### Key Derivation Function Params (KDF) - -This section contains the parameters that were using during KDF operation: - -- `memLimit`: Memory limit for the algorithm. -- `opsLimit`: Operations limit for the algorithm. -- `salt`: The salt used in the derivation process. - -#### Encrypted Data - -As mentioned above, the auth data is encrypted using a key that's derived by using user provided password & kdf params. -For encryption, we are using `XChaCha20-Poly1305` algorithm. - -## How to use the exported data - -* **Ente Authenticator app**: You can directly import the codes in the Ente Authenticator app. - > Settings -> Data -> Import Codes -> ente Encrypted export. - -* **Decrypt using Ente CLI** : Download the latest version of [Ente CLI](https://github.com/ente-io/ente/releases?q=CLI&expanded=false), and run the following command - -``` - ./ente auth decrypt -``` +Moved to +[help.ente.io/auth/migration-guides/export](https://help.ente.io/auth/migration-guides/export/) diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index 8d50827390..48d3df1f93 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -69,9 +69,16 @@ export const sidebar = [ { text: "FAQ", link: "/auth/faq/" }, { text: "Migration guides", - collapsed: true, + collapsed: false, items: [ - { text: "From Authy", link: "/auth/migration-guides/authy/" }, + { + text: "From Authy", + link: "/auth/migration-guides/authy/", + }, + { + text: "Out of Ente", + link: "/auth/migration-guides/export", + }, ], }, ], diff --git a/docs/docs/auth/migration-guides/authy/index.md b/docs/docs/auth/migration-guides/authy/index.md index 4a0ad936b1..3996367905 100644 --- a/docs/docs/auth/migration-guides/authy/index.md +++ b/docs/docs/auth/migration-guides/authy/index.md @@ -1,6 +1,6 @@ # Migrating from Authy A guide written by Green, an ente.io lover -> [!WARNING] +> [!WARNING] > Authy will soon be dropping support for its desktop apps in the near future. If you are looking to switch to ente Authenticator from Authy, I heavily recommend you export your codes as soon as you can. --- @@ -9,7 +9,7 @@ Migrating from Authy can be tiring, as you cannot export your 2FA codes through > [!CAUTION] > Under any circumstances, do **NOT** share any JSON and TXT files generated using this guide, as they contain your **unencrypted** TOTP secrets! -> +> > Also, there is **NO GUARANTEE** that these methods will export ALL of your codes. Make sure that all your accounts have been imported successfully before deleting any codes from your Authy account! --- @@ -25,7 +25,7 @@ To export from Authy, download the tool for your specific OS, then type the foll ``` Assuming the filename of the binary remains unmodified and the working directory of the terminal is the location of the binary, you should type this for MacOS: -> [!NOTE] +> [!NOTE] > On Apple Silicon devices, Rosetta 2 may be required to run the binary. ``` ./authy-export-darwin-amd64 authy_codes.txt @@ -48,12 +48,12 @@ This will generate a text file called `authy_codes.txt`, which contains your Aut A user on GitHub (gboudreau) wrote a guide to export codes from Authy (morpheus on Discord found this and showed it to us), so we are going to be using that for the migration. -To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). +To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). This will create a JSON file called `authy-to-bitwarden-export.json`, which contains your Authy codes in Bitwarden's export format. You can now import this to ente Authenticator! # Method 2.1: If the export worked, but the import didn't -> [!NOTE] +> [!NOTE] > This is intended only for users who successfully exported their codes using the guide in method 2, but could not import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. > > If the export itself failed, try using [**method 1**](#method-1-use-neerajs-export-tool) instead. diff --git a/docs/docs/auth/migration-guides/export.md b/docs/docs/auth/migration-guides/export.md new file mode 100644 index 0000000000..b4e64134e4 --- /dev/null +++ b/docs/docs/auth/migration-guides/export.md @@ -0,0 +1,63 @@ +# Auth Encrypted Export format + +## Overview + +When we export the auth codes, the data is encrypted using a key derived from the user's password. +This document describes the JSON structure used to organize exported data, including versioning and key derivation +parameters. + +## Export JSON Sample + +```json +{ + "version": 1, + "kdfParams": { + "memLimit": 4096, + "opsLimit": 3, + "salt": "example_salt" + }, + "encryptedData": "encrypted_data_here", + "encryptionNonce": "nonce_here" +} +``` + +The main object used to represent the export data. It contains the following key-value pairs: + +- `version`: The version of the export format. +- `kdfParams`: Key derivation function parameters. +- `encryptedData"`: The encrypted authentication data. +- `encryptionNonce`: The nonce used for encryption. + +### Version + +Export version is used to identify the format of the export data. + +#### Ver: 1 + +* KDF Algorithm: `ARGON2ID` +* Decrypted data format: `otpauth://totp/...`, separated by a new line. +* Encryption Algo: `XChaCha20-Poly1305` + +#### Key Derivation Function Params (KDF) + +This section contains the parameters that were using during KDF operation: + +- `memLimit`: Memory limit for the algorithm. +- `opsLimit`: Operations limit for the algorithm. +- `salt`: The salt used in the derivation process. + +#### Encrypted Data + +As mentioned above, the auth data is encrypted using a key that's derived by using user provided password & kdf params. +For encryption, we are using `XChaCha20-Poly1305` algorithm. + +## How to use the exported data + +* **Ente Authenticator app**: You can directly import the codes in the Ente Authenticator app. + > Settings -> Data -> Import Codes -> ente Encrypted export. + +* **Decrypt using Ente CLI** : Download the latest version of [Ente CLI](https://github.com/ente-io/ente/releases?q=CLI&expanded=false), and run the following command + +``` + ./ente auth decrypt +``` diff --git a/docs/docs/auth/migration-guides/index.md b/docs/docs/auth/migration-guides/index.md index 603c87011f..db9ed61f06 100644 --- a/docs/docs/auth/migration-guides/index.md +++ b/docs/docs/auth/migration-guides/index.md @@ -1,11 +1,9 @@ --- title: Migrating to Ente Auth -description: - Guides for migrating your existing 2FA tokens from other products into Ente - Auth +description: Guides for migrating your existing 2FA tokens into or out of Ente Auth --- -# Migrating to Ente Auth +# Migrating to/from Ente Auth -_Coming soon_. This section will contain guides for migrating your existing 2FA -tokens from other products into Ente Auth. +* [Migrating from Authy](authy/) +* [Exporting your data out of Ente Auth](export) From b2d64d9b72a26ed0a69f0fea1250deaaa134f86f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 10:41:52 +0530 Subject: [PATCH 283/391] Add page headers --- .../docs/auth/migration-guides/authy/index.md | 5 ++++ docs/docs/auth/migration-guides/export.md | 23 ++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/docs/docs/auth/migration-guides/authy/index.md b/docs/docs/auth/migration-guides/authy/index.md index 3996367905..62ecf6cc02 100644 --- a/docs/docs/auth/migration-guides/authy/index.md +++ b/docs/docs/auth/migration-guides/authy/index.md @@ -1,3 +1,8 @@ +--- +title: Migrating from Authy +description: Guide for importing your existing Authy 2FA tokens into Ente Auth +--- + # Migrating from Authy A guide written by Green, an ente.io lover > [!WARNING] diff --git a/docs/docs/auth/migration-guides/export.md b/docs/docs/auth/migration-guides/export.md index b4e64134e4..d04eedd333 100644 --- a/docs/docs/auth/migration-guides/export.md +++ b/docs/docs/auth/migration-guides/export.md @@ -1,12 +1,19 @@ -# Auth Encrypted Export format +--- +title: Exporting your data from Ente Auth +description: Guide for exporting your 2FA codes out from Ente Auth +--- -## Overview +# Exporting your data out of Ente Auth + +## Auth Encrypted Export format + +### Overview When we export the auth codes, the data is encrypted using a key derived from the user's password. This document describes the JSON structure used to organize exported data, including versioning and key derivation parameters. -## Export JSON Sample +### Export JSON Sample ```json { @@ -28,17 +35,17 @@ The main object used to represent the export data. It contains the following key - `encryptedData"`: The encrypted authentication data. - `encryptionNonce`: The nonce used for encryption. -### Version +#### Version Export version is used to identify the format of the export data. -#### Ver: 1 +##### Ver: 1 * KDF Algorithm: `ARGON2ID` * Decrypted data format: `otpauth://totp/...`, separated by a new line. * Encryption Algo: `XChaCha20-Poly1305` -#### Key Derivation Function Params (KDF) +##### Key Derivation Function Params (KDF) This section contains the parameters that were using during KDF operation: @@ -46,7 +53,7 @@ This section contains the parameters that were using during KDF operation: - `opsLimit`: Operations limit for the algorithm. - `salt`: The salt used in the derivation process. -#### Encrypted Data +##### Encrypted Data As mentioned above, the auth data is encrypted using a key that's derived by using user provided password & kdf params. For encryption, we are using `XChaCha20-Poly1305` algorithm. @@ -57,7 +64,7 @@ For encryption, we are using `XChaCha20-Poly1305` algorithm. > Settings -> Data -> Import Codes -> ente Encrypted export. * **Decrypt using Ente CLI** : Download the latest version of [Ente CLI](https://github.com/ente-io/ente/releases?q=CLI&expanded=false), and run the following command - + ``` ./ente auth decrypt ``` From 60d216c6fa01a00902a93b2d809c200f649e261b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 10:43:19 +0530 Subject: [PATCH 284/391] yarn pretty --- docs/docs/auth/faq/index.md | 15 ++- .../docs/auth/migration-guides/authy/index.md | 123 +++++++++++++----- docs/docs/auth/migration-guides/export.md | 62 +++++---- docs/docs/auth/migration-guides/index.md | 7 +- docs/docs/photos/faq/index.md | 6 +- .../guides/custom-server/index.md | 30 +++-- docs/docs/self-hosting/guides/index.md | 9 +- docs/docs/self-hosting/guides/mobile-build.md | 14 +- 8 files changed, 172 insertions(+), 94 deletions(-) diff --git a/docs/docs/auth/faq/index.md b/docs/docs/auth/faq/index.md index e40d184316..c84fac3839 100644 --- a/docs/docs/auth/faq/index.md +++ b/docs/docs/auth/faq/index.md @@ -1,21 +1,28 @@ - - # Frequently Asked Questions ### How secure is ente Auth? -All codes you backup via Ente is stored end-to-end encrypted. This means only you can access your codes. Our apps are open source and our cryptography has been externally audited. + +All codes you backup via Ente is stored end-to-end encrypted. This means only +you can access your codes. Our apps are open source and our cryptography has +been externally audited. ### Can I access my codes on desktop? + You can access your codes on the web @ [auth.ente.io](https://auth.ente.io). ### How can I delete or edit codes? + You can delete or edit a code by swiping left on that item. ### How can I support this project? -You can support the development of this project by subscribing to our Photos app @ [ente.io](https://ente.io). + +You can support the development of this project by subscribing to our Photos app +@ [ente.io](https://ente.io). ### How can I enable FaceID lock in Ente Auth? + You can enable FaceID lock under Settings → Security → Lockscreen. ### Why does the desktop and mobile app displays different code? + Please verify that the time on both your mobile and desktop is same. diff --git a/docs/docs/auth/migration-guides/authy/index.md b/docs/docs/auth/migration-guides/authy/index.md index 62ecf6cc02..6bc590967a 100644 --- a/docs/docs/auth/migration-guides/authy/index.md +++ b/docs/docs/auth/migration-guides/authy/index.md @@ -4,68 +4,106 @@ description: Guide for importing your existing Authy 2FA tokens into Ente Auth --- # Migrating from Authy + A guide written by Green, an ente.io lover -> [!WARNING] -> Authy will soon be dropping support for its desktop apps in the near future. If you are looking to switch to ente Authenticator from Authy, I heavily recommend you export your codes as soon as you can. + +> [!WARNING] Authy will soon be dropping support for its desktop apps in the +> near future. If you are looking to switch to ente Authenticator from Authy, I +> heavily recommend you export your codes as soon as you can. --- -Migrating from Authy can be tiring, as you cannot export your 2FA codes through the app, meaning that you would have to reconfigure 2FA for all of your accounts for your new 2FA authenticator. However, easier ways exist to export your codes out of Authy. This guide will cover two of the most used methods for mograting from Authy to ente Authenticator. +Migrating from Authy can be tiring, as you cannot export your 2FA codes through +the app, meaning that you would have to reconfigure 2FA for all of your accounts +for your new 2FA authenticator. However, easier ways exist to export your codes +out of Authy. This guide will cover two of the most used methods for mograting +from Authy to ente Authenticator. -> [!CAUTION] -> Under any circumstances, do **NOT** share any JSON and TXT files generated using this guide, as they contain your **unencrypted** TOTP secrets! +> [!CAUTION] Under any circumstances, do **NOT** share any JSON and TXT files +> generated using this guide, as they contain your **unencrypted** TOTP secrets! > -> Also, there is **NO GUARANTEE** that these methods will export ALL of your codes. Make sure that all your accounts have been imported successfully before deleting any codes from your Authy account! +> Also, there is **NO GUARANTEE** that these methods will export ALL of your +> codes. Make sure that all your accounts have been imported successfully before +> deleting any codes from your Authy account! --- # Method 1: Use Neeraj's export tool -**Who should use this?** General users who want to save time by skipping the hard (and rather technical) parts of the process.

-One way to export is to [use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) to simplify the process and skip directly to importing to ente Authenticator. +**Who should use this?** General users who want to save time by skipping the +hard (and rather technical) parts of the process.

+ +One way to export is to +[use this tool by Neeraj](https://github.com/ua741/authy-export/releases/tag/v0.0.4) +to simplify the process and skip directly to importing to ente Authenticator. + +To export from Authy, download the tool for your specific OS, then type the +following in your terminal: -To export from Authy, download the tool for your specific OS, then type the following in your terminal: ``` ./ ``` -Assuming the filename of the binary remains unmodified and the working directory of the terminal is the location of the binary, you should type this for MacOS: -> [!NOTE] -> On Apple Silicon devices, Rosetta 2 may be required to run the binary. +Assuming the filename of the binary remains unmodified and the working directory +of the terminal is the location of the binary, you should type this for MacOS: + +> [!NOTE] On Apple Silicon devices, Rosetta 2 may be required to run the binary. + ``` ./authy-export-darwin-amd64 authy_codes.txt ``` For Linux: + ``` ./authy-export-linux-amd64 authy_codes.txt ``` For Windows: + ``` ./authy-export-windows-amd64.exe authy_codes.txt ``` -This will generate a text file called `authy_codes.txt`, which contains your Authy codes in ente's plaintext export format. You can now import this to ente Authenticator! +This will generate a text file called `authy_codes.txt`, which contains your +Authy codes in ente's plaintext export format. You can now import this to ente +Authenticator! # Method 2: Use gboudreau's GitHub guide -**Who should use this?** Power users who have spare time on their hands and prefer a more "known and established" solution to exporting Authy codes.

-A user on GitHub (gboudreau) wrote a guide to export codes from Authy (morpheus on Discord found this and showed it to us), so we are going to be using that for the migration. +**Who should use this?** Power users who have spare time on their hands and +prefer a more "known and established" solution to exporting Authy codes.

+ +A user on GitHub (gboudreau) wrote a guide to export codes from Authy (morpheus +on Discord found this and showed it to us), so we are going to be using that for +the migration. -To export your data, please follow [this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). +To export your data, please follow +[this guide](https://gist.github.com/gboudreau/94bb0c11a6209c82418d01a59d958c93). -This will create a JSON file called `authy-to-bitwarden-export.json`, which contains your Authy codes in Bitwarden's export format. You can now import this to ente Authenticator! +This will create a JSON file called `authy-to-bitwarden-export.json`, which +contains your Authy codes in Bitwarden's export format. You can now import this +to ente Authenticator! # Method 2.1: If the export worked, but the import didn't -> [!NOTE] -> This is intended only for users who successfully exported their codes using the guide in method 2, but could not import it to ente Authenticator for whatever reason. If the import was successful, or you haven't tried to import the codes yet, ignore this section. + +> [!NOTE] This is intended only for users who successfully exported their codes +> using the guide in method 2, but could not import it to ente Authenticator for +> whatever reason. If the import was successful, or you haven't tried to import +> the codes yet, ignore this section. > -> If the export itself failed, try using [**method 1**](#method-1-use-neerajs-export-tool) instead. +> If the export itself failed, try using +> [**method 1**](#method-1-use-neerajs-export-tool) instead. + +Usually, you should be able to import Bitwarden exports directly into ente +Authenticator. In case this didn't work for whatever reason, I've written a +program in Python that converts the JSON file into a TXT file that ente +Authenticator can use, so you can try importing using plain text import instead. -Usually, you should be able to import Bitwarden exports directly into ente Authenticator. In case this didn't work for whatever reason, I've written a program in Python that converts the JSON file into a TXT file that ente Authenticator can use, so you can try importing using plain text import instead. +You can download my program +[here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py), +or you can copy the program below: -You can download my program [here](https://github.com/gweeeen/ducky/blob/main/duckys_other_stuff/authy_to_ente.py), or you can copy the program below: ```py import json import os @@ -84,31 +122,50 @@ writer.close() print('Saved to ' + os.getcwd() + '/auth_codes.txt') ``` -To convert the file with this program, you will need to install [Python](https://www.python.org/downloads/) on your computer. +To convert the file with this program, you will need to install +[Python](https://www.python.org/downloads/) on your computer. -Before you run the program, make sure that both the Python program and the JSON file are in the same directory, otherwise this will not work! +Before you run the program, make sure that both the Python program and the JSON +file are in the same directory, otherwise this will not work! -To run the Python program, open it in your IDE and run the program, or open your terminal and type `python3 authy_to_ente.py` (MacOS/Linux, or any other OS that uses bash) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT file called `auth_codes.txt` will be generated. You can now import your data to ente Authenticator! +To run the Python program, open it in your IDE and run the program, or open your +terminal and type `python3 authy_to_ente.py` (MacOS/Linux, or any other OS that +uses bash) or `py -3 authy_to_ente.py` (Windows). Once you run it, a new TXT +file called `auth_codes.txt` will be generated. You can now import your data to +ente Authenticator! --- -You should now have a TXT file (method 1, method 2.1) or a JSON file (method 2) that countains your TOTP secrets, which can now be imported into ente Authenticator. To import your codes, please follow one of the steps below, depending on which method you used to export your codes. + +You should now have a TXT file (method 1, method 2.1) or a JSON file (method 2) +that countains your TOTP secrets, which can now be imported into ente +Authenticator. To import your codes, please follow one of the steps below, +depending on which method you used to export your codes. # Importing to ente Authenticator (Method 1, method 2.1) + 1. Copy the TXT file to one of your devices with ente Authenticator. -2. Log in to your account (if you haven't already), or press "Use without backups". -3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes". +2. Log in to your account (if you haven't already), or press "Use without + backups". +3. Open the navigation menu (hamburger button on the top left), then press + "Data", then press "Import codes". 4. Select the "Plain text" option. 5. Select the TXT file that was made earlier. # Importing to ente Authenticator (Method 2) + 1. Copy the JSON file to one of your devices with ente Authenticator. -2. Log in to your account (if you haven't already), or press "Use without backups". -3. Open the navigation menu (hamburger button on the top left), then press "Data", then press "Import codes". +2. Log in to your account (if you haven't already), or press "Use without + backups". +3. Open the navigation menu (hamburger button on the top left), then press + "Data", then press "Import codes". 4. Select the "Bitwarden" option. 5. Select the JSON file that was made earlier. -If this didn't work, refer to [**method 2.1**](#method-21-if-the-export-worked-but-the-import-didnt).

+If this didn't work, refer to +[**method 2.1**](#method-21-if-the-export-worked-but-the-import-didnt).

-And that's it! You have now successfully migrated from Authy to ente Authenticator. +And that's it! You have now successfully migrated from Authy to ente +Authenticator. -Now that your secrets are safely stored, I recommend you delete the unencrypted JSON and TXT files that were made during the migration process for security. +Now that your secrets are safely stored, I recommend you delete the unencrypted +JSON and TXT files that were made during the migration process for security. diff --git a/docs/docs/auth/migration-guides/export.md b/docs/docs/auth/migration-guides/export.md index d04eedd333..e2fee2fcae 100644 --- a/docs/docs/auth/migration-guides/export.md +++ b/docs/docs/auth/migration-guides/export.md @@ -9,31 +9,32 @@ description: Guide for exporting your 2FA codes out from Ente Auth ### Overview -When we export the auth codes, the data is encrypted using a key derived from the user's password. -This document describes the JSON structure used to organize exported data, including versioning and key derivation -parameters. +When we export the auth codes, the data is encrypted using a key derived from +the user's password. This document describes the JSON structure used to organize +exported data, including versioning and key derivation parameters. ### Export JSON Sample ```json { - "version": 1, - "kdfParams": { - "memLimit": 4096, - "opsLimit": 3, - "salt": "example_salt" - }, - "encryptedData": "encrypted_data_here", - "encryptionNonce": "nonce_here" + "version": 1, + "kdfParams": { + "memLimit": 4096, + "opsLimit": 3, + "salt": "example_salt" + }, + "encryptedData": "encrypted_data_here", + "encryptionNonce": "nonce_here" } ``` -The main object used to represent the export data. It contains the following key-value pairs: +The main object used to represent the export data. It contains the following +key-value pairs: -- `version`: The version of the export format. -- `kdfParams`: Key derivation function parameters. -- `encryptedData"`: The encrypted authentication data. -- `encryptionNonce`: The nonce used for encryption. +- `version`: The version of the export format. +- `kdfParams`: Key derivation function parameters. +- `encryptedData"`: The encrypted authentication data. +- `encryptionNonce`: The nonce used for encryption. #### Version @@ -41,29 +42,34 @@ Export version is used to identify the format of the export data. ##### Ver: 1 -* KDF Algorithm: `ARGON2ID` -* Decrypted data format: `otpauth://totp/...`, separated by a new line. -* Encryption Algo: `XChaCha20-Poly1305` +- KDF Algorithm: `ARGON2ID` +- Decrypted data format: `otpauth://totp/...`, separated by a new line. +- Encryption Algo: `XChaCha20-Poly1305` -##### Key Derivation Function Params (KDF) +##### Key Derivation Function Params (KDF) This section contains the parameters that were using during KDF operation: -- `memLimit`: Memory limit for the algorithm. -- `opsLimit`: Operations limit for the algorithm. -- `salt`: The salt used in the derivation process. +- `memLimit`: Memory limit for the algorithm. +- `opsLimit`: Operations limit for the algorithm. +- `salt`: The salt used in the derivation process. ##### Encrypted Data -As mentioned above, the auth data is encrypted using a key that's derived by using user provided password & kdf params. -For encryption, we are using `XChaCha20-Poly1305` algorithm. +As mentioned above, the auth data is encrypted using a key that's derived by +using user provided password & kdf params. For encryption, we are using +`XChaCha20-Poly1305` algorithm. ## How to use the exported data -* **Ente Authenticator app**: You can directly import the codes in the Ente Authenticator app. - > Settings -> Data -> Import Codes -> ente Encrypted export. +- **Ente Authenticator app**: You can directly import the codes in the Ente + Authenticator app. -* **Decrypt using Ente CLI** : Download the latest version of [Ente CLI](https://github.com/ente-io/ente/releases?q=CLI&expanded=false), and run the following command + > Settings -> Data -> Import Codes -> ente Encrypted export. + +- **Decrypt using Ente CLI** : Download the latest version of + [Ente CLI](https://github.com/ente-io/ente/releases?q=CLI&expanded=false), + and run the following command ``` ./ente auth decrypt diff --git a/docs/docs/auth/migration-guides/index.md b/docs/docs/auth/migration-guides/index.md index db9ed61f06..f10d9db415 100644 --- a/docs/docs/auth/migration-guides/index.md +++ b/docs/docs/auth/migration-guides/index.md @@ -1,9 +1,10 @@ --- title: Migrating to Ente Auth -description: Guides for migrating your existing 2FA tokens into or out of Ente Auth +description: + Guides for migrating your existing 2FA tokens into or out of Ente Auth --- # Migrating to/from Ente Auth -* [Migrating from Authy](authy/) -* [Exporting your data out of Ente Auth](export) +- [Migrating from Authy](authy/) +- [Exporting your data out of Ente Auth](export) diff --git a/docs/docs/photos/faq/index.md b/docs/docs/photos/faq/index.md index 93eebcb562..c5a4e2cf96 100644 --- a/docs/docs/photos/faq/index.md +++ b/docs/docs/photos/faq/index.md @@ -3,9 +3,7 @@ title: FAQ description: Frequently asked questions about Ente Photos --- - # FAQ - -_Coming soon_. On this page we'll document some help items in a question and answer format. - +_Coming soon_. On this page we'll document some help items in a question and +answer format. diff --git a/docs/docs/self-hosting/guides/custom-server/index.md b/docs/docs/self-hosting/guides/custom-server/index.md index 51a9b6c2fe..453d05e727 100644 --- a/docs/docs/self-hosting/guides/custom-server/index.md +++ b/docs/docs/self-hosting/guides/custom-server/index.md @@ -22,22 +22,32 @@ configure the endpoint the app should be connecting to. # CLI -> [!WARNING] -> The new version of CLI that supports connecting to custom server is still in beta. -> You can download the beta version from [here](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0&expanded=true) +> [!WARNING] The new version of CLI that supports connecting to custom server is +> still in beta. You can download the beta version from +> [here](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0&expanded=true) -Define a config.yaml and put it either in the same directory as CLI or path defined in env variable `ENTE_CLI_CONFIG_PATH` +Define a config.yaml and put it either in the same directory as CLI or path +defined in env variable `ENTE_CLI_CONFIG_PATH` ```yaml endpoint: - api: "http://localhost:8080" + api: "http://localhost:8080" ``` -You should be able to [add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), and subsequently increase the [storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) using the CLI. +You should be able to +[add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), +and subsequently increase the +[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) +using the CLI. -For the admin actions, you can create `server/museum.yaml`, and whitelist add the admin userID `internal.admins`. See [local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1) in the server source code for details about how to define this. +For the admin actions, you can create `server/museum.yaml`, and whitelist add +the admin userID `internal.admins`. See +[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1) +in the server source code for details about how to define this. -You can use [account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md) command to find the user id of any account. +You can use +[account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md) +command to find the user id of any account. ```yaml .... @@ -45,5 +55,5 @@ internal: admins: # - 1580559962386440 -.... -``` \ No newline at end of file +.... +``` diff --git a/docs/docs/self-hosting/guides/index.md b/docs/docs/self-hosting/guides/index.md index 2f7582e31c..3d5b2faecd 100644 --- a/docs/docs/self-hosting/guides/index.md +++ b/docs/docs/self-hosting/guides/index.md @@ -10,9 +10,8 @@ walkthroughs, tutorials and other FAQ pages in this directory. See the sidebar for existing guides. In particular: -* If you're just looking to get started, see [configure custom - server](custom-server/). - -* For self hosting both the server and web app using external S3 buckets for - object storage, see [using external S3](external-s3). +- If you're just looking to get started, see + [configure custom server](custom-server/). +- For self hosting both the server and web app using external S3 buckets for + object storage, see [using external S3](external-s3). diff --git a/docs/docs/self-hosting/guides/mobile-build.md b/docs/docs/self-hosting/guides/mobile-build.md index 32bba3aa7a..c36903a200 100644 --- a/docs/docs/self-hosting/guides/mobile-build.md +++ b/docs/docs/self-hosting/guides/mobile-build.md @@ -30,8 +30,6 @@ flutter run --dart-define=endpoint=http://localhost:8080 --flavor independent -- flutter run --dart-define=endpoint=http://localhost:8080 ``` - - Or for the auth app: ```sh @@ -46,9 +44,11 @@ flutter run --dart-define=endpoint=http://localhost:8080 ``` ## How to build non-debug builds -For building APK, [setup your - keystore](https://docs.flutter.dev/deployment/android#create-an-upload-keystore) - and run -```sh + +For building APK, +[setup your keystore](https://docs.flutter.dev/deployment/android#create-an-upload-keystore) +and run + +```sh flutter build apk --release --flavor independent -t lib/main.dart - ``` +``` From 306ee1ad1c8d67adacd01d982bc74d0e12151c82 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 10:44:35 +0530 Subject: [PATCH 285/391] Fix the next page link on the index page ...by reintroducing it in the sidebar listing. --- docs/docs/.vitepress/sidebar.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index 48d3df1f93..de0a24f10f 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -71,6 +71,7 @@ export const sidebar = [ text: "Migration guides", collapsed: false, items: [ + { text: "Introduction", link: "/auth/migration-guides/" }, { text: "From Authy", link: "/auth/migration-guides/authy/", From 55e3a93cf6b06dca4a84ca3bd1e07f740d803d79 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 10:46:26 +0530 Subject: [PATCH 286/391] Mention the word "export" in the sidebar item --- docs/docs/.vitepress/sidebar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index de0a24f10f..e110d2a74d 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -77,7 +77,7 @@ export const sidebar = [ link: "/auth/migration-guides/authy/", }, { - text: "Out of Ente", + text: "Exporting your data", link: "/auth/migration-guides/export", }, ], From c18115ef522eeaa41738aa2aee08bfe546f692be Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 10:48:25 +0530 Subject: [PATCH 287/391] Fix link --- cli/README.md | 2 +- docs/docs/auth/migration-guides/export.md | 2 +- docs/docs/self-hosting/guides/custom-server/index.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/README.md b/cli/README.md index 5a4097a46e..8fc9aa6948 100644 --- a/cli/README.md +++ b/cli/README.md @@ -7,7 +7,7 @@ use it to decrypting the export from Ente Auth. ## Install The easiest way is to download a pre-built binary from the [GitHub -releases](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0&expanded=true). +releases](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0). You can also build these binaries yourself diff --git a/docs/docs/auth/migration-guides/export.md b/docs/docs/auth/migration-guides/export.md index e2fee2fcae..58e08387d3 100644 --- a/docs/docs/auth/migration-guides/export.md +++ b/docs/docs/auth/migration-guides/export.md @@ -68,7 +68,7 @@ using user provided password & kdf params. For encryption, we are using > Settings -> Data -> Import Codes -> ente Encrypted export. - **Decrypt using Ente CLI** : Download the latest version of - [Ente CLI](https://github.com/ente-io/ente/releases?q=CLI&expanded=false), + [Ente CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0), and run the following command ``` diff --git a/docs/docs/self-hosting/guides/custom-server/index.md b/docs/docs/self-hosting/guides/custom-server/index.md index 453d05e727..325d46dcac 100644 --- a/docs/docs/self-hosting/guides/custom-server/index.md +++ b/docs/docs/self-hosting/guides/custom-server/index.md @@ -24,7 +24,7 @@ configure the endpoint the app should be connecting to. > [!WARNING] The new version of CLI that supports connecting to custom server is > still in beta. You can download the beta version from -> [here](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0&expanded=true) +> [here](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0) Define a config.yaml and put it either in the same directory as CLI or path defined in env variable `ENTE_CLI_CONFIG_PATH` From 03c875a8b895bfef7175d2d956a477e13b6237d1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 10:54:42 +0530 Subject: [PATCH 288/391] Rearrange --- docs/docs/.vitepress/sidebar.ts | 2 +- .../docs/auth/migration-guides/authy/index.md | 24 +++++++------ .../guides/custom-server/index.md | 34 +++++++++++-------- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index e110d2a74d..cd0c81072f 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -94,7 +94,7 @@ export const sidebar = [ items: [ { text: "Introduction", link: "/self-hosting/guides/" }, { - text: "Configure custom server", + text: "Connect to custom server", link: "/self-hosting/guides/custom-server/", }, { diff --git a/docs/docs/auth/migration-guides/authy/index.md b/docs/docs/auth/migration-guides/authy/index.md index 6bc590967a..7a938bfa13 100644 --- a/docs/docs/auth/migration-guides/authy/index.md +++ b/docs/docs/auth/migration-guides/authy/index.md @@ -7,9 +7,11 @@ description: Guide for importing your existing Authy 2FA tokens into Ente Auth A guide written by Green, an ente.io lover -> [!WARNING] Authy will soon be dropping support for its desktop apps in the -> near future. If you are looking to switch to ente Authenticator from Authy, I -> heavily recommend you export your codes as soon as you can. +> [!WARNING] +> +> Authy will soon be dropping support for its desktop apps in the near future. +> If you are looking to switch to ente Authenticator from Authy, I heavily +> recommend you export your codes as soon as you can. --- @@ -19,8 +21,10 @@ for your new 2FA authenticator. However, easier ways exist to export your codes out of Authy. This guide will cover two of the most used methods for mograting from Authy to ente Authenticator. -> [!CAUTION] Under any circumstances, do **NOT** share any JSON and TXT files -> generated using this guide, as they contain your **unencrypted** TOTP secrets! +> [!CAUTION] +> +> Under any circumstances, do **NOT** share any JSON and TXT files generated +> using this guide, as they contain your **unencrypted** TOTP secrets! > > Also, there is **NO GUARANTEE** that these methods will export ALL of your > codes. Make sure that all your accounts have been imported successfully before @@ -28,7 +32,7 @@ from Authy to ente Authenticator. --- -# Method 1: Use Neeraj's export tool +## Method 1: Use Neeraj's export tool **Who should use this?** General users who want to save time by skipping the hard (and rather technical) parts of the process.

@@ -69,7 +73,7 @@ This will generate a text file called `authy_codes.txt`, which contains your Authy codes in ente's plaintext export format. You can now import this to ente Authenticator! -# Method 2: Use gboudreau's GitHub guide +## Method 2: Use gboudreau's GitHub guide **Who should use this?** Power users who have spare time on their hands and prefer a more "known and established" solution to exporting Authy codes.

@@ -85,7 +89,7 @@ This will create a JSON file called `authy-to-bitwarden-export.json`, which contains your Authy codes in Bitwarden's export format. You can now import this to ente Authenticator! -# Method 2.1: If the export worked, but the import didn't +### Method 2.1: If the export worked, but the import didn't > [!NOTE] This is intended only for users who successfully exported their codes > using the guide in method 2, but could not import it to ente Authenticator for @@ -141,7 +145,7 @@ that countains your TOTP secrets, which can now be imported into ente Authenticator. To import your codes, please follow one of the steps below, depending on which method you used to export your codes. -# Importing to ente Authenticator (Method 1, method 2.1) +## Importing to ente Authenticator (Method 1, method 2.1) 1. Copy the TXT file to one of your devices with ente Authenticator. 2. Log in to your account (if you haven't already), or press "Use without @@ -151,7 +155,7 @@ depending on which method you used to export your codes. 4. Select the "Plain text" option. 5. Select the TXT file that was made earlier. -# Importing to ente Authenticator (Method 2) +## Importing to ente Authenticator (Method 2) 1. Copy the JSON file to one of your devices with ente Authenticator. 2. Log in to your account (if you haven't already), or press "Use without diff --git a/docs/docs/self-hosting/guides/custom-server/index.md b/docs/docs/self-hosting/guides/custom-server/index.md index 325d46dcac..a17bd382b8 100644 --- a/docs/docs/self-hosting/guides/custom-server/index.md +++ b/docs/docs/self-hosting/guides/custom-server/index.md @@ -1,9 +1,14 @@ --- title: Custom server -description: Using a custom self-hosted server with frontend apps +description: Using a custom self-hosted server with Ente client apps and CLI --- -# Custom server for mobile apps +# Connecting to a custom server + +You can modify various Ente client apps and CLI to connect to a self hosted +custom server endpoint. + +## Mobile apps The pre-built Ente apps from GitHub / App Store / Play Store / F-Droid can be easily configured to use a custom server. @@ -18,12 +23,11 @@ configure the endpoint the app should be connecting to. > This is only supported by the Ente Auth app currently. We'll add this same > functionality to the Ente Photos app soon. ---- - -# CLI +## CLI -> [!WARNING] The new version of CLI that supports connecting to custom server is -> still in beta. You can download the beta version from +> [!NOTE] +> +> You can download the CLI from > [here](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0) Define a config.yaml and put it either in the same directory as CLI or path @@ -34,10 +38,10 @@ endpoint: api: "http://localhost:8080" ``` -You should be able to -[add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), -and subsequently increase the -[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) +You should be able to [add an +account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), +and subsequently increase the [storage and account +validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) using the CLI. For the admin actions, you can create `server/museum.yaml`, and whitelist add @@ -45,10 +49,6 @@ the admin userID `internal.admins`. See [local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1) in the server source code for details about how to define this. -You can use -[account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md) -command to find the user id of any account. - ```yaml .... internal: @@ -57,3 +57,7 @@ internal: .... ``` + +You can use +[account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md) +command to find the user id of any account. From 6287d40a18dd2716453151a9c9b533d0da28f63c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 11:01:36 +0530 Subject: [PATCH 289/391] Split --- docs/docs/.vitepress/sidebar.ts | 5 +++ docs/docs/self-hosting/guides/admin.md | 43 ++++++++++++++++++++++++++ docs/docs/self-hosting/guides/index.md | 3 ++ 3 files changed, 51 insertions(+) create mode 100644 docs/docs/self-hosting/guides/admin.md diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index cd0c81072f..7810f067a0 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -97,6 +97,11 @@ export const sidebar = [ text: "Connect to custom server", link: "/self-hosting/guides/custom-server/", }, + { + text: "Administering your server", + link: "/self-hosting/guides/admin", + }, + { text: "Mobile build", link: "/self-hosting/guides/mobile-build", diff --git a/docs/docs/self-hosting/guides/admin.md b/docs/docs/self-hosting/guides/admin.md new file mode 100644 index 0000000000..067db14a91 --- /dev/null +++ b/docs/docs/self-hosting/guides/admin.md @@ -0,0 +1,43 @@ +--- +title: Server admin +description: Administering your custom self-hosted Ente instance using the CLI +--- + +# Administering your custom server + +You can use [Ente's +CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0) to administer your +self hosted server. + +First we need to get your CLI to connect to your custom server. Define a +config.yaml and put it either in the same directory as CLI or path defined in +env variable `ENTE_CLI_CONFIG_PATH` + +```yaml +endpoint: + api: "http://localhost:8080" +``` + +Now you should be able to [add an +account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), +and subsequently increase the [storage and account +validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) +using the CLI. + +For the admin actions, you can create `server/museum.yaml`, and whitelist add +the admin userID `internal.admins`. See +[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1) +in the server source code for details about how to define this. + +```yaml +.... +internal: + admins: + # - 1580559962386440 + +.... +``` + +You can use +[account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md) +command to find the user id of any account. diff --git a/docs/docs/self-hosting/guides/index.md b/docs/docs/self-hosting/guides/index.md index 3d5b2faecd..a8a64d9605 100644 --- a/docs/docs/self-hosting/guides/index.md +++ b/docs/docs/self-hosting/guides/index.md @@ -13,5 +13,8 @@ See the sidebar for existing guides. In particular: - If you're just looking to get started, see [configure custom server](custom-server/). +- For various admin related tasks, e.g. increasing the storage quota on your + self hosted instance, see [administering your custom server](admin). + - For self hosting both the server and web app using external S3 buckets for object storage, see [using external S3](external-s3). From 3ffe43e9bff6d604bb40d4220b03bca760758f56 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 11:05:40 +0530 Subject: [PATCH 290/391] Also add a FAQ entry --- docs/docs/.vitepress/sidebar.ts | 4 ++++ docs/docs/self-hosting/faq/storage-space.md | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 docs/docs/self-hosting/faq/storage-space.md diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index 7810f067a0..ca531716b3 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -123,6 +123,10 @@ export const sidebar = [ text: "Verification code", link: "/self-hosting/faq/otp", }, + { + text: "Increase storage space", + link: "/self-hosting/faq/storage-space", + }, ], }, { diff --git a/docs/docs/self-hosting/faq/storage-space.md b/docs/docs/self-hosting/faq/storage-space.md new file mode 100644 index 0000000000..4af04a46fb --- /dev/null +++ b/docs/docs/self-hosting/faq/storage-space.md @@ -0,0 +1,12 @@ +--- +title: Increase storage space +description: Increasing the storage quota for users on your self hosted instance +--- + +# Increase storage space + +See the [guide for administering your server](/self-hosting/guides/admin). In +particular, you can use the `ente admin update-subscription` CLI command to +increase the ([storage and account +validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) +of accounts on your instance. From 7b850cec43595a7bbbb38d6883187869d2a0d5d0 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 11:06:16 +0530 Subject: [PATCH 291/391] Remove incomplete notice --- docs/docs/auth/index.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/docs/auth/index.md b/docs/docs/auth/index.md index 11fb333af4..8800c54226 100644 --- a/docs/docs/auth/index.md +++ b/docs/docs/auth/index.md @@ -7,8 +7,3 @@ description: User guide for Ente Auth Ente Auth is a free, cross-platform, end-to-end encrypted authenticator app. You can use it to safely store your 2FA codes (second-factor authentication codes). - -> [!CAUTION] -> -> These docs are still incomplete. If you feel like documenting an issue you ran -> into and then found a solution to, help us [fill them in](/about/contribute). From abc93872e900e12f4299d2a16aff642afea1341d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 11:08:11 +0530 Subject: [PATCH 292/391] Add header --- docs/docs/auth/faq/index.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/docs/auth/faq/index.md b/docs/docs/auth/faq/index.md index c84fac3839..2c8e1f03e8 100644 --- a/docs/docs/auth/faq/index.md +++ b/docs/docs/auth/faq/index.md @@ -1,6 +1,11 @@ +--- +title: FAQ - Auth +description: Frequently asked questions about Ente Auth +--- + # Frequently Asked Questions -### How secure is ente Auth? +### How secure is Ente Auth? All codes you backup via Ente is stored end-to-end encrypted. This means only you can access your codes. Our apps are open source and our cryptography has @@ -8,7 +13,7 @@ been externally audited. ### Can I access my codes on desktop? -You can access your codes on the web @ [auth.ente.io](https://auth.ente.io). +You can access your codes on the web at [auth.ente.io](https://auth.ente.io). ### How can I delete or edit codes? @@ -17,7 +22,7 @@ You can delete or edit a code by swiping left on that item. ### How can I support this project? You can support the development of this project by subscribing to our Photos app -@ [ente.io](https://ente.io). +at [ente.io](https://ente.io). ### How can I enable FaceID lock in Ente Auth? From cfe7b1baa0cebe2969cd1f240f3ff045c8845a97 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 11:09:26 +0530 Subject: [PATCH 293/391] Remove duplicate section --- .../guides/custom-server/index.md | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/docs/docs/self-hosting/guides/custom-server/index.md b/docs/docs/self-hosting/guides/custom-server/index.md index a17bd382b8..7f7ba50fa6 100644 --- a/docs/docs/self-hosting/guides/custom-server/index.md +++ b/docs/docs/self-hosting/guides/custom-server/index.md @@ -37,27 +37,3 @@ defined in env variable `ENTE_CLI_CONFIG_PATH` endpoint: api: "http://localhost:8080" ``` - -You should be able to [add an -account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), -and subsequently increase the [storage and account -validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) -using the CLI. - -For the admin actions, you can create `server/museum.yaml`, and whitelist add -the admin userID `internal.admins`. See -[local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml#L211C1-L232C1) -in the server source code for details about how to define this. - -```yaml -.... -internal: - admins: - # - 1580559962386440 - -.... -``` - -You can use -[account list](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_list.md) -command to find the user id of any account. From b1da0c1b700d32b642d74fcb7244f186aefa6b8e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 11:10:22 +0530 Subject: [PATCH 294/391] yarn pretty --- docs/docs/auth/faq/index.md | 2 +- docs/docs/auth/migration-guides/export.md | 4 ++-- docs/docs/self-hosting/faq/storage-space.md | 4 ++-- docs/docs/self-hosting/guides/admin.md | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/docs/auth/faq/index.md b/docs/docs/auth/faq/index.md index 2c8e1f03e8..23564e2e36 100644 --- a/docs/docs/auth/faq/index.md +++ b/docs/docs/auth/faq/index.md @@ -1,6 +1,6 @@ --- title: FAQ - Auth -description: Frequently asked questions about Ente Auth +description: Frequently asked questions about Ente Auth --- # Frequently Asked Questions diff --git a/docs/docs/auth/migration-guides/export.md b/docs/docs/auth/migration-guides/export.md index 58e08387d3..a66bea7b6b 100644 --- a/docs/docs/auth/migration-guides/export.md +++ b/docs/docs/auth/migration-guides/export.md @@ -68,8 +68,8 @@ using user provided password & kdf params. For encryption, we are using > Settings -> Data -> Import Codes -> ente Encrypted export. - **Decrypt using Ente CLI** : Download the latest version of - [Ente CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0), - and run the following command + [Ente CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0), and run + the following command ``` ./ente auth decrypt diff --git a/docs/docs/self-hosting/faq/storage-space.md b/docs/docs/self-hosting/faq/storage-space.md index 4af04a46fb..f1ad78c718 100644 --- a/docs/docs/self-hosting/faq/storage-space.md +++ b/docs/docs/self-hosting/faq/storage-space.md @@ -7,6 +7,6 @@ description: Increasing the storage quota for users on your self hosted instance See the [guide for administering your server](/self-hosting/guides/admin). In particular, you can use the `ente admin update-subscription` CLI command to -increase the ([storage and account -validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) +increase the +[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) of accounts on your instance. diff --git a/docs/docs/self-hosting/guides/admin.md b/docs/docs/self-hosting/guides/admin.md index 067db14a91..91ea4d0f8a 100644 --- a/docs/docs/self-hosting/guides/admin.md +++ b/docs/docs/self-hosting/guides/admin.md @@ -5,9 +5,9 @@ description: Administering your custom self-hosted Ente instance using the CLI # Administering your custom server -You can use [Ente's -CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0) to administer your -self hosted server. +You can use +[Ente's CLI](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0) to +administer your self hosted server. First we need to get your CLI to connect to your custom server. Define a config.yaml and put it either in the same directory as CLI or path defined in @@ -18,10 +18,10 @@ endpoint: api: "http://localhost:8080" ``` -Now you should be able to [add an -account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), -and subsequently increase the [storage and account -validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) +Now you should be able to +[add an account](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_account_add.md), +and subsequently increase the +[storage and account validity](https://github.com/ente-io/ente/blob/main/cli/docs/generated/ente_admin_update-subscription.md) using the CLI. For the admin actions, you can create `server/museum.yaml`, and whitelist add From c71d06d4059d93f9d8a6c5e799711d18052cc7a2 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 11:12:27 +0530 Subject: [PATCH 295/391] Mention the self-hosting docs in the server README --- server/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/README.md b/server/README.md index 9c4b2f696a..06fdcb5184 100644 --- a/server/README.md +++ b/server/README.md @@ -113,6 +113,11 @@ repository's [Discussions](https://github.com/ente-io/ente/discussions), or on try to clarify, and also document such FAQs. Please feel free to open documentation PRs around this too. +> [!TIP] +> +> You can find more guides and documentation around self-hosting at +> [help.ente.io/self-hosting](https://help.ente.io/self-hosting). + ## Thanks ❤️ We've had great fun with this combination (Golang + Postgres + Docker), and we From 48a8bab862851c3735d665d7eb6dbf68e4aea9bf Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 14 Mar 2024 11:24:50 +0530 Subject: [PATCH 296/391] dispose text field focus node --- mobile/lib/ui/sharing/add_partipant_page.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index cf828e1feb..d8e4693132 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -50,6 +50,7 @@ class _AddParticipantPage extends State { @override void dispose() { _textController.dispose(); + textFieldFocusNode.dispose(); super.dispose(); } From d4cf8c5f9a3dd024e655de314831bb02c074921d Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 14 Mar 2024 11:25:38 +0530 Subject: [PATCH 297/391] move super.initState to top --- mobile/lib/ui/sharing/add_partipant_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index d8e4693132..1498f90867 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -43,8 +43,8 @@ class _AddParticipantPage extends State { @override void initState() { - collectionActions = CollectionActions(CollectionsService.instance); super.initState(); + collectionActions = CollectionActions(CollectionsService.instance); } @override From 0e4ca2ad218ed8786080972cc039493e1c9bf00e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 11:36:49 +0530 Subject: [PATCH 298/391] [docs] Call out the gotcha of not connecting to the correct instance --- docs/docs/self-hosting/faq/otp.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/docs/self-hosting/faq/otp.md b/docs/docs/self-hosting/faq/otp.md index c3356b7bcc..a224d1f668 100644 --- a/docs/docs/self-hosting/faq/otp.md +++ b/docs/docs/self-hosting/faq/otp.md @@ -17,3 +17,11 @@ locally by creating a `museum.yaml` and adding the `internal.hardcoded-ott` configuration setting to it. See [local.yaml](https://github.com/ente-io/ente/blob/main/server/configurations/local.yaml) in the server source code for details about how to define this. + +> [!NOTE] +> +> If you're not able to get the OTP with the above methods, make sure that you +> are actually connecting to your self hosted instance and not to Ente's +> production servers. e.g. you can use the network requests tab in the browser +> console to verify that the API requests are going to your server instead of +> `api.ente.io`. From 6b70d8556b318187a730173aa9501503b292c368 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 14 Mar 2024 11:52:13 +0530 Subject: [PATCH 299/391] Use MediaQuery.viewInsetsOf() instead of MediaQuery.of() to reduce rebuids --- mobile/lib/ui/sharing/add_partipant_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index 1498f90867..e4a871fd86 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -56,7 +56,7 @@ class _AddParticipantPage extends State { @override Widget build(BuildContext context) { - isKeypadOpen = MediaQuery.of(context).viewInsets.bottom > 100; + isKeypadOpen = MediaQuery.viewInsetsOf(context).bottom > 100; final enteTextTheme = getEnteTextTheme(context); final enteColorScheme = getEnteColorScheme(context); final List suggestedUsers = _getSuggestedUser(); From f1e68e9eefc09067211a4ebf4b37580760ec46bd Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 14:11:29 +0530 Subject: [PATCH 300/391] Show select-all-for-day checkmark only when there is a selection --- .../photos/src/components/PhotoList/index.tsx | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/web/apps/photos/src/components/PhotoList/index.tsx b/web/apps/photos/src/components/PhotoList/index.tsx index 3eee1d6830..e6d955cdaf 100644 --- a/web/apps/photos/src/components/PhotoList/index.tsx +++ b/web/apps/photos/src/components/PhotoList/index.tsx @@ -780,23 +780,28 @@ export function PhotoList({ listItem: TimeStampListItem, isScrolling: boolean, ) => { + // Enhancement: This logic doesn't work on the shared album screen, the + // galleryContext.selectedFile is always null there. + const haveSelection = (galleryContext.selectedFile?.count ?? 0) > 0; switch (listItem.itemType) { case ITEM_TYPE.TIME: return listItem.dates ? ( listItem.dates .map((item) => [ - - onChangeSelectAllCheckBox(item.date) - } - size="small" - sx={{ pl: 0 }} - disableRipple={true} - /> + {haveSelection && ( + + onChangeSelectAllCheckBox(item.date) + } + size="small" + sx={{ pl: 0 }} + disableRipple={true} + /> + )} {item.date} ,
, @@ -804,17 +809,19 @@ export function PhotoList({ .flat() ) : ( - - onChangeSelectAllCheckBox(listItem.date) - } - size="small" - sx={{ pl: 0 }} - disableRipple={true} - /> + {haveSelection && ( + + onChangeSelectAllCheckBox(listItem.date) + } + size="small" + sx={{ pl: 0 }} + disableRipple={true} + /> + )} {listItem.date} ); From 39e5415e0a7992b1090baa58486118b26fc00d17 Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Thu, 14 Mar 2024 11:08:52 +0100 Subject: [PATCH 301/391] Update index.md --- docs/docs/auth/migration-guides/authy/index.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/docs/auth/migration-guides/authy/index.md b/docs/docs/auth/migration-guides/authy/index.md index 7a938bfa13..64501d3f66 100644 --- a/docs/docs/auth/migration-guides/authy/index.md +++ b/docs/docs/auth/migration-guides/authy/index.md @@ -91,10 +91,11 @@ to ente Authenticator! ### Method 2.1: If the export worked, but the import didn't -> [!NOTE] This is intended only for users who successfully exported their codes -> using the guide in method 2, but could not import it to ente Authenticator for -> whatever reason. If the import was successful, or you haven't tried to import -> the codes yet, ignore this section. +> [!NOTE] +> This is intended only for users who successfully exported their codes using the +> guide in method 2, but could not import it to ente Authenticator for whatever +> reason. If the import was successful, or you haven't tried to import the codes +> yet, ignore this section. > > If the export itself failed, try using > [**method 1**](#method-1-use-neerajs-export-tool) instead. From 56b750c1ac71cb6db44bdda4faef15e8c44d3a7c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 15:35:31 +0530 Subject: [PATCH 302/391] [web] Exit fullscreen if needed when pressing the info button Fixes: Info button is not working when videos are playing in full screen mode. **Tested by** Wasn't working before, but it works now. Still doesn't work with the keybinding, have left a note about that in the code. --- .../src/components/PhotoViewer/index.tsx | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/web/apps/photos/src/components/PhotoViewer/index.tsx b/web/apps/photos/src/components/PhotoViewer/index.tsx index 7025421720..425290023c 100644 --- a/web/apps/photos/src/components/PhotoViewer/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/index.tsx @@ -178,6 +178,14 @@ function PhotoViewer(props: Iprops) { switch (event.key) { case "i": case "I": + // Enhancement: This should be calling handleOpenInfo, but + // that handling the case where a keybinding triggers an + // exit from fullscreen and opening the info drawer is not + // currently working (the info drawer opens, but the exit + // from fullscreen doesn't happen). + // + // So for now, let the keybinding only work when not in + // fullscreen instead of doing a mish-mash. setShowInfo(true); break; case "Backspace": @@ -616,7 +624,18 @@ function PhotoViewer(props: Iprops) { const handleCloseInfo = () => { setShowInfo(false); }; - const handleOpenInfo = () => { + + const handleOpenInfo = (photoSwipe: any) => { + // Get out of full screen mode if needed first to be able to show info + if (isInFullScreenMode) { + const fullScreenApi: PhotoswipeFullscreenAPI = + photoSwipe?.ui?.getFullscreenAPI(); + if (fullScreenApi && fullScreenApi.isFullscreen()) { + fullScreenApi.exit(); + setIsInFullScreenMode(false); + } + } + setShowInfo(true); }; @@ -851,7 +870,7 @@ function PhotoViewer(props: Iprops) { From 91c5e54cdcfca63ac6679f1bb8f6eb28a42e6984 Mon Sep 17 00:00:00 2001 From: green <41323182+greeeen-dev@users.noreply.github.com> Date: Thu, 14 Mar 2024 11:11:44 +0100 Subject: [PATCH 303/391] Update index.md --- docs/docs/auth/migration-guides/authy/index.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/docs/auth/migration-guides/authy/index.md b/docs/docs/auth/migration-guides/authy/index.md index 64501d3f66..d215a610bc 100644 --- a/docs/docs/auth/migration-guides/authy/index.md +++ b/docs/docs/auth/migration-guides/authy/index.md @@ -51,7 +51,9 @@ following in your terminal: Assuming the filename of the binary remains unmodified and the working directory of the terminal is the location of the binary, you should type this for MacOS: -> [!NOTE] On Apple Silicon devices, Rosetta 2 may be required to run the binary. +> [!NOTE] +> +> On Apple Silicon devices, Rosetta 2 may be required to run the binary. ``` ./authy-export-darwin-amd64 authy_codes.txt @@ -92,6 +94,7 @@ to ente Authenticator! ### Method 2.1: If the export worked, but the import didn't > [!NOTE] +> > This is intended only for users who successfully exported their codes using the > guide in method 2, but could not import it to ente Authenticator for whatever > reason. If the import was successful, or you haven't tried to import the codes From 324eeed1c5301efdf112932e05def6e29411b700 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:53:26 +0530 Subject: [PATCH 304/391] [cli] Add admin list-user cmd --- cli/cmd/admin.go | 21 +++++++++++++++++++-- cli/internal/api/admin.go | 22 ++++++++++++++++++++++ cli/internal/api/models/user_details.go | 11 ++++++++--- cli/pkg/admin_actions.go | 20 ++++++++++++++++++++ 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/cli/cmd/admin.go b/cli/cmd/admin.go index 0e41bbfe2c..d46fcfbf71 100644 --- a/cli/cmd/admin.go +++ b/cli/cmd/admin.go @@ -52,9 +52,25 @@ var _disable2faCmd = &cobra.Command{ }, } +var _listUsers = &cobra.Command{ + Use: "list-users", + Short: "List all users", + RunE: func(cmd *cobra.Command, args []string) error { + recoverWithLog() + var flags = &model.AdminActionForUser{} + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if f.Name == "admin-user" { + flags.AdminEmail = f.Value.String() + } + }) + return ctrl.ListUsers(context.Background(), *flags) + }, +} + var _updateFreeUserStorage = &cobra.Command{ Use: "update-subscription", - Short: "Update subscription for the free user", + Short: "Update subscription for user", + Long: "Update subscription for the free user. If you want to apply specific limits, use the `--no-limit False` flag", RunE: func(cmd *cobra.Command, args []string) error { recoverWithLog() var flags = &model.AdminActionForUser{} @@ -80,11 +96,12 @@ func init() { _ = _userDetailsCmd.MarkFlagRequired("user") _userDetailsCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") _userDetailsCmd.Flags().StringP("user", "u", "", "The email of the user to fetch details for. (required)") + _listUsers.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") _disable2faCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") _disable2faCmd.Flags().StringP("user", "u", "", "The email of the user to disable 2FA for. (required)") _updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") _updateFreeUserStorage.Flags().StringP("user", "u", "", "The email of the user to update subscription for. (required)") // add a flag with no value --no-limit _updateFreeUserStorage.Flags().String("no-limit", "True", "When true, sets 100TB as storage limit, and expiry to current date + 100 years") - _adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage) + _adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage, _listUsers) } diff --git a/cli/internal/api/admin.go b/cli/internal/api/admin.go index 1c0b2c50af..0f21e2d825 100644 --- a/cli/internal/api/admin.go +++ b/cli/internal/api/admin.go @@ -25,6 +25,28 @@ func (c *Client) GetUserIdFromEmail(ctx context.Context, email string) (*models. } return &res, nil } + +func (c *Client) ListUsers(ctx context.Context) ([]models.User, error) { + var res struct { + Users []models.User `json:"users"` + } + r, err := c.restClient.R(). + SetContext(ctx). + SetQueryParam("sinceTime", "0"). + SetResult(&res). + Get("/admin/users/") + if err != nil { + return nil, err + } + if r.IsError() { + return nil, &ApiError{ + StatusCode: r.StatusCode(), + Message: r.String(), + } + } + return res.Users, nil +} + func (c *Client) UpdateFreePlanSub(ctx context.Context, userDetails *models.UserDetails, storageInBytes int64, expiryTimeInMicro int64) error { var res interface{} if userDetails.Subscription.ProductID != "free" { diff --git a/cli/internal/api/models/user_details.go b/cli/internal/api/models/user_details.go index 259ff972b6..6a5310d7d3 100644 --- a/cli/internal/api/models/user_details.go +++ b/cli/internal/api/models/user_details.go @@ -1,9 +1,7 @@ package models type UserDetails struct { - User struct { - ID int64 `json:"id"` - } `json:"user"` + User User `json:"user"` Usage int64 `json:"usage"` Email string `json:"email"` @@ -14,3 +12,10 @@ type UserDetails struct { PaymentProvider string `json:"paymentProvider"` } `json:"subscription"` } + +type User struct { + ID int64 + Email string `json:"email"` + Hash string `json:"hash"` + CreationTime int64 `json:"creationTime"` +} diff --git a/cli/pkg/admin_actions.go b/cli/pkg/admin_actions.go index c9ec006675..a5d1829737 100644 --- a/cli/pkg/admin_actions.go +++ b/cli/pkg/admin_actions.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "github.com/ente-io/cli/internal" + "github.com/ente-io/cli/internal/api" "github.com/ente-io/cli/pkg/model" "github.com/ente-io/cli/utils" "log" @@ -24,6 +25,25 @@ func (c *ClICtrl) GetUserId(ctx context.Context, params model.AdminActionForUser return nil } +func (c *ClICtrl) ListUsers(ctx context.Context, params model.AdminActionForUser) error { + accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) + if err != nil { + return err + } + users, err := c.Client.ListUsers(accountCtx) + if err != nil { + if apiErr, ok := err.(*api.ApiError); ok && apiErr.StatusCode == 400 && strings.Contains(apiErr.Message, "Token is too old") { + fmt.Printf("Old admin token, please re-authenticate using `ente account add` \n") + return nil + } + return err + } + for _, user := range users { + fmt.Printf("Email: %s, ID: %d, Created: %s\n", user.Email, user.ID, time.UnixMicro(user.CreationTime).Format("2006-01-02")) + } + return nil +} + func (c *ClICtrl) UpdateFreeStorage(ctx context.Context, params model.AdminActionForUser, noLimit bool) error { accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) if err != nil { From da3c6a78d46cb9cb373b313522ca2dee2e6d638d Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:01:40 +0530 Subject: [PATCH 305/391] [cli] Make it optional to pass adminUser when only one account is configured --- cli/cmd/admin.go | 8 ++++---- cli/pkg/admin_actions.go | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/cli/cmd/admin.go b/cli/cmd/admin.go index d46fcfbf71..fd22bc739b 100644 --- a/cli/cmd/admin.go +++ b/cli/cmd/admin.go @@ -94,12 +94,12 @@ func init() { rootCmd.AddCommand(_adminCmd) _ = _userDetailsCmd.MarkFlagRequired("admin-user") _ = _userDetailsCmd.MarkFlagRequired("user") - _userDetailsCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") + _userDetailsCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. ") _userDetailsCmd.Flags().StringP("user", "u", "", "The email of the user to fetch details for. (required)") - _listUsers.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") - _disable2faCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") + _listUsers.Flags().StringP("admin-user", "a", "", "The email of the admin user. ") + _disable2faCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. ") _disable2faCmd.Flags().StringP("user", "u", "", "The email of the user to disable 2FA for. (required)") - _updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user. (required)") + _updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user.") _updateFreeUserStorage.Flags().StringP("user", "u", "", "The email of the user to update subscription for. (required)") // add a flag with no value --no-limit _updateFreeUserStorage.Flags().String("no-limit", "True", "When true, sets 100TB as storage limit, and expiry to current date + 100 years") diff --git a/cli/pkg/admin_actions.go b/cli/pkg/admin_actions.go index a5d1829737..7b9927c6a7 100644 --- a/cli/pkg/admin_actions.go +++ b/cli/pkg/admin_actions.go @@ -102,6 +102,9 @@ func (c *ClICtrl) buildAdminContext(ctx context.Context, adminEmail string) (con if err != nil { return nil, err } + if len(accounts) == 0 { + return nil, fmt.Errorf("no accounts found, use `account add` to add an account") + } var acc *model.Account for _, a := range accounts { if a.Email == adminEmail { @@ -109,6 +112,14 @@ func (c *ClICtrl) buildAdminContext(ctx context.Context, adminEmail string) (con break } } + if (len(accounts) > 1) && (acc == nil) { + return nil, fmt.Errorf("multiple accounts found, specify the admin email using --admin-user") + } + if acc == nil && len(accounts) == 1 { + acc = &accounts[0] + fmt.Printf("Assuming %s as the Admin \n------------\n", acc.Email) + } + if acc == nil { return nil, fmt.Errorf("account not found for %s, use `account list` to list accounts", adminEmail) } From 6af62d87278666dc7ca6f12837b25658a4be7ce3 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:13:11 +0530 Subject: [PATCH 306/391] [cli] Add admin disable-2fa cmd --- cli/cmd/admin.go | 13 +++++++++++-- cli/internal/api/admin.go | 23 +++++++++++++++++++++++ cli/pkg/admin_actions.go | 23 ++++++++++++++++++++++- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/cli/cmd/admin.go b/cli/cmd/admin.go index fd22bc739b..3a54b13ac7 100644 --- a/cli/cmd/admin.go +++ b/cli/cmd/admin.go @@ -29,6 +29,9 @@ var _userDetailsCmd = &cobra.Command{ flags.UserEmail = f.Value.String() } }) + if flags.UserEmail == "" { + return fmt.Errorf("user email is required") + } return ctrl.GetUserId(context.Background(), *flags) }, } @@ -47,8 +50,11 @@ var _disable2faCmd = &cobra.Command{ flags.UserEmail = f.Value.String() } }) - fmt.Println("Not supported yet") - return nil + if flags.UserEmail == "" { + return fmt.Errorf("user email is required") + } + return ctrl.Disable2FA(context.Background(), *flags) + }, } @@ -86,6 +92,9 @@ var _updateFreeUserStorage = &cobra.Command{ noLimit = strings.ToLower(f.Value.String()) == "true" } }) + if flags.UserEmail == "" { + return fmt.Errorf("user email is required") + } return ctrl.UpdateFreeStorage(context.Background(), *flags, noLimit) }, } diff --git a/cli/internal/api/admin.go b/cli/internal/api/admin.go index 0f21e2d825..c2b9481112 100644 --- a/cli/internal/api/admin.go +++ b/cli/internal/api/admin.go @@ -47,6 +47,29 @@ func (c *Client) ListUsers(ctx context.Context) ([]models.User, error) { return res.Users, nil } +func (c *Client) Disable2Fa(ctx context.Context, userID int64) error { + var res interface{} + + payload := map[string]interface{}{ + "userID": userID, + } + r, err := c.restClient.R(). + SetContext(ctx). + SetResult(&res). + SetBody(payload). + Post("/admin/user/disable-2fa") + if err != nil { + return err + } + if r.IsError() { + return &ApiError{ + StatusCode: r.StatusCode(), + Message: r.String(), + } + } + return nil +} + func (c *Client) UpdateFreePlanSub(ctx context.Context, userDetails *models.UserDetails, storageInBytes int64, expiryTimeInMicro int64) error { var res interface{} if userDetails.Subscription.ProductID != "free" { diff --git a/cli/pkg/admin_actions.go b/cli/pkg/admin_actions.go index 7b9927c6a7..a7a060f665 100644 --- a/cli/pkg/admin_actions.go +++ b/cli/pkg/admin_actions.go @@ -33,7 +33,7 @@ func (c *ClICtrl) ListUsers(ctx context.Context, params model.AdminActionForUser users, err := c.Client.ListUsers(accountCtx) if err != nil { if apiErr, ok := err.(*api.ApiError); ok && apiErr.StatusCode == 400 && strings.Contains(apiErr.Message, "Token is too old") { - fmt.Printf("Old admin token, please re-authenticate using `ente account add` \n") + fmt.Printf("Error: old admin token, please re-authenticate using `ente account add` \n") return nil } return err @@ -44,6 +44,27 @@ func (c *ClICtrl) ListUsers(ctx context.Context, params model.AdminActionForUser return nil } +func (c *ClICtrl) Disable2FA(ctx context.Context, params model.AdminActionForUser) error { + accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) + if err != nil { + return err + } + userDetails, err := c.Client.GetUserIdFromEmail(accountCtx, params.UserEmail) + if err != nil { + return err + } + err = c.Client.Disable2Fa(accountCtx, userDetails.User.ID) + if err != nil { + if apiErr, ok := err.(*api.ApiError); ok && apiErr.StatusCode == 400 && strings.Contains(apiErr.Message, "Token is too old") { + fmt.Printf("Error: Old admin token, please re-authenticate using `ente account add` \n") + return nil + } + return err + } + fmt.Println("Successfully disabled 2FA for user") + return nil +} + func (c *ClICtrl) UpdateFreeStorage(ctx context.Context, params model.AdminActionForUser, noLimit bool) error { accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) if err != nil { From 8bf17af6de44101130f6aea9d936841d3dfaead2 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 14 Mar 2024 16:14:06 +0530 Subject: [PATCH 307/391] feat(share-to-multi-contacts-at-once): make multi-select possible from list of existing contacts --- mobile/lib/ui/sharing/add_partipant_page.dart | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index e4a871fd86..b9e41467ed 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -30,6 +30,7 @@ class AddParticipantPage extends StatefulWidget { } class _AddParticipantPage extends State { + final _selectedEmails = []; String selectedEmail = ''; String _email = ''; bool isEmailListEmpty = false; @@ -86,7 +87,7 @@ class _AddParticipantPage extends State { const SizedBox(height: 4), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: _getEmailField(), + child: _enterEmailField(), ), (isEmailListEmpty && widget.isAddingViewer) ? const Expanded(child: SizedBox.shrink()) @@ -102,6 +103,7 @@ class _AddParticipantPage extends State { : const SizedBox.shrink(), Expanded( child: ListView.builder( + physics: const BouncingScrollPhysics(), itemBuilder: (context, index) { if (index >= suggestedUsers.length) { return Padding( @@ -131,16 +133,18 @@ class _AddParticipantPage extends State { getEnteColorScheme(context).fillFaint, pressedColor: getEnteColorScheme(context).fillFaint, - trailingIcon: - (selectedEmail == currentUser.email) - ? Icons.check - : null, + trailingIcon: (_selectedEmails + .contains(currentUser.email)) + ? Icons.check + : null, onTap: () async { textFieldFocusNode.unfocus(); - if (selectedEmail == currentUser.email) { - selectedEmail = ''; + if (_selectedEmails + .contains(currentUser.email)) { + _selectedEmails + .remove(currentUser.email); } else { - selectedEmail = currentUser.email; + _selectedEmails.add(currentUser.email); } setState(() => {}); @@ -162,7 +166,6 @@ class _AddParticipantPage extends State { }, itemCount: suggestedUsers.length + (widget.isAddingViewer ? 0 : 1), - // physics: const ClampingScrollPhysics(), ), ), ], @@ -257,7 +260,7 @@ class _AddParticipantPage extends State { setState(() => {}); } - Widget _getEmailField() { + Widget _enterEmailField() { return TextFormField( controller: _textController, focusNode: textFieldFocusNode, From bc47368a01b5253c69b4bfc55aa0490e9bb32c90 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:18:08 +0530 Subject: [PATCH 308/391] [cli] Add API to delete-user --- cli/cmd/admin.go | 26 +++++++++++++++++++++++++- cli/internal/api/admin.go | 18 ++++++++++++++++++ cli/pkg/admin_actions.go | 17 +++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/cli/cmd/admin.go b/cli/cmd/admin.go index 3a54b13ac7..8a2d7f006b 100644 --- a/cli/cmd/admin.go +++ b/cli/cmd/admin.go @@ -58,6 +58,28 @@ var _disable2faCmd = &cobra.Command{ }, } +var _deleteUser = &cobra.Command{ + Use: "delete-user", + Short: "Delete a user", + RunE: func(cmd *cobra.Command, args []string) error { + recoverWithLog() + var flags = &model.AdminActionForUser{} + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if f.Name == "admin-user" { + flags.AdminEmail = f.Value.String() + } + if f.Name == "user" { + flags.UserEmail = f.Value.String() + } + }) + if flags.UserEmail == "" { + return fmt.Errorf("user email is required") + } + return ctrl.DeleteUser(context.Background(), *flags) + + }, +} + var _listUsers = &cobra.Command{ Use: "list-users", Short: "List all users", @@ -108,9 +130,11 @@ func init() { _listUsers.Flags().StringP("admin-user", "a", "", "The email of the admin user. ") _disable2faCmd.Flags().StringP("admin-user", "a", "", "The email of the admin user. ") _disable2faCmd.Flags().StringP("user", "u", "", "The email of the user to disable 2FA for. (required)") + _deleteUser.Flags().StringP("admin-user", "a", "", "The email of the admin user. ") + _deleteUser.Flags().StringP("user", "u", "", "The email of the user to delete. (required)") _updateFreeUserStorage.Flags().StringP("admin-user", "a", "", "The email of the admin user.") _updateFreeUserStorage.Flags().StringP("user", "u", "", "The email of the user to update subscription for. (required)") // add a flag with no value --no-limit _updateFreeUserStorage.Flags().String("no-limit", "True", "When true, sets 100TB as storage limit, and expiry to current date + 100 years") - _adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage, _listUsers) + _adminCmd.AddCommand(_userDetailsCmd, _disable2faCmd, _updateFreeUserStorage, _listUsers, _deleteUser) } diff --git a/cli/internal/api/admin.go b/cli/internal/api/admin.go index c2b9481112..9e0bcb90a7 100644 --- a/cli/internal/api/admin.go +++ b/cli/internal/api/admin.go @@ -47,6 +47,24 @@ func (c *Client) ListUsers(ctx context.Context) ([]models.User, error) { return res.Users, nil } +func (c *Client) DeleteUser(ctx context.Context, email string) error { + + r, err := c.restClient.R(). + SetContext(ctx). + SetQueryParam("email", email). + Delete("/admin/user/delete") + if err != nil { + return err + } + if r.IsError() { + return &ApiError{ + StatusCode: r.StatusCode(), + Message: r.String(), + } + } + return nil +} + func (c *Client) Disable2Fa(ctx context.Context, userID int64) error { var res interface{} diff --git a/cli/pkg/admin_actions.go b/cli/pkg/admin_actions.go index a7a060f665..0105cdc199 100644 --- a/cli/pkg/admin_actions.go +++ b/cli/pkg/admin_actions.go @@ -44,6 +44,23 @@ func (c *ClICtrl) ListUsers(ctx context.Context, params model.AdminActionForUser return nil } +func (c *ClICtrl) DeleteUser(ctx context.Context, params model.AdminActionForUser) error { + accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) + if err != nil { + return err + } + err = c.Client.DeleteUser(accountCtx, params.UserEmail) + if err != nil { + if apiErr, ok := err.(*api.ApiError); ok && apiErr.StatusCode == 400 && strings.Contains(apiErr.Message, "Token is too old") { + fmt.Printf("Error: old admin token, please re-authenticate using `ente account add` \n") + return nil + } + return err + } + fmt.Println("Successfully deleted user") + return nil +} + func (c *ClICtrl) Disable2FA(ctx context.Context, params model.AdminActionForUser) error { accountCtx, err := c.buildAdminContext(ctx, params.AdminEmail) if err != nil { From 9c04c8fbe654e2b2dd6d03af81bd9bd6e7a8798c Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:18:37 +0530 Subject: [PATCH 309/391] [cli] Generate docs --- cli/docs/generated/ente.md | 2 +- cli/docs/generated/ente_account.md | 2 +- cli/docs/generated/ente_account_add.md | 2 +- cli/docs/generated/ente_account_get-token.md | 2 +- cli/docs/generated/ente_account_list.md | 2 +- cli/docs/generated/ente_account_update.md | 2 +- cli/docs/generated/ente_admin.md | 6 ++++-- cli/docs/generated/ente_admin_delete-user.md | 21 +++++++++++++++++++ cli/docs/generated/ente_admin_disable-2fa.md | 4 ++-- cli/docs/generated/ente_admin_get-user-id.md | 4 ++-- cli/docs/generated/ente_admin_list-users.md | 20 ++++++++++++++++++ .../ente_admin_update-subscription.md | 10 ++++++--- cli/docs/generated/ente_auth.md | 2 +- cli/docs/generated/ente_auth_decrypt.md | 2 +- cli/docs/generated/ente_export.md | 2 +- cli/docs/generated/ente_version.md | 2 +- 16 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 cli/docs/generated/ente_admin_delete-user.md create mode 100644 cli/docs/generated/ente_admin_list-users.md diff --git a/cli/docs/generated/ente.md b/cli/docs/generated/ente.md index 6d0263ce42..b9d3cde176 100644 --- a/cli/docs/generated/ente.md +++ b/cli/docs/generated/ente.md @@ -25,4 +25,4 @@ ente [flags] * [ente export](ente_export.md) - Starts the export process * [ente version](ente_version.md) - Prints the current version -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_account.md b/cli/docs/generated/ente_account.md index ec26f95577..c48a653365 100644 --- a/cli/docs/generated/ente_account.md +++ b/cli/docs/generated/ente_account.md @@ -16,4 +16,4 @@ Manage account settings * [ente account list](ente_account_list.md) - list configured accounts * [ente account update](ente_account_update.md) - Update an existing account's export directory -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_account_add.md b/cli/docs/generated/ente_account_add.md index 74b2c23f9c..1904ca3702 100644 --- a/cli/docs/generated/ente_account_add.md +++ b/cli/docs/generated/ente_account_add.md @@ -16,4 +16,4 @@ ente account add [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_account_get-token.md b/cli/docs/generated/ente_account_get-token.md index 58ef3e7cd2..d7ee77255c 100644 --- a/cli/docs/generated/ente_account_get-token.md +++ b/cli/docs/generated/ente_account_get-token.md @@ -18,4 +18,4 @@ ente account get-token [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_account_list.md b/cli/docs/generated/ente_account_list.md index 3fc6fbc2e8..cfc59bb8d2 100644 --- a/cli/docs/generated/ente_account_list.md +++ b/cli/docs/generated/ente_account_list.md @@ -16,4 +16,4 @@ ente account list [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_account_update.md b/cli/docs/generated/ente_account_update.md index 04c4418e70..acb65412aa 100644 --- a/cli/docs/generated/ente_account_update.md +++ b/cli/docs/generated/ente_account_update.md @@ -19,4 +19,4 @@ ente account update [flags] * [ente account](ente_account.md) - Manage account settings -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_admin.md b/cli/docs/generated/ente_admin.md index 91e70324d0..aafe51b396 100644 --- a/cli/docs/generated/ente_admin.md +++ b/cli/docs/generated/ente_admin.md @@ -15,8 +15,10 @@ Commands for admin actions like disable or enabling 2fa, bumping up the storage ### SEE ALSO * [ente](ente.md) - CLI tool for exporting your photos from ente.io +* [ente admin delete-user](ente_admin_delete-user.md) - Delete a user * [ente admin disable-2fa](ente_admin_disable-2fa.md) - Disable 2fa for a user * [ente admin get-user-id](ente_admin_get-user-id.md) - Get user id -* [ente admin update-subscription](ente_admin_update-subscription.md) - Update subscription for the free user +* [ente admin list-users](ente_admin_list-users.md) - List all users +* [ente admin update-subscription](ente_admin_update-subscription.md) - Update subscription for user -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_admin_delete-user.md b/cli/docs/generated/ente_admin_delete-user.md new file mode 100644 index 0000000000..56c96841ed --- /dev/null +++ b/cli/docs/generated/ente_admin_delete-user.md @@ -0,0 +1,21 @@ +## ente admin delete-user + +Delete a user + +``` +ente admin delete-user [flags] +``` + +### Options + +``` + -a, --admin-user string The email of the admin user. + -h, --help help for delete-user + -u, --user string The email of the user to delete. (required) +``` + +### SEE ALSO + +* [ente admin](ente_admin.md) - Commands for admin actions + +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_admin_disable-2fa.md b/cli/docs/generated/ente_admin_disable-2fa.md index 19183fdfe6..333f0912e3 100644 --- a/cli/docs/generated/ente_admin_disable-2fa.md +++ b/cli/docs/generated/ente_admin_disable-2fa.md @@ -9,7 +9,7 @@ ente admin disable-2fa [flags] ### Options ``` - -a, --admin-user string The email of the admin user. (required) + -a, --admin-user string The email of the admin user. -h, --help help for disable-2fa -u, --user string The email of the user to disable 2FA for. (required) ``` @@ -18,4 +18,4 @@ ente admin disable-2fa [flags] * [ente admin](ente_admin.md) - Commands for admin actions -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_admin_get-user-id.md b/cli/docs/generated/ente_admin_get-user-id.md index 0151a3ec85..3d26f624ac 100644 --- a/cli/docs/generated/ente_admin_get-user-id.md +++ b/cli/docs/generated/ente_admin_get-user-id.md @@ -9,7 +9,7 @@ ente admin get-user-id [flags] ### Options ``` - -a, --admin-user string The email of the admin user. (required) + -a, --admin-user string The email of the admin user. -h, --help help for get-user-id -u, --user string The email of the user to fetch details for. (required) ``` @@ -18,4 +18,4 @@ ente admin get-user-id [flags] * [ente admin](ente_admin.md) - Commands for admin actions -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_admin_list-users.md b/cli/docs/generated/ente_admin_list-users.md new file mode 100644 index 0000000000..8841df57b5 --- /dev/null +++ b/cli/docs/generated/ente_admin_list-users.md @@ -0,0 +1,20 @@ +## ente admin list-users + +List all users + +``` +ente admin list-users [flags] +``` + +### Options + +``` + -a, --admin-user string The email of the admin user. + -h, --help help for list-users +``` + +### SEE ALSO + +* [ente admin](ente_admin.md) - Commands for admin actions + +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_admin_update-subscription.md b/cli/docs/generated/ente_admin_update-subscription.md index 30339acf20..cc1fa96234 100644 --- a/cli/docs/generated/ente_admin_update-subscription.md +++ b/cli/docs/generated/ente_admin_update-subscription.md @@ -1,6 +1,10 @@ ## ente admin update-subscription -Update subscription for the free user +Update subscription for user + +### Synopsis + +Update subscription for the free user. If you want to apply specific limits, use the `--no-limit False` flag ``` ente admin update-subscription [flags] @@ -9,7 +13,7 @@ ente admin update-subscription [flags] ### Options ``` - -a, --admin-user string The email of the admin user. (required) + -a, --admin-user string The email of the admin user. -h, --help help for update-subscription --no-limit string When true, sets 100TB as storage limit, and expiry to current date + 100 years (default "True") -u, --user string The email of the user to update subscription for. (required) @@ -19,4 +23,4 @@ ente admin update-subscription [flags] * [ente admin](ente_admin.md) - Commands for admin actions -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_auth.md b/cli/docs/generated/ente_auth.md index 4a64a944dd..5770f36f39 100644 --- a/cli/docs/generated/ente_auth.md +++ b/cli/docs/generated/ente_auth.md @@ -13,4 +13,4 @@ Authenticator commands * [ente](ente.md) - CLI tool for exporting your photos from ente.io * [ente auth decrypt](ente_auth_decrypt.md) - Decrypt authenticator export -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_auth_decrypt.md b/cli/docs/generated/ente_auth_decrypt.md index 1203319e9c..e573db2a33 100644 --- a/cli/docs/generated/ente_auth_decrypt.md +++ b/cli/docs/generated/ente_auth_decrypt.md @@ -16,4 +16,4 @@ ente auth decrypt [input] [output] [flags] * [ente auth](ente_auth.md) - Authenticator commands -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_export.md b/cli/docs/generated/ente_export.md index fb4cc6541b..c5783236cf 100644 --- a/cli/docs/generated/ente_export.md +++ b/cli/docs/generated/ente_export.md @@ -16,4 +16,4 @@ ente export [flags] * [ente](ente.md) - CLI tool for exporting your photos from ente.io -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 diff --git a/cli/docs/generated/ente_version.md b/cli/docs/generated/ente_version.md index 0254e2ebd2..b51055697f 100644 --- a/cli/docs/generated/ente_version.md +++ b/cli/docs/generated/ente_version.md @@ -16,4 +16,4 @@ ente version [flags] * [ente](ente.md) - CLI tool for exporting your photos from ente.io -###### Auto generated by spf13/cobra on 13-Mar-2024 +###### Auto generated by spf13/cobra on 14-Mar-2024 From 96072a607c1c041edf9d97bb150a3f1a83488789 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Thu, 14 Mar 2024 16:20:08 +0530 Subject: [PATCH 310/391] nit: fix typo --- .../keyboard/{keybiard_oveylay.dart => keyboard_oveylay.dart} | 0 mobile/lib/ui/viewer/file/file_caption_widget.dart | 2 +- mobile/lib/ui/viewer/location/add_location_sheet.dart | 2 +- mobile/lib/ui/viewer/location/edit_location_sheet.dart | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename mobile/lib/ui/components/keyboard/{keybiard_oveylay.dart => keyboard_oveylay.dart} (100%) diff --git a/mobile/lib/ui/components/keyboard/keybiard_oveylay.dart b/mobile/lib/ui/components/keyboard/keyboard_oveylay.dart similarity index 100% rename from mobile/lib/ui/components/keyboard/keybiard_oveylay.dart rename to mobile/lib/ui/components/keyboard/keyboard_oveylay.dart diff --git a/mobile/lib/ui/viewer/file/file_caption_widget.dart b/mobile/lib/ui/viewer/file/file_caption_widget.dart index 446c9ce551..bec10c7b20 100644 --- a/mobile/lib/ui/viewer/file/file_caption_widget.dart +++ b/mobile/lib/ui/viewer/file/file_caption_widget.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import "package:photos/generated/l10n.dart"; import 'package:photos/models/file/file.dart'; import 'package:photos/theme/ente_theme.dart'; -import 'package:photos/ui/components/keyboard/keybiard_oveylay.dart'; +import 'package:photos/ui/components/keyboard/keyboard_oveylay.dart'; import 'package:photos/ui/components/keyboard/keyboard_top_button.dart'; import 'package:photos/utils/magic_util.dart'; diff --git a/mobile/lib/ui/viewer/location/add_location_sheet.dart b/mobile/lib/ui/viewer/location/add_location_sheet.dart index cf66294315..9e1345dc04 100644 --- a/mobile/lib/ui/viewer/location/add_location_sheet.dart +++ b/mobile/lib/ui/viewer/location/add_location_sheet.dart @@ -12,7 +12,7 @@ import "package:photos/ui/common/loading_widget.dart"; import "package:photos/ui/components/bottom_of_title_bar_widget.dart"; import "package:photos/ui/components/buttons/button_widget.dart"; import "package:photos/ui/components/divider_widget.dart"; -import "package:photos/ui/components/keyboard/keybiard_oveylay.dart"; +import 'package:photos/ui/components/keyboard/keyboard_oveylay.dart'; import "package:photos/ui/components/keyboard/keyboard_top_button.dart"; import "package:photos/ui/components/models/button_type.dart"; import "package:photos/ui/components/text_input_widget.dart"; diff --git a/mobile/lib/ui/viewer/location/edit_location_sheet.dart b/mobile/lib/ui/viewer/location/edit_location_sheet.dart index b5c517a66d..66df52e909 100644 --- a/mobile/lib/ui/viewer/location/edit_location_sheet.dart +++ b/mobile/lib/ui/viewer/location/edit_location_sheet.dart @@ -13,7 +13,7 @@ import "package:photos/ui/common/loading_widget.dart"; import "package:photos/ui/components/bottom_of_title_bar_widget.dart"; import "package:photos/ui/components/buttons/button_widget.dart"; import "package:photos/ui/components/divider_widget.dart"; -import "package:photos/ui/components/keyboard/keybiard_oveylay.dart"; +import 'package:photos/ui/components/keyboard/keyboard_oveylay.dart'; import "package:photos/ui/components/keyboard/keyboard_top_button.dart"; import "package:photos/ui/components/models/button_type.dart"; import "package:photos/ui/components/text_input_widget.dart"; From 80498340b6fd163c1137c9762d5e77fd0c3e5b31 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:20:47 +0530 Subject: [PATCH 311/391] [cli] Mark docs/generated as generated for Github --- cli/.gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 cli/.gitattributes diff --git a/cli/.gitattributes b/cli/.gitattributes new file mode 100644 index 0000000000..71965b8581 --- /dev/null +++ b/cli/.gitattributes @@ -0,0 +1 @@ +docs/generated/*.md linguist-generated=true From b9a7d0926539f533c506c570ff22fdd0b356735e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:23:51 +0530 Subject: [PATCH 312/391] [auth] New translations (#1093) New translations from [Crowdin](https://crowdin.com/project/ente-authenticator-app) Co-authored-by: Crowdin Bot --- auth/lib/l10n/arb/app_de.arb | 1 - auth/lib/l10n/arb/app_ja.arb | 3 ++- auth/lib/l10n/arb/app_pt.arb | 1 - auth/lib/l10n/arb/app_zh.arb | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/auth/lib/l10n/arb/app_de.arb b/auth/lib/l10n/arb/app_de.arb index a05c7ca0d5..32507899c8 100644 --- a/auth/lib/l10n/arb/app_de.arb +++ b/auth/lib/l10n/arb/app_de.arb @@ -407,7 +407,6 @@ "hearUsWhereTitle": "Wie hast du von Ente erfahren? (optional)", "hearUsExplanation": "Wir tracken keine App-Installationen. Es würde uns jedoch helfen, wenn du uns mitteilst, wie du von uns erfahren hast!", "waitingForBrowserRequest": "Warten auf Browseranfrage...", - "launchPasskeyUrlAgain": "Passwort-URL erneut starten", "passkey": "Passkey", "developerSettingsWarning": "Sind Sie sicher, dass Sie die Entwicklereinstellungen ändern möchten?", "developerSettings": "Entwicklereinstellungen", diff --git a/auth/lib/l10n/arb/app_ja.arb b/auth/lib/l10n/arb/app_ja.arb index ed1786f714..5b281747fc 100644 --- a/auth/lib/l10n/arb/app_ja.arb +++ b/auth/lib/l10n/arb/app_ja.arb @@ -145,6 +145,7 @@ "lostDeviceTitle": "デバイスを紛失しましたか?", "twoFactorAuthTitle": "2 要素認証", "passkeyAuthTitle": "パスキー認証", + "verifyPasskey": "パスキーの認証", "recoverAccount": "アカウントを回復", "enterRecoveryKeyHint": "回復キーを入力", "recover": "回復", @@ -407,7 +408,7 @@ "hearUsWhereTitle": "Ente についてどのようにお聞きになりましたか?(任意)", "hearUsExplanation": "私たちはアプリのインストールを追跡していません。私たちをお知りになった場所を教えてください!", "waitingForBrowserRequest": "ブラウザのリクエストを待っています...", - "launchPasskeyUrlAgain": "パスキーのURLを再度起動する", + "waitingForVerification": "認証を待っています...", "passkey": "パスキー", "developerSettingsWarning": "開発者向け設定を変更してもよろしいですか?", "developerSettings": "開発者向け設定", diff --git a/auth/lib/l10n/arb/app_pt.arb b/auth/lib/l10n/arb/app_pt.arb index 10c34ab296..aa6a2a837e 100644 --- a/auth/lib/l10n/arb/app_pt.arb +++ b/auth/lib/l10n/arb/app_pt.arb @@ -407,7 +407,6 @@ "hearUsWhereTitle": "Como você ouviu sobre o Ente? (opcional)", "hearUsExplanation": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!", "waitingForBrowserRequest": "Aguardando solicitação do navegador...", - "launchPasskeyUrlAgain": "Iniciar a URL de chave de acesso novamente", "passkey": "Chave de acesso", "developerSettingsWarning": "Tem certeza de que deseja modificar as configurações de Desenvolvedor?", "developerSettings": "Configurações de desenvolvedor", diff --git a/auth/lib/l10n/arb/app_zh.arb b/auth/lib/l10n/arb/app_zh.arb index b6d4ed244f..e07e7dcfa0 100644 --- a/auth/lib/l10n/arb/app_zh.arb +++ b/auth/lib/l10n/arb/app_zh.arb @@ -407,7 +407,6 @@ "hearUsWhereTitle": "您是如何知道Ente的? (可选的)", "hearUsExplanation": "我们不跟踪应用程序安装情况。如果您告诉我们您是在哪里找到我们的,将会有所帮助!", "waitingForBrowserRequest": "正在等待浏览器请求...", - "launchPasskeyUrlAgain": "再次启动 通行密钥 URL", "passkey": "通行密钥", "developerSettingsWarning": "您确定要修改开发者设置吗?", "developerSettings": "开发者设置", From 2905315e0077e1a467b360e03eee97235e4a0542 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 16:23:53 +0530 Subject: [PATCH 313/391] [server] Improve the architecture diagram Add a dotted arrow between museum and the hot object storage to indicate that clients talk directly to the primary S3 storage. This has confused some users who were trying to setup self-hosting, them not realizing that the minio buckets need to be accessible outside the container. The actual flow is - for both GET and PUT, museum conjures up pre-signed URLs by talking to the S3 bucket, and vends these pre-signed URLs back to the client. Thereafter though (unless routed via a Cloudflare worker, which is not the case when self-hosting), the clients directly connect to this presigned URL. Maybe too much information to convey with a single dotted arrow, but at least it'll give a hint that there is a direct connection there somewhere. --- server/scripts/images/museum.png | Bin 104994 -> 166243 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/server/scripts/images/museum.png b/server/scripts/images/museum.png index a93370da8a8e620bbd2ad6d21b1caa9e4a016388..bd837dc369507f1a083ffd4926ff5aae1ca9d35c 100644 GIT binary patch literal 166243 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

p9?9Eg(^ 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 literal 104994 zcmeEuc{tQ-|1cBT5)vv|N>bU9vYQ#HNQsoCtR>lE>}xY)Xcv(XJ5Z}jnC-ua_`_~VPWAt zsejCbg@t2`g@t`9=SJ{EP)!p2dlS@ISJ(KYuCAo97vie(H3t?J{kxCNIV{e75>B!- z+4Y(QVsaD_s?RGaeM1-?ByjD<9{9dpd)b6E%QFUhKR{G`Opg_8xU4rRcaN8PS?Bl# z5gxx`L+;V?yz4X9316uMbmPj%moo2q7F=MctnkRQi!49FxuxeW>D+J0bl%i@E`;S! zGkbAOO#P#K7YYi_vh>z0&n!-FB;NAtIGIaoT3vJLy^e|IVA;asxzYA>{p}?dmH;6m zx&3S*`$pttgzgP*Q^Cn%xQ=SsMixew8bm5b2VmdIC?)ZF@~~X-RWN_Z9#ZS@QTblL z1!LV5k;@_iw)-IPN2~>C6pB^iyU(2|9Cq8~GN|$pM`AYK`RXPYud)ka7V085qrz^Q zc#8XfUb_&v=C&O83bRcmKhyEl+o56aTfP-fEcy4>jq{W59C~gq*@;;SdyqGKdt2Jo z`nQjwS2L81KHoaBfx=%gTlOZ3UsQMJfzRQQCUe`LyfxnZ-s2|j(aoC)$L{b-CMiC+ zwI}1ciUId`(}HHoX|DLR?@gZ4_e$q2$PQ&EZ z^SH!qx!HW3Z-)-d-}Zi^z;i4+l~oMmZ}T z3ztn-OK(alo^G^+Pb$b87)N|~#Pcom{P@t5?{B-0IV1&mZdToG_JpsR?HH>H=f+Kv zVe%WchU}EQHsL&qG5?%oT*JQQ0XtjG$q$?E>z^gw8B}838V1|7g=K88RPuNp%T}G$ z3CS!i4b17|h^WiQ6apZg&^v5_vlm}%liqPZW|O$?i6!i)Rd>Kaf>!qr+FFu?9bQ@P z-Pm?|lgzCxQ=U>^CCDFA29@|#%oFYg^L-hrfPLe7mN@&sBeD5p z=@A`^-OKyy&*B8fZ@+YjnzNVp5X~6FaC}1wA1zhX+?k}GeuH+Aj=+q3}321z`EmtAeo#i85@pD&KyxIr<4J`;- zW5e9zZmV;cUHx%mZ-^X#P#vot#8cX~ezkHs_4ZMS# zYFv#W;e&@tH&54ew6WWS*vxLeeuDqTjb?t0%Xi{-b>5Nse(#_FdJo&(qu-;>?-BcS z^w^zEPi}qD`5fi&@!}Ohld#F-n|H}XE$C}{@dSqWNaaNt?Ys3dr96YnC2X_alYKl9 z#{^qEorE<6pI#Mo}qi6J7q-DZMh60&-$MWLVnElT_agb-OXvwcq9PuXaJKwC$ ziYVs9!M$o*u5<2u>vUB3(w1k@#yZ^wYWixt$!Q92HFrm47`>JbdgG|{I8Hagz)Igr z@2jDf&NUh6?!_qmJ-QF2K4G`&et*b)GA;E;YGUe8s%)x4E61xHJ@+RKHcO{R9sjY# zi#?EIdD}Ag^8RJz$XGk0Blg%gVPRJa)ou_Q>SlGBf zQP1bT`$@;PK%zQPp4diIuzsGKqoAj%S7PNK>mKi(mlT;)Ve@L>N|ixXN>Cytt~vs$ z2Qxw!tU_s`l;m4+n=bJRY`SnT)&1k+T{FD5cChW>-1K>qpQx4U(v^<~Hz|ENV&&3p z7tqA1>UHp*^3yA?2S#6?Z8GkER;?STTYqa>G^lUe5x;|xs!1-DJ*6F`P4CNzGz(ir^jN3Ig zlWRYF4tHx69?2i>7Vhip9VklaVedA4omE_M)#$Zj??`W6A$~GMBS7tn=6MY(uVZ4` zVmBivcJ|#CxE07J$eShJ`7L$&z1IP+m%c%R*)uzbt-gO9T=6RHn0@{2)a_)k)rJr6 zq?;VV>k|buq;{W(zVEbSuD9dO`PHzX``u9{5QsNcx-sNL44!Ijq@8yHbNbG3cV~eFDQmt zh3?Ve2pcFwcDMD&gcc0u555{K=1+W(`k-hRSy%pO;ZaxJ;CEVYU))OMl)0gIOObbG zFwP?&VaFN74fFTJJ2CpCk2gLRMe(KVe7@(bVM_B^fs`0*xu~0%{5|(OtV#)S!%F1K zZuT;@;*nCdA8Ji&weLy@z~oo2L9{O&eH(eh|E|v6aKV{9J<^{ZK7DlLQQh9IJ$NIo zGZ$i7)q|Es$5Iqu>`3E2C)%d({K?s}jZ%B#{sr|HuGw|ntp%#JJ(2NR(<=cfbAdzH zGtCJ#iTSX^2T2dBrD!~=w=5f`>Ibi!cOcGpSDIFetiV^fQ6)7-`KMv?9DdOvS^|5z|sI_hDL$uW&Hy%rff=pU92ey?n=@ZDPpKM)Q*ZIJXD{c7<_%a6|e zo6iZK4!pSY;!5B7>jw}n3x^k+3)8jZ8lP4>Z#*Pre`4Wu{S$9TzXtC3BBYA1-}EHm zl$Alu9>lZ8m0=lP&XS>nF?)nnmXX zRCvApydX3!Bx-in{F9k)Zsf)O(pr~>hevEXujW0Aam`E5`nd&51S9458O$An~B4;9yQPihoWpbBTKGfLv z0V+RRJTuvZ(D$IfxhJl-8@2DdvG*fH+naZdw@bv7U?zd*XGXu_#O&RvlRM^d3pS80fn6(>^gOA+|gcx(I5r%>W35Faj z!NoOGBJEu}dEj!qA;%CQ9Zn5w6jZTGA0{>pJ})AG}(WY*P){p1AL58A@^kEZ=^ znnuv9OOWd>PvG!U5K34%Se(3SXvlH^{N`j~W8KKI0sLZRfq;K)`QtY$_`UBx&u=@k zu&u9QVS$4GXJLWhAb&pL7{hJ&^Edle`X9wQFN079QtEu(!pFk!w1z#xP2tiN#AOGC z05=c%0v4?R4e-;=!RL}>fZH{9Z;b%$-Rmnfz;F6v#odzYOMG0lcUu@5OX?!L93)i~ z4k{en4ds@Ul+^ONa#h3R*oi-02mhtL+sVhrLqk!~-``)sUs(a+<*2BnuCA_l@Q~u6 zL-JsSymz3x&!qr)cWXecwx$5xzd!yLZzM`k#M(!Rh0C z^*<-Md;f7Qa6v`-Ulf%T4k|Kw%^|><$!qk#{CaKuUcZjhqHm_5i*WPsa`5&BU_q6% z)(`mGv;TniYrTnsH{zNv{T8O~&OXpXf4uTvkN^8EBQIwMfEM~||8vS;pZ)iGV<&_U z0+7hd+5V)vkAoKg@sGFvJdpW{zwAZ7w}!EEfWtM5W6o|4?(4Tabnws-Ek%ZZV)*KX z|GcWCeDL63U;WFU{&-bOkxtvc(E1l6tv>~v1m)IJ{2#7_a;uW2rdU|uEGLiYoDX1~ z?6=L{(}k2-^q#TeUE@`k+H60LJ-(&!;XMalfeR-#IiIwI3ws@HwUV-7ljMT!6(|~T zjEd)Y$ETEbQzWq9q|`@UVV;OkmNUX%9_Z}kh&p{$h(lI=P#?1A6wB=p{jWV)|prmDZAqd)y6l%06q-?t;v8;Tdd8;3}4+uy^if&tep?`tr{2Bpi-SL^SBJYg( zgB}My1JVGlu0hTnHEt*@n0(^zYOkg-}ac6 zO^ze2OjWmM&t;RJj<1Xp{9dRdo{anm67y+75(th~RGX3}N4r+vN0C!~YZs_Tp1~eX z2M!i+O&wb;eykbn3ma&R>=NwVhC~wscfd+^kc)yNM6>hqY%BbTRV}Wyy%l~aC{!b+ zW$~q_wWezFqrC0Nyr3j%33BzLdRKy1MOos(ilBj_;2(bTq~))re#Ag4%i(8zrqQ?<3G#zajr!7S_!;#lf<{N_F^=a}2?

)dQy;6CZn3NSbEW;w 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 From a010a90ed6b66cf1d0f67250ce4b04a0943d12f4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:24:13 +0530 Subject: [PATCH 314/391] [mobile] New translations (#1092) New translations from [Crowdin](https://crowdin.com/project/ente-photos-app) Co-authored-by: Crowdin Bot --- mobile/fastlane/metadata/android/zh/full_description.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/fastlane/metadata/android/zh/full_description.txt b/mobile/fastlane/metadata/android/zh/full_description.txt index 301c5bd352..2410d9da0f 100644 --- a/mobile/fastlane/metadata/android/zh/full_description.txt +++ b/mobile/fastlane/metadata/android/zh/full_description.txt @@ -4,7 +4,7 @@ ente 是一个简单的应用程序来备份和分享您的照片和视频。 我们在Android、iOS、web 和桌面上有开源应用, 和您的照片将以端到端加密方式 (e2ee) 无缝同步。 -ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他们可能并不使用ente。 您可以分享可公开查看的链接,使他们可以查看您的相册,并通过添加照片来协作而不需要注册账户或下载app。 权限 +ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他们可能并不使用ente。 您可以分享可公开查看的链接,使他们可以查看您的相册,并通过添加照片来协作而不需要注册账户或下载app。 ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他们可能并不使用ente。 您可以分享可公开查看的链接,使他们可以查看您的相册,并通过添加照片来协作而不需要注册账户或下载app。 权限 您的加密数据已复制到三个不同的地点,包括巴黎的一个安全屋。 我们认真对待子孙后代,并确保您的回忆比您长寿。 我们认真对待子孙后代,并确保您的回忆比您长寿。 @@ -30,7 +30,7 @@ ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他 ente需要特定权限以执行作为图像存储提供商的职责,相关内容可以在此链接查阅:https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md 价格 -我们不会提供永久免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 +我们不会提供永久免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 支持 我们对提供真人支持感到自豪。 我们对提供真人支持感到自豪。 如果您是我们的付费客户,您可以联系 team@ente.io 并在24小时内收到来自我们团队的回复。 From 966cc697e71dbe002aa46acc7aef2d59fe24b773 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 16:35:36 +0530 Subject: [PATCH 315/391] [server] Move the server related gitattributes within that folder I mistakenly assumed that the gitattributes file can only be at the top level. However, this doesn't seem to be the case - I noticed this in a recent PR - https://github.com/ente-io/ente/pull/1104/files. And it is indeed documented: > When deciding what attributes are assigned to a path, Git .... .gitattributes > file in the same directory as the path in question. .. > > - https://git-scm.com/docs/gitattributes Ref: https://stackoverflow.com/questions/71784062/can-we-have-multiple-gitattributes-files-in-different-repo-subfolders --- .gitattributes => server/.gitattributes | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .gitattributes => server/.gitattributes (100%) diff --git a/.gitattributes b/server/.gitattributes similarity index 100% rename from .gitattributes rename to server/.gitattributes From 22685ae9114442e67e90850f42a91e1d8c3fd6f3 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Thu, 14 Mar 2024 16:35:38 +0530 Subject: [PATCH 316/391] Increase interaction timeout to 15s --- .../machine_learning/machine_learning_controller.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mobile/lib/services/machine_learning/machine_learning_controller.dart b/mobile/lib/services/machine_learning/machine_learning_controller.dart index a31da95b18..145670f2c8 100644 --- a/mobile/lib/services/machine_learning/machine_learning_controller.dart +++ b/mobile/lib/services/machine_learning/machine_learning_controller.dart @@ -17,8 +17,7 @@ class MachineLearningController { static const kMaximumTemperature = 42; // 42 degree celsius static const kMinimumBatteryLevel = 20; // 20% - static const kInitialInteractionTimeout = Duration(seconds: 10); - static const kDefaultInteractionTimeout = Duration(seconds: 5); + static const kDefaultInteractionTimeout = Duration(seconds: 15); static const kUnhealthyStates = ["over_heat", "over_voltage", "dead"]; bool _isDeviceHealthy = true; @@ -28,7 +27,7 @@ class MachineLearningController { void init() { if (Platform.isAndroid) { - _startInteractionTimer(timeout: kInitialInteractionTimeout); + _startInteractionTimer(); BatteryInfoPlugin() .androidBatteryInfoStream .listen((AndroidBatteryInfo? batteryInfo) { From 6e9893e5c516bebb91504d08b3ae2ca91731bce0 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 17:14:34 +0530 Subject: [PATCH 317/391] Create infra directory --- infra/.gitignore | 2 ++ infra/README.md | 8 ++++++++ 2 files changed, 10 insertions(+) create mode 100644 infra/.gitignore create mode 100644 infra/README.md diff --git a/infra/.gitignore b/infra/.gitignore new file mode 100644 index 0000000000..a0090b46d7 --- /dev/null +++ b/infra/.gitignore @@ -0,0 +1,2 @@ +# macOS +.DS_Store diff --git a/infra/README.md b/infra/README.md new file mode 100644 index 0000000000..e1ad6de6e4 --- /dev/null +++ b/infra/README.md @@ -0,0 +1,8 @@ +# Infra + +Various knick-knacks that we use when hosting our servers. + +These are not needed for running Ente's server or for self-hosting, these are +just additional services we run to make our infrastructure more robust. As such, +it's unlikely that you'll find the pieces here directly useful for your needs, +but feel free to have a look around if you're curious! From 3e38d56579af95eeb94d074677a820bda5cd6720 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 17:15:37 +0530 Subject: [PATCH 318/391] Import the code for copycat-db --- infra/copycat-db/.github/workflows/ci.yaml | 29 +++++ infra/copycat-db/.gitignore | 2 + infra/copycat-db/Dockerfile | 34 +++++ infra/copycat-db/README.md | 144 +++++++++++++++++++++ infra/copycat-db/Runbook.md | 13 ++ infra/copycat-db/copycat-db.sample.env | 8 ++ infra/copycat-db/copycat-db.service | 20 +++ infra/copycat-db/copycat-db.timer | 8 ++ infra/copycat-db/src/backup.sh | 50 +++++++ infra/copycat-db/src/restore.sh | 42 ++++++ infra/copycat-db/test.sh | 20 +++ 11 files changed, 370 insertions(+) create mode 100644 infra/copycat-db/.github/workflows/ci.yaml create mode 100644 infra/copycat-db/.gitignore create mode 100644 infra/copycat-db/Dockerfile create mode 100644 infra/copycat-db/README.md create mode 100644 infra/copycat-db/Runbook.md create mode 100644 infra/copycat-db/copycat-db.sample.env create mode 100644 infra/copycat-db/copycat-db.service create mode 100644 infra/copycat-db/copycat-db.timer create mode 100755 infra/copycat-db/src/backup.sh create mode 100755 infra/copycat-db/src/restore.sh create mode 100755 infra/copycat-db/test.sh diff --git a/infra/copycat-db/.github/workflows/ci.yaml b/infra/copycat-db/.github/workflows/ci.yaml new file mode 100644 index 0000000000..aa57e206c9 --- /dev/null +++ b/infra/copycat-db/.github/workflows/ci.yaml @@ -0,0 +1,29 @@ +name: Build and push Docker image + +on: + # Enable manual run + workflow_dispatch: + push: + branches: + - release + # Sequence of patterns matched against refs/tags + tags: + - "v*" # Push events to matching v*, i.e. v4.2.0 + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + name: Check out code + + - uses: mr-smithers-excellent/docker-build-push@v6 + name: Build & Push + with: + image: ente/copycat-db + registry: rg.fr-par.scw.cloud + tags: ${GITHUB_SHA}, latest + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + env: + GIT_COMMIT: ${GITHUB_SHA} diff --git a/infra/copycat-db/.gitignore b/infra/copycat-db/.gitignore new file mode 100644 index 0000000000..75236ad1c9 --- /dev/null +++ b/infra/copycat-db/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +copycat-db.env diff --git a/infra/copycat-db/Dockerfile b/infra/copycat-db/Dockerfile new file mode 100644 index 0000000000..4328ef17fb --- /dev/null +++ b/infra/copycat-db/Dockerfile @@ -0,0 +1,34 @@ +FROM ubuntu:latest + +RUN apt-get update && apt-get install -y curl gnupg +RUN apt-get install -y tini + +# Install pg_dump (via Postgres client) +# https://www.postgresql.org/download/linux/ubuntu/ +# +# We don't need it for production backups, but this is useful for local testing. +RUN \ + apt-get install -y lsb-release && \ + sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && \ + curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \ + apt-get update && \ + apt-get -y install postgresql-client-12 + +# Install SCW CLI +# Latest release: https://github.com/scaleway/scaleway-cli/releases/latest +RUN \ + export VERSION="2.26.0" && \ + curl -o /usr/local/bin/scw -L "https://github.com/scaleway/scaleway-cli/releases/download/v${VERSION}/scaleway-cli_${VERSION}_linux_amd64" && \ + chmod +x /usr/local/bin/scw + +RUN apt-get install -y jq + +# Install rclone +RUN apt-get install -y unzip +RUN curl https://rclone.org/install.sh | bash + +COPY src / + +ENTRYPOINT ["tini", "--"] + +CMD [ "/backup.sh" ] diff --git a/infra/copycat-db/README.md b/infra/copycat-db/README.md new file mode 100644 index 0000000000..95ca44ea44 --- /dev/null +++ b/infra/copycat-db/README.md @@ -0,0 +1,144 @@ +## Introduction + +Copycat DB is a [service](https://github.com/ente-io/infra) to take a backup of +our database. It uses the Scaleway CLI to take backups of the database, and +uploads them to an offsite bucket. + +This bucket has an object lock configured, so backups cannot be deleted before +expiry. Conversely, the service also deletes backups older than some threshold +when it creates a new one to avoid indefinite retention. + +In production the service runs as a cron job, scheduled using a systemd timer. + +## Required environment variables + +##### SCW_CONFIG_PATH + +Path to the `config.yaml` used by Scaleway CLI. + +This contains the credentials and the default region to use when trying to +create and download the database dump. + +If needed, this config file can be generated by running the following commands +on a shell prompt in the container (using `./test.sh sh`) + + scw init + scw config dump + +##### SCW_RDB_INSTANCE_ID + +The UUID of the Scalway RDB instance that we wish to backup. If this is missing, +then the Docker image falls back to using `pg_dump` (as outlined next). + +##### PGUSER, PGPASSWORD, PGHOST + +Not needed in production when taking a backup (since we use the Scaleway CLI to +take backups in production). + +These are used when testing a backup using `pg_dump`, and when restoring backups. + +##### RCLONE_CONFIG + +Location of the config file, that contains the destination bucket where you want +to use to save the backups, and the credentials to to access it. + +Specifically, the config file contains two remotes: + +* The bucket itself, where data will be stored. + +* A "crypt" remote that wraps the bucket by applying client side encryption. + +The configuration file will contain (lightly) obfuscated versions of the +password, and as long as we have the configuration file we can continue using +rclone to download and decrypt the plaintext. Still, it is helpful to retain the +original password too separately so that the file can be recreated if needed. + +A config file can be generated using `./test.sh sh` + + rclone config + rclone config show + +When generating the config, we keep file (and directory) name encryption off. + +Note that rclone creates a backup of the config file, so Docker needs to have +write access to the directory where it is mounted. + +##### RCLONE_DESTINATION + +Name of the (crypt) remote to which the dump should be saved. Example: +`db-backup-crypt:`. + +Note that this will not include the bucket - the bucket name will be part of the +remote that the crypt remote wraps. + +##### Logging + +The service logs to its standard out/error. The systemd unit is configured to +route these to `/var/logs/copycat-db.log`. + +## Local testing + +The provided `test.sh` script can be used to do a smoke test for building and +running the image. For example, + + ./test.sh bin/bash + +gives us a shell prompt inside the built and running container. + +For more thorough testing, run this service as part of a local test-cluster. + +## Restoring + +The service also knows how to restore the latest backup into a Postgres +instance. This functionality is used to periodically verify that the backups are +restorable. + +To invoke this, use "./restore.sh" as the command when running the container +(e.g. `./test.sh ./restore.sh`). This will restore the latest backup into the +Postgres instance whose credentials are provided via the various `PG*` +environment variables. + +## Preparing the bucket + +The database dumps are stored in a bucket that has object lock enabled +(Compliance mode), and has a default bucket level retention time of 30 days. + +## Deploying + +Ensure that promtail is running, and is configured to scrape +`/root/var/logs/copycat-db.log`. + +Create that the config and log destination directories + + sudo mkdir -p /root/var/config/scw + sudo mkdir -p /root/var/config/rclone + sudo mkdir -p /root/var/logs + +Create the env, scw and rclone configuration files + + sudo tee /root/copycat-db.env + sudo tee /root/var/config/scw/copycat-db-config.yaml + sudo tee /root/var/config/rclone/copycat-db-rclone.conf + +Add the service definition, and start the service + + scp copycat-db.{service,timer} instance: + + sudo mv copycat-db.{service,timer} /etc/systemd/system + sudo systemctl daemon-reload + +To enable the cron job + + sudo systemctl enable --now copycat-db.timer + +The timer will trigger the service on the specified schedule. In addition, if +you wish to force the job to service immediately + + sudo systemctl start copycat-db.service + +## Updating + +To update, run the [Github action](.github/workflows/ci.yaml) to push the latest +image to our Docker Registry, then restart the systemd service on the instance + + sudo systemctl restart copycat-db diff --git a/infra/copycat-db/Runbook.md b/infra/copycat-db/Runbook.md new file mode 100644 index 0000000000..fe8160c1d3 --- /dev/null +++ b/infra/copycat-db/Runbook.md @@ -0,0 +1,13 @@ + +### Service logs + +```bash +tail -f -n 100 /root/var/logs/copycat-db.log +``` + +### Backup timeout +If you are seeing time-out from scw while waiting for backup, usually just stopping the [service](.copycat-db.service) and letting the [daily timer](./copycat-db.timer) restart it later works + +```bash + sudo systemctl stop copycat-db.service +``` diff --git a/infra/copycat-db/copycat-db.sample.env b/infra/copycat-db/copycat-db.sample.env new file mode 100644 index 0000000000..243e8aa5f5 --- /dev/null +++ b/infra/copycat-db/copycat-db.sample.env @@ -0,0 +1,8 @@ +SCW_CONFIG_PATH=/var/config/scw/copycat-db-config.yaml +SCW_RDB_INSTANCE_ID= +PGUSER= +PGPASSWORD= +PGHOST=host.docker.internal +PGPORT= +RCLONE_CONFIG=/var/config/rclone/copycat-db-rclone.conf +RCLONE_DESTINATION=db-backup-crypt: diff --git a/infra/copycat-db/copycat-db.service b/infra/copycat-db/copycat-db.service new file mode 100644 index 0000000000..819baa73c5 --- /dev/null +++ b/infra/copycat-db/copycat-db.service @@ -0,0 +1,20 @@ +[Unit] +Documentation=https://github.com/ente-io/copycat-db +Requires=docker.service +After=docker.service + +[Service] +Restart=always +RestartSec=3600s +# Don't automatically restart if it fails more than 6 times in 24 hours. +StartLimitInterval=86400 +StartLimitBurst=6 +ExecStartPre=docker pull rg.fr-par.scw.cloud/ente/copycat-db +ExecStartPre=-docker stop copycat-db +ExecStartPre=-docker rm copycat-db +ExecStart=docker run --name copycat-db \ + --env-file /root/copycat-db.env \ + -v /root/var:/var \ + rg.fr-par.scw.cloud/ente/copycat-db +StandardOutput=append:/root/var/logs/copycat-db.log +StandardError=inherit diff --git a/infra/copycat-db/copycat-db.timer b/infra/copycat-db/copycat-db.timer new file mode 100644 index 0000000000..c3f6e2e861 --- /dev/null +++ b/infra/copycat-db/copycat-db.timer @@ -0,0 +1,8 @@ +[Unit] +Description=Schedule copycat-db + +[Timer] +OnCalendar=Daily + +[Install] +WantedBy=timers.target diff --git a/infra/copycat-db/src/backup.sh b/infra/copycat-db/src/backup.sh new file mode 100755 index 0000000000..f197f4b0f0 --- /dev/null +++ b/infra/copycat-db/src/backup.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +set -o errexit +set -o xtrace + +NOWS="$(date +%s)" +BACKUP_FILE="db-$NOWS.custom" + +# Scaleway backup names cannot contain dots +BACKUP_NAME="db-$NOWS-custom" + +# Calculate an expiry time 1 month from now +EXPIRYS="$(( 30 * 24 * 60 * 60 + $NOWS ))" + +# Convert it to the ISO 8601 format that SCW CLI understands +# Note that GNU date uses "-d" and an "@" to pass an epoch (macOS uses "-r"). +EXPIRY="$(date -Iseconds --utc --date "@$EXPIRYS")" + +if test -z "$SCW_RDB_INSTANCE_ID" +then + # A required SCW related environment variable hasn't been specified. This is + # expected when running the script locally for testing. Fallback to using + # pg_dump for creating the backup. + pg_dump -Fc ente_db > $BACKUP_FILE +else + # We need to export a backup first after creating it, before it can be + # downloaded. + # + # Further, our backups currently take longer than the default 20 minute + # timeout for the export set by Scaleway, and end up failing: + # + # {"error":"scaleway-sdk-go: waiting for database backup failed: timeout after 20m0s"} + # + # To avoid this we need to add a custom wait here ourselves instead of using + # the convenience `--wait` flag for the export command provided by Scaleway. + BACKUP_ID=$(scw rdb backup create instance-id=$SCW_RDB_INSTANCE_ID \ + name=$BACKUP_NAME expires-at=$EXPIRY \ + database-name=ente_db -o json | jq -r '.id') + scw rdb backup wait $BACKUP_ID timeout=5h + scw rdb backup download output=$BACKUP_FILE \ + $(scw rdb backup export $BACKUP_ID --wait -o json | jq -r '.id') +fi + +rclone copy --log-level INFO $BACKUP_FILE $RCLONE_DESTINATION + +# Delete older backups +rclone delete --log-level INFO --min-age 30d $RCLONE_DESTINATION + +set +o xtrace +echo "copycat-db: backup complete: $BACKUP_FILE" diff --git a/infra/copycat-db/src/restore.sh b/infra/copycat-db/src/restore.sh new file mode 100755 index 0000000000..8df19c62b2 --- /dev/null +++ b/infra/copycat-db/src/restore.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +set -o errexit +set -o xtrace + +# Find the name of the latest backup +# The backup file name contains the epoch, so we can just sort. +BACKUP_FILE=$(rclone lsf --include 'db-*.custom' --files-only $RCLONE_DESTINATION | sort | tail -1) + +# Download it +rclone copy --log-level INFO "${RCLONE_DESTINATION}${BACKUP_FILE}" . + +# Restore from it +# +# This create a database named rdb on Postgres - this is only used for the +# initial connection, the actual ente_db database will be created once the +# restore starts. +# +# Flags: +# +# * no-owner: recreates the schema using the current user, not the one that was +# used for the export. +# +# * no-privileges: skip the assignment of roles (this way we do not have to +# recreate all the users from the original database before proceeding with the +# restore) + +createdb rdb || true +pg_restore -d rdb --create --no-privileges --no-owner --exit-on-error "$BACKUP_FILE" + +# Delete any tokens that were in the backup +psql -d ente_db -c 'delete from tokens' + +# Delete any push tokens that were in the backup +psql -d ente_db -c 'delete from push_tokens' + +# Delete some more temporary data that might've come up in the backup +psql -d ente_db -c 'delete from queue' +psql -d ente_db -c 'delete from temp_objects' + +set +o xtrace +echo "copycat-db: restore complete: $BACKUP_FILE" diff --git a/infra/copycat-db/test.sh b/infra/copycat-db/test.sh new file mode 100755 index 0000000000..d4ac1b35f0 --- /dev/null +++ b/infra/copycat-db/test.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -o xtrace +set -o errexit + +PROJECT=copycat-db + +docker rmi "ente/$PROJECT" || true +docker build --tag "ente/$PROJECT" . + +# Interactively run the container. +# +# By passing "$@", we allow any arguments passed to test.sh to be forwarded to +# the image (useful for testing out things, e.g. `./test.sh sh`). +docker run \ + --interactive --tty --rm \ + --env-file copycat-db.env \ + --name "$PROJECT" \ + "ente/$PROJECT" \ + "$@" From aaffc740bc59a1c8829c759c1c8ee0fedcd96957 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 17:26:11 +0530 Subject: [PATCH 319/391] Update paths --- infra/copycat-db/README.md | 50 ++++++++++++++++++++------ infra/copycat-db/Runbook.md | 13 ------- infra/copycat-db/copycat-db.sample.env | 4 +-- infra/copycat-db/copycat-db.service | 2 +- 4 files changed, 42 insertions(+), 27 deletions(-) delete mode 100644 infra/copycat-db/Runbook.md diff --git a/infra/copycat-db/README.md b/infra/copycat-db/README.md index 95ca44ea44..5bb556a362 100644 --- a/infra/copycat-db/README.md +++ b/infra/copycat-db/README.md @@ -1,8 +1,8 @@ -## Introduction +# Copycat DB -Copycat DB is a [service](https://github.com/ente-io/infra) to take a backup of -our database. It uses the Scaleway CLI to take backups of the database, and -uploads them to an offsite bucket. +Copycat DB is a [service](../service.md) to take a backup of our database. It +uses the Scaleway CLI to take backups of the database, and uploads them to an +offsite bucket. This bucket has an object lock configured, so backups cannot be deleted before expiry. Conversely, the service also deletes backups older than some threshold @@ -10,6 +10,32 @@ when it creates a new one to avoid indefinite retention. In production the service runs as a cron job, scheduled using a systemd timer. +> These backups are in addition to the regular snapshots that we take, and are +> meant as a second layer of replication. For more details, see our [Reliability +> and Replication Specification](https://ente.io/reliability). + + +## Quick help + +View service status (it gets invoked as a timer automatically, doesn't need to +be started/stopped manually): + +```sh +sudo systemctl status copycat-db +``` + +View logs locally (they'll also be available on Grafana): + +```sh +sudo tail /root/var/logs/copycat-db.log +``` + +## Name + +The name copycat-db is a riff on "copycat", which is what we call our museum +instance that does the object replication. This one replicates the DB, so, +copycat-db. + ## Required environment variables ##### SCW_CONFIG_PATH @@ -90,8 +116,8 @@ For more thorough testing, run this service as part of a local test-cluster. ## Restoring The service also knows how to restore the latest backup into a Postgres -instance. This functionality is used to periodically verify that the backups are -restorable. +instance. This functionality by a separate service (Phoenix) to periodically +verify that the backups are restorable. To invoke this, use "./restore.sh" as the command when running the container (e.g. `./test.sh ./restore.sh`). This will restore the latest backup into the @@ -101,7 +127,7 @@ environment variables. ## Preparing the bucket The database dumps are stored in a bucket that has object lock enabled -(Compliance mode), and has a default bucket level retention time of 30 days. +(compliance mode), and has a default bucket level retention time of 30 days. ## Deploying @@ -127,9 +153,9 @@ Add the service definition, and start the service sudo mv copycat-db.{service,timer} /etc/systemd/system sudo systemctl daemon-reload -To enable the cron job +To start the cron job - sudo systemctl enable --now copycat-db.timer + sudo systemctl start copycat-db.timer The timer will trigger the service on the specified schedule. In addition, if you wish to force the job to service immediately @@ -138,7 +164,9 @@ you wish to force the job to service immediately ## Updating -To update, run the [Github action](.github/workflows/ci.yaml) to push the latest -image to our Docker Registry, then restart the systemd service on the instance +To update, run the [GitHub +workflow](../../.github/workflows/copycat-db-release.yaml) to build and push the +latest image to our Docker Registry, then restart the systemd service on the +instance sudo systemctl restart copycat-db diff --git a/infra/copycat-db/Runbook.md b/infra/copycat-db/Runbook.md deleted file mode 100644 index fe8160c1d3..0000000000 --- a/infra/copycat-db/Runbook.md +++ /dev/null @@ -1,13 +0,0 @@ - -### Service logs - -```bash -tail -f -n 100 /root/var/logs/copycat-db.log -``` - -### Backup timeout -If you are seeing time-out from scw while waiting for backup, usually just stopping the [service](.copycat-db.service) and letting the [daily timer](./copycat-db.timer) restart it later works - -```bash - sudo systemctl stop copycat-db.service -``` diff --git a/infra/copycat-db/copycat-db.sample.env b/infra/copycat-db/copycat-db.sample.env index 243e8aa5f5..ba557714e0 100644 --- a/infra/copycat-db/copycat-db.sample.env +++ b/infra/copycat-db/copycat-db.sample.env @@ -1,8 +1,8 @@ SCW_CONFIG_PATH=/var/config/scw/copycat-db-config.yaml SCW_RDB_INSTANCE_ID= +RCLONE_CONFIG=/var/config/rclone/copycat-db-rclone.conf +RCLONE_DESTINATION=db-backup-crypt: PGUSER= PGPASSWORD= PGHOST=host.docker.internal PGPORT= -RCLONE_CONFIG=/var/config/rclone/copycat-db-rclone.conf -RCLONE_DESTINATION=db-backup-crypt: diff --git a/infra/copycat-db/copycat-db.service b/infra/copycat-db/copycat-db.service index 819baa73c5..d3ec6c4858 100644 --- a/infra/copycat-db/copycat-db.service +++ b/infra/copycat-db/copycat-db.service @@ -1,5 +1,5 @@ [Unit] -Documentation=https://github.com/ente-io/copycat-db +Documentation=https://github.com/ente-io/ente/blob/main/infra/copycat-db Requires=docker.service After=docker.service From 7ddfeb93ddd4346b76cca3a4eab3b177a78cd639 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 17:32:54 +0530 Subject: [PATCH 320/391] Fix up the workflow --- .../workflows/copycat-db-release.yaml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) rename infra/copycat-db/.github/workflows/ci.yaml => .github/workflows/copycat-db-release.yaml (61%) diff --git a/infra/copycat-db/.github/workflows/ci.yaml b/.github/workflows/copycat-db-release.yaml similarity index 61% rename from infra/copycat-db/.github/workflows/ci.yaml rename to .github/workflows/copycat-db-release.yaml index aa57e206c9..5ec942879d 100644 --- a/infra/copycat-db/.github/workflows/ci.yaml +++ b/.github/workflows/copycat-db-release.yaml @@ -1,14 +1,7 @@ -name: Build and push Docker image +name: "Release (copycat-db)" on: - # Enable manual run - workflow_dispatch: - push: - branches: - - release - # Sequence of patterns matched against refs/tags - tags: - - "v*" # Push events to matching v*, i.e. v4.2.0 + workflow_dispatch: # Run manually jobs: build: @@ -20,10 +13,12 @@ jobs: - uses: mr-smithers-excellent/docker-build-push@v6 name: Build & Push with: + dockerfile: infra/copycat-db/Dockerfile + directory: infra/copycat-db image: ente/copycat-db registry: rg.fr-par.scw.cloud + enableBuildKit: true + buildArgs: GIT_COMMIT=${GITHUB_SHA} tags: ${GITHUB_SHA}, latest username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - env: - GIT_COMMIT: ${GITHUB_SHA} From ddeafe074984a55aa77d1e1d5a31cbed832724f1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 18:16:01 +0530 Subject: [PATCH 321/391] [mobile] Update the link to GitHub APK for photos --- mobile/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mobile/README.md b/mobile/README.md index 114a3ab38a..005d303b6b 100644 --- a/mobile/README.md +++ b/mobile/README.md @@ -23,7 +23,8 @@ If you're looking for Ente Auth instead, see [../auth](../auth/README.md). ### Android -The [GitHub releases](https://github.com/ente-io/photos-app/releases) contain +The [GitHub +releases](https://github.com/ente-io/ente/releases?q=tag%3Aphotos-v0) contain APKs, built straight from source. The latest build is available at [ente.io/apk](https://ente.io/apk). These builds keep themselves updated, without relying on third party stores. From 7aed64118999e90c2e4e0d2e8168aa0fb9cdb4e1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 18:22:51 +0530 Subject: [PATCH 322/391] Also update the links in the fastlane descriptions --- mobile/fastlane/metadata/android/de/full_description.txt | 2 +- mobile/fastlane/metadata/android/en-US/full_description.txt | 2 +- mobile/fastlane/metadata/android/es/full_description.txt | 2 +- mobile/fastlane/metadata/android/fr/full_description.txt | 2 +- mobile/fastlane/metadata/android/he/full_description.txt | 2 +- mobile/fastlane/metadata/android/it/full_description.txt | 2 +- mobile/fastlane/metadata/android/nl/full_description.txt | 2 +- mobile/fastlane/metadata/android/pt/full_description.txt | 2 +- mobile/fastlane/metadata/android/ru/full_description.txt | 2 +- mobile/fastlane/metadata/android/zh/full_description.txt | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mobile/fastlane/metadata/android/de/full_description.txt b/mobile/fastlane/metadata/android/de/full_description.txt index 2d953ade9f..4d963c1d7b 100644 --- a/mobile/fastlane/metadata/android/de/full_description.txt +++ b/mobile/fastlane/metadata/android/de/full_description.txt @@ -27,7 +27,7 @@ FEATURES - und noch VIELES mehr! BERECHTIGUNGEN -Diese können unter folgendem Link überprüft werden: https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md +Diese können unter folgendem Link überprüft werden: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md PREIS Wir bieten keine lebenslang kostenlosen Abonnements an, da es für uns wichtig ist, einen nachhaltigen Service anzubieten. Wir bieten jedoch bezahlbare Abonemments an, welche auch mit der Familie geteilt werden können. Mehr Informationen sind auf ente.io zu finden. diff --git a/mobile/fastlane/metadata/android/en-US/full_description.txt b/mobile/fastlane/metadata/android/en-US/full_description.txt index 53cab6c96a..9ba4fe3143 100644 --- a/mobile/fastlane/metadata/android/en-US/full_description.txt +++ b/mobile/fastlane/metadata/android/en-US/full_description.txt @@ -27,7 +27,7 @@ FEATURES - 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/photos-app/blob/f-droid/android/permissions.md +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. diff --git a/mobile/fastlane/metadata/android/es/full_description.txt b/mobile/fastlane/metadata/android/es/full_description.txt index dfba04a962..8c0667934c 100644 --- a/mobile/fastlane/metadata/android/es/full_description.txt +++ b/mobile/fastlane/metadata/android/es/full_description.txt @@ -27,7 +27,7 @@ CARACTERÍSTICAS - ¡Y mucho más! PERMISOS -ente solicita ciertos permisos para servir al propósito de un proveedor de almacenamiento de fotos, que puede ser revisado aquí: https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md +ente solicita ciertos permisos para servir al propósito de un proveedor de almacenamiento de fotos, que puede ser revisado aquí: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md PRECIOS No ofrecemos planes gratis para siempre, porque es importante para nosotros seguir siendo sostenibles y resistir a la prueba del tiempo. En su lugar, ofrecemos planes asequibles que puedes compartir libremente con tu familia. Puedes encontrar más información en ente.io. diff --git a/mobile/fastlane/metadata/android/fr/full_description.txt b/mobile/fastlane/metadata/android/fr/full_description.txt index ee93cf62bf..f94e467af1 100644 --- a/mobile/fastlane/metadata/android/fr/full_description.txt +++ b/mobile/fastlane/metadata/android/fr/full_description.txt @@ -27,7 +27,7 @@ CARACTÉRISTIQUES - et beaucoup de choses encore ! PERMISSIONS -ente sollicite diverses autorisations dans le but de fonctionner en tant que service de stockage de photos, et ces autorisations sont détaillées ici : https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md +ente sollicite diverses autorisations dans le but de fonctionner en tant que service de stockage de photos, et ces autorisations sont détaillées ici : https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md PRIX Nous ne proposons pas d'abonnement gratuits pour toujours, car il est important pour nous de rester durables et de résister à l'épreuve du temps. Au lieu de cela, nous vous proposons des abonnements abordables que vous pouvez partager librement avec votre famille. Vous pouvez trouver plus d'informations sur ente.io. diff --git a/mobile/fastlane/metadata/android/he/full_description.txt b/mobile/fastlane/metadata/android/he/full_description.txt index 0942858507..21719b7712 100644 --- a/mobile/fastlane/metadata/android/he/full_description.txt +++ b/mobile/fastlane/metadata/android/he/full_description.txt @@ -27,7 +27,7 @@ ente גם מקל על שיתוף האלבומים שלך עם קרובך, גם - ועוד הרבה יותר! הרשאות -ente מבקש הרשאות מסוימות כדי לספק שירותי אחסון תמונות, וניתן לסקור אותן כאן: https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md +ente מבקש הרשאות מסוימות כדי לספק שירותי אחסון תמונות, וניתן לסקור אותן כאן: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md מחיר אנחנו לא מציעים תוכניות בחינם לתמיד, משום שזה חשוב לנו להיות עמידים ולעמוד במבחן הזמן. במקום זאת אנחנו מציעים תוכניות במחיר סביר כדי שתוכל לשתף באופן חופשי עם המשפחה שלך. ניתן למצוא עוד מידע ב-ente.io. diff --git a/mobile/fastlane/metadata/android/it/full_description.txt b/mobile/fastlane/metadata/android/it/full_description.txt index 2437688c5f..9da92c97a3 100644 --- a/mobile/fastlane/metadata/android/it/full_description.txt +++ b/mobile/fastlane/metadata/android/it/full_description.txt @@ -27,7 +27,7 @@ CARATTERISTICHE - e molto altro ancora! PERMESSI -ente richiede alcune autorizzazioni per servire lo scopo di un provider di storage fotografico, che può essere esaminato qui: https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md +ente richiede alcune autorizzazioni per servire lo scopo di un provider di storage fotografico, che può essere esaminato qui: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md PREZZO Non offriamo piani gratuiti per sempre, perché per noi è importante rimanere sostenibili e resistere alla prova del tempo. Offriamo invece piani accessibili che si possono condividere liberamente con la propria famiglia. Puoi trovare maggiori informazioni su ente.io. diff --git a/mobile/fastlane/metadata/android/nl/full_description.txt b/mobile/fastlane/metadata/android/nl/full_description.txt index da0877f722..80c925263e 100644 --- a/mobile/fastlane/metadata/android/nl/full_description.txt +++ b/mobile/fastlane/metadata/android/nl/full_description.txt @@ -27,7 +27,7 @@ FUNCTIES - en nog veel meer! TOESTEMMINGEN -ente heeft bepaalde machtigingen nodig om uw foto's op te slaan, die hier bekeken kunnen worden: https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md +ente heeft bepaalde machtigingen nodig om uw foto's op te slaan, die hier bekeken kunnen worden: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md PRIJZEN We bieden geen oneindig gratis plannen aan, omdat het voor ons belangrijk is dat we duurzaam blijven en de tand des tijds weerstaan. In plaats daarvan bieden we betaalbare plannen aan die je vrij kunt delen met je familie. Je kunt meer informatie vinden op ente.io. diff --git a/mobile/fastlane/metadata/android/pt/full_description.txt b/mobile/fastlane/metadata/android/pt/full_description.txt index 2bd26df1ec..8e6bc4833e 100644 --- a/mobile/fastlane/metadata/android/pt/full_description.txt +++ b/mobile/fastlane/metadata/android/pt/full_description.txt @@ -27,7 +27,7 @@ RECURSOS - e MUITO MAIS! PERMISSÕES -ente solicita certas permissões para servir o propósito de um provedor de armazenamento de fotos, que pode ser revisado aqui: https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md +ente solicita certas permissões para servir o propósito de um provedor de armazenamento de fotos, que pode ser revisado aqui: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md PREÇO Não oferecemos planos gratuitos para sempre, porque é importante para nós que permaneçamos sustentáveis e resistamos à prova do tempo. Em vez disso, oferecemos planos acessíveis que você pode compartilhar livremente com sua família. Você pode encontrar mais informações em ente.io. diff --git a/mobile/fastlane/metadata/android/ru/full_description.txt b/mobile/fastlane/metadata/android/ru/full_description.txt index f374837e00..567f5a947f 100644 --- a/mobile/fastlane/metadata/android/ru/full_description.txt +++ b/mobile/fastlane/metadata/android/ru/full_description.txt @@ -27,7 +27,7 @@ ente также делает так, что делится альбомами с - и ещё МНОГОЕ другое! РАЗРЕШЕНИЯ -ente просит разрешения на использование хранилища фотографий, которые можно рассмотреть здесь: https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md +ente просит разрешения на использование хранилища фотографий, которые можно рассмотреть здесь: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md ЦЕНА Мы не предлагаем бесконечные бесплатные планы, потому что для нас важно оставаться устойчивыми и выдерживать испытание временем. Вместо этого мы предлагаем доступные по цене планы, которыми вы можете свободно делиться с вашей семьей. Дополнительную информацию можно найти на сайте ente.io. diff --git a/mobile/fastlane/metadata/android/zh/full_description.txt b/mobile/fastlane/metadata/android/zh/full_description.txt index 2410d9da0f..3660c62591 100644 --- a/mobile/fastlane/metadata/android/zh/full_description.txt +++ b/mobile/fastlane/metadata/android/zh/full_description.txt @@ -27,7 +27,7 @@ ente也使分享相册给自己的爱人、亲人变得轻而易举,即使他 - 还有更多特色待你发现! 权限 -ente需要特定权限以执行作为图像存储提供商的职责,相关内容可以在此链接查阅:https://github.com/ente-io/photos-app/blob/f-droid/android/permissions.md +ente需要特定权限以执行作为图像存储提供商的职责,相关内容可以在此链接查阅:https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md 价格 我们不会提供永久免费计划,因为我们必须保持可持续性,经受住时间的考验。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 相反,我们向您提供了价格实惠、可自由分享的订阅计划。 您可以在 ente.io 找到更多信息。 From b79f8347b6cf3e31674b4699052a714a28dd7f43 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 20:31:47 +0530 Subject: [PATCH 323/391] Import the existing DesktopDistribute notes --- desktop/docs/release.md | 92 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 desktop/docs/release.md diff --git a/desktop/docs/release.md b/desktop/docs/release.md new file mode 100644 index 0000000000..bdda428e1a --- /dev/null +++ b/desktop/docs/release.md @@ -0,0 +1,92 @@ +## Releases + +> [!NOTE] +> +> TODO(MR): This document needs to be audited and changed as we do the first +> release from this new monorepo. + +The Github Action that builds the desktop binaries is triggered by pushing a tag +matching the pattern `photos-desktop-v1.2.3`. This value should match the +version in `package.json`. + +So the process for doing a release would be. + +1. Create a new branch (can be named anything). On this branch, include your + changes. + +2. Mention the changes in `CHANGELOG.md`. + +3. Changing the `version` in `package.json` to `1.x.x`. + +4. Commit and push to remote + + ```sh + git add package.json && git commit -m 'Release v1.x.x' + git tag v1.x.x + git push && git push --tags + ``` + +This by itself will already trigger a new release. The GitHub action will create +a new draft release that can then be used as descibed below. + +To wrap up, we also need to merge back these changes into main. So for that, + +5. Open a PR for the branch that we're working on (where the above tag was + pushed from) to get it merged into main. + +6. In this PR, also increase the version number for the next release train. That + is, supposed we just released `v4.0.1`. Then we'll change the version number + in main to `v4.0.2-next.0`. Each pre-release will modify the `next.0` part. + Finally, at the time of the next release, this'll become `v4.0.2`. + +The GitHub Action runs on Windows, Linux and macOS. It produces the artifacts +defined in the `build` value in `package.json`. + +* Windows - An NSIS installer. +* Linux - An AppImage, and 3 other packages (`.rpm`, `.deb`, `.pacman`) +* macOS - A universal DMG + +Additionally, the GitHub action notarizes the macOS DMG. For this it needs +credentials provided via GitHub secrets. + +During the build the Sentry webpack plugin checks to see if SENTRY_AUTH_TOKEN is +defined. If so, it uploads the sourcemaps for the renderer process to Sentry +(For our GitHub action, the SENTRY_AUTH_TOKEN is defined as a GitHub secret). + +The sourcemaps for the main (node) process are currently not sent to Sentry +(this works fine in practice since the node process files are not minified, we +only run `tsc`). + +Once the build is done, a draft release with all these artifacts attached is +created. The build is idempotent, so if something goes wrong and we need to +re-run the GitHub action, just delete the draft release (if it got created) and +start a new run by pushing a new tag (if some code changes are required). + +If no code changes are required, say the build failed for some transient network +or sentry issue, we can even be re-run by the build by going to Github Action +age and rerun from there. This will re-trigger for the same tag. + +If everything goes well, we'll have a release on GitHub, and the corresponding +source maps for the renderer process uploaded to Sentry. There isn't anything +else to do: + +* The website automatically redirects to the latest release on GitHub when + people try to download. + +* The file formats with support auto update (Windows `exe`, the Linux AppImage + and the macOS DMG) also check the latest GitHub release automatically to + download and apply the update (the rest of the formats don't support auto + updates). + +* We're not putting the desktop app in other stores currently. It is available + as a `brew cask`, but we only had to open a PR to add the initial formula, now + their maintainers automatically bump the SHA, version number and the (derived + from the version) URL in the formula when their tools notice a new release on + our GitHub. + +We can also publish the draft releases by checking the "pre-release" option. +Such releases don't cause any of the channels (our website, or the desktop app +auto updater, or brew) to be notified, instead these are useful for giving links +to pre-release builds to customers. Generally, in the version number for these +we'll add a label to the version, e.g. the "beta.x" in `1.x.x-beta.x`. This +should be done both in `package.json`, and what we tag the commit with. From 477e3fee80b33ad671b4f338f59756888f19241d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 21:18:38 +0530 Subject: [PATCH 324/391] Define services --- infra/copycat-db/README.md | 7 ++- infra/services/README.md | 103 +++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 infra/services/README.md diff --git a/infra/copycat-db/README.md b/infra/copycat-db/README.md index 5bb556a362..4310c73d81 100644 --- a/infra/copycat-db/README.md +++ b/infra/copycat-db/README.md @@ -1,8 +1,8 @@ # Copycat DB -Copycat DB is a [service](../service.md) to take a backup of our database. It -uses the Scaleway CLI to take backups of the database, and uploads them to an -offsite bucket. +Copycat DB is a [service](../services/README.md) to take a backup of our +database. It uses the Scaleway CLI to take backups of the database, and uploads +them to an offsite bucket. This bucket has an object lock configured, so backups cannot be deleted before expiry. Conversely, the service also deletes backups older than some threshold @@ -14,7 +14,6 @@ In production the service runs as a cron job, scheduled using a systemd timer. > meant as a second layer of replication. For more details, see our [Reliability > and Replication Specification](https://ente.io/reliability). - ## Quick help View service status (it gets invoked as a timer automatically, doesn't need to diff --git a/infra/services/README.md b/infra/services/README.md new file mode 100644 index 0000000000..81a82c7b70 --- /dev/null +++ b/infra/services/README.md @@ -0,0 +1,103 @@ +# Services + +"Services" are various Docker images that we run on our instances and manage +using systemd. + +All our services (including museum itself) follow the same +pattern: + +* They're meant to run on vanilla Ubuntu instances. The only expectation they + have is for Docker to be installed. + +* They log to fixed, known, locations - `/root/var/log/foo.log` - so that these + logs can get ingested by Promtail. + +* Each service should consist of a Docker image (or a Docker compose file), and a + systemd unit file. + +* To start / stop / cron the service, we use the corresponding systemd command. + +* Each time the service runs it should pull the latest Docker image, so there is no +separate installation/upgrade step needed. We can just restart the service, and it'll +use the latest code. + +* Any credentials and/or configuration should be read by mounting the + appropriate file from `/root/service-name` into the running Docker container. + +## Systemd cheatsheet + +```sh +sudo systemctl status my-service +sudo systemctl start my-service +sudo systemctl stop my-service +sudo systemctl restart my-service +``` + +## Adding a service + +Create a systemd unit file (For examples, see the various `*.service` files in +this repository). + +If we want the service to start on boot, add an `[Install]` section to its +service file (_note_: there is one more step later): + +``` +[Install] +WantedBy=multi-user.target +``` + +Copy the service file to the instance where we want to run the service. +Services might also have some additional configuration or env files, also copy +those to the instance. + +```sh +scp services/example.service example.env : +``` + +SSH into the instance. + +```sh +ssh +``` + +Move the service `/etc/systemd/service`, and any config files to their expected +place. env and other config files that contain credentials are kept in `/root`. + +```sh +sudo mv example.service /etc/systemd/system +sudo mv example.env /root +``` + +If you want to start the service on boot (as spoken of in the `[Install]` +section above), then enable it (this only needs to be done once): + +```sh +sudo systemctl enable service +``` + +Restarts systemd so that it gets to know of the service. + +```sh +sudo systemctl daemon-reload +``` + +Now you can manage the service using standard systemd commands. + +```sh +sudo systemctl start example +``` + +To view stdout/err, use: + +```sh +sudo journalctl --follow --unit example +``` + +## Logging + +Services should log to files in `/var/logs` within the container. This should be +mounted to `/root/var/logs` on the instance (using the `-v` flag in the service +file which launches the Docker container or the Docker compose cluster). +Finally, ensure there is an entry for this log file in the +`promtail/promtail.yaml` on that instance. The logs will then get scraped by +Promtail and sent over to Grafana. From dc2474801c319062f5beab55b42a4149e8710681 Mon Sep 17 00:00:00 2001 From: Ashil <77285023+ashilkn@users.noreply.github.com> Date: Thu, 14 Mar 2024 21:23:53 +0530 Subject: [PATCH 325/391] [photos][mobile]Update home_widget git dependency URL (#1098) --- mobile/pubspec.lock | 2 +- mobile/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 5c3f8e2f24..7e4534520b 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -936,7 +936,7 @@ packages: path: "." ref: main resolved-ref: "49158ce4a517e87817dc84c6b96c00639281229a" - url: "https://github.com/prateekmedia/FlutterHomeWidget" + url: "https://github.com/ente-io/FlutterHomeWidget" source: git version: "0.4.1" html: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 3adcf3ca32..ca8efa9c1f 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -93,7 +93,7 @@ dependencies: google_nav_bar: ^5.0.5 home_widget: git: - url: https://github.com/prateekmedia/FlutterHomeWidget + url: https://github.com/ente-io/FlutterHomeWidget ref: main html_unescape: ^2.0.0 http: ^1.1.0 From dc29ab496ff526f06bf5f5fb7647ea9cb473f3ff Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 21:56:36 +0530 Subject: [PATCH 326/391] Add prometheus and promtail definitions --- infra/services/README.md | 31 ++++++------- infra/services/prometheus/README.md | 32 +++++++++++++ .../services/prometheus/node-exporter.service | 12 +++++ infra/services/prometheus/prometheus.service | 16 +++++++ infra/services/prometheus/prometheus.yml | 39 ++++++++++++++++ infra/services/promtail/README.md | 26 +++++++++++ infra/services/promtail/promtail.service | 19 ++++++++ infra/services/promtail/promtail.yaml | 45 +++++++++++++++++++ 8 files changed, 205 insertions(+), 15 deletions(-) create mode 100644 infra/services/prometheus/README.md create mode 100644 infra/services/prometheus/node-exporter.service create mode 100644 infra/services/prometheus/prometheus.service create mode 100644 infra/services/prometheus/prometheus.yml create mode 100644 infra/services/promtail/README.md create mode 100644 infra/services/promtail/promtail.service create mode 100644 infra/services/promtail/promtail.yaml diff --git a/infra/services/README.md b/infra/services/README.md index 81a82c7b70..17fb6ce873 100644 --- a/infra/services/README.md +++ b/infra/services/README.md @@ -1,25 +1,24 @@ # Services -"Services" are various Docker images that we run on our instances and manage -using systemd. +"Services" are Docker images we run on our instances and manage using systemd. All our services (including museum itself) follow the same pattern: -* They're meant to run on vanilla Ubuntu instances. The only expectation they - have is for Docker to be installed. +* They're run on vanilla Ubuntu instances. The only expectation they have is for + Docker to be installed. * They log to fixed, known, locations - `/root/var/log/foo.log` - so that these - logs can get ingested by Promtail. + logs can get ingested by Promtail if needed. * Each service should consist of a Docker image (or a Docker compose file), and a systemd unit file. -* To start / stop / cron the service, we use the corresponding systemd command. +* To start / stop / schedule the service, we use systemd. -* Each time the service runs it should pull the latest Docker image, so there is no -separate installation/upgrade step needed. We can just restart the service, and it'll -use the latest code. +* Each time the service runs it should pull the latest Docker image, so there is + no separate installation/upgrade step needed. We can just restart the service, + and it'll use the latest code. * Any credentials and/or configuration should be read by mounting the appropriate file from `/root/service-name` into the running Docker container. @@ -31,15 +30,16 @@ sudo systemctl status my-service sudo systemctl start my-service sudo systemctl stop my-service sudo systemctl restart my-service +sudo journalctl --unit my-service ``` ## Adding a service -Create a systemd unit file (For examples, see the various `*.service` files in -this repository). +Create a systemd unit file (See the various `*.service` files in this repository +for examples). If we want the service to start on boot, add an `[Install]` section to its -service file (_note_: there is one more step later): +service file (_note_: starting on boot requires one more step later): ``` [Install] @@ -98,6 +98,7 @@ sudo journalctl --follow --unit example Services should log to files in `/var/logs` within the container. This should be mounted to `/root/var/logs` on the instance (using the `-v` flag in the service file which launches the Docker container or the Docker compose cluster). -Finally, ensure there is an entry for this log file in the -`promtail/promtail.yaml` on that instance. The logs will then get scraped by -Promtail and sent over to Grafana. + +If these logs need to be sent to Grafana, then ensure that there is an entry for +this log file in the `promtail/promtail.yaml` on that instance. The logs will +then get scraped by Promtail and sent over to Grafana. diff --git a/infra/services/prometheus/README.md b/infra/services/prometheus/README.md new file mode 100644 index 0000000000..90dc0cca3a --- /dev/null +++ b/infra/services/prometheus/README.md @@ -0,0 +1,32 @@ +# Prometheus + +Install `prometheus.service` on an instance if it is running something that +exports custom Prometheus metrics. In particular, museum does. + +Also install `node-exporter.service` (after installing +[node-exporter](https://prometheus.io/docs/guides/node-exporter/) itself) if it +is a production instance whose metrics (CPU, disk, RAM etc) we want to monitor. + +## Installing + +Prometheus doesn't currently support environment variables in config file, so +remember to change the hardcoded `XX-HOSTNAME` too in addition to adding the +`remote_write` configuration. + +```sh +scp -P 7426 services/prometheus/* : + +nano prometheus.yml +sudo mv prometheus.yml /root/prometheus.yml +sudo mv prometheus.service /etc/systemd/system/prometheus.service +sudo mv node-exporter.service /etc/systemd/system/node-exporter.service +``` + +Tell systemd to pick up new service definitions, enable the units (so that they +automatically start on boot going forward), and start them. + +```sh +sudo systemctl daemon-reload +sudo systemctl enable node-exporter prometheus +sudo systemctl start node-exporter prometheus +``` diff --git a/infra/services/prometheus/node-exporter.service b/infra/services/prometheus/node-exporter.service new file mode 100644 index 0000000000..b28e348aee --- /dev/null +++ b/infra/services/prometheus/node-exporter.service @@ -0,0 +1,12 @@ +[Unit] +Documentation=https://prometheus.io/docs/guides/node-exporter/ +Wants=network-online.target +After=network-online.target + +[Install] +WantedBy=multi-user.target + +[Service] +User=node_exporter +Group=node_exporter +ExecStart=/usr/local/bin/node_exporter diff --git a/infra/services/prometheus/prometheus.service b/infra/services/prometheus/prometheus.service new file mode 100644 index 0000000000..a8f6c48f03 --- /dev/null +++ b/infra/services/prometheus/prometheus.service @@ -0,0 +1,16 @@ +[Unit] +Documentation=https://prometheus.io/docs/prometheus/ +Requires=docker.service +After=docker.service + +[Install] +WantedBy=multi-user.target + +[Service] +ExecStartPre=docker pull prom/prometheus +ExecStartPre=-docker stop prometheus +ExecStartPre=-docker rm prometheus +ExecStart=docker run --name prometheus \ + --add-host=host.docker.internal:host-gateway \ + -v /root/prometheus.yml:/etc/prometheus/prometheus.yml:ro \ + prom/prometheus diff --git a/infra/services/prometheus/prometheus.yml b/infra/services/prometheus/prometheus.yml new file mode 100644 index 0000000000..81d1e3d84a --- /dev/null +++ b/infra/services/prometheus/prometheus.yml @@ -0,0 +1,39 @@ +# https://prometheus.io/docs/prometheus/latest/configuration/ + +global: + scrape_interval: 30s # Default is 1m + +scrape_configs: + - job_name: museum + static_configs: + - targets: ["host.docker.internal:2112"] + relabel_configs: + - source_labels: [__address__] + regex: ".*" + target_label: instance + replacement: XX-HOSTNAME + + - job_name: "prometheus" + static_configs: + - targets: ["localhost:9090"] + relabel_configs: + - source_labels: [__address__] + regex: ".*" + target_label: instance + replacement: XX-HOSTNAME + + - job_name: "node" + static_configs: + - targets: ["host.docker.internal:9100"] + relabel_configs: + - source_labels: [__address__] + regex: ".*" + target_label: instance + replacement: XX-HOSTNAME + +# Grafana Cloud +remote_write: + - url: https://g/api/prom/push + basic_auth: + username: foo + password: bar diff --git a/infra/services/promtail/README.md b/infra/services/promtail/README.md new file mode 100644 index 0000000000..1bcf448337 --- /dev/null +++ b/infra/services/promtail/README.md @@ -0,0 +1,26 @@ +# Promtail + +Install `promtail.service` on an instance if it is running something whose logs +we want in Grafana. + +## Installing + +Replace `client.url` in the config file with the Loki URL that Promtail should +connect to, and move the files to their expected place. + +```sh +scp -P 7426 services/promtail/* : + +nano promtail.yaml +sudo mv promtail.yaml /root/promtail.yaml +sudo mv promtail.service /etc/systemd/system/promtail.service +``` + +Tell systemd to pick up new service definitions, enable the unit (so that it +automatically starts on boot), and start it this time around. + +```sh +sudo systemctl daemon-reload +sudo systemctl enable promtail +sudo systemctl start promtail +``` diff --git a/infra/services/promtail/promtail.service b/infra/services/promtail/promtail.service new file mode 100644 index 0000000000..b98ec762f2 --- /dev/null +++ b/infra/services/promtail/promtail.service @@ -0,0 +1,19 @@ +[Unit] +Documentation=https://grafana.com/docs/loki/latest/clients/promtail/ +Requires=docker.service +After=docker.service + +[Install] +WantedBy=multi-user.target + +[Service] +ExecStartPre=docker pull grafana/promtail +ExecStartPre=-docker stop promtail +ExecStartPre=-docker rm promtail +ExecStart=docker run --name promtail \ + --hostname "%H" \ + -v /root/promtail.yaml:/config.yaml:ro \ + -v /var/log:/var/log \ + -v /root/var/logs:/var/logs:ro \ + -v /var/lib/docker/containers:/var/lib/docker/containers:ro \ + grafana/promtail -config.file=/config.yaml -config.expand-env=true diff --git a/infra/services/promtail/promtail.yaml b/infra/services/promtail/promtail.yaml new file mode 100644 index 0000000000..99a2578ff6 --- /dev/null +++ b/infra/services/promtail/promtail.yaml @@ -0,0 +1,45 @@ +# https://grafana.com/docs/loki/latest/clients/promtail/configuration/ + +# We don't want Promtail's HTTP / GRPC server. +server: + disable: true + +# Loki URL +# For Grafana Cloud, it can be found in the integrations section. +clients: + - url: http://loki:3100/loki/api/v1/push + +# Manually add entries for all our services. This is a bit cumbersome, but +# - Retains flexibility in file names. +# - Makes adding job labels easy. +# - Does not get in the way of logrotation. +# +# In addition, also scrape logs from all docker containers. +scrape_configs: + - job_name: museum + static_configs: + - labels: + job: museum + host: ${HOSTNAME} + __path__: /var/logs/museum.log + + - job_name: copycat-db + static_configs: + - labels: + job: copycat-db + host: ${HOSTNAME} + __path__: /var/logs/copycat-db.log + + - job_name: phoenix + static_configs: + - labels: + job: phoenix + host: ${HOSTNAME} + __path__: /var/logs/phoenix.log + + - job_name: docker + static_configs: + - labels: + job: docker + host: ${HOSTNAME} + __path__: /var/lib/docker/containers/*/*-json.log From 12bdbcfbdc8845aadf49c54f7e78b4db7d3eff90 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 14 Mar 2024 22:33:00 +0530 Subject: [PATCH 327/391] npx prettier --config ../docs/.prettierrc.json --write '**/*.md' --- infra/copycat-db/README.md | 19 ++++++++++--------- infra/services/README.md | 34 +++++++++++++++++----------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/infra/copycat-db/README.md b/infra/copycat-db/README.md index 4310c73d81..266bd4e6e3 100644 --- a/infra/copycat-db/README.md +++ b/infra/copycat-db/README.md @@ -11,8 +11,8 @@ when it creates a new one to avoid indefinite retention. In production the service runs as a cron job, scheduled using a systemd timer. > These backups are in addition to the regular snapshots that we take, and are -> meant as a second layer of replication. For more details, see our [Reliability -> and Replication Specification](https://ente.io/reliability). +> meant as a second layer of replication. For more details, see our +> [Reliability and Replication Specification](https://ente.io/reliability). ## Quick help @@ -60,7 +60,8 @@ then the Docker image falls back to using `pg_dump` (as outlined next). Not needed in production when taking a backup (since we use the Scaleway CLI to take backups in production). -These are used when testing a backup using `pg_dump`, and when restoring backups. +These are used when testing a backup using `pg_dump`, and when restoring +backups. ##### RCLONE_CONFIG @@ -69,9 +70,9 @@ to use to save the backups, and the credentials to to access it. Specifically, the config file contains two remotes: -* The bucket itself, where data will be stored. +- The bucket itself, where data will be stored. -* A "crypt" remote that wraps the bucket by applying client side encryption. +- A "crypt" remote that wraps the bucket by applying client side encryption. The configuration file will contain (lightly) obfuscated versions of the password, and as long as we have the configuration file we can continue using @@ -163,9 +164,9 @@ you wish to force the job to service immediately ## Updating -To update, run the [GitHub -workflow](../../.github/workflows/copycat-db-release.yaml) to build and push the -latest image to our Docker Registry, then restart the systemd service on the -instance +To update, run the +[GitHub workflow](../../.github/workflows/copycat-db-release.yaml) to build and +push the latest image to our Docker Registry, then restart the systemd service +on the instance sudo systemctl restart copycat-db diff --git a/infra/services/README.md b/infra/services/README.md index 17fb6ce873..8c3a3d5691 100644 --- a/infra/services/README.md +++ b/infra/services/README.md @@ -2,26 +2,26 @@ "Services" are Docker images we run on our instances and manage using systemd. -All our services (including museum itself) follow the same -pattern: +All our services (including museum itself) follow the same pattern: -* They're run on vanilla Ubuntu instances. The only expectation they have is for - Docker to be installed. +- They're run on vanilla Ubuntu instances. The only expectation they have is + for Docker to be installed. -* They log to fixed, known, locations - `/root/var/log/foo.log` - so that these - logs can get ingested by Promtail if needed. +- They log to fixed, known, locations - `/root/var/log/foo.log` - so that + these logs can get ingested by Promtail if needed. -* Each service should consist of a Docker image (or a Docker compose file), and a - systemd unit file. +- Each service should consist of a Docker image (or a Docker compose file), + and a systemd unit file. -* To start / stop / schedule the service, we use systemd. +- To start / stop / schedule the service, we use systemd. -* Each time the service runs it should pull the latest Docker image, so there is - no separate installation/upgrade step needed. We can just restart the service, - and it'll use the latest code. +- Each time the service runs it should pull the latest Docker image, so there + is no separate installation/upgrade step needed. We can just restart the + service, and it'll use the latest code. -* Any credentials and/or configuration should be read by mounting the - appropriate file from `/root/service-name` into the running Docker container. +- Any credentials and/or configuration should be read by mounting the + appropriate file from `/root/service-name` into the running Docker + container. ## Systemd cheatsheet @@ -46,9 +46,9 @@ service file (_note_: starting on boot requires one more step later): WantedBy=multi-user.target ``` -Copy the service file to the instance where we want to run the service. -Services might also have some additional configuration or env files, also copy -those to the instance. +Copy the service file to the instance where we want to run the service. Services +might also have some additional configuration or env files, also copy those to +the instance. ```sh scp services/example.service example.env : From 123fc8a8839b1bdaecfba346307bf1990607a06e Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Fri, 15 Mar 2024 01:37:14 +0000 Subject: [PATCH 328/391] New Crowdin translations by GitHub Action --- .../public/locales/de-DE/translation.json | 6 ++-- .../public/locales/pt-BR/translation.json | 30 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/web/apps/photos/public/locales/de-DE/translation.json b/web/apps/photos/public/locales/de-DE/translation.json index a515e7366b..9e38239594 100644 --- a/web/apps/photos/public/locales/de-DE/translation.json +++ b/web/apps/photos/public/locales/de-DE/translation.json @@ -338,8 +338,8 @@ "SORT_BY_CREATION_TIME_ASCENDING": "Ältestem", "SORT_BY_UPDATION_TIME_DESCENDING": "Zuletzt aktualisiert", "SORT_BY_NAME": "Name", - "COMPRESS_THUMBNAILS": "", - "THUMBNAIL_REPLACED": "", + "COMPRESS_THUMBNAILS": "Vorschaubilder komprimieren", + "THUMBNAIL_REPLACED": "Vorschaubilder komprimiert", "FIX_THUMBNAIL": "Komprimiere", "FIX_THUMBNAIL_LATER": "Später komprimieren", "REPLACE_THUMBNAIL_NOT_STARTED": "", @@ -352,7 +352,7 @@ "UPDATE_CREATION_TIME_NOT_STARTED": "", "UPDATE_CREATION_TIME_COMPLETED": "", "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", - "CAPTION_CHARACTER_LIMIT": "", + "CAPTION_CHARACTER_LIMIT": "Maximal 5000 Zeichen", "DATE_TIME_ORIGINAL": "", "DATE_TIME_DIGITIZED": "", "METADATA_DATE": "", diff --git a/web/apps/photos/public/locales/pt-BR/translation.json b/web/apps/photos/public/locales/pt-BR/translation.json index 4eaa398c4e..617a2618db 100644 --- a/web/apps/photos/public/locales/pt-BR/translation.json +++ b/web/apps/photos/public/locales/pt-BR/translation.json @@ -8,7 +8,7 @@ "LOGIN": "Entrar", "SIGN_UP": "Registrar", "NEW_USER": "Novo no ente", - "EXISTING_USER": "Utilizador existente", + "EXISTING_USER": "Usuário existente", "ENTER_NAME": "Insira o nome", "PUBLIC_UPLOADER_NAME_MESSAGE": "Adicione um nome para que os seus amigos saibam a quem agradecer por estas ótimas fotos!", "ENTER_EMAIL": "Insira o endereço de e-mail", @@ -227,7 +227,7 @@ "INDEXING_SCHEDULED": "Indexação está programada...", "ANALYZING_PHOTOS": "Indexando fotos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", "INDEXING_PEOPLE": "Indexando pessoas em {{indexStatus.nSyncedFiles,number}} fotos...", - "INDEXING_DONE": "", + "INDEXING_DONE": "Foram indexadas {{indexStatus.nSyncedFiles,number}} fotos", "UNIDENTIFIED_FACES": "rostos não identificados", "OBJECTS": "objetos", "TEXT": "texto", @@ -347,15 +347,15 @@ "REPLACE_THUMBNAIL_NOOP": "Você não tem nenhuma miniatura que possa ser compactadas mais", "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Não foi possível compactar algumas das suas miniaturas, por favor tente novamente", "FIX_CREATION_TIME": "Corrigir hora", - "FIX_CREATION_TIME_IN_PROGRESS": "", - "CREATION_TIME_UPDATED": "", + "FIX_CREATION_TIME_IN_PROGRESS": "Corrigindo horário", + "CREATION_TIME_UPDATED": "Hora do arquivo atualizado", "UPDATE_CREATION_TIME_NOT_STARTED": "Selecione a carteira que você deseja usar", "UPDATE_CREATION_TIME_COMPLETED": "Todos os arquivos atualizados com sucesso", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "A atualização do horário falhou para alguns arquivos, por favor, tente novamente", "CAPTION_CHARACTER_LIMIT": "5000 caracteres no máximo", - "DATE_TIME_ORIGINAL": "", - "DATE_TIME_DIGITIZED": "", - "METADATA_DATE": "", + "DATE_TIME_ORIGINAL": "Data e Hora Original", + "DATE_TIME_DIGITIZED": "Data e Hora Digitalizada", + "METADATA_DATE": "Data de Metadados", "CUSTOM_TIME": "Tempo personalizado", "REOPEN_PLAN_SELECTOR_MODAL": "Reabrir planos", "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Falha ao abrir planos", @@ -408,7 +408,7 @@ "SHARED_USING": "Compartilhar usando ", "ENTE_IO": "ente.io", "SHARING_REFERRAL_CODE": "Use o código {{referralCode}} para obter 10 GB de graça", - "LIVE": "", + "LIVE": "AO VIVO", "DISABLE_PASSWORD": "Desativar bloqueio por senha", "DISABLE_PASSWORD_MESSAGE": "Tem certeza que deseja desativar o bloqueio por senha?", "PASSWORD_LOCK": "Bloqueio de senha", @@ -506,8 +506,8 @@ "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente irá parar de processar geometria facial.

Você pode reativar o reconhecimento facial novamente, se desejar, então esta operação está segura.

", "ADVANCED": "Avançado", "FACE_SEARCH_CONFIRMATION": "Eu entendo, e desejo permitir que o ente processe a geometria do rosto", - "LABS": "", - "YOURS": "", + "LABS": "Laboratórios", + "YOURS": "seu", "PASSPHRASE_STRENGTH_WEAK": "Força da senha: fraca", "PASSPHRASE_STRENGTH_MODERATE": "Força da senha: moderada", "PASSPHRASE_STRENGTH_STRONG": "Força da senha: forte", @@ -570,7 +570,7 @@ "FEEDBACK_REQUIRED": "Por favor, ajude-nos com esta informação", "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "O que o outro serviço faz melhor?", "RECOVER_TWO_FACTOR": "Recuperar dois fatores", - "at": "", + "at": "em", "AUTH_NEXT": "próximo", "AUTH_DOWNLOAD_MOBILE_APP": "Baixe nosso aplicativo móvel para gerenciar seus segredos", "HIDDEN": "Escondido", @@ -604,7 +604,7 @@ "BLUR": "Desfoque", "INVERT_COLORS": "Inverter Cores", "ASPECT_RATIO": "Proporção da imagem", - "SQUARE": "", + "SQUARE": "Quadrado", "ROTATE_LEFT": "Girar para a Esquerda", "ROTATE_RIGHT": "Girar para a Direita", "FLIP_VERTICALLY": "Inverter verticalmente", @@ -634,8 +634,8 @@ "VISIT_CAST_ENTE_IO": "Acesse cast.ente.io no dispositivo que você deseja parear.", "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair falhou. Por favor, tente novamente.", "CACHE_DIRECTORY": "Pasta de Cache", - "PASSKEYS": "", - "FREEHAND": "", + "PASSKEYS": "Chaves de acesso", + "FREEHAND": "Mão livre", "APPLY_CROP": "Aplicar Recorte", "PHOTO_EDIT_REQUIRED_TO_SAVE": "Pelo menos uma transformação ou ajuste de cor deve ser feito antes de salvar." } From 2f86fbdd95c1bdb73ded39d8d80518eb96ce6b1b Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Fri, 15 Mar 2024 02:03:25 +0000 Subject: [PATCH 329/391] New Crowdin translations by GitHub Action --- auth/lib/l10n/arb/app_pt.arb | 2 ++ auth/lib/l10n/arb/app_zh.arb | 2 ++ 2 files changed, 4 insertions(+) diff --git a/auth/lib/l10n/arb/app_pt.arb b/auth/lib/l10n/arb/app_pt.arb index aa6a2a837e..bc43e84220 100644 --- a/auth/lib/l10n/arb/app_pt.arb +++ b/auth/lib/l10n/arb/app_pt.arb @@ -145,6 +145,7 @@ "lostDeviceTitle": "Perdeu seu dispositivo?", "twoFactorAuthTitle": "Autenticação de dois fatores", "passkeyAuthTitle": "Autenticação via Chave de acesso", + "verifyPasskey": "Verificar chave de acesso", "recoverAccount": "Recuperar conta", "enterRecoveryKeyHint": "Digite sua chave de recuperação", "recover": "Recuperar", @@ -407,6 +408,7 @@ "hearUsWhereTitle": "Como você ouviu sobre o Ente? (opcional)", "hearUsExplanation": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!", "waitingForBrowserRequest": "Aguardando solicitação do navegador...", + "waitingForVerification": "Esperando por verificação...", "passkey": "Chave de acesso", "developerSettingsWarning": "Tem certeza de que deseja modificar as configurações de Desenvolvedor?", "developerSettings": "Configurações de desenvolvedor", diff --git a/auth/lib/l10n/arb/app_zh.arb b/auth/lib/l10n/arb/app_zh.arb index e07e7dcfa0..5328a14b9c 100644 --- a/auth/lib/l10n/arb/app_zh.arb +++ b/auth/lib/l10n/arb/app_zh.arb @@ -145,6 +145,7 @@ "lostDeviceTitle": "丢失了设备吗?", "twoFactorAuthTitle": "双因素认证", "passkeyAuthTitle": "通行密钥认证", + "verifyPasskey": "验证通行密钥", "recoverAccount": "恢复账户", "enterRecoveryKeyHint": "输入您的恢复密钥", "recover": "恢复", @@ -407,6 +408,7 @@ "hearUsWhereTitle": "您是如何知道Ente的? (可选的)", "hearUsExplanation": "我们不跟踪应用程序安装情况。如果您告诉我们您是在哪里找到我们的,将会有所帮助!", "waitingForBrowserRequest": "正在等待浏览器请求...", + "waitingForVerification": "等待验证...", "passkey": "通行密钥", "developerSettingsWarning": "您确定要修改开发者设置吗?", "developerSettings": "开发者设置", From 0b6d44eb99579de3f7cd0814da9d3e2d38a9a076 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 15 Mar 2024 11:21:21 +0530 Subject: [PATCH 330/391] feat(share-to-multi-contacts-at-once): make list of suggested users a state variable --- mobile/lib/ui/sharing/add_partipant_page.dart | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index b9e41467ed..27c678503d 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -37,6 +37,7 @@ class _AddParticipantPage extends State { bool _emailIsValid = false; bool isKeypadOpen = false; late CollectionActions collectionActions; + late List _suggestedUsers; // Focus nodes are necessary final textFieldFocusNode = FocusNode(); @@ -46,6 +47,7 @@ class _AddParticipantPage extends State { void initState() { super.initState(); collectionActions = CollectionActions(CollectionsService.instance); + _suggestedUsers = _getSuggestedUser(); } @override @@ -60,8 +62,7 @@ class _AddParticipantPage extends State { isKeypadOpen = MediaQuery.viewInsetsOf(context).bottom > 100; final enteTextTheme = getEnteTextTheme(context); final enteColorScheme = getEnteColorScheme(context); - final List suggestedUsers = _getSuggestedUser(); - isEmailListEmpty = suggestedUsers.isEmpty; + isEmailListEmpty = _suggestedUsers.isEmpty; return Scaffold( resizeToAvoidBottomInset: isKeypadOpen, appBar: AppBar( @@ -105,7 +106,7 @@ class _AddParticipantPage extends State { child: ListView.builder( physics: const BouncingScrollPhysics(), itemBuilder: (context, index) { - if (index >= suggestedUsers.length) { + if (index >= _suggestedUsers.length) { return Padding( padding: const EdgeInsets.symmetric( vertical: 8.0, @@ -117,7 +118,7 @@ class _AddParticipantPage extends State { ), ); } - final currentUser = suggestedUsers[index]; + final currentUser = _suggestedUsers[index]; return Column( children: [ MenuItemWidget( @@ -152,9 +153,9 @@ class _AddParticipantPage extends State { }, isTopBorderRadiusRemoved: index > 0, isBottomBorderRadiusRemoved: - index < (suggestedUsers.length - 1), + index < (_suggestedUsers.length - 1), ), - (index == (suggestedUsers.length - 1)) + (index == (_suggestedUsers.length - 1)) ? const SizedBox.shrink() : DividerWidget( dividerType: DividerType.menu, @@ -164,7 +165,7 @@ class _AddParticipantPage extends State { ], ); }, - itemCount: suggestedUsers.length + + itemCount: _suggestedUsers.length + (widget.isAddingViewer ? 0 : 1), ), ), From 987250d4f3651bdf23261240f629536a93a109a9 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 15 Mar 2024 12:28:54 +0530 Subject: [PATCH 331/391] feat(share-to-multi-contacts-at-once): add new email to list below with selected state --- .../collection_sharing_actions.dart | 56 +++++++++ .../ui/components/buttons/button_widget.dart | 4 +- mobile/lib/ui/sharing/add_partipant_page.dart | 119 +++++++++++------- 3 files changed, 131 insertions(+), 48 deletions(-) diff --git a/mobile/lib/ui/actions/collection/collection_sharing_actions.dart b/mobile/lib/ui/actions/collection/collection_sharing_actions.dart index 1e3ac0d95a..dc28197bd8 100644 --- a/mobile/lib/ui/actions/collection/collection_sharing_actions.dart +++ b/mobile/lib/ui/actions/collection/collection_sharing_actions.dart @@ -198,6 +198,62 @@ class CollectionActions { return false; } + Future doesEmailHaveAccount( + BuildContext context, + String email, { + bool showProgress = false, + }) async { + ProgressDialog? dialog; + String? publicKey; + if (showProgress) { + dialog = createProgressDialog( + context, + S.of(context).sharing, + isDismissible: true, + ); + await dialog.show(); + } + try { + publicKey = await UserService.instance.getPublicKey(email); + } catch (e) { + await dialog?.hide(); + logger.severe("Failed to get public key", e); + await showGenericErrorDialog(context: context, error: e); + return false; + } + // getPublicKey can return null when no user is associated with given + // email id + if (publicKey == null || publicKey == '') { + // todo: neeraj replace this as per the design where a new screen + // is used for error. Do this change along with handling of network errors + await showDialogWidget( + context: context, + title: S.of(context).inviteToEnte, + icon: Icons.info_outline, + body: S.of(context).emailNoEnteAccount(email), + isDismissible: true, + buttons: [ + ButtonWidget( + buttonType: ButtonType.neutral, + icon: Icons.adaptive.share, + labelText: S.of(context).sendInvite, + isInAlert: true, + onTap: () async { + unawaited( + shareText( + S.of(context).shareTextRecommendUsingEnte, + ), + ); + }, + ), + ], + ); + return false; + } else { + return true; + } + } + // addEmailToCollection returns true if add operation was successful Future addEmailToCollection( BuildContext context, diff --git a/mobile/lib/ui/components/buttons/button_widget.dart b/mobile/lib/ui/components/buttons/button_widget.dart index 2d1b170fe1..2e4d2d1dc2 100644 --- a/mobile/lib/ui/components/buttons/button_widget.dart +++ b/mobile/lib/ui/components/buttons/button_widget.dart @@ -202,14 +202,14 @@ class _ButtonChildWidgetState extends State { @override void initState() { - _setButtonTheme(); super.initState(); + _setButtonTheme(); } @override void didUpdateWidget(covariant ButtonChildWidget oldWidget) { - _setButtonTheme(); super.didUpdateWidget(oldWidget); + _setButtonTheme(); } @override diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index 27c678503d..993005ac70 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -262,54 +262,81 @@ class _AddParticipantPage extends State { } Widget _enterEmailField() { - return TextFormField( - controller: _textController, - focusNode: textFieldFocusNode, - style: getEnteTextTheme(context).body, - autofillHints: const [AutofillHints.email], - decoration: InputDecoration( - focusedBorder: OutlineInputBorder( - borderRadius: const BorderRadius.all(Radius.circular(4.0)), - borderSide: - BorderSide(color: getEnteColorScheme(context).strokeMuted), - ), - fillColor: getEnteColorScheme(context).fillFaint, - filled: true, - hintText: S.of(context).enterEmail, - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 14, - ), - border: UnderlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(4), + return Row( + children: [ + Expanded( + child: TextFormField( + controller: _textController, + focusNode: textFieldFocusNode, + style: getEnteTextTheme(context).body, + autofillHints: const [AutofillHints.email], + decoration: InputDecoration( + focusedBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all(Radius.circular(4.0)), + borderSide: + BorderSide(color: getEnteColorScheme(context).strokeMuted), + ), + fillColor: getEnteColorScheme(context).fillFaint, + filled: true, + hintText: S.of(context).enterEmail, + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 14, + ), + border: UnderlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(4), + ), + prefixIcon: Icon( + Icons.email_outlined, + color: getEnteColorScheme(context).strokeMuted, + ), + suffixIcon: _email == '' + ? null + : IconButton( + onPressed: clearFocus, + icon: Icon( + Icons.cancel, + color: getEnteColorScheme(context).strokeMuted, + ), + ), + ), + onChanged: (value) { + if (selectedEmail != '') { + selectedEmail = ''; + } + _email = value.trim(); + _emailIsValid = EmailValidator.validate(_email); + setState(() {}); + }, + autocorrect: false, + keyboardType: TextInputType.emailAddress, + //initialValue: _email, + textInputAction: TextInputAction.next, + ), ), - prefixIcon: Icon( - Icons.email_outlined, - color: getEnteColorScheme(context).strokeMuted, + const SizedBox(width: 8), + ButtonWidget( + buttonType: ButtonType.secondary, + buttonSize: ButtonSize.small, + labelText: "Add", + isDisabled: !_emailIsValid, + onTap: () async { + if (_emailIsValid) { + final result = await collectionActions.doesEmailHaveAccount( + context, + _email, + ); + if (result && mounted) { + setState(() { + _suggestedUsers.insert(0, User(email: _email)); + _selectedEmails.add(_email); + }); + } + } + }, ), - suffixIcon: _email == '' - ? null - : IconButton( - onPressed: clearFocus, - icon: Icon( - Icons.cancel, - color: getEnteColorScheme(context).strokeMuted, - ), - ), - ), - onChanged: (value) { - if (selectedEmail != '') { - selectedEmail = ''; - } - _email = value.trim(); - _emailIsValid = EmailValidator.validate(_email); - setState(() {}); - }, - autocorrect: false, - keyboardType: TextInputType.emailAddress, - //initialValue: _email, - textInputAction: TextInputAction.next, + ], ); } From 487be4a45138af8e5ad4f84e8363ec2f11fcd518 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 15 Mar 2024 12:44:54 +0530 Subject: [PATCH 332/391] feat(share-to-multi-contacts-at-once): change state to selected state of an existing email if an already existing email in the list is added from 'add new email' --- mobile/lib/ui/sharing/add_partipant_page.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index 993005ac70..9c0500dbe5 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -329,6 +329,12 @@ class _AddParticipantPage extends State { ); if (result && mounted) { setState(() { + for (var suggestedUser in _suggestedUsers) { + if (suggestedUser.email == _email) { + _selectedEmails.add(suggestedUser.email); + return; + } + } _suggestedUsers.insert(0, User(email: _email)); _selectedEmails.add(_email); }); From a4985116b833ab4142339e4c1bc1e3aecb19f7c0 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 15 Mar 2024 12:53:32 +0530 Subject: [PATCH 333/391] feat(share-to-multi-contacts-at-once): change data structure of selected emails from List to Set to avoid duplicates --- mobile/lib/ui/sharing/add_partipant_page.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index 9c0500dbe5..4d6ff55a6c 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -30,7 +30,7 @@ class AddParticipantPage extends StatefulWidget { } class _AddParticipantPage extends State { - final _selectedEmails = []; + final _selectedEmails = {}; String selectedEmail = ''; String _email = ''; bool isEmailListEmpty = false; @@ -332,11 +332,14 @@ class _AddParticipantPage extends State { for (var suggestedUser in _suggestedUsers) { if (suggestedUser.email == _email) { _selectedEmails.add(suggestedUser.email); + clearFocus(); + return; } } _suggestedUsers.insert(0, User(email: _email)); _selectedEmails.add(_email); + clearFocus(); }); } } From bd75eba9417f535dfc89c71fb265e95bd38c49ff Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 15 Mar 2024 12:56:20 +0530 Subject: [PATCH 334/391] [docs] Mention submodules in the community external S3 guide --- docs/docs/self-hosting/guides/external-s3.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/docs/self-hosting/guides/external-s3.md b/docs/docs/self-hosting/guides/external-s3.md index 40b4017247..505ae6fe92 100644 --- a/docs/docs/self-hosting/guides/external-s3.md +++ b/docs/docs/self-hosting/guides/external-s3.md @@ -17,6 +17,14 @@ have the keys and secrets for the S3 bucket. The plan is as follows: 4. Create an account and increase storage quota 5. Fix potential CORS issue with your bucket +> [!NOTE] +> +> This is a community contributed guide, and some of these steps might be out of +> sync with the upstream documentation. If something is not working correctly, +> please also see the latest +> [READMEs](https://github.com/ente-io/ente/blob/main/server/README.md) in the +> repository and/or other guides in [self-hosting](/self-hosting/). + ## 1. Create a `compose.yaml` file After cloning the main repository with @@ -25,6 +33,7 @@ After cloning the main repository with git clone https://github.com/ente-io/ente.git # Or git clone git@github.com:ente-io/ente.git cd ente +git submodule update --init --recursive ``` Create a `compose.yaml` file at the root of the project with the following From 5841aefb7540233adc8bd93e31e037fa17bdfb91 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 15 Mar 2024 13:06:07 +0530 Subject: [PATCH 335/391] [infra] Remind about needing to also enable node-exporter --- infra/services/prometheus/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infra/services/prometheus/README.md b/infra/services/prometheus/README.md index 90dc0cca3a..79bee13d5b 100644 --- a/infra/services/prometheus/README.md +++ b/infra/services/prometheus/README.md @@ -27,6 +27,6 @@ automatically start on boot going forward), and start them. ```sh sudo systemctl daemon-reload -sudo systemctl enable node-exporter prometheus -sudo systemctl start node-exporter prometheus +sudo systemctl enable --now node-exporter +sudo systemctl enable --now prometheus ``` From 1e8f772280cba8cc171a40c747354c007471b6eb Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 15 Mar 2024 13:22:29 +0530 Subject: [PATCH 336/391] feat(share-to-multi-contacts-at-once): multiple changes in one commit due mistakes when commiting - Change 'Add viewer' buttons logic to work with the new UI. - Long press on an email to verify. - Filter suggestions list with the text entered in 'Enter email' text field. --- mobile/lib/ui/sharing/add_partipant_page.dart | 253 +++++++++--------- 1 file changed, 128 insertions(+), 125 deletions(-) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index 4d6ff55a6c..7aa7c62254 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -17,7 +17,7 @@ import 'package:photos/ui/components/menu_section_title.dart'; import 'package:photos/ui/components/models/button_type.dart'; import 'package:photos/ui/sharing/user_avator_widget.dart'; import "package:photos/ui/sharing/verify_identity_dialog.dart"; -import "package:photos/utils/dialog_util.dart"; +import "package:photos/utils/toast_util.dart"; class AddParticipantPage extends StatefulWidget { final Collection collection; @@ -59,6 +59,13 @@ class _AddParticipantPage extends State { @override Widget build(BuildContext context) { + final filterSuggestedUsers = _suggestedUsers + .where( + (element) => element.email.toLowerCase().contains( + _textController.text.trim().toLowerCase(), + ), + ) + .toList(); isKeypadOpen = MediaQuery.viewInsetsOf(context).bottom > 100; final enteTextTheme = getEnteTextTheme(context); final enteColorScheme = getEnteColorScheme(context); @@ -90,89 +97,109 @@ class _AddParticipantPage extends State { padding: const EdgeInsets.symmetric(horizontal: 16.0), child: _enterEmailField(), ), - (isEmailListEmpty && widget.isAddingViewer) - ? const Expanded(child: SizedBox.shrink()) - : Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Column( - children: [ - !isEmailListEmpty - ? MenuSectionTitle( - title: S.of(context).orPickAnExistingOne, - ) - : const SizedBox.shrink(), - Expanded( - child: ListView.builder( - physics: const BouncingScrollPhysics(), - itemBuilder: (context, index) { - if (index >= _suggestedUsers.length) { - return Padding( - padding: const EdgeInsets.symmetric( - vertical: 8.0, - ), - child: MenuSectionDescriptionWidget( - content: S - .of(context) - .collaboratorsCanAddPhotosAndVideosToTheSharedAlbum, - ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Column( + children: [ + filterSuggestedUsers.isNotEmpty + ? MenuSectionTitle( + title: S.of(context).orPickAnExistingOne, + ) + : const SizedBox.shrink(), + Expanded( + child: ListView.builder( + physics: const BouncingScrollPhysics(), + itemBuilder: (context, index) { + if (index >= filterSuggestedUsers.length) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + filterSuggestedUsers.isNotEmpty + ? const MenuSectionDescriptionWidget( + content: + "Long press an email to verify.", + ) + : const SizedBox.shrink(), + widget.isAddingViewer + ? const SizedBox.shrink() + : MenuSectionDescriptionWidget( + content: S + .of(context) + .collaboratorsCanAddPhotosAndVideosToTheSharedAlbum, + ), + ], + ), + ); + } + final currentUser = filterSuggestedUsers[index]; + return Column( + children: [ + MenuItemWidget( + captionedTextWidget: CaptionedTextWidget( + title: currentUser.email, + ), + leadingIconSize: 24.0, + leadingIconWidget: UserAvatarWidget( + currentUser, + type: AvatarType.mini, + ), + menuItemColor: + getEnteColorScheme(context).fillFaint, + pressedColor: + getEnteColorScheme(context).fillFaint, + trailingIcon: + (_selectedEmails.contains(currentUser.email)) + ? Icons.check + : null, + onTap: () async { + textFieldFocusNode.unfocus(); + if (_selectedEmails + .contains(currentUser.email)) { + _selectedEmails.remove(currentUser.email); + } else { + _selectedEmails.add(currentUser.email); + } + + setState(() => {}); + // showShortToast(context, "yet to implement"); + }, + onLongPress: () { + showDialog( + context: context, + builder: (BuildContext context) { + return VerifyIdentifyDialog( + self: false, + email: currentUser.email, + ); + }, ); - } - final currentUser = _suggestedUsers[index]; - return Column( - children: [ - MenuItemWidget( - captionedTextWidget: CaptionedTextWidget( - title: currentUser.email, - ), - leadingIconSize: 24.0, - leadingIconWidget: UserAvatarWidget( - currentUser, - type: AvatarType.mini, - ), - menuItemColor: - getEnteColorScheme(context).fillFaint, - pressedColor: + }, + isTopBorderRadiusRemoved: index > 0, + isBottomBorderRadiusRemoved: + index < (filterSuggestedUsers.length - 1), + ), + (index == (filterSuggestedUsers.length - 1)) + ? const SizedBox.shrink() + : DividerWidget( + dividerType: DividerType.menu, + bgColor: getEnteColorScheme(context).fillFaint, - trailingIcon: (_selectedEmails - .contains(currentUser.email)) - ? Icons.check - : null, - onTap: () async { - textFieldFocusNode.unfocus(); - if (_selectedEmails - .contains(currentUser.email)) { - _selectedEmails - .remove(currentUser.email); - } else { - _selectedEmails.add(currentUser.email); - } - - setState(() => {}); - // showShortToast(context, "yet to implement"); - }, - isTopBorderRadiusRemoved: index > 0, - isBottomBorderRadiusRemoved: - index < (_suggestedUsers.length - 1), ), - (index == (_suggestedUsers.length - 1)) - ? const SizedBox.shrink() - : DividerWidget( - dividerType: DividerType.menu, - bgColor: getEnteColorScheme(context) - .fillFaint, - ), - ], - ); - }, - itemCount: _suggestedUsers.length + - (widget.isAddingViewer ? 0 : 1), - ), - ), - ], + ], + ); + }, + itemCount: filterSuggestedUsers.length + 1, ), ), - ), + ], + ), + ), + ), SafeArea( child: Padding( padding: const EdgeInsets.only( @@ -191,57 +218,33 @@ class _AddParticipantPage extends State { labelText: widget.isAddingViewer ? S.of(context).addViewer : S.of(context).addCollaborator, - isDisabled: (selectedEmail == '' && !_emailIsValid), - onTap: (selectedEmail == '' && !_emailIsValid) - ? null - : () async { - final emailToAdd = - selectedEmail == '' ? _email : selectedEmail; - final result = - await collectionActions.addEmailToCollection( - context, - widget.collection, - emailToAdd, - widget.isAddingViewer - ? CollectionParticipantRole.viewer - : CollectionParticipantRole.collaborator, - ); - if (result && mounted) { - Navigator.of(context).pop(true); - } - }, - ), - const SizedBox(height: 12), - GestureDetector( + isDisabled: _selectedEmails.isEmpty, onTap: () async { - if ((selectedEmail == '' && !_emailIsValid)) { - await showErrorDialog( - context, - S.of(context).invalidEmailAddress, - S.of(context).enterValidEmail, + final results = []; + for (String email in _selectedEmails) { + results.add( + await collectionActions.addEmailToCollection( + context, + widget.collection, + email, + widget.isAddingViewer + ? CollectionParticipantRole.viewer + : CollectionParticipantRole.collaborator, + ), ); - return; } - final emailToAdd = - selectedEmail == '' ? _email : selectedEmail; - // ignore: unawaited_futures - showDialog( - context: context, - builder: (BuildContext context) { - return VerifyIdentifyDialog( - self: false, - email: emailToAdd, - ); - }, + + final noOfSuccessfullAdds = + results.where((e) => e).length; + showToast( + context, + "Added $noOfSuccessfullAdds ${widget.isAddingViewer ? "viewers" : "collaborators"}", ); + + if (!results.any((e) => e == false) && mounted) { + Navigator.of(context).pop(true); + } }, - child: Text( - S.of(context).verifyIDLabel, - textAlign: TextAlign.center, - style: enteTextTheme.smallMuted.copyWith( - decoration: TextDecoration.underline, - ), - ), ), const SizedBox(height: 12), ], From ed2e3bae0d32371f6b18e941f370fa9703b6d71c Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 15 Mar 2024 16:21:04 +0530 Subject: [PATCH 337/391] clean up --- mobile/lib/ui/sharing/add_partipant_page.dart | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index 7aa7c62254..36c82b9f2b 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -31,9 +31,7 @@ class AddParticipantPage extends StatefulWidget { class _AddParticipantPage extends State { final _selectedEmails = {}; - String selectedEmail = ''; - String _email = ''; - bool isEmailListEmpty = false; + String _newEmail = ''; bool _emailIsValid = false; bool isKeypadOpen = false; late CollectionActions collectionActions; @@ -69,7 +67,6 @@ class _AddParticipantPage extends State { isKeypadOpen = MediaQuery.viewInsetsOf(context).bottom > 100; final enteTextTheme = getEnteTextTheme(context); final enteColorScheme = getEnteColorScheme(context); - isEmailListEmpty = _suggestedUsers.isEmpty; return Scaffold( resizeToAvoidBottomInset: isKeypadOpen, appBar: AppBar( @@ -258,7 +255,7 @@ class _AddParticipantPage extends State { void clearFocus() { _textController.clear(); - _email = _textController.text; + _newEmail = _textController.text; _emailIsValid = false; textFieldFocusNode.unfocus(); setState(() => {}); @@ -294,7 +291,7 @@ class _AddParticipantPage extends State { Icons.email_outlined, color: getEnteColorScheme(context).strokeMuted, ), - suffixIcon: _email == '' + suffixIcon: _newEmail == '' ? null : IconButton( onPressed: clearFocus, @@ -305,11 +302,8 @@ class _AddParticipantPage extends State { ), ), onChanged: (value) { - if (selectedEmail != '') { - selectedEmail = ''; - } - _email = value.trim(); - _emailIsValid = EmailValidator.validate(_email); + _newEmail = value.trim(); + _emailIsValid = EmailValidator.validate(_newEmail); setState(() {}); }, autocorrect: false, @@ -328,20 +322,20 @@ class _AddParticipantPage extends State { if (_emailIsValid) { final result = await collectionActions.doesEmailHaveAccount( context, - _email, + _newEmail, ); if (result && mounted) { setState(() { for (var suggestedUser in _suggestedUsers) { - if (suggestedUser.email == _email) { + if (suggestedUser.email == _newEmail) { _selectedEmails.add(suggestedUser.email); clearFocus(); return; } } - _suggestedUsers.insert(0, User(email: _email)); - _selectedEmails.add(_email); + _suggestedUsers.insert(0, User(email: _newEmail)); + _selectedEmails.add(_newEmail); clearFocus(); }); } From 7941d4bcb61e036162a0bfcb90c984f5aa44e52d Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Fri, 15 Mar 2024 16:36:45 +0530 Subject: [PATCH 338/391] Skip model downloads over mobile data --- .../frameworks/ml_framework.dart | 24 +++++++------------ .../lib/services/remote_assets_service.dart | 5 ++++ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart b/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart index 35616b1b11..94f4805831 100644 --- a/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart +++ b/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart @@ -6,7 +6,6 @@ import "package:logging/logging.dart"; import "package:photos/core/errors.dart"; import "package:photos/core/event_bus.dart"; -import "package:photos/core/network/network.dart"; import "package:photos/events/event.dart"; import "package:photos/services/remote_assets_service.dart"; @@ -103,40 +102,35 @@ abstract class MLFramework { return; } _initState = InitializationState.initializingImageModel; - final imageModel = - await RemoteAssetsService.instance.getAsset(getImageModelRemotePath()); + final imageModel = await _getModel(getImageModelRemotePath()); await loadImageModel(imageModel.path); _initState = InitializationState.initializedImageModel; } Future _initTextModel() async { _initState = InitializationState.initializingTextModel; - final textModel = - await RemoteAssetsService.instance.getAsset(getTextModelRemotePath()); + final textModel = await _getModel(getTextModelRemotePath()); await loadTextModel(textModel.path); _initState = InitializationState.initializedTextModel; } - Future _downloadFile( - String url, - String savePath, { + Future _getModel( + String url, { int trialCount = 1, }) async { + if (await RemoteAssetsService.instance.hasAsset(url)) { + return RemoteAssetsService.instance.getAsset(url); + } if (!await _canDownload()) { _initState = InitializationState.waitingForNetwork; throw WiFiUnavailableError(); } - _logger.info("Downloading " + url); - final existingFile = File(savePath); - if (await existingFile.exists()) { - await existingFile.delete(); - } try { - await NetworkClient.instance.getDio().download(url, savePath); + return RemoteAssetsService.instance.getAsset(url); } catch (e, s) { _logger.severe(e, s); if (trialCount < kMaximumRetrials) { - return _downloadFile(url, savePath, trialCount: trialCount + 1); + return _getModel(url, trialCount: trialCount + 1); } else { rethrow; } diff --git a/mobile/lib/services/remote_assets_service.dart b/mobile/lib/services/remote_assets_service.dart index 0e75b983d9..251ce6c156 100644 --- a/mobile/lib/services/remote_assets_service.dart +++ b/mobile/lib/services/remote_assets_service.dart @@ -26,6 +26,11 @@ class RemoteAssetsService { } } + Future hasAsset(String remotePath) async { + final path = await _getLocalPath(remotePath); + return File(path).exists(); + } + Future _getLocalPath(String remotePath) async { return (await getApplicationSupportDirectory()).path + "/assets/" + From 14c75333f326dd614f759ccb129c6bb0fe8cd644 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Fri, 15 Mar 2024 16:49:02 +0530 Subject: [PATCH 339/391] Simplify states --- .../semantic_search/frameworks/ml_framework.dart | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart b/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart index 94f4805831..3abd57db70 100644 --- a/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart +++ b/mobile/lib/services/machine_learning/semantic_search/frameworks/ml_framework.dart @@ -16,9 +16,9 @@ abstract class MLFramework { static final _logger = Logger("MLFramework"); final bool shouldDownloadOverMobileData; + final _initializationCompleter = Completer(); InitializationState _state = InitializationState.notInitialized; - final _initializationCompleter = Completer(); MLFramework(this.shouldDownloadOverMobileData) { Connectivity() @@ -64,6 +64,7 @@ abstract class MLFramework { /// instead of a CDN. Future init() async { try { + _initState = InitializationState.initializing; await Future.wait([_initImageModel(), _initTextModel()]); } catch (e, s) { _logger.warning(e, s); @@ -101,17 +102,13 @@ abstract class MLFramework { if (!kImageEncoderEnabled) { return; } - _initState = InitializationState.initializingImageModel; final imageModel = await _getModel(getImageModelRemotePath()); await loadImageModel(imageModel.path); - _initState = InitializationState.initializedImageModel; } Future _initTextModel() async { - _initState = InitializationState.initializingTextModel; final textModel = await _getModel(getTextModelRemotePath()); await loadTextModel(textModel.path); - _initState = InitializationState.initializedTextModel; } Future _getModel( @@ -153,9 +150,6 @@ class MLFrameworkInitializationUpdateEvent extends Event { enum InitializationState { notInitialized, waitingForNetwork, - initializingImageModel, - initializedImageModel, - initializingTextModel, - initializedTextModel, + initializing, initialized, } From 87d39ae2dd2a3489769c3a4433e1cfc5437dddf8 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 15 Mar 2024 17:09:40 +0530 Subject: [PATCH 340/391] Disable the example.org domains in the default self-hosted configuration People won't be able to get emails, but they can still create accounts on that domain in the default setup. So just comment it out as a saner default. --- server/configurations/local.yaml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/server/configurations/local.yaml b/server/configurations/local.yaml index 47d6f0d372..2c4bd8f3ce 100644 --- a/server/configurations/local.yaml +++ b/server/configurations/local.yaml @@ -174,7 +174,7 @@ stripe: webauthn: rpid: "example.com" rporigins: - - "https://example.com:3005" + - "https://example.com:3005" # Roadmap SSO (optional) # @@ -220,13 +220,17 @@ internal: # If provided, this external healthcheck url is periodically pinged. health-check-url: # Hardcoded verification codes, useful for logging in when developing. - hardcoded-ott: - emails: - - "example@example.org,123456" - # When running in a local environment, hardcode the verification code to - # 123456 for email addresses ending with @example.org - local-domain-suffix: "@example.org" - local-domain-value: 123456 + # + # Uncomment this and set these to your email ID or domain so that you don't + # need to peek into the server logs for obtaining the OTP when trying to log + # into an instance you're developing on. + # hardcoded-ott: + # emails: + # - "example@example.org,123456" + # # When running in a local environment, hardcode the verification code to + # # 123456 for email addresses ending with @example.org + # local-domain-suffix: "@example.org" + # local-domain-value: 123456 # List of user IDs that can use the admin API endpoints. admins: [] From 92ae1be40a9c9c87201b73240b630a4a7c0692a2 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 15 Mar 2024 17:15:24 +0530 Subject: [PATCH 341/391] Add a new flag to support S3 path style URLs without disabling SSL The use case for this came up in Discord - someone is running a custom self hosted instance where they're using MinIO as their "production S3", but it is not local (so they don't want the clients to connect without SSL). So we need a way to get MinIO to work, which needs path style URLs, without also disabling the SSL. --- server/configurations/local.yaml | 16 ++++++++++++---- server/pkg/utils/s3config/s3config.go | 4 ++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/server/configurations/local.yaml b/server/configurations/local.yaml index 2c4bd8f3ce..4bab089b6a 100644 --- a/server/configurations/local.yaml +++ b/server/configurations/local.yaml @@ -113,10 +113,7 @@ s3: # # 1. Disable SSL. # - # 2. Use "path" style S3 URLs where the bucket is part of the URL path, e.g. - # http://localhost:3200/b2-eu-cen. By default the bucket name is part of - # the (sub)domain, e.g. http://b2-eu-cen.localhost:3200/ and cannot be - # resolved when running locally. + # 2. Use "path" style S3 URLs (see `use_path_style_urls` below). # # 3. Directly download the file during replication instead of going via the # Cloudflare worker. @@ -125,6 +122,17 @@ s3: # not support them, specifically it doesn't support GLACIER). # #are_local_buckets: true + # Uncomment this to use "path" style S3 URLs. + # + # By default the bucket name is part of the (sub)domain, e.g. + # http://b2-eu-cen.localhost:3200/. If this is true, then we use "path" + # style S3 URLs where the bucket is part of the URL path, e.g. + # http://localhost:3200/b2-eu-cen. + # + # This is useful in scenarios when sub-domain based addressing cannot be + # resolved, e.g. when running a local instance, or when using MinIO as a + # production store. + #use_path_style_urls: true # Key used for encrypting customer emails before storing them in DB # diff --git a/server/pkg/utils/s3config/s3config.go b/server/pkg/utils/s3config/s3config.go index fe83ce6ea3..9b273bd612 100644 --- a/server/pkg/utils/s3config/s3config.go +++ b/server/pkg/utils/s3config/s3config.go @@ -104,6 +104,7 @@ func (config *S3Config) initialize() { config.s3Configs = make(map[string]*aws.Config) config.s3Clients = make(map[string]s3.S3) + usePathStyleURLs := viper.GetBool("s3.use_path_style_urls") areLocalBuckets := viper.GetBool("s3.are_local_buckets") config.areLocalBuckets = areLocalBuckets @@ -116,6 +117,9 @@ func (config *S3Config) initialize() { Endpoint: aws.String(viper.GetString("s3." + dc + ".endpoint")), Region: aws.String(viper.GetString("s3." + dc + ".region")), } + if usePathStyleURLs { + s3Config.S3ForcePathStyle = aws.Bool(true) + } if areLocalBuckets { s3Config.DisableSSL = aws.Bool(true) s3Config.S3ForcePathStyle = aws.Bool(true) From 07c41c4c92c5997475c9ea68be8f71428e0fc394 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 15 Mar 2024 20:22:15 +0530 Subject: [PATCH 342/391] extract strings --- auth/flutter | 2 +- mobile/lib/generated/intl/messages_cs.dart | 11 + mobile/lib/generated/intl/messages_de.dart | 320 ++++++++++-------- mobile/lib/generated/intl/messages_en.dart | 281 +++++++-------- mobile/lib/generated/intl/messages_es.dart | 250 +++++++------- mobile/lib/generated/intl/messages_fr.dart | 273 ++++++++------- mobile/lib/generated/intl/messages_it.dart | 269 ++++++++------- mobile/lib/generated/intl/messages_ko.dart | 11 + mobile/lib/generated/intl/messages_nl.dart | 281 +++++++-------- mobile/lib/generated/intl/messages_no.dart | 11 + mobile/lib/generated/intl/messages_pl.dart | 15 +- mobile/lib/generated/intl/messages_pt.dart | 291 ++++++++-------- mobile/lib/generated/intl/messages_zh.dart | 290 ++++++++-------- mobile/lib/generated/l10n.dart | 36 ++ mobile/lib/l10n/intl_cs.arb | 5 +- mobile/lib/l10n/intl_de.arb | 5 +- mobile/lib/l10n/intl_en.arb | 5 +- mobile/lib/l10n/intl_es.arb | 5 +- mobile/lib/l10n/intl_fr.arb | 5 +- mobile/lib/l10n/intl_it.arb | 5 +- mobile/lib/l10n/intl_ko.arb | 5 +- mobile/lib/l10n/intl_nl.arb | 5 +- mobile/lib/l10n/intl_no.arb | 5 +- mobile/lib/l10n/intl_pl.arb | 5 +- mobile/lib/l10n/intl_pt.arb | 5 +- mobile/lib/l10n/intl_zh.arb | 5 +- mobile/lib/ui/sharing/add_partipant_page.dart | 13 +- 27 files changed, 1333 insertions(+), 1081 deletions(-) diff --git a/auth/flutter b/auth/flutter index 41456452f2..367f9ea16b 160000 --- a/auth/flutter +++ b/auth/flutter @@ -1 +1 @@ -Subproject commit 41456452f29d64e8deb623a3c927524bcf9f111b +Subproject commit 367f9ea16bfae1ca451b9cc27c1366870b187ae2 diff --git a/mobile/lib/generated/intl/messages_cs.dart b/mobile/lib/generated/intl/messages_cs.dart index 71aa6589dc..5035838f4d 100644 --- a/mobile/lib/generated/intl/messages_cs.dart +++ b/mobile/lib/generated/intl/messages_cs.dart @@ -20,10 +20,18 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'cs'; + static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { + "addCollaborators": m0, "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), + "addViewers": m1, "changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage( "Change location of selected items?"), "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), @@ -37,6 +45,9 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), "joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"), "locations": MessageLookupByLibrary.simpleMessage("Locations"), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "modifyYourQueryOrTrySearchingFor": MessageLookupByLibrary.simpleMessage( "Modify your query, or try searching for"), diff --git a/mobile/lib/generated/intl/messages_de.dart b/mobile/lib/generated/intl/messages_de.dart index 5127b0ca12..ca3be9e414 100644 --- a/mobile/lib/generated/intl/messages_de.dart +++ b/mobile/lib/generated/intl/messages_de.dart @@ -21,27 +21,33 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'de'; static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m2(count) => "${Intl.plural(count, one: 'Element hinzufügen', other: 'Elemente hinzufügen')}"; - static String m1(storageAmount, endDate) => + static String m3(storageAmount, endDate) => "Dein ${storageAmount} Add-on ist gültig bis ${endDate}"; - static String m2(emailOrName) => "Von ${emailOrName} hinzugefügt"; + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + + static String m4(emailOrName) => "Von ${emailOrName} hinzugefügt"; - static String m3(albumName) => "Erfolgreich zu ${albumName} hinzugefügt"; + static String m5(albumName) => "Erfolgreich zu ${albumName} hinzugefügt"; - static String m4(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Keine Teilnehmer', one: '1 Teilnehmer', other: '${count} Teilnehmer')}"; - static String m5(versionValue) => "Version: ${versionValue}"; + static String m7(versionValue) => "Version: ${versionValue}"; - static String m6(paymentProvider) => + static String m8(paymentProvider) => "Bitte kündigen Sie Ihr aktuelles Abo über ${paymentProvider} zuerst"; - static String m7(user) => + static String m9(user) => "Der Nutzer \"${user}\" wird keine weiteren Fotos zum Album hinzufügen können.\n\nJedoch kann er weiterhin vorhandene Bilder, welche durch ihn hinzugefügt worden sind, wieder entfernen"; - static String m8(isFamilyMember, storageAmountInGb) => + static String m10(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Deine Familiengruppe hat bereits ${storageAmountInGb} GB erhalten', @@ -49,166 +55,166 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Du hast bereits ${storageAmountInGb} GB erhalten!', })}"; - static String m9(albumName) => + static String m11(albumName) => "Kollaborativer Link für ${albumName} erstellt"; - static String m10(familyAdminEmail) => + static String m12(familyAdminEmail) => "Bitte kontaktiere ${familyAdminEmail} um dein Abo zu verwalten"; - static String m11(provider) => + static String m13(provider) => "Bitte kontaktieren Sie uns über support@ente.io, um Ihr ${provider} Abo zu verwalten."; - static String m12(count) => + static String m14(count) => "${Intl.plural(count, one: 'Lösche ${count} Element', other: 'Lösche ${count} Elemente')}"; - static String m13(currentlyDeleting, totalCount) => + static String m15(currentlyDeleting, totalCount) => "Lösche ${currentlyDeleting} / ${totalCount}"; - static String m14(albumName) => + static String m16(albumName) => "Der öffentliche Link zum Zugriff auf \"${albumName}\" wird entfernt."; - static String m15(supportEmail) => + static String m17(supportEmail) => "Bitte sende eine E-Mail an ${supportEmail} von deiner registrierten E-Mail-Adresse"; - static String m16(count, storageSaved) => + static String m18(count, storageSaved) => "Du hast ${Intl.plural(count, one: '${count} duplizierte Datei', other: '${count} dupliziere Dateien')} gelöscht und (${storageSaved}!) freigegeben"; - static String m17(count, formattedSize) => + static String m19(count, formattedSize) => "${count} Dateien, ${formattedSize} jede"; - static String m18(newEmail) => "E-Mail-Adresse geändert zu ${newEmail}"; + static String m20(newEmail) => "E-Mail-Adresse geändert zu ${newEmail}"; - static String m19(email) => + static String m21(email) => "${email} hat kein Ente-Konto.\n\nSenden Sie eine Einladung, um Fotos zu teilen."; - static String m20(count, formattedNumber) => + static String m22(count, formattedNumber) => "${Intl.plural(count, one: '1 Datei', other: '${formattedNumber} Dateien')} auf diesem Gerät wurde(n) sicher gespeichert"; - static String m21(count, formattedNumber) => + static String m23(count, formattedNumber) => "${Intl.plural(count, one: '1 Datei', other: '${formattedNumber} Dateien')} in diesem Album wurde(n) sicher gespeichert"; - static String m22(storageAmountInGB) => + static String m24(storageAmountInGB) => "${storageAmountInGB} GB jedes Mal, wenn sich jemand mit deinem Code für einen bezahlten Tarif anmeldet"; - static String m23(freeAmount, storageUnit) => + static String m25(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} kostenlos"; - static String m24(endDate) => "Kostenlose Demo verfügbar bis zum ${endDate}"; + static String m26(endDate) => "Kostenlose Demo verfügbar bis zum ${endDate}"; - static String m25(count) => + static String m27(count) => "Sie können immer noch ${Intl.plural(count, one: 'darauf', other: 'auf sie')} auf ente zugreifen, solange Sie ein aktives Abonnement haben"; - static String m26(sizeInMBorGB) => "${sizeInMBorGB} freigeben"; + static String m28(sizeInMBorGB) => "${sizeInMBorGB} freigeben"; - static String m27(count, formattedSize) => + static String m29(count, formattedSize) => "${Intl.plural(count, one: 'Es kann vom Gerät gelöscht werden, um ${formattedSize} freizugeben', other: 'Sie können vom Gerät gelöscht werden, um ${formattedSize} freizugeben')}"; - static String m28(currentlyProcessing, totalCount) => + static String m30(currentlyProcessing, totalCount) => "Verarbeite ${currentlyProcessing} / ${totalCount}"; - static String m29(count) => + static String m31(count) => "${Intl.plural(count, one: '${count} Objekt', other: '${count} Objekte')}"; - static String m30(expiryTime) => "Link läuft am ${expiryTime} ab"; + static String m32(expiryTime) => "Link läuft am ${expiryTime} ab"; - static String m31(count, formattedCount) => + static String m33(count, formattedCount) => "${Intl.plural(count, zero: 'keine Erinnerungsstücke', one: '${formattedCount} Erinnerung', other: '${formattedCount} Erinnerungsstücke')}"; - static String m32(count) => + static String m34(count) => "${Intl.plural(count, one: 'Element verschieben', other: 'Elemente verschieben')}"; - static String m33(albumName) => "Erfolgreich zu ${albumName} hinzugefügt"; + static String m35(albumName) => "Erfolgreich zu ${albumName} hinzugefügt"; - static String m34(passwordStrengthValue) => + static String m36(passwordStrengthValue) => "Passwortstärke: ${passwordStrengthValue}"; - static String m35(providerName) => + static String m37(providerName) => "Bitte kontaktiere den Support von ${providerName}, falls etwas abgebucht wurde"; - static String m36(reason) => + static String m38(reason) => "Leider ist deine Zahlung aus folgendem Grund fehlgeschlagen: ${reason}"; - static String m37(endDate) => + static String m39(endDate) => "Kostenlose Testversion gültig bis ${endDate}.\nSie können anschließend ein bezahltes Paket auswählen."; - static String m38(toEmail) => "Bitte sende uns eine E-Mail an ${toEmail}"; + static String m40(toEmail) => "Bitte sende uns eine E-Mail an ${toEmail}"; - static String m39(toEmail) => "Bitte sende die Protokolle an ${toEmail}"; + static String m41(toEmail) => "Bitte sende die Protokolle an ${toEmail}"; - static String m40(storeName) => "Bewerte uns auf ${storeName}"; + static String m42(storeName) => "Bewerte uns auf ${storeName}"; - static String m41(storageInGB) => + static String m43(storageInGB) => "3. Ihr beide erhaltet ${storageInGB} GB* kostenlos"; - static String m42(userEmail) => + static String m44(userEmail) => "${userEmail} wird aus diesem geteilten Album entfernt\n\nAlle von ihnen hinzugefügte Fotos werden ebenfalls aus dem Album entfernt"; - static String m43(endDate) => "Erneuert am ${endDate}"; + static String m45(endDate) => "Erneuert am ${endDate}"; - static String m44(count) => + static String m46(count) => "${Intl.plural(count, one: '${count} Ergebnis gefunden', other: '${count} Ergebnisse gefunden')}"; - static String m45(count) => "${count} ausgewählt"; + static String m47(count) => "${count} ausgewählt"; - static String m46(count, yourCount) => + static String m48(count, yourCount) => "${count} ausgewählt (${yourCount} von Ihnen)"; - static String m47(verificationID) => + static String m49(verificationID) => "Hier ist meine Verifizierungs-ID: ${verificationID} für ente.io."; - static String m48(verificationID) => + static String m50(verificationID) => "Hey, kannst du bestätigen, dass dies deine ente.io Verifizierungs-ID ist: ${verificationID}"; - static String m49(referralCode, referralStorageInGB) => + static String m51(referralCode, referralStorageInGB) => "ente Weiterempfehlungs-Code: ${referralCode} \n\nEinlösen unter Einstellungen → Allgemein → Weiterempfehlungen, um ${referralStorageInGB} GB kostenlos zu erhalten, sobald Sie einen kostenpflichtigen Tarif abgeschlossen haben\n\nhttps://ente.io"; - static String m50(numberOfPeople) => + static String m52(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Teile mit bestimmten Personen', one: 'Teilen mit 1 Person', other: 'Teilen mit ${numberOfPeople} Personen')}"; - static String m51(emailIDs) => "Geteilt mit ${emailIDs}"; + static String m53(emailIDs) => "Geteilt mit ${emailIDs}"; - static String m52(fileType) => + static String m54(fileType) => "Dieses ${fileType} wird von deinem Gerät gelöscht."; - static String m53(fileType) => + static String m55(fileType) => "Dieses ${fileType} existiert auf ente.io und deinem Gerät."; - static String m54(fileType) => + static String m56(fileType) => "Dieses ${fileType} wird auf ente.io gelöscht."; - static String m55(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m56( + static String m58( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} von ${totalAmount} ${totalStorageUnit} verwendet"; - static String m57(id) => + static String m59(id) => "Ihr ${id} ist bereits mit einem anderen \'ente\'-Konto verknüpft.\nWenn Sie Ihre ${id} mit diesem Konto verwenden möchten, kontaktieren Sie bitte unseren Support\'"; - static String m58(endDate) => "Ihr Abo endet am ${endDate}"; + static String m60(endDate) => "Ihr Abo endet am ${endDate}"; - static String m59(completed, total) => + static String m61(completed, total) => "${completed}/${total} Erinnerungsstücke gesichert"; - static String m60(storageAmountInGB) => + static String m62(storageAmountInGB) => "Diese erhalten auch ${storageAmountInGB} GB"; - static String m61(email) => "Dies ist ${email}s Verifizierungs-ID"; + static String m63(email) => "Dies ist ${email}s Verifizierungs-ID"; - static String m62(count) => + static String m64(count) => "${Intl.plural(count, zero: '', one: '1 Tag', other: '${count} Tage')}"; - static String m63(endDate) => "Gültig bis ${endDate}"; + static String m65(endDate) => "Gültig bis ${endDate}"; - static String m64(email) => "Verifiziere ${email}"; + static String m66(email) => "Verifiziere ${email}"; - static String m65(email) => + static String m67(email) => "Wir haben eine E-Mail an ${email} gesendet"; - static String m66(count) => + static String m68(count) => "${Intl.plural(count, one: 'vor einem Jahr', other: 'vor ${count} Jahren')}"; - static String m67(storageSaved) => + static String m69(storageSaved) => "Du hast ${storageSaved} erfolgreich freigegeben!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -228,16 +234,17 @@ class MessageLookup extends MessageLookupByLibrary { "Neue E-Mail-Adresse hinzufügen"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Bearbeiter hinzufügen"), + "addCollaborators": m0, "addFromDevice": MessageLookupByLibrary.simpleMessage("Vom Gerät hinzufügen"), - "addItem": m0, + "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("Ort hinzufügen"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Hinzufügen"), "addMore": MessageLookupByLibrary.simpleMessage("Mehr hinzufügen"), "addNew": MessageLookupByLibrary.simpleMessage("Hinzufügen"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Details der Add-ons"), - "addOnValidTill": m1, + "addOnValidTill": m3, "addOns": MessageLookupByLibrary.simpleMessage("Add-ons"), "addPhotos": MessageLookupByLibrary.simpleMessage("Fotos hinzufügen"), "addSelected": @@ -248,11 +255,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Zum versteckten Album hinzufügen"), "addViewer": MessageLookupByLibrary.simpleMessage("Album teilen"), + "addViewers": m1, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Füge deine Foto jetzt hinzu"), "addedAs": MessageLookupByLibrary.simpleMessage("Hinzugefügt als"), - "addedBy": m2, - "addedSuccessfullyTo": m3, + "addedBy": m4, + "addedSuccessfullyTo": m5, "addingToFavorites": MessageLookupByLibrary.simpleMessage( "Wird zu Favoriten hinzugefügt..."), "advanced": MessageLookupByLibrary.simpleMessage("Erweitert"), @@ -263,7 +271,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Nach 1 Woche"), "after1Year": MessageLookupByLibrary.simpleMessage("Nach 1 Jahr"), "albumOwner": MessageLookupByLibrary.simpleMessage("Besitzer"), - "albumParticipantsCount": m4, + "albumParticipantsCount": m6, "albumTitle": MessageLookupByLibrary.simpleMessage("Albumtitel"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album aktualisiert"), @@ -301,7 +309,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Android, iOS, Web, Desktop"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage( "Authentifizierung erforderlich"), - "appVersion": m5, + "appVersion": m7, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Anwenden"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Code nutzen"), @@ -387,12 +395,14 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Du kannst nur Dateien entfernen, die dir gehören"), "cancel": MessageLookupByLibrary.simpleMessage("Abbrechen"), - "cancelOtherSubscription": m6, + "cancelOtherSubscription": m8, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Abonnement kündigen"), - "cannotAddMorePhotosAfterBecomingViewer": m7, + "cannotAddMorePhotosAfterBecomingViewer": m9, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Konnte geteilte Dateien nicht löschen"), + "castInstruction": MessageLookupByLibrary.simpleMessage( + "Besuche cast.ente.io auf dem Gerät, das du verbinden möchtest.\n\nGib den unten angegebenen Code ein, um das Album auf deinem Fernseher abzuspielen."), "centerPoint": MessageLookupByLibrary.simpleMessage("Mittelpunkt"), "changeEmail": MessageLookupByLibrary.simpleMessage("E-Mail-Adresse ändern"), @@ -413,10 +423,13 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Freien Speicher einlösen"), "claimMore": MessageLookupByLibrary.simpleMessage("Mehr einlösen!"), "claimed": MessageLookupByLibrary.simpleMessage("Eingelöst"), - "claimedStorageSoFar": m8, + "claimedStorageSoFar": m10, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Unkategorisiert leeren"), + "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( + "Entferne alle Dateien von \"Unkategorisiert\" die in anderen Alben vorhanden sind"), "clearCaches": MessageLookupByLibrary.simpleMessage("Cache löschen"), + "clearIndexes": MessageLookupByLibrary.simpleMessage("Indexe löschen"), "click": MessageLookupByLibrary.simpleMessage("• Klick"), "clickOnTheOverflowMenu": MessageLookupByLibrary.simpleMessage( "• Klicken Sie auf das Überlaufmenü"), @@ -435,7 +448,7 @@ class MessageLookup extends MessageLookupByLibrary { "Erstelle einen Link, um anderen zu ermöglichen, Fotos in deinem geteilten Album hinzuzufügen und zu sehen - ohne dass diese ein Konto von ente.io oder die App benötigen. Ideal, um Fotos von Events zu sammeln."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Gemeinschaftlicher Link"), - "collaborativeLinkCreatedFor": m9, + "collaborativeLinkCreatedFor": m11, "collaborator": MessageLookupByLibrary.simpleMessage("Bearbeiter"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -462,10 +475,10 @@ class MessageLookup extends MessageLookupByLibrary { "Wiederherstellungsschlüssel bestätigen"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Bestätigen Sie ihren Wiederherstellungsschlüssel"), - "contactFamilyAdmin": m10, + "contactFamilyAdmin": m12, "contactSupport": MessageLookupByLibrary.simpleMessage("Support kontaktieren"), - "contactToManageSubscription": m11, + "contactToManageSubscription": m13, "contacts": MessageLookupByLibrary.simpleMessage("Kontakte"), "contents": MessageLookupByLibrary.simpleMessage("Inhalte"), "continueLabel": MessageLookupByLibrary.simpleMessage("Weiter"), @@ -543,11 +556,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Vom Gerät löschen"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Auf ente.io löschen"), - "deleteItemCount": m12, + "deleteItemCount": m14, "deleteLocation": MessageLookupByLibrary.simpleMessage("Standort löschen"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Fotos löschen"), - "deleteProgress": m13, + "deleteProgress": m15, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Es fehlt eine zentrale Funktion, die ich benötige"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -562,17 +575,20 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Geteiltes Album löschen?"), "deleteSharedAlbumDialogBody": MessageLookupByLibrary.simpleMessage( "Dieses Album wird für alle gelöscht\n\nDu wirst den Zugriff auf geteilte Fotos in diesem Album, die anderen gehören, verlieren"), - "descriptions": MessageLookupByLibrary.simpleMessage("Descriptions"), + "descriptions": MessageLookupByLibrary.simpleMessage("Beschreibungen"), "deselectAll": MessageLookupByLibrary.simpleMessage("Alle abwählen"), "designedToOutlive": MessageLookupByLibrary.simpleMessage("Entwickelt um zu bewahren"), "details": MessageLookupByLibrary.simpleMessage("Details"), "devAccountChanged": MessageLookupByLibrary.simpleMessage( "Das Entwicklerkonto, das wir verwenden, um ente im App Store zu veröffentlichen, hat sich geändert. Aus diesem Grund musst du dich erneut anmelden.\n\nWir entschuldigen uns für die Unannehmlichkeiten, aber das war unvermeidlich."), + "deviceCodeHint": MessageLookupByLibrary.simpleMessage("Code eingeben"), "deviceFilesAutoUploading": MessageLookupByLibrary.simpleMessage( "Dateien, die zu diesem Album hinzugefügt werden, werden automatisch zu ente hochgeladen."), "deviceLockExplanation": MessageLookupByLibrary.simpleMessage( "Das Sperren des Gerätes verhindern, solange \'ente\' im Vordergrund geöffnet ist und eine Sicherung läuft. \nDies wird für gewöhnlich nicht benötigt, kann aber dabei helfen große Transfers schneller durchzuführen."), + "deviceNotFound": + MessageLookupByLibrary.simpleMessage("Gerät nicht gefunden"), "didYouKnow": MessageLookupByLibrary.simpleMessage("Schon gewusst?"), "disableAutoLock": MessageLookupByLibrary.simpleMessage( "Automatische Sperre deaktivieren"), @@ -580,7 +596,7 @@ class MessageLookup extends MessageLookupByLibrary { "Zuschauer können weiterhin Screenshots oder mit anderen externen Programmen Kopien der Bilder machen."), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Bitte beachten Sie:"), - "disableLinkMessage": m14, + "disableLinkMessage": m16, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Zweiten Faktor (2FA) deaktivieren"), "disablingTwofactorAuthentication": @@ -603,9 +619,9 @@ class MessageLookup extends MessageLookupByLibrary { "Herunterladen fehlgeschlagen"), "downloading": MessageLookupByLibrary.simpleMessage("Wird heruntergeladen..."), - "dropSupportEmail": m15, - "duplicateFileCountWithStorageSaved": m16, - "duplicateItemsGroup": m17, + "dropSupportEmail": m17, + "duplicateFileCountWithStorageSaved": m18, + "duplicateItemsGroup": m19, "edit": MessageLookupByLibrary.simpleMessage("Bearbeiten"), "editLocation": MessageLookupByLibrary.simpleMessage("Standort bearbeiten"), @@ -618,8 +634,8 @@ class MessageLookup extends MessageLookupByLibrary { "Änderungen des Standorts werden nur in ente sichtbar sein"), "eligible": MessageLookupByLibrary.simpleMessage("zulässig"), "email": MessageLookupByLibrary.simpleMessage("E-Mail"), - "emailChangedTo": m18, - "emailNoEnteAccount": m19, + "emailChangedTo": m20, + "emailNoEnteAccount": m21, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("E-Mail-Verifizierung"), "emailYourLogs": MessageLookupByLibrary.simpleMessage( @@ -719,8 +735,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Dateitypen"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Dateitypen und -namen"), - "filesBackedUpFromDevice": m20, - "filesBackedUpInAlbum": m21, + "filesBackedUpFromDevice": m22, + "filesBackedUpInAlbum": m23, "filesDeleted": MessageLookupByLibrary.simpleMessage("Dateien gelöscht"), "flip": MessageLookupByLibrary.simpleMessage("Spiegeln"), @@ -730,26 +746,26 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Passwort vergessen"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage( "Kostenlos hinzugefügter Speicherplatz"), - "freeStorageOnReferralSuccess": m22, - "freeStorageSpace": m23, + "freeStorageOnReferralSuccess": m24, + "freeStorageSpace": m25, "freeStorageUsable": MessageLookupByLibrary.simpleMessage( "Freier Speicherplatz nutzbar"), "freeTrial": MessageLookupByLibrary.simpleMessage("Kostenlose Testphase"), - "freeTrialValidTill": m24, - "freeUpAccessPostDelete": m25, - "freeUpAmount": m26, + "freeTrialValidTill": m26, + "freeUpAccessPostDelete": m27, + "freeUpAmount": m28, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Gerätespeicher freiräumen"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Speicherplatz freigeben"), - "freeUpSpaceSaving": m27, + "freeUpSpaceSaving": m29, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Bis zu 1000 Erinnerungsstücke angezeigt in der Galerie"), "general": MessageLookupByLibrary.simpleMessage("Allgemein"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Generierung von Verschlüsselungscodes..."), - "genericProgress": m28, + "genericProgress": m30, "goToSettings": MessageLookupByLibrary.simpleMessage("Zu den Einstellungen"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), @@ -790,6 +806,8 @@ class MessageLookup extends MessageLookupByLibrary { "Der eingegebene Schlüssel ist ungültig"), "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage( "Falscher Wiederherstellungs-Schlüssel"), + "indexedItems": + MessageLookupByLibrary.simpleMessage("Indizierte Elemente"), "insecureDevice": MessageLookupByLibrary.simpleMessage("Unsicheres Gerät"), "installManually": @@ -810,13 +828,14 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Etwas ist schiefgelaufen. Bitte versuche es später noch einmal. Sollte der Fehler weiter bestehen, kontaktiere unser Supportteam."), - "itemCount": m29, + "itemCount": m31, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Elemente zeigen die Anzahl der Tage bis zum dauerhaften Löschen an"), "itemsWillBeRemovedFromAlbum": MessageLookupByLibrary.simpleMessage( "Ausgewählte Elemente werden aus diesem Album entfernt"), - "joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"), + "joinDiscord": + MessageLookupByLibrary.simpleMessage("Discord beitreten"), "keepPhotos": MessageLookupByLibrary.simpleMessage("Fotos behalten"), "kiloMeterUnit": MessageLookupByLibrary.simpleMessage("km"), "kindlyHelpUsWithThisInformation": @@ -837,7 +856,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("Geräte Limit"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Aktiviert"), "linkExpired": MessageLookupByLibrary.simpleMessage("Abgelaufen"), - "linkExpiresOn": m30, + "linkExpiresOn": m32, "linkExpiry": MessageLookupByLibrary.simpleMessage("Ablaufdatum des Links"), "linkHasExpired": @@ -868,12 +887,14 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Lade Galerie …"), "loadingMessage": MessageLookupByLibrary.simpleMessage("Fotos werden geladen..."), + "loadingModel": + MessageLookupByLibrary.simpleMessage("Lade Modelle herunter..."), "localGallery": MessageLookupByLibrary.simpleMessage("Lokale Galerie"), "location": MessageLookupByLibrary.simpleMessage("Standort"), "locationName": MessageLookupByLibrary.simpleMessage("Standortname"), "locationTagFeatureDescription": MessageLookupByLibrary.simpleMessage( "Ein Standort-Tag gruppiert alle Fotos, die in einem Radius eines Fotos aufgenommen wurden"), - "locations": MessageLookupByLibrary.simpleMessage("Locations"), + "locations": MessageLookupByLibrary.simpleMessage("Orte"), "lockButtonLabel": MessageLookupByLibrary.simpleMessage("Sperren"), "lockScreenEnablePreSteps": MessageLookupByLibrary.simpleMessage( "Um den Sperrbildschirm zu aktivieren, legen Sie bitte den Geräte-Passcode oder die Bildschirmsperre in den Systemeinstellungen fest."), @@ -885,9 +906,17 @@ class MessageLookup extends MessageLookupByLibrary { "logout": MessageLookupByLibrary.simpleMessage("Ausloggen"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( "Dies wird über Logs gesendet, um uns zu helfen, Ihr Problem zu beheben. Bitte beachten Sie, dass Dateinamen aufgenommen werden, um Probleme mit bestimmten Dateien zu beheben."), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( "Drücken Sie lange auf ein Element, um es im Vollbildmodus anzuzeigen"), "lostDevice": MessageLookupByLibrary.simpleMessage("Gerät verloren?"), + "machineLearning": + MessageLookupByLibrary.simpleMessage("Maschinelles Lernen"), + "magicSearch": MessageLookupByLibrary.simpleMessage("Magische Suche"), + "magicSearchDescription": MessageLookupByLibrary.simpleMessage( + "Bitte beachten Sie, dass dies mehr Bandbreite nutzt und zu einem höheren Akkuverbrauch führt, bis alle Elemente indiziert sind."), "manage": MessageLookupByLibrary.simpleMessage("Verwalten"), "manageDeviceStorage": MessageLookupByLibrary.simpleMessage("Gerätespeicher verwalten"), @@ -901,7 +930,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Karten"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m31, + "memoryCount": m33, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("Mobil, Web, Desktop"), @@ -911,12 +940,12 @@ class MessageLookup extends MessageLookupByLibrary { "Ändere deine Suchanfrage oder suche nach"), "moments": MessageLookupByLibrary.simpleMessage("Momente"), "monthly": MessageLookupByLibrary.simpleMessage("Monatlich"), - "moveItem": m32, + "moveItem": m34, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Zum Album verschieben"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Zu verstecktem Album verschieben"), - "movedSuccessfullyTo": m33, + "movedSuccessfullyTo": m35, "movedToTrash": MessageLookupByLibrary.simpleMessage( "In den Papierkorb verschoben"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -981,19 +1010,25 @@ class MessageLookup extends MessageLookupByLibrary { "Bei Bedarf auch so kurz wie Sie wollen..."), "orPickAnExistingOne": MessageLookupByLibrary.simpleMessage( "Oder eine Vorherige auswählen"), + "pair": MessageLookupByLibrary.simpleMessage("Koppeln"), + "passkey": MessageLookupByLibrary.simpleMessage("Passkey"), + "passkeyAuthTitle": + MessageLookupByLibrary.simpleMessage("Passkey-Verifizierung"), "password": MessageLookupByLibrary.simpleMessage("Passwort"), "passwordChangedSuccessfully": MessageLookupByLibrary.simpleMessage( "Passwort erfolgreich geändert"), "passwordLock": MessageLookupByLibrary.simpleMessage("Passwort Sperre"), - "passwordStrength": m34, + "passwordStrength": m36, "passwordWarning": MessageLookupByLibrary.simpleMessage( "Wir speichern dieses Passwort nicht. Wenn du es vergisst, können wir deine Daten nicht entschlüsseln"), "paymentDetails": MessageLookupByLibrary.simpleMessage("Zahlungsdetails"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Zahlung fehlgeschlagen"), - "paymentFailedTalkToProvider": m35, - "paymentFailedWithReason": m36, + "paymentFailedTalkToProvider": m37, + "paymentFailedWithReason": m38, + "pendingItems": + MessageLookupByLibrary.simpleMessage("Ausstehende Elemente"), "pendingSync": MessageLookupByLibrary.simpleMessage("Synchronisation anstehend"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage( @@ -1016,7 +1051,9 @@ class MessageLookup extends MessageLookupByLibrary { "pickCenterPoint": MessageLookupByLibrary.simpleMessage("Mittelpunkt auswählen"), "pinAlbum": MessageLookupByLibrary.simpleMessage("Album anheften"), - "playStoreFreeTrialValidTill": m37, + "playOnTv": MessageLookupByLibrary.simpleMessage( + "Album auf dem Fernseher wiedergeben"), + "playStoreFreeTrialValidTill": m39, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore Abo"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1028,12 +1065,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Bitte wenden Sie sich an den Support, falls das Problem weiterhin besteht"), - "pleaseEmailUsAt": m38, + "pleaseEmailUsAt": m40, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Bitte erteile die nötigen Berechtigungen"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Bitte logge dich erneut ein"), - "pleaseSendTheLogsTo": m39, + "pleaseSendTheLogsTo": m41, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Bitte versuche es erneut"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1069,7 +1106,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Ticket erstellen"), "rateTheApp": MessageLookupByLibrary.simpleMessage("App bewerten"), "rateUs": MessageLookupByLibrary.simpleMessage("Bewerte uns"), - "rateUsOnStore": m40, + "rateUsOnStore": m42, "recover": MessageLookupByLibrary.simpleMessage("Wiederherstellen"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Konto wiederherstellen"), @@ -1102,7 +1139,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Gib diesen Code an deine Freunde"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Sie schließen ein bezahltes Abo ab"), - "referralStep3": m41, + "referralStep3": m43, "referrals": MessageLookupByLibrary.simpleMessage("Weiterempfehlungen"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Einlösungen sind derzeit pausiert"), @@ -1128,7 +1165,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Link entfernen"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Teilnehmer entfernen"), - "removeParticipantBody": m42, + "removeParticipantBody": m44, "removePublicLink": MessageLookupByLibrary.simpleMessage("Öffentlichen Link entfernen"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1142,7 +1179,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Datei umbenennen"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Abonnement erneuern"), - "renewsOn": m43, + "renewsOn": m45, "reportABug": MessageLookupByLibrary.simpleMessage("Fehler melden"), "reportBug": MessageLookupByLibrary.simpleMessage("Fehler melden"), "resendEmail": @@ -1205,7 +1242,7 @@ class MessageLookup extends MessageLookupByLibrary { "Gruppiere Fotos, die innerhalb des Radius eines bestimmten Fotos aufgenommen wurden"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Laden Sie Personen ein, damit Sie geteilte Fotos hier einsehen können"), - "searchResultCount": m44, + "searchResultCount": m46, "security": MessageLookupByLibrary.simpleMessage("Sicherheit"), "selectALocation": MessageLookupByLibrary.simpleMessage("Standort auswählen"), @@ -1232,8 +1269,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Ausgewählte Elemente werden aus allen Alben gelöscht und in den Papierkorb verschoben."), - "selectedPhotos": m45, - "selectedPhotosWithYours": m46, + "selectedPhotos": m47, + "selectedPhotosWithYours": m48, "send": MessageLookupByLibrary.simpleMessage("Absenden"), "sendEmail": MessageLookupByLibrary.simpleMessage("E-Mail senden"), "sendInvite": MessageLookupByLibrary.simpleMessage("Einladung senden"), @@ -1256,16 +1293,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Teile jetzt ein Album"), "shareLink": MessageLookupByLibrary.simpleMessage("Link teilen"), - "shareMyVerificationID": m47, + "shareMyVerificationID": m49, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Teile mit ausgewählten Personen"), - "shareTextConfirmOthersVerificationID": m48, + "shareTextConfirmOthersVerificationID": m50, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Lade ente herunter, damit wir einfach Fotos und Videos in höchster Qualität teilen können\n\nhttps://ente.io"), - "shareTextReferralCode": m49, + "shareTextReferralCode": m51, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Mit Nicht-Ente-Benutzern teilen"), - "shareWithPeopleSectionTitle": m50, + "shareWithPeopleSectionTitle": m52, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Teile dein erstes Album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1276,7 +1313,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Neue geteilte Fotos"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Erhalte Benachrichtigungen, wenn jemand ein Foto zu einem gemeinsam genutzten Album hinzufügt, dem du angehörst"), - "sharedWith": m51, + "sharedWith": m53, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Mit mir geteilt"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Mit dir geteilt"), @@ -1291,11 +1328,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Andere Geräte abmelden"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Ich stimme den Nutzungsbedingungen und der Datenschutzerklärung zu"), - "singleFileDeleteFromDevice": m52, + "singleFileDeleteFromDevice": m54, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Es wird aus allen Alben gelöscht."), - "singleFileInBothLocalAndRemote": m53, - "singleFileInRemoteOnly": m54, + "singleFileInBothLocalAndRemote": m55, + "singleFileInRemoteOnly": m56, "skip": MessageLookupByLibrary.simpleMessage("Überspringen"), "social": MessageLookupByLibrary.simpleMessage("Social Media"), "someItemsAreInBothEnteAndYourDevice": @@ -1333,16 +1370,17 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("✨ Abgeschlossen"), "startBackup": MessageLookupByLibrary.simpleMessage("Sicherung starten"), + "status": MessageLookupByLibrary.simpleMessage("Status"), "storage": MessageLookupByLibrary.simpleMessage("Speicherplatz"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Familie"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Sie"), - "storageInGB": m55, + "storageInGB": m57, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Speichergrenze überschritten"), - "storageUsageInfo": m56, + "storageUsageInfo": m58, "strongStrength": MessageLookupByLibrary.simpleMessage("Stark"), - "subAlreadyLinkedErrMessage": m57, - "subWillBeCancelledOn": m58, + "subAlreadyLinkedErrMessage": m59, + "subWillBeCancelledOn": m60, "subscribe": MessageLookupByLibrary.simpleMessage("Abonnieren"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Sieht aus, als sei dein Abonnement abgelaufen. Bitte abonniere, um das Teilen zu aktivieren."), @@ -1359,7 +1397,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Verbesserung vorschlagen"), "support": MessageLookupByLibrary.simpleMessage("Support"), - "syncProgress": m59, + "syncProgress": m61, "syncStopped": MessageLookupByLibrary.simpleMessage("Synchronisierung angehalten"), "syncing": MessageLookupByLibrary.simpleMessage("Synchronisiere …"), @@ -1388,7 +1426,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Diese Elemente werden von deinem Gerät gelöscht."), - "theyAlsoGetXGb": m60, + "theyAlsoGetXGb": m62, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Sie werden aus allen Alben gelöscht."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1404,7 +1442,7 @@ class MessageLookup extends MessageLookupByLibrary { "Diese E-Mail-Adresse wird bereits verwendet"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Dieses Bild hat keine Exif-Daten"), - "thisIsPersonVerificationId": m61, + "thisIsPersonVerificationId": m63, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Dies ist deine Verifizierungs-ID"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1421,7 +1459,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("Gesamt"), "totalSize": MessageLookupByLibrary.simpleMessage("Gesamtgröße"), "trash": MessageLookupByLibrary.simpleMessage("Papierkorb"), - "trashDaysLeft": m62, + "trashDaysLeft": m64, "tryAgain": MessageLookupByLibrary.simpleMessage("Erneut versuchen"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Aktiviere die Sicherung, um automatisch neu hinzugefügte Dateien dieses Ordners auf ente hochzuladen."), @@ -1476,7 +1514,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ausgewähltes Foto verwenden"), "usedSpace": MessageLookupByLibrary.simpleMessage("Belegter Speicherplatz"), - "validTill": m63, + "validTill": m65, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verifizierung fehlgeschlagen, bitte versuchen Sie es erneut"), @@ -1485,8 +1523,10 @@ class MessageLookup extends MessageLookupByLibrary { "verify": MessageLookupByLibrary.simpleMessage("Überprüfen"), "verifyEmail": MessageLookupByLibrary.simpleMessage("E-Mail-Adresse verifizieren"), - "verifyEmailID": m64, + "verifyEmailID": m66, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Überprüfen"), + "verifyPasskey": + MessageLookupByLibrary.simpleMessage("Passkey verifizieren"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Passwort überprüfen"), "verifying": MessageLookupByLibrary.simpleMessage("Verifiziere …"), @@ -1507,17 +1547,21 @@ class MessageLookup extends MessageLookupByLibrary { "viewer": MessageLookupByLibrary.simpleMessage("Zuschauer"), "visitWebToManage": MessageLookupByLibrary.simpleMessage( "Bitte rufen Sie \"web.ente.io\" auf um ihr Abo zu verwalten"), + "waitingForVerification": + MessageLookupByLibrary.simpleMessage("Warte auf Bestätigung..."), + "waitingForWifi": + MessageLookupByLibrary.simpleMessage("Warte auf WLAN..."), "weAreOpenSource": MessageLookupByLibrary.simpleMessage( "Unser Quellcode ist offen einsehbar!"), "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Wir unterstützen keine Bearbeitung von Fotos und Alben, die du noch nicht besitzt"), - "weHaveSendEmailTo": m65, + "weHaveSendEmailTo": m67, "weakStrength": MessageLookupByLibrary.simpleMessage("Schwach"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Willkommen zurück!"), "yearly": MessageLookupByLibrary.simpleMessage("Jährlich"), - "yearsAgo": m66, + "yearsAgo": m68, "yes": MessageLookupByLibrary.simpleMessage("Ja"), "yesCancel": MessageLookupByLibrary.simpleMessage("Ja, kündigen"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage( @@ -1547,7 +1591,7 @@ class MessageLookup extends MessageLookupByLibrary { "Du kannst nicht mit dir selbst teilen"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "Du hast keine archivierten Elemente."), - "youHaveSuccessfullyFreedUp": m67, + "youHaveSuccessfullyFreedUp": m69, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage( "Dein Benutzerkonto wurde gelöscht"), "yourMap": MessageLookupByLibrary.simpleMessage("Deine Karte"), diff --git a/mobile/lib/generated/intl/messages_en.dart b/mobile/lib/generated/intl/messages_en.dart index 0ca7d3024d..624a7cfb24 100644 --- a/mobile/lib/generated/intl/messages_en.dart +++ b/mobile/lib/generated/intl/messages_en.dart @@ -21,191 +21,197 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'en'; static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m2(count) => "${Intl.plural(count, one: 'Add item', other: 'Add items')}"; - static String m1(storageAmount, endDate) => + static String m3(storageAmount, endDate) => "Your ${storageAmount} add-on is valid till ${endDate}"; - static String m2(emailOrName) => "Added by ${emailOrName}"; + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + + static String m4(emailOrName) => "Added by ${emailOrName}"; - static String m3(albumName) => "Added successfully to ${albumName}"; + static String m5(albumName) => "Added successfully to ${albumName}"; - static String m4(count) => + static String m6(count) => "${Intl.plural(count, zero: 'No Participants', one: '1 Participant', other: '${count} Participants')}"; - static String m5(versionValue) => "Version: ${versionValue}"; + static String m7(versionValue) => "Version: ${versionValue}"; - static String m6(paymentProvider) => + static String m8(paymentProvider) => "Please cancel your existing subscription from ${paymentProvider} first"; - static String m7(user) => + static String m9(user) => "${user} will not be able to add more photos to this album\n\nThey will still be able to remove existing photos added by them"; - static String m8(isFamilyMember, storageAmountInGb) => + static String m10(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Your family has claimed ${storageAmountInGb} GB so far', 'false': 'You have claimed ${storageAmountInGb} GB so far', 'other': 'You have claimed ${storageAmountInGb} GB so far!', })}"; - static String m9(albumName) => "Collaborative link created for ${albumName}"; + static String m11(albumName) => "Collaborative link created for ${albumName}"; - static String m10(familyAdminEmail) => + static String m12(familyAdminEmail) => "Please contact ${familyAdminEmail} to manage your subscription"; - static String m11(provider) => + static String m13(provider) => "Please contact us at support@ente.io to manage your ${provider} subscription."; - static String m12(count) => + static String m14(count) => "${Intl.plural(count, one: 'Delete ${count} item', other: 'Delete ${count} items')}"; - static String m13(currentlyDeleting, totalCount) => + static String m15(currentlyDeleting, totalCount) => "Deleting ${currentlyDeleting} / ${totalCount}"; - static String m14(albumName) => + static String m16(albumName) => "This will remove the public link for accessing \"${albumName}\"."; - static String m15(supportEmail) => + static String m17(supportEmail) => "Please drop an email to ${supportEmail} from your registered email address"; - static String m16(count, storageSaved) => + static String m18(count, storageSaved) => "You have cleaned up ${Intl.plural(count, one: '${count} duplicate file', other: '${count} duplicate files')}, saving (${storageSaved}!)"; - static String m17(count, formattedSize) => + static String m19(count, formattedSize) => "${count} files, ${formattedSize} each"; - static String m18(newEmail) => "Email changed to ${newEmail}"; + static String m20(newEmail) => "Email changed to ${newEmail}"; - static String m19(email) => + static String m21(email) => "${email} does not have an ente account.\n\nSend them an invite to share photos."; - static String m20(count, formattedNumber) => + static String m22(count, formattedNumber) => "${Intl.plural(count, one: '1 file', other: '${formattedNumber} files')} on this device have been backed up safely"; - static String m21(count, formattedNumber) => + static String m23(count, formattedNumber) => "${Intl.plural(count, one: '1 file', other: '${formattedNumber} files')} in this album has been backed up safely"; - static String m22(storageAmountInGB) => + static String m24(storageAmountInGB) => "${storageAmountInGB} GB each time someone signs up for a paid plan and applies your code"; - static String m23(freeAmount, storageUnit) => + static String m25(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} free"; - static String m24(endDate) => "Free trial valid till ${endDate}"; + static String m26(endDate) => "Free trial valid till ${endDate}"; - static String m25(count) => + static String m27(count) => "You can still access ${Intl.plural(count, one: 'it', other: 'them')} on ente as long as you have an active subscription"; - static String m26(sizeInMBorGB) => "Free up ${sizeInMBorGB}"; + static String m28(sizeInMBorGB) => "Free up ${sizeInMBorGB}"; - static String m27(count, formattedSize) => + static String m29(count, formattedSize) => "${Intl.plural(count, one: 'It can be deleted from the device to free up ${formattedSize}', other: 'They can be deleted from the device to free up ${formattedSize}')}"; - static String m28(currentlyProcessing, totalCount) => + static String m30(currentlyProcessing, totalCount) => "Processing ${currentlyProcessing} / ${totalCount}"; - static String m29(count) => + static String m31(count) => "${Intl.plural(count, one: '${count} item', other: '${count} items')}"; - static String m30(expiryTime) => "Link will expire on ${expiryTime}"; + static String m32(expiryTime) => "Link will expire on ${expiryTime}"; - static String m31(count, formattedCount) => + static String m33(count, formattedCount) => "${Intl.plural(count, zero: 'no memories', one: '${formattedCount} memory', other: '${formattedCount} memories')}"; - static String m32(count) => + static String m34(count) => "${Intl.plural(count, one: 'Move item', other: 'Move items')}"; - static String m33(albumName) => "Moved successfully to ${albumName}"; + static String m35(albumName) => "Moved successfully to ${albumName}"; - static String m34(passwordStrengthValue) => + static String m36(passwordStrengthValue) => "Password strength: ${passwordStrengthValue}"; - static String m35(providerName) => + static String m37(providerName) => "Please talk to ${providerName} support if you were charged"; - static String m36(reason) => + static String m38(reason) => "Unfortunately your payment failed due to ${reason}"; - static String m37(endDate) => + static String m39(endDate) => "Free trial valid till ${endDate}.\nYou can choose a paid plan afterwards."; - static String m38(toEmail) => "Please email us at ${toEmail}"; + static String m40(toEmail) => "Please email us at ${toEmail}"; - static String m39(toEmail) => "Please send the logs to \n${toEmail}"; + static String m41(toEmail) => "Please send the logs to \n${toEmail}"; - static String m40(storeName) => "Rate us on ${storeName}"; + static String m42(storeName) => "Rate us on ${storeName}"; - static String m41(storageInGB) => + static String m43(storageInGB) => "3. Both of you get ${storageInGB} GB* free"; - static String m42(userEmail) => + static String m44(userEmail) => "${userEmail} will be removed from this shared album\n\nAny photos added by them will also be removed from the album"; - static String m43(endDate) => "Subscription renews on ${endDate}"; + static String m45(endDate) => "Subscription renews on ${endDate}"; - static String m44(count) => + static String m46(count) => "${Intl.plural(count, one: '${count} result found', other: '${count} results found')}"; - static String m45(count) => "${count} selected"; + static String m47(count) => "${count} selected"; - static String m46(count, yourCount) => + static String m48(count, yourCount) => "${count} selected (${yourCount} yours)"; - static String m47(verificationID) => + static String m49(verificationID) => "Here\'s my verification ID: ${verificationID} for ente.io."; - static String m48(verificationID) => + static String m50(verificationID) => "Hey, can you confirm that this is your ente.io verification ID: ${verificationID}"; - static String m49(referralCode, referralStorageInGB) => + static String m51(referralCode, referralStorageInGB) => "ente referral code: ${referralCode} \n\nApply it in Settings → General → Referrals to get ${referralStorageInGB} GB free after you signup for a paid plan\n\nhttps://ente.io"; - static String m50(numberOfPeople) => + static String m52(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Share with specific people', one: 'Shared with 1 person', other: 'Shared with ${numberOfPeople} people')}"; - static String m51(emailIDs) => "Shared with ${emailIDs}"; + static String m53(emailIDs) => "Shared with ${emailIDs}"; - static String m52(fileType) => + static String m54(fileType) => "This ${fileType} will be deleted from your device."; - static String m53(fileType) => + static String m55(fileType) => "This ${fileType} is in both ente and your device."; - static String m54(fileType) => "This ${fileType} will be deleted from ente."; + static String m56(fileType) => "This ${fileType} will be deleted from ente."; - static String m55(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m56( + static String m58( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} of ${totalAmount} ${totalStorageUnit} used"; - static String m57(id) => + static String m59(id) => "Your ${id} is already linked to another ente account.\nIf you would like to use your ${id} with this account, please contact our support\'\'"; - static String m58(endDate) => + static String m60(endDate) => "Your subscription will be cancelled on ${endDate}"; - static String m59(completed, total) => + static String m61(completed, total) => "${completed}/${total} memories preserved"; - static String m60(storageAmountInGB) => + static String m62(storageAmountInGB) => "They also get ${storageAmountInGB} GB"; - static String m61(email) => "This is ${email}\'s Verification ID"; + static String m63(email) => "This is ${email}\'s Verification ID"; - static String m62(count) => + static String m64(count) => "${Intl.plural(count, zero: '', one: '1 day', other: '${count} days')}"; - static String m63(endDate) => "Valid till ${endDate}"; + static String m65(endDate) => "Valid till ${endDate}"; - static String m64(email) => "Verify ${email}"; + static String m66(email) => "Verify ${email}"; - static String m65(email) => "We have sent a mail to ${email}"; + static String m67(email) => "We have sent a mail to ${email}"; - static String m66(count) => + static String m68(count) => "${Intl.plural(count, one: '${count} year ago', other: '${count} years ago')}"; - static String m67(storageSaved) => + static String m69(storageSaved) => "You have successfully freed up ${storageSaved}!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -223,16 +229,17 @@ class MessageLookup extends MessageLookupByLibrary { "addANewEmail": MessageLookupByLibrary.simpleMessage("Add a new email"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Add collaborator"), + "addCollaborators": m0, "addFromDevice": MessageLookupByLibrary.simpleMessage("Add from device"), - "addItem": m0, + "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("Add location"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Add"), "addMore": MessageLookupByLibrary.simpleMessage("Add more"), "addNew": MessageLookupByLibrary.simpleMessage("Add new"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Details of add-ons"), - "addOnValidTill": m1, + "addOnValidTill": m3, "addOns": MessageLookupByLibrary.simpleMessage("Add-ons"), "addPhotos": MessageLookupByLibrary.simpleMessage("Add photos"), "addSelected": MessageLookupByLibrary.simpleMessage("Add selected"), @@ -241,11 +248,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), "addViewer": MessageLookupByLibrary.simpleMessage("Add viewer"), + "addViewers": m1, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Add your photos now"), "addedAs": MessageLookupByLibrary.simpleMessage("Added as"), - "addedBy": m2, - "addedSuccessfullyTo": m3, + "addedBy": m4, + "addedSuccessfullyTo": m5, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Adding to favorites..."), "advanced": MessageLookupByLibrary.simpleMessage("Advanced"), @@ -256,7 +264,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("After 1 week"), "after1Year": MessageLookupByLibrary.simpleMessage("After 1 year"), "albumOwner": MessageLookupByLibrary.simpleMessage("Owner"), - "albumParticipantsCount": m4, + "albumParticipantsCount": m6, "albumTitle": MessageLookupByLibrary.simpleMessage("Album title"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album updated"), "albums": MessageLookupByLibrary.simpleMessage("Albums"), @@ -290,7 +298,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Android, iOS, Web, Desktop"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("Authentication required"), - "appVersion": m5, + "appVersion": m7, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Apply"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Apply code"), @@ -374,10 +382,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Can only remove files owned by you"), "cancel": MessageLookupByLibrary.simpleMessage("Cancel"), - "cancelOtherSubscription": m6, + "cancelOtherSubscription": m8, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Cancel subscription"), - "cannotAddMorePhotosAfterBecomingViewer": m7, + "cannotAddMorePhotosAfterBecomingViewer": m9, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage("Cannot delete shared files"), "castInstruction": MessageLookupByLibrary.simpleMessage( @@ -401,7 +409,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Claim free storage"), "claimMore": MessageLookupByLibrary.simpleMessage("Claim more!"), "claimed": MessageLookupByLibrary.simpleMessage("Claimed"), - "claimedStorageSoFar": m8, + "claimedStorageSoFar": m10, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Clean Uncategorized"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -426,7 +434,7 @@ class MessageLookup extends MessageLookupByLibrary { "Create a link to allow people to add and view photos in your shared album without needing an ente app or account. Great for collecting event photos."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Collaborative link"), - "collaborativeLinkCreatedFor": m9, + "collaborativeLinkCreatedFor": m11, "collaborator": MessageLookupByLibrary.simpleMessage("Collaborator"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -453,10 +461,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Confirm recovery key"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage("Confirm your recovery key"), - "contactFamilyAdmin": m10, + "contactFamilyAdmin": m12, "contactSupport": MessageLookupByLibrary.simpleMessage("Contact support"), - "contactToManageSubscription": m11, + "contactToManageSubscription": m13, "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "contents": MessageLookupByLibrary.simpleMessage("Contents"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continue"), @@ -531,11 +539,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Delete from device"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Delete from ente"), - "deleteItemCount": m12, + "deleteItemCount": m14, "deleteLocation": MessageLookupByLibrary.simpleMessage("Delete location"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Delete photos"), - "deleteProgress": m13, + "deleteProgress": m15, "deleteReason1": MessageLookupByLibrary.simpleMessage( "It’s missing a key feature that I need"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -572,7 +580,7 @@ class MessageLookup extends MessageLookupByLibrary { "Viewers can still take screenshots or save a copy of your photos using external tools"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Please note"), - "disableLinkMessage": m14, + "disableLinkMessage": m16, "disableTwofactor": MessageLookupByLibrary.simpleMessage("Disable two-factor"), "disablingTwofactorAuthentication": @@ -593,9 +601,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Download failed"), "downloading": MessageLookupByLibrary.simpleMessage("Downloading..."), - "dropSupportEmail": m15, - "duplicateFileCountWithStorageSaved": m16, - "duplicateItemsGroup": m17, + "dropSupportEmail": m17, + "duplicateFileCountWithStorageSaved": m18, + "duplicateItemsGroup": m19, "edit": MessageLookupByLibrary.simpleMessage("Edit"), "editLocation": MessageLookupByLibrary.simpleMessage("Edit location"), "editLocationTagTitle": @@ -606,8 +614,8 @@ class MessageLookup extends MessageLookupByLibrary { "Edits to location will only be seen within Ente"), "eligible": MessageLookupByLibrary.simpleMessage("eligible"), "email": MessageLookupByLibrary.simpleMessage("Email"), - "emailChangedTo": m18, - "emailNoEnteAccount": m19, + "emailChangedTo": m20, + "emailNoEnteAccount": m21, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Email verification"), "emailYourLogs": @@ -702,8 +710,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("File types and names"), - "filesBackedUpFromDevice": m20, - "filesBackedUpInAlbum": m21, + "filesBackedUpFromDevice": m22, + "filesBackedUpInAlbum": m23, "filesDeleted": MessageLookupByLibrary.simpleMessage("Files deleted"), "flip": MessageLookupByLibrary.simpleMessage("Flip"), "forYourMemories": @@ -712,24 +720,24 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Forgot password"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Free storage claimed"), - "freeStorageOnReferralSuccess": m22, - "freeStorageSpace": m23, + "freeStorageOnReferralSuccess": m24, + "freeStorageSpace": m25, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Free storage usable"), "freeTrial": MessageLookupByLibrary.simpleMessage("Free trial"), - "freeTrialValidTill": m24, - "freeUpAccessPostDelete": m25, - "freeUpAmount": m26, + "freeTrialValidTill": m26, + "freeUpAccessPostDelete": m27, + "freeUpAmount": m28, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Free up device space"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Free up space"), - "freeUpSpaceSaving": m27, + "freeUpSpaceSaving": m29, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Up to 1000 memories shown in gallery"), "general": MessageLookupByLibrary.simpleMessage("General"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Generating encryption keys..."), - "genericProgress": m28, + "genericProgress": m30, "goToSettings": MessageLookupByLibrary.simpleMessage("Go to settings"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), "grantFullAccessPrompt": MessageLookupByLibrary.simpleMessage( @@ -787,7 +795,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "It looks like something went wrong. Please retry after some time. If the error persists, please contact our support team."), - "itemCount": m29, + "itemCount": m31, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Items show the number of days remaining before permanent deletion"), @@ -812,7 +820,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("Device limit"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Enabled"), "linkExpired": MessageLookupByLibrary.simpleMessage("Expired"), - "linkExpiresOn": m30, + "linkExpiresOn": m32, "linkExpiry": MessageLookupByLibrary.simpleMessage("Link expiry"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("Link has expired"), @@ -861,6 +869,9 @@ class MessageLookup extends MessageLookupByLibrary { "logout": MessageLookupByLibrary.simpleMessage("Logout"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( "This will send across logs to help us debug your issue. Please note that file names will be included to help track issues with specific files."), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( "Long-press on an item to view in full-screen"), @@ -882,7 +893,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Maps"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m31, + "memoryCount": m33, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("Mobile, Web, Desktop"), @@ -892,11 +903,11 @@ class MessageLookup extends MessageLookupByLibrary { "Modify your query, or try searching for"), "moments": MessageLookupByLibrary.simpleMessage("Moments"), "monthly": MessageLookupByLibrary.simpleMessage("Monthly"), - "moveItem": m32, + "moveItem": m34, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Move to album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Move to hidden album"), - "movedSuccessfullyTo": m33, + "movedSuccessfullyTo": m35, "movedToTrash": MessageLookupByLibrary.simpleMessage("Moved to trash"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage("Moving files to album..."), @@ -965,14 +976,14 @@ class MessageLookup extends MessageLookupByLibrary { "passwordChangedSuccessfully": MessageLookupByLibrary.simpleMessage( "Password changed successfully"), "passwordLock": MessageLookupByLibrary.simpleMessage("Password lock"), - "passwordStrength": m34, + "passwordStrength": m36, "passwordWarning": MessageLookupByLibrary.simpleMessage( "We don\'t store this password, so if you forget, we cannot decrypt your data"), "paymentDetails": MessageLookupByLibrary.simpleMessage("Payment details"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Payment failed"), - "paymentFailedTalkToProvider": m35, - "paymentFailedWithReason": m36, + "paymentFailedTalkToProvider": m37, + "paymentFailedWithReason": m38, "pendingItems": MessageLookupByLibrary.simpleMessage("Pending items"), "pendingSync": MessageLookupByLibrary.simpleMessage("Pending sync"), "peopleUsingYourCode": @@ -996,7 +1007,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Pick center point"), "pinAlbum": MessageLookupByLibrary.simpleMessage("Pin album"), "playOnTv": MessageLookupByLibrary.simpleMessage("Play album on TV"), - "playStoreFreeTrialValidTill": m37, + "playStoreFreeTrialValidTill": m39, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore subscription"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1008,12 +1019,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Please contact support if the problem persists"), - "pleaseEmailUsAt": m38, + "pleaseEmailUsAt": m40, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Please grant permissions"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Please login again"), - "pleaseSendTheLogsTo": m39, + "pleaseSendTheLogsTo": m41, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Please try again"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1048,7 +1059,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Raise ticket"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Rate the app"), "rateUs": MessageLookupByLibrary.simpleMessage("Rate us"), - "rateUsOnStore": m40, + "rateUsOnStore": m42, "recover": MessageLookupByLibrary.simpleMessage("Recover"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recover account"), @@ -1079,7 +1090,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Give this code to your friends"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. They sign up for a paid plan"), - "referralStep3": m41, + "referralStep3": m43, "referrals": MessageLookupByLibrary.simpleMessage("Referrals"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Referrals are currently paused"), @@ -1103,7 +1114,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Remove link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Remove participant"), - "removeParticipantBody": m42, + "removeParticipantBody": m44, "removePublicLink": MessageLookupByLibrary.simpleMessage("Remove public link"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1117,7 +1128,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Rename file"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renew subscription"), - "renewsOn": m43, + "renewsOn": m45, "reportABug": MessageLookupByLibrary.simpleMessage("Report a bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Report bug"), "resendEmail": MessageLookupByLibrary.simpleMessage("Resend email"), @@ -1177,7 +1188,7 @@ class MessageLookup extends MessageLookupByLibrary { "Group photos that are taken within some radius of a photo"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invite people, and you\'ll see all photos shared by them here"), - "searchResultCount": m44, + "searchResultCount": m46, "security": MessageLookupByLibrary.simpleMessage("Security"), "selectALocation": MessageLookupByLibrary.simpleMessage("Select a location"), @@ -1204,8 +1215,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Selected items will be deleted from all albums and moved to trash."), - "selectedPhotos": m45, - "selectedPhotosWithYours": m46, + "selectedPhotos": m47, + "selectedPhotosWithYours": m48, "send": MessageLookupByLibrary.simpleMessage("Send"), "sendEmail": MessageLookupByLibrary.simpleMessage("Send email"), "sendInvite": MessageLookupByLibrary.simpleMessage("Send invite"), @@ -1227,16 +1238,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Share an album now"), "shareLink": MessageLookupByLibrary.simpleMessage("Share link"), - "shareMyVerificationID": m47, + "shareMyVerificationID": m49, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Share only with the people you want"), - "shareTextConfirmOthersVerificationID": m48, + "shareTextConfirmOthersVerificationID": m50, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Download ente so we can easily share original quality photos and videos\n\nhttps://ente.io"), - "shareTextReferralCode": m49, + "shareTextReferralCode": m51, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage("Share with non-ente users"), - "shareWithPeopleSectionTitle": m50, + "shareWithPeopleSectionTitle": m52, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Share your first album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1247,7 +1258,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("New shared photos"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Receive notifications when someone adds a photo to a shared album that you\'re a part of"), - "sharedWith": m51, + "sharedWith": m53, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Shared with me"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Shared with you"), @@ -1261,11 +1272,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Sign out other devices"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "I agree to the terms of service and privacy policy"), - "singleFileDeleteFromDevice": m52, + "singleFileDeleteFromDevice": m54, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "It will be deleted from all albums."), - "singleFileInBothLocalAndRemote": m53, - "singleFileInRemoteOnly": m54, + "singleFileInBothLocalAndRemote": m55, + "singleFileInRemoteOnly": m56, "skip": MessageLookupByLibrary.simpleMessage("Skip"), "social": MessageLookupByLibrary.simpleMessage("Social"), "someItemsAreInBothEnteAndYourDevice": @@ -1303,13 +1314,13 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Storage"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Family"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("You"), - "storageInGB": m55, + "storageInGB": m57, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Storage limit exceeded"), - "storageUsageInfo": m56, + "storageUsageInfo": m58, "strongStrength": MessageLookupByLibrary.simpleMessage("Strong"), - "subAlreadyLinkedErrMessage": m57, - "subWillBeCancelledOn": m58, + "subAlreadyLinkedErrMessage": m59, + "subWillBeCancelledOn": m60, "subscribe": MessageLookupByLibrary.simpleMessage("Subscribe"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Looks like your subscription has expired. Please subscribe to enable sharing."), @@ -1326,7 +1337,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Suggest features"), "support": MessageLookupByLibrary.simpleMessage("Support"), - "syncProgress": m59, + "syncProgress": m61, "syncStopped": MessageLookupByLibrary.simpleMessage("Sync stopped"), "syncing": MessageLookupByLibrary.simpleMessage("Syncing..."), "systemTheme": MessageLookupByLibrary.simpleMessage("System"), @@ -1352,7 +1363,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "These items will be deleted from your device."), - "theyAlsoGetXGb": m60, + "theyAlsoGetXGb": m62, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "They will be deleted from all albums."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1368,7 +1379,7 @@ class MessageLookup extends MessageLookupByLibrary { "This email is already in use"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage("This image has no exif data"), - "thisIsPersonVerificationId": m61, + "thisIsPersonVerificationId": m63, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "This is your Verification ID"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1384,7 +1395,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("total"), "totalSize": MessageLookupByLibrary.simpleMessage("Total size"), "trash": MessageLookupByLibrary.simpleMessage("Trash"), - "trashDaysLeft": m62, + "trashDaysLeft": m64, "tryAgain": MessageLookupByLibrary.simpleMessage("Try again"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Turn on backup to automatically upload files added to this device folder to ente."), @@ -1436,7 +1447,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Use selected photo"), "usedSpace": MessageLookupByLibrary.simpleMessage("Used space"), - "validTill": m63, + "validTill": m65, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verification failed, please try again"), @@ -1444,7 +1455,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Verification ID"), "verify": MessageLookupByLibrary.simpleMessage("Verify"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Verify email"), - "verifyEmailID": m64, + "verifyEmailID": m66, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verify"), "verifyPasskey": MessageLookupByLibrary.simpleMessage("Verify passkey"), "verifyPassword": @@ -1475,11 +1486,11 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "We don\'t support editing photos and albums that you don\'t own yet"), - "weHaveSendEmailTo": m65, + "weHaveSendEmailTo": m67, "weakStrength": MessageLookupByLibrary.simpleMessage("Weak"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Welcome back!"), "yearly": MessageLookupByLibrary.simpleMessage("Yearly"), - "yearsAgo": m66, + "yearsAgo": m68, "yes": MessageLookupByLibrary.simpleMessage("Yes"), "yesCancel": MessageLookupByLibrary.simpleMessage("Yes, cancel"), "yesConvertToViewer": @@ -1509,7 +1520,7 @@ class MessageLookup extends MessageLookupByLibrary { "You cannot share with yourself"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "You don\'t have any archived items."), - "youHaveSuccessfullyFreedUp": m67, + "youHaveSuccessfullyFreedUp": m69, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage( "Your account has been deleted"), "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), diff --git a/mobile/lib/generated/intl/messages_es.dart b/mobile/lib/generated/intl/messages_es.dart index 7b2121bb59..0c2673d464 100644 --- a/mobile/lib/generated/intl/messages_es.dart +++ b/mobile/lib/generated/intl/messages_es.dart @@ -21,24 +21,30 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'es'; static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m2(count) => "${Intl.plural(count, one: 'Agregar elemento', other: 'Agregar elementos')}}"; - static String m2(emailOrName) => "Añadido por ${emailOrName}"; + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + + static String m4(emailOrName) => "Añadido por ${emailOrName}"; - static String m3(albumName) => "Añadido exitosamente a ${albumName}"; + static String m5(albumName) => "Añadido exitosamente a ${albumName}"; - static String m4(count) => + static String m6(count) => "${Intl.plural(count, zero: 'No hay Participantes', one: '1 Participante', other: '${count} Participantes')}"; - static String m5(versionValue) => "Versión: ${versionValue}"; + static String m7(versionValue) => "Versión: ${versionValue}"; - static String m6(paymentProvider) => + static String m8(paymentProvider) => "Por favor, cancele primero su suscripción existente de ${paymentProvider}"; - static String m7(user) => + static String m9(user) => "${user} no podrá añadir más fotos a este álbum\n\nTodavía podrán eliminar las fotos ya añadidas por ellos"; - static String m8(isFamilyMember, storageAmountInGb) => + static String m10(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Su familia ha reclamado ${storageAmountInGb} GB hasta el momento', @@ -48,145 +54,146 @@ class MessageLookup extends MessageLookupByLibrary { '¡Tú has reclamado ${storageAmountInGb} GB hasta el momento!', })}"; - static String m9(albumName) => "Enlace colaborativo creado para ${albumName}"; + static String m11(albumName) => + "Enlace colaborativo creado para ${albumName}"; - static String m10(familyAdminEmail) => + static String m12(familyAdminEmail) => "Por favor contacta con ${familyAdminEmail} para administrar tu suscripción"; - static String m11(provider) => + static String m13(provider) => "Por favor, contáctenos en support@ente.io para gestionar su suscripción a ${provider}."; - static String m13(currentlyDeleting, totalCount) => + static String m15(currentlyDeleting, totalCount) => "Borrando ${currentlyDeleting} / ${totalCount}"; - static String m14(albumName) => + static String m16(albumName) => "Esto eliminará el enlace público para acceder a \"${albumName}\"."; - static String m15(supportEmail) => + static String m17(supportEmail) => "Por favor, envíe un email a ${supportEmail} desde su dirección de correo electrónico registrada"; - static String m16(count, storageSaved) => + static String m18(count, storageSaved) => "¡Has limpiado ${Intl.plural(count, one: '${count} archivo duplicado', other: '${count} archivos duplicados')}, ahorrando (${storageSaved}!)"; - static String m18(newEmail) => "Correo cambiado a ${newEmail}"; + static String m20(newEmail) => "Correo cambiado a ${newEmail}"; - static String m19(email) => + static String m21(email) => "${email} no tiene una cuenta ente.\n\nEnvíale una invitación para compartir fotos."; - static String m20(count, formattedNumber) => + static String m22(count, formattedNumber) => "${Intl.plural(count, one: '1 archivo', other: '${formattedNumber} archivos')} en este dispositivo han sido respaldados de forma segura"; - static String m21(count, formattedNumber) => + static String m23(count, formattedNumber) => "${Intl.plural(count, one: '1 archivo', other: '${formattedNumber} archivos')} en este álbum ha sido respaldado de forma segura"; - static String m22(storageAmountInGB) => + static String m24(storageAmountInGB) => "${storageAmountInGB} GB cada vez que alguien se registra en un plan de pago y aplica tu código"; - static String m23(freeAmount, storageUnit) => + static String m25(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} gratis"; - static String m24(endDate) => "Prueba gratuita válida hasta${endDate}"; + static String m26(endDate) => "Prueba gratuita válida hasta${endDate}"; - static String m25(count) => + static String m27(count) => "Aún puedes acceder ${Intl.plural(count, one: 'si', other: 'entonces')} en ente mientras mantengas una suscripción activa"; - static String m26(sizeInMBorGB) => "Liberar ${sizeInMBorGB}"; + static String m28(sizeInMBorGB) => "Liberar ${sizeInMBorGB}"; - static String m27(count, formattedSize) => + static String m29(count, formattedSize) => "${Intl.plural(count, one: 'Se puede eliminar del dispositivo para liberar ${formattedSize}', other: 'Se pueden eliminar del dispositivo para liberar ${formattedSize}')}"; - static String m29(count) => + static String m31(count) => "${Intl.plural(count, one: '${count} elemento', other: '${count} elementos')}"; - static String m30(expiryTime) => "El enlace caducará en ${expiryTime}"; + static String m32(expiryTime) => "El enlace caducará en ${expiryTime}"; - static String m31(count, formattedCount) => + static String m33(count, formattedCount) => "${Intl.plural(count, zero: 'no recuerdos', one: '${formattedCount} recuerdo', other: '${formattedCount} recuerdos')}\n"; - static String m32(count) => + static String m34(count) => "${Intl.plural(count, one: 'Mover elemento', other: 'Mover elementos')}"; - static String m33(albumName) => "Movido exitosamente a ${albumName}"; + static String m35(albumName) => "Movido exitosamente a ${albumName}"; - static String m34(passwordStrengthValue) => + static String m36(passwordStrengthValue) => "Seguridad de la contraseña : ${passwordStrengthValue}"; - static String m35(providerName) => + static String m37(providerName) => "Por favor hable con el soporte de ${providerName} si se le cobró"; - static String m36(reason) => + static String m38(reason) => "Lamentablemente tu pago falló debido a ${reason}"; - static String m38(toEmail) => + static String m40(toEmail) => "Por favor, envíanos un correo electrónico a ${toEmail}"; - static String m39(toEmail) => "Por favor, envíe los registros a ${toEmail}"; + static String m41(toEmail) => "Por favor, envíe los registros a ${toEmail}"; - static String m40(storeName) => "Califícanos en ${storeName}"; + static String m42(storeName) => "Califícanos en ${storeName}"; - static String m41(storageInGB) => + static String m43(storageInGB) => "3. Ambos obtienen ${storageInGB} GB* gratis"; - static String m42(userEmail) => + static String m44(userEmail) => "${userEmail} será eliminado de este álbum compartido\n\nCualquier foto añadida por ellos también será eliminada del álbum"; - static String m43(endDate) => "Se renueva el ${endDate}"; + static String m45(endDate) => "Se renueva el ${endDate}"; - static String m45(count) => "${count} seleccionados"; + static String m47(count) => "${count} seleccionados"; - static String m46(count, yourCount) => + static String m48(count, yourCount) => "${count} seleccionados (${yourCount} tuyos)"; - static String m47(verificationID) => + static String m49(verificationID) => "Aquí está mi ID de verificación: ${verificationID} para ente.io."; - static String m48(verificationID) => + static String m50(verificationID) => "Hola, ¿puedes confirmar que esta es tu ID de verificación ente.io: ${verificationID}?"; - static String m49(referralCode, referralStorageInGB) => + static String m51(referralCode, referralStorageInGB) => "ente código de referencia: ${referralCode} \n\nAplicarlo en Ajustes → General → Referencias para obtener ${referralStorageInGB} GB gratis después de registrarse en un plan de pago\n\nhttps://ente.io"; - static String m50(numberOfPeople) => + static String m52(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Compartir con personas específicas', one: 'Compartido con 1 persona', other: 'Compartido con ${numberOfPeople} personas')}"; - static String m51(emailIDs) => "Compartido con ${emailIDs}"; + static String m53(emailIDs) => "Compartido con ${emailIDs}"; - static String m52(fileType) => + static String m54(fileType) => "Este ${fileType} se eliminará de tu dispositivo."; - static String m53(fileType) => + static String m55(fileType) => "Este ${fileType} está tanto en ente como en tu dispositivo."; - static String m54(fileType) => "Este ${fileType} se eliminará de ente."; + static String m56(fileType) => "Este ${fileType} se eliminará de ente."; - static String m55(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m56( + static String m58( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} de ${totalAmount} ${totalStorageUnit} usados"; - static String m57(id) => + static String m59(id) => "Su ${id} ya está vinculado a otra cuenta ente.\nSi desea utilizar su ${id} con esta cuenta, póngase en contacto con nuestro servicio de asistencia\'\'"; - static String m58(endDate) => "Tu suscripción se cancelará el ${endDate}"; + static String m60(endDate) => "Tu suscripción se cancelará el ${endDate}"; - static String m59(completed, total) => + static String m61(completed, total) => "${completed}/${total} recuerdos conservados"; - static String m60(storageAmountInGB) => + static String m62(storageAmountInGB) => "También obtienen ${storageAmountInGB} GB"; - static String m61(email) => "Este es el ID de verificación de ${email}"; + static String m63(email) => "Este es el ID de verificación de ${email}"; - static String m64(email) => "Verificar ${email}"; + static String m66(email) => "Verificar ${email}"; - static String m65(email) => + static String m67(email) => "Hemos enviado un correo a ${email}"; - static String m66(count) => + static String m68(count) => "${Intl.plural(count, one: '${count} hace un año', other: '${count} hace años')}"; - static String m67(storageSaved) => "¡Has liberado ${storageSaved} con éxito!"; + static String m69(storageSaved) => "¡Has liberado ${storageSaved} con éxito!"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -204,7 +211,8 @@ class MessageLookup extends MessageLookupByLibrary { "Agregar nuevo correo electrónico"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Agregar colaborador"), - "addItem": m0, + "addCollaborators": m0, + "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("Agregar ubicación"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Añadir"), @@ -214,9 +222,10 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), "addViewer": MessageLookupByLibrary.simpleMessage("Añadir espectador"), + "addViewers": m1, "addedAs": MessageLookupByLibrary.simpleMessage("Agregado como"), - "addedBy": m2, - "addedSuccessfullyTo": m3, + "addedBy": m4, + "addedSuccessfullyTo": m5, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Añadiendo a favoritos..."), "advanced": MessageLookupByLibrary.simpleMessage("Avanzado"), @@ -229,7 +238,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Después de una semana"), "after1Year": MessageLookupByLibrary.simpleMessage("Después de un año"), "albumOwner": MessageLookupByLibrary.simpleMessage("Propietario"), - "albumParticipantsCount": m4, + "albumParticipantsCount": m6, "albumTitle": MessageLookupByLibrary.simpleMessage("Título del álbum"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Álbum actualizado"), @@ -247,7 +256,7 @@ class MessageLookup extends MessageLookupByLibrary { "Permitir que la gente añada fotos"), "androidIosWebDesktop": MessageLookupByLibrary.simpleMessage( "Android, iOS, Web, Computadora"), - "appVersion": m5, + "appVersion": m7, "appleId": MessageLookupByLibrary.simpleMessage("ID de Apple"), "apply": MessageLookupByLibrary.simpleMessage("Aplicar"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Usar código"), @@ -329,10 +338,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Sólo puede eliminar archivos de tu propiedad"), "cancel": MessageLookupByLibrary.simpleMessage("Cancelar"), - "cancelOtherSubscription": m6, + "cancelOtherSubscription": m8, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Cancelar suscripción"), - "cannotAddMorePhotosAfterBecomingViewer": m7, + "cannotAddMorePhotosAfterBecomingViewer": m9, "centerPoint": MessageLookupByLibrary.simpleMessage("Punto central"), "changeEmail": MessageLookupByLibrary.simpleMessage("Cambiar correo electrónico"), @@ -353,7 +362,7 @@ class MessageLookup extends MessageLookupByLibrary { "Reclamar almacenamiento gratis"), "claimMore": MessageLookupByLibrary.simpleMessage("¡Reclama más!"), "claimed": MessageLookupByLibrary.simpleMessage("Reclamado"), - "claimedStorageSoFar": m8, + "claimedStorageSoFar": m10, "clearCaches": MessageLookupByLibrary.simpleMessage("Limpiar caché"), "click": MessageLookupByLibrary.simpleMessage("• Click"), "clickOnTheOverflowMenu": MessageLookupByLibrary.simpleMessage( @@ -371,7 +380,7 @@ class MessageLookup extends MessageLookupByLibrary { "Crea un enlace para que la gente pueda añadir y ver fotos en tu álbum compartido sin necesidad de la aplicación ente o una cuenta. Genial para recolectar fotos de eventos."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Enlace colaborativo"), - "collaborativeLinkCreatedFor": m9, + "collaborativeLinkCreatedFor": m11, "collaborator": MessageLookupByLibrary.simpleMessage("Colaborador"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -396,10 +405,10 @@ class MessageLookup extends MessageLookupByLibrary { "Confirmar clave de recuperación"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Confirme su clave de recuperación"), - "contactFamilyAdmin": m10, + "contactFamilyAdmin": m12, "contactSupport": MessageLookupByLibrary.simpleMessage("Contactar con soporte"), - "contactToManageSubscription": m11, + "contactToManageSubscription": m13, "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuar"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( @@ -472,7 +481,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Borrar la ubicación"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Borrar las fotos"), - "deleteProgress": m13, + "deleteProgress": m15, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Falta una característica clave que necesito"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -506,7 +515,7 @@ class MessageLookup extends MessageLookupByLibrary { "Los espectadores todavía pueden tomar capturas de pantalla o guardar una copia de sus fotos usando herramientas externas"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Por favor tenga en cuenta"), - "disableLinkMessage": m14, + "disableLinkMessage": m16, "disableTwofactor": MessageLookupByLibrary.simpleMessage("Deshabilitar dos factores"), "disablingTwofactorAuthentication": @@ -527,8 +536,8 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Descarga fallida"), "downloading": MessageLookupByLibrary.simpleMessage("Descargando..."), - "dropSupportEmail": m15, - "duplicateFileCountWithStorageSaved": m16, + "dropSupportEmail": m17, + "duplicateFileCountWithStorageSaved": m18, "edit": MessageLookupByLibrary.simpleMessage("Editar"), "editLocation": MessageLookupByLibrary.simpleMessage("Edit location"), "editLocationTagTitle": @@ -540,8 +549,8 @@ class MessageLookup extends MessageLookupByLibrary { "Edits to location will only be seen within Ente"), "eligible": MessageLookupByLibrary.simpleMessage("elegible"), "email": MessageLookupByLibrary.simpleMessage("Correo electrónico"), - "emailChangedTo": m18, - "emailNoEnteAccount": m19, + "emailChangedTo": m20, + "emailNoEnteAccount": m21, "emailYourLogs": MessageLookupByLibrary.simpleMessage( "Envíe sus registros por correo electrónico"), "empty": MessageLookupByLibrary.simpleMessage("Vaciar"), @@ -630,8 +639,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileSavedToGallery": MessageLookupByLibrary.simpleMessage( "Archivo guardado en la galería"), "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), - "filesBackedUpFromDevice": m20, - "filesBackedUpInAlbum": m21, + "filesBackedUpFromDevice": m22, + "filesBackedUpInAlbum": m23, "filesDeleted": MessageLookupByLibrary.simpleMessage("Archivos eliminados"), "flip": MessageLookupByLibrary.simpleMessage("Voltear"), @@ -641,18 +650,18 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Olvidé mi contraseña"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage( "Almacenamiento gratuito reclamado"), - "freeStorageOnReferralSuccess": m22, - "freeStorageSpace": m23, + "freeStorageOnReferralSuccess": m24, + "freeStorageSpace": m25, "freeStorageUsable": MessageLookupByLibrary.simpleMessage( "Almacenamiento libre disponible"), "freeTrial": MessageLookupByLibrary.simpleMessage("Prueba gratuita"), - "freeTrialValidTill": m24, - "freeUpAccessPostDelete": m25, - "freeUpAmount": m26, + "freeTrialValidTill": m26, + "freeUpAccessPostDelete": m27, + "freeUpAmount": m28, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Liberar espacio del dispositivo"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Liberar espacio"), - "freeUpSpaceSaving": m27, + "freeUpSpaceSaving": m29, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Hasta 1000 memorias mostradas en la galería"), "general": MessageLookupByLibrary.simpleMessage("General"), @@ -698,7 +707,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Parece que algo salió mal. Por favor, vuelve a intentarlo después de algún tiempo. Si el error persiste, ponte en contacto con nuestro equipo de soporte."), - "itemCount": m29, + "itemCount": m31, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Los artículos muestran el número de días restantes antes de ser borrados permanente"), @@ -727,7 +736,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Límite del dispositivo"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Habilitado"), "linkExpired": MessageLookupByLibrary.simpleMessage("Vencido"), - "linkExpiresOn": m30, + "linkExpiresOn": m32, "linkExpiry": MessageLookupByLibrary.simpleMessage("Enlace vence"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("El enlace ha caducado"), @@ -776,6 +785,9 @@ class MessageLookup extends MessageLookupByLibrary { "logout": MessageLookupByLibrary.simpleMessage("Cerrar sesión"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( "Esto enviará registros para ayudarnos a depurar su problema. Tenga en cuenta que los nombres de los archivos se incluirán para ayudar a rastrear problemas con archivos específicos."), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( "Pulsación prolongada en un elemento para ver en pantalla completa"), "lostDevice": @@ -793,7 +805,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Administrar tu suscripción"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m31, + "memoryCount": m33, "merchandise": MessageLookupByLibrary.simpleMessage("Mercancías"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("Celular, Web, Computadora"), @@ -802,11 +814,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Modify your query, or try searching for"), "monthly": MessageLookupByLibrary.simpleMessage("Mensual"), - "moveItem": m32, + "moveItem": m34, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Mover al álbum"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Move to hidden album"), - "movedSuccessfullyTo": m33, + "movedSuccessfullyTo": m35, "movedToTrash": MessageLookupByLibrary.simpleMessage("Movido a la papelera"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -856,14 +868,14 @@ class MessageLookup extends MessageLookupByLibrary { "Contraseña cambiada correctamente"), "passwordLock": MessageLookupByLibrary.simpleMessage("Bloqueo por contraseña"), - "passwordStrength": m34, + "passwordStrength": m36, "passwordWarning": MessageLookupByLibrary.simpleMessage( "No almacenamos esta contraseña, así que si la olvidas, no podemos descifrar tus datos"), "paymentDetails": MessageLookupByLibrary.simpleMessage("Detalles de pago"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Pago fallido"), - "paymentFailedTalkToProvider": m35, - "paymentFailedWithReason": m36, + "paymentFailedTalkToProvider": m37, + "paymentFailedWithReason": m38, "pendingSync": MessageLookupByLibrary.simpleMessage("Sincronización pendiente"), "peopleUsingYourCode": @@ -890,12 +902,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Por favor contacte a soporte técnico si el problema persiste"), - "pleaseEmailUsAt": m38, + "pleaseEmailUsAt": m40, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Por favor, concede permiso"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( "Por favor, vuelva a iniciar sesión"), - "pleaseSendTheLogsTo": m39, + "pleaseSendTheLogsTo": m41, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Por favor, inténtalo nuevamente"), "pleaseVerifyTheCodeYouHaveEntered": @@ -929,7 +941,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Evalúa la aplicación"), "rateUs": MessageLookupByLibrary.simpleMessage("Califícanos"), - "rateUsOnStore": m40, + "rateUsOnStore": m42, "recover": MessageLookupByLibrary.simpleMessage("Recuperar"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recuperar cuenta"), @@ -961,7 +973,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Dale este código a tus amigos"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Se inscriben a un plan pagado"), - "referralStep3": m41, + "referralStep3": m43, "referrals": MessageLookupByLibrary.simpleMessage("Referidos"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Las referencias están actualmente en pausa"), @@ -986,7 +998,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Eliminar enlace"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Quitar participante"), - "removeParticipantBody": m42, + "removeParticipantBody": m44, "removePublicLink": MessageLookupByLibrary.simpleMessage("Quitar enlace público"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1000,7 +1012,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Renombrar archivo"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renovar suscripción"), - "renewsOn": m43, + "renewsOn": m45, "reportABug": MessageLookupByLibrary.simpleMessage("Reportar un error"), "reportBug": MessageLookupByLibrary.simpleMessage("Reportar error"), "resendEmail": @@ -1062,8 +1074,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Los archivos seleccionados serán eliminados de todos los álbumes y movidos a la papelera."), - "selectedPhotos": m45, - "selectedPhotosWithYours": m46, + "selectedPhotos": m47, + "selectedPhotosWithYours": m48, "send": MessageLookupByLibrary.simpleMessage("Enviar"), "sendEmail": MessageLookupByLibrary.simpleMessage("Enviar correo electrónico"), @@ -1088,32 +1100,32 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Compartir un álbum ahora"), "shareLink": MessageLookupByLibrary.simpleMessage("Compartir enlace"), - "shareMyVerificationID": m47, + "shareMyVerificationID": m49, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Comparte sólo con la gente que quieres"), - "shareTextConfirmOthersVerificationID": m48, + "shareTextConfirmOthersVerificationID": m50, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Descarga ente para que podamos compartir fácilmente fotos y videos en su calidad original\n\nhttps://ente.io"), - "shareTextReferralCode": m49, + "shareTextReferralCode": m51, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Compartir con usuarios no ente"), - "shareWithPeopleSectionTitle": m50, + "shareWithPeopleSectionTitle": m52, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Comparte tu primer álbum"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( "Crear álbumes compartidos y colaborativos con otros usuarios ente, incluyendo usuarios en planes gratuitos."), "sharedByMe": MessageLookupByLibrary.simpleMessage("Compartido por mí"), - "sharedWith": m51, + "sharedWith": m53, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Compartido conmigo"), "sharing": MessageLookupByLibrary.simpleMessage("Compartiendo..."), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Estoy de acuerdo con los términos del servicio y la política de privacidad"), - "singleFileDeleteFromDevice": m52, + "singleFileDeleteFromDevice": m54, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Se borrará de todos los álbumes."), - "singleFileInBothLocalAndRemote": m53, - "singleFileInRemoteOnly": m54, + "singleFileInBothLocalAndRemote": m55, + "singleFileInRemoteOnly": m56, "skip": MessageLookupByLibrary.simpleMessage("Omitir"), "social": MessageLookupByLibrary.simpleMessage("Social"), "someItemsAreInBothEnteAndYourDevice": @@ -1148,13 +1160,13 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Almacenamiento"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Familia"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Usted"), - "storageInGB": m55, + "storageInGB": m57, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Límite de datos excedido"), - "storageUsageInfo": m56, + "storageUsageInfo": m58, "strongStrength": MessageLookupByLibrary.simpleMessage("Segura"), - "subAlreadyLinkedErrMessage": m57, - "subWillBeCancelledOn": m58, + "subAlreadyLinkedErrMessage": m59, + "subWillBeCancelledOn": m60, "subscribe": MessageLookupByLibrary.simpleMessage("Suscribirse"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Parece que su suscripción ha caducado. Por favor, suscríbase para habilitar el compartir."), @@ -1167,7 +1179,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Sugerir una característica"), "support": MessageLookupByLibrary.simpleMessage("Soporte"), - "syncProgress": m59, + "syncProgress": m61, "syncStopped": MessageLookupByLibrary.simpleMessage("Sincronización detenida"), "syncing": MessageLookupByLibrary.simpleMessage("Sincronizando..."), @@ -1195,7 +1207,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Estos elementos se eliminarán de tu dispositivo."), - "theyAlsoGetXGb": m60, + "theyAlsoGetXGb": m62, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Se borrarán de todos los álbumes."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1211,7 +1223,7 @@ class MessageLookup extends MessageLookupByLibrary { "Este correo electrónico ya está en uso"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Esta imagen no tiene datos exif"), - "thisIsPersonVerificationId": m61, + "thisIsPersonVerificationId": m63, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Esta es tu ID de verificación"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1281,7 +1293,7 @@ class MessageLookup extends MessageLookupByLibrary { "verify": MessageLookupByLibrary.simpleMessage("Verificar"), "verifyEmail": MessageLookupByLibrary.simpleMessage( "Verificar correo electrónico"), - "verifyEmailID": m64, + "verifyEmailID": m66, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verificar"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Verificar contraseña"), @@ -1304,12 +1316,12 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "No admitimos la edición de fotos y álbunes que aún no son tuyos"), - "weHaveSendEmailTo": m65, + "weHaveSendEmailTo": m67, "weakStrength": MessageLookupByLibrary.simpleMessage("Poco segura"), "welcomeBack": MessageLookupByLibrary.simpleMessage("¡Bienvenido de nuevo!"), "yearly": MessageLookupByLibrary.simpleMessage("Anualmente"), - "yearsAgo": m66, + "yearsAgo": m68, "yes": MessageLookupByLibrary.simpleMessage("Sí"), "yesCancel": MessageLookupByLibrary.simpleMessage("Sí, cancelar"), "yesConvertToViewer": @@ -1339,7 +1351,7 @@ class MessageLookup extends MessageLookupByLibrary { "No puedes compartir contigo mismo"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "No tienes nada de elementos archivados."), - "youHaveSuccessfullyFreedUp": m67, + "youHaveSuccessfullyFreedUp": m69, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Su cuenta ha sido eliminada"), "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), diff --git a/mobile/lib/generated/intl/messages_fr.dart b/mobile/lib/generated/intl/messages_fr.dart index b2ac59426c..6bef1659c6 100644 --- a/mobile/lib/generated/intl/messages_fr.dart +++ b/mobile/lib/generated/intl/messages_fr.dart @@ -21,24 +21,30 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'fr'; static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m2(count) => "${Intl.plural(count, one: 'Ajoutez un objet', other: 'Ajoutez des objets')}"; - static String m2(emailOrName) => "Ajouté par ${emailOrName}"; + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + + static String m4(emailOrName) => "Ajouté par ${emailOrName}"; - static String m3(albumName) => "Ajouté avec succès à ${albumName}"; + static String m5(albumName) => "Ajouté avec succès à ${albumName}"; - static String m4(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Aucun Participant', one: '1 Participant', other: '${count} Participants')}"; - static String m5(versionValue) => "Version : ${versionValue}"; + static String m7(versionValue) => "Version : ${versionValue}"; - static String m6(paymentProvider) => + static String m8(paymentProvider) => "Veuillez d\'abord annuler votre abonnement existant de ${paymentProvider}"; - static String m7(user) => + static String m9(user) => "${user} ne pourra pas ajouter plus de photos à cet album\n\nIl pourrait toujours supprimer les photos existantes ajoutées par eux"; - static String m8(isFamilyMember, storageAmountInGb) => + static String m10(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Votre famille a demandé ${storageAmountInGb} GB jusqu\'à présent', @@ -48,161 +54,161 @@ class MessageLookup extends MessageLookupByLibrary { 'Vous avez réclamé ${storageAmountInGb} GB jusqu\'à présent!', })}"; - static String m9(albumName) => "Lien collaboratif créé pour ${albumName}"; + static String m11(albumName) => "Lien collaboratif créé pour ${albumName}"; - static String m10(familyAdminEmail) => + static String m12(familyAdminEmail) => "Veuillez contacter ${familyAdminEmail} pour gérer votre abonnement"; - static String m11(provider) => + static String m13(provider) => "Veuillez nous contacter à support@ente.io pour gérer votre abonnement ${provider}."; - static String m12(count) => + static String m14(count) => "${Intl.plural(count, one: 'Supprimer le fichier', other: 'Supprimer ${count} fichiers')}"; - static String m13(currentlyDeleting, totalCount) => + static String m15(currentlyDeleting, totalCount) => "Suppression de ${currentlyDeleting} / ${totalCount}"; - static String m14(albumName) => + static String m16(albumName) => "Cela supprimera le lien public pour accéder à \"${albumName}\"."; - static String m15(supportEmail) => + static String m17(supportEmail) => "Veuillez envoyer un e-mail à ${supportEmail} depuis votre adresse enregistrée"; - static String m16(count, storageSaved) => + static String m18(count, storageSaved) => "Vous avez nettoyé ${Intl.plural(count, one: '${count} fichier dupliqué', other: '${count} fichiers dupliqués')}, sauvegarde (${storageSaved}!)"; - static String m17(count, formattedSize) => + static String m19(count, formattedSize) => "${count} fichiers, ${formattedSize} chacun"; - static String m18(newEmail) => "L\'e-mail a été changé en ${newEmail}"; + static String m20(newEmail) => "L\'e-mail a été changé en ${newEmail}"; - static String m19(email) => + static String m21(email) => "${email} n\'a pas de compte ente.\n\nEnvoyez une invitation pour partager des photos."; - static String m20(count, formattedNumber) => + static String m22(count, formattedNumber) => "${Intl.plural(count, one: '1 fichier sur cet appareil a été sauvegardé en toute sécurité', other: '${formattedNumber} fichiers sur cet appareil ont été sauvegardés en toute sécurité')}"; - static String m21(count, formattedNumber) => + static String m23(count, formattedNumber) => "${Intl.plural(count, 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é')}"; - static String m22(storageAmountInGB) => + static String m24(storageAmountInGB) => "${storageAmountInGB} Go chaque fois que quelqu\'un s\'inscrit à une offre payante et applique votre code"; - static String m23(freeAmount, storageUnit) => + static String m25(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} libre"; - static String m24(endDate) => "Essai gratuit valide jusqu’au ${endDate}"; + static String m26(endDate) => "Essai gratuit valide jusqu’au ${endDate}"; - static String m25(count) => + static String m27(count) => "Vous pouvez toujours ${Intl.plural(count, one: 'y', other: 'y')} accéder sur ente tant que vous avez un abonnement actif"; - static String m26(sizeInMBorGB) => "Libérer ${sizeInMBorGB}"; + static String m28(sizeInMBorGB) => "Libérer ${sizeInMBorGB}"; - static String m27(count, formattedSize) => + static String m29(count, formattedSize) => "${Intl.plural(count, one: 'Peut être supprimé de l\'appareil pour libérer ${formattedSize}', other: 'Peuvent être supprimés de l\'appareil pour libérer ${formattedSize}')}"; - static String m29(count) => + static String m31(count) => "${Intl.plural(count, one: '${count} objet', other: '${count} objets')}"; - static String m30(expiryTime) => "Le lien expirera le ${expiryTime}"; + static String m32(expiryTime) => "Le lien expirera le ${expiryTime}"; - static String m31(count, formattedCount) => + static String m33(count, formattedCount) => "${Intl.plural(count, one: '${formattedCount} mémoire', other: '${formattedCount} souvenirs')}"; - static String m32(count) => + static String m34(count) => "${Intl.plural(count, one: 'Déplacez l\'objet', other: 'Déplacez des objets')}"; - static String m33(albumName) => "Déplacé avec succès vers ${albumName}"; + static String m35(albumName) => "Déplacé avec succès vers ${albumName}"; - static String m34(passwordStrengthValue) => + static String m36(passwordStrengthValue) => "Sécurité du mot de passe : ${passwordStrengthValue}"; - static String m35(providerName) => + static String m37(providerName) => "Veuillez contacter le support ${providerName} si vous avez été facturé"; - static String m36(reason) => + static String m38(reason) => "Malheureusement, votre paiement a échoué pour ${reason}"; - static String m37(endDate) => + static String m39(endDate) => "Essai gratuit valable jusqu\'à ${endDate}.\nVous pouvez choisir un plan payant par la suite."; - static String m38(toEmail) => "Merci de nous envoyer un e-mail à ${toEmail}"; + static String m40(toEmail) => "Merci de nous envoyer un e-mail à ${toEmail}"; - static String m39(toEmail) => "Envoyez les logs à ${toEmail}"; + static String m41(toEmail) => "Envoyez les logs à ${toEmail}"; - static String m40(storeName) => "Notez-nous sur ${storeName}"; + static String m42(storeName) => "Notez-nous sur ${storeName}"; - static String m41(storageInGB) => + static String m43(storageInGB) => "3. Vous recevez tous les deux ${storageInGB} GB* gratuits"; - static String m42(userEmail) => + static String m44(userEmail) => "${userEmail} sera retiré de cet album partagé\n\nToutes les photos ajoutées par eux seront également retirées de l\'album"; - static String m43(endDate) => "Renouvellement le ${endDate}"; + static String m45(endDate) => "Renouvellement le ${endDate}"; - static String m44(count) => + static String m46(count) => "${Intl.plural(count, one: '${count} résultat trouvé', other: '${count} résultats trouvés')}"; - static String m45(count) => "${count} sélectionné(s)"; + static String m47(count) => "${count} sélectionné(s)"; - static String m46(count, yourCount) => + static String m48(count, yourCount) => "${count} sélectionné(s) (${yourCount} à vous)"; - static String m47(verificationID) => + static String m49(verificationID) => "Voici mon ID de vérification : ${verificationID} pour ente.io."; - static String m48(verificationID) => + static String m50(verificationID) => "Hé, pouvez-vous confirmer qu\'il s\'agit de votre ID de vérification ente.io : ${verificationID}"; - static String m49(referralCode, referralStorageInGB) => + static String m51(referralCode, referralStorageInGB) => "code de parrainage ente : ${referralCode} \n\nAppliquez le dans Paramètres → Général → Références pour obtenir ${referralStorageInGB} Go gratuitement après votre inscription à un plan payant\n\nhttps://ente.io"; - static String m50(numberOfPeople) => + static String m52(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Partagez avec des personnes spécifiques', one: 'Partagé avec 1 personne', other: 'Partagé avec ${numberOfPeople} des gens')}"; - static String m51(emailIDs) => "Partagé avec ${emailIDs}"; + static String m53(emailIDs) => "Partagé avec ${emailIDs}"; - static String m52(fileType) => + static String m54(fileType) => "Elle ${fileType} sera supprimée de votre appareil."; - static String m53(fileType) => + static String m55(fileType) => "Cette ${fileType} est à la fois sur ente et sur votre appareil."; - static String m54(fileType) => "Ce ${fileType} sera supprimé de ente."; + static String m56(fileType) => "Ce ${fileType} sera supprimé de ente."; - static String m55(storageAmountInGB) => "${storageAmountInGB} Go"; + static String m57(storageAmountInGB) => "${storageAmountInGB} Go"; - static String m56( + static String m58( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} sur ${totalAmount} ${totalStorageUnit} utilisé"; - static String m57(id) => + static String m59(id) => "Votre ${id} est déjà lié à un autre compte ente.\nSi vous souhaitez utiliser votre ${id} avec ce compte, veuillez contacter notre support"; - static String m58(endDate) => "Votre abonnement sera annulé le ${endDate}"; + static String m60(endDate) => "Votre abonnement sera annulé le ${endDate}"; - static String m59(completed, total) => + static String m61(completed, total) => "${completed}/${total} souvenirs préservés"; - static String m60(storageAmountInGB) => + static String m62(storageAmountInGB) => "Ils obtiennent aussi ${storageAmountInGB} Go"; - static String m61(email) => "Ceci est l\'ID de vérification de ${email}"; + static String m63(email) => "Ceci est l\'ID de vérification de ${email}"; - static String m62(count) => + static String m64(count) => "${Intl.plural(count, zero: '0 jour', one: '1 jour', other: '${count} jours')}"; - static String m63(endDate) => "Valable jusqu\'au ${endDate}"; + static String m65(endDate) => "Valable jusqu\'au ${endDate}"; - static String m64(email) => "Vérifier ${email}"; + static String m66(email) => "Vérifier ${email}"; - static String m65(email) => + static String m67(email) => "Nous avons envoyé un e-mail à ${email}"; - static String m66(count) => + static String m68(count) => "${Intl.plural(count, one: 'il y a ${count} an', other: 'il y a ${count} ans')}"; - static String m67(storageSaved) => + static String m69(storageSaved) => "Vous avez libéré ${storageSaved} avec succès !"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -221,9 +227,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter un nouvel email"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Ajouter un collaborateur"), + "addCollaborators": m0, "addFromDevice": MessageLookupByLibrary.simpleMessage("Ajouter depuis l\'appareil"), - "addItem": m0, + "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("Ajouter la localisation"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Ajouter"), @@ -243,11 +250,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter à un album masqué"), "addViewer": MessageLookupByLibrary.simpleMessage("Ajouter un observateur"), + "addViewers": m1, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage( "Ajoutez vos photos maintenant"), "addedAs": MessageLookupByLibrary.simpleMessage("Ajouté comme"), - "addedBy": m2, - "addedSuccessfullyTo": m3, + "addedBy": m4, + "addedSuccessfullyTo": m5, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Ajout aux favoris..."), "advanced": MessageLookupByLibrary.simpleMessage("Avancé"), @@ -258,7 +266,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Après 1 semaine"), "after1Year": MessageLookupByLibrary.simpleMessage("Après 1 an"), "albumOwner": MessageLookupByLibrary.simpleMessage("Propriétaire"), - "albumParticipantsCount": m4, + "albumParticipantsCount": m6, "albumTitle": MessageLookupByLibrary.simpleMessage("Titre de l\'album"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album mis à jour"), @@ -293,7 +301,7 @@ class MessageLookup extends MessageLookupByLibrary { "Android, iOS, Web, Ordinateur"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("Authentification requise"), - "appVersion": m5, + "appVersion": m7, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Appliquer"), "applyCodeTitle": @@ -383,10 +391,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Vous ne pouvez supprimer que les fichiers que vous possédez"), "cancel": MessageLookupByLibrary.simpleMessage("Annuler"), - "cancelOtherSubscription": m6, + "cancelOtherSubscription": m8, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Annuler l\'abonnement"), - "cannotAddMorePhotosAfterBecomingViewer": m7, + "cannotAddMorePhotosAfterBecomingViewer": m9, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Les fichiers partagés ne peuvent pas être supprimés"), "centerPoint": MessageLookupByLibrary.simpleMessage("Point central"), @@ -409,7 +417,7 @@ class MessageLookup extends MessageLookupByLibrary { "Réclamer le stockage gratuit"), "claimMore": MessageLookupByLibrary.simpleMessage("Réclamez plus !"), "claimed": MessageLookupByLibrary.simpleMessage("Réclamée"), - "claimedStorageSoFar": m8, + "claimedStorageSoFar": m10, "clearCaches": MessageLookupByLibrary.simpleMessage("Nettoyer le cache"), "click": MessageLookupByLibrary.simpleMessage("• Click"), @@ -430,7 +438,7 @@ class MessageLookup extends MessageLookupByLibrary { "Créez un lien pour permettre aux gens d\'ajouter et de voir des photos dans votre album partagé sans avoir besoin d\'une application ente ou d\'un compte. Idéal pour collecter des photos d\'événement."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Lien collaboratif"), - "collaborativeLinkCreatedFor": m9, + "collaborativeLinkCreatedFor": m11, "collaborator": MessageLookupByLibrary.simpleMessage("Collaborateur"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -458,10 +466,10 @@ class MessageLookup extends MessageLookupByLibrary { "Confirmer la clé de récupération"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Confirmer la clé de récupération"), - "contactFamilyAdmin": m10, + "contactFamilyAdmin": m12, "contactSupport": MessageLookupByLibrary.simpleMessage("Contacter l\'assistance"), - "contactToManageSubscription": m11, + "contactToManageSubscription": m13, "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "contents": MessageLookupByLibrary.simpleMessage("Contenus"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuer"), @@ -542,12 +550,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Supprimer de l\'appareil"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Supprimer de ente"), - "deleteItemCount": m12, + "deleteItemCount": m14, "deleteLocation": MessageLookupByLibrary.simpleMessage("Supprimer la localisation"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Supprimer des photos"), - "deleteProgress": m13, + "deleteProgress": m15, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Il manque une fonction clé dont j\'ai besoin"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -581,7 +589,7 @@ class MessageLookup extends MessageLookupByLibrary { "Les téléspectateurs peuvent toujours prendre des captures d\'écran ou enregistrer une copie de vos photos en utilisant des outils externes"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Veuillez remarquer"), - "disableLinkMessage": m14, + "disableLinkMessage": m16, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Désactiver la double-authentification"), "disablingTwofactorAuthentication": @@ -602,9 +610,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Échec du téléchargement"), "downloading": MessageLookupByLibrary.simpleMessage("Téléchargement en cours..."), - "dropSupportEmail": m15, - "duplicateFileCountWithStorageSaved": m16, - "duplicateItemsGroup": m17, + "dropSupportEmail": m17, + "duplicateFileCountWithStorageSaved": m18, + "duplicateItemsGroup": m19, "edit": MessageLookupByLibrary.simpleMessage("Éditer"), "editLocation": MessageLookupByLibrary.simpleMessage("Edit location"), "editLocationTagTitle": @@ -616,8 +624,8 @@ class MessageLookup extends MessageLookupByLibrary { "Edits to location will only be seen within Ente"), "eligible": MessageLookupByLibrary.simpleMessage("éligible"), "email": MessageLookupByLibrary.simpleMessage("E-mail"), - "emailChangedTo": m18, - "emailNoEnteAccount": m19, + "emailChangedTo": m20, + "emailNoEnteAccount": m21, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage( "Vérification de l\'adresse e-mail"), "emailYourLogs": @@ -716,8 +724,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Types de fichiers"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Types et noms de fichiers"), - "filesBackedUpFromDevice": m20, - "filesBackedUpInAlbum": m21, + "filesBackedUpFromDevice": m22, + "filesBackedUpInAlbum": m23, "filesDeleted": MessageLookupByLibrary.simpleMessage("Fichiers supprimés"), "flip": MessageLookupByLibrary.simpleMessage("Retourner"), @@ -727,19 +735,19 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Mot de passe oublié"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Stockage gratuit réclamé"), - "freeStorageOnReferralSuccess": m22, - "freeStorageSpace": m23, + "freeStorageOnReferralSuccess": m24, + "freeStorageSpace": m25, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Stockage gratuit utilisable"), "freeTrial": MessageLookupByLibrary.simpleMessage("Essai gratuit"), - "freeTrialValidTill": m24, - "freeUpAccessPostDelete": m25, - "freeUpAmount": m26, + "freeTrialValidTill": m26, + "freeUpAccessPostDelete": m27, + "freeUpAmount": m28, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Libérer de l\'espace sur l\'appareil"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Libérer de l\'espace"), - "freeUpSpaceSaving": m27, + "freeUpSpaceSaving": m29, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Jusqu\'à 1000 souvenirs affichés dans la galerie"), "general": MessageLookupByLibrary.simpleMessage("Général"), @@ -806,7 +814,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Il semble qu\'une erreur s\'est produite. Veuillez réessayer après un certain temps. Si l\'erreur persiste, veuillez contacter notre équipe d\'assistance."), - "itemCount": m29, + "itemCount": m31, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Les éléments montrent le nombre de jours restants avant la suppression définitive"), @@ -835,7 +843,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Limite d\'appareil"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Activé"), "linkExpired": MessageLookupByLibrary.simpleMessage("Expiré"), - "linkExpiresOn": m30, + "linkExpiresOn": m32, "linkExpiry": MessageLookupByLibrary.simpleMessage("Expiration du lien"), "linkHasExpired": @@ -884,6 +892,9 @@ class MessageLookup extends MessageLookupByLibrary { "logout": MessageLookupByLibrary.simpleMessage("Déconnexion"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( "Cela enverra des logs pour nous aider à déboguer votre problème. Veuillez noter que les noms de fichiers seront inclus pour aider à suivre les problèmes avec des fichiers spécifiques."), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( "Appuyez longuement sur un élément pour le voir en plein écran"), @@ -901,7 +912,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Cartes"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m31, + "memoryCount": m33, "merchandise": MessageLookupByLibrary.simpleMessage("Marchandise"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("Mobile, Web, Ordinateur"), @@ -912,12 +923,12 @@ class MessageLookup extends MessageLookupByLibrary { "Modifiez votre requête, ou essayez de rechercher"), "moments": MessageLookupByLibrary.simpleMessage("Souvenirs"), "monthly": MessageLookupByLibrary.simpleMessage("Mensuel"), - "moveItem": m32, + "moveItem": m34, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Déplacer vers l\'album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Déplacer vers un album masqué"), - "movedSuccessfullyTo": m33, + "movedSuccessfullyTo": m35, "movedToTrash": MessageLookupByLibrary.simpleMessage("Déplacé dans la corbeille"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -981,15 +992,15 @@ class MessageLookup extends MessageLookupByLibrary { "Le mot de passe a été modifié"), "passwordLock": MessageLookupByLibrary.simpleMessage("Mot de passe verrou"), - "passwordStrength": m34, + "passwordStrength": m36, "passwordWarning": MessageLookupByLibrary.simpleMessage( "Nous ne stockons pas ce mot de passe, donc si vous l\'oubliez, nous ne pouvons pas déchiffrer vos données"), "paymentDetails": MessageLookupByLibrary.simpleMessage("Détails de paiement"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Échec du paiement"), - "paymentFailedTalkToProvider": m35, - "paymentFailedWithReason": m36, + "paymentFailedTalkToProvider": m37, + "paymentFailedWithReason": m38, "pendingSync": MessageLookupByLibrary.simpleMessage("Synchronisation en attente"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage( @@ -1012,7 +1023,7 @@ class MessageLookup extends MessageLookupByLibrary { "pickCenterPoint": MessageLookupByLibrary.simpleMessage( "Sélectionner le point central"), "pinAlbum": MessageLookupByLibrary.simpleMessage("Épingler l\'album"), - "playStoreFreeTrialValidTill": m37, + "playStoreFreeTrialValidTill": m39, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Abonnement au PlayStore"), "pleaseContactSupportAndWeWillBeHappyToHelp": @@ -1021,12 +1032,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Merci de contacter l\'assistance si cette erreur persiste"), - "pleaseEmailUsAt": m38, + "pleaseEmailUsAt": m40, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Veuillez accorder la permission"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Veuillez vous reconnecter"), - "pleaseSendTheLogsTo": m39, + "pleaseSendTheLogsTo": m41, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Veuillez réessayer"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1062,7 +1073,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Évaluer l\'application"), "rateUs": MessageLookupByLibrary.simpleMessage("Évaluez-nous"), - "rateUsOnStore": m40, + "rateUsOnStore": m42, "recover": MessageLookupByLibrary.simpleMessage("Récupérer"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Récupérer un compte"), @@ -1093,7 +1104,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Donnez ce code à vos amis"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Ils s\'inscrivent à une offre payante"), - "referralStep3": m41, + "referralStep3": m43, "referrals": MessageLookupByLibrary.simpleMessage("Parrainages"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Les recommandations sont actuellement en pause"), @@ -1119,7 +1130,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Supprimer le lien"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Supprimer le participant"), - "removeParticipantBody": m42, + "removeParticipantBody": m44, "removePublicLink": MessageLookupByLibrary.simpleMessage("Supprimer le lien public"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1135,7 +1146,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Renommer le fichier"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renouveler l’abonnement"), - "renewsOn": m43, + "renewsOn": m45, "reportABug": MessageLookupByLibrary.simpleMessage("Signaler un bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Signaler un bug"), "resendEmail": @@ -1200,7 +1211,7 @@ class MessageLookup extends MessageLookupByLibrary { "Grouper les photos qui sont prises dans un certain angle d\'une photo"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invitez des gens, et vous verrez ici toutes les photos qu\'ils partagent"), - "searchResultCount": m44, + "searchResultCount": m46, "security": MessageLookupByLibrary.simpleMessage("Sécurité"), "selectALocation": MessageLookupByLibrary.simpleMessage("Select a location"), @@ -1229,8 +1240,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Les éléments sélectionnés seront supprimés de tous les albums et déplacés dans la corbeille."), - "selectedPhotos": m45, - "selectedPhotosWithYours": m46, + "selectedPhotos": m47, + "selectedPhotosWithYours": m48, "send": MessageLookupByLibrary.simpleMessage("Envoyer"), "sendEmail": MessageLookupByLibrary.simpleMessage("Envoyer un e-mail"), "sendInvite": @@ -1256,16 +1267,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage( "Partagez un album maintenant"), "shareLink": MessageLookupByLibrary.simpleMessage("Partager le lien"), - "shareMyVerificationID": m47, + "shareMyVerificationID": m49, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Partager uniquement avec les personnes que vous voulez"), - "shareTextConfirmOthersVerificationID": m48, + "shareTextConfirmOthersVerificationID": m50, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Téléchargez ente pour que nous puissions facilement partager des photos et des vidéos de qualité originale\n\nhttps://ente.io"), - "shareTextReferralCode": m49, + "shareTextReferralCode": m51, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Partager avec des utilisateurs non-ente"), - "shareWithPeopleSectionTitle": m50, + "shareWithPeopleSectionTitle": m52, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Partagez votre premier album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1276,7 +1287,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nouvelles photos partagées"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Recevoir des notifications quand quelqu\'un ajoute une photo à un album partagé dont vous faites partie"), - "sharedWith": m51, + "sharedWith": m53, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Partagés avec moi"), "sharedWithYou": @@ -1286,11 +1297,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Montrer les souvenirs"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "J\'accepte les conditions d\'utilisation et la politique de confidentialité"), - "singleFileDeleteFromDevice": m52, + "singleFileDeleteFromDevice": m54, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Elle sera supprimée de tous les albums."), - "singleFileInBothLocalAndRemote": m53, - "singleFileInRemoteOnly": m54, + "singleFileInBothLocalAndRemote": m55, + "singleFileInRemoteOnly": m56, "skip": MessageLookupByLibrary.simpleMessage("Ignorer"), "social": MessageLookupByLibrary.simpleMessage("Réseaux Sociaux"), "someItemsAreInBothEnteAndYourDevice": @@ -1330,14 +1341,14 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Stockage"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Famille"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Vous"), - "storageInGB": m55, + "storageInGB": m57, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Limite de stockage atteinte"), - "storageUsageInfo": m56, + "storageUsageInfo": m58, "strongStrength": MessageLookupByLibrary.simpleMessage("Securité forte"), - "subAlreadyLinkedErrMessage": m57, - "subWillBeCancelledOn": m58, + "subAlreadyLinkedErrMessage": m59, + "subWillBeCancelledOn": m60, "subscribe": MessageLookupByLibrary.simpleMessage("S\'abonner"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Il semble que votre abonnement ait expiré. Veuillez vous abonner pour activer le partage."), @@ -1354,7 +1365,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage( "Suggérer des fonctionnalités"), "support": MessageLookupByLibrary.simpleMessage("Support"), - "syncProgress": m59, + "syncProgress": m61, "syncStopped": MessageLookupByLibrary.simpleMessage("Synchronisation arrêtée ?"), "syncing": MessageLookupByLibrary.simpleMessage( @@ -1383,7 +1394,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Ces éléments seront supprimés de votre appareil."), - "theyAlsoGetXGb": m60, + "theyAlsoGetXGb": m62, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Ils seront supprimés de tous les albums."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1399,7 +1410,7 @@ class MessageLookup extends MessageLookupByLibrary { "Cette adresse mail est déjà utilisé"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Cette image n\'a pas de données exif"), - "thisIsPersonVerificationId": m61, + "thisIsPersonVerificationId": m63, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Ceci est votre ID de vérification"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1415,7 +1426,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("total"), "totalSize": MessageLookupByLibrary.simpleMessage("Taille totale"), "trash": MessageLookupByLibrary.simpleMessage("Corbeille"), - "trashDaysLeft": m62, + "trashDaysLeft": m64, "tryAgain": MessageLookupByLibrary.simpleMessage("Réessayer"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Activez la sauvegarde pour télécharger automatiquement les fichiers ajoutés à ce dossier de l\'appareil sur ente."), @@ -1473,7 +1484,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage( "Utiliser la photo sélectionnée"), "usedSpace": MessageLookupByLibrary.simpleMessage("Mémoire utilisée"), - "validTill": m63, + "validTill": m65, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "La vérification a échouée, veuillez réessayer"), @@ -1482,7 +1493,7 @@ class MessageLookup extends MessageLookupByLibrary { "verify": MessageLookupByLibrary.simpleMessage("Vérifier"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Vérifier l\'email"), - "verifyEmailID": m64, + "verifyEmailID": m66, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Vérifier"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Vérifier le mot de passe"), @@ -1511,11 +1522,11 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Nous ne prenons pas en charge l\'édition des photos et des albums que vous ne possédez pas encore"), - "weHaveSendEmailTo": m65, + "weHaveSendEmailTo": m67, "weakStrength": MessageLookupByLibrary.simpleMessage("Securité Faible"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bienvenue !"), "yearly": MessageLookupByLibrary.simpleMessage("Annuel"), - "yearsAgo": m66, + "yearsAgo": m68, "yes": MessageLookupByLibrary.simpleMessage("Oui"), "yesCancel": MessageLookupByLibrary.simpleMessage("Oui, annuler"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage( @@ -1546,7 +1557,7 @@ class MessageLookup extends MessageLookupByLibrary { "Vous ne pouvez pas partager avec vous-même"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "Vous n\'avez aucun élément archivé."), - "youHaveSuccessfullyFreedUp": m67, + "youHaveSuccessfullyFreedUp": m69, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Votre compte a été supprimé"), "yourMap": MessageLookupByLibrary.simpleMessage("Votre carte"), diff --git a/mobile/lib/generated/intl/messages_it.dart b/mobile/lib/generated/intl/messages_it.dart index d18386043e..8b9b28b35b 100644 --- a/mobile/lib/generated/intl/messages_it.dart +++ b/mobile/lib/generated/intl/messages_it.dart @@ -21,24 +21,30 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'it'; static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m2(count) => "${Intl.plural(count, one: 'Aggiungi elemento', other: 'Aggiungi elementi')}"; - static String m2(emailOrName) => "Aggiunto da ${emailOrName}"; + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + + static String m4(emailOrName) => "Aggiunto da ${emailOrName}"; - static String m3(albumName) => "Aggiunto con successo su ${albumName}"; + static String m5(albumName) => "Aggiunto con successo su ${albumName}"; - static String m4(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Nessun partecipante', one: '1 Partecipante', other: '${count} Partecipanti')}"; - static String m5(versionValue) => "Versione: ${versionValue}"; + static String m7(versionValue) => "Versione: ${versionValue}"; - static String m6(paymentProvider) => + static String m8(paymentProvider) => "Annulla prima il tuo abbonamento esistente da ${paymentProvider}"; - static String m7(user) => + static String m9(user) => "${user} non sarà più in grado di aggiungere altre foto a questo album\n\nSarà ancora in grado di rimuovere le foto esistenti aggiunte da lui o lei"; - static String m8(isFamilyMember, storageAmountInGb) => + static String m10(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Il tuo piano famiglia ha già richiesto ${storageAmountInGb} GB finora', @@ -46,158 +52,158 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Hai già richiesto ${storageAmountInGb} GB finora!', })}"; - static String m9(albumName) => "Link collaborativo creato per ${albumName}"; + static String m11(albumName) => "Link collaborativo creato per ${albumName}"; - static String m10(familyAdminEmail) => + static String m12(familyAdminEmail) => "Contatta ${familyAdminEmail} per gestire il tuo abbonamento"; - static String m11(provider) => + static String m13(provider) => "Scrivi all\'indirizzo support@ente.io per gestire il tuo abbonamento ${provider}."; - static String m12(count) => + static String m14(count) => "${Intl.plural(count, one: 'Elimina ${count} elemento', other: 'Elimina ${count} elementi')}"; - static String m13(currentlyDeleting, totalCount) => + static String m15(currentlyDeleting, totalCount) => "Eliminazione di ${currentlyDeleting} / ${totalCount}"; - static String m14(albumName) => + static String m16(albumName) => "Questo rimuoverà il link pubblico per accedere a \"${albumName}\"."; - static String m15(supportEmail) => + static String m17(supportEmail) => "Per favore invia un\'email a ${supportEmail} dall\'indirizzo email con cui ti sei registrato"; - static String m16(count, storageSaved) => + static String m18(count, storageSaved) => "Hai ripulito ${Intl.plural(count, one: '${count} doppione', other: '${count} doppioni')}, salvando (${storageSaved}!)"; - static String m17(count, formattedSize) => + static String m19(count, formattedSize) => "${count} file, ${formattedSize} l\'uno"; - static String m18(newEmail) => "Email cambiata in ${newEmail}"; + static String m20(newEmail) => "Email cambiata in ${newEmail}"; - static String m19(email) => + static String m21(email) => "${email} non ha un account su ente.\n\nInvia un invito per condividere foto."; - static String m20(count, formattedNumber) => + static String m22(count, formattedNumber) => "${Intl.plural(count, one: '1 file', other: '${formattedNumber} file')} di quest\'album sono stati salvati in modo sicuro"; - static String m21(count, formattedNumber) => + static String m23(count, formattedNumber) => "${Intl.plural(count, one: '1 file', other: '${formattedNumber} file')} di quest\'album sono stati salvati in modo sicuro"; - static String m22(storageAmountInGB) => + static String m24(storageAmountInGB) => "${storageAmountInGB} GB ogni volta che qualcuno si iscrive a un piano a pagamento e applica il tuo codice"; - static String m23(freeAmount, storageUnit) => + static String m25(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} liberi"; - static String m24(endDate) => "La prova gratuita termina il ${endDate}"; + static String m26(endDate) => "La prova gratuita termina il ${endDate}"; - static String m25(count) => + static String m27(count) => "Puoi ancora accedere a ${Intl.plural(count, one: '', other: 'loro')} su ente finché hai un abbonamento attivo"; - static String m26(sizeInMBorGB) => "Libera ${sizeInMBorGB}"; + static String m28(sizeInMBorGB) => "Libera ${sizeInMBorGB}"; - static String m27(count, formattedSize) => + static String m29(count, formattedSize) => "${Intl.plural(count, one: 'Può essere cancellata per liberare ${formattedSize}', other: 'Possono essere cancellati per liberare ${formattedSize}')}"; - static String m29(count) => + static String m31(count) => "${Intl.plural(count, one: '${count} elemento', other: '${count} elementi')}"; - static String m30(expiryTime) => "Il link scadrà il ${expiryTime}"; + static String m32(expiryTime) => "Il link scadrà il ${expiryTime}"; - static String m31(count, formattedCount) => + static String m33(count, formattedCount) => "${Intl.plural(count, one: '${formattedCount} ricordo', other: '${formattedCount} ricordi')}"; - static String m32(count) => + static String m34(count) => "${Intl.plural(count, one: 'Sposta elemento', other: 'Sposta elementi')}"; - static String m33(albumName) => "Spostato con successo su ${albumName}"; + static String m35(albumName) => "Spostato con successo su ${albumName}"; - static String m34(passwordStrengthValue) => + static String m36(passwordStrengthValue) => "Sicurezza password: ${passwordStrengthValue}"; - static String m35(providerName) => + static String m37(providerName) => "Si prega di parlare con il supporto di ${providerName} se ti è stato addebitato qualcosa"; - static String m36(reason) => + static String m38(reason) => "Purtroppo il tuo pagamento non è riuscito a causa di ${reason}"; - static String m37(endDate) => + static String m39(endDate) => "Prova gratuita valida fino al ${endDate}.\nPuoi scegliere un piano a pagamento in seguito."; - static String m38(toEmail) => "Per favore invia un\'email a ${toEmail}"; + static String m40(toEmail) => "Per favore invia un\'email a ${toEmail}"; - static String m39(toEmail) => "Invia i log a \n${toEmail}"; + static String m41(toEmail) => "Invia i log a \n${toEmail}"; - static String m40(storeName) => "Valutaci su ${storeName}"; + static String m42(storeName) => "Valutaci su ${storeName}"; - static String m41(storageInGB) => + static String m43(storageInGB) => "3. Ottenete entrambi ${storageInGB} GB* gratis"; - static String m42(userEmail) => + static String m44(userEmail) => "${userEmail} verrà rimosso da questo album condiviso\n\nQualsiasi foto aggiunta dall\'utente verrà rimossa dall\'album"; - static String m43(endDate) => "Si rinnova il ${endDate}"; + static String m45(endDate) => "Si rinnova il ${endDate}"; - static String m45(count) => "${count} selezionati"; + static String m47(count) => "${count} selezionati"; - static String m46(count, yourCount) => + static String m48(count, yourCount) => "${count} selezionato (${yourCount} tuoi)"; - static String m47(verificationID) => + static String m49(verificationID) => "Ecco il mio ID di verifica: ${verificationID} per ente.io."; - static String m48(verificationID) => + static String m50(verificationID) => "Hey, puoi confermare che questo è il tuo ID di verifica: ${verificationID} su ente.io"; - static String m49(referralCode, referralStorageInGB) => + static String m51(referralCode, referralStorageInGB) => "ente referral code: ${referralCode} \n\nApplicalo in Impostazioni → Generale → Referral per ottenere ${referralStorageInGB} GB gratis dopo la registrazione di un piano a pagamento\n\nhttps://ente.io"; - static String m50(numberOfPeople) => + static String m52(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Condividi con persone specifiche', one: 'Condividi con una persona', other: 'Condividi con ${numberOfPeople} persone')}"; - static String m51(emailIDs) => "Condiviso con ${emailIDs}"; + static String m53(emailIDs) => "Condiviso con ${emailIDs}"; - static String m52(fileType) => + static String m54(fileType) => "Questo ${fileType} verrà eliminato dal tuo dispositivo."; - static String m53(fileType) => + static String m55(fileType) => "Questo ${fileType} è sia su ente che sul tuo dispositivo."; - static String m54(fileType) => "Questo ${fileType} verrà eliminato su ente."; + static String m56(fileType) => "Questo ${fileType} verrà eliminato su ente."; - static String m55(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m56( + static String m58( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} di ${totalAmount} ${totalStorageUnit} utilizzati"; - static String m57(id) => + static String m59(id) => "Il tuo ${id} è già collegato ad un altro account ente.\nSe desideri utilizzare il tuo ${id} con questo account, contatta il nostro supporto\'\'"; - static String m58(endDate) => "L\'abbonamento verrà cancellato il ${endDate}"; + static String m60(endDate) => "L\'abbonamento verrà cancellato il ${endDate}"; - static String m59(completed, total) => + static String m61(completed, total) => "${completed}/${total} ricordi conservati"; - static String m60(storageAmountInGB) => + static String m62(storageAmountInGB) => "Anche loro riceveranno ${storageAmountInGB} GB"; - static String m61(email) => "Questo è l\'ID di verifica di ${email}"; + static String m63(email) => "Questo è l\'ID di verifica di ${email}"; - static String m62(count) => + static String m64(count) => "${Intl.plural(count, zero: '', one: '1 giorno', other: '${count} giorni')}"; - static String m63(endDate) => "Valido fino al ${endDate}"; + static String m65(endDate) => "Valido fino al ${endDate}"; - static String m64(email) => "Verifica ${email}"; + static String m66(email) => "Verifica ${email}"; - static String m65(email) => + static String m67(email) => "Abbiamo inviato una mail a ${email}"; - static String m66(count) => + static String m68(count) => "${Intl.plural(count, one: '${count} anno fa', other: '${count} anni fa')}"; - static String m67(storageSaved) => + static String m69(storageSaved) => "Hai liberato con successo ${storageSaved}!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -216,9 +222,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Aggiungi una nuova email"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Aggiungi collaboratore"), + "addCollaborators": m0, "addFromDevice": MessageLookupByLibrary.simpleMessage("Aggiungi dal dispositivo"), - "addItem": m0, + "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("Aggiungi luogo"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Aggiungi"), "addMore": MessageLookupByLibrary.simpleMessage("Aggiungi altri"), @@ -235,9 +242,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Aggiungi ad album nascosto"), "addViewer": MessageLookupByLibrary.simpleMessage("Aggiungi in sola lettura"), + "addViewers": m1, "addedAs": MessageLookupByLibrary.simpleMessage("Aggiunto come"), - "addedBy": m2, - "addedSuccessfullyTo": m3, + "addedBy": m4, + "addedSuccessfullyTo": m5, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Aggiunto ai preferiti..."), "advanced": MessageLookupByLibrary.simpleMessage("Avanzate"), @@ -249,7 +257,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Dopo una settimana"), "after1Year": MessageLookupByLibrary.simpleMessage("Dopo un anno"), "albumOwner": MessageLookupByLibrary.simpleMessage("Proprietario"), - "albumParticipantsCount": m4, + "albumParticipantsCount": m6, "albumTitle": MessageLookupByLibrary.simpleMessage("Titolo album"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album aggiornato"), @@ -286,7 +294,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Android, iOS, Web, Desktop"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("Autenticazione necessaria"), - "appVersion": m5, + "appVersion": m7, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Applica"), "applyCodeTitle": @@ -370,10 +378,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Puoi rimuovere solo i file di tua proprietà"), "cancel": MessageLookupByLibrary.simpleMessage("Annulla"), - "cancelOtherSubscription": m6, + "cancelOtherSubscription": m8, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Annulla abbonamento"), - "cannotAddMorePhotosAfterBecomingViewer": m7, + "cannotAddMorePhotosAfterBecomingViewer": m9, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Impossibile eliminare i file condivisi"), "centerPoint": MessageLookupByLibrary.simpleMessage("Punto centrale"), @@ -396,7 +404,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Richiedi spazio gratuito"), "claimMore": MessageLookupByLibrary.simpleMessage("Richiedine di più!"), "claimed": MessageLookupByLibrary.simpleMessage("Riscattato"), - "claimedStorageSoFar": m8, + "claimedStorageSoFar": m10, "clearCaches": MessageLookupByLibrary.simpleMessage("Svuota cache"), "click": MessageLookupByLibrary.simpleMessage("• Clic"), "clickOnTheOverflowMenu": @@ -416,7 +424,7 @@ class MessageLookup extends MessageLookupByLibrary { "Crea un link per consentire alle persone di aggiungere e visualizzare foto nel tuo album condiviso senza bisogno di un\'applicazione o di un account ente. Ottimo per raccogliere foto di un evento."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Link collaborativo"), - "collaborativeLinkCreatedFor": m9, + "collaborativeLinkCreatedFor": m11, "collaborator": MessageLookupByLibrary.simpleMessage("Collaboratore"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -444,10 +452,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Conferma chiave di recupero"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Conferma la tua chiave di recupero"), - "contactFamilyAdmin": m10, + "contactFamilyAdmin": m12, "contactSupport": MessageLookupByLibrary.simpleMessage("Contatta il supporto"), - "contactToManageSubscription": m11, + "contactToManageSubscription": m13, "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continua"), "continueOnFreeTrial": @@ -523,11 +531,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Elimina dal dispositivo"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Elimina da ente"), - "deleteItemCount": m12, + "deleteItemCount": m14, "deleteLocation": MessageLookupByLibrary.simpleMessage("Elimina posizione"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Elimina foto"), - "deleteProgress": m13, + "deleteProgress": m15, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Manca una caratteristica chiave di cui ho bisogno"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -561,7 +569,7 @@ class MessageLookup extends MessageLookupByLibrary { "I visualizzatori possono scattare screenshot o salvare una copia delle foto utilizzando strumenti esterni"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Nota bene"), - "disableLinkMessage": m14, + "disableLinkMessage": m16, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Disabilita autenticazione a due fattori"), "disablingTwofactorAuthentication": @@ -582,9 +590,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Scaricamento fallito"), "downloading": MessageLookupByLibrary.simpleMessage("Scaricamento in corso..."), - "dropSupportEmail": m15, - "duplicateFileCountWithStorageSaved": m16, - "duplicateItemsGroup": m17, + "dropSupportEmail": m17, + "duplicateFileCountWithStorageSaved": m18, + "duplicateItemsGroup": m19, "edit": MessageLookupByLibrary.simpleMessage("Modifica"), "editLocation": MessageLookupByLibrary.simpleMessage("Edit location"), "editLocationTagTitle": @@ -595,8 +603,8 @@ class MessageLookup extends MessageLookupByLibrary { "Edits to location will only be seen within Ente"), "eligible": MessageLookupByLibrary.simpleMessage("idoneo"), "email": MessageLookupByLibrary.simpleMessage("Email"), - "emailChangedTo": m18, - "emailNoEnteAccount": m19, + "emailChangedTo": m20, + "emailNoEnteAccount": m21, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Verifica Email"), "emailYourLogs": MessageLookupByLibrary.simpleMessage( @@ -689,8 +697,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Aggiungi descrizione..."), "fileSavedToGallery": MessageLookupByLibrary.simpleMessage("File salvato nella galleria"), - "filesBackedUpFromDevice": m20, - "filesBackedUpInAlbum": m21, + "filesBackedUpFromDevice": m22, + "filesBackedUpInAlbum": m23, "filesDeleted": MessageLookupByLibrary.simpleMessage("File eliminati"), "flip": MessageLookupByLibrary.simpleMessage("Capovolgi"), "forYourMemories": @@ -699,18 +707,18 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Password dimenticata"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Spazio gratuito richiesto"), - "freeStorageOnReferralSuccess": m22, - "freeStorageSpace": m23, + "freeStorageOnReferralSuccess": m24, + "freeStorageSpace": m25, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Spazio libero utilizzabile"), "freeTrial": MessageLookupByLibrary.simpleMessage("Prova gratuita"), - "freeTrialValidTill": m24, - "freeUpAccessPostDelete": m25, - "freeUpAmount": m26, + "freeTrialValidTill": m26, + "freeUpAccessPostDelete": m27, + "freeUpAmount": m28, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Libera spazio"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Libera spazio"), - "freeUpSpaceSaving": m27, + "freeUpSpaceSaving": m29, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Fino a 1000 ricordi mostrati nella galleria"), "general": MessageLookupByLibrary.simpleMessage("Generali"), @@ -775,7 +783,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Sembra che qualcosa sia andato storto. Riprova tra un po\'. Se l\'errore persiste, contatta il nostro team di supporto."), - "itemCount": m29, + "itemCount": m31, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Gli elementi mostrano il numero di giorni rimanenti prima della cancellazione permanente"), @@ -804,7 +812,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Limite dei dispositivi"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Attivato"), "linkExpired": MessageLookupByLibrary.simpleMessage("Scaduto"), - "linkExpiresOn": m30, + "linkExpiresOn": m32, "linkExpiry": MessageLookupByLibrary.simpleMessage("Scadenza del link"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("Il link è scaduto"), @@ -852,6 +860,9 @@ class MessageLookup extends MessageLookupByLibrary { "logout": MessageLookupByLibrary.simpleMessage("Disconnetti"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( "Invia i log per aiutarci a risolvere il tuo problema. Si prega di notare che i nomi dei file saranno inclusi per aiutare a tenere traccia di problemi con file specifici."), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( "Premi a lungo su un elemento per visualizzarlo a schermo intero"), @@ -870,7 +881,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Mappe"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m31, + "memoryCount": m33, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("Mobile, Web, Desktop"), @@ -879,12 +890,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Modify your query, or try searching for"), "monthly": MessageLookupByLibrary.simpleMessage("Mensile"), - "moveItem": m32, + "moveItem": m34, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Sposta nell\'album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Sposta in album nascosto"), - "movedSuccessfullyTo": m33, + "movedSuccessfullyTo": m35, "movedToTrash": MessageLookupByLibrary.simpleMessage("Spostato nel cestino"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -948,15 +959,15 @@ class MessageLookup extends MessageLookupByLibrary { "Password modificata con successo"), "passwordLock": MessageLookupByLibrary.simpleMessage("Blocco con password"), - "passwordStrength": m34, + "passwordStrength": m36, "passwordWarning": MessageLookupByLibrary.simpleMessage( "Noi non memorizziamo la tua password, quindi se te la dimentichi, non possiamo decriptare i tuoi dati"), "paymentDetails": MessageLookupByLibrary.simpleMessage("Dettagli di Pagamento"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Pagamento non riuscito"), - "paymentFailedTalkToProvider": m35, - "paymentFailedWithReason": m36, + "paymentFailedTalkToProvider": m37, + "paymentFailedWithReason": m38, "pendingSync": MessageLookupByLibrary.simpleMessage("Sincronizzazione in sospeso"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage( @@ -976,7 +987,7 @@ class MessageLookup extends MessageLookupByLibrary { "pickCenterPoint": MessageLookupByLibrary.simpleMessage( "Selezionare il punto centrale"), "pinAlbum": MessageLookupByLibrary.simpleMessage("Fissa l\'album"), - "playStoreFreeTrialValidTill": m37, + "playStoreFreeTrialValidTill": m39, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Abbonamento su PlayStore"), "pleaseContactSupportAndWeWillBeHappyToHelp": @@ -985,12 +996,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Riprova. Se il problema persiste, ti invitiamo a contattare l\'assistenza"), - "pleaseEmailUsAt": m38, + "pleaseEmailUsAt": m40, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Concedi i permessi"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( "Effettua nuovamente l\'accesso"), - "pleaseSendTheLogsTo": m39, + "pleaseSendTheLogsTo": m41, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Riprova"), "pleaseVerifyTheCodeYouHaveEntered": MessageLookupByLibrary.simpleMessage( @@ -1024,7 +1035,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Invia ticket"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Valuta l\'app"), "rateUs": MessageLookupByLibrary.simpleMessage("Lascia una recensione"), - "rateUsOnStore": m40, + "rateUsOnStore": m42, "recover": MessageLookupByLibrary.simpleMessage("Recupera"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recupera account"), @@ -1056,7 +1067,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Condividi questo codice con i tuoi amici"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Si iscrivono per un piano a pagamento"), - "referralStep3": m41, + "referralStep3": m43, "referrals": MessageLookupByLibrary.simpleMessage("Invita un Amico"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "I referral code sono attualmente in pausa"), @@ -1080,7 +1091,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Elimina link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Rimuovi partecipante"), - "removeParticipantBody": m42, + "removeParticipantBody": m44, "removePublicLink": MessageLookupByLibrary.simpleMessage("Rimuovi link pubblico"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1094,7 +1105,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Rinomina file"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Rinnova abbonamento"), - "renewsOn": m43, + "renewsOn": m45, "reportABug": MessageLookupByLibrary.simpleMessage("Segnala un bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Segnala un bug"), "resendEmail": MessageLookupByLibrary.simpleMessage("Rinvia email"), @@ -1159,8 +1170,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Gli elementi selezionati verranno eliminati da tutti gli album e spostati nel cestino."), - "selectedPhotos": m45, - "selectedPhotosWithYours": m46, + "selectedPhotos": m47, + "selectedPhotosWithYours": m48, "send": MessageLookupByLibrary.simpleMessage("Invia"), "sendEmail": MessageLookupByLibrary.simpleMessage("Invia email"), "sendInvite": MessageLookupByLibrary.simpleMessage("Invita"), @@ -1184,16 +1195,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Condividi un album"), "shareLink": MessageLookupByLibrary.simpleMessage("Condividi link"), - "shareMyVerificationID": m47, + "shareMyVerificationID": m49, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Condividi solo con le persone che vuoi"), - "shareTextConfirmOthersVerificationID": m48, + "shareTextConfirmOthersVerificationID": m50, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Scarica ente in modo da poter facilmente condividere foto e video senza perdita di qualità\n\nhttps://ente.io"), - "shareTextReferralCode": m49, + "shareTextReferralCode": m51, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Condividi con utenti che non hanno un account ente"), - "shareWithPeopleSectionTitle": m50, + "shareWithPeopleSectionTitle": m52, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Condividi il tuo primo album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1204,7 +1215,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nuove foto condivise"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Ricevi notifiche quando qualcuno aggiunge una foto a un album condiviso, di cui fai parte"), - "sharedWith": m51, + "sharedWith": m53, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Condivisi con me"), "sharedWithYou": @@ -1214,11 +1225,11 @@ class MessageLookup extends MessageLookupByLibrary { "showMemories": MessageLookupByLibrary.simpleMessage("Mostra ricordi"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Accetto i termini di servizio e la politica sulla privacy"), - "singleFileDeleteFromDevice": m52, + "singleFileDeleteFromDevice": m54, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Verrà eliminato da tutti gli album."), - "singleFileInBothLocalAndRemote": m53, - "singleFileInRemoteOnly": m54, + "singleFileInBothLocalAndRemote": m55, + "singleFileInRemoteOnly": m56, "skip": MessageLookupByLibrary.simpleMessage("Salta"), "social": MessageLookupByLibrary.simpleMessage("Social"), "someItemsAreInBothEnteAndYourDevice": @@ -1259,13 +1270,13 @@ class MessageLookup extends MessageLookupByLibrary { "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Famiglia"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Tu"), - "storageInGB": m55, + "storageInGB": m57, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Limite d\'archiviazione superato"), - "storageUsageInfo": m56, + "storageUsageInfo": m58, "strongStrength": MessageLookupByLibrary.simpleMessage("Forte"), - "subAlreadyLinkedErrMessage": m57, - "subWillBeCancelledOn": m58, + "subAlreadyLinkedErrMessage": m59, + "subWillBeCancelledOn": m60, "subscribe": MessageLookupByLibrary.simpleMessage("Iscriviti"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Sembra che il tuo abbonamento sia scaduto. Iscriviti per abilitare la condivisione."), @@ -1282,7 +1293,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Suggerisci una funzionalità"), "support": MessageLookupByLibrary.simpleMessage("Assistenza"), - "syncProgress": m59, + "syncProgress": m61, "syncStopped": MessageLookupByLibrary.simpleMessage("Sincronizzazione interrotta"), "syncing": MessageLookupByLibrary.simpleMessage( @@ -1311,7 +1322,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Questi file verranno eliminati dal tuo dispositivo."), - "theyAlsoGetXGb": m60, + "theyAlsoGetXGb": m62, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Verranno eliminati da tutti gli album."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1328,7 +1339,7 @@ class MessageLookup extends MessageLookupByLibrary { "Questo indirizzo email è già registrato"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Questa immagine non ha dati EXIF"), - "thisIsPersonVerificationId": m61, + "thisIsPersonVerificationId": m63, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Questo è il tuo ID di verifica"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1344,7 +1355,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("totale"), "totalSize": MessageLookupByLibrary.simpleMessage("Dimensioni totali"), "trash": MessageLookupByLibrary.simpleMessage("Cestino"), - "trashDaysLeft": m62, + "trashDaysLeft": m64, "tryAgain": MessageLookupByLibrary.simpleMessage("Riprova"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Attiva il backup per caricare automaticamente i file aggiunti in questa cartella del dispositivo su ente."), @@ -1401,7 +1412,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Usa la foto selezionata"), "usedSpace": MessageLookupByLibrary.simpleMessage("Spazio utilizzato"), - "validTill": m63, + "validTill": m65, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verifica fallita, per favore prova di nuovo"), @@ -1409,7 +1420,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("ID di verifica"), "verify": MessageLookupByLibrary.simpleMessage("Verifica"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Verifica email"), - "verifyEmailID": m64, + "verifyEmailID": m66, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verifica"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Verifica password"), @@ -1436,11 +1447,11 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Non puoi modificare foto e album che non possiedi"), - "weHaveSendEmailTo": m65, + "weHaveSendEmailTo": m67, "weakStrength": MessageLookupByLibrary.simpleMessage("Debole"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bentornato/a!"), "yearly": MessageLookupByLibrary.simpleMessage("Annuale"), - "yearsAgo": m66, + "yearsAgo": m68, "yes": MessageLookupByLibrary.simpleMessage("Si"), "yesCancel": MessageLookupByLibrary.simpleMessage("Sì, cancella"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage( @@ -1470,7 +1481,7 @@ class MessageLookup extends MessageLookupByLibrary { "Non puoi condividere con te stesso"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "Non hai nulla di archiviato."), - "youHaveSuccessfullyFreedUp": m67, + "youHaveSuccessfullyFreedUp": m69, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage( "Il tuo account è stato eliminato"), "yourMap": MessageLookupByLibrary.simpleMessage("Your map"), diff --git a/mobile/lib/generated/intl/messages_ko.dart b/mobile/lib/generated/intl/messages_ko.dart index a97232febc..83d8495a04 100644 --- a/mobile/lib/generated/intl/messages_ko.dart +++ b/mobile/lib/generated/intl/messages_ko.dart @@ -20,10 +20,18 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ko'; + static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { + "addCollaborators": m0, "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), + "addViewers": m1, "changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage( "Change location of selected items?"), "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), @@ -37,6 +45,9 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), "joinDiscord": MessageLookupByLibrary.simpleMessage("Join Discord"), "locations": MessageLookupByLibrary.simpleMessage("Locations"), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "modifyYourQueryOrTrySearchingFor": MessageLookupByLibrary.simpleMessage( "Modify your query, or try searching for"), diff --git a/mobile/lib/generated/intl/messages_nl.dart b/mobile/lib/generated/intl/messages_nl.dart index 1a54922240..1f53a6ffe4 100644 --- a/mobile/lib/generated/intl/messages_nl.dart +++ b/mobile/lib/generated/intl/messages_nl.dart @@ -21,27 +21,33 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'nl'; static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m2(count) => "${Intl.plural(count, one: 'Bestand toevoegen', other: 'Bestanden toevoegen')}"; - static String m1(storageAmount, endDate) => + static String m3(storageAmount, endDate) => "Jouw ${storageAmount} add-on is geldig tot ${endDate}"; - static String m2(emailOrName) => "Toegevoegd door ${emailOrName}"; + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + + static String m4(emailOrName) => "Toegevoegd door ${emailOrName}"; - static String m3(albumName) => "Succesvol toegevoegd aan ${albumName}"; + static String m5(albumName) => "Succesvol toegevoegd aan ${albumName}"; - static String m4(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Geen deelnemers', one: '1 deelnemer', other: '${count} deelnemers')}"; - static String m5(versionValue) => "Versie: ${versionValue}"; + static String m7(versionValue) => "Versie: ${versionValue}"; - static String m6(paymentProvider) => + static String m8(paymentProvider) => "Annuleer eerst uw bestaande abonnement bij ${paymentProvider}"; - static String m7(user) => + static String m9(user) => "${user} zal geen foto\'s meer kunnen toevoegen aan dit album\n\nDe gebruiker zal nog steeds bestaande foto\'s kunnen verwijderen die door hen zijn toegevoegd"; - static String m8(isFamilyMember, storageAmountInGb) => + static String m10(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Jouw familie heeft ${storageAmountInGb} GB geclaimd tot nu toe', @@ -49,167 +55,167 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Je hebt ${storageAmountInGb} GB geclaimd tot nu toe!', })}"; - static String m9(albumName) => + static String m11(albumName) => "Gezamenlijke link aangemaakt voor ${albumName}"; - static String m10(familyAdminEmail) => + static String m12(familyAdminEmail) => "Neem contact op met ${familyAdminEmail} om uw abonnement te beheren"; - static String m11(provider) => + static String m13(provider) => "Neem contact met ons op via support@ente.io om uw ${provider} abonnement te beheren."; - static String m12(count) => + static String m14(count) => "${Intl.plural(count, one: 'Verwijder ${count} bestand', other: 'Verwijder ${count} bestanden')}"; - static String m13(currentlyDeleting, totalCount) => + static String m15(currentlyDeleting, totalCount) => "Verwijderen van ${currentlyDeleting} / ${totalCount}"; - static String m14(albumName) => + static String m16(albumName) => "Dit verwijdert de openbare link voor toegang tot \"${albumName}\"."; - static String m15(supportEmail) => + static String m17(supportEmail) => "Stuur een e-mail naar ${supportEmail} vanaf het door jou geregistreerde e-mailadres"; - static String m16(count, storageSaved) => + static String m18(count, storageSaved) => "Je hebt ${Intl.plural(count, one: '${count} dubbel bestand', other: '${count} dubbele bestanden')} opgeruimd, totaal (${storageSaved}!)"; - static String m17(count, formattedSize) => + static String m19(count, formattedSize) => "${count} bestanden, elk ${formattedSize}"; - static String m18(newEmail) => "E-mailadres gewijzigd naar ${newEmail}"; + static String m20(newEmail) => "E-mailadres gewijzigd naar ${newEmail}"; - static String m19(email) => + static String m21(email) => "${email} heeft geen ente account.\n\nStuur ze een uitnodiging om foto\'s te delen."; - static String m20(count, formattedNumber) => + static String m22(count, formattedNumber) => "${Intl.plural(count, one: '1 bestand', other: '${formattedNumber} bestanden')} in dit album zijn veilig geback-upt"; - static String m21(count, formattedNumber) => + static String m23(count, formattedNumber) => "${Intl.plural(count, one: '1 bestand', other: '${formattedNumber} bestanden')} in dit album is veilig geback-upt"; - static String m22(storageAmountInGB) => + static String m24(storageAmountInGB) => "${storageAmountInGB} GB telkens als iemand zich aanmeldt voor een betaald abonnement en je code toepast"; - static String m23(freeAmount, storageUnit) => + static String m25(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} vrij"; - static String m24(endDate) => "Gratis proefversie geldig tot ${endDate}"; + static String m26(endDate) => "Gratis proefversie geldig tot ${endDate}"; - static String m25(count) => + static String m27(count) => "U heeft nog steeds toegang tot ${Intl.plural(count, one: 'het', other: 'ze')} op ente zolang u een actief abonnement heeft"; - static String m26(sizeInMBorGB) => "Maak ${sizeInMBorGB} vrij"; + static String m28(sizeInMBorGB) => "Maak ${sizeInMBorGB} vrij"; - static String m27(count, formattedSize) => + static String m29(count, formattedSize) => "${Intl.plural(count, one: 'Het kan verwijderd worden van het apparaat om ${formattedSize} vrij te maken', other: 'Ze kunnen verwijderd worden van het apparaat om ${formattedSize} vrij te maken')}"; - static String m28(currentlyProcessing, totalCount) => + static String m30(currentlyProcessing, totalCount) => "Verwerken van ${currentlyProcessing} / ${totalCount}"; - static String m29(count) => + static String m31(count) => "${Intl.plural(count, one: '${count} item', other: '${count} items')}"; - static String m30(expiryTime) => "Link vervalt op ${expiryTime}"; + static String m32(expiryTime) => "Link vervalt op ${expiryTime}"; - static String m31(count, formattedCount) => + static String m33(count, formattedCount) => "${Intl.plural(count, zero: 'geen herinneringen', one: '${formattedCount} herinnering', other: '${formattedCount} herinneringen')}"; - static String m32(count) => + static String m34(count) => "${Intl.plural(count, one: 'Bestand verplaatsen', other: 'Bestanden verplaatsen')}"; - static String m33(albumName) => "Succesvol verplaatst naar ${albumName}"; + static String m35(albumName) => "Succesvol verplaatst naar ${albumName}"; - static String m34(passwordStrengthValue) => + static String m36(passwordStrengthValue) => "Wachtwoord sterkte: ${passwordStrengthValue}"; - static String m35(providerName) => + static String m37(providerName) => "Praat met ${providerName} klantenservice als u in rekening bent gebracht"; - static String m36(reason) => + static String m38(reason) => "Helaas is uw betaling mislukt vanwege ${reason}"; - static String m37(endDate) => + static String m39(endDate) => "Gratis proefperiode geldig tot ${endDate}.\nU kunt naderhand een betaald abonnement kiezen."; - static String m38(toEmail) => "Stuur ons een e-mail op ${toEmail}"; + static String m40(toEmail) => "Stuur ons een e-mail op ${toEmail}"; - static String m39(toEmail) => + static String m41(toEmail) => "Verstuur de logboeken alstublieft naar ${toEmail}"; - static String m40(storeName) => "Beoordeel ons op ${storeName}"; + static String m42(storeName) => "Beoordeel ons op ${storeName}"; - static String m41(storageInGB) => + static String m43(storageInGB) => "Jullie krijgen allebei ${storageInGB} GB* gratis"; - static String m42(userEmail) => + static String m44(userEmail) => "${userEmail} zal worden verwijderd uit dit gedeelde album\n\nAlle door hen toegevoegde foto\'s worden ook uit het album verwijderd"; - static String m43(endDate) => "Wordt verlengd op ${endDate}"; + static String m45(endDate) => "Wordt verlengd op ${endDate}"; - static String m44(count) => + static String m46(count) => "${Intl.plural(count, one: '${count} resultaat gevonden', other: '${count} resultaten gevonden')}"; - static String m45(count) => "${count} geselecteerd"; + static String m47(count) => "${count} geselecteerd"; - static String m46(count, yourCount) => + static String m48(count, yourCount) => "${count} geselecteerd (${yourCount} van jou)"; - static String m47(verificationID) => + static String m49(verificationID) => "Hier is mijn verificatie-ID: ${verificationID} voor ente.io."; - static String m48(verificationID) => + static String m50(verificationID) => "Hey, kunt u bevestigen dat dit uw ente.io verificatie-ID is: ${verificationID}"; - static String m49(referralCode, referralStorageInGB) => + static String m51(referralCode, referralStorageInGB) => "ente verwijzingscode: ${referralCode} \n\nPas het toe bij Instellingen → Algemeen → Verwijzingen om ${referralStorageInGB} GB gratis te krijgen nadat je je hebt aangemeld voor een betaald abonnement\n\nhttps://ente.io"; - static String m50(numberOfPeople) => + static String m52(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Deel met specifieke mensen', one: 'Gedeeld met 1 persoon', other: 'Gedeeld met ${numberOfPeople} mensen')}"; - static String m51(emailIDs) => "Gedeeld met ${emailIDs}"; + static String m53(emailIDs) => "Gedeeld met ${emailIDs}"; - static String m52(fileType) => + static String m54(fileType) => "Deze ${fileType} zal worden verwijderd van jouw apparaat."; - static String m53(fileType) => + static String m55(fileType) => "Deze ${fileType} staat zowel in ente als op jouw apparaat."; - static String m54(fileType) => + static String m56(fileType) => "Deze ${fileType} zal worden verwijderd uit ente."; - static String m55(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m56( + static String m58( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} van ${totalAmount} ${totalStorageUnit} gebruikt"; - static String m57(id) => + static String m59(id) => "Uw ${id} is al aan een ander ente account gekoppeld.\nAls u uw ${id} wilt gebruiken met dit account, neem dan contact op met onze klantenservice"; - static String m58(endDate) => "Uw abonnement loopt af op ${endDate}"; + static String m60(endDate) => "Uw abonnement loopt af op ${endDate}"; - static String m59(completed, total) => + static String m61(completed, total) => "${completed}/${total} herinneringen bewaard"; - static String m60(storageAmountInGB) => + static String m62(storageAmountInGB) => "Zij krijgen ook ${storageAmountInGB} GB"; - static String m61(email) => "Dit is de verificatie-ID van ${email}"; + static String m63(email) => "Dit is de verificatie-ID van ${email}"; - static String m62(count) => + static String m64(count) => "${Intl.plural(count, zero: '', one: '1 dag', other: '${count} dagen')}"; - static String m63(endDate) => "Geldig tot ${endDate}"; + static String m65(endDate) => "Geldig tot ${endDate}"; - static String m64(email) => "Verifieer ${email}"; + static String m66(email) => "Verifieer ${email}"; - static String m65(email) => + static String m67(email) => "We hebben een e-mail gestuurd naar ${email}"; - static String m66(count) => + static String m68(count) => "${Intl.plural(count, one: '${count} jaar geleden', other: '${count} jaar geleden')}"; - static String m67(storageSaved) => + static String m69(storageSaved) => "Je hebt ${storageSaved} succesvol vrijgemaakt!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -228,9 +234,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nieuw e-mailadres toevoegen"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Samenwerker toevoegen"), + "addCollaborators": m0, "addFromDevice": MessageLookupByLibrary.simpleMessage("Toevoegen vanaf apparaat"), - "addItem": m0, + "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("Locatie toevoegen"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Toevoegen"), @@ -238,7 +245,7 @@ class MessageLookup extends MessageLookupByLibrary { "addNew": MessageLookupByLibrary.simpleMessage("Nieuwe toevoegen"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Details van add-ons"), - "addOnValidTill": m1, + "addOnValidTill": m3, "addOns": MessageLookupByLibrary.simpleMessage("Add-ons"), "addPhotos": MessageLookupByLibrary.simpleMessage("Foto\'s toevoegen"), "addSelected": @@ -249,11 +256,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Toevoegen aan verborgen album"), "addViewer": MessageLookupByLibrary.simpleMessage("Voeg kijker toe"), + "addViewers": m1, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Voeg nu je foto\'s toe"), "addedAs": MessageLookupByLibrary.simpleMessage("Toegevoegd als"), - "addedBy": m2, - "addedSuccessfullyTo": m3, + "addedBy": m4, + "addedSuccessfullyTo": m5, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Toevoegen aan favorieten..."), "advanced": MessageLookupByLibrary.simpleMessage("Geavanceerd"), @@ -264,7 +272,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Na 1 week"), "after1Year": MessageLookupByLibrary.simpleMessage("Na 1 jaar"), "albumOwner": MessageLookupByLibrary.simpleMessage("Eigenaar"), - "albumParticipantsCount": m4, + "albumParticipantsCount": m6, "albumTitle": MessageLookupByLibrary.simpleMessage("Albumtitel"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album bijgewerkt"), @@ -300,7 +308,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Android, iOS, Web, Desktop"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("Verificatie vereist"), - "appVersion": m5, + "appVersion": m7, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Toepassen"), "applyCodeTitle": @@ -386,10 +394,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Kan alleen bestanden verwijderen die jouw eigendom zijn"), "cancel": MessageLookupByLibrary.simpleMessage("Annuleer"), - "cancelOtherSubscription": m6, + "cancelOtherSubscription": m8, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Abonnement opzeggen"), - "cannotAddMorePhotosAfterBecomingViewer": m7, + "cannotAddMorePhotosAfterBecomingViewer": m9, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Kan gedeelde bestanden niet verwijderen"), "castInstruction": MessageLookupByLibrary.simpleMessage( @@ -413,7 +421,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Claim gratis opslag"), "claimMore": MessageLookupByLibrary.simpleMessage("Claim meer!"), "claimed": MessageLookupByLibrary.simpleMessage("Geclaimd"), - "claimedStorageSoFar": m8, + "claimedStorageSoFar": m10, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Ongecategoriseerd opschonen"), "clearCaches": MessageLookupByLibrary.simpleMessage("Cache legen"), @@ -436,7 +444,7 @@ class MessageLookup extends MessageLookupByLibrary { "Maak een link waarmee mensen foto\'s in jouw gedeelde album kunnen toevoegen en bekijken zonder dat ze daarvoor een ente app of account nodig hebben. Handig voor het verzamelen van foto\'s van evenementen."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Gezamenlijke link"), - "collaborativeLinkCreatedFor": m9, + "collaborativeLinkCreatedFor": m11, "collaborator": MessageLookupByLibrary.simpleMessage("Samenwerker"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -464,10 +472,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Bevestig herstelsleutel"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage("Bevestig herstelsleutel"), - "contactFamilyAdmin": m10, + "contactFamilyAdmin": m12, "contactSupport": MessageLookupByLibrary.simpleMessage("Contacteer klantenservice"), - "contactToManageSubscription": m11, + "contactToManageSubscription": m13, "contacts": MessageLookupByLibrary.simpleMessage("Contacten"), "contents": MessageLookupByLibrary.simpleMessage("Inhoud"), "continueLabel": MessageLookupByLibrary.simpleMessage("Doorgaan"), @@ -544,12 +552,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Verwijder van apparaat"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Verwijder van ente"), - "deleteItemCount": m12, + "deleteItemCount": m14, "deleteLocation": MessageLookupByLibrary.simpleMessage("Verwijder locatie"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Foto\'s verwijderen"), - "deleteProgress": m13, + "deleteProgress": m15, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Ik mis een belangrijke functie"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -587,7 +595,7 @@ class MessageLookup extends MessageLookupByLibrary { "Kijkers kunnen nog steeds screenshots maken of een kopie van je foto\'s opslaan met behulp van externe tools"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Let op"), - "disableLinkMessage": m14, + "disableLinkMessage": m16, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Tweestapsverificatie uitschakelen"), "disablingTwofactorAuthentication": @@ -608,9 +616,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Download mislukt"), "downloading": MessageLookupByLibrary.simpleMessage("Downloaden..."), - "dropSupportEmail": m15, - "duplicateFileCountWithStorageSaved": m16, - "duplicateItemsGroup": m17, + "dropSupportEmail": m17, + "duplicateFileCountWithStorageSaved": m18, + "duplicateItemsGroup": m19, "edit": MessageLookupByLibrary.simpleMessage("Bewerken"), "editLocation": MessageLookupByLibrary.simpleMessage("Locatie bewerken"), @@ -623,8 +631,8 @@ class MessageLookup extends MessageLookupByLibrary { "Bewerkte locatie wordt alleen gezien binnen Ente"), "eligible": MessageLookupByLibrary.simpleMessage("gerechtigd"), "email": MessageLookupByLibrary.simpleMessage("E-mail"), - "emailChangedTo": m18, - "emailNoEnteAccount": m19, + "emailChangedTo": m20, + "emailNoEnteAccount": m21, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("E-mailverificatie"), "emailYourLogs": @@ -728,8 +736,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Bestandstype"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Bestandstypen en namen"), - "filesBackedUpFromDevice": m20, - "filesBackedUpInAlbum": m21, + "filesBackedUpFromDevice": m22, + "filesBackedUpInAlbum": m23, "filesDeleted": MessageLookupByLibrary.simpleMessage("Bestanden verwijderd"), "flip": MessageLookupByLibrary.simpleMessage("Omdraaien"), @@ -739,24 +747,24 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Wachtwoord vergeten"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Gratis opslag geclaimd"), - "freeStorageOnReferralSuccess": m22, - "freeStorageSpace": m23, + "freeStorageOnReferralSuccess": m24, + "freeStorageSpace": m25, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Gratis opslag bruikbaar"), "freeTrial": MessageLookupByLibrary.simpleMessage("Gratis proefversie"), - "freeTrialValidTill": m24, - "freeUpAccessPostDelete": m25, - "freeUpAmount": m26, + "freeTrialValidTill": m26, + "freeUpAccessPostDelete": m27, + "freeUpAmount": m28, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Apparaatruimte vrijmaken"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Ruimte vrijmaken"), - "freeUpSpaceSaving": m27, + "freeUpSpaceSaving": m29, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Tot 1000 herinneringen getoond in de galerij"), "general": MessageLookupByLibrary.simpleMessage("Algemeen"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Encryptiesleutels genereren..."), - "genericProgress": m28, + "genericProgress": m30, "goToSettings": MessageLookupByLibrary.simpleMessage("Ga naar instellingen"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), @@ -817,7 +825,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Het lijkt erop dat er iets fout is gegaan. Probeer het later opnieuw. Als de fout zich blijft voordoen, neem dan contact op met ons supportteam."), - "itemCount": m29, + "itemCount": m31, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Bestanden tonen het aantal resterende dagen voordat ze permanent worden verwijderd"), @@ -844,7 +852,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Apparaat limiet"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Ingeschakeld"), "linkExpired": MessageLookupByLibrary.simpleMessage("Verlopen"), - "linkExpiresOn": m30, + "linkExpiresOn": m32, "linkExpiry": MessageLookupByLibrary.simpleMessage("Vervaldatum"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("Link is vervallen"), @@ -893,6 +901,9 @@ class MessageLookup extends MessageLookupByLibrary { "logout": MessageLookupByLibrary.simpleMessage("Uitloggen"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( "Dit zal logboeken verzenden om ons te helpen uw probleem op te lossen. Houd er rekening mee dat bestandsnamen zullen worden meegenomen om problemen met specifieke bestanden bij te houden."), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( "Houd een bestand lang ingedrukt om te bekijken op volledig scherm"), "lostDevice": @@ -916,7 +927,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Kaarten"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m31, + "memoryCount": m33, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("Mobiel, Web, Desktop"), @@ -926,12 +937,12 @@ class MessageLookup extends MessageLookupByLibrary { "Pas je zoekopdracht aan of zoek naar"), "moments": MessageLookupByLibrary.simpleMessage("Momenten"), "monthly": MessageLookupByLibrary.simpleMessage("Maandelijks"), - "moveItem": m32, + "moveItem": m34, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Verplaats naar album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Verplaatsen naar verborgen album"), - "movedSuccessfullyTo": m33, + "movedSuccessfullyTo": m35, "movedToTrash": MessageLookupByLibrary.simpleMessage("Naar prullenbak verplaatst"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -1001,15 +1012,15 @@ class MessageLookup extends MessageLookupByLibrary { "passwordChangedSuccessfully": MessageLookupByLibrary.simpleMessage( "Wachtwoord succesvol aangepast"), "passwordLock": MessageLookupByLibrary.simpleMessage("Wachtwoord slot"), - "passwordStrength": m34, + "passwordStrength": m36, "passwordWarning": MessageLookupByLibrary.simpleMessage( "Wij slaan dit wachtwoord niet op, dus als je het vergeet, kunnen we je gegevens niet ontsleutelen"), "paymentDetails": MessageLookupByLibrary.simpleMessage("Betaalgegevens"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Betaling mislukt"), - "paymentFailedTalkToProvider": m35, - "paymentFailedWithReason": m36, + "paymentFailedTalkToProvider": m37, + "paymentFailedWithReason": m38, "pendingItems": MessageLookupByLibrary.simpleMessage("Bestanden in behandeling"), "pendingSync": MessageLookupByLibrary.simpleMessage( @@ -1037,7 +1048,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Album bovenaan vastzetten"), "playOnTv": MessageLookupByLibrary.simpleMessage("Album afspelen op TV"), - "playStoreFreeTrialValidTill": m37, + "playStoreFreeTrialValidTill": m39, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore abonnement"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1049,12 +1060,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Neem contact op met klantenservice als het probleem aanhoudt"), - "pleaseEmailUsAt": m38, + "pleaseEmailUsAt": m40, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Geef alstublieft toestemming"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Log opnieuw in"), - "pleaseSendTheLogsTo": m39, + "pleaseSendTheLogsTo": m41, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Probeer het nog eens"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1089,7 +1100,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Meld probleem"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Beoordeel de app"), "rateUs": MessageLookupByLibrary.simpleMessage("Beoordeel ons"), - "rateUsOnStore": m40, + "rateUsOnStore": m42, "recover": MessageLookupByLibrary.simpleMessage("Herstellen"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Account herstellen"), @@ -1120,7 +1131,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Geef deze code aan je vrienden"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Ze registreren voor een betaald plan"), - "referralStep3": m41, + "referralStep3": m43, "referrals": MessageLookupByLibrary.simpleMessage("Referenties"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Verwijzingen zijn momenteel gepauzeerd"), @@ -1146,7 +1157,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Verwijder link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Deelnemer verwijderen"), - "removeParticipantBody": m42, + "removeParticipantBody": m44, "removePublicLink": MessageLookupByLibrary.simpleMessage("Verwijder publieke link"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1162,7 +1173,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Bestandsnaam wijzigen"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Abonnement verlengen"), - "renewsOn": m43, + "renewsOn": m45, "reportABug": MessageLookupByLibrary.simpleMessage("Een fout melden"), "reportBug": MessageLookupByLibrary.simpleMessage("Fout melden"), "resendEmail": @@ -1224,7 +1235,7 @@ class MessageLookup extends MessageLookupByLibrary { "Foto\'s groeperen die in een bepaalde straal van een foto worden genomen"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Nodig mensen uit, en je ziet alle foto\'s die door hen worden gedeeld hier"), - "searchResultCount": m44, + "searchResultCount": m46, "security": MessageLookupByLibrary.simpleMessage("Beveiliging"), "selectALocation": MessageLookupByLibrary.simpleMessage("Selecteer een locatie"), @@ -1251,8 +1262,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Geselecteerde bestanden worden verwijderd uit alle albums en verplaatst naar de prullenbak."), - "selectedPhotos": m45, - "selectedPhotosWithYours": m46, + "selectedPhotos": m47, + "selectedPhotosWithYours": m48, "send": MessageLookupByLibrary.simpleMessage("Verzenden"), "sendEmail": MessageLookupByLibrary.simpleMessage("E-mail versturen"), "sendInvite": @@ -1276,16 +1287,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Deel nu een album"), "shareLink": MessageLookupByLibrary.simpleMessage("Link delen"), - "shareMyVerificationID": m47, + "shareMyVerificationID": m49, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Deel alleen met de mensen die u wilt"), - "shareTextConfirmOthersVerificationID": m48, + "shareTextConfirmOthersVerificationID": m50, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Download ente zodat we gemakkelijk foto\'s en video\'s van originele kwaliteit kunnen delen\n\nhttps://ente.io"), - "shareTextReferralCode": m49, + "shareTextReferralCode": m51, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Delen met niet-ente gebruikers"), - "shareWithPeopleSectionTitle": m50, + "shareWithPeopleSectionTitle": m52, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Deel jouw eerste album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1296,7 +1307,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nieuwe gedeelde foto\'s"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Ontvang meldingen wanneer iemand een foto toevoegt aan een gedeeld album waar je deel van uitmaakt"), - "sharedWith": m51, + "sharedWith": m53, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Gedeeld met mij"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Gedeeld met jou"), @@ -1311,11 +1322,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Log uit op andere apparaten"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Ik ga akkoord met de gebruiksvoorwaarden en privacybeleid"), - "singleFileDeleteFromDevice": m52, + "singleFileDeleteFromDevice": m54, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Het wordt uit alle albums verwijderd."), - "singleFileInBothLocalAndRemote": m53, - "singleFileInRemoteOnly": m54, + "singleFileInBothLocalAndRemote": m55, + "singleFileInRemoteOnly": m56, "skip": MessageLookupByLibrary.simpleMessage("Overslaan"), "social": MessageLookupByLibrary.simpleMessage("Sociale media"), "someItemsAreInBothEnteAndYourDevice": MessageLookupByLibrary.simpleMessage( @@ -1353,13 +1364,13 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Opslagruimte"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Familie"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Jij"), - "storageInGB": m55, + "storageInGB": m57, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Opslaglimiet overschreden"), - "storageUsageInfo": m56, + "storageUsageInfo": m58, "strongStrength": MessageLookupByLibrary.simpleMessage("Sterk"), - "subAlreadyLinkedErrMessage": m57, - "subWillBeCancelledOn": m58, + "subAlreadyLinkedErrMessage": m59, + "subWillBeCancelledOn": m60, "subscribe": MessageLookupByLibrary.simpleMessage("Abonneer"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Het lijkt erop dat je abonnement is verlopen. Abonneer om delen mogelijk te maken."), @@ -1376,7 +1387,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Features voorstellen"), "support": MessageLookupByLibrary.simpleMessage("Ondersteuning"), - "syncProgress": m59, + "syncProgress": m61, "syncStopped": MessageLookupByLibrary.simpleMessage("Synchronisatie gestopt"), "syncing": MessageLookupByLibrary.simpleMessage("Synchroniseren..."), @@ -1404,7 +1415,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Deze bestanden zullen worden verwijderd van uw apparaat."), - "theyAlsoGetXGb": m60, + "theyAlsoGetXGb": m62, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Ze zullen uit alle albums worden verwijderd."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1420,7 +1431,7 @@ class MessageLookup extends MessageLookupByLibrary { "Dit e-mailadres is al in gebruik"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Deze foto heeft geen exif gegevens"), - "thisIsPersonVerificationId": m61, + "thisIsPersonVerificationId": m63, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage("Dit is uw verificatie-ID"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1437,7 +1448,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("totaal"), "totalSize": MessageLookupByLibrary.simpleMessage("Totale grootte"), "trash": MessageLookupByLibrary.simpleMessage("Prullenbak"), - "trashDaysLeft": m62, + "trashDaysLeft": m64, "tryAgain": MessageLookupByLibrary.simpleMessage("Probeer opnieuw"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Schakel back-up in om bestanden die toegevoegd zijn aan deze map op dit apparaat automatisch te uploaden."), @@ -1493,7 +1504,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Gebruik geselecteerde foto"), "usedSpace": MessageLookupByLibrary.simpleMessage("Gebruikte ruimte"), - "validTill": m63, + "validTill": m65, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Verificatie mislukt, probeer het opnieuw"), @@ -1501,7 +1512,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Verificatie ID"), "verify": MessageLookupByLibrary.simpleMessage("Verifiëren"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Bevestig e-mail"), - "verifyEmailID": m64, + "verifyEmailID": m66, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verifiëren"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Bevestig wachtwoord"), @@ -1530,11 +1541,11 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "We ondersteunen het bewerken van foto\'s en albums waar je niet de eigenaar van bent nog niet"), - "weHaveSendEmailTo": m65, + "weHaveSendEmailTo": m67, "weakStrength": MessageLookupByLibrary.simpleMessage("Zwak"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Welkom terug!"), "yearly": MessageLookupByLibrary.simpleMessage("Jaarlijks"), - "yearsAgo": m66, + "yearsAgo": m68, "yes": MessageLookupByLibrary.simpleMessage("Ja"), "yesCancel": MessageLookupByLibrary.simpleMessage("Ja, opzeggen"), "yesConvertToViewer": @@ -1564,7 +1575,7 @@ class MessageLookup extends MessageLookupByLibrary { "Je kunt niet met jezelf delen"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "U heeft geen gearchiveerde bestanden."), - "youHaveSuccessfullyFreedUp": m67, + "youHaveSuccessfullyFreedUp": m69, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Je account is verwijderd"), "yourMap": MessageLookupByLibrary.simpleMessage("Jouw kaart"), diff --git a/mobile/lib/generated/intl/messages_no.dart b/mobile/lib/generated/intl/messages_no.dart index 795caf2007..05477cfeba 100644 --- a/mobile/lib/generated/intl/messages_no.dart +++ b/mobile/lib/generated/intl/messages_no.dart @@ -20,12 +20,20 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'no'; + static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("Velkommen tilbake!"), + "addCollaborators": m0, "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), + "addViewers": m1, "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Hva er hovedårsaken til at du sletter kontoen din?"), "cancel": MessageLookupByLibrary.simpleMessage("Avbryt"), @@ -59,6 +67,9 @@ class MessageLookup extends MessageLookupByLibrary { "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage( "Vær vennlig og hjelp oss med denne informasjonen"), "locations": MessageLookupByLibrary.simpleMessage("Locations"), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "modifyYourQueryOrTrySearchingFor": MessageLookupByLibrary.simpleMessage( "Modify your query, or try searching for"), diff --git a/mobile/lib/generated/intl/messages_pl.dart b/mobile/lib/generated/intl/messages_pl.dart index 2647e1191c..af6ba43533 100644 --- a/mobile/lib/generated/intl/messages_pl.dart +++ b/mobile/lib/generated/intl/messages_pl.dart @@ -20,7 +20,13 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'pl'; - static String m34(passwordStrengthValue) => + static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + + static String m36(passwordStrengthValue) => "Siła hasła: ${passwordStrengthValue}"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -28,8 +34,10 @@ class MessageLookup extends MessageLookupByLibrary { "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("Witaj ponownie!"), "activeSessions": MessageLookupByLibrary.simpleMessage("Aktywne sesje"), + "addCollaborators": m0, "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), + "addViewers": m1, "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Jaka jest przyczyna usunięcia konta?"), "cancel": MessageLookupByLibrary.simpleMessage("Anuluj"), @@ -119,6 +127,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Pomóż nam z tą informacją"), "locations": MessageLookupByLibrary.simpleMessage("Locations"), "logInLabel": MessageLookupByLibrary.simpleMessage("Zaloguj się"), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "moderateStrength": MessageLookupByLibrary.simpleMessage("Umiarkowana"), "modifyYourQueryOrTrySearchingFor": MessageLookupByLibrary.simpleMessage( @@ -134,7 +145,7 @@ class MessageLookup extends MessageLookupByLibrary { "password": MessageLookupByLibrary.simpleMessage("Hasło"), "passwordChangedSuccessfully": MessageLookupByLibrary.simpleMessage( "Hasło zostało pomyślnie zmienione"), - "passwordStrength": m34, + "passwordStrength": m36, "passwordWarning": MessageLookupByLibrary.simpleMessage( "Nie przechowujemy tego hasła, więc jeśli go zapomnisz, nie będziemy w stanie odszyfrować Twoich danych"), "pleaseTryAgain": diff --git a/mobile/lib/generated/intl/messages_pt.dart b/mobile/lib/generated/intl/messages_pt.dart index 4a2bfa26d1..ffdc0d2573 100644 --- a/mobile/lib/generated/intl/messages_pt.dart +++ b/mobile/lib/generated/intl/messages_pt.dart @@ -21,27 +21,33 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'pt'; static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m2(count) => "${Intl.plural(count, one: 'Adicionar item', other: 'Adicionar itens')}"; - static String m1(storageAmount, endDate) => + static String m3(storageAmount, endDate) => "Seu complemento ${storageAmount} é válido até o dia ${endDate}"; - static String m2(emailOrName) => "Adicionado por ${emailOrName}"; + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + + static String m4(emailOrName) => "Adicionado por ${emailOrName}"; - static String m3(albumName) => "Adicionado com sucesso a ${albumName}"; + static String m5(albumName) => "Adicionado com sucesso a ${albumName}"; - static String m4(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Nenhum Participante', one: '1 Participante', other: '${count} Participantes')}"; - static String m5(versionValue) => "Versão: ${versionValue}"; + static String m7(versionValue) => "Versão: ${versionValue}"; - static String m6(paymentProvider) => + static String m8(paymentProvider) => "Por favor, cancele sua assinatura existente do ${paymentProvider} primeiro"; - static String m7(user) => + static String m9(user) => "${user} Não poderá adicionar mais fotos a este álbum\n\nEles ainda poderão remover as fotos existentes adicionadas por eles"; - static String m8(isFamilyMember, storageAmountInGb) => + static String m10(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Sua família reeinvindicou ${storageAmountInGb} GB até agora', @@ -49,163 +55,163 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Você reeinvindicou ${storageAmountInGb} GB até agora', })}"; - static String m9(albumName) => "Link colaborativo criado para ${albumName}"; + static String m11(albumName) => "Link colaborativo criado para ${albumName}"; - static String m10(familyAdminEmail) => + static String m12(familyAdminEmail) => "Entre em contato com ${familyAdminEmail} para gerenciar sua assinatura"; - static String m11(provider) => + static String m13(provider) => "Entre em contato conosco pelo e-mail support@ente.io para gerenciar sua assinatura ${provider}."; - static String m12(count) => + static String m14(count) => "${Intl.plural(count, one: 'Excluir ${count} item', other: 'Excluir ${count} itens')}"; - static String m13(currentlyDeleting, totalCount) => + static String m15(currentlyDeleting, totalCount) => "Excluindo ${currentlyDeleting} / ${totalCount}"; - static String m14(albumName) => + static String m16(albumName) => "Isso removerá o link público para acessar \"${albumName}\"."; - static String m15(supportEmail) => + static String m17(supportEmail) => "Por favor, envie um e-mail para ${supportEmail} a partir do seu endereço de e-mail registrado"; - static String m16(count, storageSaved) => + static String m18(count, storageSaved) => "Você limpou ${Intl.plural(count, one: '${count} arquivo duplicado', other: '${count} arquivos duplicados')}, salvando (${storageSaved}!)"; - static String m17(count, formattedSize) => + static String m19(count, formattedSize) => "${count} Arquivos, ${formattedSize} cada"; - static String m18(newEmail) => "E-mail alterado para ${newEmail}"; + static String m20(newEmail) => "E-mail alterado para ${newEmail}"; - static String m19(email) => + static String m21(email) => "${email} Não possui uma conta Ente.\n\nEnvie um convite para compartilhar fotos."; - static String m20(count, formattedNumber) => + static String m22(count, formattedNumber) => "${Intl.plural(count, one: '1 arquivo', other: '${formattedNumber} arquivos')} neste dispositivo teve um backup seguro"; - static String m21(count, formattedNumber) => + static String m23(count, formattedNumber) => "${Intl.plural(count, one: '1 arquivo', other: '${formattedNumber} arquivos')} neste álbum teve um backup seguro"; - static String m22(storageAmountInGB) => + static String m24(storageAmountInGB) => "${storageAmountInGB} GB cada vez que alguém se inscrever para um plano pago e aplica o seu código"; - static String m23(freeAmount, storageUnit) => + static String m25(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} grátis"; - static String m24(endDate) => "Teste gratuito acaba em ${endDate}"; + static String m26(endDate) => "Teste gratuito acaba em ${endDate}"; - static String m25(count) => + static String m27(count) => "Você ainda pode acessar ${Intl.plural(count, one: 'ele', other: 'eles')} no ente contanto que você tenha uma assinatura ativa"; - static String m26(sizeInMBorGB) => "Liberar ${sizeInMBorGB}"; + static String m28(sizeInMBorGB) => "Liberar ${sizeInMBorGB}"; - static String m27(count, formattedSize) => + static String m29(count, formattedSize) => "${Intl.plural(count, one: 'Pode ser excluído do dispositivo para liberar ${formattedSize}', other: 'Eles podem ser excluídos do dispositivo para liberar ${formattedSize}')}"; - static String m28(currentlyProcessing, totalCount) => + static String m30(currentlyProcessing, totalCount) => "Processando ${currentlyProcessing} / ${totalCount}"; - static String m29(count) => + static String m31(count) => "${Intl.plural(count, one: '${count} item', other: '${count} items')}"; - static String m30(expiryTime) => "O link irá expirar em ${expiryTime}"; + static String m32(expiryTime) => "O link irá expirar em ${expiryTime}"; - static String m31(count, formattedCount) => + static String m33(count, formattedCount) => "${Intl.plural(count, zero: 'no memories', one: '${formattedCount} memory', other: '${formattedCount} memories')}"; - static String m32(count) => + static String m34(count) => "${Intl.plural(count, one: 'Mover item', other: 'Mover itens')}"; - static String m33(albumName) => "Movido com sucesso para ${albumName}"; + static String m35(albumName) => "Movido com sucesso para ${albumName}"; - static String m34(passwordStrengthValue) => + static String m36(passwordStrengthValue) => "Segurança da senha: ${passwordStrengthValue}"; - static String m35(providerName) => + static String m37(providerName) => "Por favor, fale com o suporte ${providerName} se você foi cobrado"; - static String m36(reason) => + static String m38(reason) => "Infelizmente o seu pagamento falhou devido a ${reason}"; - static String m37(endDate) => + static String m39(endDate) => "Teste gratuito válido até ${endDate}.\nVocê pode escolher um plano pago depois."; - static String m38(toEmail) => + static String m40(toEmail) => "Por favor, envie-nos um e-mail para ${toEmail}"; - static String m39(toEmail) => "Por favor, envie os logs para \n${toEmail}"; + static String m41(toEmail) => "Por favor, envie os logs para \n${toEmail}"; - static String m40(storeName) => "Avalie-nos em ${storeName}"; + static String m42(storeName) => "Avalie-nos em ${storeName}"; - static String m41(storageInGB) => "3. Ambos ganham ${storageInGB} GB* grátis"; + static String m43(storageInGB) => "3. Ambos ganham ${storageInGB} GB* grátis"; - static String m42(userEmail) => + static String m44(userEmail) => "${userEmail} será removido deste álbum compartilhado\n\nQuaisquer fotos adicionadas por eles também serão removidas do álbum"; - static String m43(endDate) => "Renovação de assinatura em ${endDate}"; + static String m45(endDate) => "Renovação de assinatura em ${endDate}"; - static String m44(count) => + static String m46(count) => "${Intl.plural(count, one: '${count} resultado encontrado', other: '${count} resultado encontrado')}"; - static String m45(count) => "${count} Selecionados"; + static String m47(count) => "${count} Selecionados"; - static String m46(count, yourCount) => + static String m48(count, yourCount) => "${count} Selecionado (${yourCount} seus)"; - static String m47(verificationID) => + static String m49(verificationID) => "Aqui está meu ID de verificação para o Ente.io: ${verificationID}"; - static String m48(verificationID) => + static String m50(verificationID) => "Ei, você pode confirmar que este é seu ID de verificação do Ente.io? ${verificationID}"; - static String m49(referralCode, referralStorageInGB) => + static String m51(referralCode, referralStorageInGB) => "Código de referência do ente: ${referralCode} \n\nAplique em Configurações → Geral → Indicações para obter ${referralStorageInGB} GB gratuitamente após a sua inscrição em um plano pago\n\nhttps://ente.io"; - static String m50(numberOfPeople) => + static String m52(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Compartilhe com pessoas específicas', one: 'Compartilhado com 1 pessoa', other: 'Compartilhado com ${numberOfPeople} pessoas')}"; - static String m51(emailIDs) => "Compartilhado com ${emailIDs}"; + static String m53(emailIDs) => "Compartilhado com ${emailIDs}"; - static String m52(fileType) => + static String m54(fileType) => "Este ${fileType} será excluído do seu dispositivo."; - static String m53(fileType) => + static String m55(fileType) => "Este ${fileType} está em ente e no seu dispositivo."; - static String m54(fileType) => "Este ${fileType} será excluído do ente."; + static String m56(fileType) => "Este ${fileType} será excluído do ente."; - static String m55(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m56( + static String m58( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "${usedAmount} ${usedStorageUnit} de ${totalAmount} ${totalStorageUnit} usado"; - static String m57(id) => + static String m59(id) => "Seu ${id} já está vinculado a outra conta ente.\nSe você gostaria de usar seu ${id} com esta conta, por favor contate nosso suporte\'\'"; - static String m58(endDate) => "Sua assinatura será cancelada em ${endDate}"; + static String m60(endDate) => "Sua assinatura será cancelada em ${endDate}"; - static String m59(completed, total) => + static String m61(completed, total) => "${completed}/${total} memórias preservadas"; - static String m60(storageAmountInGB) => + static String m62(storageAmountInGB) => "Eles também recebem ${storageAmountInGB} GB"; - static String m61(email) => "Este é o ID de verificação de ${email}"; + static String m63(email) => "Este é o ID de verificação de ${email}"; - static String m62(count) => + static String m64(count) => "${Intl.plural(count, zero: '', one: '1 dia', other: '${count} dias')}"; - static String m63(endDate) => "Válido até ${endDate}"; + static String m65(endDate) => "Válido até ${endDate}"; - static String m64(email) => "Verificar ${email}"; + static String m66(email) => "Verificar ${email}"; - static String m65(email) => "Enviamos um e-mail à ${email}"; + static String m67(email) => "Enviamos um e-mail à ${email}"; - static String m66(count) => + static String m68(count) => "${Intl.plural(count, one: '${count} anos atrás', other: '${count} anos atrás')}"; - static String m67(storageSaved) => + static String m69(storageSaved) => "Você liberou ${storageSaved} com sucesso!"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -224,16 +230,17 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Adicionar um novo email"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Adicionar colaborador"), + "addCollaborators": m0, "addFromDevice": MessageLookupByLibrary.simpleMessage( "Adicionar a partir do dispositivo"), - "addItem": m0, + "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("Adicionar local"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Adicionar"), "addMore": MessageLookupByLibrary.simpleMessage("Adicione mais"), "addNew": MessageLookupByLibrary.simpleMessage("Adicionar novo"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Detalhes dos complementos"), - "addOnValidTill": m1, + "addOnValidTill": m3, "addOns": MessageLookupByLibrary.simpleMessage("Complementos"), "addPhotos": MessageLookupByLibrary.simpleMessage("Adicionar fotos"), "addSelected": @@ -245,11 +252,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Adicionar a álbum oculto"), "addViewer": MessageLookupByLibrary.simpleMessage("Adicionar visualizador"), + "addViewers": m1, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Adicione suas fotos agora"), "addedAs": MessageLookupByLibrary.simpleMessage("Adicionado como"), - "addedBy": m2, - "addedSuccessfullyTo": m3, + "addedBy": m4, + "addedSuccessfullyTo": m5, "addingToFavorites": MessageLookupByLibrary.simpleMessage( "Adicionando aos favoritos..."), "advanced": MessageLookupByLibrary.simpleMessage("Avançado"), @@ -260,7 +268,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Após 1 semana"), "after1Year": MessageLookupByLibrary.simpleMessage("Após 1 ano"), "albumOwner": MessageLookupByLibrary.simpleMessage("Proprietário"), - "albumParticipantsCount": m4, + "albumParticipantsCount": m6, "albumTitle": MessageLookupByLibrary.simpleMessage("Título do álbum"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Álbum atualizado"), @@ -297,7 +305,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Android, iOS, Web, Desktop"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("Autenticação necessária"), - "appVersion": m5, + "appVersion": m7, "appleId": MessageLookupByLibrary.simpleMessage("ID da Apple"), "apply": MessageLookupByLibrary.simpleMessage("Aplicar"), "applyCodeTitle": @@ -384,10 +392,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Só é possível remover arquivos de sua propriedade"), "cancel": MessageLookupByLibrary.simpleMessage("Cancelar"), - "cancelOtherSubscription": m6, + "cancelOtherSubscription": m8, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Cancelar assinatura"), - "cannotAddMorePhotosAfterBecomingViewer": m7, + "cannotAddMorePhotosAfterBecomingViewer": m9, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Não é possível excluir arquivos compartilhados"), "castInstruction": MessageLookupByLibrary.simpleMessage( @@ -411,9 +419,11 @@ class MessageLookup extends MessageLookupByLibrary { "Reivindicar armazenamento gratuito"), "claimMore": MessageLookupByLibrary.simpleMessage("Reivindique mais!"), "claimed": MessageLookupByLibrary.simpleMessage("Reivindicado"), - "claimedStorageSoFar": m8, + "claimedStorageSoFar": m10, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Limpar Sem Categoria"), + "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( + "Remover todos os arquivos de Não Categorizados que estão presentes em outros álbuns"), "clearCaches": MessageLookupByLibrary.simpleMessage("Limpar cache"), "clearIndexes": MessageLookupByLibrary.simpleMessage("Limpar índices"), "click": MessageLookupByLibrary.simpleMessage("Clique"), @@ -434,7 +444,7 @@ class MessageLookup extends MessageLookupByLibrary { "Crie um link para permitir pessoas adicionar e ver fotos no seu álbum compartilhado sem a necessidade do aplicativo ou uma conta Ente. Ótimo para colecionar fotos de eventos."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Link Colaborativo"), - "collaborativeLinkCreatedFor": m9, + "collaborativeLinkCreatedFor": m11, "collaborator": MessageLookupByLibrary.simpleMessage("Colaborador"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -461,10 +471,10 @@ class MessageLookup extends MessageLookupByLibrary { "Confirme a chave de recuperação"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Confirme sua chave de recuperação"), - "contactFamilyAdmin": m10, + "contactFamilyAdmin": m12, "contactSupport": MessageLookupByLibrary.simpleMessage("Contate o suporte"), - "contactToManageSubscription": m11, + "contactToManageSubscription": m13, "contacts": MessageLookupByLibrary.simpleMessage("Contatos"), "contents": MessageLookupByLibrary.simpleMessage("Conteúdos"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuar"), @@ -540,10 +550,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Excluir do dispositivo"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Excluir do ente"), - "deleteItemCount": m12, + "deleteItemCount": m14, "deleteLocation": MessageLookupByLibrary.simpleMessage("Excluir Local"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Excluir fotos"), - "deleteProgress": m13, + "deleteProgress": m15, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Está faltando um recurso-chave que eu preciso"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -558,7 +568,7 @@ class MessageLookup extends MessageLookupByLibrary { "Excluir álbum compartilhado?"), "deleteSharedAlbumDialogBody": MessageLookupByLibrary.simpleMessage( "O álbum será apagado para todos\n\nVocê perderá o acesso a fotos compartilhadas neste álbum que pertencem aos outros"), - "descriptions": MessageLookupByLibrary.simpleMessage("Descriptions"), + "descriptions": MessageLookupByLibrary.simpleMessage("Descrições"), "deselectAll": MessageLookupByLibrary.simpleMessage("Desmarcar todos"), "designedToOutlive": MessageLookupByLibrary.simpleMessage("Feito para ter logenvidade"), @@ -580,7 +590,7 @@ class MessageLookup extends MessageLookupByLibrary { "Os espectadores ainda podem tirar screenshots ou salvar uma cópia de suas fotos usando ferramentas externas"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Observe"), - "disableLinkMessage": m14, + "disableLinkMessage": m16, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Desativar autenticação de dois fatores"), "disablingTwofactorAuthentication": @@ -603,9 +613,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Falha ao baixar"), "downloading": MessageLookupByLibrary.simpleMessage("Baixando..."), - "dropSupportEmail": m15, - "duplicateFileCountWithStorageSaved": m16, - "duplicateItemsGroup": m17, + "dropSupportEmail": m17, + "duplicateFileCountWithStorageSaved": m18, + "duplicateItemsGroup": m19, "edit": MessageLookupByLibrary.simpleMessage("Editar"), "editLocation": MessageLookupByLibrary.simpleMessage("Editar local"), "editLocationTagTitle": @@ -616,8 +626,8 @@ class MessageLookup extends MessageLookupByLibrary { "Edições para local só serão vistas dentro do Ente"), "eligible": MessageLookupByLibrary.simpleMessage("elegível"), "email": MessageLookupByLibrary.simpleMessage("E-mail"), - "emailChangedTo": m18, - "emailNoEnteAccount": m19, + "emailChangedTo": m20, + "emailNoEnteAccount": m21, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Verificação de e-mail"), "emailYourLogs": @@ -716,8 +726,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Tipos de arquivo"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Tipos de arquivo e nomes"), - "filesBackedUpFromDevice": m20, - "filesBackedUpInAlbum": m21, + "filesBackedUpFromDevice": m22, + "filesBackedUpInAlbum": m23, "filesDeleted": MessageLookupByLibrary.simpleMessage("Arquivos excluídos"), "flip": MessageLookupByLibrary.simpleMessage("Inverter"), @@ -727,24 +737,24 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Esqueceu sua senha"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage( "Armazenamento gratuito reivindicado"), - "freeStorageOnReferralSuccess": m22, - "freeStorageSpace": m23, + "freeStorageOnReferralSuccess": m24, + "freeStorageSpace": m25, "freeStorageUsable": MessageLookupByLibrary.simpleMessage( "Armazenamento livre utilizável"), "freeTrial": MessageLookupByLibrary.simpleMessage("Teste gratuito"), - "freeTrialValidTill": m24, - "freeUpAccessPostDelete": m25, - "freeUpAmount": m26, + "freeTrialValidTill": m26, + "freeUpAccessPostDelete": m27, + "freeUpAmount": m28, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Liberar espaço no dispositivo"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Liberar espaço"), - "freeUpSpaceSaving": m27, + "freeUpSpaceSaving": m29, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Até 1000 memórias mostradas na galeria"), "general": MessageLookupByLibrary.simpleMessage("Geral"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Gerando chaves de criptografia..."), - "genericProgress": m28, + "genericProgress": m30, "goToSettings": MessageLookupByLibrary.simpleMessage("Ir para Configurações"), "googlePlayId": @@ -806,7 +816,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Parece que algo deu errado. Por favor, tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de suporte."), - "itemCount": m29, + "itemCount": m31, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Os itens mostram o número de dias restantes antes da exclusão permanente"), @@ -834,7 +844,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Limite do dispositivo"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Ativado"), "linkExpired": MessageLookupByLibrary.simpleMessage("Expirado"), - "linkExpiresOn": m30, + "linkExpiresOn": m32, "linkExpiry": MessageLookupByLibrary.simpleMessage("Expiração do link"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("O link expirou"), @@ -872,7 +882,7 @@ class MessageLookup extends MessageLookupByLibrary { "locationName": MessageLookupByLibrary.simpleMessage("Nome do Local"), "locationTagFeatureDescription": MessageLookupByLibrary.simpleMessage( "Uma tag em grupo de todas as fotos que foram tiradas dentro de algum raio de uma foto"), - "locations": MessageLookupByLibrary.simpleMessage("Locations"), + "locations": MessageLookupByLibrary.simpleMessage("Locais"), "lockButtonLabel": MessageLookupByLibrary.simpleMessage("Bloquear"), "lockScreenEnablePreSteps": MessageLookupByLibrary.simpleMessage( "Para ativar o bloqueio de tela, por favor ative um método de autenticação nas configurações do sistema do seu dispositivo."), @@ -884,6 +894,9 @@ class MessageLookup extends MessageLookupByLibrary { "logout": MessageLookupByLibrary.simpleMessage("Encerrar sessão"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( "Isso enviará através dos logs para nos ajudar a depurar o seu problema. Por favor, note que nomes de arquivos serão incluídos para ajudar a rastrear problemas com arquivos específicos."), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( "Pressione e segure em um item para exibir em tela cheia"), @@ -907,7 +920,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Mapas"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m31, + "memoryCount": m33, "merchandise": MessageLookupByLibrary.simpleMessage("Produtos"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("Mobile, Web, Desktop"), @@ -917,11 +930,11 @@ class MessageLookup extends MessageLookupByLibrary { "Modifique sua consulta ou tente procurar por"), "moments": MessageLookupByLibrary.simpleMessage("Momentos"), "monthly": MessageLookupByLibrary.simpleMessage("Mensal"), - "moveItem": m32, + "moveItem": m34, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Mover para álbum"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Mover para álbum oculto"), - "movedSuccessfullyTo": m33, + "movedSuccessfullyTo": m35, "movedToTrash": MessageLookupByLibrary.simpleMessage("Movido para a lixeira"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -994,15 +1007,15 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Senha alterada com sucesso"), "passwordLock": MessageLookupByLibrary.simpleMessage("Bloqueio de senha"), - "passwordStrength": m34, + "passwordStrength": m36, "passwordWarning": MessageLookupByLibrary.simpleMessage( "Nós não salvamos essa senha, se você esquecer nós não poderemos descriptografar seus dados"), "paymentDetails": MessageLookupByLibrary.simpleMessage("Detalhes de pagamento"), "paymentFailed": MessageLookupByLibrary.simpleMessage("Falha no pagamento"), - "paymentFailedTalkToProvider": m35, - "paymentFailedWithReason": m36, + "paymentFailedTalkToProvider": m37, + "paymentFailedWithReason": m38, "pendingItems": MessageLookupByLibrary.simpleMessage("Itens pendentes"), "pendingSync": MessageLookupByLibrary.simpleMessage("Sincronização pendente"), @@ -1028,7 +1041,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinAlbum": MessageLookupByLibrary.simpleMessage("Fixar álbum"), "playOnTv": MessageLookupByLibrary.simpleMessage("Reproduzir álbum na TV"), - "playStoreFreeTrialValidTill": m37, + "playStoreFreeTrialValidTill": m39, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Assinatura da PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1040,12 +1053,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Por favor, contate o suporte se o problema persistir"), - "pleaseEmailUsAt": m38, + "pleaseEmailUsAt": m40, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Por favor, conceda as permissões"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( "Por favor, faça login novamente"), - "pleaseSendTheLogsTo": m39, + "pleaseSendTheLogsTo": m41, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Por favor, tente novamente"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1082,7 +1095,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Avalie o aplicativo"), "rateUs": MessageLookupByLibrary.simpleMessage("Avalie-nos"), - "rateUsOnStore": m40, + "rateUsOnStore": m42, "recover": MessageLookupByLibrary.simpleMessage("Recuperar"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recuperar conta"), @@ -1114,7 +1127,7 @@ class MessageLookup extends MessageLookupByLibrary { "Envie esse código aos seus amigos"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Eles se inscreveram para um plano pago"), - "referralStep3": m41, + "referralStep3": m43, "referrals": MessageLookupByLibrary.simpleMessage("Indicações"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Referências estão atualmente pausadas"), @@ -1138,7 +1151,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Remover link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Remover participante"), - "removeParticipantBody": m42, + "removeParticipantBody": m44, "removePublicLink": MessageLookupByLibrary.simpleMessage("Remover link público"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1152,7 +1165,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Renomear arquivo"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renovar assinatura"), - "renewsOn": m43, + "renewsOn": m45, "reportABug": MessageLookupByLibrary.simpleMessage("Reportar um problema"), "reportBug": @@ -1217,7 +1230,7 @@ class MessageLookup extends MessageLookupByLibrary { "Fotos de grupo que estão sendo tiradas em algum raio da foto"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Convide pessoas e você verá todas as fotos compartilhadas por elas aqui"), - "searchResultCount": m44, + "searchResultCount": m46, "security": MessageLookupByLibrary.simpleMessage("Segurança"), "selectALocation": MessageLookupByLibrary.simpleMessage("Selecionar um local"), @@ -1245,8 +1258,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Os itens selecionados serão excluídos de todos os álbuns e movidos para o lixo."), - "selectedPhotos": m45, - "selectedPhotosWithYours": m46, + "selectedPhotos": m47, + "selectedPhotosWithYours": m48, "send": MessageLookupByLibrary.simpleMessage("Enviar"), "sendEmail": MessageLookupByLibrary.simpleMessage("Enviar e-mail"), "sendInvite": MessageLookupByLibrary.simpleMessage("Enviar convite"), @@ -1270,16 +1283,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Compartilhar um álbum agora"), "shareLink": MessageLookupByLibrary.simpleMessage("Compartilhar link"), - "shareMyVerificationID": m47, + "shareMyVerificationID": m49, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Compartilhar apenas com as pessoas que você quiser"), - "shareTextConfirmOthersVerificationID": m48, + "shareTextConfirmOthersVerificationID": m50, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Baixe o Ente para podermos compartilhar facilmente fotos e vídeos de alta qualidade\n\nhttps://ente.io"), - "shareTextReferralCode": m49, + "shareTextReferralCode": m51, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Compartilhar com usuários não-Ente"), - "shareWithPeopleSectionTitle": m50, + "shareWithPeopleSectionTitle": m52, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Compartilhar seu primeiro álbum"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1292,7 +1305,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Novas fotos compartilhadas"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Receber notificações quando alguém adicionar uma foto em um álbum compartilhado que você faz parte"), - "sharedWith": m51, + "sharedWith": m53, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Compartilhado comigo"), "sharedWithYou": @@ -1308,11 +1321,11 @@ class MessageLookup extends MessageLookupByLibrary { "Terminar sessão em outros dispositivos"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Eu concordo com os termos de serviço e a política de privacidade"), - "singleFileDeleteFromDevice": m52, + "singleFileDeleteFromDevice": m54, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Ele será excluído de todos os álbuns."), - "singleFileInBothLocalAndRemote": m53, - "singleFileInRemoteOnly": m54, + "singleFileInBothLocalAndRemote": m55, + "singleFileInRemoteOnly": m56, "skip": MessageLookupByLibrary.simpleMessage("Pular"), "social": MessageLookupByLibrary.simpleMessage("Redes sociais"), "someItemsAreInBothEnteAndYourDevice": @@ -1353,13 +1366,13 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Armazenamento"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Família"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Você"), - "storageInGB": m55, + "storageInGB": m57, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Limite de armazenamento excedido"), - "storageUsageInfo": m56, + "storageUsageInfo": m58, "strongStrength": MessageLookupByLibrary.simpleMessage("Forte"), - "subAlreadyLinkedErrMessage": m57, - "subWillBeCancelledOn": m58, + "subAlreadyLinkedErrMessage": m59, + "subWillBeCancelledOn": m60, "subscribe": MessageLookupByLibrary.simpleMessage("Assinar"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Parece que sua assinatura expirou. Por favor inscreva-se para ativar o compartilhamento."), @@ -1376,7 +1389,7 @@ class MessageLookup extends MessageLookupByLibrary { "suggestFeatures": MessageLookupByLibrary.simpleMessage("Sugerir funcionalidades"), "support": MessageLookupByLibrary.simpleMessage("Suporte"), - "syncProgress": m59, + "syncProgress": m61, "syncStopped": MessageLookupByLibrary.simpleMessage("Sincronização interrompida"), "syncing": MessageLookupByLibrary.simpleMessage("Sincronizando..."), @@ -1403,7 +1416,7 @@ class MessageLookup extends MessageLookupByLibrary { "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( "Estes itens serão excluídos do seu dispositivo."), - "theyAlsoGetXGb": m60, + "theyAlsoGetXGb": m62, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage( "Ele será excluído de todos os álbuns."), "thisActionCannotBeUndone": MessageLookupByLibrary.simpleMessage( @@ -1419,7 +1432,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Este e-mail já está em uso"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Esta imagem não tem dados exif"), - "thisIsPersonVerificationId": m61, + "thisIsPersonVerificationId": m63, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Este é o seu ID de verificação"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1435,7 +1448,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("total"), "totalSize": MessageLookupByLibrary.simpleMessage("Tamanho total"), "trash": MessageLookupByLibrary.simpleMessage("Lixeira"), - "trashDaysLeft": m62, + "trashDaysLeft": m64, "tryAgain": MessageLookupByLibrary.simpleMessage("Tente novamente"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( "Ative o backup para enviar automaticamente arquivos adicionados a esta pasta do dispositivo para o ente."), @@ -1488,7 +1501,7 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("Utilizar foto selecionada"), "usedSpace": MessageLookupByLibrary.simpleMessage("Espaço em uso"), - "validTill": m63, + "validTill": m65, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Falha na verificação, por favor, tente novamente"), @@ -1496,8 +1509,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("ID de Verificação"), "verify": MessageLookupByLibrary.simpleMessage("Verificar"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Verificar email"), - "verifyEmailID": m64, + "verifyEmailID": m66, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Verificar"), + "verifyPasskey": + MessageLookupByLibrary.simpleMessage("Verificar chave de acesso"), "verifyPassword": MessageLookupByLibrary.simpleMessage("Verificar senha"), "verifying": MessageLookupByLibrary.simpleMessage("Verificando..."), @@ -1518,6 +1533,8 @@ class MessageLookup extends MessageLookupByLibrary { "viewer": MessageLookupByLibrary.simpleMessage("Visualizador"), "visitWebToManage": MessageLookupByLibrary.simpleMessage( "Por favor visite web.ente.io para gerenciar sua assinatura"), + "waitingForVerification": MessageLookupByLibrary.simpleMessage( + "Esperando por verificação..."), "waitingForWifi": MessageLookupByLibrary.simpleMessage("Esperando por Wi-Fi..."), "weAreOpenSource": @@ -1525,12 +1542,12 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Não suportamos a edição de fotos e álbuns que você ainda não possui"), - "weHaveSendEmailTo": m65, + "weHaveSendEmailTo": m67, "weakStrength": MessageLookupByLibrary.simpleMessage("Fraca"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bem-vindo de volta!"), "yearly": MessageLookupByLibrary.simpleMessage("Anual"), - "yearsAgo": m66, + "yearsAgo": m68, "yes": MessageLookupByLibrary.simpleMessage("Sim"), "yesCancel": MessageLookupByLibrary.simpleMessage("Sim, cancelar"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage( @@ -1561,7 +1578,7 @@ class MessageLookup extends MessageLookupByLibrary { "Você não pode compartilhar consigo mesmo"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage( "Você não tem nenhum item arquivado."), - "youHaveSuccessfullyFreedUp": m67, + "youHaveSuccessfullyFreedUp": m69, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Sua conta foi excluída"), "yourMap": MessageLookupByLibrary.simpleMessage("Seu mapa"), diff --git a/mobile/lib/generated/intl/messages_zh.dart b/mobile/lib/generated/intl/messages_zh.dart index 4a056efe89..ca420142bb 100644 --- a/mobile/lib/generated/intl/messages_zh.dart +++ b/mobile/lib/generated/intl/messages_zh.dart @@ -21,174 +21,180 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'zh'; static String m0(count) => + "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; + + static String m2(count) => "${Intl.plural(count, one: '添加一个项目', other: '添加一些项目')}"; - static String m1(storageAmount, endDate) => + static String m3(storageAmount, endDate) => "您的 ${storageAmount} 插件有效期至 ${endDate}"; - static String m2(emailOrName) => "由 ${emailOrName} 添加"; + static String m1(count) => + "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; + + static String m4(emailOrName) => "由 ${emailOrName} 添加"; - static String m3(albumName) => "成功添加到 ${albumName}"; + static String m5(albumName) => "成功添加到 ${albumName}"; - static String m4(count) => + static String m6(count) => "${Intl.plural(count, zero: '无参与者', one: '1个参与者', other: '${count} 个参与者')}"; - static String m5(versionValue) => "版本: ${versionValue}"; + static String m7(versionValue) => "版本: ${versionValue}"; - static String m6(paymentProvider) => "请先取消您现有的订阅 ${paymentProvider}"; + static String m8(paymentProvider) => "请先取消您现有的订阅 ${paymentProvider}"; - static String m7(user) => "${user} 将无法添加更多照片到此相册\n\n他们仍然能够删除他们添加的现有照片"; + static String m9(user) => "${user} 将无法添加更多照片到此相册\n\n他们仍然能够删除他们添加的现有照片"; - static String m8(isFamilyMember, storageAmountInGb) => + static String m10(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': '到目前为止,您的家庭已经领取了 ${storageAmountInGb} GB', 'false': '到目前为止,您已经领取了 ${storageAmountInGb} GB', 'other': '到目前为止,您已经领取了${storageAmountInGb} GB', })}"; - static String m9(albumName) => "为 ${albumName} 创建了协作链接"; + static String m11(albumName) => "为 ${albumName} 创建了协作链接"; - static String m10(familyAdminEmail) => + static String m12(familyAdminEmail) => "请联系 ${familyAdminEmail} 来管理您的订阅"; - static String m11(provider) => + static String m13(provider) => "请通过support@ente.io 用英语联系我们来管理您的 ${provider} 订阅。"; - static String m12(count) => + static String m14(count) => "${Intl.plural(count, one: '删除 ${count} 个项目', other: '删除 ${count} 个项目')}"; - static String m13(currentlyDeleting, totalCount) => + static String m15(currentlyDeleting, totalCount) => "正在删除 ${currentlyDeleting} /共 ${totalCount}"; - static String m14(albumName) => "这将删除用于访问\"${albumName}\"的公共链接。"; + static String m16(albumName) => "这将删除用于访问\"${albumName}\"的公共链接。"; - static String m15(supportEmail) => "请从您注册的邮箱发送一封邮件到 ${supportEmail}"; + static String m17(supportEmail) => "请从您注册的邮箱发送一封邮件到 ${supportEmail}"; - static String m16(count, storageSaved) => + static String m18(count, storageSaved) => "您已经清理了 ${Intl.plural(count, other: '${count} 个重复文件')}, 释放了 (${storageSaved}!)"; - static String m17(count, formattedSize) => + static String m19(count, formattedSize) => "${count} 个文件,每个文件 ${formattedSize}"; - static String m18(newEmail) => "电子邮件已更改为 ${newEmail}"; + static String m20(newEmail) => "电子邮件已更改为 ${newEmail}"; - static String m19(email) => "${email} 没有 ente 账户。\n\n向他们发送分享照片的邀请。"; + static String m21(email) => "${email} 没有 ente 账户。\n\n向他们发送分享照片的邀请。"; - static String m20(count, formattedNumber) => + static String m22(count, formattedNumber) => "此设备上的 ${Intl.plural(count, one: '1 个文件', other: '${formattedNumber} 个文件')} 已安全备份"; - static String m21(count, formattedNumber) => + static String m23(count, formattedNumber) => "此相册中的 ${Intl.plural(count, one: '1 个文件', other: '${formattedNumber} 个文件')} 已安全备份"; - static String m22(storageAmountInGB) => + static String m24(storageAmountInGB) => "每当有人使用您的代码注册付费计划时您将获得${storageAmountInGB} GB"; - static String m23(freeAmount, storageUnit) => + static String m25(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} 空闲"; - static String m24(endDate) => "免费试用有效期至 ${endDate}"; + static String m26(endDate) => "免费试用有效期至 ${endDate}"; - static String m25(count) => + static String m27(count) => "只要您有有效的订阅,您仍然可以在 ente 上访问 ${Intl.plural(count, one: 'it', other: 'them')}"; - static String m26(sizeInMBorGB) => "释放 ${sizeInMBorGB}"; + static String m28(sizeInMBorGB) => "释放 ${sizeInMBorGB}"; - static String m27(count, formattedSize) => + static String m29(count, formattedSize) => "${Intl.plural(count, one: '它可以从设备中删除以释放 ${formattedSize}', other: '它们可以从设备中删除以释放 ${formattedSize}')}"; - static String m28(currentlyProcessing, totalCount) => + static String m30(currentlyProcessing, totalCount) => "正在处理 ${currentlyProcessing} / ${totalCount}"; - static String m29(count) => + static String m31(count) => "${Intl.plural(count, one: '${count} 个项目', other: '${count} 个项目')}"; - static String m30(expiryTime) => "链接将在 ${expiryTime} 过期"; + static String m32(expiryTime) => "链接将在 ${expiryTime} 过期"; - static String m31(count, formattedCount) => + static String m33(count, formattedCount) => "${Intl.plural(count, zero: '没有回忆', one: '${formattedCount} 个回忆', other: '${formattedCount} 个回忆')}"; - static String m32(count) => + static String m34(count) => "${Intl.plural(count, one: '移动一个项目', other: '移动一些项目')}"; - static String m33(albumName) => "成功移动到 ${albumName}"; + static String m35(albumName) => "成功移动到 ${albumName}"; - static String m34(passwordStrengthValue) => "密码强度: ${passwordStrengthValue}"; + static String m36(passwordStrengthValue) => "密码强度: ${passwordStrengthValue}"; - static String m35(providerName) => "如果您被收取费用,请用英语与 ${providerName} 的客服聊天"; + static String m37(providerName) => "如果您被收取费用,请用英语与 ${providerName} 的客服聊天"; - static String m36(reason) => "很抱歉,您的支付因 ${reason} 而失败"; + static String m38(reason) => "很抱歉,您的支付因 ${reason} 而失败"; - static String m37(endDate) => "免费试用有效期至 ${endDate}。\n之后您可以选择付费计划。"; + static String m39(endDate) => "免费试用有效期至 ${endDate}。\n之后您可以选择付费计划。"; - static String m38(toEmail) => "请给我们发送电子邮件至 ${toEmail}"; + static String m40(toEmail) => "请给我们发送电子邮件至 ${toEmail}"; - static String m39(toEmail) => "请将日志发送至 \n${toEmail}"; + static String m41(toEmail) => "请将日志发送至 \n${toEmail}"; - static String m40(storeName) => "在 ${storeName} 上给我们评分"; + static String m42(storeName) => "在 ${storeName} 上给我们评分"; - static String m41(storageInGB) => "3. 你和朋友都将免费获得 ${storageInGB} GB*"; + static String m43(storageInGB) => "3. 你和朋友都将免费获得 ${storageInGB} GB*"; - static String m42(userEmail) => + static String m44(userEmail) => "${userEmail} 将从这个共享相册中删除\n\nTA们添加的任何照片也将从相册中删除"; - static String m43(endDate) => "在 ${endDate} 前续费"; + static String m45(endDate) => "在 ${endDate} 前续费"; - static String m44(count) => + static String m46(count) => "${Intl.plural(count, other: '已找到 ${count} 个结果')}"; - static String m45(count) => "已选择 ${count} 个"; + static String m47(count) => "已选择 ${count} 个"; - static String m46(count, yourCount) => "选择了 ${count} 个 (您的 ${yourCount} 个)"; + static String m48(count, yourCount) => "选择了 ${count} 个 (您的 ${yourCount} 个)"; - static String m47(verificationID) => "这是我的ente.io 的验证 ID: ${verificationID}。"; + static String m49(verificationID) => "这是我的ente.io 的验证 ID: ${verificationID}。"; - static String m48(verificationID) => + static String m50(verificationID) => "嘿,你能确认这是你的 ente.io 验证 ID吗:${verificationID}"; - static String m49(referralCode, referralStorageInGB) => + static String m51(referralCode, referralStorageInGB) => "ente推荐码: ${referralCode} \n\n注册付费计划后在设置 → 常规 → 推荐中应用它以免费获得 ${referralStorageInGB} GB空间\n\nhttps://ente.io"; - static String m50(numberOfPeople) => + static String m52(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: '与特定人员共享', one: '与 1 人共享', other: '与 ${numberOfPeople} 人共享')}"; - static String m51(emailIDs) => "与 ${emailIDs} 共享"; + static String m53(emailIDs) => "与 ${emailIDs} 共享"; - static String m52(fileType) => "此 ${fileType} 将从您的设备中删除。"; + static String m54(fileType) => "此 ${fileType} 将从您的设备中删除。"; - static String m53(fileType) => "此 ${fileType} 同时在ente和您的设备中。"; + static String m55(fileType) => "此 ${fileType} 同时在ente和您的设备中。"; - static String m54(fileType) => "此 ${fileType} 将从ente中删除。"; + static String m56(fileType) => "此 ${fileType} 将从ente中删除。"; - static String m55(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m57(storageAmountInGB) => "${storageAmountInGB} GB"; - static String m56( + static String m58( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "已使用 ${usedAmount} ${usedStorageUnit} / ${totalAmount} ${totalStorageUnit}"; - static String m57(id) => + static String m59(id) => "您的 ${id} 已经链接到另一个ente账户。\n如果您想要通过此账户使用您的 ${id} ,请联系我们的客服\'\'"; - static String m58(endDate) => "您的订阅将于 ${endDate} 取消"; + static String m60(endDate) => "您的订阅将于 ${endDate} 取消"; - static String m59(completed, total) => "已保存的回忆 ${completed}/共 ${total}"; + static String m61(completed, total) => "已保存的回忆 ${completed}/共 ${total}"; - static String m60(storageAmountInGB) => "他们也会获得 ${storageAmountInGB} GB"; + static String m62(storageAmountInGB) => "他们也会获得 ${storageAmountInGB} GB"; - static String m61(email) => "这是 ${email} 的验证ID"; + static String m63(email) => "这是 ${email} 的验证ID"; - static String m62(count) => + static String m64(count) => "${Intl.plural(count, zero: '', one: '1天', other: '${count} 天')}"; - static String m63(endDate) => "有效期至 ${endDate}"; + static String m65(endDate) => "有效期至 ${endDate}"; - static String m64(email) => "验证 ${email}"; + static String m66(email) => "验证 ${email}"; - static String m65(email) => "我们已经发送邮件到 ${email}"; + static String m67(email) => "我们已经发送邮件到 ${email}"; - static String m66(count) => + static String m68(count) => "${Intl.plural(count, one: '${count} 年前', other: '${count} 年前')}"; - static String m67(storageSaved) => "您已成功释放了 ${storageSaved}!"; + static String m69(storageSaved) => "您已成功释放了 ${storageSaved}!"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -202,14 +208,15 @@ class MessageLookup extends MessageLookupByLibrary { "activeSessions": MessageLookupByLibrary.simpleMessage("已登录的设备"), "addANewEmail": MessageLookupByLibrary.simpleMessage("添加新的电子邮件"), "addCollaborator": MessageLookupByLibrary.simpleMessage("添加协作者"), + "addCollaborators": m0, "addFromDevice": MessageLookupByLibrary.simpleMessage("从设备添加"), - "addItem": m0, + "addItem": m2, "addLocation": MessageLookupByLibrary.simpleMessage("添加地点"), "addLocationButton": MessageLookupByLibrary.simpleMessage("添加"), "addMore": MessageLookupByLibrary.simpleMessage("添加更多"), "addNew": MessageLookupByLibrary.simpleMessage("新建"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("附加组件详情"), - "addOnValidTill": m1, + "addOnValidTill": m3, "addOns": MessageLookupByLibrary.simpleMessage("附加组件"), "addPhotos": MessageLookupByLibrary.simpleMessage("添加照片"), "addSelected": MessageLookupByLibrary.simpleMessage("添加所选项"), @@ -217,10 +224,11 @@ class MessageLookup extends MessageLookupByLibrary { "addToEnte": MessageLookupByLibrary.simpleMessage("添加到 ente"), "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("添加到隐藏相册"), "addViewer": MessageLookupByLibrary.simpleMessage("添加查看者"), + "addViewers": m1, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("立即添加您的照片"), "addedAs": MessageLookupByLibrary.simpleMessage("已添加为"), - "addedBy": m2, - "addedSuccessfullyTo": m3, + "addedBy": m4, + "addedSuccessfullyTo": m5, "addingToFavorites": MessageLookupByLibrary.simpleMessage("正在添加到收藏..."), "advanced": MessageLookupByLibrary.simpleMessage("高级设置"), "advancedSettings": MessageLookupByLibrary.simpleMessage("高级设置"), @@ -230,7 +238,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("1 周后"), "after1Year": MessageLookupByLibrary.simpleMessage("1 年后"), "albumOwner": MessageLookupByLibrary.simpleMessage("所有者"), - "albumParticipantsCount": m4, + "albumParticipantsCount": m6, "albumTitle": MessageLookupByLibrary.simpleMessage("相册标题"), "albumUpdated": MessageLookupByLibrary.simpleMessage("相册已更新"), "albums": MessageLookupByLibrary.simpleMessage("相册"), @@ -259,7 +267,7 @@ class MessageLookup extends MessageLookupByLibrary { "androidIosWebDesktop": MessageLookupByLibrary.simpleMessage("安卓, iOS, 网页端, 桌面端"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("需要身份验证"), - "appVersion": m5, + "appVersion": m7, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("应用"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("应用代码"), @@ -331,9 +339,9 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage("只能删除您拥有的文件"), "cancel": MessageLookupByLibrary.simpleMessage("取消"), - "cancelOtherSubscription": m6, + "cancelOtherSubscription": m8, "cancelSubscription": MessageLookupByLibrary.simpleMessage("取消订阅"), - "cannotAddMorePhotosAfterBecomingViewer": m7, + "cannotAddMorePhotosAfterBecomingViewer": m9, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage("无法删除共享文件"), "castInstruction": MessageLookupByLibrary.simpleMessage( @@ -352,8 +360,10 @@ class MessageLookup extends MessageLookupByLibrary { "claimFreeStorage": MessageLookupByLibrary.simpleMessage("领取免费存储"), "claimMore": MessageLookupByLibrary.simpleMessage("领取更多!"), "claimed": MessageLookupByLibrary.simpleMessage("已领取"), - "claimedStorageSoFar": m8, + "claimedStorageSoFar": m10, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("清除未分类的"), + "cleanUncategorizedDescription": + MessageLookupByLibrary.simpleMessage("从“未分类”中删除其他相册中存在的所有文件"), "clearCaches": MessageLookupByLibrary.simpleMessage("清除缓存"), "clearIndexes": MessageLookupByLibrary.simpleMessage("清空索引"), "click": MessageLookupByLibrary.simpleMessage("• 点击"), @@ -369,7 +379,7 @@ class MessageLookup extends MessageLookupByLibrary { "collabLinkSectionDescription": MessageLookupByLibrary.simpleMessage( "创建一个链接以允许其他人在您的共享相册中添加和查看照片,而无需应用程序或ente账户。 非常适合收集活动照片。"), "collaborativeLink": MessageLookupByLibrary.simpleMessage("协作链接"), - "collaborativeLinkCreatedFor": m9, + "collaborativeLinkCreatedFor": m11, "collaborator": MessageLookupByLibrary.simpleMessage("协作者"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage("协作者可以将照片和视频添加到共享相册中。"), @@ -390,9 +400,9 @@ class MessageLookup extends MessageLookupByLibrary { "confirmRecoveryKey": MessageLookupByLibrary.simpleMessage("确认恢复密钥"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage("确认您的恢复密钥"), - "contactFamilyAdmin": m10, + "contactFamilyAdmin": m12, "contactSupport": MessageLookupByLibrary.simpleMessage("联系支持"), - "contactToManageSubscription": m11, + "contactToManageSubscription": m13, "contacts": MessageLookupByLibrary.simpleMessage("联系人"), "contents": MessageLookupByLibrary.simpleMessage("内容"), "continueLabel": MessageLookupByLibrary.simpleMessage("继续"), @@ -450,10 +460,10 @@ class MessageLookup extends MessageLookupByLibrary { "deleteFromBoth": MessageLookupByLibrary.simpleMessage("同时从两者中删除"), "deleteFromDevice": MessageLookupByLibrary.simpleMessage("从设备中删除"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("从ente 中删除"), - "deleteItemCount": m12, + "deleteItemCount": m14, "deleteLocation": MessageLookupByLibrary.simpleMessage("删除位置"), "deletePhotos": MessageLookupByLibrary.simpleMessage("删除照片"), - "deleteProgress": m13, + "deleteProgress": m15, "deleteReason1": MessageLookupByLibrary.simpleMessage("找不到我想要的功能"), "deleteReason2": MessageLookupByLibrary.simpleMessage("应用或某个功能没有按我的预期运行"), @@ -465,7 +475,7 @@ class MessageLookup extends MessageLookupByLibrary { "deleteSharedAlbum": MessageLookupByLibrary.simpleMessage("要删除共享相册吗?"), "deleteSharedAlbumDialogBody": MessageLookupByLibrary.simpleMessage( "将为所有人删除相册\n\n您将无法访问此相册中他人拥有的共享照片"), - "descriptions": MessageLookupByLibrary.simpleMessage("Descriptions"), + "descriptions": MessageLookupByLibrary.simpleMessage("描述"), "deselectAll": MessageLookupByLibrary.simpleMessage("取消全选"), "designedToOutlive": MessageLookupByLibrary.simpleMessage("经久耐用"), "details": MessageLookupByLibrary.simpleMessage("详情"), @@ -483,7 +493,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("查看者仍然可以使用外部工具截图或保存您的照片副本"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("请注意"), - "disableLinkMessage": m14, + "disableLinkMessage": m16, "disableTwofactor": MessageLookupByLibrary.simpleMessage("禁用双因素认证"), "disablingTwofactorAuthentication": MessageLookupByLibrary.simpleMessage("正在禁用双因素认证..."), @@ -500,9 +510,9 @@ class MessageLookup extends MessageLookupByLibrary { "download": MessageLookupByLibrary.simpleMessage("下载"), "downloadFailed": MessageLookupByLibrary.simpleMessage("下載失敗"), "downloading": MessageLookupByLibrary.simpleMessage("正在下载..."), - "dropSupportEmail": m15, - "duplicateFileCountWithStorageSaved": m16, - "duplicateItemsGroup": m17, + "dropSupportEmail": m17, + "duplicateFileCountWithStorageSaved": m18, + "duplicateItemsGroup": m19, "edit": MessageLookupByLibrary.simpleMessage("编辑"), "editLocation": MessageLookupByLibrary.simpleMessage("编辑位置"), "editLocationTagTitle": MessageLookupByLibrary.simpleMessage("编辑位置"), @@ -511,8 +521,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("对位置的编辑只能在 Ente 内看到"), "eligible": MessageLookupByLibrary.simpleMessage("符合资格"), "email": MessageLookupByLibrary.simpleMessage("电子邮件地址"), - "emailChangedTo": m18, - "emailNoEnteAccount": m19, + "emailChangedTo": m20, + "emailNoEnteAccount": m21, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("电子邮件验证"), "emailYourLogs": MessageLookupByLibrary.simpleMessage("通过电子邮件发送您的日志"), @@ -589,29 +599,29 @@ class MessageLookup extends MessageLookupByLibrary { "fileSavedToGallery": MessageLookupByLibrary.simpleMessage("文件已保存到相册"), "fileTypes": MessageLookupByLibrary.simpleMessage("文件类型"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("文件类型和名称"), - "filesBackedUpFromDevice": m20, - "filesBackedUpInAlbum": m21, + "filesBackedUpFromDevice": m22, + "filesBackedUpInAlbum": m23, "filesDeleted": MessageLookupByLibrary.simpleMessage("文件已删除"), "flip": MessageLookupByLibrary.simpleMessage("上下翻转"), "forYourMemories": MessageLookupByLibrary.simpleMessage("为您的回忆"), "forgotPassword": MessageLookupByLibrary.simpleMessage("忘记密码"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("已领取的免费存储"), - "freeStorageOnReferralSuccess": m22, - "freeStorageSpace": m23, + "freeStorageOnReferralSuccess": m24, + "freeStorageSpace": m25, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("可用的免费存储"), "freeTrial": MessageLookupByLibrary.simpleMessage("免费试用"), - "freeTrialValidTill": m24, - "freeUpAccessPostDelete": m25, - "freeUpAmount": m26, + "freeTrialValidTill": m26, + "freeUpAccessPostDelete": m27, + "freeUpAmount": m28, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("释放设备空间"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("释放空间"), - "freeUpSpaceSaving": m27, + "freeUpSpaceSaving": m29, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage("在图库中显示最多1000个回忆"), "general": MessageLookupByLibrary.simpleMessage("通用"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage("正在生成加密密钥..."), - "genericProgress": m28, + "genericProgress": m30, "goToSettings": MessageLookupByLibrary.simpleMessage("前往设置"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), "grantFullAccessPrompt": @@ -662,7 +672,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "看起来出了点问题。 请稍后重试。 如果错误仍然存在,请联系我们的支持团队。"), - "itemCount": m29, + "itemCount": m31, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage("项目显示永久删除前剩余的天数"), "itemsWillBeRemovedFromAlbum": @@ -685,7 +695,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("设备限制"), "linkEnabled": MessageLookupByLibrary.simpleMessage("已启用"), "linkExpired": MessageLookupByLibrary.simpleMessage("已过期"), - "linkExpiresOn": m30, + "linkExpiresOn": m32, "linkExpiry": MessageLookupByLibrary.simpleMessage("链接过期"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("链接已过期"), "linkNeverExpires": MessageLookupByLibrary.simpleMessage("永不"), @@ -716,7 +726,7 @@ class MessageLookup extends MessageLookupByLibrary { "locationName": MessageLookupByLibrary.simpleMessage("地点名称"), "locationTagFeatureDescription": MessageLookupByLibrary.simpleMessage("位置标签将在照片的某个半径范围内拍摄的所有照片进行分组"), - "locations": MessageLookupByLibrary.simpleMessage("Locations"), + "locations": MessageLookupByLibrary.simpleMessage("位置"), "lockButtonLabel": MessageLookupByLibrary.simpleMessage("锁定"), "lockScreenEnablePreSteps": MessageLookupByLibrary.simpleMessage("要启用锁屏,请在系统设置中设置设备密码或屏幕锁定。"), @@ -728,6 +738,9 @@ class MessageLookup extends MessageLookupByLibrary { "logout": MessageLookupByLibrary.simpleMessage("退出登录"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( "这将跨日志发送以帮助我们调试您的问题。 请注意,将包含文件名以帮助跟踪特定文件的问题。"), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Long press an email to verify end to end encryption."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage("长按一个项目来全屏查看"), "lostDevice": MessageLookupByLibrary.simpleMessage("丢失了设备吗?"), @@ -745,7 +758,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("地图"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m31, + "memoryCount": m33, "merchandise": MessageLookupByLibrary.simpleMessage("商品"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("移动端, 网页端, 桌面端"), @@ -754,10 +767,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("修改您的查询,或尝试搜索"), "moments": MessageLookupByLibrary.simpleMessage("瞬间"), "monthly": MessageLookupByLibrary.simpleMessage("每月"), - "moveItem": m32, + "moveItem": m34, "moveToAlbum": MessageLookupByLibrary.simpleMessage("移动到相册"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("移至隐藏相册"), - "movedSuccessfullyTo": m33, + "movedSuccessfullyTo": m35, "movedToTrash": MessageLookupByLibrary.simpleMessage("已移至回收站"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage("正在将文件移动到相册..."), @@ -819,13 +832,13 @@ class MessageLookup extends MessageLookupByLibrary { "passwordChangedSuccessfully": MessageLookupByLibrary.simpleMessage("密码修改成功"), "passwordLock": MessageLookupByLibrary.simpleMessage("密码锁"), - "passwordStrength": m34, + "passwordStrength": m36, "passwordWarning": MessageLookupByLibrary.simpleMessage( "我们不储存这个密码,所以如果忘记, 我们将无法解密您的数据"), "paymentDetails": MessageLookupByLibrary.simpleMessage("付款明细"), "paymentFailed": MessageLookupByLibrary.simpleMessage("支付失败"), - "paymentFailedTalkToProvider": m35, - "paymentFailedWithReason": m36, + "paymentFailedTalkToProvider": m37, + "paymentFailedWithReason": m38, "pendingItems": MessageLookupByLibrary.simpleMessage("待处理项目"), "pendingSync": MessageLookupByLibrary.simpleMessage("正在等待同步"), "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage("使用您的代码的人"), @@ -843,7 +856,7 @@ class MessageLookup extends MessageLookupByLibrary { "pickCenterPoint": MessageLookupByLibrary.simpleMessage("选择中心点"), "pinAlbum": MessageLookupByLibrary.simpleMessage("置顶相册"), "playOnTv": MessageLookupByLibrary.simpleMessage("在电视上播放相册"), - "playStoreFreeTrialValidTill": m37, + "playStoreFreeTrialValidTill": m39, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore 订阅"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -853,10 +866,10 @@ class MessageLookup extends MessageLookupByLibrary { "请用英语联系 support@ente.io ,我们将乐意提供帮助!"), "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage("如果问题仍然存在,请联系支持"), - "pleaseEmailUsAt": m38, + "pleaseEmailUsAt": m40, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("请授予权限"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("请重新登录"), - "pleaseSendTheLogsTo": m39, + "pleaseSendTheLogsTo": m41, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("请重试"), "pleaseVerifyTheCodeYouHaveEntered": MessageLookupByLibrary.simpleMessage("请验证您输入的代码"), @@ -882,7 +895,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("提升工单"), "rateTheApp": MessageLookupByLibrary.simpleMessage("为此应用评分"), "rateUs": MessageLookupByLibrary.simpleMessage("给我们评分"), - "rateUsOnStore": m40, + "rateUsOnStore": m42, "recover": MessageLookupByLibrary.simpleMessage("恢复"), "recoverAccount": MessageLookupByLibrary.simpleMessage("恢复账户"), "recoverButton": MessageLookupByLibrary.simpleMessage("恢复"), @@ -907,7 +920,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("把我们推荐给你的朋友然后获得延长一倍的订阅计划"), "referralStep1": MessageLookupByLibrary.simpleMessage("1. 将此代码提供给您的朋友"), "referralStep2": MessageLookupByLibrary.simpleMessage("2. 他们注册一个付费计划"), - "referralStep3": m41, + "referralStep3": m43, "referrals": MessageLookupByLibrary.simpleMessage("推荐人"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage("推荐已暂停"), @@ -926,7 +939,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeFromFavorite": MessageLookupByLibrary.simpleMessage("从收藏中移除"), "removeLink": MessageLookupByLibrary.simpleMessage("移除链接"), "removeParticipant": MessageLookupByLibrary.simpleMessage("移除参与者"), - "removeParticipantBody": m42, + "removeParticipantBody": m44, "removePublicLink": MessageLookupByLibrary.simpleMessage("删除公开链接"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage("您要删除的某些项目是由其他人添加的,您将无法访问它们"), @@ -937,7 +950,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameAlbum": MessageLookupByLibrary.simpleMessage("重命名相册"), "renameFile": MessageLookupByLibrary.simpleMessage("重命名文件"), "renewSubscription": MessageLookupByLibrary.simpleMessage("续费订阅"), - "renewsOn": m43, + "renewsOn": m45, "reportABug": MessageLookupByLibrary.simpleMessage("报告错误"), "reportBug": MessageLookupByLibrary.simpleMessage("报告错误"), "resendEmail": MessageLookupByLibrary.simpleMessage("重新发送电子邮件"), @@ -984,7 +997,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("在照片的一定半径内拍摄的几组照片"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage("邀请他人,您将在此看到他们分享的所有照片"), - "searchResultCount": m44, + "searchResultCount": m46, "security": MessageLookupByLibrary.simpleMessage("安全"), "selectALocation": MessageLookupByLibrary.simpleMessage("选择一个位置"), "selectALocationFirst": @@ -1004,8 +1017,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("所选文件夹将被加密和备份"), "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage("所选项目将从所有相册中删除并移动到回收站。"), - "selectedPhotos": m45, - "selectedPhotosWithYours": m46, + "selectedPhotos": m47, + "selectedPhotosWithYours": m48, "send": MessageLookupByLibrary.simpleMessage("发送"), "sendEmail": MessageLookupByLibrary.simpleMessage("发送电子邮件"), "sendInvite": MessageLookupByLibrary.simpleMessage("发送邀请"), @@ -1024,16 +1037,16 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("打开相册并点击右上角的分享按钮进行分享"), "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("立即分享相册"), "shareLink": MessageLookupByLibrary.simpleMessage("分享链接"), - "shareMyVerificationID": m47, + "shareMyVerificationID": m49, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage("仅与您想要的人分享"), - "shareTextConfirmOthersVerificationID": m48, + "shareTextConfirmOthersVerificationID": m50, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "下载 ente,以便我们轻松分享原始质量的照片和视频\n\nhttps://ente.io"), - "shareTextReferralCode": m49, + "shareTextReferralCode": m51, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage("与非ente 用户分享"), - "shareWithPeopleSectionTitle": m50, + "shareWithPeopleSectionTitle": m52, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("分享您的第一个相册"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1044,7 +1057,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("新共享的照片"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage("当有人将照片添加到您所属的共享相册时收到通知"), - "sharedWith": m51, + "sharedWith": m53, "sharedWithMe": MessageLookupByLibrary.simpleMessage("与我共享"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("已与您共享"), "sharing": MessageLookupByLibrary.simpleMessage("正在分享..."), @@ -1056,11 +1069,11 @@ class MessageLookup extends MessageLookupByLibrary { "signOutOtherDevices": MessageLookupByLibrary.simpleMessage("登出其他设备"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "我同意 服务条款隐私政策"), - "singleFileDeleteFromDevice": m52, + "singleFileDeleteFromDevice": m54, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage("它将从所有相册中删除。"), - "singleFileInBothLocalAndRemote": m53, - "singleFileInRemoteOnly": m54, + "singleFileInBothLocalAndRemote": m55, + "singleFileInRemoteOnly": m56, "skip": MessageLookupByLibrary.simpleMessage("跳过"), "social": MessageLookupByLibrary.simpleMessage("社交"), "someItemsAreInBothEnteAndYourDevice": @@ -1091,12 +1104,12 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("存储空间"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("家庭"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("您"), - "storageInGB": m55, + "storageInGB": m57, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("已超出存储限制"), - "storageUsageInfo": m56, + "storageUsageInfo": m58, "strongStrength": MessageLookupByLibrary.simpleMessage("强"), - "subAlreadyLinkedErrMessage": m57, - "subWillBeCancelledOn": m58, + "subAlreadyLinkedErrMessage": m59, + "subWillBeCancelledOn": m60, "subscribe": MessageLookupByLibrary.simpleMessage("订阅"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage("您的订阅似乎已过期。请订阅以启用分享。"), @@ -1109,7 +1122,7 @@ class MessageLookup extends MessageLookupByLibrary { "successfullyUnhid": MessageLookupByLibrary.simpleMessage("已成功取消隐藏"), "suggestFeatures": MessageLookupByLibrary.simpleMessage("建议新功能"), "support": MessageLookupByLibrary.simpleMessage("支持"), - "syncProgress": m59, + "syncProgress": m61, "syncStopped": MessageLookupByLibrary.simpleMessage("同步已停止"), "syncing": MessageLookupByLibrary.simpleMessage("正在同步···"), "systemTheme": MessageLookupByLibrary.simpleMessage("适应系统"), @@ -1132,7 +1145,7 @@ class MessageLookup extends MessageLookupByLibrary { "theme": MessageLookupByLibrary.simpleMessage("主题"), "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage("这些项目将从您的设备中删除。"), - "theyAlsoGetXGb": m60, + "theyAlsoGetXGb": m62, "theyWillBeDeletedFromAllAlbums": MessageLookupByLibrary.simpleMessage("他们将从所有相册中删除。"), "thisActionCannotBeUndone": @@ -1146,7 +1159,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("这个邮箱地址已经被使用"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage("此图像没有Exif 数据"), - "thisIsPersonVerificationId": m61, + "thisIsPersonVerificationId": m63, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage("这是您的验证 ID"), "thisWillLogYouOutOfTheFollowingDevice": @@ -1160,7 +1173,7 @@ class MessageLookup extends MessageLookupByLibrary { "total": MessageLookupByLibrary.simpleMessage("总计"), "totalSize": MessageLookupByLibrary.simpleMessage("总大小"), "trash": MessageLookupByLibrary.simpleMessage("回收站"), - "trashDaysLeft": m62, + "trashDaysLeft": m64, "tryAgain": MessageLookupByLibrary.simpleMessage("请再试一次"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage("打开备份以自动上传添加到此设备文件夹的文件。"), @@ -1203,14 +1216,15 @@ class MessageLookup extends MessageLookupByLibrary { "useRecoveryKey": MessageLookupByLibrary.simpleMessage("使用恢复密钥"), "useSelectedPhoto": MessageLookupByLibrary.simpleMessage("使用所选照片"), "usedSpace": MessageLookupByLibrary.simpleMessage("已用空间"), - "validTill": m63, + "validTill": m65, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage("验证失败,请重试"), "verificationId": MessageLookupByLibrary.simpleMessage("验证 ID"), "verify": MessageLookupByLibrary.simpleMessage("验证"), "verifyEmail": MessageLookupByLibrary.simpleMessage("验证电子邮件"), - "verifyEmailID": m64, + "verifyEmailID": m66, "verifyIDLabel": MessageLookupByLibrary.simpleMessage("验证"), + "verifyPasskey": MessageLookupByLibrary.simpleMessage("验证通行密钥"), "verifyPassword": MessageLookupByLibrary.simpleMessage("验证密码"), "verifying": MessageLookupByLibrary.simpleMessage("正在验证..."), "verifyingRecoveryKey": @@ -1226,15 +1240,17 @@ class MessageLookup extends MessageLookupByLibrary { "viewer": MessageLookupByLibrary.simpleMessage("查看者"), "visitWebToManage": MessageLookupByLibrary.simpleMessage("请访问 web.ente.io 来管理您的订阅"), + "waitingForVerification": + MessageLookupByLibrary.simpleMessage("等待验证..."), "waitingForWifi": MessageLookupByLibrary.simpleMessage("正在等待 WiFi..."), "weAreOpenSource": MessageLookupByLibrary.simpleMessage("我们是开源的 !"), "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage("我们不支持编辑您尚未拥有的照片和相册"), - "weHaveSendEmailTo": m65, + "weHaveSendEmailTo": m67, "weakStrength": MessageLookupByLibrary.simpleMessage("弱"), "welcomeBack": MessageLookupByLibrary.simpleMessage("欢迎回来!"), "yearly": MessageLookupByLibrary.simpleMessage("每年"), - "yearsAgo": m66, + "yearsAgo": m68, "yes": MessageLookupByLibrary.simpleMessage("是"), "yesCancel": MessageLookupByLibrary.simpleMessage("是的,取消"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage("是的,转换为查看者"), @@ -1260,7 +1276,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("莫开玩笑,您不能与自己分享"), "youDontHaveAnyArchivedItems": MessageLookupByLibrary.simpleMessage("您没有任何存档的项目。"), - "youHaveSuccessfullyFreedUp": m67, + "youHaveSuccessfullyFreedUp": m69, "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("您的账户已删除"), "yourMap": MessageLookupByLibrary.simpleMessage("您的地图"), diff --git a/mobile/lib/generated/l10n.dart b/mobile/lib/generated/l10n.dart index 03b753399d..78e376d486 100644 --- a/mobile/lib/generated/l10n.dart +++ b/mobile/lib/generated/l10n.dart @@ -8427,6 +8427,42 @@ class S { args: [], ); } + + /// `{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}` + String addViewers(num count) { + return Intl.plural( + count, + zero: 'Add viewer', + one: 'Add viewer', + other: 'Add viewers', + name: 'addViewers', + desc: '', + args: [count], + ); + } + + /// `{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}` + String addCollaborators(num count) { + return Intl.plural( + count, + zero: 'Add collaborator', + one: 'Add collaborator', + other: 'Add collaborators', + name: 'addCollaborators', + desc: '', + args: [count], + ); + } + + /// `Long press an email to verify end to end encryption.` + String get longPressAnEmailToVerifyEndToEndEncryption { + return Intl.message( + 'Long press an email to verify end to end encryption.', + name: 'longPressAnEmailToVerifyEndToEndEncryption', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/mobile/lib/l10n/intl_cs.arb b/mobile/lib/l10n/intl_cs.arb index d9ce7ebeb1..b552b10528 100644 --- a/mobile/lib/l10n/intl_cs.arb +++ b/mobile/lib/l10n/intl_cs.arb @@ -13,5 +13,8 @@ "editsToLocationWillOnlyBeSeenWithinEnte": "Edits to location will only be seen within Ente", "joinDiscord": "Join Discord", "locations": "Locations", - "descriptions": "Descriptions" + "descriptions": "Descriptions", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_de.arb b/mobile/lib/l10n/intl_de.arb index 50a4a1b219..6b971ff63a 100644 --- a/mobile/lib/l10n/intl_de.arb +++ b/mobile/lib/l10n/intl_de.arb @@ -1199,5 +1199,8 @@ "deviceCodeHint": "Code eingeben", "joinDiscord": "Discord beitreten", "locations": "Orte", - "descriptions": "Beschreibungen" + "descriptions": "Beschreibungen", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_en.arb b/mobile/lib/l10n/intl_en.arb index 16b2031280..eff0f89408 100644 --- a/mobile/lib/l10n/intl_en.arb +++ b/mobile/lib/l10n/intl_en.arb @@ -1199,5 +1199,8 @@ "deviceCodeHint": "Enter the code", "joinDiscord": "Join Discord", "locations": "Locations", - "descriptions": "Descriptions" + "descriptions": "Descriptions", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_es.arb b/mobile/lib/l10n/intl_es.arb index cbbb60a451..fcdff5ccfc 100644 --- a/mobile/lib/l10n/intl_es.arb +++ b/mobile/lib/l10n/intl_es.arb @@ -975,5 +975,8 @@ "editsToLocationWillOnlyBeSeenWithinEnte": "Edits to location will only be seen within Ente", "joinDiscord": "Join Discord", "locations": "Locations", - "descriptions": "Descriptions" + "descriptions": "Descriptions", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_fr.arb b/mobile/lib/l10n/intl_fr.arb index f0afcaa98e..d24e118271 100644 --- a/mobile/lib/l10n/intl_fr.arb +++ b/mobile/lib/l10n/intl_fr.arb @@ -1156,5 +1156,8 @@ "editsToLocationWillOnlyBeSeenWithinEnte": "Edits to location will only be seen within Ente", "joinDiscord": "Join Discord", "locations": "Locations", - "descriptions": "Descriptions" + "descriptions": "Descriptions", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_it.arb b/mobile/lib/l10n/intl_it.arb index be0dc1e2c6..ef8eeda349 100644 --- a/mobile/lib/l10n/intl_it.arb +++ b/mobile/lib/l10n/intl_it.arb @@ -1118,5 +1118,8 @@ "editsToLocationWillOnlyBeSeenWithinEnte": "Edits to location will only be seen within Ente", "joinDiscord": "Join Discord", "locations": "Locations", - "descriptions": "Descriptions" + "descriptions": "Descriptions", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ko.arb b/mobile/lib/l10n/intl_ko.arb index d9ce7ebeb1..b552b10528 100644 --- a/mobile/lib/l10n/intl_ko.arb +++ b/mobile/lib/l10n/intl_ko.arb @@ -13,5 +13,8 @@ "editsToLocationWillOnlyBeSeenWithinEnte": "Edits to location will only be seen within Ente", "joinDiscord": "Join Discord", "locations": "Locations", - "descriptions": "Descriptions" + "descriptions": "Descriptions", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_nl.arb b/mobile/lib/l10n/intl_nl.arb index 0f2ab0ec2a..43ca7ee5d2 100644 --- a/mobile/lib/l10n/intl_nl.arb +++ b/mobile/lib/l10n/intl_nl.arb @@ -1194,5 +1194,8 @@ "deviceCodeHint": "Voer de code in", "joinDiscord": "Join Discord", "locations": "Locations", - "descriptions": "Descriptions" + "descriptions": "Descriptions", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_no.arb b/mobile/lib/l10n/intl_no.arb index 8d40561fce..b4ba1d96d3 100644 --- a/mobile/lib/l10n/intl_no.arb +++ b/mobile/lib/l10n/intl_no.arb @@ -27,5 +27,8 @@ "editsToLocationWillOnlyBeSeenWithinEnte": "Edits to location will only be seen within Ente", "joinDiscord": "Join Discord", "locations": "Locations", - "descriptions": "Descriptions" + "descriptions": "Descriptions", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_pl.arb b/mobile/lib/l10n/intl_pl.arb index 6bd5a30aa2..8dd33fda6e 100644 --- a/mobile/lib/l10n/intl_pl.arb +++ b/mobile/lib/l10n/intl_pl.arb @@ -114,5 +114,8 @@ "editsToLocationWillOnlyBeSeenWithinEnte": "Edits to location will only be seen within Ente", "joinDiscord": "Join Discord", "locations": "Locations", - "descriptions": "Descriptions" + "descriptions": "Descriptions", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_pt.arb b/mobile/lib/l10n/intl_pt.arb index bf0e534097..9c47deb671 100644 --- a/mobile/lib/l10n/intl_pt.arb +++ b/mobile/lib/l10n/intl_pt.arb @@ -1199,5 +1199,8 @@ "deviceCodeHint": "Insira o código", "joinDiscord": "Junte-se ao Discord", "locations": "Locais", - "descriptions": "Descrições" + "descriptions": "Descrições", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_zh.arb b/mobile/lib/l10n/intl_zh.arb index 4e9e9e4eb1..dd9b9f160e 100644 --- a/mobile/lib/l10n/intl_zh.arb +++ b/mobile/lib/l10n/intl_zh.arb @@ -1199,5 +1199,8 @@ "deviceCodeHint": "输入代码", "joinDiscord": "加入 Discord", "locations": "位置", - "descriptions": "描述" + "descriptions": "描述", + "addViewers": "{count, plural, zero {Add viewer} one {Add viewer} other {Add viewers}}", + "addCollaborators": "{count, plural, zero {Add collaborator} one {Add collaborator} other {Add collaborators}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Long press an email to verify end to end encryption." } \ No newline at end of file diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_partipant_page.dart index 36c82b9f2b..91378b3a5b 100644 --- a/mobile/lib/ui/sharing/add_partipant_page.dart +++ b/mobile/lib/ui/sharing/add_partipant_page.dart @@ -117,9 +117,10 @@ class _AddParticipantPage extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ filterSuggestedUsers.isNotEmpty - ? const MenuSectionDescriptionWidget( - content: - "Long press an email to verify.", + ? MenuSectionDescriptionWidget( + content: S + .of(context) + .longPressAnEmailToVerifyEndToEndEncryption, ) : const SizedBox.shrink(), widget.isAddingViewer @@ -213,8 +214,10 @@ class _AddParticipantPage extends State { buttonType: ButtonType.primary, buttonSize: ButtonSize.large, labelText: widget.isAddingViewer - ? S.of(context).addViewer - : S.of(context).addCollaborator, + ? S.of(context).addViewers(_selectedEmails.length) + : S + .of(context) + .addCollaborators(_selectedEmails.length), isDisabled: _selectedEmails.isEmpty, onTap: () async { final results = []; From bb622bfcd0657ba1dfa8c9872a3f0ae2f17ef734 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 15 Mar 2024 20:49:51 +0530 Subject: [PATCH 343/391] fix typo in file name --- .../{add_partipant_page.dart => add_participant_page.dart} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename mobile/lib/ui/sharing/{add_partipant_page.dart => add_participant_page.dart} (100%) diff --git a/mobile/lib/ui/sharing/add_partipant_page.dart b/mobile/lib/ui/sharing/add_participant_page.dart similarity index 100% rename from mobile/lib/ui/sharing/add_partipant_page.dart rename to mobile/lib/ui/sharing/add_participant_page.dart From 64814ef82f77bc07cf00708d2a7dd2230b583036 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Fri, 15 Mar 2024 21:07:38 +0530 Subject: [PATCH 344/391] minor fixes --- mobile/lib/ui/sharing/album_participants_page.dart | 2 +- mobile/lib/ui/sharing/share_collection_page.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/lib/ui/sharing/album_participants_page.dart b/mobile/lib/ui/sharing/album_participants_page.dart index 494df319f1..0c137f3001 100644 --- a/mobile/lib/ui/sharing/album_participants_page.dart +++ b/mobile/lib/ui/sharing/album_participants_page.dart @@ -11,7 +11,7 @@ import 'package:photos/ui/components/menu_item_widget/menu_item_widget.dart'; import 'package:photos/ui/components/menu_section_title.dart'; import 'package:photos/ui/components/title_bar_title_widget.dart'; import 'package:photos/ui/components/title_bar_widget.dart'; -import 'package:photos/ui/sharing/add_partipant_page.dart'; +import "package:photos/ui/sharing/add_participant_page.dart"; import 'package:photos/ui/sharing/manage_album_participant.dart'; import 'package:photos/ui/sharing/user_avator_widget.dart'; import 'package:photos/utils/navigation_util.dart'; diff --git a/mobile/lib/ui/sharing/share_collection_page.dart b/mobile/lib/ui/sharing/share_collection_page.dart index e63a39f3e6..8e515fc68c 100644 --- a/mobile/lib/ui/sharing/share_collection_page.dart +++ b/mobile/lib/ui/sharing/share_collection_page.dart @@ -13,7 +13,7 @@ import 'package:photos/ui/components/divider_widget.dart'; import 'package:photos/ui/components/menu_item_widget/menu_item_widget.dart'; import 'package:photos/ui/components/menu_section_description_widget.dart'; import 'package:photos/ui/components/menu_section_title.dart'; -import 'package:photos/ui/sharing/add_partipant_page.dart'; +import "package:photos/ui/sharing/add_participant_page.dart"; import 'package:photos/ui/sharing/album_participants_page.dart'; import "package:photos/ui/sharing/album_share_info_widget.dart"; import "package:photos/ui/sharing/manage_album_participant.dart"; From 36982c5332682f2ccd774e0bd5efe110897100f2 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Sat, 16 Mar 2024 02:30:25 +0530 Subject: [PATCH 345/391] [server] Add util to findMissingElements while comparing two arrays --- server/pkg/utils/array/array.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/server/pkg/utils/array/array.go b/server/pkg/utils/array/array.go index 98869ad5dd..46d1e31132 100644 --- a/server/pkg/utils/array/array.go +++ b/server/pkg/utils/array/array.go @@ -47,3 +47,36 @@ func Int64InList(a int64, list []int64) bool { } return false } + +// FindMissingElementsInSecondList identifies elements in 'sourceList' that are not present in 'targetList'. +// +// This function creates a set from 'targetList' for efficient lookup, then iterates through 'sourceList' +// to identify which elements are missing in 'targetList'. This method is particularly efficient for large +// lists, as it avoids the quadratic complexity of nested iterations by utilizing a hash set for O(1) lookups. +// +// Parameters: +// - sourceList: An array of int64 elements to check against 'targetList'. +// - targetList: An array of int64 elements used as the reference set to identify missing elements from 'sourceList'. +// +// Returns: +// - A slice of int64 representing the elements found in 'sourceList' but not in 'targetList'. +// If all elements of 'sourceList' are present in 'targetList', an empty slice is returned. +// +// Example usage: +// missingElements := FindMissingElementsInSecondList([]int64{1, 2, 3, 4}, []int64{2, 4, 6}) +// fmt.Println(missingElements) // Output: [1, 3] +func FindMissingElementsInSecondList(sourceList []int64, targetList []int64) []int64 { + targetSet := make(map[int64]struct{}) + for _, item := range targetList { + targetSet[item] = struct{}{} + } + + var missingElements []int64 + for _, item := range sourceList { + if _, found := targetSet[item]; !found { + missingElements = append(missingElements, item) + } + } + + return missingElements +} From b78b2fe715a1d249e0a98284c3e1b31e8213a957 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta Date: Sat, 16 Mar 2024 23:57:05 +0530 Subject: [PATCH 346/391] Delete yarn.lock --- yarn.lock | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index fb57ccd13a..0000000000 --- a/yarn.lock +++ /dev/null @@ -1,4 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - From e927064476bec33eb9fc19422b0216e485b78613 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Sun, 17 Mar 2024 09:37:02 +0530 Subject: [PATCH 347/391] [server] Add endpoint to get embedding for givenFilesIds --- server/cmd/museum/main.go | 1 + server/ente/embedding.go | 27 ++-- server/pkg/api/embedding.go | 16 +++ server/pkg/controller/embedding/controller.go | 117 +++++++++++++++++- server/pkg/repo/embedding/repository.go | 10 ++ 5 files changed, 162 insertions(+), 9 deletions(-) diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 9403efaa5a..5dc1bc0b77 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -679,6 +679,7 @@ func main() { privateAPI.PUT("/embeddings", embeddingHandler.InsertOrUpdate) privateAPI.GET("/embeddings/diff", embeddingHandler.GetDiff) + privateAPI.GET("/embeddings/files", embeddingHandler.GetFilesEmbedding) privateAPI.DELETE("/embeddings", embeddingHandler.DeleteAll) offerHandler := &api.OfferHandler{Controller: offerController} diff --git a/server/ente/embedding.go b/server/ente/embedding.go index b59332ec6c..2a92adf792 100644 --- a/server/ente/embedding.go +++ b/server/ente/embedding.go @@ -1,11 +1,12 @@ package ente type Embedding struct { - FileID int64 `json:"fileID"` - Model string `json:"model"` - EncryptedEmbedding string `json:"encryptedEmbedding"` - DecryptionHeader string `json:"decryptionHeader"` - UpdatedAt int64 `json:"updatedAt"` + FileID int64 `json:"fileID"` + Model string `json:"model"` + EncryptedEmbedding string `json:"encryptedEmbedding"` + DecryptionHeader string `json:"decryptionHeader"` + UpdatedAt int64 `json:"updatedAt"` + Client *string `json:"client,omitempty"` } type InsertOrUpdateEmbeddingRequest struct { @@ -22,11 +23,23 @@ type GetEmbeddingDiffRequest struct { Limit int16 `form:"limit" binding:"required"` } +type GetFilesEmbeddingRequest struct { + Model Model `form:"model" binding:"required"` + FileIDs []int64 `form:"fileIDs" binding:"required"` +} + +type GetFilesEmbeddingResponse struct { + Embeddings []Embedding `json:"embeddings"` + NoDataFileIDs []int64 `json:"noDataFileIDs"` + ErrFileIDs []int64 `json:"errFileIDs"` +} + type Model string const ( - OnnxClip Model = "onnx-clip" - GgmlClip Model = "ggml-clip" + OnnxClip Model = "onnx-clip" + GgmlClip Model = "ggml-clip" + OnnxYolo5MobileNet Model = "onnx-yolo5-mobile" ) type EmbeddingObject struct { diff --git a/server/pkg/api/embedding.go b/server/pkg/api/embedding.go index 983bed52cf..4b072b0b70 100644 --- a/server/pkg/api/embedding.go +++ b/server/pkg/api/embedding.go @@ -50,6 +50,22 @@ func (h *EmbeddingHandler) GetDiff(c *gin.Context) { }) } +// GetFilesEmbedding returns the embeddings for the files +func (h *EmbeddingHandler) GetFilesEmbedding(c *gin.Context) { + var request ente.GetFilesEmbeddingRequest + if err := c.ShouldBindQuery(&request); err != nil { + handler.Error(c, + stacktrace.Propagate(ente.ErrBadRequest, fmt.Sprintf("Request binding failed %s", err))) + return + } + resp, err := h.Controller.GetFilesEmbedding(c, request) + if err != nil { + handler.Error(c, stacktrace.Propagate(err, "")) + return + } + c.JSON(http.StatusOK, resp) +} + // DeleteAll handler for deleting all embeddings for the user func (h *EmbeddingHandler) DeleteAll(c *gin.Context) { err := h.Controller.DeleteAll(c) diff --git a/server/pkg/controller/embedding/controller.go b/server/pkg/controller/embedding/controller.go index ce086aadbf..fd124e12ac 100644 --- a/server/pkg/controller/embedding/controller.go +++ b/server/pkg/controller/embedding/controller.go @@ -1,11 +1,12 @@ package embedding import ( + "bytes" "encoding/json" "errors" "fmt" + "github.com/ente-io/museum/pkg/utils/array" "strconv" - "strings" "sync" "github.com/aws/aws-sdk-go/aws" @@ -118,6 +119,61 @@ func (c *Controller) GetDiff(ctx *gin.Context, req ente.GetEmbeddingDiffRequest) return embeddings, nil } +func (c *Controller) GetFilesEmbedding(ctx *gin.Context, req ente.GetFilesEmbeddingRequest) (*ente.GetFilesEmbeddingResponse, error) { + userID := auth.GetUserID(ctx.Request.Header) + if err := c._validateGetFileEmbeddingsRequest(ctx, userID, req); err != nil { + return nil, stacktrace.Propagate(err, "") + } + + userFileEmbeddings, err := c.Repo.GetFilesEmbedding(ctx, userID, req.Model, req.FileIDs) + if err != nil { + return nil, stacktrace.Propagate(err, "") + } + + dbFileIds := make([]int64, 0) + for _, embedding := range userFileEmbeddings { + dbFileIds = append(dbFileIds, embedding.FileID) + } + missingFileIds := array.FindMissingElementsInSecondList(req.FileIDs, dbFileIds) + errFileIds := make([]int64, 0) + + // Collect object keys for userFileEmbeddings with missing data + var objectKeys []string + for i := range userFileEmbeddings { + objectKey := c.getObjectKey(userID, userFileEmbeddings[i].FileID, userFileEmbeddings[i].Model) + objectKeys = append(objectKeys, objectKey) + } + + // Fetch missing userFileEmbeddings in parallel + embeddingObjects, err := c.getEmbeddingObjectsParallelV2(userID, userFileEmbeddings) + if err != nil { + return nil, stacktrace.Propagate(err, "") + } + fetchedEmbeddings := make([]ente.Embedding, 0) + + // Populate missing data in userFileEmbeddings from fetched objects + for _, obj := range embeddingObjects { + if obj.err != nil { + errFileIds = append(errFileIds, obj.dbEmbeddingRow.FileID) + } else { + fetchedEmbeddings = append(fetchedEmbeddings, ente.Embedding{ + FileID: obj.dbEmbeddingRow.FileID, + Model: obj.dbEmbeddingRow.Model, + EncryptedEmbedding: obj.embeddingObject.EncryptedEmbedding, + DecryptionHeader: obj.embeddingObject.DecryptionHeader, + UpdatedAt: obj.dbEmbeddingRow.UpdatedAt, + Client: obj.dbEmbeddingRow.Client, + }) + } + } + + return &ente.GetFilesEmbeddingResponse{ + Embeddings: fetchedEmbeddings, + NoDataFileIDs: missingFileIds, + ErrFileIDs: errFileIds, + }, nil +} + func (c *Controller) DeleteAll(ctx *gin.Context) error { userID := auth.GetUserID(ctx.Request.Header) @@ -208,7 +264,7 @@ func (c *Controller) uploadObject(obj ente.EmbeddingObject, key string) error { up := s3manager.UploadInput{ Bucket: c.S3Config.GetHotBucket(), Key: &key, - Body: strings.NewReader(string(embeddingObj)), + Body: bytes.NewReader(embeddingObj), } result, err := uploader.Upload(&up) if err != nil { @@ -253,6 +309,44 @@ func (c *Controller) getEmbeddingObjectsParallel(objectKeys []string) ([]ente.Em return embeddingObjects, nil } +type embeddingObjectResult struct { + embeddingObject ente.EmbeddingObject + dbEmbeddingRow ente.Embedding + err error +} + +func (c *Controller) getEmbeddingObjectsParallelV2(userID int64, dbEmbeddingRows []ente.Embedding) ([]embeddingObjectResult, error) { + var wg sync.WaitGroup + embeddingObjects := make([]embeddingObjectResult, len(dbEmbeddingRows)) + downloader := s3manager.NewDownloaderWithClient(c.S3Config.GetHotS3Client()) + + for i, dbEmbeddingRow := range dbEmbeddingRows { + wg.Add(1) + globalFetchSemaphore <- struct{}{} // Acquire from global semaphore + go func(i int, dbEmbeddingRow ente.Embedding) { + defer wg.Done() + defer func() { <-globalFetchSemaphore }() // Release back to global semaphore + objectKey := c.getObjectKey(userID, dbEmbeddingRow.FileID, dbEmbeddingRow.Model) + obj, err := c.getEmbeddingObject(objectKey, downloader) + if err != nil { + log.Error("error fetching embedding object: "+objectKey, err) + embeddingObjects[i] = embeddingObjectResult{ + err: err, + dbEmbeddingRow: dbEmbeddingRow, + } + + } else { + embeddingObjects[i] = embeddingObjectResult{ + embeddingObject: obj, + dbEmbeddingRow: dbEmbeddingRow, + } + } + }(i, dbEmbeddingRow) + } + wg.Wait() + return embeddingObjects, nil +} + func (c *Controller) getEmbeddingObject(objectKey string, downloader *s3manager.Downloader) (ente.EmbeddingObject, error) { var obj ente.EmbeddingObject buff := &aws.WriteAtBuffer{} @@ -271,3 +365,22 @@ func (c *Controller) getEmbeddingObject(objectKey string, downloader *s3manager. } return obj, nil } + +func (c *Controller) _validateGetFileEmbeddingsRequest(ctx *gin.Context, userID int64, req ente.GetFilesEmbeddingRequest) error { + if req.Model == "" { + return ente.NewBadRequestWithMessage("model is required") + } + if len(req.FileIDs) == 0 { + return ente.NewBadRequestWithMessage("fileIDs are required") + } + if len(req.FileIDs) > 100 { + return ente.NewBadRequestWithMessage("fileIDs should be less than or equal to 100") + } + if err := c.AccessCtrl.VerifyFileOwnership(ctx, &access.VerifyFileOwnershipParams{ + ActorUserId: userID, + FileIDs: req.FileIDs, + }); err != nil { + return stacktrace.Propagate(err, "User does not own some file(s)") + } + return nil +} diff --git a/server/pkg/repo/embedding/repository.go b/server/pkg/repo/embedding/repository.go index e44753b24a..90e8a82642 100644 --- a/server/pkg/repo/embedding/repository.go +++ b/server/pkg/repo/embedding/repository.go @@ -55,6 +55,16 @@ func (r *Repository) GetDiff(ctx context.Context, ownerID int64, model ente.Mode return convertRowsToEmbeddings(rows) } +func (r *Repository) GetFilesEmbedding(ctx context.Context, ownerID int64, model ente.Model, fileIDs []int64) ([]ente.Embedding, error) { + rows, err := r.DB.QueryContext(ctx, `SELECT file_id, model, encrypted_embedding, decryption_header, updated_at + FROM embeddings + WHERE owner_id = $1 AND model = $2 AND file_id = ANY($3)`, ownerID, model, fileIDs) + if err != nil { + return nil, stacktrace.Propagate(err, "") + } + return convertRowsToEmbeddings(rows) +} + func (r *Repository) DeleteAll(ctx context.Context, ownerID int64) error { _, err := r.DB.ExecContext(ctx, "DELETE FROM embeddings WHERE owner_id = $1", ownerID) if err != nil { From 12b9ac4db6e87056649a0a0390b3153e5a639da0 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta Date: Sun, 17 Mar 2024 09:59:59 +0530 Subject: [PATCH 348/391] [server] Rate limit (#1121) ## Description ## Tests --- server/cmd/museum/main.go | 19 +++++++------ server/pkg/middleware/rate_limit.go | 44 +++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 14ceb3e3bd..5ea4f33896 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -178,7 +178,8 @@ func main() { authCache := cache.New(1*time.Minute, 15*time.Minute) accessTokenCache := cache.New(1*time.Minute, 15*time.Minute) discordController := discord.NewDiscordController(userRepo, hostName, environment) - rateLimiter := middleware.NewRateLimitMiddleware(discordController) + rateLimiter := middleware.NewRateLimitMiddleware(discordController, 5000, 5*time.Second) + defer rateLimiter.Stop() emailNotificationCtrl := &email.EmailNotificationController{ UserRepo: userRepo, @@ -360,22 +361,22 @@ func main() { server.Use(requestid.New(), middleware.Logger(urlSanitizer), cors(), gzip.Gzip(gzip.DefaultCompression), middleware.PanicRecover()) publicAPI := server.Group("/") - publicAPI.Use(rateLimiter.APIRateLimitMiddleware(urlSanitizer)) + publicAPI.Use(rateLimiter.GlobalRateLimiter(), rateLimiter.APIRateLimitMiddleware(urlSanitizer)) privateAPI := server.Group("/") - privateAPI.Use(authMiddleware.TokenAuthMiddleware(nil), rateLimiter.APIRateLimitForUserMiddleware(urlSanitizer)) + privateAPI.Use(rateLimiter.GlobalRateLimiter(), authMiddleware.TokenAuthMiddleware(nil), rateLimiter.APIRateLimitForUserMiddleware(urlSanitizer)) adminAPI := server.Group("/admin") - adminAPI.Use(authMiddleware.TokenAuthMiddleware(nil), authMiddleware.AdminAuthMiddleware()) + adminAPI.Use(rateLimiter.GlobalRateLimiter(), authMiddleware.TokenAuthMiddleware(nil), authMiddleware.AdminAuthMiddleware()) paymentJwtAuthAPI := server.Group("/") - paymentJwtAuthAPI.Use(authMiddleware.TokenAuthMiddleware(jwt.PAYMENT.Ptr())) + paymentJwtAuthAPI.Use(rateLimiter.GlobalRateLimiter(), authMiddleware.TokenAuthMiddleware(jwt.PAYMENT.Ptr())) familiesJwtAuthAPI := server.Group("/") //The middleware order matters. First, the userID must be set in the context, so that we can apply limit for user. - familiesJwtAuthAPI.Use(authMiddleware.TokenAuthMiddleware(jwt.FAMILIES.Ptr()), rateLimiter.APIRateLimitForUserMiddleware(urlSanitizer)) + familiesJwtAuthAPI.Use(rateLimiter.GlobalRateLimiter(), authMiddleware.TokenAuthMiddleware(jwt.FAMILIES.Ptr()), rateLimiter.APIRateLimitForUserMiddleware(urlSanitizer)) publicCollectionAPI := server.Group("/public-collection") - publicCollectionAPI.Use(accessTokenMiddleware.AccessTokenAuthMiddleware(urlSanitizer)) + publicCollectionAPI.Use(rateLimiter.GlobalRateLimiter(), accessTokenMiddleware.AccessTokenAuthMiddleware(urlSanitizer)) healthCheckHandler := &api.HealthCheckHandler{ DB: db, @@ -472,7 +473,7 @@ func main() { privateAPI.DELETE("/users/delete", userHandler.DeleteUser) accountsJwtAuthAPI := server.Group("/") - accountsJwtAuthAPI.Use(authMiddleware.TokenAuthMiddleware(jwt.ACCOUNTS.Ptr()), rateLimiter.APIRateLimitForUserMiddleware(urlSanitizer)) + accountsJwtAuthAPI.Use(rateLimiter.GlobalRateLimiter(), authMiddleware.TokenAuthMiddleware(jwt.ACCOUNTS.Ptr()), rateLimiter.APIRateLimitForUserMiddleware(urlSanitizer)) passkeysHandler := &api.PasskeyHandler{ Controller: passkeyCtrl, } @@ -531,7 +532,7 @@ func main() { castCtrl := cast.NewController(&castDb, accessCtrl) castMiddleware := middleware.CastMiddleware{CastCtrl: castCtrl, Cache: authCache} - castAPI.Use(castMiddleware.CastAuthMiddleware()) + castAPI.Use(rateLimiter.GlobalRateLimiter(), castMiddleware.CastAuthMiddleware()) castHandler := &api.CastHandler{ CollectionCtrl: collectionController, diff --git a/server/pkg/middleware/rate_limit.go b/server/pkg/middleware/rate_limit.go index 391c018878..fede9ec877 100644 --- a/server/pkg/middleware/rate_limit.go +++ b/server/pkg/middleware/rate_limit.go @@ -5,6 +5,8 @@ import ( "net/http" "strconv" "strings" + "sync/atomic" + "time" "github.com/ente-io/museum/pkg/controller/discord" "github.com/ente-io/museum/pkg/utils/auth" @@ -20,14 +22,40 @@ type RateLimitMiddleware struct { limit10ReqPerMin *limiter.Limiter limit200ReqPerSec *limiter.Limiter discordCtrl *discord.DiscordController + count int64 // Use int64 for atomic operations + limit int64 + reset time.Duration + ticker *time.Ticker } -func NewRateLimitMiddleware(discordCtrl *discord.DiscordController) *RateLimitMiddleware { - return &RateLimitMiddleware{ +func NewRateLimitMiddleware(discordCtrl *discord.DiscordController, limit int64, reset time.Duration) *RateLimitMiddleware { + rl := &RateLimitMiddleware{ limit10ReqPerMin: rateLimiter("10-M"), limit200ReqPerSec: rateLimiter("200-S"), discordCtrl: discordCtrl, + limit: limit, + reset: reset, + ticker: time.NewTicker(reset), } + go func() { + for range rl.ticker.C { + atomic.StoreInt64(&rl.count, 0) // Reset the count every reset interval + } + }() + return rl +} + +// Increment increments the counter in a thread-safe manner. +// Returns true if the increment was within the rate limit, false if the rate limit was exceeded. +func (r *RateLimitMiddleware) Increment() bool { + // Atomically increment the count + newCount := atomic.AddInt64(&r.count, 1) + return newCount <= r.limit +} + +// Stop the internal ticker, effectively stopping the rate limiter. +func (r *RateLimitMiddleware) Stop() { + r.ticker.Stop() } // rateLimiter will return instance of limiter.Limiter based on internal - @@ -44,6 +72,18 @@ func rateLimiter(interval string) *limiter.Limiter { return instance } +// GlobalRateLimiter rate limits all requests to the server, regardless of the endpoint. +func (r *RateLimitMiddleware) GlobalRateLimiter() gin.HandlerFunc { + return func(c *gin.Context) { + if !r.Increment() { + go r.discordCtrl.NotifyPotentialAbuse("Global rate limit breached") + c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{"error": "Rate limit breached, try later"}) + return + } + c.Next() + } +} + // APIRateLimitMiddleware only rate limits sensitive public endpoints which have a higher risk // of abuse by any bad actor. func (r *RateLimitMiddleware) APIRateLimitMiddleware(urlSanitizer func(_ *gin.Context) string) gin.HandlerFunc { From ba6a8b6aa4171f7fa1fca380878b20309b364bf2 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta Date: Sun, 17 Mar 2024 11:30:35 +0530 Subject: [PATCH 349/391] [docs] Update family-plans.md (#1123) ## Description ## Tests --- docs/docs/photos/features/family-plans.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/docs/photos/features/family-plans.md b/docs/docs/photos/features/family-plans.md index 8405c7dcf7..bb4cb3a700 100644 --- a/docs/docs/photos/features/family-plans.md +++ b/docs/docs/photos/features/family-plans.md @@ -22,3 +22,10 @@ In brief, - You can invite 5 family members. So including yourself, it will be 6 people who can share a single subscription, paying only once. + + +## FAQ + +* **Can you assign a storage quota for each individual member in the family plan?** + Unfortunately, at this moment, assigning a storage quota for each individual member in the family plan is not supported. For updates on this feature request, please follow [this thread](https://github.com/ente-io/ente/discussions/857). + From 9012a96a5871b0c4012301bc3bf64ca885e50e3d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Sun, 17 Mar 2024 11:55:57 +0530 Subject: [PATCH 350/391] [web] Add passkeys related translations Obtained these strings from https://github.com/ente-io/accounts-web/blob/33faadf83ea6c39732ffd185fc4716b006612684/apps/accounts/public/locales/en/translation.json#L632 I didn't have a way of exhaustively ensuring that all strings are covered, but I've tried to manually verify. Once this is merged and translation files synced with Crowdin, I'll do another PR to update the `local/**/translation.json` files within apps/accounts. --- .../public/locales/en-US/translation.json | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/web/apps/photos/public/locales/en-US/translation.json b/web/apps/photos/public/locales/en-US/translation.json index ea74f4f5ff..de8d2fe2a1 100644 --- a/web/apps/photos/public/locales/en-US/translation.json +++ b/web/apps/photos/public/locales/en-US/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", "FREEHAND": "Freehand", "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving.", + "PASSKEYS": "Passkeys", + "DELETE_PASSKEY": "Delete passkey", + "DELETE_PASSKEY_CONFIRMATION": "Are you sure you want to delete this passkey? This action is irreversible.", + "RENAME_PASSKEY": "Rename passkey", + "ADD_PASSKEY": "Add passkey", + "ENTER_PASSKEY_NAME": "Enter passkey name", + "PASSKEYS_DESCRIPTION": "Passkeys are a modern and secure second-factor for your Ente account. They use on-device biometric authentication for convenience and security.", + "CREATED_AT": "Created at", + "PASSKEY_LOGIN_FAILED": "Passkey login failed", + "PASSKEY_LOGIN_URL_INVALID": "The login URL is invalid.", + "PASSKEY_LOGIN_ERRORED": "An error occurred while logging in with passkey.", + "TRY_AGAIN": "Try again", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "Follow the steps from your browser to continue logging in.", + "LOGIN_WITH_PASSKEY": "Login with passkey" } From 022c11d7fa42a212762fda9b1e030083ca8241bd Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 03:38:51 +0530 Subject: [PATCH 351/391] Import the base nginx service definition we use --- infra/services/nginx/README.md | 21 +++++++++++++++++++++ infra/services/nginx/nginx.service | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 infra/services/nginx/README.md create mode 100644 infra/services/nginx/nginx.service diff --git a/infra/services/nginx/README.md b/infra/services/nginx/README.md new file mode 100644 index 0000000000..43e570946e --- /dev/null +++ b/infra/services/nginx/README.md @@ -0,0 +1,21 @@ +# Nginx + +This is a base nginx service that terminates TLS, and can be used as a reverse +proxy for arbitrary services by adding new entries in `/root/nginx/conf.d` and +`sudo systemctl restart nginx`. + +## Installation + +Create a directory to house service specific configuration + + sudo mkdir -p /root/nginx/conf.d + +Add the SSL certificate provided by Cloudflare + + sudo tee /root/nginx/cert.pem + sudo tee /root/nginx/key.pem + +## Adding a service + +When adding new services that sit behind nginx, add their nginx conf file to +`/root/nginx/conf.d` and and restart the nginx service. diff --git a/infra/services/nginx/nginx.service b/infra/services/nginx/nginx.service new file mode 100644 index 0000000000..4f772d38dd --- /dev/null +++ b/infra/services/nginx/nginx.service @@ -0,0 +1,19 @@ +[Unit] +Documentation=https://www.docker.com/blog/how-to-use-the-official-nginx-docker-image/ +Requires=docker.service +After=docker.service + +[Install] +WantedBy=multi-user.target + +[Service] +ExecStartPre=docker pull nginx +ExecStartPre=-docker stop nginx +ExecStartPre=-docker rm nginx +ExecStart=docker run --name nginx \ + --add-host=host.docker.internal:host-gateway \ + -p 443:443 \ + -v /root/nginx/cert.pem:/etc/ssl/certs/cert.pem:ro \ + -v /root/nginx/key.pem:/etc/ssl/private/key.pem:ro \ + -v /root/nginx/conf.d:/etc/nginx/conf.d:ro \ + nginx From 6bbd296c2582e46812848c7f6c3180c8de104db8 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 18 Mar 2024 03:38:20 +0000 Subject: [PATCH 352/391] New Crowdin translations by GitHub Action --- .../public/locales/bg-BG/translation.json | 17 ++++- .../public/locales/de-DE/translation.json | 75 +++++++++++-------- .../public/locales/es-ES/translation.json | 17 ++++- .../public/locales/fa-IR/translation.json | 17 ++++- .../public/locales/fi-FI/translation.json | 17 ++++- .../public/locales/fr-FR/translation.json | 17 ++++- .../public/locales/it-IT/translation.json | 17 ++++- .../public/locales/ko-KR/translation.json | 17 ++++- .../public/locales/nl-NL/translation.json | 17 ++++- .../public/locales/pt-BR/translation.json | 17 ++++- .../public/locales/pt-PT/translation.json | 17 ++++- .../public/locales/ru-RU/translation.json | 17 ++++- .../public/locales/sv-SE/translation.json | 17 ++++- .../public/locales/th-TH/translation.json | 17 ++++- .../public/locales/tr-TR/translation.json | 17 ++++- .../public/locales/zh-CN/translation.json | 17 ++++- 16 files changed, 269 insertions(+), 61 deletions(-) diff --git a/web/apps/photos/public/locales/bg-BG/translation.json b/web/apps/photos/public/locales/bg-BG/translation.json index 6b02fae652..03faf16c2d 100644 --- a/web/apps/photos/public/locales/bg-BG/translation.json +++ b/web/apps/photos/public/locales/bg-BG/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/de-DE/translation.json b/web/apps/photos/public/locales/de-DE/translation.json index 9e38239594..9a1c4073c6 100644 --- a/web/apps/photos/public/locales/de-DE/translation.json +++ b/web/apps/photos/public/locales/de-DE/translation.json @@ -163,7 +163,7 @@ "SUBSCRIPTION_PURCHASE_CANCELLED": "Dein Kauf wurde abgebrochen. Bitte versuche es erneut, wenn du abonnieren willst", "SUBSCRIPTION_PURCHASE_FAILED": "Kauf des Abonnements fehlgeschlagen Bitte versuchen Sie es erneut", "SUBSCRIPTION_UPDATE_FAILED": "Aktualisierung des Abonnements fehlgeschlagen Bitte versuchen Sie es erneut", - "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Es tut uns leid, die Zahlung ist fehlgeschlagen, als wir versuchten Ihre Karte zu belasten. Bitte aktualisieren Sie Ihre Zahlungsmethode und versuchen Sie es erneut", "STRIPE_AUTHENTICATION_FAILED": "Wir können deine Zahlungsmethode nicht authentifizieren. Bitte wähle eine andere Zahlungsmethode und versuche es erneut", "UPDATE_PAYMENT_METHOD": "Zahlungsmethode aktualisieren", "MONTHLY": "Monatlich", @@ -260,13 +260,13 @@ "ENABLE": "Aktivieren", "LOST_DEVICE": "Zwei-Faktor-Gerät verloren", "INCORRECT_CODE": "Falscher Code", - "TWO_FACTOR_INFO": "", + "TWO_FACTOR_INFO": "Fügen Sie eine zusätzliche Sicherheitsebene hinzu, indem Sie mehr als Ihre E-Mail und Ihr Passwort benötigen, um sich mit Ihrem Account anzumelden", "DISABLE_TWO_FACTOR_LABEL": "Deaktiviere die Zwei-Faktor-Authentifizierung", "UPDATE_TWO_FACTOR_LABEL": "Authentifizierungsgerät aktualisieren", "DISABLE": "Deaktivieren", "RECONFIGURE": "Neu einrichten", "UPDATE_TWO_FACTOR": "Zweiten Faktor aktualisieren", - "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE_TWO_FACTOR_MESSAGE": "Fahren Sie fort, werden alle Ihre zuvor konfigurierten Authentifikatoren ungültig", "UPDATE": "Aktualisierung", "DISABLE_TWO_FACTOR": "Zweiten Faktor deaktivieren", "DISABLE_TWO_FACTOR_MESSAGE": "Bist du sicher, dass du die Zwei-Faktor-Authentifizierung deaktivieren willst", @@ -278,24 +278,24 @@ "LAST_EXPORT_TIME": "Letztes Exportdatum", "EXPORT_AGAIN": "Neusynchronisation", "LOCAL_STORAGE_NOT_ACCESSIBLE": "Lokaler Speicher nicht zugänglich", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Ihr Browser oder ein Addon blockiert ente vor der Speicherung von Daten im lokalen Speicher. Bitte versuchen Sie, den Browser-Modus zu wechseln und die Seite neu zu laden.", "SEND_OTT": "OTP senden", "EMAIl_ALREADY_OWNED": "Diese E-Mail wird bereits verwendet", "ETAGS_BLOCKED": "", "SKIPPED_VIDEOS_INFO": "", "LIVE_PHOTOS_DETECTED": "", - "RETRY_FAILED": "", + "RETRY_FAILED": "Fehlgeschlagene Uploads erneut probieren", "FAILED_UPLOADS": "Fehlgeschlagene Uploads ", "SKIPPED_FILES": "Ignorierte Uploads", "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Das Vorschaubild konnte nicht erzeugt werden", "UNSUPPORTED_FILES": "Nicht unterstützte Dateien", - "SUCCESSFUL_UPLOADS": "", + "SUCCESSFUL_UPLOADS": "Erfolgreiche Uploads", "SKIPPED_INFO": "", "UNSUPPORTED_INFO": "ente unterstützt diese Dateiformate noch nicht", "BLOCKED_UPLOADS": "Blockierte Uploads", "SKIPPED_VIDEOS": "Übersprungene Videos", "INPROGRESS_METADATA_EXTRACTION": "In Bearbeitung", - "INPROGRESS_UPLOADS": "", + "INPROGRESS_UPLOADS": "Upload läuft", "TOO_LARGE_UPLOADS": "Große Dateien", "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Zu wenig Speicher", "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Diese Dateien wurden nicht hochgeladen, da sie die maximale Größe für Ihren Speicherplan überschreiten", @@ -346,10 +346,10 @@ "REPLACE_THUMBNAIL_COMPLETED": "", "REPLACE_THUMBNAIL_NOOP": "", "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", - "FIX_CREATION_TIME": "", - "FIX_CREATION_TIME_IN_PROGRESS": "", - "CREATION_TIME_UPDATED": "", - "UPDATE_CREATION_TIME_NOT_STARTED": "", + "FIX_CREATION_TIME": "Zeit reparieren", + "FIX_CREATION_TIME_IN_PROGRESS": "Zeit wird repariert", + "CREATION_TIME_UPDATED": "Datei-Zeit aktualisiert", + "UPDATE_CREATION_TIME_NOT_STARTED": "Wählen Sie die Option, die Sie verwenden möchten", "UPDATE_CREATION_TIME_COMPLETED": "", "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", "CAPTION_CHARACTER_LIMIT": "Maximal 5000 Zeichen", @@ -358,25 +358,25 @@ "METADATA_DATE": "", "CUSTOM_TIME": "Benutzerdefinierte Zeit", "REOPEN_PLAN_SELECTOR_MODAL": "", - "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Fehler beim Öffnen der Pläne", "INSTALL": "Installieren", "SHARING_DETAILS": "Details teilen", "MODIFY_SHARING": "Freigabe ändern", "ADD_COLLABORATORS": "Bearbeiter hinzufügen", "ADD_NEW_EMAIL": "Neue E-Mail-Adresse hinzufügen", - "shared_with_people_zero": "", + "shared_with_people_zero": "Mit bestimmten Personen teilen", "shared_with_people_one": "Geteilt mit einer Person", - "shared_with_people_other": "", + "shared_with_people_other": "Geteilt mit {{count, number}} Personen", "participants_zero": "Keine Teilnehmer", "participants_one": "1 Teilnehmer", - "participants_other": "", + "participants_other": "{{count, number}} Teilnehmer", "ADD_VIEWERS": "Betrachter hinzufügen", "PARTICIPANTS": "Teilnehmer", "CHANGE_PERMISSIONS_TO_VIEWER": "", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", "CONVERT_TO_VIEWER": "Ja, zu \"Beobachter\" ändern", "CONVERT_TO_COLLABORATOR": "", - "CHANGE_PERMISSION": "", + "CHANGE_PERMISSION": "Berechtigung ändern?", "REMOVE_PARTICIPANT": "Entfernen?", "CONFIRM_REMOVE": "Ja, entfernen", "MANAGE": "Verwalten", @@ -384,9 +384,9 @@ "COLLABORATOR_RIGHTS": "Bearbeiter können Fotos & Videos zu dem geteilten Album hinzufügen", "REMOVE_PARTICIPANT_HEAD": "Teilnehmer entfernen", "OWNER": "Besitzer", - "COLLABORATORS": "", + "COLLABORATORS": "Bearbeiter", "ADD_MORE": "Mehr hinzufügen", - "VIEWERS": "", + "VIEWERS": "Zuschauer", "OR_ADD_EXISTING": "Oder eine Vorherige auswählen", "REMOVE_PARTICIPANT_MESSAGE": "", "NOT_FOUND": "404 - Nicht gefunden", @@ -401,19 +401,19 @@ "NO_DEVICE_LIMIT": "Keins", "LINK_EXPIRY": "Ablaufdatum des Links", "NEVER": "Niemals", - "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD": "Download deaktivieren", "DISABLE_FILE_DOWNLOAD_MESSAGE": "", - "MALICIOUS_CONTENT": "", - "COPYRIGHT": "", - "SHARED_USING": "", + "MALICIOUS_CONTENT": "Enthält schädliche Inhalte", + "COPYRIGHT": "Verletzung des Urheberrechts von jemandem, den ich repräsentieren darf", + "SHARED_USING": "Freigegeben über ", "ENTE_IO": "ente.io", "SHARING_REFERRAL_CODE": "", "LIVE": "LIVE", - "DISABLE_PASSWORD": "", - "DISABLE_PASSWORD_MESSAGE": "", + "DISABLE_PASSWORD": "Passwort-Sperre deaktivieren", + "DISABLE_PASSWORD_MESSAGE": "Sind Sie sicher, dass Sie die Passwort-Sperre deaktivieren möchten?", "PASSWORD_LOCK": "Passwort Sperre", "LOCK": "Sperren", - "DOWNLOAD_UPLOAD_LOGS": "", + "DOWNLOAD_UPLOAD_LOGS": "Debug-Logs", "UPLOAD_FILES": "Datei", "UPLOAD_DIRS": "Ordner", "UPLOAD_GOOGLE_TAKEOUT": "Google Takeout", @@ -467,13 +467,13 @@ "FAMILY_PLAN": "Familientarif", "DOWNLOAD_LOGS": "Logs herunterladen", "DOWNLOAD_LOGS_MESSAGE": "", - "CHANGE_FOLDER": "", - "TWO_MONTHS_FREE": "", + "CHANGE_FOLDER": "Ordner ändern", + "TWO_MONTHS_FREE": "Erhalte 2 Monate kostenlos bei Jahresabonnements", "GB": "GB", "POPULAR": "Beliebt", - "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_OPTION_LABEL": "Mit kostenloser Testversion fortfahren", "FREE_PLAN_DESCRIPTION": "1 GB für 1 Jahr", - "CURRENT_USAGE": "", + "CURRENT_USAGE": "Aktuelle Nutzung ist {{usage}}", "WEAK_DEVICE": "", "DRAG_AND_DROP_HINT": "", "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/es-ES/translation.json b/web/apps/photos/public/locales/es-ES/translation.json index 64c2849ebb..a29165e4ee 100644 --- a/web/apps/photos/public/locales/es-ES/translation.json +++ b/web/apps/photos/public/locales/es-ES/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/fa-IR/translation.json b/web/apps/photos/public/locales/fa-IR/translation.json index 68e1da3b97..2d21fcb3d3 100644 --- a/web/apps/photos/public/locales/fa-IR/translation.json +++ b/web/apps/photos/public/locales/fa-IR/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/fi-FI/translation.json b/web/apps/photos/public/locales/fi-FI/translation.json index fbc0b937a9..888ed7093e 100644 --- a/web/apps/photos/public/locales/fi-FI/translation.json +++ b/web/apps/photos/public/locales/fi-FI/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/fr-FR/translation.json b/web/apps/photos/public/locales/fr-FR/translation.json index 2d183c9eb2..43d9590691 100644 --- a/web/apps/photos/public/locales/fr-FR/translation.json +++ b/web/apps/photos/public/locales/fr-FR/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "Visitez cast.ente.io sur l'appareil que vous voulez associer.", "CAST_AUTO_PAIR_FAILED": "La paire automatique de Chromecast a échoué. Veuillez réessayer.", "CACHE_DIRECTORY": "Dossier du cache", - "PASSKEYS": "Clés d'accès", "FREEHAND": "Main levée", "APPLY_CROP": "Appliquer le recadrage", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "Au moins une transformation ou un ajustement de couleur doit être effectué avant de sauvegarder." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Au moins une transformation ou un ajustement de couleur doit être effectué avant de sauvegarder.", + "PASSKEYS": "Clés d'accès", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/it-IT/translation.json b/web/apps/photos/public/locales/it-IT/translation.json index dd7afc1582..ae450e5fef 100644 --- a/web/apps/photos/public/locales/it-IT/translation.json +++ b/web/apps/photos/public/locales/it-IT/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/ko-KR/translation.json b/web/apps/photos/public/locales/ko-KR/translation.json index 7482dd3979..4fbe6c0777 100644 --- a/web/apps/photos/public/locales/ko-KR/translation.json +++ b/web/apps/photos/public/locales/ko-KR/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/nl-NL/translation.json b/web/apps/photos/public/locales/nl-NL/translation.json index 2b2aa11115..15d9bfdba0 100644 --- a/web/apps/photos/public/locales/nl-NL/translation.json +++ b/web/apps/photos/public/locales/nl-NL/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "Cache map", - "PASSKEYS": "", "FREEHAND": "Losse hand", "APPLY_CROP": "Bijsnijden toepassen", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "Tenminste één transformatie of kleuraanpassing moet worden uitgevoerd voordat u opslaat." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Tenminste één transformatie of kleuraanpassing moet worden uitgevoerd voordat u opslaat.", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/pt-BR/translation.json b/web/apps/photos/public/locales/pt-BR/translation.json index 617a2618db..0da001742f 100644 --- a/web/apps/photos/public/locales/pt-BR/translation.json +++ b/web/apps/photos/public/locales/pt-BR/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "Acesse cast.ente.io no dispositivo que você deseja parear.", "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair falhou. Por favor, tente novamente.", "CACHE_DIRECTORY": "Pasta de Cache", - "PASSKEYS": "Chaves de acesso", "FREEHAND": "Mão livre", "APPLY_CROP": "Aplicar Recorte", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "Pelo menos uma transformação ou ajuste de cor deve ser feito antes de salvar." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Pelo menos uma transformação ou ajuste de cor deve ser feito antes de salvar.", + "PASSKEYS": "Chaves de acesso", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/pt-PT/translation.json b/web/apps/photos/public/locales/pt-PT/translation.json index ac7d179688..2309803267 100644 --- a/web/apps/photos/public/locales/pt-PT/translation.json +++ b/web/apps/photos/public/locales/pt-PT/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/ru-RU/translation.json b/web/apps/photos/public/locales/ru-RU/translation.json index 0e97155633..c85db22361 100644 --- a/web/apps/photos/public/locales/ru-RU/translation.json +++ b/web/apps/photos/public/locales/ru-RU/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/sv-SE/translation.json b/web/apps/photos/public/locales/sv-SE/translation.json index 550780b444..f88535795a 100644 --- a/web/apps/photos/public/locales/sv-SE/translation.json +++ b/web/apps/photos/public/locales/sv-SE/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/th-TH/translation.json b/web/apps/photos/public/locales/th-TH/translation.json index fbc0b937a9..888ed7093e 100644 --- a/web/apps/photos/public/locales/th-TH/translation.json +++ b/web/apps/photos/public/locales/th-TH/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/tr-TR/translation.json b/web/apps/photos/public/locales/tr-TR/translation.json index fbc0b937a9..888ed7093e 100644 --- a/web/apps/photos/public/locales/tr-TR/translation.json +++ b/web/apps/photos/public/locales/tr-TR/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/photos/public/locales/zh-CN/translation.json b/web/apps/photos/public/locales/zh-CN/translation.json index 6e513f24b9..0a72e1c70a 100644 --- a/web/apps/photos/public/locales/zh-CN/translation.json +++ b/web/apps/photos/public/locales/zh-CN/translation.json @@ -634,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "在您要配对的设备上访问 cast.ente.io 。", "CAST_AUTO_PAIR_FAILED": "Chromecast 自动配对失败。请再试一次。", "CACHE_DIRECTORY": "缓存文件夹", - "PASSKEYS": "通行密钥", "FREEHAND": "手画", "APPLY_CROP": "应用裁剪", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "保存之前必须至少执行一项转换或颜色调整。" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "保存之前必须至少执行一项转换或颜色调整。", + "PASSKEYS": "通行密钥", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } From e09851196042b1a0673c3f3cc7d6302d380983f0 Mon Sep 17 00:00:00 2001 From: Shubh Date: Mon, 18 Mar 2024 09:08:31 +0530 Subject: [PATCH 353/391] [auth] add rockstar games icon (#1125) add Rockstar Games icon Signed-off-by: Shubh --- auth/assets/custom-icons/_data/custom-icons.json | 4 ++++ auth/assets/custom-icons/icons/rockstar_games.svg | 1 + 2 files changed, 5 insertions(+) create mode 100644 auth/assets/custom-icons/icons/rockstar_games.svg diff --git a/auth/assets/custom-icons/_data/custom-icons.json b/auth/assets/custom-icons/_data/custom-icons.json index b248ad8cb8..489b2a7ec3 100644 --- a/auth/assets/custom-icons/_data/custom-icons.json +++ b/auth/assets/custom-icons/_data/custom-icons.json @@ -267,6 +267,10 @@ "title": "Revolt", "hex": "858585" }, + { + "title": "Rockstar Games", + "slug": "rockstar_games" + }, { "title": "Rust Language Forum", "slug": "rust_language_forum", diff --git a/auth/assets/custom-icons/icons/rockstar_games.svg b/auth/assets/custom-icons/icons/rockstar_games.svg new file mode 100644 index 0000000000..bf2061c2b3 --- /dev/null +++ b/auth/assets/custom-icons/icons/rockstar_games.svg @@ -0,0 +1 @@ + \ No newline at end of file From 4acc8395bae4582879792bfdae9bbdda0258ca3e Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 18 Mar 2024 09:59:35 +0530 Subject: [PATCH 354/391] [server] Prefix discord msg with hostname --- server/pkg/controller/discord/discord.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/pkg/controller/discord/discord.go b/server/pkg/controller/discord/discord.go index 2c07fe4041..94876c8149 100644 --- a/server/pkg/controller/discord/discord.go +++ b/server/pkg/controller/discord/discord.go @@ -106,7 +106,7 @@ func (c *DiscordController) NotifyAccountDelete(userID int64, paymentProvider st } func (c *DiscordController) NotifyPotentialAbuse(message string) { - c.Notify(message) + c.Notify(fmt.Sprintf("%s: %s", c.HostName, message)) } func (c *DiscordController) getTimeSinceSignUp(userID int64) string { From 7de60f1ceda87afccf230be186068df3c726ffb1 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:02:13 +0530 Subject: [PATCH 355/391] [server] Reduce discord message frequency --- server/pkg/middleware/rate_limit.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/pkg/middleware/rate_limit.go b/server/pkg/middleware/rate_limit.go index fede9ec877..08e0f00b66 100644 --- a/server/pkg/middleware/rate_limit.go +++ b/server/pkg/middleware/rate_limit.go @@ -76,7 +76,9 @@ func rateLimiter(interval string) *limiter.Limiter { func (r *RateLimitMiddleware) GlobalRateLimiter() gin.HandlerFunc { return func(c *gin.Context) { if !r.Increment() { - go r.discordCtrl.NotifyPotentialAbuse("Global rate limit breached") + if r.count%100 == 0 { + go r.discordCtrl.NotifyPotentialAbuse(fmt.Sprintf("Global ratelimit (%d) breached %d", r.limit, r.count)) + } c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{"error": "Rate limit breached, try later"}) return } From 47747f1d56256345ab05f5717625ffcb5af17560 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:12:02 +0530 Subject: [PATCH 356/391] Update config --- server/cmd/museum/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 5ea4f33896..3a6ebac154 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -178,7 +178,7 @@ func main() { authCache := cache.New(1*time.Minute, 15*time.Minute) accessTokenCache := cache.New(1*time.Minute, 15*time.Minute) discordController := discord.NewDiscordController(userRepo, hostName, environment) - rateLimiter := middleware.NewRateLimitMiddleware(discordController, 5000, 5*time.Second) + rateLimiter := middleware.NewRateLimitMiddleware(discordController, 1000, 1*time.Second) defer rateLimiter.Stop() emailNotificationCtrl := &email.EmailNotificationController{ From 9beedcf4e09369b82285a9e4b5cdce5705718e52 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 10:08:36 +0530 Subject: [PATCH 357/391] Move into separate folder --- infra/services/prometheus/README.md | 9 ++- infra/services/promtail/README.md | 2 +- server/README.md | 7 +- server/scripts/deploy/README.md | 73 +++++++++++++++++++ server/scripts/{ => deploy}/museum.service | 0 .../deploy/update-and-restart-museum.sh | 15 ++++ 6 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 server/scripts/deploy/README.md rename server/scripts/{ => deploy}/museum.service (100%) create mode 100755 server/scripts/deploy/update-and-restart-museum.sh diff --git a/infra/services/prometheus/README.md b/infra/services/prometheus/README.md index 79bee13d5b..54ca3e5595 100644 --- a/infra/services/prometheus/README.md +++ b/infra/services/prometheus/README.md @@ -3,9 +3,10 @@ Install `prometheus.service` on an instance if it is running something that exports custom Prometheus metrics. In particular, museum does. -Also install `node-exporter.service` (after installing -[node-exporter](https://prometheus.io/docs/guides/node-exporter/) itself) if it -is a production instance whose metrics (CPU, disk, RAM etc) we want to monitor. +If it is an instance whose metrics (CPU, disk, RAM etc) we want to monitor, also +install `node-exporter.service` after installing +[node-exporter](https://prometheus.io/docs/guides/node-exporter/) itself (Note +that our prepare-instance script already installs node-exporter) . ## Installing @@ -14,7 +15,7 @@ remember to change the hardcoded `XX-HOSTNAME` too in addition to adding the `remote_write` configuration. ```sh -scp -P 7426 services/prometheus/* : +scp services/prometheus/* : nano prometheus.yml sudo mv prometheus.yml /root/prometheus.yml diff --git a/infra/services/promtail/README.md b/infra/services/promtail/README.md index 1bcf448337..389542e177 100644 --- a/infra/services/promtail/README.md +++ b/infra/services/promtail/README.md @@ -9,7 +9,7 @@ Replace `client.url` in the config file with the Loki URL that Promtail should connect to, and move the files to their expected place. ```sh -scp -P 7426 services/promtail/* : +scp services/promtail/* : nano promtail.yaml sudo mv promtail.yaml /root/promtail.yaml diff --git a/server/README.md b/server/README.md index 06fdcb5184..40b479577d 100644 --- a/server/README.md +++ b/server/README.md @@ -95,9 +95,10 @@ setup we ourselves use in production. > [!TIP] > > On our production servers, we wrap museum in a [systemd -> service](scripts/museum.service). Our production machines are vanilla Ubuntu -> images, with Docker and Promtail installed. We then plonk in this systemd -> service, and use `systemctl start|stop|status museum` to herd it around. +> service](scripts/deploy/museum.service). Our production machines are vanilla +> Ubuntu images, with Docker and Promtail installed. We then plonk in this +> systemd service, and use `systemctl start|stop|status museum` to herd it +> around. Some people new to Docker/Go/Postgres might have general questions though. Unfortunately, because of limited engineering bandwidth **we will currently not diff --git a/server/scripts/deploy/README.md b/server/scripts/deploy/README.md new file mode 100644 index 0000000000..40da5183f8 --- /dev/null +++ b/server/scripts/deploy/README.md @@ -0,0 +1,73 @@ +# Production Deployments + +Museum runs using Docker + systemd on production instances, load balanced via +Cloudflare. + +This document outlines how we ourselves deploy museum. Note that this is very +specific to our use case, and while this might be useful as an example, this is +likely overkill for simple self hosted deployments. + +## Overview + +We use museum's Dockerfile to build images which we then run on vanilla Ubuntu +servers (+ Docker installed). For ease of administration, we wrap Docker +commands to start/stop/update it in a systemd service. + +* The production machines are vanilla Ubuntu instances, with Docker and Promtail +installed. + +* There is a [GitHub action](../../../.github/workflows/server-release.yml) to + build museum Docker images using its Dockerfile. + +* We wrap the commands to start and stop containers using these images in a + systemd service. + +* We call this general concept of standalone Docker images that are managed +using systemd as "services". More examples and details +[here](../../../infra/services/README.md). + +* So museum is a "service". You can see its systemd unit definition in + [museum.service](museum.service) + +* On the running instance, we use `systemctl start|stop|status museum` to manage + it. + +* The service automatically updates itself on each start. There's also a + convenience [script](update-and-restart-museum.sh) that pre-downloads the + latest image to further reduce the delay during a restart. + +## Installation + +To bring up an additional museum node: + +* Prepare the instance to run our services + +* Setup [promtail](../../../infra/services/promtail/README.md), [prometheus and node-exporter](../../../infra/services/prometheus/README.md) services + +* Add credentials + + sudo mkdir -p /root/museum/credentials + sudo tee /root/museum/credentials/tls.cert + sudo tee /root/museum/credentials/tls.key + sudo tee /root/museum/credentials/pst-service-account.json + sudo tee /root/museum/credentials/fcm-service-account.json + sudo tee /root/museum/credentials.yaml + +* Copy the service definition and restart script to the new instance. The + restart script can remain in the ente user's home directory. Move the service + definition to its proper place. + + scp /scripts/museum.service : + scp update-and-restart-museum.sh : + + sudo mv museum.service /etc/systemd/system + sudo systemctl daemon-reload + +## Starting + +SSH into the instance, and run + + ./update-and-restart-museum.sh + +This'll ask for sudo credentials, pull the latest Docker image, restart the +museum service and start tailing the logs (as a sanity check). diff --git a/server/scripts/museum.service b/server/scripts/deploy/museum.service similarity index 100% rename from server/scripts/museum.service rename to server/scripts/deploy/museum.service diff --git a/server/scripts/deploy/update-and-restart-museum.sh b/server/scripts/deploy/update-and-restart-museum.sh new file mode 100755 index 0000000000..e4e5b34da6 --- /dev/null +++ b/server/scripts/deploy/update-and-restart-museum.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# This script is meant to be run on the production instances. +# +# It will pull the latest Docker image, restart the museum process and start +# tailing the logs. + +set -o errexit + +# The service file also does this, but also pre-pull here to minimize downtime. +sudo docker pull rg.fr-par.scw.cloud/ente/museum-prod + +sudo systemctl restart museum +sudo systemctl status museum | more +sudo tail -f /root/var/logs/museum.log From a0599f7b33c29ef9f82a3ff1191a22dc0389e298 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 10:25:11 +0530 Subject: [PATCH 358/391] Outline the nginx approach --- server/scripts/deploy/README.md | 26 +++++++++++++++++++++---- server/scripts/deploy/museum.nginx.conf | 17 ++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 server/scripts/deploy/museum.nginx.conf diff --git a/server/scripts/deploy/README.md b/server/scripts/deploy/README.md index 40da5183f8..81ebb63567 100644 --- a/server/scripts/deploy/README.md +++ b/server/scripts/deploy/README.md @@ -36,6 +36,9 @@ using systemd as "services". More examples and details convenience [script](update-and-restart-museum.sh) that pre-downloads the latest image to further reduce the delay during a restart. +* Optionally and alternatively, museum can also be run behind an Nginx. This + option has a separate service definition. + ## Installation To bring up an additional museum node: @@ -44,25 +47,40 @@ To bring up an additional museum node: * Setup [promtail](../../../infra/services/promtail/README.md), [prometheus and node-exporter](../../../infra/services/prometheus/README.md) services +* If running behind Nginx, install the + [nginx](../../../infra/services/nginx/README.md) service. + * Add credentials sudo mkdir -p /root/museum/credentials - sudo tee /root/museum/credentials/tls.cert - sudo tee /root/museum/credentials/tls.key sudo tee /root/museum/credentials/pst-service-account.json sudo tee /root/museum/credentials/fcm-service-account.json sudo tee /root/museum/credentials.yaml +* If not running behind Nginx, add the TLS credentials (otherwise add them to + Nginx) + + sudo tee /root/museum/credentials/tls.cert + sudo tee /root/museum/credentials/tls.key + * Copy the service definition and restart script to the new instance. The restart script can remain in the ente user's home directory. Move the service definition to its proper place. - scp /scripts/museum.service : - scp update-and-restart-museum.sh : + scp scripts/deploy/{museum.service,update-and-restart-museum.sh} : sudo mv museum.service /etc/systemd/system sudo systemctl daemon-reload +* If running behind Nginx, a separate set of service definition and convenience + scripts need to be added. + + scp scripts/deploy/{museum-nginx.service,update-and-restart-museum-nginx.sh} : + + sudo mv museum-nginx.service /etc/systemd/system + sudo systemctl daemon-reload + sudo systemctl restart nginx + ## Starting SSH into the instance, and run diff --git a/server/scripts/deploy/museum.nginx.conf b/server/scripts/deploy/museum.nginx.conf new file mode 100644 index 0000000000..9af7b41a0b --- /dev/null +++ b/server/scripts/deploy/museum.nginx.conf @@ -0,0 +1,17 @@ +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + ssl_certificate /etc/ssl/certs/cert.pem; + ssl_certificate_key /etc/ssl/private/key.pem; + + server_name api.ente.io; + + location / { + proxy_pass http://host.docker.internal:9000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} + From d893efe5d1a78012ba9b86345f850f9be564fbbe Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 10:27:42 +0530 Subject: [PATCH 359/391] Remove the restart limiter During recent DDoS attacks, these restart limits had to be manually disabled. For now, disabling them in our reference copy too, will bring them back if they are needed later. --- server/scripts/deploy/museum.service | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/scripts/deploy/museum.service b/server/scripts/deploy/museum.service index 6f66133fe2..eb908e24a5 100644 --- a/server/scripts/deploy/museum.service +++ b/server/scripts/deploy/museum.service @@ -2,9 +2,6 @@ Documentation=https://github.com/ente-io/museum Requires=docker.service After=docker.service -# Don't automatically restart if it fails more than 5 times in 10 minutes. -StartLimitIntervalSec=600 -StartLimitBurst=5 [Service] Restart=on-failure From 9ba9b8a9849fba978ed99016242e5370fce61132 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 10:39:39 +0530 Subject: [PATCH 360/391] Add initial nginx conf --- infra/services/nginx/README.md | 17 ++++++++++++++--- server/scripts/deploy/README.md | 17 ++++++++++------- server/scripts/deploy/museum.nginx.service | 20 ++++++++++++++++++++ server/scripts/deploy/museum.service | 2 +- 4 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 server/scripts/deploy/museum.nginx.service diff --git a/infra/services/nginx/README.md b/infra/services/nginx/README.md index 43e570946e..923c33712a 100644 --- a/infra/services/nginx/README.md +++ b/infra/services/nginx/README.md @@ -1,6 +1,6 @@ # Nginx -This is a base nginx service that terminates TLS, and can be used as a reverse +This is a base Nginx service that terminates TLS, and can be used as a reverse proxy for arbitrary services by adding new entries in `/root/nginx/conf.d` and `sudo systemctl restart nginx`. @@ -15,7 +15,18 @@ Add the SSL certificate provided by Cloudflare sudo tee /root/nginx/cert.pem sudo tee /root/nginx/key.pem +Tell systemd to pick up new service definition, enable it (so that it +automatically starts on boot going forward), and start it. + +```sh +sudo systemctl daemon-reload +sudo systemctl enable --now nginx +``` + ## Adding a service -When adding new services that sit behind nginx, add their nginx conf file to -`/root/nginx/conf.d` and and restart the nginx service. +When adding new services that sit behind Nginx, + +1. Add its nginx conf file to `/root/nginx/conf.d` + +2. Restart nginx (`sudo systemctl restart nginx`) diff --git a/server/scripts/deploy/README.md b/server/scripts/deploy/README.md index 81ebb63567..7472a48671 100644 --- a/server/scripts/deploy/README.md +++ b/server/scripts/deploy/README.md @@ -57,7 +57,7 @@ To bring up an additional museum node: sudo tee /root/museum/credentials/fcm-service-account.json sudo tee /root/museum/credentials.yaml -* If not running behind Nginx, add the TLS credentials (otherwise add them to +* If not running behind Nginx, add the TLS credentials (otherwise add the to Nginx) sudo tee /root/museum/credentials/tls.cert @@ -67,18 +67,21 @@ To bring up an additional museum node: restart script can remain in the ente user's home directory. Move the service definition to its proper place. - scp scripts/deploy/{museum.service,update-and-restart-museum.sh} : + # If using nginx + scp scripts/deploy/museum.nginx.service :museum.service + # otherwise + scp scripts/deploy/museum.service : + + scp scripts/deploy/update-and-restart-museum.sh : sudo mv museum.service /etc/systemd/system sudo systemctl daemon-reload -* If running behind Nginx, a separate set of service definition and convenience - scripts need to be added. +* If running behind Nginx, tell it about museum - scp scripts/deploy/{museum-nginx.service,update-and-restart-museum-nginx.sh} : + scp scripts/deploy/museum.nginx.conf : - sudo mv museum-nginx.service /etc/systemd/system - sudo systemctl daemon-reload + sudo mv museum.nginx.conf /etc/systemd/system sudo systemctl restart nginx ## Starting diff --git a/server/scripts/deploy/museum.nginx.service b/server/scripts/deploy/museum.nginx.service new file mode 100644 index 0000000000..470add9349 --- /dev/null +++ b/server/scripts/deploy/museum.nginx.service @@ -0,0 +1,20 @@ +[Unit] +Documentation=https://github.com/ente-io/ente/tree/main/server#readme +Requires=docker.service +After=docker.service + +[Service] +Restart=on-failure +ExecStartPre=docker pull rg.fr-par.scw.cloud/ente/museum-prod +ExecStartPre=-docker stop museum +ExecStartPre=-docker rm museum +ExecStart=docker run --name museum \ + -e ENVIRONMENT=production \ + --hostname "%H" \ + -p 443:443 \ + -p 2112:2112 \ + -v /root/museum/credentials:/credentials:ro \ + -v /root/museum/credentials.yaml:/credentials.yaml:ro \ + -v /root/museum/data:/data:ro \ + -v /root/var:/var \ + rg.fr-par.scw.cloud/ente/museum-prod diff --git a/server/scripts/deploy/museum.service b/server/scripts/deploy/museum.service index eb908e24a5..470add9349 100644 --- a/server/scripts/deploy/museum.service +++ b/server/scripts/deploy/museum.service @@ -1,5 +1,5 @@ [Unit] -Documentation=https://github.com/ente-io/museum +Documentation=https://github.com/ente-io/ente/tree/main/server#readme Requires=docker.service After=docker.service From 303b26b95ffa4f0c3b91329aa22d2de6e4e412cd Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 10:48:12 +0530 Subject: [PATCH 361/391] Tweak the nginx setup --- server/cmd/museum/main.go | 2 +- server/configurations/proxy.yaml | 11 +++++++++++ server/scripts/deploy/README.md | 3 --- server/scripts/deploy/museum.nginx.conf | 2 +- server/scripts/deploy/museum.nginx.service | 4 ++-- server/scripts/deploy/update-and-restart-museum.sh | 2 +- 6 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 server/configurations/proxy.yaml diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 5ea4f33896..4905e82a4f 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -712,7 +712,7 @@ func main() { } func runServer(environment string, server *gin.Engine) { - if environment == "local" { + if environment == "local" || environment == "proxy" { server.Run(":8080") } else { certPath, err := config.CredentialFilePath("tls.cert") diff --git a/server/configurations/proxy.yaml b/server/configurations/proxy.yaml new file mode 100644 index 0000000000..0f206f09a2 --- /dev/null +++ b/server/configurations/proxy.yaml @@ -0,0 +1,11 @@ +# Production setup when running behind a reverse proxy like Nginx +# +# - TLS terminates on Nginx not on us +# - Otherwise the same as `production.yaml` + +log-file: /var/logs/museum.log + +stripe: + path: + success: ?status=success&session_id={CHECKOUT_SESSION_ID} + cancel: ?status=fail&reason=canceled diff --git a/server/scripts/deploy/README.md b/server/scripts/deploy/README.md index 7472a48671..5b55e6e78e 100644 --- a/server/scripts/deploy/README.md +++ b/server/scripts/deploy/README.md @@ -1,8 +1,5 @@ # Production Deployments -Museum runs using Docker + systemd on production instances, load balanced via -Cloudflare. - This document outlines how we ourselves deploy museum. Note that this is very specific to our use case, and while this might be useful as an example, this is likely overkill for simple self hosted deployments. diff --git a/server/scripts/deploy/museum.nginx.conf b/server/scripts/deploy/museum.nginx.conf index 9af7b41a0b..c36a352e6a 100644 --- a/server/scripts/deploy/museum.nginx.conf +++ b/server/scripts/deploy/museum.nginx.conf @@ -7,7 +7,7 @@ server { server_name api.ente.io; location / { - proxy_pass http://host.docker.internal:9000; + proxy_pass http://host.docker.internal:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; diff --git a/server/scripts/deploy/museum.nginx.service b/server/scripts/deploy/museum.nginx.service index 470add9349..6b32690f79 100644 --- a/server/scripts/deploy/museum.nginx.service +++ b/server/scripts/deploy/museum.nginx.service @@ -9,9 +9,9 @@ ExecStartPre=docker pull rg.fr-par.scw.cloud/ente/museum-prod ExecStartPre=-docker stop museum ExecStartPre=-docker rm museum ExecStart=docker run --name museum \ - -e ENVIRONMENT=production \ + -e ENVIRONMENT=proxy \ --hostname "%H" \ - -p 443:443 \ + -p 8080:8080 \ -p 2112:2112 \ -v /root/museum/credentials:/credentials:ro \ -v /root/museum/credentials.yaml:/credentials.yaml:ro \ diff --git a/server/scripts/deploy/update-and-restart-museum.sh b/server/scripts/deploy/update-and-restart-museum.sh index e4e5b34da6..85f93ae05d 100755 --- a/server/scripts/deploy/update-and-restart-museum.sh +++ b/server/scripts/deploy/update-and-restart-museum.sh @@ -3,7 +3,7 @@ # This script is meant to be run on the production instances. # # It will pull the latest Docker image, restart the museum process and start -# tailing the logs. +# tailing the logs as a sanity check. set -o errexit From f695c5e0d328637bd2e95f7f944b3c4a659959fb Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 11:06:54 +0530 Subject: [PATCH 362/391] Remove extra newline --- server/scripts/deploy/museum.nginx.conf | 1 - 1 file changed, 1 deletion(-) diff --git a/server/scripts/deploy/museum.nginx.conf b/server/scripts/deploy/museum.nginx.conf index c36a352e6a..fb3da7d1dc 100644 --- a/server/scripts/deploy/museum.nginx.conf +++ b/server/scripts/deploy/museum.nginx.conf @@ -14,4 +14,3 @@ server { proxy_set_header X-Forwarded-Proto $scheme; } } - From 5ee878c30e81685578af7ebc69e8e63fc4add048 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 12:33:27 +0530 Subject: [PATCH 363/391] Require nginx before starting museum.nginx --- server/scripts/deploy/museum.nginx.service | 1 + 1 file changed, 1 insertion(+) diff --git a/server/scripts/deploy/museum.nginx.service b/server/scripts/deploy/museum.nginx.service index 6b32690f79..93e414a01e 100644 --- a/server/scripts/deploy/museum.nginx.service +++ b/server/scripts/deploy/museum.nginx.service @@ -2,6 +2,7 @@ Documentation=https://github.com/ente-io/ente/tree/main/server#readme Requires=docker.service After=docker.service +Requires=nginx.service [Service] Restart=on-failure From d8347c39765e842a81c51bfa310fad731b83d76d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 12:35:18 +0530 Subject: [PATCH 364/391] Remove extra environment --- server/cmd/museum/main.go | 7 ++++--- server/configurations/local.yaml | 6 ++++++ server/configurations/production.yaml | 3 +++ server/configurations/proxy.yaml | 11 ----------- server/scripts/deploy/museum.nginx.service | 3 ++- 5 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 server/configurations/proxy.yaml diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 4905e82a4f..2c9f5fdd41 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -712,9 +712,8 @@ func main() { } func runServer(environment string, server *gin.Engine) { - if environment == "local" || environment == "proxy" { - server.Run(":8080") - } else { + useTLS := viper.GetBool("http.use_tls") + if useTLS { certPath, err := config.CredentialFilePath("tls.cert") if err != nil { log.Fatal(err) @@ -726,6 +725,8 @@ func runServer(environment string, server *gin.Engine) { } log.Fatal(server.RunTLS(":443", certPath, keyPath)) + } else { + server.Run(":8080") } } diff --git a/server/configurations/local.yaml b/server/configurations/local.yaml index 4bab089b6a..ebb85833b5 100644 --- a/server/configurations/local.yaml +++ b/server/configurations/local.yaml @@ -65,6 +65,12 @@ # It must be specified if running in a non-local environment. log-file: "" +# HTTP connection parameters +http: + # If true, bind to 443 and use TLS. + # By default, this is false, and museum will bind to 8080 without TLS. + # use_tls: true + # Database connection parameters db: host: localhost diff --git a/server/configurations/production.yaml b/server/configurations/production.yaml index 6c7c20b81f..d3d48b3568 100644 --- a/server/configurations/production.yaml +++ b/server/configurations/production.yaml @@ -1,5 +1,8 @@ log-file: /var/logs/museum.log +http: + use_tls: true + stripe: path: success: ?status=success&session_id={CHECKOUT_SESSION_ID} diff --git a/server/configurations/proxy.yaml b/server/configurations/proxy.yaml deleted file mode 100644 index 0f206f09a2..0000000000 --- a/server/configurations/proxy.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# Production setup when running behind a reverse proxy like Nginx -# -# - TLS terminates on Nginx not on us -# - Otherwise the same as `production.yaml` - -log-file: /var/logs/museum.log - -stripe: - path: - success: ?status=success&session_id={CHECKOUT_SESSION_ID} - cancel: ?status=fail&reason=canceled diff --git a/server/scripts/deploy/museum.nginx.service b/server/scripts/deploy/museum.nginx.service index 93e414a01e..fa0472ca8c 100644 --- a/server/scripts/deploy/museum.nginx.service +++ b/server/scripts/deploy/museum.nginx.service @@ -10,7 +10,8 @@ ExecStartPre=docker pull rg.fr-par.scw.cloud/ente/museum-prod ExecStartPre=-docker stop museum ExecStartPre=-docker rm museum ExecStart=docker run --name museum \ - -e ENVIRONMENT=proxy \ + -e ENVIRONMENT=production \ + -e ENTE_HTTP-USE_TLS=0 \ --hostname "%H" \ -p 8080:8080 \ -p 2112:2112 \ From 30cf709eb24da26ae7a06d0a5cfa1b057d53c858 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 12:39:16 +0530 Subject: [PATCH 365/391] Wrap --- server/scripts/deploy/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/scripts/deploy/README.md b/server/scripts/deploy/README.md index 5b55e6e78e..78766064bf 100644 --- a/server/scripts/deploy/README.md +++ b/server/scripts/deploy/README.md @@ -42,7 +42,8 @@ To bring up an additional museum node: * Prepare the instance to run our services -* Setup [promtail](../../../infra/services/promtail/README.md), [prometheus and node-exporter](../../../infra/services/prometheus/README.md) services +* Setup [promtail](../../../infra/services/promtail/README.md), [prometheus and + node-exporter](../../../infra/services/prometheus/README.md) services * If running behind Nginx, install the [nginx](../../../infra/services/nginx/README.md) service. From 7ded8ad4fe1265729edb7b0463615f2bcdce5b9a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 13:07:36 +0530 Subject: [PATCH 366/391] Fix key name --- server/cmd/museum/main.go | 2 +- server/configurations/local.yaml | 2 +- server/configurations/production.yaml | 2 +- server/scripts/deploy/museum.nginx.service | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 2c9f5fdd41..bf661d7d63 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -712,7 +712,7 @@ func main() { } func runServer(environment string, server *gin.Engine) { - useTLS := viper.GetBool("http.use_tls") + useTLS := viper.GetBool("http.use-tls") if useTLS { certPath, err := config.CredentialFilePath("tls.cert") if err != nil { diff --git a/server/configurations/local.yaml b/server/configurations/local.yaml index ebb85833b5..80274df194 100644 --- a/server/configurations/local.yaml +++ b/server/configurations/local.yaml @@ -69,7 +69,7 @@ log-file: "" http: # If true, bind to 443 and use TLS. # By default, this is false, and museum will bind to 8080 without TLS. - # use_tls: true + # use-tls: true # Database connection parameters db: diff --git a/server/configurations/production.yaml b/server/configurations/production.yaml index d3d48b3568..937d0c907a 100644 --- a/server/configurations/production.yaml +++ b/server/configurations/production.yaml @@ -1,7 +1,7 @@ log-file: /var/logs/museum.log http: - use_tls: true + use-tls: true stripe: path: diff --git a/server/scripts/deploy/museum.nginx.service b/server/scripts/deploy/museum.nginx.service index fa0472ca8c..e484cc73fb 100644 --- a/server/scripts/deploy/museum.nginx.service +++ b/server/scripts/deploy/museum.nginx.service @@ -11,7 +11,7 @@ ExecStartPre=-docker stop museum ExecStartPre=-docker rm museum ExecStart=docker run --name museum \ -e ENVIRONMENT=production \ - -e ENTE_HTTP-USE_TLS=0 \ + -e ENTE_HTTP_USE-TLS=1 \ --hostname "%H" \ -p 8080:8080 \ -p 2112:2112 \ From 2f38f23b7787e42842e80ab38af889eaac52c327 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 13:30:07 +0530 Subject: [PATCH 367/391] Update install instructions --- infra/services/nginx/README.md | 8 ++++++++ infra/services/prometheus/README.md | 3 ++- infra/services/promtail/README.md | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/infra/services/nginx/README.md b/infra/services/nginx/README.md index 923c33712a..2cf335f212 100644 --- a/infra/services/nginx/README.md +++ b/infra/services/nginx/README.md @@ -6,6 +6,14 @@ proxy for arbitrary services by adding new entries in `/root/nginx/conf.d` and ## Installation +Copy the service definition + +```sh +scp services/nginx/nginx.service : + +sudo mv nginx.service /etc/systemd/system/nginx.service +``` + Create a directory to house service specific configuration sudo mkdir -p /root/nginx/conf.d diff --git a/infra/services/prometheus/README.md b/infra/services/prometheus/README.md index 54ca3e5595..8f05f7fb9b 100644 --- a/infra/services/prometheus/README.md +++ b/infra/services/prometheus/README.md @@ -15,7 +15,8 @@ remember to change the hardcoded `XX-HOSTNAME` too in addition to adding the `remote_write` configuration. ```sh -scp services/prometheus/* : +scp services/prometheus/prometheus.* : +scp services/prometheus/node-exporter.service : nano prometheus.yml sudo mv prometheus.yml /root/prometheus.yml diff --git a/infra/services/promtail/README.md b/infra/services/promtail/README.md index 389542e177..e6d3352962 100644 --- a/infra/services/promtail/README.md +++ b/infra/services/promtail/README.md @@ -9,7 +9,7 @@ Replace `client.url` in the config file with the Loki URL that Promtail should connect to, and move the files to their expected place. ```sh -scp services/promtail/* : +scp services/promtail/promtail.* : nano promtail.yaml sudo mv promtail.yaml /root/promtail.yaml From c43a0a7182e582d2e9b1597dff3ce26537996c92 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 13:31:10 +0530 Subject: [PATCH 368/391] Shorten --- infra/services/promtail/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/infra/services/promtail/README.md b/infra/services/promtail/README.md index e6d3352962..9a12b10c33 100644 --- a/infra/services/promtail/README.md +++ b/infra/services/promtail/README.md @@ -21,6 +21,5 @@ automatically starts on boot), and start it this time around. ```sh sudo systemctl daemon-reload -sudo systemctl enable promtail -sudo systemctl start promtail +sudo systemctl enable --now promtail ``` From 53cf5ffc45d18745e62c93b38e6e28437a5fa652 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 14:35:42 +0530 Subject: [PATCH 369/391] Fix some paths in README --- server/scripts/deploy/README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/server/scripts/deploy/README.md b/server/scripts/deploy/README.md index 78766064bf..04d1212109 100644 --- a/server/scripts/deploy/README.md +++ b/server/scripts/deploy/README.md @@ -55,6 +55,13 @@ To bring up an additional museum node: sudo tee /root/museum/credentials/fcm-service-account.json sudo tee /root/museum/credentials.yaml +* Add billing data + + scp /path/to/billing/*.json : + + sudo mkdir -p /root/museum/data/billing + sudo mv *.json /root/museum/data/billing/ + * If not running behind Nginx, add the TLS credentials (otherwise add the to Nginx) @@ -79,7 +86,7 @@ To bring up an additional museum node: scp scripts/deploy/museum.nginx.conf : - sudo mv museum.nginx.conf /etc/systemd/system + sudo mv museum.nginx.conf /root/nginx/conf.d sudo systemctl restart nginx ## Starting From c564e50d592a0c08e2e264e893005bc37eebb5d0 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 18 Mar 2024 14:38:11 +0530 Subject: [PATCH 370/391] [server] change method type to post --- server/cmd/museum/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 8e4d08deba..1bbf7580af 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -681,7 +681,7 @@ func main() { privateAPI.PUT("/embeddings", embeddingHandler.InsertOrUpdate) privateAPI.GET("/embeddings/diff", embeddingHandler.GetDiff) - privateAPI.GET("/embeddings/files", embeddingHandler.GetFilesEmbedding) + privateAPI.POST("/embeddings/files", embeddingHandler.GetFilesEmbedding) privateAPI.DELETE("/embeddings", embeddingHandler.DeleteAll) offerHandler := &api.OfferHandler{Controller: offerController} From f494832bd774045f7004e1c424829138380966e0 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 15:21:47 +0530 Subject: [PATCH 371/391] Limit max connections at the nginx level --- server/scripts/deploy/museum.nginx.conf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/scripts/deploy/museum.nginx.conf b/server/scripts/deploy/museum.nginx.conf index fb3da7d1dc..3213122a76 100644 --- a/server/scripts/deploy/museum.nginx.conf +++ b/server/scripts/deploy/museum.nginx.conf @@ -1,3 +1,7 @@ +upstream museum { + server host.docker.internal:8080 max_conns=50; +} + server { listen 443 ssl http2; listen [::]:443 ssl http2; @@ -7,7 +11,7 @@ server { server_name api.ente.io; location / { - proxy_pass http://host.docker.internal:8080; + proxy_pass http://museum; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; From 27b13765d717ce72b9e0d872ea06c4440b615f13 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 15:23:23 +0530 Subject: [PATCH 372/391] Fix the environment var --- server/scripts/deploy/museum.nginx.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/scripts/deploy/museum.nginx.service b/server/scripts/deploy/museum.nginx.service index e484cc73fb..566c6c0486 100644 --- a/server/scripts/deploy/museum.nginx.service +++ b/server/scripts/deploy/museum.nginx.service @@ -11,7 +11,7 @@ ExecStartPre=-docker stop museum ExecStartPre=-docker rm museum ExecStart=docker run --name museum \ -e ENVIRONMENT=production \ - -e ENTE_HTTP_USE-TLS=1 \ + -e ENTE_HTTP_USE-TLS=0 \ --hostname "%H" \ -p 8080:8080 \ -p 2112:2112 \ From c177efe79cb657b1052d5531db85f2c65d2bdf98 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 15:44:00 +0530 Subject: [PATCH 373/391] Add documentation comments --- infra/services/nginx/README.md | 19 +++++++++++++++++++ server/scripts/deploy/museum.nginx.conf | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/infra/services/nginx/README.md b/infra/services/nginx/README.md index 2cf335f212..6d46b4de18 100644 --- a/infra/services/nginx/README.md +++ b/infra/services/nginx/README.md @@ -38,3 +38,22 @@ When adding new services that sit behind Nginx, 1. Add its nginx conf file to `/root/nginx/conf.d` 2. Restart nginx (`sudo systemctl restart nginx`) + +## Configuration files + +All the files we put into `/root/nginx/conf.d` get included in an `http` block. +We can see this in the default configuration of nginx: + + http { + ... + include /etc/nginx/conf.d/*.conf; + } + +> To view the default configuration, run the following command against the +> [official Docker image for Nginx](https://hub.docker.com/_/nginx), which is +> also what we use: +> +> docker run --rm --entrypoint=cat nginx /etc/nginx/nginx.conf > /tmp/nginx.conf + +This is a [handy tool](https://nginx-playground.wizardzines.com) to check the +syntax of the configuration files. diff --git a/server/scripts/deploy/museum.nginx.conf b/server/scripts/deploy/museum.nginx.conf index 3213122a76..65ed19b49e 100644 --- a/server/scripts/deploy/museum.nginx.conf +++ b/server/scripts/deploy/museum.nginx.conf @@ -1,4 +1,8 @@ +# This file gets loaded in a top level http block by the default nginx.conf +# See infra/services/nginx/README.md for more details. + upstream museum { + # https://nginx.org/en/docs/http/ngx_http_upstream_module.html server host.docker.internal:8080 max_conns=50; } From fb0e2d2604d7d2b198f1a82df90f34879e39bd88 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 15:54:25 +0530 Subject: [PATCH 374/391] Don't restart museum on restarting nginx --- server/scripts/deploy/museum.nginx.service | 1 - 1 file changed, 1 deletion(-) diff --git a/server/scripts/deploy/museum.nginx.service b/server/scripts/deploy/museum.nginx.service index 566c6c0486..73cdd3ff1c 100644 --- a/server/scripts/deploy/museum.nginx.service +++ b/server/scripts/deploy/museum.nginx.service @@ -2,7 +2,6 @@ Documentation=https://github.com/ente-io/ente/tree/main/server#readme Requires=docker.service After=docker.service -Requires=nginx.service [Service] Restart=on-failure From 4ff378cd0636da788de54f2de91c149828f267c8 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 20:01:37 +0530 Subject: [PATCH 375/391] [web] Update translations for the non-photos apps --- .../public/locales/bg-BG/translation.json | 654 +++++++++ .../public/locales/de-DE/translation.json | 316 ++-- .../public/locales/en-US/translation.json | 20 +- .../public/locales/es-ES/translation.json | 20 +- .../public/locales/fa-IR/translation.json | 20 +- .../public/locales/fi-FI/translation.json | 20 +- .../public/locales/fr-FR/translation.json | 20 +- .../public/locales/it-IT/translation.json | 20 +- .../public/locales/ko-KR/translation.json | 170 +-- .../public/locales/nl-NL/translation.json | 20 +- .../public/locales/pt-BR/translation.json | 48 +- .../public/locales/pt-PT/translation.json | 20 +- .../public/locales/ru-RU/translation.json | 20 +- .../public/locales/sv-SE/translation.json | 124 +- .../public/locales/th-TH/translation.json | 20 +- .../public/locales/tr-TR/translation.json | 20 +- .../public/locales/zh-CN/translation.json | 28 +- .../public/locales/bg-BG/translation.json | 654 +++++++++ .../public/locales/de-DE/translation.json | 630 ++++---- .../public/locales/en-US/translation.json | 20 +- .../public/locales/es-ES/translation.json | 234 +-- .../public/locales/fa-IR/translation.json | 1268 ++++++++-------- .../public/locales/fi-FI/translation.json | 1270 +++++++++-------- .../public/locales/fr-FR/translation.json | 60 +- .../public/locales/it-IT/translation.json | 604 ++++---- .../public/locales/ko-KR/translation.json | 654 +++++++++ .../public/locales/nl-NL/translation.json | 42 +- .../public/locales/pt-BR/translation.json | 48 +- .../public/locales/pt-PT/translation.json | 1180 +++++++-------- .../public/locales/ru-RU/translation.json | 1270 +++++++++-------- .../public/locales/sv-SE/translation.json | 654 +++++++++ .../public/locales/th-TH/translation.json | 654 +++++++++ .../public/locales/tr-TR/translation.json | 1270 +++++++++-------- .../public/locales/zh-CN/translation.json | 28 +- .../public/locales/bg-BG/translation.json | 654 +++++++++ .../public/locales/de-DE/translation.json | 654 +++++++++ .../public/locales/en-US}/translation.json | 20 +- .../public/locales/es-ES/translation.json | 654 +++++++++ .../public/locales/fa-IR/translation.json | 654 +++++++++ .../public/locales/fi-FI/translation.json | 654 +++++++++ .../public/locales/fr-FR/translation.json | 654 +++++++++ .../public/locales/it-IT/translation.json | 654 +++++++++ .../public/locales/ko-KR/translation.json | 654 +++++++++ .../public/locales/nl-NL/translation.json | 654 +++++++++ .../public/locales/pt-BR/translation.json | 654 +++++++++ .../public/locales/pt-PT/translation.json | 654 +++++++++ .../public/locales/ru-RU/translation.json | 654 +++++++++ .../public/locales/sv-SE/translation.json | 654 +++++++++ .../public/locales/th-TH/translation.json | 654 +++++++++ .../public/locales/tr-TR/translation.json | 654 +++++++++ .../public/locales/zh-CN/translation.json | 654 +++++++++ 51 files changed, 18309 insertions(+), 4275 deletions(-) create mode 100644 web/apps/accounts/public/locales/bg-BG/translation.json create mode 100644 web/apps/auth/public/locales/bg-BG/translation.json create mode 100644 web/apps/auth/public/locales/ko-KR/translation.json create mode 100644 web/apps/auth/public/locales/sv-SE/translation.json create mode 100644 web/apps/auth/public/locales/th-TH/translation.json create mode 100644 web/apps/cast/public/locales/bg-BG/translation.json create mode 100644 web/apps/cast/public/locales/de-DE/translation.json rename web/apps/{accounts/public/locales/en => cast/public/locales/en-US}/translation.json (97%) create mode 100644 web/apps/cast/public/locales/es-ES/translation.json create mode 100644 web/apps/cast/public/locales/fa-IR/translation.json create mode 100644 web/apps/cast/public/locales/fi-FI/translation.json create mode 100644 web/apps/cast/public/locales/fr-FR/translation.json create mode 100644 web/apps/cast/public/locales/it-IT/translation.json create mode 100644 web/apps/cast/public/locales/ko-KR/translation.json create mode 100644 web/apps/cast/public/locales/nl-NL/translation.json create mode 100644 web/apps/cast/public/locales/pt-BR/translation.json create mode 100644 web/apps/cast/public/locales/pt-PT/translation.json create mode 100644 web/apps/cast/public/locales/ru-RU/translation.json create mode 100644 web/apps/cast/public/locales/sv-SE/translation.json create mode 100644 web/apps/cast/public/locales/th-TH/translation.json create mode 100644 web/apps/cast/public/locales/tr-TR/translation.json create mode 100644 web/apps/cast/public/locales/zh-CN/translation.json diff --git a/web/apps/accounts/public/locales/bg-BG/translation.json b/web/apps/accounts/public/locales/bg-BG/translation.json new file mode 100644 index 0000000000..03faf16c2d --- /dev/null +++ b/web/apps/accounts/public/locales/bg-BG/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Личен бекъп
на твоите спомени
", + "HERO_SLIDE_1": "Криптиран от край до край по подразбиране", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/accounts/public/locales/de-DE/translation.json b/web/apps/accounts/public/locales/de-DE/translation.json index c0333d1317..9a1c4073c6 100644 --- a/web/apps/accounts/public/locales/de-DE/translation.json +++ b/web/apps/accounts/public/locales/de-DE/translation.json @@ -31,80 +31,78 @@ "VERIFY_PASSPHRASE": "Einloggen", "INCORRECT_PASSPHRASE": "Falsches Passwort", "ENTER_ENC_PASSPHRASE": "Bitte gib ein Passwort ein, mit dem wir deine Daten verschlüsseln können", - "PASSPHRASE_DISCLAIMER": "", + "PASSPHRASE_DISCLAIMER": "Wir speichern dein Passwort nicht. Wenn du es vergisst, können wir dir nicht helfen, deine Daten ohne einen Wiederherstellungsschlüssel wiederherzustellen.", "WELCOME_TO_ENTE_HEADING": "Willkommen bei
", - "WELCOME_TO_ENTE_SUBHEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "Ende-zu-Ende verschlüsselte Fotospeicherung und Freigabe", "WHERE_YOUR_BEST_PHOTOS_LIVE": "Wo deine besten Fotos leben", "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generierung von Verschlüsselungsschlüsseln...", "PASSPHRASE_HINT": "Passwort", "CONFIRM_PASSPHRASE": "Passwort bestätigen", - "REFERRAL_CODE_HINT": "", - "REFERRAL_INFO": "", + "REFERRAL_CODE_HINT": "Wie hast du von Ente erfahren? (optional)", + "REFERRAL_INFO": "Wir tracken keine App-Installationen. Es würde uns jedoch helfen, wenn du uns mitteilst, wie du von uns erfahren hast!", "PASSPHRASE_MATCH_ERROR": "Die Passwörter stimmen nicht überein", - "CONSOLE_WARNING_STOP": "STOPP!", - "CONSOLE_WARNING_DESC": "", "CREATE_COLLECTION": "Neues Album", "ENTER_ALBUM_NAME": "Albumname", "CLOSE_OPTION": "Schließen (Esc)", "ENTER_FILE_NAME": "Dateiname", "CLOSE": "Schließen", "NO": "Nein", - "NOTHING_HERE": "", + "NOTHING_HERE": "Hier gibt es noch nichts zu sehen 👀", "UPLOAD": "Hochladen", "IMPORT": "Importieren", "ADD_PHOTOS": "Fotos hinzufügen", "ADD_MORE_PHOTOS": "Mehr Fotos hinzufügen", - "add_photos_one": "", - "add_photos_other": "", + "add_photos_one": "Eine Datei hinzufügen", + "add_photos_other": "{{count, number}} Dateien hinzufügen", "SELECT_PHOTOS": "Foto auswählen", "FILE_UPLOAD": "Datei hochladen", "UPLOAD_STAGE_MESSAGE": { "0": "Hochladen wird vorbereitet", - "1": "", - "2": "", - "3": "", - "4": "", + "1": "Lese Google-Metadaten", + "2": "Metadaten von {{uploadCounter.finished, number}} / {{uploadCounter.total, number}} Dateien extrahiert", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} Dateien verarbeitet", + "4": "Verbleibende Uploads werden abgebrochen", "5": "Sicherung abgeschlossen" }, - "FILE_NOT_UPLOADED_LIST": "", + "FILE_NOT_UPLOADED_LIST": "Die folgenden Dateien wurden nicht hochgeladen", "SUBSCRIPTION_EXPIRED": "Abonnement abgelaufen", - "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Dein Abonnement ist abgelaufen, bitte erneuere es", "STORAGE_QUOTA_EXCEEDED": "Speichergrenze überschritten", - "INITIAL_LOAD_DELAY_WARNING": "", - "USER_DOES_NOT_EXIST": "", - "NO_ACCOUNT": "", - "ACCOUNT_EXISTS": "", + "INITIAL_LOAD_DELAY_WARNING": "Das erste Laden kann einige Zeit in Anspruch nehmen", + "USER_DOES_NOT_EXIST": "Leider konnte kein Benutzer mit dieser E-Mail gefunden werden", + "NO_ACCOUNT": "Kein Konto vorhanden", + "ACCOUNT_EXISTS": "Es ist bereits ein Account vorhanden", "CREATE": "Erstellen", "DOWNLOAD": "Herunterladen", "DOWNLOAD_OPTION": "Herunterladen (D)", "DOWNLOAD_FAVORITES": "Favoriten herunterladen", - "DOWNLOAD_UNCATEGORIZED": "", - "DOWNLOAD_HIDDEN_ITEMS": "", + "DOWNLOAD_UNCATEGORIZED": "Download unkategorisiert", + "DOWNLOAD_HIDDEN_ITEMS": "Versteckte Dateien herunterladen", "COPY_OPTION": "Als PNG kopieren (Strg / Cmd - C)", - "TOGGLE_FULLSCREEN": "", + "TOGGLE_FULLSCREEN": "Vollbild umschalten (F)", "ZOOM_IN_OUT": "Herein-/Herauszoomen", - "PREVIOUS": "", - "NEXT": "", - "TITLE_PHOTOS": "", - "TITLE_ALBUMS": "", - "TITLE_AUTH": "", + "PREVIOUS": "Vorherige (←)", + "NEXT": "Weitere (→)", + "TITLE_PHOTOS": "Ente Fotos", + "TITLE_ALBUMS": "Ente Fotos", + "TITLE_AUTH": "Ente Auth", "UPLOAD_FIRST_PHOTO": "Lade dein erstes Foto hoch", "IMPORT_YOUR_FOLDERS": "Importiere deiner Ordner", - "UPLOAD_DROPZONE_MESSAGE": "", - "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "UPLOAD_DROPZONE_MESSAGE": "Loslassen, um Dateien zu sichern", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Loslassen, um beobachteten Ordner hinzuzufügen", "TRASH_FILES_TITLE": "Dateien löschen?", "TRASH_FILE_TITLE": "Datei löschen?", "DELETE_FILES_TITLE": "Sofort löschen?", - "DELETE_FILES_MESSAGE": "", + "DELETE_FILES_MESSAGE": "Ausgewählte Dateien werden dauerhaft aus Ihrem Ente-Konto gelöscht.", "DELETE": "Löschen", "DELETE_OPTION": "Löschen (DEL)", - "FAVORITE_OPTION": "", - "UNFAVORITE_OPTION": "", - "MULTI_FOLDER_UPLOAD": "", - "UPLOAD_STRATEGY_CHOICE": "", + "FAVORITE_OPTION": "Zu Favoriten hinzufügen (L)", + "UNFAVORITE_OPTION": "Von Favoriten entfernen (L)", + "MULTI_FOLDER_UPLOAD": "Mehrere Ordner erkannt", + "UPLOAD_STRATEGY_CHOICE": "Möchtest du sie hochladen in", "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Ein einzelnes Album", "OR": "oder", - "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Getrennte Alben", "SESSION_EXPIRED_MESSAGE": "Ihre Sitzung ist abgelaufen. Bitte loggen Sie sich erneut ein, um fortzufahren", "SESSION_EXPIRED": "Sitzung abgelaufen", "PASSWORD_GENERATION_FAILED": "Dein Browser konnte keinen starken Schlüssel generieren, der den Verschlüsselungsstandards des Entes entspricht, bitte versuche die mobile App oder einen anderen Browser zu verwenden", @@ -113,9 +111,9 @@ "RECOVERY_KEY": "Wiederherstellungsschlüssel", "SAVE_LATER": "Auf später verschieben", "SAVE": "Schlüssel speichern", - "RECOVERY_KEY_DESCRIPTION": "", - "RECOVER_KEY_GENERATION_FAILED": "", - "KEY_NOT_STORED_DISCLAIMER": "", + "RECOVERY_KEY_DESCRIPTION": "Falls du dein Passwort vergisst, kannst du deine Daten nur mit diesem Schlüssel wiederherstellen.", + "RECOVER_KEY_GENERATION_FAILED": "Wiederherstellungsschlüssel konnte nicht generiert werden, bitte versuche es erneut", + "KEY_NOT_STORED_DISCLAIMER": "Wir speichern diesen Schlüssel nicht, also speichere ihn bitte an einem sicheren Ort", "FORGOT_PASSWORD": "Passwort vergessen", "RECOVER_ACCOUNT": "Konto wiederherstellen", "RECOVERY_KEY_HINT": "Wiederherstellungsschlüssel", @@ -132,15 +130,15 @@ "CANCEL": "Abbrechen", "LOGOUT": "Ausloggen", "DELETE_ACCOUNT": "Konto löschen", - "DELETE_ACCOUNT_MESSAGE": "", + "DELETE_ACCOUNT_MESSAGE": "

Bitte sende eine E-Mail an {{emailID}} mit deiner registrierten E-Mail-Adresse.

Deine Anfrage wird innerhalb von 72 Stunden bearbeitet.

", "LOGOUT_MESSAGE": "Sind sie sicher, dass sie sich ausloggen möchten?", "CHANGE_EMAIL": "E-Mail-Adresse ändern", "OK": "OK", "SUCCESS": "Erfolgreich", "ERROR": "Fehler", "MESSAGE": "Nachricht", - "INSTALL_MOBILE_APP": "", - "DOWNLOAD_APP_MESSAGE": "", + "INSTALL_MOBILE_APP": "Installiere unsere Android oder iOS App, um automatisch alle deine Fotos zu sichern", + "DOWNLOAD_APP_MESSAGE": "Entschuldigung, dieser Vorgang wird derzeit nur von unserer Desktop-App unterstützt", "DOWNLOAD_APP": "Desktopanwendung herunterladen", "EXPORT": "Daten exportieren", "SUBSCRIPTION": "Abonnement", @@ -154,37 +152,37 @@ "MANAGE_PLAN": "Verwalte dein Abonnement", "ACTIVE": "Aktiv", "OFFLINE_MSG": "Du bist offline, gecachte Erinnerungen werden angezeigt", - "FREE_SUBSCRIPTION_INFO": "", + "FREE_SUBSCRIPTION_INFO": "Du bist auf dem kostenlosen Plan, der am {{date, dateTime}} ausläuft", "FAMILY_SUBSCRIPTION_INFO": "Sie haben einen Familienplan verwaltet von", "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Erneuert am {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Endet am {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Ihr Abo endet am {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "", + "ADD_ON_AVAILABLE_TILL": "Dein {{storage, string}} Add-on ist gültig bis {{date, dateTime}}", "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Sie haben Ihr Speichervolumen überschritten, bitte upgraden Sie", - "SUBSCRIPTION_PURCHASE_SUCCESS": "", - "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

Wir haben deine Zahlung erhalten

Dein Abonnement ist gültig bis {{date, dateTime}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "Dein Kauf wurde abgebrochen. Bitte versuche es erneut, wenn du abonnieren willst", "SUBSCRIPTION_PURCHASE_FAILED": "Kauf des Abonnements fehlgeschlagen Bitte versuchen Sie es erneut", "SUBSCRIPTION_UPDATE_FAILED": "Aktualisierung des Abonnements fehlgeschlagen Bitte versuchen Sie es erneut", - "UPDATE_PAYMENT_METHOD_MESSAGE": "", - "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Es tut uns leid, die Zahlung ist fehlgeschlagen, als wir versuchten Ihre Karte zu belasten. Bitte aktualisieren Sie Ihre Zahlungsmethode und versuchen Sie es erneut", + "STRIPE_AUTHENTICATION_FAILED": "Wir können deine Zahlungsmethode nicht authentifizieren. Bitte wähle eine andere Zahlungsmethode und versuche es erneut", "UPDATE_PAYMENT_METHOD": "Zahlungsmethode aktualisieren", "MONTHLY": "Monatlich", "YEARLY": "Jährlich", "UPDATE_SUBSCRIPTION_MESSAGE": "Sind Sie sicher, dass Sie Ihren Tarif ändern möchten?", "UPDATE_SUBSCRIPTION": "Plan ändern", "CANCEL_SUBSCRIPTION": "Abonnement kündigen", - "CANCEL_SUBSCRIPTION_MESSAGE": "", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", - "SUBSCRIPTION_CANCEL_FAILED": "", - "SUBSCRIPTION_CANCEL_SUCCESS": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Alle deine Daten werden am Ende dieses Abrechnungszeitraums von unseren Servern gelöscht.

Bist du sicher, dass du dein Abonnement kündigen möchtest?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Bist du sicher, dass du dein Abonnement beenden möchtest?

", + "SUBSCRIPTION_CANCEL_FAILED": "Abonnement konnte nicht storniert werden", + "SUBSCRIPTION_CANCEL_SUCCESS": "Abonnement erfolgreich beendet", "REACTIVATE_SUBSCRIPTION": "Abonnement reaktivieren", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "", - "SUBSCRIPTION_ACTIVATE_SUCCESS": "", - "SUBSCRIPTION_ACTIVATE_FAILED": "", - "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", - "CANCEL_SUBSCRIPTION_ON_MOBILE": "", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", - "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Nach der Reaktivierung wird am {{date, dateTime}} abgerechnet", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Abonnement erfolgreich aktiviert ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Reaktivierung der Abonnementverlängerung fehlgeschlagen", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Vielen Dank", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Mobiles Abonnement kündigen", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Bitte kündige dein Abonnement in der mobilen App, um hier ein Abonnement zu aktivieren", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Bitte kontaktiere uns über {{emailID}}, um dein Abo zu verwalten", "RENAME": "Umbenennen", "RENAME_FILE": "Datei umbenennen", "RENAME_COLLECTION": "Album umbenennen", @@ -198,43 +196,43 @@ "SHAREES": "Geteilt mit", "SHARE_WITH_SELF": "Du kannst nicht mit dir selbst teilen", "ALREADY_SHARED": "Hoppla, Sie teilen dies bereits mit {{email}}", - "SHARING_BAD_REQUEST_ERROR": "", - "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "SHARING_BAD_REQUEST_ERROR": "Albumfreigabe nicht erlaubt", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Freigabe ist für kostenlose Konten deaktiviert", "DOWNLOAD_COLLECTION": "Album herunterladen", - "DOWNLOAD_COLLECTION_MESSAGE": "", - "CREATE_ALBUM_FAILED": "", + "DOWNLOAD_COLLECTION_MESSAGE": "

Bist du sicher, dass du das komplette Album herunterladen möchtest?

Alle Dateien werden der Warteschlange zum sequenziellen Download hinzugefügt

", + "CREATE_ALBUM_FAILED": "Fehler beim Erstellen des Albums, bitte versuche es erneut", "SEARCH": "Suchen", "SEARCH_RESULTS": "Ergebnisse durchsuchen", - "NO_RESULTS": "", - "SEARCH_HINT": "", + "NO_RESULTS": "Keine Ergebnisse gefunden", + "SEARCH_HINT": "Suche nach Alben, Datum, Beschreibungen, ...", "SEARCH_TYPE": { "COLLECTION": "Album", "LOCATION": "Standort", - "CITY": "", + "CITY": "Ort", "DATE": "Datum", "FILE_NAME": "Dateiname", "THING": "Inhalt", "FILE_CAPTION": "Beschreibung", - "FILE_TYPE": "", - "CLIP": "" + "FILE_TYPE": "Dateityp", + "CLIP": "Magie" }, "photos_count_zero": "Keine Erinnerungen", - "photos_count_one": "", - "photos_count_other": "", - "TERMS_AND_CONDITIONS": "", + "photos_count_one": "Eine Erinnerung", + "photos_count_other": "{{count, number}} Erinnerungen", + "TERMS_AND_CONDITIONS": "Ich stimme den Bedingungen und Datenschutzrichtlinien zu", "ADD_TO_COLLECTION": "Zum Album hinzufügen", - "SELECTED": "", - "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "SELECTED": "ausgewählt", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Dieses Video kann in deinem Browser nicht abgespielt werden", "PEOPLE": "Personen", - "INDEXING_SCHEDULED": "", - "ANALYZING_PHOTOS": "", - "INDEXING_PEOPLE": "", - "INDEXING_DONE": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "INDEXING_SCHEDULED": "Indizierung ist geplant...", + "ANALYZING_PHOTOS": "Indiziere Fotos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", + "INDEXING_PEOPLE": "Indiziere Personen in {{indexStatus.nSyncedFiles,number}} Fotos...", + "INDEXING_DONE": "{{indexStatus.nSyncedFiles,number}} Fotos wurden indiziert", + "UNIDENTIFIED_FACES": "unidentifizierte Gesichter", + "OBJECTS": "Objekte", + "TEXT": "Text", "INFO": "Info ", - "INFO_OPTION": "", + "INFO_OPTION": "Info (I)", "FILE_NAME": "Dateiname", "CAPTION_PLACEHOLDER": "Eine Beschreibung hinzufügen", "LOCATION": "Standort", @@ -244,8 +242,8 @@ "ENABLE_MAPS": "Karten aktivieren?", "ENABLE_MAP": "Karte aktivieren", "DISABLE_MAPS": "Karten deaktivieren?", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", + "ENABLE_MAP_DESCRIPTION": "

Dies wird deine Fotos auf einer Weltkarte anzeigen.

Die Karte wird von OpenStreetMap gehostet und die genauen Standorte deiner Fotos werden niemals geteilt.

Diese Funktion kannst du jederzeit in den Einstellungen deaktivieren.

", + "DISABLE_MAP_DESCRIPTION": "

Dies wird die Anzeige deiner Fotos auf einer Weltkarte deaktivieren.

Du kannst diese Funktion jederzeit in den Einstellungen aktivieren.

", "DISABLE_MAP": "Karte deaktivieren", "DETAILS": "Details", "VIEW_EXIF": "Alle EXIF-Daten anzeigen", @@ -254,67 +252,67 @@ "ISO": "ISO", "TWO_FACTOR": "Zwei-Faktor", "TWO_FACTOR_AUTHENTICATION": "Zwei-Faktor-Authentifizierung", - "TWO_FACTOR_QR_INSTRUCTION": "", + "TWO_FACTOR_QR_INSTRUCTION": "Scanne den QR-Code unten mit deiner bevorzugten Authentifizierungs-App", "ENTER_CODE_MANUALLY": "Geben Sie den Code manuell ein", - "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Bitte gib diesen Code in deiner bevorzugten Authentifizierungs-App ein", "SCAN_QR_CODE": "QR‐Code stattdessen scannen", "ENABLE_TWO_FACTOR": "Zwei-Faktor-Authentifizierung aktivieren", "ENABLE": "Aktivieren", - "LOST_DEVICE": "", + "LOST_DEVICE": "Zwei-Faktor-Gerät verloren", "INCORRECT_CODE": "Falscher Code", - "TWO_FACTOR_INFO": "", + "TWO_FACTOR_INFO": "Fügen Sie eine zusätzliche Sicherheitsebene hinzu, indem Sie mehr als Ihre E-Mail und Ihr Passwort benötigen, um sich mit Ihrem Account anzumelden", "DISABLE_TWO_FACTOR_LABEL": "Deaktiviere die Zwei-Faktor-Authentifizierung", - "UPDATE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "Authentifizierungsgerät aktualisieren", "DISABLE": "Deaktivieren", "RECONFIGURE": "Neu einrichten", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "UPDATE_TWO_FACTOR": "Zweiten Faktor aktualisieren", + "UPDATE_TWO_FACTOR_MESSAGE": "Fahren Sie fort, werden alle Ihre zuvor konfigurierten Authentifikatoren ungültig", + "UPDATE": "Aktualisierung", + "DISABLE_TWO_FACTOR": "Zweiten Faktor deaktivieren", + "DISABLE_TWO_FACTOR_MESSAGE": "Bist du sicher, dass du die Zwei-Faktor-Authentifizierung deaktivieren willst", + "TWO_FACTOR_DISABLE_FAILED": "Fehler beim Deaktivieren des zweiten Faktors, bitte versuchen Sie es erneut", "EXPORT_DATA": "Daten exportieren", "SELECT_FOLDER": "Ordner auswählen", "DESTINATION": "Zielort", "START": "Start", - "LAST_EXPORT_TIME": "", - "EXPORT_AGAIN": "", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "LAST_EXPORT_TIME": "Letztes Exportdatum", + "EXPORT_AGAIN": "Neusynchronisation", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Lokaler Speicher nicht zugänglich", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Ihr Browser oder ein Addon blockiert ente vor der Speicherung von Daten im lokalen Speicher. Bitte versuchen Sie, den Browser-Modus zu wechseln und die Seite neu zu laden.", "SEND_OTT": "OTP senden", "EMAIl_ALREADY_OWNED": "Diese E-Mail wird bereits verwendet", "ETAGS_BLOCKED": "", "SKIPPED_VIDEOS_INFO": "", "LIVE_PHOTOS_DETECTED": "", - "RETRY_FAILED": "", + "RETRY_FAILED": "Fehlgeschlagene Uploads erneut probieren", "FAILED_UPLOADS": "Fehlgeschlagene Uploads ", "SKIPPED_FILES": "Ignorierte Uploads", "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Das Vorschaubild konnte nicht erzeugt werden", "UNSUPPORTED_FILES": "Nicht unterstützte Dateien", - "SUCCESSFUL_UPLOADS": "", + "SUCCESSFUL_UPLOADS": "Erfolgreiche Uploads", "SKIPPED_INFO": "", "UNSUPPORTED_INFO": "ente unterstützt diese Dateiformate noch nicht", "BLOCKED_UPLOADS": "Blockierte Uploads", "SKIPPED_VIDEOS": "Übersprungene Videos", "INPROGRESS_METADATA_EXTRACTION": "In Bearbeitung", - "INPROGRESS_UPLOADS": "", + "INPROGRESS_UPLOADS": "Upload läuft", "TOO_LARGE_UPLOADS": "Große Dateien", "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Zu wenig Speicher", "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Diese Dateien wurden nicht hochgeladen, da sie die maximale Größe für Ihren Speicherplan überschreiten", "TOO_LARGE_INFO": "Diese Dateien wurden nicht hochgeladen, da sie unsere maximale Dateigröße überschreiten", "THUMBNAIL_GENERATION_FAILED_INFO": "Diese Dateien wurden hochgeladen, aber leider konnten wir nicht die Thumbnails für sie generieren.", "UPLOAD_TO_COLLECTION": "In Album hochladen", - "UNCATEGORIZED": "", + "UNCATEGORIZED": "Unkategorisiert", "ARCHIVE": "Archiv", "FAVORITES": "Favoriten", "ARCHIVE_COLLECTION": "Album archivieren", "ARCHIVE_SECTION_NAME": "Archiv", "ALL_SECTION_NAME": "Alle", "MOVE_TO_COLLECTION": "Zum Album verschieben", - "UNARCHIVE": "", - "UNARCHIVE_COLLECTION": "", - "HIDE_COLLECTION": "", - "UNHIDE_COLLECTION": "", + "UNARCHIVE": "Dearchivieren", + "UNARCHIVE_COLLECTION": "Album dearchivieren", + "HIDE_COLLECTION": "Album ausblenden", + "UNHIDE_COLLECTION": "Album wieder einblenden", "MOVE": "Verschieben", "ADD": "Hinzufügen", "REMOVE": "Entfernen", @@ -336,86 +334,86 @@ "LEAVE_SHARED_ALBUM_MESSAGE": "", "NOT_FILE_OWNER": "Dateien in einem freigegebenen Album können nicht gelöscht werden", "CONFIRM_SELF_REMOVE_MESSAGE": "", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Einige der Elemente, die du entfernst, wurden von anderen Nutzern hinzugefügt und du wirst den Zugriff auf sie verlieren.", "SORT_BY_CREATION_TIME_ASCENDING": "Ältestem", "SORT_BY_UPDATION_TIME_DESCENDING": "Zuletzt aktualisiert", "SORT_BY_NAME": "Name", - "COMPRESS_THUMBNAILS": "", - "THUMBNAIL_REPLACED": "", + "COMPRESS_THUMBNAILS": "Vorschaubilder komprimieren", + "THUMBNAIL_REPLACED": "Vorschaubilder komprimiert", "FIX_THUMBNAIL": "Komprimiere", - "FIX_THUMBNAIL_LATER": "", + "FIX_THUMBNAIL_LATER": "Später komprimieren", "REPLACE_THUMBNAIL_NOT_STARTED": "", "REPLACE_THUMBNAIL_COMPLETED": "", "REPLACE_THUMBNAIL_NOOP": "", "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", - "FIX_CREATION_TIME": "", - "FIX_CREATION_TIME_IN_PROGRESS": "", - "CREATION_TIME_UPDATED": "", - "UPDATE_CREATION_TIME_NOT_STARTED": "", + "FIX_CREATION_TIME": "Zeit reparieren", + "FIX_CREATION_TIME_IN_PROGRESS": "Zeit wird repariert", + "CREATION_TIME_UPDATED": "Datei-Zeit aktualisiert", + "UPDATE_CREATION_TIME_NOT_STARTED": "Wählen Sie die Option, die Sie verwenden möchten", "UPDATE_CREATION_TIME_COMPLETED": "", "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", - "CAPTION_CHARACTER_LIMIT": "", + "CAPTION_CHARACTER_LIMIT": "Maximal 5000 Zeichen", "DATE_TIME_ORIGINAL": "", "DATE_TIME_DIGITIZED": "", "METADATA_DATE": "", - "CUSTOM_TIME": "", + "CUSTOM_TIME": "Benutzerdefinierte Zeit", "REOPEN_PLAN_SELECTOR_MODAL": "", - "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Fehler beim Öffnen der Pläne", "INSTALL": "Installieren", "SHARING_DETAILS": "Details teilen", - "MODIFY_SHARING": "", - "ADD_COLLABORATORS": "", - "ADD_NEW_EMAIL": "", - "shared_with_people_zero": "", - "shared_with_people_one": "", - "shared_with_people_other": "", - "participants_zero": "", - "participants_one": "", - "participants_other": "", - "ADD_VIEWERS": "", - "PARTICIPANTS": "", + "MODIFY_SHARING": "Freigabe ändern", + "ADD_COLLABORATORS": "Bearbeiter hinzufügen", + "ADD_NEW_EMAIL": "Neue E-Mail-Adresse hinzufügen", + "shared_with_people_zero": "Mit bestimmten Personen teilen", + "shared_with_people_one": "Geteilt mit einer Person", + "shared_with_people_other": "Geteilt mit {{count, number}} Personen", + "participants_zero": "Keine Teilnehmer", + "participants_one": "1 Teilnehmer", + "participants_other": "{{count, number}} Teilnehmer", + "ADD_VIEWERS": "Betrachter hinzufügen", + "PARTICIPANTS": "Teilnehmer", "CHANGE_PERMISSIONS_TO_VIEWER": "", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", - "CONVERT_TO_VIEWER": "", + "CONVERT_TO_VIEWER": "Ja, zu \"Beobachter\" ändern", "CONVERT_TO_COLLABORATOR": "", - "CHANGE_PERMISSION": "", + "CHANGE_PERMISSION": "Berechtigung ändern?", "REMOVE_PARTICIPANT": "Entfernen?", "CONFIRM_REMOVE": "Ja, entfernen", "MANAGE": "Verwalten", - "ADDED_AS": "", - "COLLABORATOR_RIGHTS": "", + "ADDED_AS": "Hinzugefügt als", + "COLLABORATOR_RIGHTS": "Bearbeiter können Fotos & Videos zu dem geteilten Album hinzufügen", "REMOVE_PARTICIPANT_HEAD": "Teilnehmer entfernen", "OWNER": "Besitzer", - "COLLABORATORS": "", - "ADD_MORE": "", - "VIEWERS": "", - "OR_ADD_EXISTING": "", + "COLLABORATORS": "Bearbeiter", + "ADD_MORE": "Mehr hinzufügen", + "VIEWERS": "Zuschauer", + "OR_ADD_EXISTING": "Oder eine Vorherige auswählen", "REMOVE_PARTICIPANT_MESSAGE": "", "NOT_FOUND": "404 - Nicht gefunden", "LINK_EXPIRED": "Link ist abgelaufen", "LINK_EXPIRED_MESSAGE": "Dieser Link ist abgelaufen oder wurde deaktiviert!", - "MANAGE_LINK": "", + "MANAGE_LINK": "Link verwalten", "LINK_TOO_MANY_REQUESTS": "Sorry, dieses Album wurde auf zu vielen Geräten angezeigt!", "FILE_DOWNLOAD": "Downloads erlauben", "LINK_PASSWORD_LOCK": "Passwort Sperre", - "PUBLIC_COLLECT": "", + "PUBLIC_COLLECT": "Hinzufügen von Fotos erlauben", "LINK_DEVICE_LIMIT": "Geräte Limit", - "NO_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "Keins", "LINK_EXPIRY": "Ablaufdatum des Links", "NEVER": "Niemals", - "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD": "Download deaktivieren", "DISABLE_FILE_DOWNLOAD_MESSAGE": "", - "MALICIOUS_CONTENT": "", - "COPYRIGHT": "", - "SHARED_USING": "", + "MALICIOUS_CONTENT": "Enthält schädliche Inhalte", + "COPYRIGHT": "Verletzung des Urheberrechts von jemandem, den ich repräsentieren darf", + "SHARED_USING": "Freigegeben über ", "ENTE_IO": "ente.io", "SHARING_REFERRAL_CODE": "", "LIVE": "LIVE", - "DISABLE_PASSWORD": "", - "DISABLE_PASSWORD_MESSAGE": "", + "DISABLE_PASSWORD": "Passwort-Sperre deaktivieren", + "DISABLE_PASSWORD_MESSAGE": "Sind Sie sicher, dass Sie die Passwort-Sperre deaktivieren möchten?", "PASSWORD_LOCK": "Passwort Sperre", - "LOCK": "", - "DOWNLOAD_UPLOAD_LOGS": "", + "LOCK": "Sperren", + "DOWNLOAD_UPLOAD_LOGS": "Debug-Logs", "UPLOAD_FILES": "Datei", "UPLOAD_DIRS": "Ordner", "UPLOAD_GOOGLE_TAKEOUT": "Google Takeout", @@ -469,13 +467,13 @@ "FAMILY_PLAN": "Familientarif", "DOWNLOAD_LOGS": "Logs herunterladen", "DOWNLOAD_LOGS_MESSAGE": "", - "CHANGE_FOLDER": "", - "TWO_MONTHS_FREE": "", + "CHANGE_FOLDER": "Ordner ändern", + "TWO_MONTHS_FREE": "Erhalte 2 Monate kostenlos bei Jahresabonnements", "GB": "GB", "POPULAR": "Beliebt", - "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_OPTION_LABEL": "Mit kostenloser Testversion fortfahren", "FREE_PLAN_DESCRIPTION": "1 GB für 1 Jahr", - "CURRENT_USAGE": "", + "CURRENT_USAGE": "Aktuelle Nutzung ist {{usage}}", "WEAK_DEVICE": "", "DRAG_AND_DROP_HINT": "", "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/en-US/translation.json b/web/apps/accounts/public/locales/en-US/translation.json index 6870df3194..de8d2fe2a1 100644 --- a/web/apps/accounts/public/locales/en-US/translation.json +++ b/web/apps/accounts/public/locales/en-US/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", "PASSPHRASE_MATCH_ERROR": "Passwords don't match", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "This is a browser feature intended for developers. Please don't copy-paste unverified code here.", "CREATE_COLLECTION": "New album", "ENTER_ALBUM_NAME": "Album name", "CLOSE_OPTION": "Close (Esc)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Downloading {{name}}", "DOWNLOAD_FAILED": "Download failed", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", "CHRISTMAS": "Christmas", "CHRISTMAS_EVE": "Christmas Eve", "NEW_YEAR": "New Year", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", "FREEHAND": "Freehand", "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving.", + "PASSKEYS": "Passkeys", + "DELETE_PASSKEY": "Delete passkey", + "DELETE_PASSKEY_CONFIRMATION": "Are you sure you want to delete this passkey? This action is irreversible.", + "RENAME_PASSKEY": "Rename passkey", + "ADD_PASSKEY": "Add passkey", + "ENTER_PASSKEY_NAME": "Enter passkey name", + "PASSKEYS_DESCRIPTION": "Passkeys are a modern and secure second-factor for your Ente account. They use on-device biometric authentication for convenience and security.", + "CREATED_AT": "Created at", + "PASSKEY_LOGIN_FAILED": "Passkey login failed", + "PASSKEY_LOGIN_URL_INVALID": "The login URL is invalid.", + "PASSKEY_LOGIN_ERRORED": "An error occurred while logging in with passkey.", + "TRY_AGAIN": "Try again", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "Follow the steps from your browser to continue logging in.", + "LOGIN_WITH_PASSKEY": "Login with passkey" } diff --git a/web/apps/accounts/public/locales/es-ES/translation.json b/web/apps/accounts/public/locales/es-ES/translation.json index 4adb22ee50..a29165e4ee 100644 --- a/web/apps/accounts/public/locales/es-ES/translation.json +++ b/web/apps/accounts/public/locales/es-ES/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "", "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "Las contraseñas no coinciden", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "Esta es una característica del navegador destinada a los desarrolladores. Por favor, no copie y pegue código sin verificar aquí.", "CREATE_COLLECTION": "Nuevo álbum", "ENTER_ALBUM_NAME": "Nombre del álbum", "CLOSE_OPTION": "Cerrar (Esc)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/fa-IR/translation.json b/web/apps/accounts/public/locales/fa-IR/translation.json index 3817bccd8e..2d21fcb3d3 100644 --- a/web/apps/accounts/public/locales/fa-IR/translation.json +++ b/web/apps/accounts/public/locales/fa-IR/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "", "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "", - "CONSOLE_WARNING_STOP": "", - "CONSOLE_WARNING_DESC": "", "CREATE_COLLECTION": "", "ENTER_ALBUM_NAME": "", "CLOSE_OPTION": "", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/fi-FI/translation.json b/web/apps/accounts/public/locales/fi-FI/translation.json index bc335bc777..888ed7093e 100644 --- a/web/apps/accounts/public/locales/fi-FI/translation.json +++ b/web/apps/accounts/public/locales/fi-FI/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "", "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "", - "CONSOLE_WARNING_STOP": "", - "CONSOLE_WARNING_DESC": "", "CREATE_COLLECTION": "", "ENTER_ALBUM_NAME": "", "CLOSE_OPTION": "", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/fr-FR/translation.json b/web/apps/accounts/public/locales/fr-FR/translation.json index 0d878a703f..43d9590691 100644 --- a/web/apps/accounts/public/locales/fr-FR/translation.json +++ b/web/apps/accounts/public/locales/fr-FR/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "Comment avez-vous entendu parler de Ente? (facultatif)", "REFERRAL_INFO": "Nous ne suivons pas les installations d'applications. Il serait utile que vous nous disiez comment vous nous avez trouvés !", "PASSPHRASE_MATCH_ERROR": "Les mots de passe ne correspondent pas", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "Ceci est une fonction de navigateur dédiée aux développeurs. Veuillez ne pas copier-coller un code non vérifié à cet endroit.", "CREATE_COLLECTION": "Nouvel album", "ENTER_ALBUM_NAME": "Nom de l'album", "CLOSE_OPTION": "Fermer (Échap)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Téléchargement de {{name}}", "DOWNLOAD_FAILED": "Échec du téléchargement", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} fichiers", - "CRASH_REPORTING": "Rapport de plantage", "CHRISTMAS": "Noël", "CHRISTMAS_EVE": "Réveillon de Noël", "NEW_YEAR": "Nouvel an", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "Visitez cast.ente.io sur l'appareil que vous voulez associer.", "CAST_AUTO_PAIR_FAILED": "La paire automatique de Chromecast a échoué. Veuillez réessayer.", "CACHE_DIRECTORY": "Dossier du cache", - "PASSKEYS": "Clés d'accès", "FREEHAND": "Main levée", "APPLY_CROP": "Appliquer le recadrage", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "Au moins une transformation ou un ajustement de couleur doit être effectué avant de sauvegarder." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Au moins une transformation ou un ajustement de couleur doit être effectué avant de sauvegarder.", + "PASSKEYS": "Clés d'accès", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/it-IT/translation.json b/web/apps/accounts/public/locales/it-IT/translation.json index 3d8dcb3c67..ae450e5fef 100644 --- a/web/apps/accounts/public/locales/it-IT/translation.json +++ b/web/apps/accounts/public/locales/it-IT/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "Come hai conosciuto Ente? (opzionale)", "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "Le password non corrispondono", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "Questa è una funzionalità del browser destinata agli sviluppatori. Non copiare né incollare codice non verificato qui.", "CREATE_COLLECTION": "Nuovo album", "ENTER_ALBUM_NAME": "Nome album", "CLOSE_OPTION": "Chiudi (Esc)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/ko-KR/translation.json b/web/apps/accounts/public/locales/ko-KR/translation.json index bc335bc777..4fbe6c0777 100644 --- a/web/apps/accounts/public/locales/ko-KR/translation.json +++ b/web/apps/accounts/public/locales/ko-KR/translation.json @@ -1,83 +1,81 @@ { - "HERO_SLIDE_1_TITLE": "", - "HERO_SLIDE_1": "", - "HERO_SLIDE_2_TITLE": "", - "HERO_SLIDE_2": "", - "HERO_SLIDE_3_TITLE": "", - "HERO_SLIDE_3": "", - "LOGIN": "", - "SIGN_UP": "", - "NEW_USER": "", - "EXISTING_USER": "", - "ENTER_NAME": "", - "PUBLIC_UPLOADER_NAME_MESSAGE": "", - "ENTER_EMAIL": "", - "EMAIL_ERROR": "", - "REQUIRED": "", - "EMAIL_SENT": "", - "CHECK_INBOX": "", - "ENTER_OTT": "", - "RESEND_MAIL": "", - "VERIFY": "", - "UNKNOWN_ERROR": "", - "INVALID_CODE": "", - "EXPIRED_CODE": "", - "SENDING": "", - "SENT": "", - "PASSWORD": "", - "LINK_PASSWORD": "", - "RETURN_PASSPHRASE_HINT": "", - "SET_PASSPHRASE": "", - "VERIFY_PASSPHRASE": "", - "INCORRECT_PASSPHRASE": "", - "ENTER_ENC_PASSPHRASE": "", - "PASSPHRASE_DISCLAIMER": "", - "WELCOME_TO_ENTE_HEADING": "", - "WELCOME_TO_ENTE_SUBHEADING": "", - "WHERE_YOUR_BEST_PHOTOS_LIVE": "", - "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", - "PASSPHRASE_HINT": "", - "CONFIRM_PASSPHRASE": "", - "REFERRAL_CODE_HINT": "", - "REFERRAL_INFO": "", - "PASSPHRASE_MATCH_ERROR": "", - "CONSOLE_WARNING_STOP": "", - "CONSOLE_WARNING_DESC": "", - "CREATE_COLLECTION": "", - "ENTER_ALBUM_NAME": "", - "CLOSE_OPTION": "", - "ENTER_FILE_NAME": "", - "CLOSE": "", - "NO": "", - "NOTHING_HERE": "", - "UPLOAD": "", - "IMPORT": "", - "ADD_PHOTOS": "", - "ADD_MORE_PHOTOS": "", - "add_photos_one": "", - "add_photos_other": "", - "SELECT_PHOTOS": "", - "FILE_UPLOAD": "", + "HERO_SLIDE_1_TITLE": "추억을 안전하게 백업하세요", + "HERO_SLIDE_1": "종단간 암호화가 기본지원입니다", + "HERO_SLIDE_2_TITLE": "낙진대피소에 안전하게 보관됩니다", + "HERO_SLIDE_2": "오랫동안 보존할 수 있도록한 설계", + "HERO_SLIDE_3_TITLE": "
어디에서나
이용가능
", + "HERO_SLIDE_3": "안드로이드, iOS, 웹, 데스크탑", + "LOGIN": "로그인", + "SIGN_UP": "회원가입", + "NEW_USER": "ente의 새소식", + "EXISTING_USER": "기존 사용자", + "ENTER_NAME": "이름 입력", + "PUBLIC_UPLOADER_NAME_MESSAGE": "친구들이 이 멋진 사진에 대해 고마워할 수 있도록 이름을 추가하세요!", + "ENTER_EMAIL": "이메일 주소를 입력하세요", + "EMAIL_ERROR": "올바른 이메일을 입력하세요", + "REQUIRED": "필수", + "EMAIL_SENT": "{{email}} 로 인증 코드가 전송되었습니다", + "CHECK_INBOX": "인증을 완료하기 위해 당신의 메일 수신함(그리고 스팸 수신함)을 확인하세요.", + "ENTER_OTT": "인증 코드", + "RESEND_MAIL": "코드 재전송하기", + "VERIFY": "인증", + "UNKNOWN_ERROR": "문제가 생긴 것 같아요. 다시 시도하세요", + "INVALID_CODE": "잘못된 인증 코드", + "EXPIRED_CODE": "입력한 인증 코드가 만료되었습니다", + "SENDING": "전송 중...", + "SENT": "발송 완료!", + "PASSWORD": "비밀번호", + "LINK_PASSWORD": "앨범 잠금해제를 위해 비밀번호를 입력하세요", + "RETURN_PASSPHRASE_HINT": "비밀번호", + "SET_PASSPHRASE": "비밀번호 설정", + "VERIFY_PASSPHRASE": "로그인", + "INCORRECT_PASSPHRASE": "잘못된 비밀번호입니다", + "ENTER_ENC_PASSPHRASE": "당신의 데이터를 암호화하는 데 사용할 수 있는 비밀번호를 입력하세요", + "PASSPHRASE_DISCLAIMER": "우리는 귀하의 비밀번호를 저장하지 않습니다. 만약 비밀번호를 잊어버린 경우 복구 키 없다면 데이터 복구를 도와드릴 수 없습니다.", + "WELCOME_TO_ENTE_HEADING": "환영합니다 ", + "WELCOME_TO_ENTE_SUBHEADING": "End-to-End 암호화된 사진 저장 및 공유", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "당신 최고의 사진이 있는 곳", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "암호 키 생성 중...", + "PASSPHRASE_HINT": "비밀번호", + "CONFIRM_PASSPHRASE": "비밀번호 확인", + "REFERRAL_CODE_HINT": "어떻게 Ente에 대해 들으셨나요? (선택사항)", + "REFERRAL_INFO": "우리는 앱 설치를 추적하지 않습니다. 우리를 알게 된 곳을 남겨주시면 우리에게 도움이 될꺼에요!", + "PASSPHRASE_MATCH_ERROR": "비밀번호가 일치하지 않습니다", + "CREATE_COLLECTION": "새 앨범", + "ENTER_ALBUM_NAME": "앨범 이름", + "CLOSE_OPTION": "닫기 (Esc)", + "ENTER_FILE_NAME": "파일 이름", + "CLOSE": "닫기", + "NO": "아니오", + "NOTHING_HERE": "아직 볼 수 있는 것이 없어요 👀", + "UPLOAD": "업로드", + "IMPORT": "가져오기", + "ADD_PHOTOS": "사진 추가", + "ADD_MORE_PHOTOS": "사진 더 추가하기", + "add_photos_one": "아이템 하나 추가", + "add_photos_other": "아이템 {{count, number}} 개 추가하기", + "SELECT_PHOTOS": "사진 선택하기", + "FILE_UPLOAD": "파일 업로드", "UPLOAD_STAGE_MESSAGE": { - "0": "", - "1": "", - "2": "", - "3": "", - "4": "", - "5": "" + "0": "업로드 준비중", + "1": "구글 메타데이타 파일들 읽는중", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} 파일 메타데이터가 추출되었습니다", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} 파일이 처리되었습니다", + "4": "남은 업로드 취소중", + "5": "백업 완료" }, - "FILE_NOT_UPLOADED_LIST": "", - "SUBSCRIPTION_EXPIRED": "", - "SUBSCRIPTION_EXPIRED_MESSAGE": "", - "STORAGE_QUOTA_EXCEEDED": "", - "INITIAL_LOAD_DELAY_WARNING": "", - "USER_DOES_NOT_EXIST": "", - "NO_ACCOUNT": "", - "ACCOUNT_EXISTS": "", - "CREATE": "", - "DOWNLOAD": "", - "DOWNLOAD_OPTION": "", - "DOWNLOAD_FAVORITES": "", + "FILE_NOT_UPLOADED_LIST": "아래 파일들은 업로드 되지 않았습니다", + "SUBSCRIPTION_EXPIRED": "구독 만료", + "SUBSCRIPTION_EXPIRED_MESSAGE": "당신 구독이 만료되었으니, 구독을 갱신해주세요", + "STORAGE_QUOTA_EXCEEDED": "스토리지 제한이 초과되었습니다", + "INITIAL_LOAD_DELAY_WARNING": "처음 로딩시 다소 시간이 걸릴 수 있습니다", + "USER_DOES_NOT_EXIST": "죄송합니다. 해당 이메일을 사용하는 사용자를 찾을 수 없습니다", + "NO_ACCOUNT": "계정이 없습니다", + "ACCOUNT_EXISTS": "이미 계정이 있습니다", + "CREATE": "만들기", + "DOWNLOAD": "다운로드", + "DOWNLOAD_OPTION": "다운로드 (D)", + "DOWNLOAD_FAVORITES": "즐겨찾기 다운로드", "DOWNLOAD_UNCATEGORIZED": "", "DOWNLOAD_HIDDEN_ITEMS": "", "COPY_OPTION": "", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/nl-NL/translation.json b/web/apps/accounts/public/locales/nl-NL/translation.json index df869b0dd3..15d9bfdba0 100644 --- a/web/apps/accounts/public/locales/nl-NL/translation.json +++ b/web/apps/accounts/public/locales/nl-NL/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "Hoe hoorde je over Ente? (optioneel)", "REFERRAL_INFO": "Wij gebruiken geen tracking. Het zou helpen als je ons vertelt waar je ons gevonden hebt!", "PASSPHRASE_MATCH_ERROR": "Wachtwoorden komen niet overeen", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "Dit is een browserfunctie bedoeld voor ontwikkelaars. Gelieve hier geen niet-geverifieerde code te kopiëren/plakken.", "CREATE_COLLECTION": "Nieuw album", "ENTER_ALBUM_NAME": "Album naam", "CLOSE_OPTION": "Sluiten (Esc)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "{{name}} downloaden", "DOWNLOAD_FAILED": "Download mislukt", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} bestanden", - "CRASH_REPORTING": "Foutenrapportering", "CHRISTMAS": "Kerst", "CHRISTMAS_EVE": "Kerstavond", "NEW_YEAR": "Nieuwjaar", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "Cache map", - "PASSKEYS": "", "FREEHAND": "Losse hand", "APPLY_CROP": "Bijsnijden toepassen", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "Tenminste één transformatie of kleuraanpassing moet worden uitgevoerd voordat u opslaat." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Tenminste één transformatie of kleuraanpassing moet worden uitgevoerd voordat u opslaat.", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/pt-BR/translation.json b/web/apps/accounts/public/locales/pt-BR/translation.json index 5145a24aab..0da001742f 100644 --- a/web/apps/accounts/public/locales/pt-BR/translation.json +++ b/web/apps/accounts/public/locales/pt-BR/translation.json @@ -8,7 +8,7 @@ "LOGIN": "Entrar", "SIGN_UP": "Registrar", "NEW_USER": "Novo no ente", - "EXISTING_USER": "Utilizador existente", + "EXISTING_USER": "Usuário existente", "ENTER_NAME": "Insira o nome", "PUBLIC_UPLOADER_NAME_MESSAGE": "Adicione um nome para que os seus amigos saibam a quem agradecer por estas ótimas fotos!", "ENTER_EMAIL": "Insira o endereço de e-mail", @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "Como você ouviu sobre o Ente? (opcional)", "REFERRAL_INFO": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!", "PASSPHRASE_MATCH_ERROR": "As senhas não coincidem", - "CONSOLE_WARNING_STOP": "PARAR!", - "CONSOLE_WARNING_DESC": "Este é um recurso de navegador destinado a desenvolvedores. Por favor, não copie e cole o código não confirmado aqui.", "CREATE_COLLECTION": "Novo álbum", "ENTER_ALBUM_NAME": "Nome do álbum", "CLOSE_OPTION": "Fechar (Esc)", @@ -229,7 +227,7 @@ "INDEXING_SCHEDULED": "Indexação está programada...", "ANALYZING_PHOTOS": "Indexando fotos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", "INDEXING_PEOPLE": "Indexando pessoas em {{indexStatus.nSyncedFiles,number}} fotos...", - "INDEXING_DONE": "", + "INDEXING_DONE": "Foram indexadas {{indexStatus.nSyncedFiles,number}} fotos", "UNIDENTIFIED_FACES": "rostos não identificados", "OBJECTS": "objetos", "TEXT": "texto", @@ -349,15 +347,15 @@ "REPLACE_THUMBNAIL_NOOP": "Você não tem nenhuma miniatura que possa ser compactadas mais", "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Não foi possível compactar algumas das suas miniaturas, por favor tente novamente", "FIX_CREATION_TIME": "Corrigir hora", - "FIX_CREATION_TIME_IN_PROGRESS": "", - "CREATION_TIME_UPDATED": "", + "FIX_CREATION_TIME_IN_PROGRESS": "Corrigindo horário", + "CREATION_TIME_UPDATED": "Hora do arquivo atualizado", "UPDATE_CREATION_TIME_NOT_STARTED": "Selecione a carteira que você deseja usar", "UPDATE_CREATION_TIME_COMPLETED": "Todos os arquivos atualizados com sucesso", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "A atualização do horário falhou para alguns arquivos, por favor, tente novamente", "CAPTION_CHARACTER_LIMIT": "5000 caracteres no máximo", - "DATE_TIME_ORIGINAL": "", - "DATE_TIME_DIGITIZED": "", - "METADATA_DATE": "", + "DATE_TIME_ORIGINAL": "Data e Hora Original", + "DATE_TIME_DIGITIZED": "Data e Hora Digitalizada", + "METADATA_DATE": "Data de Metadados", "CUSTOM_TIME": "Tempo personalizado", "REOPEN_PLAN_SELECTOR_MODAL": "Reabrir planos", "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Falha ao abrir planos", @@ -410,7 +408,7 @@ "SHARED_USING": "Compartilhar usando ", "ENTE_IO": "ente.io", "SHARING_REFERRAL_CODE": "Use o código {{referralCode}} para obter 10 GB de graça", - "LIVE": "", + "LIVE": "AO VIVO", "DISABLE_PASSWORD": "Desativar bloqueio por senha", "DISABLE_PASSWORD_MESSAGE": "Tem certeza que deseja desativar o bloqueio por senha?", "PASSWORD_LOCK": "Bloqueio de senha", @@ -508,8 +506,8 @@ "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente irá parar de processar geometria facial.

Você pode reativar o reconhecimento facial novamente, se desejar, então esta operação está segura.

", "ADVANCED": "Avançado", "FACE_SEARCH_CONFIRMATION": "Eu entendo, e desejo permitir que o ente processe a geometria do rosto", - "LABS": "", - "YOURS": "", + "LABS": "Laboratórios", + "YOURS": "seu", "PASSPHRASE_STRENGTH_WEAK": "Força da senha: fraca", "PASSPHRASE_STRENGTH_MODERATE": "Força da senha: moderada", "PASSPHRASE_STRENGTH_STRONG": "Força da senha: forte", @@ -572,7 +570,7 @@ "FEEDBACK_REQUIRED": "Por favor, ajude-nos com esta informação", "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "O que o outro serviço faz melhor?", "RECOVER_TWO_FACTOR": "Recuperar dois fatores", - "at": "", + "at": "em", "AUTH_NEXT": "próximo", "AUTH_DOWNLOAD_MOBILE_APP": "Baixe nosso aplicativo móvel para gerenciar seus segredos", "HIDDEN": "Escondido", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Transferindo {{name}}", "DOWNLOAD_FAILED": "Falha ao baixar", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} arquivos", - "CRASH_REPORTING": "Relatório de falhas", "CHRISTMAS": "Natal", "CHRISTMAS_EVE": "Véspera de Natal", "NEW_YEAR": "Ano Novo", @@ -607,7 +604,7 @@ "BLUR": "Desfoque", "INVERT_COLORS": "Inverter Cores", "ASPECT_RATIO": "Proporção da imagem", - "SQUARE": "", + "SQUARE": "Quadrado", "ROTATE_LEFT": "Girar para a Esquerda", "ROTATE_RIGHT": "Girar para a Direita", "FLIP_VERTICALLY": "Inverter verticalmente", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "Acesse cast.ente.io no dispositivo que você deseja parear.", "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair falhou. Por favor, tente novamente.", "CACHE_DIRECTORY": "Pasta de Cache", - "PASSKEYS": "", - "FREEHAND": "", + "FREEHAND": "Mão livre", "APPLY_CROP": "Aplicar Recorte", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "Pelo menos uma transformação ou ajuste de cor deve ser feito antes de salvar." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Pelo menos uma transformação ou ajuste de cor deve ser feito antes de salvar.", + "PASSKEYS": "Chaves de acesso", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/pt-PT/translation.json b/web/apps/accounts/public/locales/pt-PT/translation.json index fb33bb972f..2309803267 100644 --- a/web/apps/accounts/public/locales/pt-PT/translation.json +++ b/web/apps/accounts/public/locales/pt-PT/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "", "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "", - "CONSOLE_WARNING_STOP": "PARAR!", - "CONSOLE_WARNING_DESC": "", "CREATE_COLLECTION": "Novo álbum", "ENTER_ALBUM_NAME": "Nome do álbum", "CLOSE_OPTION": "Fechar (Esc)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/ru-RU/translation.json b/web/apps/accounts/public/locales/ru-RU/translation.json index d551758ade..c85db22361 100644 --- a/web/apps/accounts/public/locales/ru-RU/translation.json +++ b/web/apps/accounts/public/locales/ru-RU/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "Как вы узнали о Ente? (необязательно)", "REFERRAL_INFO": "Будет полезно, если вы укажете, где нашли нас, так как мы не отслеживаем установки приложения!", "PASSPHRASE_MATCH_ERROR": "Пароли не совпадают", - "CONSOLE_WARNING_STOP": "Остановись!", - "CONSOLE_WARNING_DESC": "Это функция браузера, предназначенная для разработчиков. Пожалуйста, не копируйте и не вставляйте сюда непроверенный код.", "CREATE_COLLECTION": "Новый альбом", "ENTER_ALBUM_NAME": "Название альбома", "CLOSE_OPTION": "Закрыть (Esc)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Загрузка {{name}}", "DOWNLOAD_FAILED": "Загрузка не удалась", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} файлов", - "CRASH_REPORTING": "Отчеты об ошибках", "CHRISTMAS": "Рождество", "CHRISTMAS_EVE": "Канун Рождества", "NEW_YEAR": "Новый год", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/sv-SE/translation.json b/web/apps/accounts/public/locales/sv-SE/translation.json index bc335bc777..f88535795a 100644 --- a/web/apps/accounts/public/locales/sv-SE/translation.json +++ b/web/apps/accounts/public/locales/sv-SE/translation.json @@ -9,9 +9,9 @@ "SIGN_UP": "", "NEW_USER": "", "EXISTING_USER": "", - "ENTER_NAME": "", + "ENTER_NAME": "Ange namn", "PUBLIC_UPLOADER_NAME_MESSAGE": "", - "ENTER_EMAIL": "", + "ENTER_EMAIL": "Ange e-postadress", "EMAIL_ERROR": "", "REQUIRED": "", "EMAIL_SENT": "", @@ -24,31 +24,29 @@ "EXPIRED_CODE": "", "SENDING": "", "SENT": "", - "PASSWORD": "", + "PASSWORD": "Lösenord", "LINK_PASSWORD": "", - "RETURN_PASSPHRASE_HINT": "", + "RETURN_PASSPHRASE_HINT": "Lösenord", "SET_PASSPHRASE": "", - "VERIFY_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "Logga in", "INCORRECT_PASSPHRASE": "", "ENTER_ENC_PASSPHRASE": "", "PASSPHRASE_DISCLAIMER": "", - "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_HEADING": "Välkommen till ", "WELCOME_TO_ENTE_SUBHEADING": "", "WHERE_YOUR_BEST_PHOTOS_LIVE": "", "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", - "PASSPHRASE_HINT": "", - "CONFIRM_PASSPHRASE": "", + "PASSPHRASE_HINT": "Lösenord", + "CONFIRM_PASSPHRASE": "Bekräfta lösenord", "REFERRAL_CODE_HINT": "", "REFERRAL_INFO": "", - "PASSPHRASE_MATCH_ERROR": "", - "CONSOLE_WARNING_STOP": "", - "CONSOLE_WARNING_DESC": "", + "PASSPHRASE_MATCH_ERROR": "Lösenorden matchar inte", "CREATE_COLLECTION": "", "ENTER_ALBUM_NAME": "", "CLOSE_OPTION": "", - "ENTER_FILE_NAME": "", - "CLOSE": "", - "NO": "", + "ENTER_FILE_NAME": "Filnamn", + "CLOSE": "Stäng", + "NO": "Nej", "NOTHING_HERE": "", "UPLOAD": "", "IMPORT": "", @@ -96,31 +94,31 @@ "TRASH_FILE_TITLE": "", "DELETE_FILES_TITLE": "", "DELETE_FILES_MESSAGE": "", - "DELETE": "", + "DELETE": "Radera", "DELETE_OPTION": "", "FAVORITE_OPTION": "", "UNFAVORITE_OPTION": "", "MULTI_FOLDER_UPLOAD": "", "UPLOAD_STRATEGY_CHOICE": "", "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", - "OR": "", + "OR": "eller", "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", "SESSION_EXPIRED_MESSAGE": "", "SESSION_EXPIRED": "", "PASSWORD_GENERATION_FAILED": "", - "CHANGE_PASSWORD": "", + "CHANGE_PASSWORD": "Ändra lösenord", "GO_BACK": "", - "RECOVERY_KEY": "", + "RECOVERY_KEY": "Återställningsnyckel", "SAVE_LATER": "", - "SAVE": "", + "SAVE": "Spara nyckel", "RECOVERY_KEY_DESCRIPTION": "", "RECOVER_KEY_GENERATION_FAILED": "", "KEY_NOT_STORED_DISCLAIMER": "", - "FORGOT_PASSWORD": "", + "FORGOT_PASSWORD": "Glömt lösenord", "RECOVER_ACCOUNT": "", "RECOVERY_KEY_HINT": "", "RECOVER": "", - "NO_RECOVERY_KEY": "", + "NO_RECOVERY_KEY": "Ingen återställningsnyckel?", "INCORRECT_RECOVERY_KEY": "", "SORRY": "", "NO_RECOVERY_KEY_MESSAGE": "", @@ -128,30 +126,30 @@ "CONTACT_SUPPORT": "", "REQUEST_FEATURE": "", "SUPPORT": "", - "CONFIRM": "", - "CANCEL": "", - "LOGOUT": "", - "DELETE_ACCOUNT": "", + "CONFIRM": "Bekräfta", + "CANCEL": "Avbryt", + "LOGOUT": "Logga ut", + "DELETE_ACCOUNT": "Radera konto", "DELETE_ACCOUNT_MESSAGE": "", "LOGOUT_MESSAGE": "", "CHANGE_EMAIL": "", "OK": "", "SUCCESS": "", "ERROR": "", - "MESSAGE": "", + "MESSAGE": "Meddelande", "INSTALL_MOBILE_APP": "", "DOWNLOAD_APP_MESSAGE": "", "DOWNLOAD_APP": "", "EXPORT": "", "SUBSCRIPTION": "", - "SUBSCRIBE": "", - "MANAGEMENT_PORTAL": "", + "SUBSCRIBE": "Prenumerera", + "MANAGEMENT_PORTAL": "Hantera betalningsmetod", "MANAGE_FAMILY_PORTAL": "", "LEAVE_FAMILY_PLAN": "", "LEAVE": "", "LEAVE_FAMILY_CONFIRM": "", "CHOOSE_PLAN": "", - "MANAGE_PLAN": "", + "MANAGE_PLAN": "Hantera din prenumeration", "ACTIVE": "", "OFFLINE_MSG": "", "FREE_SUBSCRIPTION_INFO": "", @@ -203,18 +201,18 @@ "DOWNLOAD_COLLECTION": "", "DOWNLOAD_COLLECTION_MESSAGE": "", "CREATE_ALBUM_FAILED": "", - "SEARCH": "", - "SEARCH_RESULTS": "", - "NO_RESULTS": "", + "SEARCH": "Sök", + "SEARCH_RESULTS": "Sökresultat", + "NO_RESULTS": "Inga resultat hittades", "SEARCH_HINT": "", "SEARCH_TYPE": { "COLLECTION": "", "LOCATION": "", "CITY": "", - "DATE": "", + "DATE": "Datum", "FILE_NAME": "", "THING": "", - "FILE_CAPTION": "", + "FILE_CAPTION": "Beskrivning", "FILE_TYPE": "", "CLIP": "" }, @@ -369,11 +367,11 @@ "shared_with_people_zero": "", "shared_with_people_one": "", "shared_with_people_other": "", - "participants_zero": "", - "participants_one": "", + "participants_zero": "Inga deltagare", + "participants_one": "1 deltagare", "participants_other": "", "ADD_VIEWERS": "", - "PARTICIPANTS": "", + "PARTICIPANTS": "Deltagare", "CHANGE_PERMISSIONS_TO_VIEWER": "", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", "CONVERT_TO_VIEWER": "", @@ -416,14 +414,14 @@ "PASSWORD_LOCK": "", "LOCK": "", "DOWNLOAD_UPLOAD_LOGS": "", - "UPLOAD_FILES": "", - "UPLOAD_DIRS": "", + "UPLOAD_FILES": "Fil", + "UPLOAD_DIRS": "Mapp", "UPLOAD_GOOGLE_TAKEOUT": "", "DEDUPLICATE_FILES": "", "AUTHENTICATOR_SECTION": "", "NO_DUPLICATES_FOUND": "", "CLUB_BY_CAPTURE_TIME": "", - "FILES": "", + "FILES": "Filer", "EACH": "", "DEDUPLICATE_BASED_ON_SIZE": "", "STOP_ALL_UPLOADS_MESSAGE": "", @@ -432,8 +430,8 @@ "STOP_DOWNLOADS_HEADER": "", "YES_STOP_DOWNLOADS": "", "STOP_ALL_DOWNLOADS_MESSAGE": "", - "albums_one": "", - "albums_other": "", + "albums_one": "1 album", + "albums_other": "{{count, number}} album", "ALL_ALBUMS": "", "ALBUMS": "", "ALL_HIDDEN_ALBUMS": "", @@ -459,19 +457,19 @@ "FOLDERS_AUTOMATICALLY_MONITORED": "", "UPLOAD_NEW_FILES_TO_ENTE": "", "REMOVE_DELETED_FILES_FROM_ENTE": "", - "ADD_FOLDER": "", + "ADD_FOLDER": "Lägg till mapp", "STOP_WATCHING": "", "STOP_WATCHING_FOLDER": "", "STOP_WATCHING_DIALOG_MESSAGE": "", "YES_STOP": "", - "MONTH_SHORT": "", - "YEAR": "", + "MONTH_SHORT": "mån", + "YEAR": "år", "FAMILY_PLAN": "", "DOWNLOAD_LOGS": "", "DOWNLOAD_LOGS_MESSAGE": "", "CHANGE_FOLDER": "", "TWO_MONTHS_FREE": "", - "GB": "", + "GB": "GB", "POPULAR": "", "FREE_PLAN_OPTION_LABEL": "", "FREE_PLAN_DESCRIPTION": "", @@ -492,7 +490,7 @@ "IGNORE_THIS_VERSION": "", "TODAY": "", "YESTERDAY": "", - "NAME_PLACEHOLDER": "", + "NAME_PLACEHOLDER": "Namn...", "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", "CHOSE_THEME": "", @@ -514,7 +512,7 @@ "PASSPHRASE_STRENGTH_MODERATE": "", "PASSPHRASE_STRENGTH_STRONG": "", "PREFERENCES": "", - "LANGUAGE": "", + "LANGUAGE": "Språk", "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", "SUBSCRIPTION_VERIFICATION_ERROR": "", @@ -532,8 +530,8 @@ "MONTH": "", "YEAR": "" }, - "COPY_LINK": "", - "DONE": "", + "COPY_LINK": "Kopiera länk", + "DONE": "Klar", "LINK_SHARE_TITLE": "", "REMOVE_LINK": "", "CREATE_PUBLIC_SHARING": "", @@ -579,7 +577,7 @@ "HIDE": "", "UNHIDE": "", "UNHIDE_TO_COLLECTION": "", - "SORT_BY": "", + "SORT_BY": "Sortera efter", "NEWEST_FIRST": "", "OLDEST_FIRST": "", "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", @@ -590,12 +588,11 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", "NEW_YEAR_EVE": "", - "IMAGE": "", + "IMAGE": "Bild", "VIDEO": "", "LIVE_PHOTO": "", "CONVERT": "", @@ -616,10 +613,10 @@ "SAVE_A_COPY_TO_ENTE": "", "RESTORE_ORIGINAL": "", "TRANSFORM": "", - "COLORS": "", + "COLORS": "Färger", "FLIP": "", "ROTATION": "", - "RESET": "", + "RESET": "Återställ", "PHOTO_EDITOR": "", "FASTER_UPLOAD": "", "FASTER_UPLOAD_DESCRIPTION": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/th-TH/translation.json b/web/apps/accounts/public/locales/th-TH/translation.json index bc335bc777..888ed7093e 100644 --- a/web/apps/accounts/public/locales/th-TH/translation.json +++ b/web/apps/accounts/public/locales/th-TH/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "", "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "", - "CONSOLE_WARNING_STOP": "", - "CONSOLE_WARNING_DESC": "", "CREATE_COLLECTION": "", "ENTER_ALBUM_NAME": "", "CLOSE_OPTION": "", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/tr-TR/translation.json b/web/apps/accounts/public/locales/tr-TR/translation.json index bc335bc777..888ed7093e 100644 --- a/web/apps/accounts/public/locales/tr-TR/translation.json +++ b/web/apps/accounts/public/locales/tr-TR/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "", "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "", - "CONSOLE_WARNING_STOP": "", - "CONSOLE_WARNING_DESC": "", "CREATE_COLLECTION": "", "ENTER_ALBUM_NAME": "", "CLOSE_OPTION": "", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "", "DOWNLOAD_FAILED": "", "DOWNLOAD_PROGRESS": "", - "CRASH_REPORTING": "", "CHRISTMAS": "", "CHRISTMAS_EVE": "", "NEW_YEAR": "", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "", "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "", - "PASSKEYS": "", "FREEHAND": "", "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/accounts/public/locales/zh-CN/translation.json b/web/apps/accounts/public/locales/zh-CN/translation.json index 15ef565ddd..0a72e1c70a 100644 --- a/web/apps/accounts/public/locales/zh-CN/translation.json +++ b/web/apps/accounts/public/locales/zh-CN/translation.json @@ -9,7 +9,7 @@ "SIGN_UP": "注册", "NEW_USER": "刚来到 ente", "EXISTING_USER": "现有用户", - "ENTER_NAME": "现有用户", + "ENTER_NAME": "输入名字", "PUBLIC_UPLOADER_NAME_MESSAGE": "请添加一个名字,以便您的朋友知晓该感谢谁拍摄了这些精美的照片!", "ENTER_EMAIL": "请输入电子邮件地址", "EMAIL_ERROR": "请输入有效的电子邮件", @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "您是如何知道Ente的? (可选的)", "REFERRAL_INFO": "我们不跟踪应用程序安装情况,如果您告诉我们您是在哪里找到我们的,将会有所帮助!", "PASSPHRASE_MATCH_ERROR": "两次输入的密码不一致", - "CONSOLE_WARNING_STOP": "停止!", - "CONSOLE_WARNING_DESC": "这是专为开发人员设计的浏览器功能。 请不要在此处复制粘贴未经验证的代码。", "CREATE_COLLECTION": "新建相册", "ENTER_ALBUM_NAME": "相册名称", "CLOSE_OPTION": "关闭 (或按Esc键)", @@ -85,9 +83,9 @@ "ZOOM_IN_OUT": "放大/缩小", "PREVIOUS": "上一个 (←)", "NEXT": "下一个 (→)", - "TITLE_PHOTOS": "ente 照片", - "TITLE_ALBUMS": "ente 照片", - "TITLE_AUTH": "ente 验证器", + "TITLE_PHOTOS": "Ente 照片", + "TITLE_ALBUMS": "Ente 照片", + "TITLE_AUTH": "Ente 验证器", "UPLOAD_FIRST_PHOTO": "上传您的第一张照片", "IMPORT_YOUR_FOLDERS": "导入您的文件夹", "UPLOAD_DROPZONE_MESSAGE": "拖放以备份您的文件", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "正在下载 {{name}}", "DOWNLOAD_FAILED": "下载失败", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} 个文件", - "CRASH_REPORTING": "崩溃报告", "CHRISTMAS": "圣诞", "CHRISTMAS_EVE": "平安夜", "NEW_YEAR": "新年", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "在您要配对的设备上访问 cast.ente.io 。", "CAST_AUTO_PAIR_FAILED": "Chromecast 自动配对失败。请再试一次。", "CACHE_DIRECTORY": "缓存文件夹", - "PASSKEYS": "通行密钥", "FREEHAND": "手画", "APPLY_CROP": "应用裁剪", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "保存之前必须至少执行一项转换或颜色调整。" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "保存之前必须至少执行一项转换或颜色调整。", + "PASSKEYS": "通行密钥", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/bg-BG/translation.json b/web/apps/auth/public/locales/bg-BG/translation.json new file mode 100644 index 0000000000..03faf16c2d --- /dev/null +++ b/web/apps/auth/public/locales/bg-BG/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Личен бекъп
на твоите спомени
", + "HERO_SLIDE_1": "Криптиран от край до край по подразбиране", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/auth/public/locales/de-DE/translation.json b/web/apps/auth/public/locales/de-DE/translation.json index b09446dc83..9a1c4073c6 100644 --- a/web/apps/auth/public/locales/de-DE/translation.json +++ b/web/apps/auth/public/locales/de-DE/translation.json @@ -31,80 +31,78 @@ "VERIFY_PASSPHRASE": "Einloggen", "INCORRECT_PASSPHRASE": "Falsches Passwort", "ENTER_ENC_PASSPHRASE": "Bitte gib ein Passwort ein, mit dem wir deine Daten verschlüsseln können", - "PASSPHRASE_DISCLAIMER": "We don't store your password, so if you forget it, we will not be able to help you recover your data without a recovery key.", + "PASSPHRASE_DISCLAIMER": "Wir speichern dein Passwort nicht. Wenn du es vergisst, können wir dir nicht helfen, deine Daten ohne einen Wiederherstellungsschlüssel wiederherzustellen.", "WELCOME_TO_ENTE_HEADING": "Willkommen bei
", - "WELCOME_TO_ENTE_SUBHEADING": "End to end encrypted photo storage and sharing", + "WELCOME_TO_ENTE_SUBHEADING": "Ende-zu-Ende verschlüsselte Fotospeicherung und Freigabe", "WHERE_YOUR_BEST_PHOTOS_LIVE": "Wo deine besten Fotos leben", "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generierung von Verschlüsselungsschlüsseln...", "PASSPHRASE_HINT": "Passwort", "CONFIRM_PASSPHRASE": "Passwort bestätigen", - "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", - "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", + "REFERRAL_CODE_HINT": "Wie hast du von Ente erfahren? (optional)", + "REFERRAL_INFO": "Wir tracken keine App-Installationen. Es würde uns jedoch helfen, wenn du uns mitteilst, wie du von uns erfahren hast!", "PASSPHRASE_MATCH_ERROR": "Die Passwörter stimmen nicht überein", - "CONSOLE_WARNING_STOP": "STOPP!", - "CONSOLE_WARNING_DESC": "This is a browser feature intended for developers. Please don't copy-paste unverified code here.", "CREATE_COLLECTION": "Neues Album", "ENTER_ALBUM_NAME": "Albumname", "CLOSE_OPTION": "Schließen (Esc)", "ENTER_FILE_NAME": "Dateiname", "CLOSE": "Schließen", "NO": "Nein", - "NOTHING_HERE": "Nothing to see here yet 👀", + "NOTHING_HERE": "Hier gibt es noch nichts zu sehen 👀", "UPLOAD": "Hochladen", "IMPORT": "Importieren", "ADD_PHOTOS": "Fotos hinzufügen", "ADD_MORE_PHOTOS": "Mehr Fotos hinzufügen", - "add_photos_one": "Add 1 item", - "add_photos_other": "Add {{count, number}} items", + "add_photos_one": "Eine Datei hinzufügen", + "add_photos_other": "{{count, number}} Dateien hinzufügen", "SELECT_PHOTOS": "Foto auswählen", "FILE_UPLOAD": "Datei hochladen", "UPLOAD_STAGE_MESSAGE": { "0": "Hochladen wird vorbereitet", - "1": "Reading google metadata files", - "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files metadata extracted", - "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files processed", - "4": "Cancelling remaining uploads", + "1": "Lese Google-Metadaten", + "2": "Metadaten von {{uploadCounter.finished, number}} / {{uploadCounter.total, number}} Dateien extrahiert", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} Dateien verarbeitet", + "4": "Verbleibende Uploads werden abgebrochen", "5": "Sicherung abgeschlossen" }, - "FILE_NOT_UPLOADED_LIST": "The following files were not uploaded", + "FILE_NOT_UPLOADED_LIST": "Die folgenden Dateien wurden nicht hochgeladen", "SUBSCRIPTION_EXPIRED": "Abonnement abgelaufen", - "SUBSCRIPTION_EXPIRED_MESSAGE": "Your subscription has expired, please renew", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Dein Abonnement ist abgelaufen, bitte erneuere es", "STORAGE_QUOTA_EXCEEDED": "Speichergrenze überschritten", - "INITIAL_LOAD_DELAY_WARNING": "First load may take some time", - "USER_DOES_NOT_EXIST": "Sorry, could not find a user with that email", - "NO_ACCOUNT": "Don't have an account", - "ACCOUNT_EXISTS": "Already have an account", + "INITIAL_LOAD_DELAY_WARNING": "Das erste Laden kann einige Zeit in Anspruch nehmen", + "USER_DOES_NOT_EXIST": "Leider konnte kein Benutzer mit dieser E-Mail gefunden werden", + "NO_ACCOUNT": "Kein Konto vorhanden", + "ACCOUNT_EXISTS": "Es ist bereits ein Account vorhanden", "CREATE": "Erstellen", "DOWNLOAD": "Herunterladen", "DOWNLOAD_OPTION": "Herunterladen (D)", "DOWNLOAD_FAVORITES": "Favoriten herunterladen", - "DOWNLOAD_UNCATEGORIZED": "Download uncategorized", - "DOWNLOAD_HIDDEN_ITEMS": "Download hidden items", + "DOWNLOAD_UNCATEGORIZED": "Download unkategorisiert", + "DOWNLOAD_HIDDEN_ITEMS": "Versteckte Dateien herunterladen", "COPY_OPTION": "Als PNG kopieren (Strg / Cmd - C)", - "TOGGLE_FULLSCREEN": "Toggle fullscreen (F)", + "TOGGLE_FULLSCREEN": "Vollbild umschalten (F)", "ZOOM_IN_OUT": "Herein-/Herauszoomen", - "PREVIOUS": "Previous (←)", - "NEXT": "Next (→)", - "TITLE_PHOTOS": "Ente Photos", - "TITLE_ALBUMS": "Ente Photos", + "PREVIOUS": "Vorherige (←)", + "NEXT": "Weitere (→)", + "TITLE_PHOTOS": "Ente Fotos", + "TITLE_ALBUMS": "Ente Fotos", "TITLE_AUTH": "Ente Auth", "UPLOAD_FIRST_PHOTO": "Lade dein erstes Foto hoch", "IMPORT_YOUR_FOLDERS": "Importiere deiner Ordner", - "UPLOAD_DROPZONE_MESSAGE": "Drop to backup your files", - "WATCH_FOLDER_DROPZONE_MESSAGE": "Drop to add watched folder", + "UPLOAD_DROPZONE_MESSAGE": "Loslassen, um Dateien zu sichern", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Loslassen, um beobachteten Ordner hinzuzufügen", "TRASH_FILES_TITLE": "Dateien löschen?", "TRASH_FILE_TITLE": "Datei löschen?", "DELETE_FILES_TITLE": "Sofort löschen?", - "DELETE_FILES_MESSAGE": "Selected files will be permanently deleted from your ente account.", + "DELETE_FILES_MESSAGE": "Ausgewählte Dateien werden dauerhaft aus Ihrem Ente-Konto gelöscht.", "DELETE": "Löschen", "DELETE_OPTION": "Löschen (DEL)", - "FAVORITE_OPTION": "Favorite (L)", - "UNFAVORITE_OPTION": "Unfavorite (L)", - "MULTI_FOLDER_UPLOAD": "Multiple folders detected", - "UPLOAD_STRATEGY_CHOICE": "Would you like to upload them into", + "FAVORITE_OPTION": "Zu Favoriten hinzufügen (L)", + "UNFAVORITE_OPTION": "Von Favoriten entfernen (L)", + "MULTI_FOLDER_UPLOAD": "Mehrere Ordner erkannt", + "UPLOAD_STRATEGY_CHOICE": "Möchtest du sie hochladen in", "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Ein einzelnes Album", "OR": "oder", - "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Separate albums", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Getrennte Alben", "SESSION_EXPIRED_MESSAGE": "Ihre Sitzung ist abgelaufen. Bitte loggen Sie sich erneut ein, um fortzufahren", "SESSION_EXPIRED": "Sitzung abgelaufen", "PASSWORD_GENERATION_FAILED": "Dein Browser konnte keinen starken Schlüssel generieren, der den Verschlüsselungsstandards des Entes entspricht, bitte versuche die mobile App oder einen anderen Browser zu verwenden", @@ -113,9 +111,9 @@ "RECOVERY_KEY": "Wiederherstellungsschlüssel", "SAVE_LATER": "Auf später verschieben", "SAVE": "Schlüssel speichern", - "RECOVERY_KEY_DESCRIPTION": "If you forget your password, the only way you can recover your data is with this key.", - "RECOVER_KEY_GENERATION_FAILED": "Recovery code could not be generated, please try again", - "KEY_NOT_STORED_DISCLAIMER": "We don't store this key, so please save this in a safe place", + "RECOVERY_KEY_DESCRIPTION": "Falls du dein Passwort vergisst, kannst du deine Daten nur mit diesem Schlüssel wiederherstellen.", + "RECOVER_KEY_GENERATION_FAILED": "Wiederherstellungsschlüssel konnte nicht generiert werden, bitte versuche es erneut", + "KEY_NOT_STORED_DISCLAIMER": "Wir speichern diesen Schlüssel nicht, also speichere ihn bitte an einem sicheren Ort", "FORGOT_PASSWORD": "Passwort vergessen", "RECOVER_ACCOUNT": "Konto wiederherstellen", "RECOVERY_KEY_HINT": "Wiederherstellungsschlüssel", @@ -132,15 +130,15 @@ "CANCEL": "Abbrechen", "LOGOUT": "Ausloggen", "DELETE_ACCOUNT": "Konto löschen", - "DELETE_ACCOUNT_MESSAGE": "

Please send an email to {{emailID}} from your registered email address.

Your request will be processed within 72 hours.

", + "DELETE_ACCOUNT_MESSAGE": "

Bitte sende eine E-Mail an {{emailID}} mit deiner registrierten E-Mail-Adresse.

Deine Anfrage wird innerhalb von 72 Stunden bearbeitet.

", "LOGOUT_MESSAGE": "Sind sie sicher, dass sie sich ausloggen möchten?", "CHANGE_EMAIL": "E-Mail-Adresse ändern", "OK": "OK", "SUCCESS": "Erfolgreich", "ERROR": "Fehler", "MESSAGE": "Nachricht", - "INSTALL_MOBILE_APP": "Install our Android or iOS app to automatically backup all your photos", - "DOWNLOAD_APP_MESSAGE": "Sorry, this operation is currently only supported on our desktop app", + "INSTALL_MOBILE_APP": "Installiere unsere Android oder iOS App, um automatisch alle deine Fotos zu sichern", + "DOWNLOAD_APP_MESSAGE": "Entschuldigung, dieser Vorgang wird derzeit nur von unserer Desktop-App unterstützt", "DOWNLOAD_APP": "Desktopanwendung herunterladen", "EXPORT": "Daten exportieren", "SUBSCRIPTION": "Abonnement", @@ -154,37 +152,37 @@ "MANAGE_PLAN": "Verwalte dein Abonnement", "ACTIVE": "Aktiv", "OFFLINE_MSG": "Du bist offline, gecachte Erinnerungen werden angezeigt", - "FREE_SUBSCRIPTION_INFO": "You are on the free plan that expires on {{date, dateTime}}", + "FREE_SUBSCRIPTION_INFO": "Du bist auf dem kostenlosen Plan, der am {{date, dateTime}} ausläuft", "FAMILY_SUBSCRIPTION_INFO": "Sie haben einen Familienplan verwaltet von", "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Erneuert am {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Endet am {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Ihr Abo endet am {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "Dein {{storage, string}} Add-on ist gültig bis {{date, dateTime}}", "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Sie haben Ihr Speichervolumen überschritten, bitte upgraden Sie", - "SUBSCRIPTION_PURCHASE_SUCCESS": "

We've received your payment

Your subscription is valid till {{date, dateTime}}

", - "SUBSCRIPTION_PURCHASE_CANCELLED": "Your purchase was canceled, please try again if you want to subscribe", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

Wir haben deine Zahlung erhalten

Dein Abonnement ist gültig bis {{date, dateTime}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "Dein Kauf wurde abgebrochen. Bitte versuche es erneut, wenn du abonnieren willst", "SUBSCRIPTION_PURCHASE_FAILED": "Kauf des Abonnements fehlgeschlagen Bitte versuchen Sie es erneut", "SUBSCRIPTION_UPDATE_FAILED": "Aktualisierung des Abonnements fehlgeschlagen Bitte versuchen Sie es erneut", - "UPDATE_PAYMENT_METHOD_MESSAGE": "We are sorry, payment failed when we tried to charge your card, please update your payment method and try again", - "STRIPE_AUTHENTICATION_FAILED": "We are unable to authenticate your payment method. please choose a different payment method and try again", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Es tut uns leid, die Zahlung ist fehlgeschlagen, als wir versuchten Ihre Karte zu belasten. Bitte aktualisieren Sie Ihre Zahlungsmethode und versuchen Sie es erneut", + "STRIPE_AUTHENTICATION_FAILED": "Wir können deine Zahlungsmethode nicht authentifizieren. Bitte wähle eine andere Zahlungsmethode und versuche es erneut", "UPDATE_PAYMENT_METHOD": "Zahlungsmethode aktualisieren", "MONTHLY": "Monatlich", "YEARLY": "Jährlich", "UPDATE_SUBSCRIPTION_MESSAGE": "Sind Sie sicher, dass Sie Ihren Tarif ändern möchten?", "UPDATE_SUBSCRIPTION": "Plan ändern", "CANCEL_SUBSCRIPTION": "Abonnement kündigen", - "CANCEL_SUBSCRIPTION_MESSAGE": "

All of your data will be deleted from our servers at the end of this billing period.

Are you sure that you want to cancel your subscription?

", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

", - "SUBSCRIPTION_CANCEL_FAILED": "Failed to cancel subscription", - "SUBSCRIPTION_CANCEL_SUCCESS": "Subscription canceled successfully", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Alle deine Daten werden am Ende dieses Abrechnungszeitraums von unseren Servern gelöscht.

Bist du sicher, dass du dein Abonnement kündigen möchtest?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Bist du sicher, dass du dein Abonnement beenden möchtest?

", + "SUBSCRIPTION_CANCEL_FAILED": "Abonnement konnte nicht storniert werden", + "SUBSCRIPTION_CANCEL_SUCCESS": "Abonnement erfolgreich beendet", "REACTIVATE_SUBSCRIPTION": "Abonnement reaktivieren", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "Once reactivated, you will be billed on {{date, dateTime}}", - "SUBSCRIPTION_ACTIVATE_SUCCESS": "Subscription activated successfully ", - "SUBSCRIPTION_ACTIVATE_FAILED": "Failed to reactivate subscription renewals", - "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Thank you", - "CANCEL_SUBSCRIPTION_ON_MOBILE": "Cancel mobile subscription", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Please cancel your subscription from the mobile app to activate a subscription here", - "MAIL_TO_MANAGE_SUBSCRIPTION": "Please contact us at {{emailID}} to manage your subscription", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Nach der Reaktivierung wird am {{date, dateTime}} abgerechnet", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Abonnement erfolgreich aktiviert ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Reaktivierung der Abonnementverlängerung fehlgeschlagen", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Vielen Dank", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Mobiles Abonnement kündigen", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Bitte kündige dein Abonnement in der mobilen App, um hier ein Abonnement zu aktivieren", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Bitte kontaktiere uns über {{emailID}}, um dein Abo zu verwalten", "RENAME": "Umbenennen", "RENAME_FILE": "Datei umbenennen", "RENAME_COLLECTION": "Album umbenennen", @@ -198,41 +196,41 @@ "SHAREES": "Geteilt mit", "SHARE_WITH_SELF": "Du kannst nicht mit dir selbst teilen", "ALREADY_SHARED": "Hoppla, Sie teilen dies bereits mit {{email}}", - "SHARING_BAD_REQUEST_ERROR": "Sharing album not allowed", - "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Sharing is disabled for free accounts", + "SHARING_BAD_REQUEST_ERROR": "Albumfreigabe nicht erlaubt", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Freigabe ist für kostenlose Konten deaktiviert", "DOWNLOAD_COLLECTION": "Album herunterladen", - "DOWNLOAD_COLLECTION_MESSAGE": "

Are you sure you want to download the complete album?

All files will be queued for download sequentially

", - "CREATE_ALBUM_FAILED": "Failed to create album , please try again", + "DOWNLOAD_COLLECTION_MESSAGE": "

Bist du sicher, dass du das komplette Album herunterladen möchtest?

Alle Dateien werden der Warteschlange zum sequenziellen Download hinzugefügt

", + "CREATE_ALBUM_FAILED": "Fehler beim Erstellen des Albums, bitte versuche es erneut", "SEARCH": "Suchen", "SEARCH_RESULTS": "Ergebnisse durchsuchen", - "NO_RESULTS": "No results found", - "SEARCH_HINT": "Search for albums, dates, descriptions, ...", + "NO_RESULTS": "Keine Ergebnisse gefunden", + "SEARCH_HINT": "Suche nach Alben, Datum, Beschreibungen, ...", "SEARCH_TYPE": { "COLLECTION": "Album", "LOCATION": "Standort", - "CITY": "Location", + "CITY": "Ort", "DATE": "Datum", "FILE_NAME": "Dateiname", "THING": "Inhalt", "FILE_CAPTION": "Beschreibung", - "FILE_TYPE": "File type", - "CLIP": "Magic" + "FILE_TYPE": "Dateityp", + "CLIP": "Magie" }, "photos_count_zero": "Keine Erinnerungen", - "photos_count_one": "1 memory", - "photos_count_other": "{{count, number}} memories", - "TERMS_AND_CONDITIONS": "I agree to the terms and privacy policy", + "photos_count_one": "Eine Erinnerung", + "photos_count_other": "{{count, number}} Erinnerungen", + "TERMS_AND_CONDITIONS": "Ich stimme den Bedingungen und Datenschutzrichtlinien zu", "ADD_TO_COLLECTION": "Zum Album hinzufügen", - "SELECTED": "selected", - "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "This video cannot be played on your browser", + "SELECTED": "ausgewählt", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Dieses Video kann in deinem Browser nicht abgespielt werden", "PEOPLE": "Personen", - "INDEXING_SCHEDULED": "Indexing is scheduled...", - "ANALYZING_PHOTOS": "Indexing photos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", - "INDEXING_PEOPLE": "Indexing people in {{indexStatus.nSyncedFiles,number}} photos...", - "INDEXING_DONE": "Indexed {{indexStatus.nSyncedFiles,number}} photos", - "UNIDENTIFIED_FACES": "unidentified faces", - "OBJECTS": "objects", - "TEXT": "text", + "INDEXING_SCHEDULED": "Indizierung ist geplant...", + "ANALYZING_PHOTOS": "Indiziere Fotos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", + "INDEXING_PEOPLE": "Indiziere Personen in {{indexStatus.nSyncedFiles,number}} Fotos...", + "INDEXING_DONE": "{{indexStatus.nSyncedFiles,number}} Fotos wurden indiziert", + "UNIDENTIFIED_FACES": "unidentifizierte Gesichter", + "OBJECTS": "Objekte", + "TEXT": "Text", "INFO": "Info ", "INFO_OPTION": "Info (I)", "FILE_NAME": "Dateiname", @@ -244,8 +242,8 @@ "ENABLE_MAPS": "Karten aktivieren?", "ENABLE_MAP": "Karte aktivieren", "DISABLE_MAPS": "Karten deaktivieren?", - "ENABLE_MAP_DESCRIPTION": "

This will show your photos on a world map.

The map is hosted by OpenStreetMap, and the exact locations of your photos are never shared.

You can disable this feature anytime from Settings.

", - "DISABLE_MAP_DESCRIPTION": "

This will disable the display of your photos on a world map.

You can enable this feature anytime from Settings.

", + "ENABLE_MAP_DESCRIPTION": "

Dies wird deine Fotos auf einer Weltkarte anzeigen.

Die Karte wird von OpenStreetMap gehostet und die genauen Standorte deiner Fotos werden niemals geteilt.

Diese Funktion kannst du jederzeit in den Einstellungen deaktivieren.

", + "DISABLE_MAP_DESCRIPTION": "

Dies wird die Anzeige deiner Fotos auf einer Weltkarte deaktivieren.

Du kannst diese Funktion jederzeit in den Einstellungen aktivieren.

", "DISABLE_MAP": "Karte deaktivieren", "DETAILS": "Details", "VIEW_EXIF": "Alle EXIF-Daten anzeigen", @@ -254,67 +252,67 @@ "ISO": "ISO", "TWO_FACTOR": "Zwei-Faktor", "TWO_FACTOR_AUTHENTICATION": "Zwei-Faktor-Authentifizierung", - "TWO_FACTOR_QR_INSTRUCTION": "Scan the QR code below with your favorite authenticator app", + "TWO_FACTOR_QR_INSTRUCTION": "Scanne den QR-Code unten mit deiner bevorzugten Authentifizierungs-App", "ENTER_CODE_MANUALLY": "Geben Sie den Code manuell ein", - "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Please enter this code in your favorite authenticator app", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Bitte gib diesen Code in deiner bevorzugten Authentifizierungs-App ein", "SCAN_QR_CODE": "QR‐Code stattdessen scannen", "ENABLE_TWO_FACTOR": "Zwei-Faktor-Authentifizierung aktivieren", "ENABLE": "Aktivieren", - "LOST_DEVICE": "Lost two-factor device", + "LOST_DEVICE": "Zwei-Faktor-Gerät verloren", "INCORRECT_CODE": "Falscher Code", - "TWO_FACTOR_INFO": "Add an additional layer of security by requiring more than your email and password to log in to your account", + "TWO_FACTOR_INFO": "Fügen Sie eine zusätzliche Sicherheitsebene hinzu, indem Sie mehr als Ihre E-Mail und Ihr Passwort benötigen, um sich mit Ihrem Account anzumelden", "DISABLE_TWO_FACTOR_LABEL": "Deaktiviere die Zwei-Faktor-Authentifizierung", - "UPDATE_TWO_FACTOR_LABEL": "Update your authenticator device", + "UPDATE_TWO_FACTOR_LABEL": "Authentifizierungsgerät aktualisieren", "DISABLE": "Deaktivieren", "RECONFIGURE": "Neu einrichten", - "UPDATE_TWO_FACTOR": "Update two-factor", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuing forward will void any previously configured authenticators", - "UPDATE": "Update", - "DISABLE_TWO_FACTOR": "Disable two-factor", - "DISABLE_TWO_FACTOR_MESSAGE": "Are you sure you want to disable your two-factor authentication", - "TWO_FACTOR_DISABLE_FAILED": "Failed to disable two factor, please try again", + "UPDATE_TWO_FACTOR": "Zweiten Faktor aktualisieren", + "UPDATE_TWO_FACTOR_MESSAGE": "Fahren Sie fort, werden alle Ihre zuvor konfigurierten Authentifikatoren ungültig", + "UPDATE": "Aktualisierung", + "DISABLE_TWO_FACTOR": "Zweiten Faktor deaktivieren", + "DISABLE_TWO_FACTOR_MESSAGE": "Bist du sicher, dass du die Zwei-Faktor-Authentifizierung deaktivieren willst", + "TWO_FACTOR_DISABLE_FAILED": "Fehler beim Deaktivieren des zweiten Faktors, bitte versuchen Sie es erneut", "EXPORT_DATA": "Daten exportieren", "SELECT_FOLDER": "Ordner auswählen", "DESTINATION": "Zielort", "START": "Start", - "LAST_EXPORT_TIME": "Last export time", - "EXPORT_AGAIN": "Resync", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "Local storage not accessible", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Your browser or an addon is blocking ente from saving data into local storage. please try loading this page after switching your browsing mode.", + "LAST_EXPORT_TIME": "Letztes Exportdatum", + "EXPORT_AGAIN": "Neusynchronisation", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Lokaler Speicher nicht zugänglich", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Ihr Browser oder ein Addon blockiert ente vor der Speicherung von Daten im lokalen Speicher. Bitte versuchen Sie, den Browser-Modus zu wechseln und die Seite neu zu laden.", "SEND_OTT": "OTP senden", "EMAIl_ALREADY_OWNED": "Diese E-Mail wird bereits verwendet", - "ETAGS_BLOCKED": "

We were unable to upload the following files because of your browser configuration.

Please disable any addons that might be preventing ente from using eTags to upload large files, or use our desktop app for a more reliable import experience.

", - "SKIPPED_VIDEOS_INFO": "

Presently we do not support adding videos via public links.

To share videos, please signup for ente and share with the intended recipients using their email.

", - "LIVE_PHOTOS_DETECTED": "The photo and video files from your Live Photos have been merged into a single file", - "RETRY_FAILED": "Retry failed uploads", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "Fehlgeschlagene Uploads erneut probieren", "FAILED_UPLOADS": "Fehlgeschlagene Uploads ", "SKIPPED_FILES": "Ignorierte Uploads", "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Das Vorschaubild konnte nicht erzeugt werden", "UNSUPPORTED_FILES": "Nicht unterstützte Dateien", - "SUCCESSFUL_UPLOADS": "Successful uploads", - "SKIPPED_INFO": "Skipped these as there are files with matching names in the same album", + "SUCCESSFUL_UPLOADS": "Erfolgreiche Uploads", + "SKIPPED_INFO": "", "UNSUPPORTED_INFO": "ente unterstützt diese Dateiformate noch nicht", "BLOCKED_UPLOADS": "Blockierte Uploads", "SKIPPED_VIDEOS": "Übersprungene Videos", "INPROGRESS_METADATA_EXTRACTION": "In Bearbeitung", - "INPROGRESS_UPLOADS": "Uploads in progress", + "INPROGRESS_UPLOADS": "Upload läuft", "TOO_LARGE_UPLOADS": "Große Dateien", "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Zu wenig Speicher", "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Diese Dateien wurden nicht hochgeladen, da sie die maximale Größe für Ihren Speicherplan überschreiten", "TOO_LARGE_INFO": "Diese Dateien wurden nicht hochgeladen, da sie unsere maximale Dateigröße überschreiten", "THUMBNAIL_GENERATION_FAILED_INFO": "Diese Dateien wurden hochgeladen, aber leider konnten wir nicht die Thumbnails für sie generieren.", "UPLOAD_TO_COLLECTION": "In Album hochladen", - "UNCATEGORIZED": "Uncategorized", + "UNCATEGORIZED": "Unkategorisiert", "ARCHIVE": "Archiv", "FAVORITES": "Favoriten", "ARCHIVE_COLLECTION": "Album archivieren", "ARCHIVE_SECTION_NAME": "Archiv", "ALL_SECTION_NAME": "Alle", "MOVE_TO_COLLECTION": "Zum Album verschieben", - "UNARCHIVE": "Unarchive", - "UNARCHIVE_COLLECTION": "Unarchive album", - "HIDE_COLLECTION": "Hide album", - "UNHIDE_COLLECTION": "Unhide album", + "UNARCHIVE": "Dearchivieren", + "UNARCHIVE_COLLECTION": "Album dearchivieren", + "HIDE_COLLECTION": "Album ausblenden", + "UNHIDE_COLLECTION": "Album wieder einblenden", "MOVE": "Verschieben", "ADD": "Hinzufügen", "REMOVE": "Entfernen", @@ -322,204 +320,204 @@ "REMOVE_FROM_COLLECTION": "Aus Album entfernen", "TRASH": "Papierkorb", "MOVE_TO_TRASH": "In Papierkorb verschieben", - "TRASH_FILES_MESSAGE": "Selected files will be removed from all albums and moved to trash.", - "TRASH_FILE_MESSAGE": "The file will be removed from all albums and moved to trash.", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", "DELETE_PERMANENTLY": "Dauerhaft löschen", "RESTORE": "Wiederherstellen", "RESTORE_TO_COLLECTION": "In Album wiederherstellen", "EMPTY_TRASH": "Papierkorb leeren", "EMPTY_TRASH_TITLE": "Papierkorb leeren?", - "EMPTY_TRASH_MESSAGE": "These files will be permanently deleted from your ente account.", + "EMPTY_TRASH_MESSAGE": "", "LEAVE_SHARED_ALBUM": "Ja, verlassen", "LEAVE_ALBUM": "Album verlassen", "LEAVE_SHARED_ALBUM_TITLE": "Geteiltes Album verlassen?", - "LEAVE_SHARED_ALBUM_MESSAGE": "You will leave the album, and it will stop being visible to you.", + "LEAVE_SHARED_ALBUM_MESSAGE": "", "NOT_FILE_OWNER": "Dateien in einem freigegebenen Album können nicht gelöscht werden", - "CONFIRM_SELF_REMOVE_MESSAGE": "Selected items will be removed from this album. Items which are only in this album will be moved to Uncategorized.", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Some of the items you are removing were added by other people, and you will lose access to them.", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Einige der Elemente, die du entfernst, wurden von anderen Nutzern hinzugefügt und du wirst den Zugriff auf sie verlieren.", "SORT_BY_CREATION_TIME_ASCENDING": "Ältestem", "SORT_BY_UPDATION_TIME_DESCENDING": "Zuletzt aktualisiert", "SORT_BY_NAME": "Name", - "COMPRESS_THUMBNAILS": "Compress thumbnails", - "THUMBNAIL_REPLACED": "Thumbnails compressed", + "COMPRESS_THUMBNAILS": "Vorschaubilder komprimieren", + "THUMBNAIL_REPLACED": "Vorschaubilder komprimiert", "FIX_THUMBNAIL": "Komprimiere", - "FIX_THUMBNAIL_LATER": "Compress later", - "REPLACE_THUMBNAIL_NOT_STARTED": "Some of your videos thumbnails can be compressed to save space. would you like ente to compress them?", - "REPLACE_THUMBNAIL_COMPLETED": "Successfully compressed all thumbnails", - "REPLACE_THUMBNAIL_NOOP": "You have no thumbnails that can be compressed further", - "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Could not compress some of your thumbnails, please retry", - "FIX_CREATION_TIME": "Fix time", - "FIX_CREATION_TIME_IN_PROGRESS": "Fixing time", - "CREATION_TIME_UPDATED": "File time updated", - "UPDATE_CREATION_TIME_NOT_STARTED": "Select the option you want to use", - "UPDATE_CREATION_TIME_COMPLETED": "Successfully updated all files", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "File time updation failed for some files, please retry", - "CAPTION_CHARACTER_LIMIT": "5000 characters max", - "DATE_TIME_ORIGINAL": "EXIF:DateTimeOriginal", - "DATE_TIME_DIGITIZED": "EXIF:DateTimeDigitized", - "METADATA_DATE": "EXIF:MetadataDate", - "CUSTOM_TIME": "Custom time", - "REOPEN_PLAN_SELECTOR_MODAL": "Re-open plans", - "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Failed to open plans", + "FIX_THUMBNAIL_LATER": "Später komprimieren", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "Zeit reparieren", + "FIX_CREATION_TIME_IN_PROGRESS": "Zeit wird repariert", + "CREATION_TIME_UPDATED": "Datei-Zeit aktualisiert", + "UPDATE_CREATION_TIME_NOT_STARTED": "Wählen Sie die Option, die Sie verwenden möchten", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "Maximal 5000 Zeichen", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "Benutzerdefinierte Zeit", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Fehler beim Öffnen der Pläne", "INSTALL": "Installieren", "SHARING_DETAILS": "Details teilen", - "MODIFY_SHARING": "Modify sharing", - "ADD_COLLABORATORS": "Add collaborators", - "ADD_NEW_EMAIL": "Add a new email", - "shared_with_people_zero": "Share with specific people", - "shared_with_people_one": "Shared with 1 person", - "shared_with_people_other": "Shared with {{count, number}} people", - "participants_zero": "No participants", - "participants_one": "1 participant", - "participants_other": "{{count, number}} participants", - "ADD_VIEWERS": "Add viewers", - "PARTICIPANTS": "Participants", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} will not be able to add more photos to the album

They will still be able to remove photos added by them

", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} will be able to add photos to the album", - "CONVERT_TO_VIEWER": "Yes, convert to viewer", - "CONVERT_TO_COLLABORATOR": "Yes, convert to collaborator", - "CHANGE_PERMISSION": "Change permission?", + "MODIFY_SHARING": "Freigabe ändern", + "ADD_COLLABORATORS": "Bearbeiter hinzufügen", + "ADD_NEW_EMAIL": "Neue E-Mail-Adresse hinzufügen", + "shared_with_people_zero": "Mit bestimmten Personen teilen", + "shared_with_people_one": "Geteilt mit einer Person", + "shared_with_people_other": "Geteilt mit {{count, number}} Personen", + "participants_zero": "Keine Teilnehmer", + "participants_one": "1 Teilnehmer", + "participants_other": "{{count, number}} Teilnehmer", + "ADD_VIEWERS": "Betrachter hinzufügen", + "PARTICIPANTS": "Teilnehmer", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "Ja, zu \"Beobachter\" ändern", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "Berechtigung ändern?", "REMOVE_PARTICIPANT": "Entfernen?", "CONFIRM_REMOVE": "Ja, entfernen", "MANAGE": "Verwalten", - "ADDED_AS": "Added as", - "COLLABORATOR_RIGHTS": "Collaborators can add photos and videos to the shared album", + "ADDED_AS": "Hinzugefügt als", + "COLLABORATOR_RIGHTS": "Bearbeiter können Fotos & Videos zu dem geteilten Album hinzufügen", "REMOVE_PARTICIPANT_HEAD": "Teilnehmer entfernen", "OWNER": "Besitzer", - "COLLABORATORS": "Collaborators", - "ADD_MORE": "Add more", - "VIEWERS": "Viewers", - "OR_ADD_EXISTING": "Or pick an existing one", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} will be removed from the album

Any photos added by them will also be removed from the album

", + "COLLABORATORS": "Bearbeiter", + "ADD_MORE": "Mehr hinzufügen", + "VIEWERS": "Zuschauer", + "OR_ADD_EXISTING": "Oder eine Vorherige auswählen", + "REMOVE_PARTICIPANT_MESSAGE": "", "NOT_FOUND": "404 - Nicht gefunden", "LINK_EXPIRED": "Link ist abgelaufen", "LINK_EXPIRED_MESSAGE": "Dieser Link ist abgelaufen oder wurde deaktiviert!", - "MANAGE_LINK": "Manage link", + "MANAGE_LINK": "Link verwalten", "LINK_TOO_MANY_REQUESTS": "Sorry, dieses Album wurde auf zu vielen Geräten angezeigt!", "FILE_DOWNLOAD": "Downloads erlauben", "LINK_PASSWORD_LOCK": "Passwort Sperre", - "PUBLIC_COLLECT": "Allow adding photos", + "PUBLIC_COLLECT": "Hinzufügen von Fotos erlauben", "LINK_DEVICE_LIMIT": "Geräte Limit", - "NO_DEVICE_LIMIT": "None", + "NO_DEVICE_LIMIT": "Keins", "LINK_EXPIRY": "Ablaufdatum des Links", "NEVER": "Niemals", - "DISABLE_FILE_DOWNLOAD": "Disable download", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Are you sure that you want to disable the download button for files?

Viewers can still take screenshots or save a copy of your photos using external tools.

", - "MALICIOUS_CONTENT": "Contains malicious content", - "COPYRIGHT": "Infringes on the copyright of someone I am authorized to represent", - "SHARED_USING": "Shared using ", + "DISABLE_FILE_DOWNLOAD": "Download deaktivieren", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "Enthält schädliche Inhalte", + "COPYRIGHT": "Verletzung des Urheberrechts von jemandem, den ich repräsentieren darf", + "SHARED_USING": "Freigegeben über ", "ENTE_IO": "ente.io", - "SHARING_REFERRAL_CODE": "Use code {{referralCode}} to get 10 GB free", + "SHARING_REFERRAL_CODE": "", "LIVE": "LIVE", - "DISABLE_PASSWORD": "Disable password lock", - "DISABLE_PASSWORD_MESSAGE": "Are you sure that you want to disable the password lock?", + "DISABLE_PASSWORD": "Passwort-Sperre deaktivieren", + "DISABLE_PASSWORD_MESSAGE": "Sind Sie sicher, dass Sie die Passwort-Sperre deaktivieren möchten?", "PASSWORD_LOCK": "Passwort Sperre", - "LOCK": "Lock", - "DOWNLOAD_UPLOAD_LOGS": "Debug logs", + "LOCK": "Sperren", + "DOWNLOAD_UPLOAD_LOGS": "Debug-Logs", "UPLOAD_FILES": "Datei", "UPLOAD_DIRS": "Ordner", "UPLOAD_GOOGLE_TAKEOUT": "Google Takeout", - "DEDUPLICATE_FILES": "Deduplicate files", + "DEDUPLICATE_FILES": "", "AUTHENTICATOR_SECTION": "Authenticator", "NO_DUPLICATES_FOUND": "Du hast keine Duplikate, die gelöscht werden können", - "CLUB_BY_CAPTURE_TIME": "Club by capture time", + "CLUB_BY_CAPTURE_TIME": "", "FILES": "Dateien", - "EACH": "Each", - "DEDUPLICATE_BASED_ON_SIZE": "The following files were clubbed based on their sizes, please review and delete items you believe are duplicates", - "STOP_ALL_UPLOADS_MESSAGE": "Are you sure that you want to stop all the uploads in progress?", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", "STOP_UPLOADS_HEADER": "Hochladen stoppen?", "YES_STOP_UPLOADS": "Ja, Hochladen stoppen", - "STOP_DOWNLOADS_HEADER": "Stop downloads?", - "YES_STOP_DOWNLOADS": "Yes, stop downloads", - "STOP_ALL_DOWNLOADS_MESSAGE": "Are you sure that you want to stop all the downloads in progress?", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", "albums_one": "1 Album", - "albums_other": "{{count, number}} Albums", + "albums_other": "", "ALL_ALBUMS": "Alle Alben", "ALBUMS": "Alben", - "ALL_HIDDEN_ALBUMS": "All hidden albums", - "HIDDEN_ALBUMS": "Hidden albums", - "HIDDEN_ITEMS": "Hidden items", - "HIDDEN_ITEMS_SECTION_NAME": "Hidden_items", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", "ENTER_TWO_FACTOR_OTP": "Gib den 6-stelligen Code aus\ndeiner Authentifizierungs-App ein.", "CREATE_ACCOUNT": "Account erstellen", "COPIED": "Kopiert", "CANVAS_BLOCKED_TITLE": "Vorschaubild konnte nicht erstellt werden", - "CANVAS_BLOCKED_MESSAGE": "

It looks like your browser has disabled access to canvas, which is necessary to generate thumbnails for your photos

Please enable access to your browser's canvas, or check out our desktop app

", - "WATCH_FOLDERS": "Watch folders", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", "UPGRADE_NOW": "Jetzt upgraden", - "RENEW_NOW": "Renew now", + "RENEW_NOW": "", "STORAGE": "Speicher", "USED": "verwendet", "YOU": "Sie", "FAMILY": "Familie", "FREE": "frei", "OF": "von", - "WATCHED_FOLDERS": "Watched folders", - "NO_FOLDERS_ADDED": "No folders added yet!", - "FOLDERS_AUTOMATICALLY_MONITORED": "The folders you add here will monitored to automatically", - "UPLOAD_NEW_FILES_TO_ENTE": "Upload new files to ente", - "REMOVE_DELETED_FILES_FROM_ENTE": "Remove deleted files from ente", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", "ADD_FOLDER": "Ordner hinzufügen", - "STOP_WATCHING": "Stop watching", - "STOP_WATCHING_FOLDER": "Stop watching folder?", - "STOP_WATCHING_DIALOG_MESSAGE": "Your existing files will not be deleted, but ente will stop automatically updating the linked ente album on changes in this folder.", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", "YES_STOP": "Ja, Stopp", - "MONTH_SHORT": "mo", + "MONTH_SHORT": "", "YEAR": "Jahr", "FAMILY_PLAN": "Familientarif", "DOWNLOAD_LOGS": "Logs herunterladen", - "DOWNLOAD_LOGS_MESSAGE": "

This will download debug logs, which you can email to us to help debug your issue.

Please note that file names will be included to help track issues with specific files.

", - "CHANGE_FOLDER": "Change Folder", - "TWO_MONTHS_FREE": "Get 2 months free on yearly plans", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "Ordner ändern", + "TWO_MONTHS_FREE": "Erhalte 2 Monate kostenlos bei Jahresabonnements", "GB": "GB", "POPULAR": "Beliebt", - "FREE_PLAN_OPTION_LABEL": "Continue with free trial", + "FREE_PLAN_OPTION_LABEL": "Mit kostenloser Testversion fortfahren", "FREE_PLAN_DESCRIPTION": "1 GB für 1 Jahr", - "CURRENT_USAGE": "Current usage is {{usage}}", - "WEAK_DEVICE": "The web browser you're using is not powerful enough to encrypt your photos. Please try to log in to ente on your computer, or download the ente mobile/desktop app.", - "DRAG_AND_DROP_HINT": "Or drag and drop into the ente window", - "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Your uploaded data will be scheduled for deletion, and your account will be permanently deleted.

This action is not reversible.", + "CURRENT_USAGE": "Aktuelle Nutzung ist {{usage}}", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", "AUTHENTICATE": "Authentifizieren", - "UPLOADED_TO_SINGLE_COLLECTION": "Uploaded to single collection", - "UPLOADED_TO_SEPARATE_COLLECTIONS": "Uploaded to separate collections", + "UPLOADED_TO_SINGLE_COLLECTION": "", + "UPLOADED_TO_SEPARATE_COLLECTIONS": "", "NEVERMIND": "Egal", "UPDATE_AVAILABLE": "Neue Version verfügbar", - "UPDATE_INSTALLABLE_MESSAGE": "A new version of ente is ready to be installed.", + "UPDATE_INSTALLABLE_MESSAGE": "", "INSTALL_NOW": "Jetzt installieren", "INSTALL_ON_NEXT_LAUNCH": "Beim nächsten Start installieren", - "UPDATE_AVAILABLE_MESSAGE": "A new version of ente has been released, but it cannot be automatically downloaded and installed.", - "DOWNLOAD_AND_INSTALL": "Download and install", + "UPDATE_AVAILABLE_MESSAGE": "", + "DOWNLOAD_AND_INSTALL": "", "IGNORE_THIS_VERSION": "Diese Version ignorieren", "TODAY": "Heute", "YESTERDAY": "Gestern", "NAME_PLACEHOLDER": "Name...", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Cannot create albums from file/folder mix", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

You have dragged and dropped a mixture of files and folders.

Please provide either only files, or only folders when selecting option to create separate albums

", - "CHOSE_THEME": "Choose theme", - "ML_SEARCH": "Face recognition", - "ENABLE_ML_SEARCH_DESCRIPTION": "

This will enable on-device machine learning and face search which will start analyzing your uploaded photos locally.

For the first run after login or enabling this feature, it will download all images on local device to analyze them. So please only enable this if you are ok with bandwidth and local processing of all images in your photo library.

If this is the first time you're enabling this, we'll also ask your permission to process face data.

", - "ML_MORE_DETAILS": "More details", - "ENABLE_FACE_SEARCH": "Enable face recognition", - "ENABLE_FACE_SEARCH_TITLE": "Enable face recognition?", - "ENABLE_FACE_SEARCH_DESCRIPTION": "

If you enable face recognition, ente will extract face geometry from your photos. This will happen on your device, and any generated biometric data will be end-to-encrypted.

Please click here for more details about this feature in our privacy policy

", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", "DISABLE_BETA": "Beta deaktivieren", - "DISABLE_FACE_SEARCH": "Disable face recognition", - "DISABLE_FACE_SEARCH_TITLE": "Disable face recognition?", - "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente will stop processing face geometry.

You can reenable face recognition again if you wish, so this operation is safe.

", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", "ADVANCED": "Erweitert", - "FACE_SEARCH_CONFIRMATION": "I understand, and wish to allow ente to process face geometry", - "LABS": "Labs", - "YOURS": "yours", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", "PASSPHRASE_STRENGTH_WEAK": "Passwortstärke: Schwach", - "PASSPHRASE_STRENGTH_MODERATE": "Password strength: Moderate", + "PASSPHRASE_STRENGTH_MODERATE": "", "PASSPHRASE_STRENGTH_STRONG": "Passwortstärke: Stark", "PREFERENCES": "Einstellungen", "LANGUAGE": "Sprache", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Invalid export directory", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

The export directory you have selected does not exist.

Please select a valid directory.

", - "SUBSCRIPTION_VERIFICATION_ERROR": "Subscription verification failed", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", "STORAGE_UNITS": { - "B": "B", + "B": "", "KB": "KB", "MB": "MB", "GB": "GB", @@ -539,46 +537,46 @@ "CREATE_PUBLIC_SHARING": "Öffentlichen Link erstellen", "PUBLIC_LINK_CREATED": "Öffentlicher Link erstellt", "PUBLIC_LINK_ENABLED": "Öffentlicher Link aktiviert", - "COLLECT_PHOTOS": "Collect photos", - "PUBLIC_COLLECT_SUBTEXT": "Allow people with the link to also add photos to the shared album.", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", "STOP_EXPORT": "Stop", - "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} items synced", - "MIGRATING_EXPORT": "Preparing...", - "RENAMING_COLLECTION_FOLDERS": "Renaming album folders...", - "TRASHING_DELETED_FILES": "Trashing deleted files...", - "TRASHING_DELETED_COLLECTIONS": "Trashing deleted albums...", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", "EXPORT_NOTIFICATION": { "START": "Export gestartet", - "IN_PROGRESS": "Export already in progress", + "IN_PROGRESS": "", "FINISH": "Export abgeschlossen", - "UP_TO_DATE": "No new files to export" + "UP_TO_DATE": "" }, - "CONTINUOUS_EXPORT": "Sync continuously", - "TOTAL_ITEMS": "Total items", - "PENDING_ITEMS": "Pending items", - "EXPORT_STARTING": "Export starting...", - "DELETE_ACCOUNT_REASON_LABEL": "What is the main reason you are deleting your account?", - "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Select a reason", + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", "DELETE_REASON": { - "MISSING_FEATURE": "It's missing a key feature that I need", - "BROKEN_BEHAVIOR": "The app or a certain feature does not behave as I think it should", - "FOUND_ANOTHER_SERVICE": "I found another service that I like better", - "NOT_LISTED": "My reason isn't listed" + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" }, - "DELETE_ACCOUNT_FEEDBACK_LABEL": "We are sorry to see you go. Please explain why you are leaving to help us improve.", - "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Feedback", - "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Yes, I want to permanently delete this account and all its data", + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", "CONFIRM_DELETE_ACCOUNT": "Kontolöschung bestätigen", - "FEEDBACK_REQUIRED": "Kindly help us with this information", - "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "What does the other service do better?", - "RECOVER_TWO_FACTOR": "Recover two-factor", - "at": "at", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", "AUTH_NEXT": "Weiter", - "AUTH_DOWNLOAD_MOBILE_APP": "Download our mobile app to manage your secrets", + "AUTH_DOWNLOAD_MOBILE_APP": "", "HIDDEN": "Versteckt", "HIDE": "Ausblenden", "UNHIDE": "Einblenden", - "UNHIDE_TO_COLLECTION": "Unhide to album", + "UNHIDE_TO_COLLECTION": "", "SORT_BY": "Sortieren nach", "NEWEST_FIRST": "Neueste zuerst", "OLDEST_FIRST": "Älteste zuerst", @@ -586,59 +584,71 @@ "SELECT_COLLECTION": "Album auswählen", "PIN_ALBUM": "Album anheften", "UNPIN_ALBUM": "Album lösen", - "DOWNLOAD_COMPLETE": "Download complete", - "DOWNLOADING_COLLECTION": "Downloading {{name}}", - "DOWNLOAD_FAILED": "Download failed", - "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", - "CHRISTMAS": "Christmas", - "CHRISTMAS_EVE": "Christmas Eve", - "NEW_YEAR": "New Year", - "NEW_YEAR_EVE": "New Year's Eve", - "IMAGE": "Image", - "VIDEO": "Video", - "LIVE_PHOTO": "Live Photo", - "CONVERT": "Convert", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Are you sure you want to close the editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Download your edited image or save a copy to ente to persist your changes.", - "BRIGHTNESS": "Brightness", - "CONTRAST": "Contrast", - "SATURATION": "Saturation", - "BLUR": "Blur", - "INVERT_COLORS": "Invert Colors", - "ASPECT_RATIO": "Aspect Ratio", - "SQUARE": "Square", - "ROTATE_LEFT": "Rotate Left", - "ROTATE_RIGHT": "Rotate Right", - "FLIP_VERTICALLY": "Flip Vertically", - "FLIP_HORIZONTALLY": "Flip Horizontally", - "DOWNLOAD_EDITED": "Download Edited", - "SAVE_A_COPY_TO_ENTE": "Save a copy to ente", - "RESTORE_ORIGINAL": "Restore Original", - "TRANSFORM": "Transform", - "COLORS": "Colors", - "FLIP": "Flip", - "ROTATION": "Rotation", - "RESET": "Reset", - "PHOTO_EDITOR": "Photo Editor", - "FASTER_UPLOAD": "Faster uploads", - "FASTER_UPLOAD_DESCRIPTION": "Route uploads through nearby servers", - "MAGIC_SEARCH_STATUS": "Magic Search Status", - "INDEXED_ITEMS": "Indexed items", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", - "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", - "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/en-US/translation.json b/web/apps/auth/public/locales/en-US/translation.json index 6870df3194..de8d2fe2a1 100644 --- a/web/apps/auth/public/locales/en-US/translation.json +++ b/web/apps/auth/public/locales/en-US/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", "PASSPHRASE_MATCH_ERROR": "Passwords don't match", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "This is a browser feature intended for developers. Please don't copy-paste unverified code here.", "CREATE_COLLECTION": "New album", "ENTER_ALBUM_NAME": "Album name", "CLOSE_OPTION": "Close (Esc)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Downloading {{name}}", "DOWNLOAD_FAILED": "Download failed", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", "CHRISTMAS": "Christmas", "CHRISTMAS_EVE": "Christmas Eve", "NEW_YEAR": "New Year", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", "FREEHAND": "Freehand", "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving.", + "PASSKEYS": "Passkeys", + "DELETE_PASSKEY": "Delete passkey", + "DELETE_PASSKEY_CONFIRMATION": "Are you sure you want to delete this passkey? This action is irreversible.", + "RENAME_PASSKEY": "Rename passkey", + "ADD_PASSKEY": "Add passkey", + "ENTER_PASSKEY_NAME": "Enter passkey name", + "PASSKEYS_DESCRIPTION": "Passkeys are a modern and secure second-factor for your Ente account. They use on-device biometric authentication for convenience and security.", + "CREATED_AT": "Created at", + "PASSKEY_LOGIN_FAILED": "Passkey login failed", + "PASSKEY_LOGIN_URL_INVALID": "The login URL is invalid.", + "PASSKEY_LOGIN_ERRORED": "An error occurred while logging in with passkey.", + "TRY_AGAIN": "Try again", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "Follow the steps from your browser to continue logging in.", + "LOGIN_WITH_PASSKEY": "Login with passkey" } diff --git a/web/apps/auth/public/locales/es-ES/translation.json b/web/apps/auth/public/locales/es-ES/translation.json index 05f3d03256..a29165e4ee 100644 --- a/web/apps/auth/public/locales/es-ES/translation.json +++ b/web/apps/auth/public/locales/es-ES/translation.json @@ -38,11 +38,9 @@ "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generando claves de encriptación...", "PASSPHRASE_HINT": "Contraseña", "CONFIRM_PASSPHRASE": "Confirmar contraseña", - "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", - "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "Las contraseñas no coinciden", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "Esta es una característica del navegador destinada a los desarrolladores. Por favor, no copie y pegue código sin verificar aquí.", "CREATE_COLLECTION": "Nuevo álbum", "ENTER_ALBUM_NAME": "Nombre del álbum", "CLOSE_OPTION": "Cerrar (Esc)", @@ -79,7 +77,7 @@ "DOWNLOAD_OPTION": "Descargar (D)", "DOWNLOAD_FAVORITES": "Descargar favoritos", "DOWNLOAD_UNCATEGORIZED": "Descargar no categorizados", - "DOWNLOAD_HIDDEN_ITEMS": "Download hidden items", + "DOWNLOAD_HIDDEN_ITEMS": "", "COPY_OPTION": "Copiar como PNG (Ctrl/Cmd - C)", "TOGGLE_FULLSCREEN": "Alternar pantalla completa (F)", "ZOOM_IN_OUT": "Acercar/alejar", @@ -159,7 +157,7 @@ "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Se renueva en {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Termina el {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Tu suscripción será cancelada el {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "", "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Ha excedido su cuota de almacenamiento, por favor actualice", "SUBSCRIPTION_PURCHASE_SUCCESS": "

Hemos recibido tu pago

¡Tu suscripción es válida hasta {{date, dateTime}}

", "SUBSCRIPTION_PURCHASE_CANCELLED": "Tu compra ha sido cancelada, por favor inténtalo de nuevo si quieres suscribirte", @@ -174,7 +172,7 @@ "UPDATE_SUBSCRIPTION": "Cambiar de plan", "CANCEL_SUBSCRIPTION": "Cancelar suscripción", "CANCEL_SUBSCRIPTION_MESSAGE": "

Todos tus datos serán eliminados de nuestros servidores al final de este periodo de facturación.

¿Está seguro de que desea cancelar su suscripción?

", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", "SUBSCRIPTION_CANCEL_FAILED": "No se pudo cancelar la suscripción", "SUBSCRIPTION_CANCEL_SUCCESS": "Suscripción cancelada correctamente", "REACTIVATE_SUBSCRIPTION": "Reactivar la suscripción", @@ -210,13 +208,13 @@ "SEARCH_TYPE": { "COLLECTION": "Álbum", "LOCATION": "Localización", - "CITY": "Location", + "CITY": "", "DATE": "Fecha", "FILE_NAME": "Nombre del archivo", "THING": "Contenido", "FILE_CAPTION": "Descripción", - "FILE_TYPE": "File type", - "CLIP": "Magic" + "FILE_TYPE": "", + "CLIP": "" }, "photos_count_zero": "No hay recuerdos", "photos_count_one": "1 recuerdo", @@ -239,14 +237,14 @@ "CAPTION_PLACEHOLDER": "Añadir una descripción", "LOCATION": "Localización", "SHOW_ON_MAP": "Ver en OpenStreetMap", - "MAP": "Map", - "MAP_SETTINGS": "Map Settings", - "ENABLE_MAPS": "Enable Maps?", - "ENABLE_MAP": "Enable map", - "DISABLE_MAPS": "Disable Maps?", - "ENABLE_MAP_DESCRIPTION": "

This will show your photos on a world map.

The map is hosted by OpenStreetMap, and the exact locations of your photos are never shared.

You can disable this feature anytime from Settings.

", - "DISABLE_MAP_DESCRIPTION": "

This will disable the display of your photos on a world map.

You can enable this feature anytime from Settings.

", - "DISABLE_MAP": "Disable map", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", "DETAILS": "Detalles", "VIEW_EXIF": "Ver todos los datos de EXIF", "NO_EXIF": "No hay datos EXIF", @@ -313,8 +311,8 @@ "MOVE_TO_COLLECTION": "Mover al álbum", "UNARCHIVE": "Desarchivar", "UNARCHIVE_COLLECTION": "Desarchivar álbum", - "HIDE_COLLECTION": "Hide album", - "UNHIDE_COLLECTION": "Unhide album", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", "MOVE": "Mover", "ADD": "Añadir", "REMOVE": "Eliminar", @@ -357,40 +355,40 @@ "CAPTION_CHARACTER_LIMIT": "Máximo 5000 caracteres", "DATE_TIME_ORIGINAL": "EXIF: Fecha original", "DATE_TIME_DIGITIZED": "EXIF: Fecha Digitalizado", - "METADATA_DATE": "EXIF:MetadataDate", + "METADATA_DATE": "", "CUSTOM_TIME": "Hora personalizada", "REOPEN_PLAN_SELECTOR_MODAL": "Reabrir planes", "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Error al abrir los planes", "INSTALL": "Instalar", "SHARING_DETAILS": "Compartir detalles", "MODIFY_SHARING": "Modificar compartir", - "ADD_COLLABORATORS": "Add collaborators", - "ADD_NEW_EMAIL": "Add a new email", - "shared_with_people_zero": "Share with specific people", - "shared_with_people_one": "Shared with 1 person", - "shared_with_people_other": "Shared with {{count, number}} people", - "participants_zero": "No participants", - "participants_one": "1 participant", - "participants_other": "{{count, number}} participants", - "ADD_VIEWERS": "Add viewers", - "PARTICIPANTS": "Participants", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} will not be able to add more photos to the album

They will still be able to remove photos added by them

", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} will be able to add photos to the album", - "CONVERT_TO_VIEWER": "Yes, convert to viewer", - "CONVERT_TO_COLLABORATOR": "Yes, convert to collaborator", - "CHANGE_PERMISSION": "Change permission?", - "REMOVE_PARTICIPANT": "Remove?", - "CONFIRM_REMOVE": "Yes, remove", - "MANAGE": "Manage", - "ADDED_AS": "Added as", - "COLLABORATOR_RIGHTS": "Collaborators can add photos and videos to the shared album", - "REMOVE_PARTICIPANT_HEAD": "Remove participant", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", "OWNER": "Propietario", "COLLABORATORS": "Colaboradores", "ADD_MORE": "Añadir más", - "VIEWERS": "Viewers", + "VIEWERS": "", "OR_ADD_EXISTING": "O elige uno existente", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} will be removed from the album

Any photos added by them will also be removed from the album

", + "REMOVE_PARTICIPANT_MESSAGE": "", "NOT_FOUND": "404 - No Encontrado", "LINK_EXPIRED": "Enlace expirado", "LINK_EXPIRED_MESSAGE": "Este enlace ha caducado o ha sido desactivado!", @@ -436,10 +434,10 @@ "albums_other": "{{count}} álbumes", "ALL_ALBUMS": "Todos los álbumes", "ALBUMS": "Álbumes", - "ALL_HIDDEN_ALBUMS": "All hidden albums", - "HIDDEN_ALBUMS": "Hidden albums", - "HIDDEN_ITEMS": "Hidden items", - "HIDDEN_ITEMS_SECTION_NAME": "Hidden_items", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", "ENTER_TWO_FACTOR_OTP": "Ingrese el código de seis dígitos de su aplicación de autenticación a continuación.", "CREATE_ACCOUNT": "Crear cuenta", "COPIED": "Copiado", @@ -543,10 +541,10 @@ "PUBLIC_COLLECT_SUBTEXT": "Permitir a las personas con el enlace añadir fotos al álbum compartido.", "STOP_EXPORT": "Stop", "EXPORT_PROGRESS": "{{progress.success}} / {{progress.total}} archivos exportados", - "MIGRATING_EXPORT": "Preparing...", - "RENAMING_COLLECTION_FOLDERS": "Renaming album folders...", - "TRASHING_DELETED_FILES": "Trashing deleted files...", - "TRASHING_DELETED_COLLECTIONS": "Trashing deleted albums...", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", "EXPORT_NOTIFICATION": { "START": "Exportar iniciando", "IN_PROGRESS": "Exportación ya en curso", @@ -575,70 +573,82 @@ "at": "a las", "AUTH_NEXT": "siguiente", "AUTH_DOWNLOAD_MOBILE_APP": "Descarga nuestra aplicación móvil para administrar tus secretos", - "HIDDEN": "Hidden", + "HIDDEN": "", "HIDE": "Ocultar", "UNHIDE": "Mostrar", "UNHIDE_TO_COLLECTION": "Hacer visible al álbum", - "SORT_BY": "Sort by", - "NEWEST_FIRST": "Newest first", - "OLDEST_FIRST": "Oldest first", - "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "This file could not be previewed. Click here to download the original.", - "SELECT_COLLECTION": "Select album", - "PIN_ALBUM": "Pin album", - "UNPIN_ALBUM": "Unpin album", - "DOWNLOAD_COMPLETE": "Download complete", - "DOWNLOADING_COLLECTION": "Downloading {{name}}", - "DOWNLOAD_FAILED": "Download failed", - "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", - "CHRISTMAS": "Christmas", - "CHRISTMAS_EVE": "Christmas Eve", - "NEW_YEAR": "New Year", - "NEW_YEAR_EVE": "New Year's Eve", - "IMAGE": "Image", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", "VIDEO": "Video", - "LIVE_PHOTO": "Live Photo", - "CONVERT": "Convert", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Are you sure you want to close the editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Download your edited image or save a copy to ente to persist your changes.", - "BRIGHTNESS": "Brightness", - "CONTRAST": "Contrast", - "SATURATION": "Saturation", - "BLUR": "Blur", - "INVERT_COLORS": "Invert Colors", - "ASPECT_RATIO": "Aspect Ratio", - "SQUARE": "Square", - "ROTATE_LEFT": "Rotate Left", - "ROTATE_RIGHT": "Rotate Right", - "FLIP_VERTICALLY": "Flip Vertically", - "FLIP_HORIZONTALLY": "Flip Horizontally", - "DOWNLOAD_EDITED": "Download Edited", - "SAVE_A_COPY_TO_ENTE": "Save a copy to ente", - "RESTORE_ORIGINAL": "Restore Original", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", "TRANSFORM": "Transformar", "COLORS": "Colores", - "FLIP": "Flip", - "ROTATION": "Rotation", - "RESET": "Reset", - "PHOTO_EDITOR": "Photo Editor", - "FASTER_UPLOAD": "Faster uploads", - "FASTER_UPLOAD_DESCRIPTION": "Route uploads through nearby servers", - "MAGIC_SEARCH_STATUS": "Magic Search Status", - "INDEXED_ITEMS": "Indexed items", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", - "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", - "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/fa-IR/translation.json b/web/apps/auth/public/locales/fa-IR/translation.json index 2c36eda0cd..2d21fcb3d3 100644 --- a/web/apps/auth/public/locales/fa-IR/translation.json +++ b/web/apps/auth/public/locales/fa-IR/translation.json @@ -1,644 +1,654 @@ { - "HERO_SLIDE_1_TITLE": "
Private backups
for your memories
", - "HERO_SLIDE_1": "End-to-end encrypted by default", - "HERO_SLIDE_2_TITLE": "
Safely stored
at a fallout shelter
", - "HERO_SLIDE_2": "Designed to outlive", - "HERO_SLIDE_3_TITLE": "
Available
everywhere
", - "HERO_SLIDE_3": "Android, iOS, Web, Desktop", - "LOGIN": "Login", - "SIGN_UP": "Signup", - "NEW_USER": "New to ente", - "EXISTING_USER": "Existing user", - "ENTER_NAME": "Enter name", - "PUBLIC_UPLOADER_NAME_MESSAGE": "Add a name so that your friends know who to thank for these great photos!", - "ENTER_EMAIL": "Enter email address", - "EMAIL_ERROR": "Enter a valid email", - "REQUIRED": "Required", - "EMAIL_SENT": "Verification code sent to {{email}}", - "CHECK_INBOX": "Please check your inbox (and spam) to complete verification", - "ENTER_OTT": "Verification code", - "RESEND_MAIL": "Resend code", - "VERIFY": "Verify", - "UNKNOWN_ERROR": "Something went wrong, please try again", - "INVALID_CODE": "Invalid verification code", - "EXPIRED_CODE": "Your verification code has expired", - "SENDING": "Sending...", - "SENT": "Sent!", - "PASSWORD": "Password", - "LINK_PASSWORD": "Enter password to unlock the album", - "RETURN_PASSPHRASE_HINT": "Password", - "SET_PASSPHRASE": "Set password", - "VERIFY_PASSPHRASE": "Sign in", - "INCORRECT_PASSPHRASE": "Incorrect password", - "ENTER_ENC_PASSPHRASE": "Please enter a password that we can use to encrypt your data", - "PASSPHRASE_DISCLAIMER": "We don't store your password, so if you forget it, we will not be able to help you recover your data without a recovery key.", + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", "WELCOME_TO_ENTE_HEADING": "به خوش آمدید", - "WELCOME_TO_ENTE_SUBHEADING": "End to end encrypted photo storage and sharing", - "WHERE_YOUR_BEST_PHOTOS_LIVE": "Where your best photos live", - "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generating encryption keys...", - "PASSPHRASE_HINT": "Password", - "CONFIRM_PASSPHRASE": "Confirm password", - "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", - "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", - "PASSPHRASE_MATCH_ERROR": "Passwords don't match", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "This is a browser feature intended for developers. Please don't copy-paste unverified code here.", - "CREATE_COLLECTION": "New album", - "ENTER_ALBUM_NAME": "Album name", - "CLOSE_OPTION": "Close (Esc)", - "ENTER_FILE_NAME": "File name", - "CLOSE": "Close", - "NO": "No", - "NOTHING_HERE": "Nothing to see here yet 👀", - "UPLOAD": "Upload", - "IMPORT": "Import", - "ADD_PHOTOS": "Add photos", - "ADD_MORE_PHOTOS": "Add more photos", - "add_photos_one": "Add 1 item", - "add_photos_other": "Add {{count, number}} items", - "SELECT_PHOTOS": "Select photos", - "FILE_UPLOAD": "File Upload", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", "UPLOAD_STAGE_MESSAGE": { - "0": "Preparing to upload", - "1": "Reading google metadata files", - "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files metadata extracted", - "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files processed", - "4": "Cancelling remaining uploads", - "5": "Backup complete" + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" }, - "FILE_NOT_UPLOADED_LIST": "The following files were not uploaded", - "SUBSCRIPTION_EXPIRED": "Subscription expired", - "SUBSCRIPTION_EXPIRED_MESSAGE": "Your subscription has expired, please renew", - "STORAGE_QUOTA_EXCEEDED": "Storage limit exceeded", - "INITIAL_LOAD_DELAY_WARNING": "First load may take some time", - "USER_DOES_NOT_EXIST": "Sorry, could not find a user with that email", - "NO_ACCOUNT": "Don't have an account", - "ACCOUNT_EXISTS": "Already have an account", - "CREATE": "Create", - "DOWNLOAD": "Download", - "DOWNLOAD_OPTION": "Download (D)", - "DOWNLOAD_FAVORITES": "Download favorites", - "DOWNLOAD_UNCATEGORIZED": "Download uncategorized", - "DOWNLOAD_HIDDEN_ITEMS": "Download hidden items", - "COPY_OPTION": "Copy as PNG (Ctrl/Cmd - C)", - "TOGGLE_FULLSCREEN": "Toggle fullscreen (F)", - "ZOOM_IN_OUT": "Zoom in/out", - "PREVIOUS": "Previous (←)", - "NEXT": "Next (→)", - "TITLE_PHOTOS": "Ente Photos", - "TITLE_ALBUMS": "Ente Photos", - "TITLE_AUTH": "Ente Auth", - "UPLOAD_FIRST_PHOTO": "Upload your first photo", - "IMPORT_YOUR_FOLDERS": "Import your folders", - "UPLOAD_DROPZONE_MESSAGE": "Drop to backup your files", - "WATCH_FOLDER_DROPZONE_MESSAGE": "Drop to add watched folder", - "TRASH_FILES_TITLE": "Delete files?", - "TRASH_FILE_TITLE": "Delete file?", - "DELETE_FILES_TITLE": "Delete immediately?", - "DELETE_FILES_MESSAGE": "Selected files will be permanently deleted from your ente account.", - "DELETE": "Delete", - "DELETE_OPTION": "Delete (DEL)", - "FAVORITE_OPTION": "Favorite (L)", - "UNFAVORITE_OPTION": "Unfavorite (L)", - "MULTI_FOLDER_UPLOAD": "Multiple folders detected", - "UPLOAD_STRATEGY_CHOICE": "Would you like to upload them into", - "UPLOAD_STRATEGY_SINGLE_COLLECTION": "A single album", - "OR": "or", - "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Separate albums", - "SESSION_EXPIRED_MESSAGE": "Your session has expired, please login again to continue", - "SESSION_EXPIRED": "Session expired", - "PASSWORD_GENERATION_FAILED": "Your browser was unable to generate a strong key that meets ente's encryption standards, please try using the mobile app or another browser", - "CHANGE_PASSWORD": "Change password", - "GO_BACK": "Go back", - "RECOVERY_KEY": "Recovery key", - "SAVE_LATER": "Do this later", - "SAVE": "Save Key", - "RECOVERY_KEY_DESCRIPTION": "If you forget your password, the only way you can recover your data is with this key.", - "RECOVER_KEY_GENERATION_FAILED": "Recovery code could not be generated, please try again", - "KEY_NOT_STORED_DISCLAIMER": "We don't store this key, so please save this in a safe place", - "FORGOT_PASSWORD": "Forgot password", - "RECOVER_ACCOUNT": "Recover account", - "RECOVERY_KEY_HINT": "Recovery key", - "RECOVER": "Recover", - "NO_RECOVERY_KEY": "No recovery key?", - "INCORRECT_RECOVERY_KEY": "Incorrect recovery key", - "SORRY": "Sorry", - "NO_RECOVERY_KEY_MESSAGE": "Due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Please drop an email to {{emailID}} from your registered email address", - "CONTACT_SUPPORT": "Contact support", - "REQUEST_FEATURE": "Request Feature", - "SUPPORT": "Support", - "CONFIRM": "Confirm", - "CANCEL": "Cancel", - "LOGOUT": "Logout", - "DELETE_ACCOUNT": "Delete account", - "DELETE_ACCOUNT_MESSAGE": "

Please send an email to {{emailID}} from your registered email address.

Your request will be processed within 72 hours.

", - "LOGOUT_MESSAGE": "Are you sure you want to logout?", - "CHANGE_EMAIL": "Change email", - "OK": "OK", - "SUCCESS": "Success", - "ERROR": "Error", - "MESSAGE": "Message", - "INSTALL_MOBILE_APP": "Install our Android or iOS app to automatically backup all your photos", - "DOWNLOAD_APP_MESSAGE": "Sorry, this operation is currently only supported on our desktop app", - "DOWNLOAD_APP": "Download desktop app", - "EXPORT": "Export Data", - "SUBSCRIPTION": "Subscription", - "SUBSCRIBE": "Subscribe", - "MANAGEMENT_PORTAL": "Manage payment method", - "MANAGE_FAMILY_PORTAL": "Manage family", - "LEAVE_FAMILY_PLAN": "Leave family plan", - "LEAVE": "Leave", - "LEAVE_FAMILY_CONFIRM": "Are you sure that you want to leave family plan?", - "CHOOSE_PLAN": "Choose your plan", - "MANAGE_PLAN": "Manage your subscription", - "ACTIVE": "Active", - "OFFLINE_MSG": "You are offline, cached memories are being shown", - "FREE_SUBSCRIPTION_INFO": "You are on the free plan that expires on {{date, dateTime}}", - "FAMILY_SUBSCRIPTION_INFO": "You are on a family plan managed by", - "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Renews on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Ends on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Your subscription will be cancelled on {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", - "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "You have exceeded your storage quota, please upgrade", - "SUBSCRIPTION_PURCHASE_SUCCESS": "

We've received your payment

Your subscription is valid till {{date, dateTime}}

", - "SUBSCRIPTION_PURCHASE_CANCELLED": "Your purchase was canceled, please try again if you want to subscribe", - "SUBSCRIPTION_PURCHASE_FAILED": "Subscription purchase failed , please try again", - "SUBSCRIPTION_UPDATE_FAILED": "Subscription updated failed , please try again", - "UPDATE_PAYMENT_METHOD_MESSAGE": "We are sorry, payment failed when we tried to charge your card, please update your payment method and try again", - "STRIPE_AUTHENTICATION_FAILED": "We are unable to authenticate your payment method. please choose a different payment method and try again", - "UPDATE_PAYMENT_METHOD": "Update payment method", - "MONTHLY": "Monthly", - "YEARLY": "Yearly", - "UPDATE_SUBSCRIPTION_MESSAGE": "Are you sure you want to change your plan?", - "UPDATE_SUBSCRIPTION": "Change plan", - "CANCEL_SUBSCRIPTION": "Cancel subscription", - "CANCEL_SUBSCRIPTION_MESSAGE": "

All of your data will be deleted from our servers at the end of this billing period.

Are you sure that you want to cancel your subscription?

", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

", - "SUBSCRIPTION_CANCEL_FAILED": "Failed to cancel subscription", - "SUBSCRIPTION_CANCEL_SUCCESS": "Subscription canceled successfully", - "REACTIVATE_SUBSCRIPTION": "Reactivate subscription", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "Once reactivated, you will be billed on {{date, dateTime}}", - "SUBSCRIPTION_ACTIVATE_SUCCESS": "Subscription activated successfully ", - "SUBSCRIPTION_ACTIVATE_FAILED": "Failed to reactivate subscription renewals", - "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Thank you", - "CANCEL_SUBSCRIPTION_ON_MOBILE": "Cancel mobile subscription", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Please cancel your subscription from the mobile app to activate a subscription here", - "MAIL_TO_MANAGE_SUBSCRIPTION": "Please contact us at {{emailID}} to manage your subscription", - "RENAME": "Rename", - "RENAME_FILE": "Rename file", - "RENAME_COLLECTION": "Rename album", - "DELETE_COLLECTION_TITLE": "Delete album?", - "DELETE_COLLECTION": "Delete album", - "DELETE_COLLECTION_MESSAGE": "Also delete the photos (and videos) present in this album from all other albums they are part of?", - "DELETE_PHOTOS": "Delete photos", - "KEEP_PHOTOS": "Keep photos", - "SHARE": "Share", - "SHARE_COLLECTION": "Share album", - "SHAREES": "Shared with", - "SHARE_WITH_SELF": "Oops, you cannot share with yourself", - "ALREADY_SHARED": "Oops, you're already sharing this with {{email}}", - "SHARING_BAD_REQUEST_ERROR": "Sharing album not allowed", - "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Sharing is disabled for free accounts", - "DOWNLOAD_COLLECTION": "Download album", - "DOWNLOAD_COLLECTION_MESSAGE": "

Are you sure you want to download the complete album?

All files will be queued for download sequentially

", - "CREATE_ALBUM_FAILED": "Failed to create album , please try again", - "SEARCH": "Search", - "SEARCH_RESULTS": "Search results", - "NO_RESULTS": "No results found", - "SEARCH_HINT": "Search for albums, dates, descriptions, ...", + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", "SEARCH_TYPE": { - "COLLECTION": "Album", - "LOCATION": "Location", - "CITY": "Location", - "DATE": "Date", - "FILE_NAME": "File name", - "THING": "Content", - "FILE_CAPTION": "Description", - "FILE_TYPE": "File type", - "CLIP": "Magic" + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" }, - "photos_count_zero": "No memories", - "photos_count_one": "1 memory", - "photos_count_other": "{{count, number}} memories", - "TERMS_AND_CONDITIONS": "I agree to the terms and privacy policy", - "ADD_TO_COLLECTION": "Add to album", - "SELECTED": "selected", - "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "This video cannot be played on your browser", - "PEOPLE": "People", - "INDEXING_SCHEDULED": "Indexing is scheduled...", - "ANALYZING_PHOTOS": "Indexing photos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", - "INDEXING_PEOPLE": "Indexing people in {{indexStatus.nSyncedFiles,number}} photos...", - "INDEXING_DONE": "Indexed {{indexStatus.nSyncedFiles,number}} photos", - "UNIDENTIFIED_FACES": "unidentified faces", - "OBJECTS": "objects", - "TEXT": "text", - "INFO": "Info ", - "INFO_OPTION": "Info (I)", - "FILE_NAME": "File name", - "CAPTION_PLACEHOLDER": "Add a description", - "LOCATION": "Location", - "SHOW_ON_MAP": "View on OpenStreetMap", - "MAP": "Map", - "MAP_SETTINGS": "Map Settings", - "ENABLE_MAPS": "Enable Maps?", - "ENABLE_MAP": "Enable map", - "DISABLE_MAPS": "Disable Maps?", - "ENABLE_MAP_DESCRIPTION": "

This will show your photos on a world map.

The map is hosted by OpenStreetMap, and the exact locations of your photos are never shared.

You can disable this feature anytime from Settings.

", - "DISABLE_MAP_DESCRIPTION": "

This will disable the display of your photos on a world map.

You can enable this feature anytime from Settings.

", - "DISABLE_MAP": "Disable map", - "DETAILS": "Details", - "VIEW_EXIF": "View all EXIF data", - "NO_EXIF": "No EXIF data", - "EXIF": "EXIF", - "ISO": "ISO", - "TWO_FACTOR": "Two-factor", - "TWO_FACTOR_AUTHENTICATION": "Two-factor authentication", - "TWO_FACTOR_QR_INSTRUCTION": "Scan the QR code below with your favorite authenticator app", - "ENTER_CODE_MANUALLY": "Enter the code manually", - "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Please enter this code in your favorite authenticator app", - "SCAN_QR_CODE": "Scan QR code instead", - "ENABLE_TWO_FACTOR": "Enable two-factor", - "ENABLE": "Enable", - "LOST_DEVICE": "Lost two-factor device", - "INCORRECT_CODE": "Incorrect code", - "TWO_FACTOR_INFO": "Add an additional layer of security by requiring more than your email and password to log in to your account", - "DISABLE_TWO_FACTOR_LABEL": "Disable two-factor authentication", - "UPDATE_TWO_FACTOR_LABEL": "Update your authenticator device", - "DISABLE": "Disable", - "RECONFIGURE": "Reconfigure", - "UPDATE_TWO_FACTOR": "Update two-factor", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuing forward will void any previously configured authenticators", - "UPDATE": "Update", - "DISABLE_TWO_FACTOR": "Disable two-factor", - "DISABLE_TWO_FACTOR_MESSAGE": "Are you sure you want to disable your two-factor authentication", - "TWO_FACTOR_DISABLE_FAILED": "Failed to disable two factor, please try again", - "EXPORT_DATA": "Export data", - "SELECT_FOLDER": "Select folder", - "DESTINATION": "Destination", - "START": "Start", - "LAST_EXPORT_TIME": "Last export time", - "EXPORT_AGAIN": "Resync", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "Local storage not accessible", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Your browser or an addon is blocking ente from saving data into local storage. please try loading this page after switching your browsing mode.", - "SEND_OTT": "Send OTP", - "EMAIl_ALREADY_OWNED": "Email already taken", - "ETAGS_BLOCKED": "

We were unable to upload the following files because of your browser configuration.

Please disable any addons that might be preventing ente from using eTags to upload large files, or use our desktop app for a more reliable import experience.

", - "SKIPPED_VIDEOS_INFO": "

Presently we do not support adding videos via public links.

To share videos, please signup for ente and share with the intended recipients using their email.

", - "LIVE_PHOTOS_DETECTED": "The photo and video files from your Live Photos have been merged into a single file", - "RETRY_FAILED": "Retry failed uploads", - "FAILED_UPLOADS": "Failed uploads ", - "SKIPPED_FILES": "Ignored uploads", - "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Thumbnail generation failed", - "UNSUPPORTED_FILES": "Unsupported files", - "SUCCESSFUL_UPLOADS": "Successful uploads", - "SKIPPED_INFO": "Skipped these as there are files with matching names in the same album", - "UNSUPPORTED_INFO": "ente does not support these file formats yet", - "BLOCKED_UPLOADS": "Blocked uploads", - "SKIPPED_VIDEOS": "Skipped videos", - "INPROGRESS_METADATA_EXTRACTION": "In progress", - "INPROGRESS_UPLOADS": "Uploads in progress", - "TOO_LARGE_UPLOADS": "Large files", - "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Insufficient storage", - "LARGER_THAN_AVAILABLE_STORAGE_INFO": "These files were not uploaded as they exceed the maximum size limit for your storage plan", - "TOO_LARGE_INFO": "These files were not uploaded as they exceed our maximum file size limit", - "THUMBNAIL_GENERATION_FAILED_INFO": "These files were uploaded, but unfortunately we could not generate the thumbnails for them.", - "UPLOAD_TO_COLLECTION": "Upload to album", - "UNCATEGORIZED": "Uncategorized", - "ARCHIVE": "Archive", - "FAVORITES": "Favorites", - "ARCHIVE_COLLECTION": "Archive album", - "ARCHIVE_SECTION_NAME": "Archive", - "ALL_SECTION_NAME": "All", - "MOVE_TO_COLLECTION": "Move to album", - "UNARCHIVE": "Unarchive", - "UNARCHIVE_COLLECTION": "Unarchive album", - "HIDE_COLLECTION": "Hide album", - "UNHIDE_COLLECTION": "Unhide album", - "MOVE": "Move", - "ADD": "Add", - "REMOVE": "Remove", - "YES_REMOVE": "Yes, remove", - "REMOVE_FROM_COLLECTION": "Remove from album", - "TRASH": "Trash", - "MOVE_TO_TRASH": "Move to trash", - "TRASH_FILES_MESSAGE": "Selected files will be removed from all albums and moved to trash.", - "TRASH_FILE_MESSAGE": "The file will be removed from all albums and moved to trash.", - "DELETE_PERMANENTLY": "Delete permanently", - "RESTORE": "Restore", - "RESTORE_TO_COLLECTION": "Restore to album", - "EMPTY_TRASH": "Empty trash", - "EMPTY_TRASH_TITLE": "Empty trash?", - "EMPTY_TRASH_MESSAGE": "These files will be permanently deleted from your ente account.", - "LEAVE_SHARED_ALBUM": "Yes, leave", - "LEAVE_ALBUM": "Leave album", - "LEAVE_SHARED_ALBUM_TITLE": "Leave shared album?", - "LEAVE_SHARED_ALBUM_MESSAGE": "You will leave the album, and it will stop being visible to you.", - "NOT_FILE_OWNER": "You cannot delete files in a shared album", - "CONFIRM_SELF_REMOVE_MESSAGE": "Selected items will be removed from this album. Items which are only in this album will be moved to Uncategorized.", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Some of the items you are removing were added by other people, and you will lose access to them.", - "SORT_BY_CREATION_TIME_ASCENDING": "Oldest", - "SORT_BY_UPDATION_TIME_DESCENDING": "Last updated", - "SORT_BY_NAME": "Name", - "COMPRESS_THUMBNAILS": "Compress thumbnails", - "THUMBNAIL_REPLACED": "Thumbnails compressed", - "FIX_THUMBNAIL": "Compress", - "FIX_THUMBNAIL_LATER": "Compress later", - "REPLACE_THUMBNAIL_NOT_STARTED": "Some of your videos thumbnails can be compressed to save space. would you like ente to compress them?", - "REPLACE_THUMBNAIL_COMPLETED": "Successfully compressed all thumbnails", - "REPLACE_THUMBNAIL_NOOP": "You have no thumbnails that can be compressed further", - "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Could not compress some of your thumbnails, please retry", - "FIX_CREATION_TIME": "Fix time", - "FIX_CREATION_TIME_IN_PROGRESS": "Fixing time", - "CREATION_TIME_UPDATED": "File time updated", - "UPDATE_CREATION_TIME_NOT_STARTED": "Select the option you want to use", - "UPDATE_CREATION_TIME_COMPLETED": "Successfully updated all files", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "File time updation failed for some files, please retry", - "CAPTION_CHARACTER_LIMIT": "5000 characters max", - "DATE_TIME_ORIGINAL": "EXIF:DateTimeOriginal", - "DATE_TIME_DIGITIZED": "EXIF:DateTimeDigitized", - "METADATA_DATE": "EXIF:MetadataDate", - "CUSTOM_TIME": "Custom time", - "REOPEN_PLAN_SELECTOR_MODAL": "Re-open plans", - "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Failed to open plans", - "INSTALL": "Install", - "SHARING_DETAILS": "Sharing details", - "MODIFY_SHARING": "Modify sharing", - "ADD_COLLABORATORS": "Add collaborators", - "ADD_NEW_EMAIL": "Add a new email", - "shared_with_people_zero": "Share with specific people", - "shared_with_people_one": "Shared with 1 person", - "shared_with_people_other": "Shared with {{count, number}} people", - "participants_zero": "No participants", - "participants_one": "1 participant", - "participants_other": "{{count, number}} participants", - "ADD_VIEWERS": "Add viewers", - "PARTICIPANTS": "Participants", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} will not be able to add more photos to the album

They will still be able to remove photos added by them

", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} will be able to add photos to the album", - "CONVERT_TO_VIEWER": "Yes, convert to viewer", - "CONVERT_TO_COLLABORATOR": "Yes, convert to collaborator", - "CHANGE_PERMISSION": "Change permission?", - "REMOVE_PARTICIPANT": "Remove?", - "CONFIRM_REMOVE": "Yes, remove", - "MANAGE": "Manage", - "ADDED_AS": "Added as", - "COLLABORATOR_RIGHTS": "Collaborators can add photos and videos to the shared album", - "REMOVE_PARTICIPANT_HEAD": "Remove participant", - "OWNER": "Owner", - "COLLABORATORS": "Collaborators", - "ADD_MORE": "Add more", - "VIEWERS": "Viewers", - "OR_ADD_EXISTING": "Or pick an existing one", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} will be removed from the album

Any photos added by them will also be removed from the album

", - "NOT_FOUND": "404 - not found", - "LINK_EXPIRED": "Link expired", - "LINK_EXPIRED_MESSAGE": "This link has either expired or been disabled!", - "MANAGE_LINK": "Manage link", - "LINK_TOO_MANY_REQUESTS": "Sorry, this album has been viewed on too many devices!", - "FILE_DOWNLOAD": "Allow downloads", - "LINK_PASSWORD_LOCK": "Password lock", - "PUBLIC_COLLECT": "Allow adding photos", - "LINK_DEVICE_LIMIT": "Device limit", - "NO_DEVICE_LIMIT": "None", - "LINK_EXPIRY": "Link expiry", - "NEVER": "Never", - "DISABLE_FILE_DOWNLOAD": "Disable download", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Are you sure that you want to disable the download button for files?

Viewers can still take screenshots or save a copy of your photos using external tools.

", - "MALICIOUS_CONTENT": "Contains malicious content", - "COPYRIGHT": "Infringes on the copyright of someone I am authorized to represent", - "SHARED_USING": "Shared using ", - "ENTE_IO": "ente.io", - "SHARING_REFERRAL_CODE": "Use code {{referralCode}} to get 10 GB free", - "LIVE": "LIVE", - "DISABLE_PASSWORD": "Disable password lock", - "DISABLE_PASSWORD_MESSAGE": "Are you sure that you want to disable the password lock?", - "PASSWORD_LOCK": "Password lock", - "LOCK": "Lock", - "DOWNLOAD_UPLOAD_LOGS": "Debug logs", - "UPLOAD_FILES": "File", - "UPLOAD_DIRS": "Folder", - "UPLOAD_GOOGLE_TAKEOUT": "Google takeout", - "DEDUPLICATE_FILES": "Deduplicate files", - "AUTHENTICATOR_SECTION": "Authenticator", - "NO_DUPLICATES_FOUND": "You've no duplicate files that can be cleared", - "CLUB_BY_CAPTURE_TIME": "Club by capture time", - "FILES": "Files", - "EACH": "Each", - "DEDUPLICATE_BASED_ON_SIZE": "The following files were clubbed based on their sizes, please review and delete items you believe are duplicates", - "STOP_ALL_UPLOADS_MESSAGE": "Are you sure that you want to stop all the uploads in progress?", - "STOP_UPLOADS_HEADER": "Stop uploads?", - "YES_STOP_UPLOADS": "Yes, stop uploads", - "STOP_DOWNLOADS_HEADER": "Stop downloads?", - "YES_STOP_DOWNLOADS": "Yes, stop downloads", - "STOP_ALL_DOWNLOADS_MESSAGE": "Are you sure that you want to stop all the downloads in progress?", - "albums_one": "1 Album", - "albums_other": "{{count, number}} Albums", - "ALL_ALBUMS": "All Albums", - "ALBUMS": "Albums", - "ALL_HIDDEN_ALBUMS": "All hidden albums", - "HIDDEN_ALBUMS": "Hidden albums", - "HIDDEN_ITEMS": "Hidden items", - "HIDDEN_ITEMS_SECTION_NAME": "Hidden_items", - "ENTER_TWO_FACTOR_OTP": "Enter the 6-digit code from your authenticator app.", - "CREATE_ACCOUNT": "Create account", - "COPIED": "Copied", - "CANVAS_BLOCKED_TITLE": "Unable to generate thumbnail", - "CANVAS_BLOCKED_MESSAGE": "

It looks like your browser has disabled access to canvas, which is necessary to generate thumbnails for your photos

Please enable access to your browser's canvas, or check out our desktop app

", - "WATCH_FOLDERS": "Watch folders", - "UPGRADE_NOW": "Upgrade now", - "RENEW_NOW": "Renew now", - "STORAGE": "Storage", - "USED": "used", - "YOU": "You", - "FAMILY": "Family", - "FREE": "free", - "OF": "of", - "WATCHED_FOLDERS": "Watched folders", - "NO_FOLDERS_ADDED": "No folders added yet!", - "FOLDERS_AUTOMATICALLY_MONITORED": "The folders you add here will monitored to automatically", - "UPLOAD_NEW_FILES_TO_ENTE": "Upload new files to ente", - "REMOVE_DELETED_FILES_FROM_ENTE": "Remove deleted files from ente", - "ADD_FOLDER": "Add folder", - "STOP_WATCHING": "Stop watching", - "STOP_WATCHING_FOLDER": "Stop watching folder?", - "STOP_WATCHING_DIALOG_MESSAGE": "Your existing files will not be deleted, but ente will stop automatically updating the linked ente album on changes in this folder.", - "YES_STOP": "Yes, stop", - "MONTH_SHORT": "mo", - "YEAR": "year", - "FAMILY_PLAN": "Family plan", - "DOWNLOAD_LOGS": "Download logs", - "DOWNLOAD_LOGS_MESSAGE": "

This will download debug logs, which you can email to us to help debug your issue.

Please note that file names will be included to help track issues with specific files.

", - "CHANGE_FOLDER": "Change Folder", - "TWO_MONTHS_FREE": "Get 2 months free on yearly plans", - "GB": "GB", - "POPULAR": "Popular", - "FREE_PLAN_OPTION_LABEL": "Continue with free trial", - "FREE_PLAN_DESCRIPTION": "1 GB for 1 year", - "CURRENT_USAGE": "Current usage is {{usage}}", - "WEAK_DEVICE": "The web browser you're using is not powerful enough to encrypt your photos. Please try to log in to ente on your computer, or download the ente mobile/desktop app.", - "DRAG_AND_DROP_HINT": "Or drag and drop into the ente window", - "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Your uploaded data will be scheduled for deletion, and your account will be permanently deleted.

This action is not reversible.", - "AUTHENTICATE": "Authenticate", - "UPLOADED_TO_SINGLE_COLLECTION": "Uploaded to single collection", - "UPLOADED_TO_SEPARATE_COLLECTIONS": "Uploaded to separate collections", - "NEVERMIND": "Nevermind", - "UPDATE_AVAILABLE": "Update available", - "UPDATE_INSTALLABLE_MESSAGE": "A new version of ente is ready to be installed.", - "INSTALL_NOW": "Install now", - "INSTALL_ON_NEXT_LAUNCH": "Install on next launch", - "UPDATE_AVAILABLE_MESSAGE": "A new version of ente has been released, but it cannot be automatically downloaded and installed.", - "DOWNLOAD_AND_INSTALL": "Download and install", - "IGNORE_THIS_VERSION": "Ignore this version", - "TODAY": "Today", - "YESTERDAY": "Yesterday", - "NAME_PLACEHOLDER": "Name...", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Cannot create albums from file/folder mix", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

You have dragged and dropped a mixture of files and folders.

Please provide either only files, or only folders when selecting option to create separate albums

", - "CHOSE_THEME": "Choose theme", - "ML_SEARCH": "Face recognition", - "ENABLE_ML_SEARCH_DESCRIPTION": "

This will enable on-device machine learning and face search which will start analyzing your uploaded photos locally.

For the first run after login or enabling this feature, it will download all images on local device to analyze them. So please only enable this if you are ok with bandwidth and local processing of all images in your photo library.

If this is the first time you're enabling this, we'll also ask your permission to process face data.

", - "ML_MORE_DETAILS": "More details", - "ENABLE_FACE_SEARCH": "Enable face recognition", - "ENABLE_FACE_SEARCH_TITLE": "Enable face recognition?", - "ENABLE_FACE_SEARCH_DESCRIPTION": "

If you enable face recognition, ente will extract face geometry from your photos. This will happen on your device, and any generated biometric data will be end-to-encrypted.

Please click here for more details about this feature in our privacy policy

", - "DISABLE_BETA": "Pause recognition", - "DISABLE_FACE_SEARCH": "Disable face recognition", - "DISABLE_FACE_SEARCH_TITLE": "Disable face recognition?", - "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente will stop processing face geometry.

You can reenable face recognition again if you wish, so this operation is safe.

", - "ADVANCED": "Advanced", - "FACE_SEARCH_CONFIRMATION": "I understand, and wish to allow ente to process face geometry", - "LABS": "Labs", - "YOURS": "yours", - "PASSPHRASE_STRENGTH_WEAK": "Password strength: Weak", - "PASSPHRASE_STRENGTH_MODERATE": "Password strength: Moderate", - "PASSPHRASE_STRENGTH_STRONG": "Password strength: Strong", - "PREFERENCES": "Preferences", - "LANGUAGE": "Language", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Invalid export directory", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

The export directory you have selected does not exist.

Please select a valid directory.

", - "SUBSCRIPTION_VERIFICATION_ERROR": "Subscription verification failed", + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", "STORAGE_UNITS": { - "B": "B", - "KB": "KB", - "MB": "MB", - "GB": "GB", - "TB": "TB" + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" }, "AFTER_TIME": { - "HOUR": "after an hour", - "DAY": "after a day", - "WEEK": "after a week", - "MONTH": "after a month", - "YEAR": "after a year" + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" }, - "COPY_LINK": "Copy link", - "DONE": "Done", - "LINK_SHARE_TITLE": "Or share a link", - "REMOVE_LINK": "Remove link", - "CREATE_PUBLIC_SHARING": "Create public link", - "PUBLIC_LINK_CREATED": "Public link created", - "PUBLIC_LINK_ENABLED": "Public link enabled", - "COLLECT_PHOTOS": "Collect photos", - "PUBLIC_COLLECT_SUBTEXT": "Allow people with the link to also add photos to the shared album.", - "STOP_EXPORT": "Stop", - "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} items synced", - "MIGRATING_EXPORT": "Preparing...", - "RENAMING_COLLECTION_FOLDERS": "Renaming album folders...", - "TRASHING_DELETED_FILES": "Trashing deleted files...", - "TRASHING_DELETED_COLLECTIONS": "Trashing deleted albums...", + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", "EXPORT_NOTIFICATION": { - "START": "Export started", - "IN_PROGRESS": "Export already in progress", - "FINISH": "Export finished", - "UP_TO_DATE": "No new files to export" + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" }, - "CONTINUOUS_EXPORT": "Sync continuously", - "TOTAL_ITEMS": "Total items", - "PENDING_ITEMS": "Pending items", - "EXPORT_STARTING": "Export starting...", - "DELETE_ACCOUNT_REASON_LABEL": "What is the main reason you are deleting your account?", - "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Select a reason", + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", "DELETE_REASON": { - "MISSING_FEATURE": "It's missing a key feature that I need", - "BROKEN_BEHAVIOR": "The app or a certain feature does not behave as I think it should", - "FOUND_ANOTHER_SERVICE": "I found another service that I like better", - "NOT_LISTED": "My reason isn't listed" + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" }, - "DELETE_ACCOUNT_FEEDBACK_LABEL": "We are sorry to see you go. Please explain why you are leaving to help us improve.", - "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Feedback", - "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Yes, I want to permanently delete this account and all its data", - "CONFIRM_DELETE_ACCOUNT": "Confirm Account Deletion", - "FEEDBACK_REQUIRED": "Kindly help us with this information", - "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "What does the other service do better?", - "RECOVER_TWO_FACTOR": "Recover two-factor", - "at": "at", - "AUTH_NEXT": "next", - "AUTH_DOWNLOAD_MOBILE_APP": "Download our mobile app to manage your secrets", - "HIDDEN": "Hidden", - "HIDE": "Hide", - "UNHIDE": "Unhide", - "UNHIDE_TO_COLLECTION": "Unhide to album", - "SORT_BY": "Sort by", - "NEWEST_FIRST": "Newest first", - "OLDEST_FIRST": "Oldest first", - "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "This file could not be previewed. Click here to download the original.", - "SELECT_COLLECTION": "Select album", - "PIN_ALBUM": "Pin album", - "UNPIN_ALBUM": "Unpin album", - "DOWNLOAD_COMPLETE": "Download complete", - "DOWNLOADING_COLLECTION": "Downloading {{name}}", - "DOWNLOAD_FAILED": "Download failed", - "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", - "CHRISTMAS": "Christmas", - "CHRISTMAS_EVE": "Christmas Eve", - "NEW_YEAR": "New Year", - "NEW_YEAR_EVE": "New Year's Eve", - "IMAGE": "Image", - "VIDEO": "Video", - "LIVE_PHOTO": "Live Photo", - "CONVERT": "Convert", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Are you sure you want to close the editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Download your edited image or save a copy to ente to persist your changes.", - "BRIGHTNESS": "Brightness", - "CONTRAST": "Contrast", - "SATURATION": "Saturation", - "BLUR": "Blur", - "INVERT_COLORS": "Invert Colors", - "ASPECT_RATIO": "Aspect Ratio", - "SQUARE": "Square", - "ROTATE_LEFT": "Rotate Left", - "ROTATE_RIGHT": "Rotate Right", - "FLIP_VERTICALLY": "Flip Vertically", - "FLIP_HORIZONTALLY": "Flip Horizontally", - "DOWNLOAD_EDITED": "Download Edited", - "SAVE_A_COPY_TO_ENTE": "Save a copy to ente", - "RESTORE_ORIGINAL": "Restore Original", - "TRANSFORM": "Transform", - "COLORS": "Colors", - "FLIP": "Flip", - "ROTATION": "Rotation", - "RESET": "Reset", - "PHOTO_EDITOR": "Photo Editor", - "FASTER_UPLOAD": "Faster uploads", - "FASTER_UPLOAD_DESCRIPTION": "Route uploads through nearby servers", - "MAGIC_SEARCH_STATUS": "Magic Search Status", - "INDEXED_ITEMS": "Indexed items", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", - "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", - "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/fi-FI/translation.json b/web/apps/auth/public/locales/fi-FI/translation.json index 6870df3194..888ed7093e 100644 --- a/web/apps/auth/public/locales/fi-FI/translation.json +++ b/web/apps/auth/public/locales/fi-FI/translation.json @@ -1,644 +1,654 @@ { - "HERO_SLIDE_1_TITLE": "
Private backups
for your memories
", - "HERO_SLIDE_1": "End-to-end encrypted by default", - "HERO_SLIDE_2_TITLE": "
Safely stored
at a fallout shelter
", - "HERO_SLIDE_2": "Designed to outlive", - "HERO_SLIDE_3_TITLE": "
Available
everywhere
", - "HERO_SLIDE_3": "Android, iOS, Web, Desktop", - "LOGIN": "Login", - "SIGN_UP": "Signup", - "NEW_USER": "New to ente", - "EXISTING_USER": "Existing user", - "ENTER_NAME": "Enter name", - "PUBLIC_UPLOADER_NAME_MESSAGE": "Add a name so that your friends know who to thank for these great photos!", - "ENTER_EMAIL": "Enter email address", - "EMAIL_ERROR": "Enter a valid email", - "REQUIRED": "Required", - "EMAIL_SENT": "Verification code sent to {{email}}", - "CHECK_INBOX": "Please check your inbox (and spam) to complete verification", - "ENTER_OTT": "Verification code", - "RESEND_MAIL": "Resend code", - "VERIFY": "Verify", - "UNKNOWN_ERROR": "Something went wrong, please try again", - "INVALID_CODE": "Invalid verification code", - "EXPIRED_CODE": "Your verification code has expired", - "SENDING": "Sending...", - "SENT": "Sent!", - "PASSWORD": "Password", - "LINK_PASSWORD": "Enter password to unlock the album", - "RETURN_PASSPHRASE_HINT": "Password", - "SET_PASSPHRASE": "Set password", - "VERIFY_PASSPHRASE": "Sign in", - "INCORRECT_PASSPHRASE": "Incorrect password", - "ENTER_ENC_PASSPHRASE": "Please enter a password that we can use to encrypt your data", - "PASSPHRASE_DISCLAIMER": "We don't store your password, so if you forget it, we will not be able to help you recover your data without a recovery key.", - "WELCOME_TO_ENTE_HEADING": "Welcome to ", - "WELCOME_TO_ENTE_SUBHEADING": "End to end encrypted photo storage and sharing", - "WHERE_YOUR_BEST_PHOTOS_LIVE": "Where your best photos live", - "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generating encryption keys...", - "PASSPHRASE_HINT": "Password", - "CONFIRM_PASSPHRASE": "Confirm password", - "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", - "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", - "PASSPHRASE_MATCH_ERROR": "Passwords don't match", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "This is a browser feature intended for developers. Please don't copy-paste unverified code here.", - "CREATE_COLLECTION": "New album", - "ENTER_ALBUM_NAME": "Album name", - "CLOSE_OPTION": "Close (Esc)", - "ENTER_FILE_NAME": "File name", - "CLOSE": "Close", - "NO": "No", - "NOTHING_HERE": "Nothing to see here yet 👀", - "UPLOAD": "Upload", - "IMPORT": "Import", - "ADD_PHOTOS": "Add photos", - "ADD_MORE_PHOTOS": "Add more photos", - "add_photos_one": "Add 1 item", - "add_photos_other": "Add {{count, number}} items", - "SELECT_PHOTOS": "Select photos", - "FILE_UPLOAD": "File Upload", + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", "UPLOAD_STAGE_MESSAGE": { - "0": "Preparing to upload", - "1": "Reading google metadata files", - "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files metadata extracted", - "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files processed", - "4": "Cancelling remaining uploads", - "5": "Backup complete" + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" }, - "FILE_NOT_UPLOADED_LIST": "The following files were not uploaded", - "SUBSCRIPTION_EXPIRED": "Subscription expired", - "SUBSCRIPTION_EXPIRED_MESSAGE": "Your subscription has expired, please renew", - "STORAGE_QUOTA_EXCEEDED": "Storage limit exceeded", - "INITIAL_LOAD_DELAY_WARNING": "First load may take some time", - "USER_DOES_NOT_EXIST": "Sorry, could not find a user with that email", - "NO_ACCOUNT": "Don't have an account", - "ACCOUNT_EXISTS": "Already have an account", - "CREATE": "Create", - "DOWNLOAD": "Download", - "DOWNLOAD_OPTION": "Download (D)", - "DOWNLOAD_FAVORITES": "Download favorites", - "DOWNLOAD_UNCATEGORIZED": "Download uncategorized", - "DOWNLOAD_HIDDEN_ITEMS": "Download hidden items", - "COPY_OPTION": "Copy as PNG (Ctrl/Cmd - C)", - "TOGGLE_FULLSCREEN": "Toggle fullscreen (F)", - "ZOOM_IN_OUT": "Zoom in/out", - "PREVIOUS": "Previous (←)", - "NEXT": "Next (→)", - "TITLE_PHOTOS": "Ente Photos", - "TITLE_ALBUMS": "Ente Photos", - "TITLE_AUTH": "Ente Auth", - "UPLOAD_FIRST_PHOTO": "Upload your first photo", - "IMPORT_YOUR_FOLDERS": "Import your folders", - "UPLOAD_DROPZONE_MESSAGE": "Drop to backup your files", - "WATCH_FOLDER_DROPZONE_MESSAGE": "Drop to add watched folder", - "TRASH_FILES_TITLE": "Delete files?", - "TRASH_FILE_TITLE": "Delete file?", - "DELETE_FILES_TITLE": "Delete immediately?", - "DELETE_FILES_MESSAGE": "Selected files will be permanently deleted from your ente account.", - "DELETE": "Delete", - "DELETE_OPTION": "Delete (DEL)", - "FAVORITE_OPTION": "Favorite (L)", - "UNFAVORITE_OPTION": "Unfavorite (L)", - "MULTI_FOLDER_UPLOAD": "Multiple folders detected", - "UPLOAD_STRATEGY_CHOICE": "Would you like to upload them into", - "UPLOAD_STRATEGY_SINGLE_COLLECTION": "A single album", - "OR": "or", - "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Separate albums", - "SESSION_EXPIRED_MESSAGE": "Your session has expired, please login again to continue", - "SESSION_EXPIRED": "Session expired", - "PASSWORD_GENERATION_FAILED": "Your browser was unable to generate a strong key that meets ente's encryption standards, please try using the mobile app or another browser", - "CHANGE_PASSWORD": "Change password", - "GO_BACK": "Go back", - "RECOVERY_KEY": "Recovery key", - "SAVE_LATER": "Do this later", - "SAVE": "Save Key", - "RECOVERY_KEY_DESCRIPTION": "If you forget your password, the only way you can recover your data is with this key.", - "RECOVER_KEY_GENERATION_FAILED": "Recovery code could not be generated, please try again", - "KEY_NOT_STORED_DISCLAIMER": "We don't store this key, so please save this in a safe place", - "FORGOT_PASSWORD": "Forgot password", - "RECOVER_ACCOUNT": "Recover account", - "RECOVERY_KEY_HINT": "Recovery key", - "RECOVER": "Recover", - "NO_RECOVERY_KEY": "No recovery key?", - "INCORRECT_RECOVERY_KEY": "Incorrect recovery key", - "SORRY": "Sorry", - "NO_RECOVERY_KEY_MESSAGE": "Due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Please drop an email to {{emailID}} from your registered email address", - "CONTACT_SUPPORT": "Contact support", - "REQUEST_FEATURE": "Request Feature", - "SUPPORT": "Support", - "CONFIRM": "Confirm", - "CANCEL": "Cancel", - "LOGOUT": "Logout", - "DELETE_ACCOUNT": "Delete account", - "DELETE_ACCOUNT_MESSAGE": "

Please send an email to {{emailID}} from your registered email address.

Your request will be processed within 72 hours.

", - "LOGOUT_MESSAGE": "Are you sure you want to logout?", - "CHANGE_EMAIL": "Change email", - "OK": "OK", - "SUCCESS": "Success", - "ERROR": "Error", - "MESSAGE": "Message", - "INSTALL_MOBILE_APP": "Install our Android or iOS app to automatically backup all your photos", - "DOWNLOAD_APP_MESSAGE": "Sorry, this operation is currently only supported on our desktop app", - "DOWNLOAD_APP": "Download desktop app", - "EXPORT": "Export Data", - "SUBSCRIPTION": "Subscription", - "SUBSCRIBE": "Subscribe", - "MANAGEMENT_PORTAL": "Manage payment method", - "MANAGE_FAMILY_PORTAL": "Manage family", - "LEAVE_FAMILY_PLAN": "Leave family plan", - "LEAVE": "Leave", - "LEAVE_FAMILY_CONFIRM": "Are you sure that you want to leave family plan?", - "CHOOSE_PLAN": "Choose your plan", - "MANAGE_PLAN": "Manage your subscription", - "ACTIVE": "Active", - "OFFLINE_MSG": "You are offline, cached memories are being shown", - "FREE_SUBSCRIPTION_INFO": "You are on the free plan that expires on {{date, dateTime}}", - "FAMILY_SUBSCRIPTION_INFO": "You are on a family plan managed by", - "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Renews on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Ends on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Your subscription will be cancelled on {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", - "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "You have exceeded your storage quota, please upgrade", - "SUBSCRIPTION_PURCHASE_SUCCESS": "

We've received your payment

Your subscription is valid till {{date, dateTime}}

", - "SUBSCRIPTION_PURCHASE_CANCELLED": "Your purchase was canceled, please try again if you want to subscribe", - "SUBSCRIPTION_PURCHASE_FAILED": "Subscription purchase failed , please try again", - "SUBSCRIPTION_UPDATE_FAILED": "Subscription updated failed , please try again", - "UPDATE_PAYMENT_METHOD_MESSAGE": "We are sorry, payment failed when we tried to charge your card, please update your payment method and try again", - "STRIPE_AUTHENTICATION_FAILED": "We are unable to authenticate your payment method. please choose a different payment method and try again", - "UPDATE_PAYMENT_METHOD": "Update payment method", - "MONTHLY": "Monthly", - "YEARLY": "Yearly", - "UPDATE_SUBSCRIPTION_MESSAGE": "Are you sure you want to change your plan?", - "UPDATE_SUBSCRIPTION": "Change plan", - "CANCEL_SUBSCRIPTION": "Cancel subscription", - "CANCEL_SUBSCRIPTION_MESSAGE": "

All of your data will be deleted from our servers at the end of this billing period.

Are you sure that you want to cancel your subscription?

", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

", - "SUBSCRIPTION_CANCEL_FAILED": "Failed to cancel subscription", - "SUBSCRIPTION_CANCEL_SUCCESS": "Subscription canceled successfully", - "REACTIVATE_SUBSCRIPTION": "Reactivate subscription", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "Once reactivated, you will be billed on {{date, dateTime}}", - "SUBSCRIPTION_ACTIVATE_SUCCESS": "Subscription activated successfully ", - "SUBSCRIPTION_ACTIVATE_FAILED": "Failed to reactivate subscription renewals", - "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Thank you", - "CANCEL_SUBSCRIPTION_ON_MOBILE": "Cancel mobile subscription", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Please cancel your subscription from the mobile app to activate a subscription here", - "MAIL_TO_MANAGE_SUBSCRIPTION": "Please contact us at {{emailID}} to manage your subscription", - "RENAME": "Rename", - "RENAME_FILE": "Rename file", - "RENAME_COLLECTION": "Rename album", - "DELETE_COLLECTION_TITLE": "Delete album?", - "DELETE_COLLECTION": "Delete album", - "DELETE_COLLECTION_MESSAGE": "Also delete the photos (and videos) present in this album from all other albums they are part of?", - "DELETE_PHOTOS": "Delete photos", - "KEEP_PHOTOS": "Keep photos", - "SHARE": "Share", - "SHARE_COLLECTION": "Share album", - "SHAREES": "Shared with", - "SHARE_WITH_SELF": "Oops, you cannot share with yourself", - "ALREADY_SHARED": "Oops, you're already sharing this with {{email}}", - "SHARING_BAD_REQUEST_ERROR": "Sharing album not allowed", - "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Sharing is disabled for free accounts", - "DOWNLOAD_COLLECTION": "Download album", - "DOWNLOAD_COLLECTION_MESSAGE": "

Are you sure you want to download the complete album?

All files will be queued for download sequentially

", - "CREATE_ALBUM_FAILED": "Failed to create album , please try again", - "SEARCH": "Search", - "SEARCH_RESULTS": "Search results", - "NO_RESULTS": "No results found", - "SEARCH_HINT": "Search for albums, dates, descriptions, ...", + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", "SEARCH_TYPE": { - "COLLECTION": "Album", - "LOCATION": "Location", - "CITY": "Location", - "DATE": "Date", - "FILE_NAME": "File name", - "THING": "Content", - "FILE_CAPTION": "Description", - "FILE_TYPE": "File type", - "CLIP": "Magic" + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" }, - "photos_count_zero": "No memories", - "photos_count_one": "1 memory", - "photos_count_other": "{{count, number}} memories", - "TERMS_AND_CONDITIONS": "I agree to the terms and privacy policy", - "ADD_TO_COLLECTION": "Add to album", - "SELECTED": "selected", - "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "This video cannot be played on your browser", - "PEOPLE": "People", - "INDEXING_SCHEDULED": "Indexing is scheduled...", - "ANALYZING_PHOTOS": "Indexing photos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", - "INDEXING_PEOPLE": "Indexing people in {{indexStatus.nSyncedFiles,number}} photos...", - "INDEXING_DONE": "Indexed {{indexStatus.nSyncedFiles,number}} photos", - "UNIDENTIFIED_FACES": "unidentified faces", - "OBJECTS": "objects", - "TEXT": "text", - "INFO": "Info ", - "INFO_OPTION": "Info (I)", - "FILE_NAME": "File name", - "CAPTION_PLACEHOLDER": "Add a description", - "LOCATION": "Location", - "SHOW_ON_MAP": "View on OpenStreetMap", - "MAP": "Map", - "MAP_SETTINGS": "Map Settings", - "ENABLE_MAPS": "Enable Maps?", - "ENABLE_MAP": "Enable map", - "DISABLE_MAPS": "Disable Maps?", - "ENABLE_MAP_DESCRIPTION": "

This will show your photos on a world map.

The map is hosted by OpenStreetMap, and the exact locations of your photos are never shared.

You can disable this feature anytime from Settings.

", - "DISABLE_MAP_DESCRIPTION": "

This will disable the display of your photos on a world map.

You can enable this feature anytime from Settings.

", - "DISABLE_MAP": "Disable map", - "DETAILS": "Details", - "VIEW_EXIF": "View all EXIF data", - "NO_EXIF": "No EXIF data", - "EXIF": "EXIF", - "ISO": "ISO", - "TWO_FACTOR": "Two-factor", - "TWO_FACTOR_AUTHENTICATION": "Two-factor authentication", - "TWO_FACTOR_QR_INSTRUCTION": "Scan the QR code below with your favorite authenticator app", - "ENTER_CODE_MANUALLY": "Enter the code manually", - "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Please enter this code in your favorite authenticator app", - "SCAN_QR_CODE": "Scan QR code instead", - "ENABLE_TWO_FACTOR": "Enable two-factor", - "ENABLE": "Enable", - "LOST_DEVICE": "Lost two-factor device", - "INCORRECT_CODE": "Incorrect code", - "TWO_FACTOR_INFO": "Add an additional layer of security by requiring more than your email and password to log in to your account", - "DISABLE_TWO_FACTOR_LABEL": "Disable two-factor authentication", - "UPDATE_TWO_FACTOR_LABEL": "Update your authenticator device", - "DISABLE": "Disable", - "RECONFIGURE": "Reconfigure", - "UPDATE_TWO_FACTOR": "Update two-factor", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuing forward will void any previously configured authenticators", - "UPDATE": "Update", - "DISABLE_TWO_FACTOR": "Disable two-factor", - "DISABLE_TWO_FACTOR_MESSAGE": "Are you sure you want to disable your two-factor authentication", - "TWO_FACTOR_DISABLE_FAILED": "Failed to disable two factor, please try again", - "EXPORT_DATA": "Export data", - "SELECT_FOLDER": "Select folder", - "DESTINATION": "Destination", - "START": "Start", - "LAST_EXPORT_TIME": "Last export time", - "EXPORT_AGAIN": "Resync", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "Local storage not accessible", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Your browser or an addon is blocking ente from saving data into local storage. please try loading this page after switching your browsing mode.", - "SEND_OTT": "Send OTP", - "EMAIl_ALREADY_OWNED": "Email already taken", - "ETAGS_BLOCKED": "

We were unable to upload the following files because of your browser configuration.

Please disable any addons that might be preventing ente from using eTags to upload large files, or use our desktop app for a more reliable import experience.

", - "SKIPPED_VIDEOS_INFO": "

Presently we do not support adding videos via public links.

To share videos, please signup for ente and share with the intended recipients using their email.

", - "LIVE_PHOTOS_DETECTED": "The photo and video files from your Live Photos have been merged into a single file", - "RETRY_FAILED": "Retry failed uploads", - "FAILED_UPLOADS": "Failed uploads ", - "SKIPPED_FILES": "Ignored uploads", - "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Thumbnail generation failed", - "UNSUPPORTED_FILES": "Unsupported files", - "SUCCESSFUL_UPLOADS": "Successful uploads", - "SKIPPED_INFO": "Skipped these as there are files with matching names in the same album", - "UNSUPPORTED_INFO": "ente does not support these file formats yet", - "BLOCKED_UPLOADS": "Blocked uploads", - "SKIPPED_VIDEOS": "Skipped videos", - "INPROGRESS_METADATA_EXTRACTION": "In progress", - "INPROGRESS_UPLOADS": "Uploads in progress", - "TOO_LARGE_UPLOADS": "Large files", - "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Insufficient storage", - "LARGER_THAN_AVAILABLE_STORAGE_INFO": "These files were not uploaded as they exceed the maximum size limit for your storage plan", - "TOO_LARGE_INFO": "These files were not uploaded as they exceed our maximum file size limit", - "THUMBNAIL_GENERATION_FAILED_INFO": "These files were uploaded, but unfortunately we could not generate the thumbnails for them.", - "UPLOAD_TO_COLLECTION": "Upload to album", - "UNCATEGORIZED": "Uncategorized", - "ARCHIVE": "Archive", - "FAVORITES": "Favorites", - "ARCHIVE_COLLECTION": "Archive album", - "ARCHIVE_SECTION_NAME": "Archive", - "ALL_SECTION_NAME": "All", - "MOVE_TO_COLLECTION": "Move to album", - "UNARCHIVE": "Unarchive", - "UNARCHIVE_COLLECTION": "Unarchive album", - "HIDE_COLLECTION": "Hide album", - "UNHIDE_COLLECTION": "Unhide album", - "MOVE": "Move", - "ADD": "Add", - "REMOVE": "Remove", - "YES_REMOVE": "Yes, remove", - "REMOVE_FROM_COLLECTION": "Remove from album", - "TRASH": "Trash", - "MOVE_TO_TRASH": "Move to trash", - "TRASH_FILES_MESSAGE": "Selected files will be removed from all albums and moved to trash.", - "TRASH_FILE_MESSAGE": "The file will be removed from all albums and moved to trash.", - "DELETE_PERMANENTLY": "Delete permanently", - "RESTORE": "Restore", - "RESTORE_TO_COLLECTION": "Restore to album", - "EMPTY_TRASH": "Empty trash", - "EMPTY_TRASH_TITLE": "Empty trash?", - "EMPTY_TRASH_MESSAGE": "These files will be permanently deleted from your ente account.", - "LEAVE_SHARED_ALBUM": "Yes, leave", - "LEAVE_ALBUM": "Leave album", - "LEAVE_SHARED_ALBUM_TITLE": "Leave shared album?", - "LEAVE_SHARED_ALBUM_MESSAGE": "You will leave the album, and it will stop being visible to you.", - "NOT_FILE_OWNER": "You cannot delete files in a shared album", - "CONFIRM_SELF_REMOVE_MESSAGE": "Selected items will be removed from this album. Items which are only in this album will be moved to Uncategorized.", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Some of the items you are removing were added by other people, and you will lose access to them.", - "SORT_BY_CREATION_TIME_ASCENDING": "Oldest", - "SORT_BY_UPDATION_TIME_DESCENDING": "Last updated", - "SORT_BY_NAME": "Name", - "COMPRESS_THUMBNAILS": "Compress thumbnails", - "THUMBNAIL_REPLACED": "Thumbnails compressed", - "FIX_THUMBNAIL": "Compress", - "FIX_THUMBNAIL_LATER": "Compress later", - "REPLACE_THUMBNAIL_NOT_STARTED": "Some of your videos thumbnails can be compressed to save space. would you like ente to compress them?", - "REPLACE_THUMBNAIL_COMPLETED": "Successfully compressed all thumbnails", - "REPLACE_THUMBNAIL_NOOP": "You have no thumbnails that can be compressed further", - "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Could not compress some of your thumbnails, please retry", - "FIX_CREATION_TIME": "Fix time", - "FIX_CREATION_TIME_IN_PROGRESS": "Fixing time", - "CREATION_TIME_UPDATED": "File time updated", - "UPDATE_CREATION_TIME_NOT_STARTED": "Select the option you want to use", - "UPDATE_CREATION_TIME_COMPLETED": "Successfully updated all files", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "File time updation failed for some files, please retry", - "CAPTION_CHARACTER_LIMIT": "5000 characters max", - "DATE_TIME_ORIGINAL": "EXIF:DateTimeOriginal", - "DATE_TIME_DIGITIZED": "EXIF:DateTimeDigitized", - "METADATA_DATE": "EXIF:MetadataDate", - "CUSTOM_TIME": "Custom time", - "REOPEN_PLAN_SELECTOR_MODAL": "Re-open plans", - "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Failed to open plans", - "INSTALL": "Install", - "SHARING_DETAILS": "Sharing details", - "MODIFY_SHARING": "Modify sharing", - "ADD_COLLABORATORS": "Add collaborators", - "ADD_NEW_EMAIL": "Add a new email", - "shared_with_people_zero": "Share with specific people", - "shared_with_people_one": "Shared with 1 person", - "shared_with_people_other": "Shared with {{count, number}} people", - "participants_zero": "No participants", - "participants_one": "1 participant", - "participants_other": "{{count, number}} participants", - "ADD_VIEWERS": "Add viewers", - "PARTICIPANTS": "Participants", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} will not be able to add more photos to the album

They will still be able to remove photos added by them

", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} will be able to add photos to the album", - "CONVERT_TO_VIEWER": "Yes, convert to viewer", - "CONVERT_TO_COLLABORATOR": "Yes, convert to collaborator", - "CHANGE_PERMISSION": "Change permission?", - "REMOVE_PARTICIPANT": "Remove?", - "CONFIRM_REMOVE": "Yes, remove", - "MANAGE": "Manage", - "ADDED_AS": "Added as", - "COLLABORATOR_RIGHTS": "Collaborators can add photos and videos to the shared album", - "REMOVE_PARTICIPANT_HEAD": "Remove participant", - "OWNER": "Owner", - "COLLABORATORS": "Collaborators", - "ADD_MORE": "Add more", - "VIEWERS": "Viewers", - "OR_ADD_EXISTING": "Or pick an existing one", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} will be removed from the album

Any photos added by them will also be removed from the album

", - "NOT_FOUND": "404 - not found", - "LINK_EXPIRED": "Link expired", - "LINK_EXPIRED_MESSAGE": "This link has either expired or been disabled!", - "MANAGE_LINK": "Manage link", - "LINK_TOO_MANY_REQUESTS": "Sorry, this album has been viewed on too many devices!", - "FILE_DOWNLOAD": "Allow downloads", - "LINK_PASSWORD_LOCK": "Password lock", - "PUBLIC_COLLECT": "Allow adding photos", - "LINK_DEVICE_LIMIT": "Device limit", - "NO_DEVICE_LIMIT": "None", - "LINK_EXPIRY": "Link expiry", - "NEVER": "Never", - "DISABLE_FILE_DOWNLOAD": "Disable download", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Are you sure that you want to disable the download button for files?

Viewers can still take screenshots or save a copy of your photos using external tools.

", - "MALICIOUS_CONTENT": "Contains malicious content", - "COPYRIGHT": "Infringes on the copyright of someone I am authorized to represent", - "SHARED_USING": "Shared using ", - "ENTE_IO": "ente.io", - "SHARING_REFERRAL_CODE": "Use code {{referralCode}} to get 10 GB free", - "LIVE": "LIVE", - "DISABLE_PASSWORD": "Disable password lock", - "DISABLE_PASSWORD_MESSAGE": "Are you sure that you want to disable the password lock?", - "PASSWORD_LOCK": "Password lock", - "LOCK": "Lock", - "DOWNLOAD_UPLOAD_LOGS": "Debug logs", - "UPLOAD_FILES": "File", - "UPLOAD_DIRS": "Folder", - "UPLOAD_GOOGLE_TAKEOUT": "Google takeout", - "DEDUPLICATE_FILES": "Deduplicate files", - "AUTHENTICATOR_SECTION": "Authenticator", - "NO_DUPLICATES_FOUND": "You've no duplicate files that can be cleared", - "CLUB_BY_CAPTURE_TIME": "Club by capture time", - "FILES": "Files", - "EACH": "Each", - "DEDUPLICATE_BASED_ON_SIZE": "The following files were clubbed based on their sizes, please review and delete items you believe are duplicates", - "STOP_ALL_UPLOADS_MESSAGE": "Are you sure that you want to stop all the uploads in progress?", - "STOP_UPLOADS_HEADER": "Stop uploads?", - "YES_STOP_UPLOADS": "Yes, stop uploads", - "STOP_DOWNLOADS_HEADER": "Stop downloads?", - "YES_STOP_DOWNLOADS": "Yes, stop downloads", - "STOP_ALL_DOWNLOADS_MESSAGE": "Are you sure that you want to stop all the downloads in progress?", - "albums_one": "1 Album", - "albums_other": "{{count, number}} Albums", - "ALL_ALBUMS": "All Albums", - "ALBUMS": "Albums", - "ALL_HIDDEN_ALBUMS": "All hidden albums", - "HIDDEN_ALBUMS": "Hidden albums", - "HIDDEN_ITEMS": "Hidden items", - "HIDDEN_ITEMS_SECTION_NAME": "Hidden_items", - "ENTER_TWO_FACTOR_OTP": "Enter the 6-digit code from your authenticator app.", - "CREATE_ACCOUNT": "Create account", - "COPIED": "Copied", - "CANVAS_BLOCKED_TITLE": "Unable to generate thumbnail", - "CANVAS_BLOCKED_MESSAGE": "

It looks like your browser has disabled access to canvas, which is necessary to generate thumbnails for your photos

Please enable access to your browser's canvas, or check out our desktop app

", - "WATCH_FOLDERS": "Watch folders", - "UPGRADE_NOW": "Upgrade now", - "RENEW_NOW": "Renew now", - "STORAGE": "Storage", - "USED": "used", - "YOU": "You", - "FAMILY": "Family", - "FREE": "free", - "OF": "of", - "WATCHED_FOLDERS": "Watched folders", - "NO_FOLDERS_ADDED": "No folders added yet!", - "FOLDERS_AUTOMATICALLY_MONITORED": "The folders you add here will monitored to automatically", - "UPLOAD_NEW_FILES_TO_ENTE": "Upload new files to ente", - "REMOVE_DELETED_FILES_FROM_ENTE": "Remove deleted files from ente", - "ADD_FOLDER": "Add folder", - "STOP_WATCHING": "Stop watching", - "STOP_WATCHING_FOLDER": "Stop watching folder?", - "STOP_WATCHING_DIALOG_MESSAGE": "Your existing files will not be deleted, but ente will stop automatically updating the linked ente album on changes in this folder.", - "YES_STOP": "Yes, stop", - "MONTH_SHORT": "mo", - "YEAR": "year", - "FAMILY_PLAN": "Family plan", - "DOWNLOAD_LOGS": "Download logs", - "DOWNLOAD_LOGS_MESSAGE": "

This will download debug logs, which you can email to us to help debug your issue.

Please note that file names will be included to help track issues with specific files.

", - "CHANGE_FOLDER": "Change Folder", - "TWO_MONTHS_FREE": "Get 2 months free on yearly plans", - "GB": "GB", - "POPULAR": "Popular", - "FREE_PLAN_OPTION_LABEL": "Continue with free trial", - "FREE_PLAN_DESCRIPTION": "1 GB for 1 year", - "CURRENT_USAGE": "Current usage is {{usage}}", - "WEAK_DEVICE": "The web browser you're using is not powerful enough to encrypt your photos. Please try to log in to ente on your computer, or download the ente mobile/desktop app.", - "DRAG_AND_DROP_HINT": "Or drag and drop into the ente window", - "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Your uploaded data will be scheduled for deletion, and your account will be permanently deleted.

This action is not reversible.", - "AUTHENTICATE": "Authenticate", - "UPLOADED_TO_SINGLE_COLLECTION": "Uploaded to single collection", - "UPLOADED_TO_SEPARATE_COLLECTIONS": "Uploaded to separate collections", - "NEVERMIND": "Nevermind", - "UPDATE_AVAILABLE": "Update available", - "UPDATE_INSTALLABLE_MESSAGE": "A new version of ente is ready to be installed.", - "INSTALL_NOW": "Install now", - "INSTALL_ON_NEXT_LAUNCH": "Install on next launch", - "UPDATE_AVAILABLE_MESSAGE": "A new version of ente has been released, but it cannot be automatically downloaded and installed.", - "DOWNLOAD_AND_INSTALL": "Download and install", - "IGNORE_THIS_VERSION": "Ignore this version", - "TODAY": "Today", - "YESTERDAY": "Yesterday", - "NAME_PLACEHOLDER": "Name...", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Cannot create albums from file/folder mix", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

You have dragged and dropped a mixture of files and folders.

Please provide either only files, or only folders when selecting option to create separate albums

", - "CHOSE_THEME": "Choose theme", - "ML_SEARCH": "Face recognition", - "ENABLE_ML_SEARCH_DESCRIPTION": "

This will enable on-device machine learning and face search which will start analyzing your uploaded photos locally.

For the first run after login or enabling this feature, it will download all images on local device to analyze them. So please only enable this if you are ok with bandwidth and local processing of all images in your photo library.

If this is the first time you're enabling this, we'll also ask your permission to process face data.

", - "ML_MORE_DETAILS": "More details", - "ENABLE_FACE_SEARCH": "Enable face recognition", - "ENABLE_FACE_SEARCH_TITLE": "Enable face recognition?", - "ENABLE_FACE_SEARCH_DESCRIPTION": "

If you enable face recognition, ente will extract face geometry from your photos. This will happen on your device, and any generated biometric data will be end-to-encrypted.

Please click here for more details about this feature in our privacy policy

", - "DISABLE_BETA": "Pause recognition", - "DISABLE_FACE_SEARCH": "Disable face recognition", - "DISABLE_FACE_SEARCH_TITLE": "Disable face recognition?", - "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente will stop processing face geometry.

You can reenable face recognition again if you wish, so this operation is safe.

", - "ADVANCED": "Advanced", - "FACE_SEARCH_CONFIRMATION": "I understand, and wish to allow ente to process face geometry", - "LABS": "Labs", - "YOURS": "yours", - "PASSPHRASE_STRENGTH_WEAK": "Password strength: Weak", - "PASSPHRASE_STRENGTH_MODERATE": "Password strength: Moderate", - "PASSPHRASE_STRENGTH_STRONG": "Password strength: Strong", - "PREFERENCES": "Preferences", - "LANGUAGE": "Language", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Invalid export directory", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

The export directory you have selected does not exist.

Please select a valid directory.

", - "SUBSCRIPTION_VERIFICATION_ERROR": "Subscription verification failed", + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", "STORAGE_UNITS": { - "B": "B", - "KB": "KB", - "MB": "MB", - "GB": "GB", - "TB": "TB" + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" }, "AFTER_TIME": { - "HOUR": "after an hour", - "DAY": "after a day", - "WEEK": "after a week", - "MONTH": "after a month", - "YEAR": "after a year" + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" }, - "COPY_LINK": "Copy link", - "DONE": "Done", - "LINK_SHARE_TITLE": "Or share a link", - "REMOVE_LINK": "Remove link", - "CREATE_PUBLIC_SHARING": "Create public link", - "PUBLIC_LINK_CREATED": "Public link created", - "PUBLIC_LINK_ENABLED": "Public link enabled", - "COLLECT_PHOTOS": "Collect photos", - "PUBLIC_COLLECT_SUBTEXT": "Allow people with the link to also add photos to the shared album.", - "STOP_EXPORT": "Stop", - "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} items synced", - "MIGRATING_EXPORT": "Preparing...", - "RENAMING_COLLECTION_FOLDERS": "Renaming album folders...", - "TRASHING_DELETED_FILES": "Trashing deleted files...", - "TRASHING_DELETED_COLLECTIONS": "Trashing deleted albums...", + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", "EXPORT_NOTIFICATION": { - "START": "Export started", - "IN_PROGRESS": "Export already in progress", - "FINISH": "Export finished", - "UP_TO_DATE": "No new files to export" + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" }, - "CONTINUOUS_EXPORT": "Sync continuously", - "TOTAL_ITEMS": "Total items", - "PENDING_ITEMS": "Pending items", - "EXPORT_STARTING": "Export starting...", - "DELETE_ACCOUNT_REASON_LABEL": "What is the main reason you are deleting your account?", - "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Select a reason", + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", "DELETE_REASON": { - "MISSING_FEATURE": "It's missing a key feature that I need", - "BROKEN_BEHAVIOR": "The app or a certain feature does not behave as I think it should", - "FOUND_ANOTHER_SERVICE": "I found another service that I like better", - "NOT_LISTED": "My reason isn't listed" + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" }, - "DELETE_ACCOUNT_FEEDBACK_LABEL": "We are sorry to see you go. Please explain why you are leaving to help us improve.", - "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Feedback", - "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Yes, I want to permanently delete this account and all its data", - "CONFIRM_DELETE_ACCOUNT": "Confirm Account Deletion", - "FEEDBACK_REQUIRED": "Kindly help us with this information", - "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "What does the other service do better?", - "RECOVER_TWO_FACTOR": "Recover two-factor", - "at": "at", - "AUTH_NEXT": "next", - "AUTH_DOWNLOAD_MOBILE_APP": "Download our mobile app to manage your secrets", - "HIDDEN": "Hidden", - "HIDE": "Hide", - "UNHIDE": "Unhide", - "UNHIDE_TO_COLLECTION": "Unhide to album", - "SORT_BY": "Sort by", - "NEWEST_FIRST": "Newest first", - "OLDEST_FIRST": "Oldest first", - "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "This file could not be previewed. Click here to download the original.", - "SELECT_COLLECTION": "Select album", - "PIN_ALBUM": "Pin album", - "UNPIN_ALBUM": "Unpin album", - "DOWNLOAD_COMPLETE": "Download complete", - "DOWNLOADING_COLLECTION": "Downloading {{name}}", - "DOWNLOAD_FAILED": "Download failed", - "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", - "CHRISTMAS": "Christmas", - "CHRISTMAS_EVE": "Christmas Eve", - "NEW_YEAR": "New Year", - "NEW_YEAR_EVE": "New Year's Eve", - "IMAGE": "Image", - "VIDEO": "Video", - "LIVE_PHOTO": "Live Photo", - "CONVERT": "Convert", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Are you sure you want to close the editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Download your edited image or save a copy to ente to persist your changes.", - "BRIGHTNESS": "Brightness", - "CONTRAST": "Contrast", - "SATURATION": "Saturation", - "BLUR": "Blur", - "INVERT_COLORS": "Invert Colors", - "ASPECT_RATIO": "Aspect Ratio", - "SQUARE": "Square", - "ROTATE_LEFT": "Rotate Left", - "ROTATE_RIGHT": "Rotate Right", - "FLIP_VERTICALLY": "Flip Vertically", - "FLIP_HORIZONTALLY": "Flip Horizontally", - "DOWNLOAD_EDITED": "Download Edited", - "SAVE_A_COPY_TO_ENTE": "Save a copy to ente", - "RESTORE_ORIGINAL": "Restore Original", - "TRANSFORM": "Transform", - "COLORS": "Colors", - "FLIP": "Flip", - "ROTATION": "Rotation", - "RESET": "Reset", - "PHOTO_EDITOR": "Photo Editor", - "FASTER_UPLOAD": "Faster uploads", - "FASTER_UPLOAD_DESCRIPTION": "Route uploads through nearby servers", - "MAGIC_SEARCH_STATUS": "Magic Search Status", - "INDEXED_ITEMS": "Indexed items", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", - "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", - "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/fr-FR/translation.json b/web/apps/auth/public/locales/fr-FR/translation.json index b94bc3973f..43d9590691 100644 --- a/web/apps/auth/public/locales/fr-FR/translation.json +++ b/web/apps/auth/public/locales/fr-FR/translation.json @@ -38,11 +38,9 @@ "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Génération des clés de chiffrement...", "PASSPHRASE_HINT": "Mot de passe", "CONFIRM_PASSPHRASE": "Confirmer le mot de passe", - "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", - "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", + "REFERRAL_CODE_HINT": "Comment avez-vous entendu parler de Ente? (facultatif)", + "REFERRAL_INFO": "Nous ne suivons pas les installations d'applications. Il serait utile que vous nous disiez comment vous nous avez trouvés !", "PASSPHRASE_MATCH_ERROR": "Les mots de passe ne correspondent pas", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "Ceci est une fonction de navigateur dédiée aux développeurs. Veuillez ne pas copier-coller un code non vérifié à cet endroit.", "CREATE_COLLECTION": "Nouvel album", "ENTER_ALBUM_NAME": "Nom de l'album", "CLOSE_OPTION": "Fermer (Échap)", @@ -159,7 +157,7 @@ "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Renouveler le {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Pris fin le {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Votre abonnement sera annulé le {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "Votre module {{storage, string}} est valable jusqu'au {{date, dateTime}}", "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Vous avez dépassé votre quota de stockage, veuillez mettre à niveau ", "SUBSCRIPTION_PURCHASE_SUCCESS": "

Nous avons reçu votre paiement

Votre abonnement est valide jusqu'au {{date, dateTime}}

", "SUBSCRIPTION_PURCHASE_CANCELLED": "Votre achat est annulé, veuillez réessayer si vous souhaitez vous abonner", @@ -174,7 +172,7 @@ "UPDATE_SUBSCRIPTION": "Changer de plan", "CANCEL_SUBSCRIPTION": "Annuler l'abonnement", "CANCEL_SUBSCRIPTION_MESSAGE": "

Toutes vos données seront supprimées de nos serveurs à la fin de cette période d'abonnement.

Voulez-vous vraiment annuler votre abonnement?

", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "Êtes-vous sûr de vouloir annuler votre abonnement ", "SUBSCRIPTION_CANCEL_FAILED": "Échec lors de l'annulation de l'abonnement", "SUBSCRIPTION_CANCEL_SUCCESS": "Votre abonnement a bien été annulé", "REACTIVATE_SUBSCRIPTION": "Réactiver l'abonnement", @@ -210,7 +208,7 @@ "SEARCH_TYPE": { "COLLECTION": "l'album", "LOCATION": "Emplacement", - "CITY": "Location", + "CITY": "Adresse", "DATE": "Date", "FILE_NAME": "Nom de fichier", "THING": "Chose", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Téléchargement de {{name}}", "DOWNLOAD_FAILED": "Échec du téléchargement", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} fichiers", - "CRASH_REPORTING": "Rapport de plantage", "CHRISTMAS": "Noël", "CHRISTMAS_EVE": "Réveillon de Noël", "NEW_YEAR": "Nouvel an", @@ -623,22 +620,35 @@ "PHOTO_EDITOR": "Éditeur de photos", "FASTER_UPLOAD": "Chargements plus rapides", "FASTER_UPLOAD_DESCRIPTION": "Router les chargements vers les serveurs à proximité", - "MAGIC_SEARCH_STATUS": "Magic Search Status", + "MAGIC_SEARCH_STATUS": "Statut de la recherche magique", "INDEXED_ITEMS": "Éléments indexés", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", - "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", - "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "CAST_ALBUM_TO_TV": "Jouer l'album sur la TV", + "ENTER_CAST_PIN_CODE": "Entrez le code que vous voyez sur la TV ci-dessous pour appairer cet appareil.", + "PAIR_DEVICE_TO_TV": "Associer les appareils", + "TV_NOT_FOUND": "TV introuvable. Avez-vous entré le code PIN correctement ?", + "AUTO_CAST_PAIR": "Paire automatique", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "La paire automatique nécessite la connexion aux serveurs Google et ne fonctionne qu'avec les appareils pris en charge par Chromecast. Google ne recevra pas de données sensibles, telles que vos photos.", + "PAIR_WITH_PIN": "Associer avec le code PIN", + "CHOOSE_DEVICE_FROM_BROWSER": "Choisissez un périphérique compatible avec la caste à partir de la fenêtre pop-up du navigateur.", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "L'association avec le code PIN fonctionne pour tout appareil grand écran sur lequel vous voulez lire votre album.", + "VISIT_CAST_ENTE_IO": "Visitez cast.ente.io sur l'appareil que vous voulez associer.", + "CAST_AUTO_PAIR_FAILED": "La paire automatique de Chromecast a échoué. Veuillez réessayer.", + "CACHE_DIRECTORY": "Dossier du cache", + "FREEHAND": "Main levée", + "APPLY_CROP": "Appliquer le recadrage", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Au moins une transformation ou un ajustement de couleur doit être effectué avant de sauvegarder.", + "PASSKEYS": "Clés d'accès", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/it-IT/translation.json b/web/apps/auth/public/locales/it-IT/translation.json index 679478f703..ae450e5fef 100644 --- a/web/apps/auth/public/locales/it-IT/translation.json +++ b/web/apps/auth/public/locales/it-IT/translation.json @@ -39,10 +39,8 @@ "PASSPHRASE_HINT": "Password", "CONFIRM_PASSPHRASE": "Conferma la password", "REFERRAL_CODE_HINT": "Come hai conosciuto Ente? (opzionale)", - "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", + "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "Le password non corrispondono", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "Questa è una funzionalità del browser destinata agli sviluppatori. Non copiare né incollare codice non verificato qui.", "CREATE_COLLECTION": "Nuovo album", "ENTER_ALBUM_NAME": "Nome album", "CLOSE_OPTION": "Chiudi (Esc)", @@ -85,9 +83,9 @@ "ZOOM_IN_OUT": "Zoom in/out", "PREVIOUS": "Precedente (←)", "NEXT": "Successivo (→)", - "TITLE_PHOTOS": "Ente Photos", - "TITLE_ALBUMS": "Ente Photos", - "TITLE_AUTH": "Ente Auth", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", "UPLOAD_FIRST_PHOTO": "Carica la tua prima foto", "IMPORT_YOUR_FOLDERS": "Importa una cartella", "UPLOAD_DROPZONE_MESSAGE": "Rilascia per eseguire il backup dei file", @@ -159,7 +157,7 @@ "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Si rinnova il {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Termina il {{date, dateTime}}", "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Il tuo abbonamento verrà annullato il {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "", "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Hai superato la quota di archiviazione assegnata, si prega di aggiornare ", "SUBSCRIPTION_PURCHASE_SUCCESS": "

Abbiamo ricevuto il tuo pagamento

Il tuo abbonamento è valido fino a {{date, dateTime}}

", "SUBSCRIPTION_PURCHASE_CANCELLED": "Il tuo acquisto è stato annullato, riprova se vuoi iscriverti", @@ -174,23 +172,23 @@ "UPDATE_SUBSCRIPTION": "Cambia piano", "CANCEL_SUBSCRIPTION": "Annulla abbonamento", "CANCEL_SUBSCRIPTION_MESSAGE": "

Tutti i tuoi dati saranno cancellati dai nostri server alla fine di questo periodo di fatturazione.

Sei sicuro di voler annullare il tuo abbonamento?

", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", "SUBSCRIPTION_CANCEL_FAILED": "Impossibile annullare l'abbonamento", "SUBSCRIPTION_CANCEL_SUCCESS": "Abbonamento annullato con successo", "REACTIVATE_SUBSCRIPTION": "Riattiva abbonamento", "REACTIVATE_SUBSCRIPTION_MESSAGE": "Una volta riattivato, ti verrà addebitato il valore di {{date, dateTime}}", "SUBSCRIPTION_ACTIVATE_SUCCESS": "Iscrizione attivata con successo ", - "SUBSCRIPTION_ACTIVATE_FAILED": "Failed to reactivate subscription renewals", + "SUBSCRIPTION_ACTIVATE_FAILED": "", "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Grazie", "CANCEL_SUBSCRIPTION_ON_MOBILE": "Annulla abbonamento mobile", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Please cancel your subscription from the mobile app to activate a subscription here", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", "MAIL_TO_MANAGE_SUBSCRIPTION": "Per favore contattaci su {{emailID}} per gestire il tuo abbonamento", "RENAME": "Rinomina", "RENAME_FILE": "Rinomina file", "RENAME_COLLECTION": "Rinomina album", "DELETE_COLLECTION_TITLE": "Eliminare l'album?", "DELETE_COLLECTION": "Elimina album", - "DELETE_COLLECTION_MESSAGE": "Also delete the photos (and videos) present in this album from all other albums they are part of?", + "DELETE_COLLECTION_MESSAGE": "", "DELETE_PHOTOS": "Elimina foto", "KEEP_PHOTOS": "Mantieni foto", "SHARE": "Condividi", @@ -205,8 +203,8 @@ "CREATE_ALBUM_FAILED": "Operazione di creazione dell'album fallita, per favore riprova", "SEARCH": "Ricerca", "SEARCH_RESULTS": "Risultati della ricerca", - "NO_RESULTS": "No results found", - "SEARCH_HINT": "Search for albums, dates, descriptions, ...", + "NO_RESULTS": "", + "SEARCH_HINT": "", "SEARCH_TYPE": { "COLLECTION": "Album", "LOCATION": "Posizione", @@ -216,25 +214,25 @@ "THING": "Contenuto", "FILE_CAPTION": "Descrizione", "FILE_TYPE": "Tipo del file", - "CLIP": "Magic" + "CLIP": "" }, "photos_count_zero": "Nessuna memoria", - "photos_count_one": "1 memory", - "photos_count_other": "{{count, number}} memories", - "TERMS_AND_CONDITIONS": "I agree to the terms and privacy policy", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", "ADD_TO_COLLECTION": "Aggiungi all'album", - "SELECTED": "selected", + "SELECTED": "", "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Questo video non può essere riprodotto nel tuo browser", "PEOPLE": "Persone", - "INDEXING_SCHEDULED": "Indexing is scheduled...", - "ANALYZING_PHOTOS": "Indexing photos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", - "INDEXING_PEOPLE": "Indexing people in {{indexStatus.nSyncedFiles,number}} photos...", - "INDEXING_DONE": "Indexed {{indexStatus.nSyncedFiles,number}} photos", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", "UNIDENTIFIED_FACES": "volti non identificati", - "OBJECTS": "objects", + "OBJECTS": "", "TEXT": "testo", "INFO": "Info ", - "INFO_OPTION": "Info (I)", + "INFO_OPTION": "", "FILE_NAME": "Nome file", "CAPTION_PLACEHOLDER": "Aggiungi una descrizione", "LOCATION": "Posizione", @@ -244,12 +242,12 @@ "ENABLE_MAPS": "Attivare Mappa?", "ENABLE_MAP": "Attivare mappa", "DISABLE_MAPS": "Disattivare Mappa?", - "ENABLE_MAP_DESCRIPTION": "

This will show your photos on a world map.

The map is hosted by OpenStreetMap, and the exact locations of your photos are never shared.

You can disable this feature anytime from Settings.

", - "DISABLE_MAP_DESCRIPTION": "

This will disable the display of your photos on a world map.

You can enable this feature anytime from Settings.

", - "DISABLE_MAP": "Disable map", - "DETAILS": "Details", - "VIEW_EXIF": "View all EXIF data", - "NO_EXIF": "No EXIF data", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", "EXIF": "EXIF", "ISO": "ISO", "TWO_FACTOR": "Due fattori", @@ -260,41 +258,41 @@ "SCAN_QR_CODE": "Oppure scansiona il codice QR", "ENABLE_TWO_FACTOR": "Attiva due fattori", "ENABLE": "Attiva", - "LOST_DEVICE": "Lost two-factor device", + "LOST_DEVICE": "", "INCORRECT_CODE": "Codice errato", "TWO_FACTOR_INFO": "Aggiungi un ulteriore livello di sicurezza richiedendo più informazioni rispetto a email e password per eseguire l'accesso al tuo account", - "DISABLE_TWO_FACTOR_LABEL": "Disable two-factor authentication", - "UPDATE_TWO_FACTOR_LABEL": "Update your authenticator device", - "DISABLE": "Disable", - "RECONFIGURE": "Reconfigure", - "UPDATE_TWO_FACTOR": "Update two-factor", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuing forward will void any previously configured authenticators", - "UPDATE": "Update", - "DISABLE_TWO_FACTOR": "Disable two-factor", - "DISABLE_TWO_FACTOR_MESSAGE": "Are you sure you want to disable your two-factor authentication", - "TWO_FACTOR_DISABLE_FAILED": "Failed to disable two factor, please try again", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", "EXPORT_DATA": "Esporta dati", - "SELECT_FOLDER": "Select folder", - "DESTINATION": "Destination", - "START": "Start", - "LAST_EXPORT_TIME": "Last export time", - "EXPORT_AGAIN": "Resync", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "Local storage not accessible", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Your browser or an addon is blocking ente from saving data into local storage. please try loading this page after switching your browsing mode.", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", "SEND_OTT": "Invia OTP", "EMAIl_ALREADY_OWNED": "Email già in uso", - "ETAGS_BLOCKED": "

We were unable to upload the following files because of your browser configuration.

Please disable any addons that might be preventing ente from using eTags to upload large files, or use our desktop app for a more reliable import experience.

", - "SKIPPED_VIDEOS_INFO": "

Presently we do not support adding videos via public links.

To share videos, please signup for ente and share with the intended recipients using their email.

", - "LIVE_PHOTOS_DETECTED": "The photo and video files from your Live Photos have been merged into a single file", - "RETRY_FAILED": "Retry failed uploads", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", "FAILED_UPLOADS": "Caricamento fallito ", "SKIPPED_FILES": "Ignora caricamenti", - "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Thumbnail generation failed", - "UNSUPPORTED_FILES": "Unsupported files", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", "SUCCESSFUL_UPLOADS": "Caricamenti eseguiti con successo", - "SKIPPED_INFO": "Skipped these as there are files with matching names in the same album", - "UNSUPPORTED_INFO": "ente does not support these file formats yet", - "BLOCKED_UPLOADS": "Blocked uploads", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", "SKIPPED_VIDEOS": "Video saltati", "INPROGRESS_METADATA_EXTRACTION": "In corso", "INPROGRESS_UPLOADS": "Caricamenti in corso", @@ -302,9 +300,9 @@ "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Spazio insufficiente", "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Questi file non sono stati caricati perché supererebbero la capacità massima del tuo piano di spazio d'archiviazione", "TOO_LARGE_INFO": "Questi file non sono stati caricati perché superano il nostro limite di pesantezza di un file", - "THUMBNAIL_GENERATION_FAILED_INFO": "These files were uploaded, but unfortunately we could not generate the thumbnails for them.", - "UPLOAD_TO_COLLECTION": "Upload to album", - "UNCATEGORIZED": "Uncategorized", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", "ARCHIVE": "Archivio", "FAVORITES": "Preferiti", "ARCHIVE_COLLECTION": "Album archiviato", @@ -333,10 +331,10 @@ "LEAVE_SHARED_ALBUM": "Sì, esci", "LEAVE_ALBUM": "Abbandona l'album", "LEAVE_SHARED_ALBUM_TITLE": "Abbandonare l'album condiviso?", - "LEAVE_SHARED_ALBUM_MESSAGE": "You will leave the album, and it will stop being visible to you.", - "NOT_FILE_OWNER": "You cannot delete files in a shared album", - "CONFIRM_SELF_REMOVE_MESSAGE": "Selected items will be removed from this album. Items which are only in this album will be moved to Uncategorized.", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Some of the items you are removing were added by other people, and you will lose access to them.", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", "SORT_BY_CREATION_TIME_ASCENDING": "Meno recente", "SORT_BY_UPDATION_TIME_DESCENDING": "Ultimo aggiornamento", "SORT_BY_NAME": "Nome", @@ -344,180 +342,180 @@ "THUMBNAIL_REPLACED": "Miniature compresse", "FIX_THUMBNAIL": "Comprimi", "FIX_THUMBNAIL_LATER": "Comprimi più tardi", - "REPLACE_THUMBNAIL_NOT_STARTED": "Some of your videos thumbnails can be compressed to save space. would you like ente to compress them?", - "REPLACE_THUMBNAIL_COMPLETED": "Successfully compressed all thumbnails", - "REPLACE_THUMBNAIL_NOOP": "You have no thumbnails that can be compressed further", - "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Could not compress some of your thumbnails, please retry", - "FIX_CREATION_TIME": "Fix time", - "FIX_CREATION_TIME_IN_PROGRESS": "Fixing time", - "CREATION_TIME_UPDATED": "File time updated", - "UPDATE_CREATION_TIME_NOT_STARTED": "Select the option you want to use", - "UPDATE_CREATION_TIME_COMPLETED": "Successfully updated all files", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "File time updation failed for some files, please retry", - "CAPTION_CHARACTER_LIMIT": "5000 characters max", - "DATE_TIME_ORIGINAL": "EXIF:DateTimeOriginal", - "DATE_TIME_DIGITIZED": "EXIF:DateTimeDigitized", - "METADATA_DATE": "EXIF:MetadataDate", - "CUSTOM_TIME": "Custom time", - "REOPEN_PLAN_SELECTOR_MODAL": "Re-open plans", - "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Failed to open plans", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", "INSTALL": "Installa", - "SHARING_DETAILS": "Sharing details", - "MODIFY_SHARING": "Modify sharing", - "ADD_COLLABORATORS": "Add collaborators", - "ADD_NEW_EMAIL": "Add a new email", - "shared_with_people_zero": "Share with specific people", - "shared_with_people_one": "Shared with 1 person", - "shared_with_people_other": "Shared with {{count, number}} people", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", "participants_zero": "Nessun partecipante", "participants_one": "1 partecipante", "participants_other": "{{count, number}} partecipanti", - "ADD_VIEWERS": "Add viewers", + "ADD_VIEWERS": "", "PARTICIPANTS": "Partecipanti", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} will not be able to add more photos to the album

They will still be able to remove photos added by them

", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} will be able to add photos to the album", - "CONVERT_TO_VIEWER": "Yes, convert to viewer", - "CONVERT_TO_COLLABORATOR": "Yes, convert to collaborator", - "CHANGE_PERMISSION": "Change permission?", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", "REMOVE_PARTICIPANT": "Rimuovere?", "CONFIRM_REMOVE": "Sì, rimuovi", "MANAGE": "Gestisci", "ADDED_AS": "Aggiunto come", - "COLLABORATOR_RIGHTS": "Collaborators can add photos and videos to the shared album", + "COLLABORATOR_RIGHTS": "", "REMOVE_PARTICIPANT_HEAD": "Rimuovi partecipante", - "OWNER": "Owner", - "COLLABORATORS": "Collaborators", - "ADD_MORE": "Add more", - "VIEWERS": "Viewers", - "OR_ADD_EXISTING": "Or pick an existing one", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} will be removed from the album

Any photos added by them will also be removed from the album

", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", "NOT_FOUND": "404 - non trovato", "LINK_EXPIRED": "Link scaduto", - "LINK_EXPIRED_MESSAGE": "This link has either expired or been disabled!", - "MANAGE_LINK": "Manage link", - "LINK_TOO_MANY_REQUESTS": "Sorry, this album has been viewed on too many devices!", - "FILE_DOWNLOAD": "Allow downloads", - "LINK_PASSWORD_LOCK": "Password lock", - "PUBLIC_COLLECT": "Allow adding photos", - "LINK_DEVICE_LIMIT": "Device limit", - "NO_DEVICE_LIMIT": "None", - "LINK_EXPIRY": "Link expiry", - "NEVER": "Never", - "DISABLE_FILE_DOWNLOAD": "Disable download", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Are you sure that you want to disable the download button for files?

Viewers can still take screenshots or save a copy of your photos using external tools.

", - "MALICIOUS_CONTENT": "Contains malicious content", - "COPYRIGHT": "Infringes on the copyright of someone I am authorized to represent", - "SHARED_USING": "Shared using ", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", "ENTE_IO": "ente.io", - "SHARING_REFERRAL_CODE": "Use code {{referralCode}} to get 10 GB free", - "LIVE": "LIVE", - "DISABLE_PASSWORD": "Disable password lock", - "DISABLE_PASSWORD_MESSAGE": "Are you sure that you want to disable the password lock?", - "PASSWORD_LOCK": "Password lock", - "LOCK": "Lock", - "DOWNLOAD_UPLOAD_LOGS": "Debug logs", - "UPLOAD_FILES": "File", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", "UPLOAD_DIRS": "Cartella", - "UPLOAD_GOOGLE_TAKEOUT": "Google takeout", - "DEDUPLICATE_FILES": "Deduplicate files", - "AUTHENTICATOR_SECTION": "Authenticator", - "NO_DUPLICATES_FOUND": "You've no duplicate files that can be cleared", - "CLUB_BY_CAPTURE_TIME": "Club by capture time", - "FILES": "Files", - "EACH": "Each", - "DEDUPLICATE_BASED_ON_SIZE": "The following files were clubbed based on their sizes, please review and delete items you believe are duplicates", - "STOP_ALL_UPLOADS_MESSAGE": "Are you sure that you want to stop all the uploads in progress?", - "STOP_UPLOADS_HEADER": "Stop uploads?", - "YES_STOP_UPLOADS": "Yes, stop uploads", - "STOP_DOWNLOADS_HEADER": "Stop downloads?", - "YES_STOP_DOWNLOADS": "Yes, stop downloads", - "STOP_ALL_DOWNLOADS_MESSAGE": "Are you sure that you want to stop all the downloads in progress?", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", "albums_one": "1 Album", "albums_other": "{{count, number}} Album", "ALL_ALBUMS": "Tutti gli Album", "ALBUMS": "Album", - "ALL_HIDDEN_ALBUMS": "All hidden albums", - "HIDDEN_ALBUMS": "Hidden albums", - "HIDDEN_ITEMS": "Hidden items", - "HIDDEN_ITEMS_SECTION_NAME": "Hidden_items", - "ENTER_TWO_FACTOR_OTP": "Enter the 6-digit code from your authenticator app.", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", "CREATE_ACCOUNT": "Crea account", - "COPIED": "Copied", - "CANVAS_BLOCKED_TITLE": "Unable to generate thumbnail", - "CANVAS_BLOCKED_MESSAGE": "

It looks like your browser has disabled access to canvas, which is necessary to generate thumbnails for your photos

Please enable access to your browser's canvas, or check out our desktop app

", - "WATCH_FOLDERS": "Watch folders", - "UPGRADE_NOW": "Upgrade now", - "RENEW_NOW": "Renew now", - "STORAGE": "Storage", - "USED": "used", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", "YOU": "Tu", "FAMILY": "Famiglia", "FREE": "gratis", - "OF": "of", - "WATCHED_FOLDERS": "Watched folders", + "OF": "", + "WATCHED_FOLDERS": "", "NO_FOLDERS_ADDED": "Ancora nessuna cartella aggiunta!", - "FOLDERS_AUTOMATICALLY_MONITORED": "The folders you add here will monitored to automatically", - "UPLOAD_NEW_FILES_TO_ENTE": "Upload new files to ente", - "REMOVE_DELETED_FILES_FROM_ENTE": "Remove deleted files from ente", - "ADD_FOLDER": "Add folder", - "STOP_WATCHING": "Stop watching", - "STOP_WATCHING_FOLDER": "Stop watching folder?", - "STOP_WATCHING_DIALOG_MESSAGE": "Your existing files will not be deleted, but ente will stop automatically updating the linked ente album on changes in this folder.", - "YES_STOP": "Yes, stop", - "MONTH_SHORT": "mo", - "YEAR": "year", - "FAMILY_PLAN": "Family plan", - "DOWNLOAD_LOGS": "Download logs", - "DOWNLOAD_LOGS_MESSAGE": "

This will download debug logs, which you can email to us to help debug your issue.

Please note that file names will be included to help track issues with specific files.

", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", "CHANGE_FOLDER": "Cambia Cartella", "TWO_MONTHS_FREE": "Ottieni 2 mesi gratis sui piani annuali", "GB": "GB", - "POPULAR": "Popular", - "FREE_PLAN_OPTION_LABEL": "Continue with free trial", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", "FREE_PLAN_DESCRIPTION": "1 GB per 1 anno", - "CURRENT_USAGE": "Current usage is {{usage}}", - "WEAK_DEVICE": "The web browser you're using is not powerful enough to encrypt your photos. Please try to log in to ente on your computer, or download the ente mobile/desktop app.", - "DRAG_AND_DROP_HINT": "Or drag and drop into the ente window", - "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Your uploaded data will be scheduled for deletion, and your account will be permanently deleted.

This action is not reversible.", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", "AUTHENTICATE": "Autenticati", - "UPLOADED_TO_SINGLE_COLLECTION": "Uploaded to single collection", - "UPLOADED_TO_SEPARATE_COLLECTIONS": "Uploaded to separate collections", - "NEVERMIND": "Nevermind", - "UPDATE_AVAILABLE": "Update available", - "UPDATE_INSTALLABLE_MESSAGE": "A new version of ente is ready to be installed.", - "INSTALL_NOW": "Install now", - "INSTALL_ON_NEXT_LAUNCH": "Install on next launch", - "UPDATE_AVAILABLE_MESSAGE": "A new version of ente has been released, but it cannot be automatically downloaded and installed.", - "DOWNLOAD_AND_INSTALL": "Download and install", - "IGNORE_THIS_VERSION": "Ignore this version", + "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": "Oggi", "YESTERDAY": "Ieri", "NAME_PLACEHOLDER": "Nome...", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Cannot create albums from file/folder mix", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

You have dragged and dropped a mixture of files and folders.

Please provide either only files, or only folders when selecting option to create separate albums

", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", "CHOSE_THEME": "Seleziona tema", - "ML_SEARCH": "Face recognition", - "ENABLE_ML_SEARCH_DESCRIPTION": "

This will enable on-device machine learning and face search which will start analyzing your uploaded photos locally.

For the first run after login or enabling this feature, it will download all images on local device to analyze them. So please only enable this if you are ok with bandwidth and local processing of all images in your photo library.

If this is the first time you're enabling this, we'll also ask your permission to process face data.

", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", "ML_MORE_DETAILS": "Più dettagli", - "ENABLE_FACE_SEARCH": "Enable face recognition", - "ENABLE_FACE_SEARCH_TITLE": "Enable face recognition?", - "ENABLE_FACE_SEARCH_DESCRIPTION": "

If you enable face recognition, ente will extract face geometry from your photos. This will happen on your device, and any generated biometric data will be end-to-encrypted.

Please click here for more details about this feature in our privacy policy

", - "DISABLE_BETA": "Pause recognition", - "DISABLE_FACE_SEARCH": "Disable face recognition", - "DISABLE_FACE_SEARCH_TITLE": "Disable face recognition?", - "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente will stop processing face geometry.

You can reenable face recognition again if you wish, so this operation is safe.

", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", "ADVANCED": "Avanzate", - "FACE_SEARCH_CONFIRMATION": "I understand, and wish to allow ente to process face geometry", - "LABS": "Labs", - "YOURS": "yours", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", "PASSPHRASE_STRENGTH_WEAK": "Sicurezza password: Debole", "PASSPHRASE_STRENGTH_MODERATE": "Sicurezza password: Moderata", "PASSPHRASE_STRENGTH_STRONG": "Sicurezza password: Forte", - "PREFERENCES": "Preferences", + "PREFERENCES": "", "LANGUAGE": "Lingua", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Invalid export directory", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

The export directory you have selected does not exist.

Please select a valid directory.

", - "SUBSCRIPTION_VERIFICATION_ERROR": "Subscription verification failed", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", "STORAGE_UNITS": { "B": "B", "KB": "KB", @@ -539,106 +537,118 @@ "CREATE_PUBLIC_SHARING": "Crea link pubblico", "PUBLIC_LINK_CREATED": "Link pubblick creato", "PUBLIC_LINK_ENABLED": "Link pubblico attivato", - "COLLECT_PHOTOS": "Collect photos", - "PUBLIC_COLLECT_SUBTEXT": "Allow people with the link to also add photos to the shared album.", - "STOP_EXPORT": "Stop", - "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} items synced", - "MIGRATING_EXPORT": "Preparing...", - "RENAMING_COLLECTION_FOLDERS": "Renaming album folders...", - "TRASHING_DELETED_FILES": "Trashing deleted files...", - "TRASHING_DELETED_COLLECTIONS": "Trashing deleted albums...", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", "EXPORT_NOTIFICATION": { - "START": "Export started", - "IN_PROGRESS": "Export already in progress", - "FINISH": "Export finished", - "UP_TO_DATE": "No new files to export" + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" }, - "CONTINUOUS_EXPORT": "Sync continuously", - "TOTAL_ITEMS": "Total items", - "PENDING_ITEMS": "Pending items", - "EXPORT_STARTING": "Export starting...", - "DELETE_ACCOUNT_REASON_LABEL": "What is the main reason you are deleting your account?", + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Seleziona un motivo", "DELETE_REASON": { - "MISSING_FEATURE": "It's missing a key feature that I need", - "BROKEN_BEHAVIOR": "The app or a certain feature does not behave as I think it should", - "FOUND_ANOTHER_SERVICE": "I found another service that I like better", - "NOT_LISTED": "My reason isn't listed" + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" }, - "DELETE_ACCOUNT_FEEDBACK_LABEL": "We are sorry to see you go. Please explain why you are leaving to help us improve.", - "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Feedback", - "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Yes, I want to permanently delete this account and all its data", - "CONFIRM_DELETE_ACCOUNT": "Confirm Account Deletion", - "FEEDBACK_REQUIRED": "Kindly help us with this information", - "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "What does the other service do better?", - "RECOVER_TWO_FACTOR": "Recover two-factor", - "at": "at", - "AUTH_NEXT": "next", - "AUTH_DOWNLOAD_MOBILE_APP": "Download our mobile app to manage your secrets", - "HIDDEN": "Hidden", - "HIDE": "Hide", - "UNHIDE": "Unhide", - "UNHIDE_TO_COLLECTION": "Unhide to album", - "SORT_BY": "Sort by", - "NEWEST_FIRST": "Newest first", - "OLDEST_FIRST": "Oldest first", - "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "This file could not be previewed. Click here to download the original.", - "SELECT_COLLECTION": "Select album", - "PIN_ALBUM": "Pin album", - "UNPIN_ALBUM": "Unpin album", - "DOWNLOAD_COMPLETE": "Download complete", - "DOWNLOADING_COLLECTION": "Downloading {{name}}", - "DOWNLOAD_FAILED": "Download failed", - "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", - "CHRISTMAS": "Christmas", - "CHRISTMAS_EVE": "Christmas Eve", - "NEW_YEAR": "New Year", - "NEW_YEAR_EVE": "New Year's Eve", - "IMAGE": "Image", - "VIDEO": "Video", - "LIVE_PHOTO": "Live Photo", - "CONVERT": "Convert", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Are you sure you want to close the editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Download your edited image or save a copy to ente to persist your changes.", - "BRIGHTNESS": "Brightness", - "CONTRAST": "Contrast", - "SATURATION": "Saturation", - "BLUR": "Blur", - "INVERT_COLORS": "Invert Colors", - "ASPECT_RATIO": "Aspect Ratio", - "SQUARE": "Square", - "ROTATE_LEFT": "Rotate Left", - "ROTATE_RIGHT": "Rotate Right", - "FLIP_VERTICALLY": "Flip Vertically", - "FLIP_HORIZONTALLY": "Flip Horizontally", - "DOWNLOAD_EDITED": "Download Edited", - "SAVE_A_COPY_TO_ENTE": "Save a copy to ente", - "RESTORE_ORIGINAL": "Restore Original", - "TRANSFORM": "Transform", - "COLORS": "Colors", - "FLIP": "Flip", - "ROTATION": "Rotation", - "RESET": "Reset", - "PHOTO_EDITOR": "Photo Editor", - "FASTER_UPLOAD": "Faster uploads", - "FASTER_UPLOAD_DESCRIPTION": "Route uploads through nearby servers", - "MAGIC_SEARCH_STATUS": "Magic Search Status", - "INDEXED_ITEMS": "Indexed items", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", - "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", - "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/ko-KR/translation.json b/web/apps/auth/public/locales/ko-KR/translation.json new file mode 100644 index 0000000000..4fbe6c0777 --- /dev/null +++ b/web/apps/auth/public/locales/ko-KR/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "추억을 안전하게 백업하세요", + "HERO_SLIDE_1": "종단간 암호화가 기본지원입니다", + "HERO_SLIDE_2_TITLE": "낙진대피소에 안전하게 보관됩니다", + "HERO_SLIDE_2": "오랫동안 보존할 수 있도록한 설계", + "HERO_SLIDE_3_TITLE": "
어디에서나
이용가능
", + "HERO_SLIDE_3": "안드로이드, iOS, 웹, 데스크탑", + "LOGIN": "로그인", + "SIGN_UP": "회원가입", + "NEW_USER": "ente의 새소식", + "EXISTING_USER": "기존 사용자", + "ENTER_NAME": "이름 입력", + "PUBLIC_UPLOADER_NAME_MESSAGE": "친구들이 이 멋진 사진에 대해 고마워할 수 있도록 이름을 추가하세요!", + "ENTER_EMAIL": "이메일 주소를 입력하세요", + "EMAIL_ERROR": "올바른 이메일을 입력하세요", + "REQUIRED": "필수", + "EMAIL_SENT": "{{email}} 로 인증 코드가 전송되었습니다", + "CHECK_INBOX": "인증을 완료하기 위해 당신의 메일 수신함(그리고 스팸 수신함)을 확인하세요.", + "ENTER_OTT": "인증 코드", + "RESEND_MAIL": "코드 재전송하기", + "VERIFY": "인증", + "UNKNOWN_ERROR": "문제가 생긴 것 같아요. 다시 시도하세요", + "INVALID_CODE": "잘못된 인증 코드", + "EXPIRED_CODE": "입력한 인증 코드가 만료되었습니다", + "SENDING": "전송 중...", + "SENT": "발송 완료!", + "PASSWORD": "비밀번호", + "LINK_PASSWORD": "앨범 잠금해제를 위해 비밀번호를 입력하세요", + "RETURN_PASSPHRASE_HINT": "비밀번호", + "SET_PASSPHRASE": "비밀번호 설정", + "VERIFY_PASSPHRASE": "로그인", + "INCORRECT_PASSPHRASE": "잘못된 비밀번호입니다", + "ENTER_ENC_PASSPHRASE": "당신의 데이터를 암호화하는 데 사용할 수 있는 비밀번호를 입력하세요", + "PASSPHRASE_DISCLAIMER": "우리는 귀하의 비밀번호를 저장하지 않습니다. 만약 비밀번호를 잊어버린 경우 복구 키 없다면 데이터 복구를 도와드릴 수 없습니다.", + "WELCOME_TO_ENTE_HEADING": "환영합니다 ", + "WELCOME_TO_ENTE_SUBHEADING": "End-to-End 암호화된 사진 저장 및 공유", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "당신 최고의 사진이 있는 곳", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "암호 키 생성 중...", + "PASSPHRASE_HINT": "비밀번호", + "CONFIRM_PASSPHRASE": "비밀번호 확인", + "REFERRAL_CODE_HINT": "어떻게 Ente에 대해 들으셨나요? (선택사항)", + "REFERRAL_INFO": "우리는 앱 설치를 추적하지 않습니다. 우리를 알게 된 곳을 남겨주시면 우리에게 도움이 될꺼에요!", + "PASSPHRASE_MATCH_ERROR": "비밀번호가 일치하지 않습니다", + "CREATE_COLLECTION": "새 앨범", + "ENTER_ALBUM_NAME": "앨범 이름", + "CLOSE_OPTION": "닫기 (Esc)", + "ENTER_FILE_NAME": "파일 이름", + "CLOSE": "닫기", + "NO": "아니오", + "NOTHING_HERE": "아직 볼 수 있는 것이 없어요 👀", + "UPLOAD": "업로드", + "IMPORT": "가져오기", + "ADD_PHOTOS": "사진 추가", + "ADD_MORE_PHOTOS": "사진 더 추가하기", + "add_photos_one": "아이템 하나 추가", + "add_photos_other": "아이템 {{count, number}} 개 추가하기", + "SELECT_PHOTOS": "사진 선택하기", + "FILE_UPLOAD": "파일 업로드", + "UPLOAD_STAGE_MESSAGE": { + "0": "업로드 준비중", + "1": "구글 메타데이타 파일들 읽는중", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} 파일 메타데이터가 추출되었습니다", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} 파일이 처리되었습니다", + "4": "남은 업로드 취소중", + "5": "백업 완료" + }, + "FILE_NOT_UPLOADED_LIST": "아래 파일들은 업로드 되지 않았습니다", + "SUBSCRIPTION_EXPIRED": "구독 만료", + "SUBSCRIPTION_EXPIRED_MESSAGE": "당신 구독이 만료되었으니, 구독을 갱신해주세요", + "STORAGE_QUOTA_EXCEEDED": "스토리지 제한이 초과되었습니다", + "INITIAL_LOAD_DELAY_WARNING": "처음 로딩시 다소 시간이 걸릴 수 있습니다", + "USER_DOES_NOT_EXIST": "죄송합니다. 해당 이메일을 사용하는 사용자를 찾을 수 없습니다", + "NO_ACCOUNT": "계정이 없습니다", + "ACCOUNT_EXISTS": "이미 계정이 있습니다", + "CREATE": "만들기", + "DOWNLOAD": "다운로드", + "DOWNLOAD_OPTION": "다운로드 (D)", + "DOWNLOAD_FAVORITES": "즐겨찾기 다운로드", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/auth/public/locales/nl-NL/translation.json b/web/apps/auth/public/locales/nl-NL/translation.json index 1bfeb6d257..15d9bfdba0 100644 --- a/web/apps/auth/public/locales/nl-NL/translation.json +++ b/web/apps/auth/public/locales/nl-NL/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "Hoe hoorde je over Ente? (optioneel)", "REFERRAL_INFO": "Wij gebruiken geen tracking. Het zou helpen als je ons vertelt waar je ons gevonden hebt!", "PASSPHRASE_MATCH_ERROR": "Wachtwoorden komen niet overeen", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "Dit is een browserfunctie bedoeld voor ontwikkelaars. Gelieve hier geen niet-geverifieerde code te kopiëren/plakken.", "CREATE_COLLECTION": "Nieuw album", "ENTER_ALBUM_NAME": "Album naam", "CLOSE_OPTION": "Sluiten (Esc)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "{{name}} downloaden", "DOWNLOAD_FAILED": "Download mislukt", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} bestanden", - "CRASH_REPORTING": "Foutenrapportering", "CHRISTMAS": "Kerst", "CHRISTMAS_EVE": "Kerstavond", "NEW_YEAR": "Nieuwjaar", @@ -625,20 +622,33 @@ "FASTER_UPLOAD_DESCRIPTION": "Uploaden door nabije servers", "MAGIC_SEARCH_STATUS": "Magische Zoekfunctie Status", "INDEXED_ITEMS": "Geïndexeerde bestanden", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", "CACHE_DIRECTORY": "Cache map", - "PASSKEYS": "Passkeys", "FREEHAND": "Losse hand", "APPLY_CROP": "Bijsnijden toepassen", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "Tenminste één transformatie of kleuraanpassing moet worden uitgevoerd voordat u opslaat." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Tenminste één transformatie of kleuraanpassing moet worden uitgevoerd voordat u opslaat.", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/pt-BR/translation.json b/web/apps/auth/public/locales/pt-BR/translation.json index dd264db38a..0da001742f 100644 --- a/web/apps/auth/public/locales/pt-BR/translation.json +++ b/web/apps/auth/public/locales/pt-BR/translation.json @@ -8,7 +8,7 @@ "LOGIN": "Entrar", "SIGN_UP": "Registrar", "NEW_USER": "Novo no ente", - "EXISTING_USER": "Utilizador existente", + "EXISTING_USER": "Usuário existente", "ENTER_NAME": "Insira o nome", "PUBLIC_UPLOADER_NAME_MESSAGE": "Adicione um nome para que os seus amigos saibam a quem agradecer por estas ótimas fotos!", "ENTER_EMAIL": "Insira o endereço de e-mail", @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "Como você ouviu sobre o Ente? (opcional)", "REFERRAL_INFO": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!", "PASSPHRASE_MATCH_ERROR": "As senhas não coincidem", - "CONSOLE_WARNING_STOP": "PARAR!", - "CONSOLE_WARNING_DESC": "Este é um recurso de navegador destinado a desenvolvedores. Por favor, não copie e cole o código não confirmado aqui.", "CREATE_COLLECTION": "Novo álbum", "ENTER_ALBUM_NAME": "Nome do álbum", "CLOSE_OPTION": "Fechar (Esc)", @@ -229,7 +227,7 @@ "INDEXING_SCHEDULED": "Indexação está programada...", "ANALYZING_PHOTOS": "Indexando fotos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", "INDEXING_PEOPLE": "Indexando pessoas em {{indexStatus.nSyncedFiles,number}} fotos...", - "INDEXING_DONE": "Indexed {{indexStatus.nSyncedFiles,number}} photos", + "INDEXING_DONE": "Foram indexadas {{indexStatus.nSyncedFiles,number}} fotos", "UNIDENTIFIED_FACES": "rostos não identificados", "OBJECTS": "objetos", "TEXT": "texto", @@ -349,15 +347,15 @@ "REPLACE_THUMBNAIL_NOOP": "Você não tem nenhuma miniatura que possa ser compactadas mais", "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Não foi possível compactar algumas das suas miniaturas, por favor tente novamente", "FIX_CREATION_TIME": "Corrigir hora", - "FIX_CREATION_TIME_IN_PROGRESS": "Fixing time", - "CREATION_TIME_UPDATED": "File time updated", + "FIX_CREATION_TIME_IN_PROGRESS": "Corrigindo horário", + "CREATION_TIME_UPDATED": "Hora do arquivo atualizado", "UPDATE_CREATION_TIME_NOT_STARTED": "Selecione a carteira que você deseja usar", "UPDATE_CREATION_TIME_COMPLETED": "Todos os arquivos atualizados com sucesso", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "File time updation failed for some files, please retry", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "A atualização do horário falhou para alguns arquivos, por favor, tente novamente", "CAPTION_CHARACTER_LIMIT": "5000 caracteres no máximo", - "DATE_TIME_ORIGINAL": "EXIF:DateTimeOriginal", - "DATE_TIME_DIGITIZED": "EXIF:DateTimeDigitized", - "METADATA_DATE": "EXIF:MetadataDate", + "DATE_TIME_ORIGINAL": "Data e Hora Original", + "DATE_TIME_DIGITIZED": "Data e Hora Digitalizada", + "METADATA_DATE": "Data de Metadados", "CUSTOM_TIME": "Tempo personalizado", "REOPEN_PLAN_SELECTOR_MODAL": "Reabrir planos", "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Falha ao abrir planos", @@ -410,7 +408,7 @@ "SHARED_USING": "Compartilhar usando ", "ENTE_IO": "ente.io", "SHARING_REFERRAL_CODE": "Use o código {{referralCode}} para obter 10 GB de graça", - "LIVE": "LIVE", + "LIVE": "AO VIVO", "DISABLE_PASSWORD": "Desativar bloqueio por senha", "DISABLE_PASSWORD_MESSAGE": "Tem certeza que deseja desativar o bloqueio por senha?", "PASSWORD_LOCK": "Bloqueio de senha", @@ -508,8 +506,8 @@ "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente irá parar de processar geometria facial.

Você pode reativar o reconhecimento facial novamente, se desejar, então esta operação está segura.

", "ADVANCED": "Avançado", "FACE_SEARCH_CONFIRMATION": "Eu entendo, e desejo permitir que o ente processe a geometria do rosto", - "LABS": "Labs", - "YOURS": "yours", + "LABS": "Laboratórios", + "YOURS": "seu", "PASSPHRASE_STRENGTH_WEAK": "Força da senha: fraca", "PASSPHRASE_STRENGTH_MODERATE": "Força da senha: moderada", "PASSPHRASE_STRENGTH_STRONG": "Força da senha: forte", @@ -572,7 +570,7 @@ "FEEDBACK_REQUIRED": "Por favor, ajude-nos com esta informação", "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "O que o outro serviço faz melhor?", "RECOVER_TWO_FACTOR": "Recuperar dois fatores", - "at": "at", + "at": "em", "AUTH_NEXT": "próximo", "AUTH_DOWNLOAD_MOBILE_APP": "Baixe nosso aplicativo móvel para gerenciar seus segredos", "HIDDEN": "Escondido", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Transferindo {{name}}", "DOWNLOAD_FAILED": "Falha ao baixar", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} arquivos", - "CRASH_REPORTING": "Relatório de falhas", "CHRISTMAS": "Natal", "CHRISTMAS_EVE": "Véspera de Natal", "NEW_YEAR": "Ano Novo", @@ -607,7 +604,7 @@ "BLUR": "Desfoque", "INVERT_COLORS": "Inverter Cores", "ASPECT_RATIO": "Proporção da imagem", - "SQUARE": "Square", + "SQUARE": "Quadrado", "ROTATE_LEFT": "Girar para a Esquerda", "ROTATE_RIGHT": "Girar para a Direita", "FLIP_VERTICALLY": "Inverter verticalmente", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "Acesse cast.ente.io no dispositivo que você deseja parear.", "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair falhou. Por favor, tente novamente.", "CACHE_DIRECTORY": "Pasta de Cache", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", + "FREEHAND": "Mão livre", "APPLY_CROP": "Aplicar Recorte", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "Pelo menos uma transformação ou ajuste de cor deve ser feito antes de salvar." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Pelo menos uma transformação ou ajuste de cor deve ser feito antes de salvar.", + "PASSKEYS": "Chaves de acesso", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/pt-PT/translation.json b/web/apps/auth/public/locales/pt-PT/translation.json index ffb1debb4c..2309803267 100644 --- a/web/apps/auth/public/locales/pt-PT/translation.json +++ b/web/apps/auth/public/locales/pt-PT/translation.json @@ -1,8 +1,8 @@ { "HERO_SLIDE_1_TITLE": "
Backups privados
para as suas memórias
", - "HERO_SLIDE_1": "End-to-end encrypted by default", - "HERO_SLIDE_2_TITLE": "
Safely stored
at a fallout shelter
", - "HERO_SLIDE_2": "Designed to outlive", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", "HERO_SLIDE_3_TITLE": "
Disponível
em qualquer lugar
", "HERO_SLIDE_3": "Android, iOS, Web, Desktop", "LOGIN": "Entrar", @@ -30,27 +30,25 @@ "SET_PASSPHRASE": "Definir palavra-passe", "VERIFY_PASSPHRASE": "Entrar", "INCORRECT_PASSPHRASE": "Palavra-passe incorreta", - "ENTER_ENC_PASSPHRASE": "Please enter a password that we can use to encrypt your data", - "PASSPHRASE_DISCLAIMER": "We don't store your password, so if you forget it, we will not be able to help you recover your data without a recovery key.", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", "WELCOME_TO_ENTE_HEADING": "Bem-vindo ao ", - "WELCOME_TO_ENTE_SUBHEADING": "End to end encrypted photo storage and sharing", - "WHERE_YOUR_BEST_PHOTOS_LIVE": "Where your best photos live", - "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generating encryption keys...", - "PASSPHRASE_HINT": "Password", - "CONFIRM_PASSPHRASE": "Confirm password", - "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", - "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", - "PASSPHRASE_MATCH_ERROR": "Passwords don't match", - "CONSOLE_WARNING_STOP": "PARAR!", - "CONSOLE_WARNING_DESC": "This is a browser feature intended for developers. Please don't copy-paste unverified code here.", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", "CREATE_COLLECTION": "Novo álbum", "ENTER_ALBUM_NAME": "Nome do álbum", "CLOSE_OPTION": "Fechar (Esc)", "ENTER_FILE_NAME": "Nome do ficheiro", "CLOSE": "Fechar", "NO": "Não", - "NOTHING_HERE": "Nothing to see here yet 👀", - "UPLOAD": "Upload", + "NOTHING_HERE": "", + "UPLOAD": "", "IMPORT": "Importar", "ADD_PHOTOS": "Adicionar fotos", "ADD_MORE_PHOTOS": "Adicionar mais fotos", @@ -59,586 +57,598 @@ "SELECT_PHOTOS": "Selecionar fotos", "FILE_UPLOAD": "Enviar Ficheiro", "UPLOAD_STAGE_MESSAGE": { - "0": "Preparing to upload", - "1": "Reading google metadata files", - "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files metadata extracted", - "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files processed", - "4": "Cancelling remaining uploads", - "5": "Backup complete" + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" }, - "FILE_NOT_UPLOADED_LIST": "The following files were not uploaded", - "SUBSCRIPTION_EXPIRED": "Subscription expired", - "SUBSCRIPTION_EXPIRED_MESSAGE": "Your subscription has expired, please renew", - "STORAGE_QUOTA_EXCEEDED": "Storage limit exceeded", - "INITIAL_LOAD_DELAY_WARNING": "First load may take some time", - "USER_DOES_NOT_EXIST": "Sorry, could not find a user with that email", + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", "NO_ACCOUNT": "Não possui uma conta", "ACCOUNT_EXISTS": "Já possui uma conta", "CREATE": "Criar", - "DOWNLOAD": "Download", - "DOWNLOAD_OPTION": "Download (D)", - "DOWNLOAD_FAVORITES": "Download favorites", - "DOWNLOAD_UNCATEGORIZED": "Download uncategorized", - "DOWNLOAD_HIDDEN_ITEMS": "Download hidden items", - "COPY_OPTION": "Copy as PNG (Ctrl/Cmd - C)", - "TOGGLE_FULLSCREEN": "Toggle fullscreen (F)", - "ZOOM_IN_OUT": "Zoom in/out", - "PREVIOUS": "Previous (←)", - "NEXT": "Next (→)", - "TITLE_PHOTOS": "Ente Photos", - "TITLE_ALBUMS": "Ente Photos", - "TITLE_AUTH": "Ente Auth", - "UPLOAD_FIRST_PHOTO": "Upload your first photo", - "IMPORT_YOUR_FOLDERS": "Import your folders", - "UPLOAD_DROPZONE_MESSAGE": "Drop to backup your files", - "WATCH_FOLDER_DROPZONE_MESSAGE": "Drop to add watched folder", - "TRASH_FILES_TITLE": "Delete files?", - "TRASH_FILE_TITLE": "Delete file?", - "DELETE_FILES_TITLE": "Delete immediately?", - "DELETE_FILES_MESSAGE": "Selected files will be permanently deleted from your ente account.", - "DELETE": "Delete", - "DELETE_OPTION": "Delete (DEL)", - "FAVORITE_OPTION": "Favorite (L)", - "UNFAVORITE_OPTION": "Unfavorite (L)", - "MULTI_FOLDER_UPLOAD": "Multiple folders detected", - "UPLOAD_STRATEGY_CHOICE": "Would you like to upload them into", - "UPLOAD_STRATEGY_SINGLE_COLLECTION": "A single album", - "OR": "or", - "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Separate albums", - "SESSION_EXPIRED_MESSAGE": "Your session has expired, please login again to continue", - "SESSION_EXPIRED": "Session expired", - "PASSWORD_GENERATION_FAILED": "Your browser was unable to generate a strong key that meets ente's encryption standards, please try using the mobile app or another browser", - "CHANGE_PASSWORD": "Change password", - "GO_BACK": "Go back", - "RECOVERY_KEY": "Recovery key", - "SAVE_LATER": "Do this later", - "SAVE": "Save Key", - "RECOVERY_KEY_DESCRIPTION": "If you forget your password, the only way you can recover your data is with this key.", - "RECOVER_KEY_GENERATION_FAILED": "Recovery code could not be generated, please try again", - "KEY_NOT_STORED_DISCLAIMER": "We don't store this key, so please save this in a safe place", - "FORGOT_PASSWORD": "Forgot password", - "RECOVER_ACCOUNT": "Recover account", - "RECOVERY_KEY_HINT": "Recovery key", - "RECOVER": "Recover", - "NO_RECOVERY_KEY": "No recovery key?", - "INCORRECT_RECOVERY_KEY": "Incorrect recovery key", - "SORRY": "Sorry", - "NO_RECOVERY_KEY_MESSAGE": "Due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Please drop an email to {{emailID}} from your registered email address", - "CONTACT_SUPPORT": "Contact support", - "REQUEST_FEATURE": "Request Feature", - "SUPPORT": "Support", - "CONFIRM": "Confirm", - "CANCEL": "Cancel", - "LOGOUT": "Logout", - "DELETE_ACCOUNT": "Delete account", - "DELETE_ACCOUNT_MESSAGE": "

Please send an email to {{emailID}} from your registered email address.

Your request will be processed within 72 hours.

", - "LOGOUT_MESSAGE": "Are you sure you want to logout?", - "CHANGE_EMAIL": "Change email", - "OK": "OK", - "SUCCESS": "Success", - "ERROR": "Error", - "MESSAGE": "Message", - "INSTALL_MOBILE_APP": "Install our Android or iOS app to automatically backup all your photos", - "DOWNLOAD_APP_MESSAGE": "Sorry, this operation is currently only supported on our desktop app", - "DOWNLOAD_APP": "Download desktop app", - "EXPORT": "Export Data", - "SUBSCRIPTION": "Subscription", - "SUBSCRIBE": "Subscribe", - "MANAGEMENT_PORTAL": "Manage payment method", - "MANAGE_FAMILY_PORTAL": "Manage family", - "LEAVE_FAMILY_PLAN": "Leave family plan", - "LEAVE": "Leave", - "LEAVE_FAMILY_CONFIRM": "Are you sure that you want to leave family plan?", - "CHOOSE_PLAN": "Choose your plan", - "MANAGE_PLAN": "Manage your subscription", - "ACTIVE": "Active", - "OFFLINE_MSG": "You are offline, cached memories are being shown", - "FREE_SUBSCRIPTION_INFO": "You are on the free plan that expires on {{date, dateTime}}", - "FAMILY_SUBSCRIPTION_INFO": "You are on a family plan managed by", - "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Renews on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Ends on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Your subscription will be cancelled on {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", - "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "You have exceeded your storage quota, please upgrade", - "SUBSCRIPTION_PURCHASE_SUCCESS": "

We've received your payment

Your subscription is valid till {{date, dateTime}}

", - "SUBSCRIPTION_PURCHASE_CANCELLED": "Your purchase was canceled, please try again if you want to subscribe", - "SUBSCRIPTION_PURCHASE_FAILED": "Subscription purchase failed , please try again", - "SUBSCRIPTION_UPDATE_FAILED": "Subscription updated failed , please try again", - "UPDATE_PAYMENT_METHOD_MESSAGE": "We are sorry, payment failed when we tried to charge your card, please update your payment method and try again", - "STRIPE_AUTHENTICATION_FAILED": "We are unable to authenticate your payment method. please choose a different payment method and try again", - "UPDATE_PAYMENT_METHOD": "Update payment method", - "MONTHLY": "Monthly", - "YEARLY": "Yearly", - "UPDATE_SUBSCRIPTION_MESSAGE": "Are you sure you want to change your plan?", - "UPDATE_SUBSCRIPTION": "Change plan", - "CANCEL_SUBSCRIPTION": "Cancel subscription", - "CANCEL_SUBSCRIPTION_MESSAGE": "

All of your data will be deleted from our servers at the end of this billing period.

Are you sure that you want to cancel your subscription?

", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

", - "SUBSCRIPTION_CANCEL_FAILED": "Failed to cancel subscription", - "SUBSCRIPTION_CANCEL_SUCCESS": "Subscription canceled successfully", - "REACTIVATE_SUBSCRIPTION": "Reactivate subscription", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "Once reactivated, you will be billed on {{date, dateTime}}", - "SUBSCRIPTION_ACTIVATE_SUCCESS": "Subscription activated successfully ", - "SUBSCRIPTION_ACTIVATE_FAILED": "Failed to reactivate subscription renewals", - "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Thank you", - "CANCEL_SUBSCRIPTION_ON_MOBILE": "Cancel mobile subscription", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Please cancel your subscription from the mobile app to activate a subscription here", - "MAIL_TO_MANAGE_SUBSCRIPTION": "Please contact us at {{emailID}} to manage your subscription", - "RENAME": "Rename", - "RENAME_FILE": "Rename file", - "RENAME_COLLECTION": "Rename album", - "DELETE_COLLECTION_TITLE": "Delete album?", - "DELETE_COLLECTION": "Delete album", - "DELETE_COLLECTION_MESSAGE": "Also delete the photos (and videos) present in this album from all other albums they are part of?", - "DELETE_PHOTOS": "Delete photos", - "KEEP_PHOTOS": "Keep photos", - "SHARE": "Share", - "SHARE_COLLECTION": "Share album", - "SHAREES": "Shared with", - "SHARE_WITH_SELF": "Oops, you cannot share with yourself", - "ALREADY_SHARED": "Oops, you're already sharing this with {{email}}", - "SHARING_BAD_REQUEST_ERROR": "Sharing album not allowed", - "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Sharing is disabled for free accounts", - "DOWNLOAD_COLLECTION": "Download album", - "DOWNLOAD_COLLECTION_MESSAGE": "

Are you sure you want to download the complete album?

All files will be queued for download sequentially

", - "CREATE_ALBUM_FAILED": "Failed to create album , please try again", - "SEARCH": "Search", - "SEARCH_RESULTS": "Search results", - "NO_RESULTS": "No results found", - "SEARCH_HINT": "Search for albums, dates, descriptions, ...", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", "SEARCH_TYPE": { - "COLLECTION": "Album", - "LOCATION": "Location", - "CITY": "Location", - "DATE": "Date", - "FILE_NAME": "File name", - "THING": "Content", - "FILE_CAPTION": "Description", - "FILE_TYPE": "File type", - "CLIP": "Magic" + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" }, - "photos_count_zero": "No memories", - "photos_count_one": "1 memory", - "photos_count_other": "{{count, number}} memories", - "TERMS_AND_CONDITIONS": "I agree to the terms and privacy policy", - "ADD_TO_COLLECTION": "Add to album", - "SELECTED": "selected", - "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "This video cannot be played on your browser", - "PEOPLE": "People", - "INDEXING_SCHEDULED": "Indexing is scheduled...", - "ANALYZING_PHOTOS": "Indexing photos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", - "INDEXING_PEOPLE": "Indexing people in {{indexStatus.nSyncedFiles,number}} photos...", - "INDEXING_DONE": "Indexed {{indexStatus.nSyncedFiles,number}} photos", - "UNIDENTIFIED_FACES": "unidentified faces", - "OBJECTS": "objects", - "TEXT": "text", - "INFO": "Info ", - "INFO_OPTION": "Info (I)", - "FILE_NAME": "File name", - "CAPTION_PLACEHOLDER": "Add a description", - "LOCATION": "Location", - "SHOW_ON_MAP": "View on OpenStreetMap", - "MAP": "Map", - "MAP_SETTINGS": "Map Settings", - "ENABLE_MAPS": "Enable Maps?", - "ENABLE_MAP": "Enable map", - "DISABLE_MAPS": "Disable Maps?", - "ENABLE_MAP_DESCRIPTION": "

This will show your photos on a world map.

The map is hosted by OpenStreetMap, and the exact locations of your photos are never shared.

You can disable this feature anytime from Settings.

", - "DISABLE_MAP_DESCRIPTION": "

This will disable the display of your photos on a world map.

You can enable this feature anytime from Settings.

", - "DISABLE_MAP": "Disable map", - "DETAILS": "Details", - "VIEW_EXIF": "View all EXIF data", - "NO_EXIF": "No EXIF data", - "EXIF": "EXIF", - "ISO": "ISO", - "TWO_FACTOR": "Two-factor", - "TWO_FACTOR_AUTHENTICATION": "Two-factor authentication", - "TWO_FACTOR_QR_INSTRUCTION": "Scan the QR code below with your favorite authenticator app", - "ENTER_CODE_MANUALLY": "Enter the code manually", - "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Please enter this code in your favorite authenticator app", - "SCAN_QR_CODE": "Scan QR code instead", - "ENABLE_TWO_FACTOR": "Enable two-factor", - "ENABLE": "Enable", - "LOST_DEVICE": "Lost two-factor device", - "INCORRECT_CODE": "Incorrect code", - "TWO_FACTOR_INFO": "Add an additional layer of security by requiring more than your email and password to log in to your account", - "DISABLE_TWO_FACTOR_LABEL": "Disable two-factor authentication", - "UPDATE_TWO_FACTOR_LABEL": "Update your authenticator device", - "DISABLE": "Disable", - "RECONFIGURE": "Reconfigure", - "UPDATE_TWO_FACTOR": "Update two-factor", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuing forward will void any previously configured authenticators", - "UPDATE": "Update", - "DISABLE_TWO_FACTOR": "Disable two-factor", - "DISABLE_TWO_FACTOR_MESSAGE": "Are you sure you want to disable your two-factor authentication", - "TWO_FACTOR_DISABLE_FAILED": "Failed to disable two factor, please try again", - "EXPORT_DATA": "Export data", - "SELECT_FOLDER": "Select folder", - "DESTINATION": "Destination", - "START": "Start", - "LAST_EXPORT_TIME": "Last export time", - "EXPORT_AGAIN": "Resync", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "Local storage not accessible", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Your browser or an addon is blocking ente from saving data into local storage. please try loading this page after switching your browsing mode.", - "SEND_OTT": "Send OTP", - "EMAIl_ALREADY_OWNED": "Email already taken", - "ETAGS_BLOCKED": "

We were unable to upload the following files because of your browser configuration.

Please disable any addons that might be preventing ente from using eTags to upload large files, or use our desktop app for a more reliable import experience.

", - "SKIPPED_VIDEOS_INFO": "

Presently we do not support adding videos via public links.

To share videos, please signup for ente and share with the intended recipients using their email.

", - "LIVE_PHOTOS_DETECTED": "The photo and video files from your Live Photos have been merged into a single file", - "RETRY_FAILED": "Retry failed uploads", - "FAILED_UPLOADS": "Failed uploads ", - "SKIPPED_FILES": "Ignored uploads", - "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Thumbnail generation failed", - "UNSUPPORTED_FILES": "Unsupported files", - "SUCCESSFUL_UPLOADS": "Successful uploads", - "SKIPPED_INFO": "Skipped these as there are files with matching names in the same album", - "UNSUPPORTED_INFO": "ente does not support these file formats yet", - "BLOCKED_UPLOADS": "Blocked uploads", - "SKIPPED_VIDEOS": "Skipped videos", - "INPROGRESS_METADATA_EXTRACTION": "In progress", - "INPROGRESS_UPLOADS": "Uploads in progress", - "TOO_LARGE_UPLOADS": "Large files", - "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Insufficient storage", - "LARGER_THAN_AVAILABLE_STORAGE_INFO": "These files were not uploaded as they exceed the maximum size limit for your storage plan", - "TOO_LARGE_INFO": "These files were not uploaded as they exceed our maximum file size limit", - "THUMBNAIL_GENERATION_FAILED_INFO": "These files were uploaded, but unfortunately we could not generate the thumbnails for them.", - "UPLOAD_TO_COLLECTION": "Upload to album", - "UNCATEGORIZED": "Uncategorized", - "ARCHIVE": "Archive", - "FAVORITES": "Favorites", - "ARCHIVE_COLLECTION": "Archive album", - "ARCHIVE_SECTION_NAME": "Archive", - "ALL_SECTION_NAME": "All", - "MOVE_TO_COLLECTION": "Move to album", - "UNARCHIVE": "Unarchive", - "UNARCHIVE_COLLECTION": "Unarchive album", - "HIDE_COLLECTION": "Hide album", - "UNHIDE_COLLECTION": "Unhide album", - "MOVE": "Move", - "ADD": "Add", - "REMOVE": "Remove", - "YES_REMOVE": "Yes, remove", - "REMOVE_FROM_COLLECTION": "Remove from album", - "TRASH": "Trash", - "MOVE_TO_TRASH": "Move to trash", - "TRASH_FILES_MESSAGE": "Selected files will be removed from all albums and moved to trash.", - "TRASH_FILE_MESSAGE": "The file will be removed from all albums and moved to trash.", - "DELETE_PERMANENTLY": "Delete permanently", - "RESTORE": "Restore", - "RESTORE_TO_COLLECTION": "Restore to album", - "EMPTY_TRASH": "Empty trash", - "EMPTY_TRASH_TITLE": "Empty trash?", - "EMPTY_TRASH_MESSAGE": "These files will be permanently deleted from your ente account.", - "LEAVE_SHARED_ALBUM": "Yes, leave", - "LEAVE_ALBUM": "Leave album", - "LEAVE_SHARED_ALBUM_TITLE": "Leave shared album?", - "LEAVE_SHARED_ALBUM_MESSAGE": "You will leave the album, and it will stop being visible to you.", - "NOT_FILE_OWNER": "You cannot delete files in a shared album", - "CONFIRM_SELF_REMOVE_MESSAGE": "Selected items will be removed from this album. Items which are only in this album will be moved to Uncategorized.", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Some of the items you are removing were added by other people, and you will lose access to them.", - "SORT_BY_CREATION_TIME_ASCENDING": "Oldest", - "SORT_BY_UPDATION_TIME_DESCENDING": "Last updated", - "SORT_BY_NAME": "Name", - "COMPRESS_THUMBNAILS": "Compress thumbnails", - "THUMBNAIL_REPLACED": "Thumbnails compressed", - "FIX_THUMBNAIL": "Compress", - "FIX_THUMBNAIL_LATER": "Compress later", - "REPLACE_THUMBNAIL_NOT_STARTED": "Some of your videos thumbnails can be compressed to save space. would you like ente to compress them?", - "REPLACE_THUMBNAIL_COMPLETED": "Successfully compressed all thumbnails", - "REPLACE_THUMBNAIL_NOOP": "You have no thumbnails that can be compressed further", - "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Could not compress some of your thumbnails, please retry", - "FIX_CREATION_TIME": "Fix time", - "FIX_CREATION_TIME_IN_PROGRESS": "Fixing time", - "CREATION_TIME_UPDATED": "File time updated", - "UPDATE_CREATION_TIME_NOT_STARTED": "Select the option you want to use", - "UPDATE_CREATION_TIME_COMPLETED": "Successfully updated all files", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "File time updation failed for some files, please retry", - "CAPTION_CHARACTER_LIMIT": "5000 characters max", - "DATE_TIME_ORIGINAL": "EXIF:DateTimeOriginal", - "DATE_TIME_DIGITIZED": "EXIF:DateTimeDigitized", - "METADATA_DATE": "EXIF:MetadataDate", - "CUSTOM_TIME": "Custom time", - "REOPEN_PLAN_SELECTOR_MODAL": "Re-open plans", - "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Failed to open plans", - "INSTALL": "Install", - "SHARING_DETAILS": "Sharing details", - "MODIFY_SHARING": "Modify sharing", - "ADD_COLLABORATORS": "Add collaborators", - "ADD_NEW_EMAIL": "Add a new email", - "shared_with_people_zero": "Share with specific people", - "shared_with_people_one": "Shared with 1 person", - "shared_with_people_other": "Shared with {{count, number}} people", - "participants_zero": "No participants", - "participants_one": "1 participant", - "participants_other": "{{count, number}} participants", - "ADD_VIEWERS": "Add viewers", - "PARTICIPANTS": "Participants", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} will not be able to add more photos to the album

They will still be able to remove photos added by them

", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} will be able to add photos to the album", - "CONVERT_TO_VIEWER": "Yes, convert to viewer", - "CONVERT_TO_COLLABORATOR": "Yes, convert to collaborator", - "CHANGE_PERMISSION": "Change permission?", - "REMOVE_PARTICIPANT": "Remove?", - "CONFIRM_REMOVE": "Yes, remove", - "MANAGE": "Manage", - "ADDED_AS": "Added as", - "COLLABORATOR_RIGHTS": "Collaborators can add photos and videos to the shared album", - "REMOVE_PARTICIPANT_HEAD": "Remove participant", - "OWNER": "Owner", - "COLLABORATORS": "Collaborators", - "ADD_MORE": "Add more", - "VIEWERS": "Viewers", - "OR_ADD_EXISTING": "Or pick an existing one", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} will be removed from the album

Any photos added by them will also be removed from the album

", - "NOT_FOUND": "404 - not found", - "LINK_EXPIRED": "Link expired", - "LINK_EXPIRED_MESSAGE": "This link has either expired or been disabled!", - "MANAGE_LINK": "Manage link", - "LINK_TOO_MANY_REQUESTS": "Sorry, this album has been viewed on too many devices!", - "FILE_DOWNLOAD": "Allow downloads", - "LINK_PASSWORD_LOCK": "Password lock", - "PUBLIC_COLLECT": "Allow adding photos", - "LINK_DEVICE_LIMIT": "Device limit", - "NO_DEVICE_LIMIT": "None", - "LINK_EXPIRY": "Link expiry", - "NEVER": "Never", - "DISABLE_FILE_DOWNLOAD": "Disable download", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Are you sure that you want to disable the download button for files?

Viewers can still take screenshots or save a copy of your photos using external tools.

", - "MALICIOUS_CONTENT": "Contains malicious content", - "COPYRIGHT": "Infringes on the copyright of someone I am authorized to represent", - "SHARED_USING": "Shared using ", - "ENTE_IO": "ente.io", - "SHARING_REFERRAL_CODE": "Use code {{referralCode}} to get 10 GB free", - "LIVE": "LIVE", - "DISABLE_PASSWORD": "Disable password lock", - "DISABLE_PASSWORD_MESSAGE": "Are you sure that you want to disable the password lock?", - "PASSWORD_LOCK": "Password lock", - "LOCK": "Lock", - "DOWNLOAD_UPLOAD_LOGS": "Debug logs", - "UPLOAD_FILES": "File", - "UPLOAD_DIRS": "Folder", - "UPLOAD_GOOGLE_TAKEOUT": "Google takeout", - "DEDUPLICATE_FILES": "Deduplicate files", - "AUTHENTICATOR_SECTION": "Authenticator", - "NO_DUPLICATES_FOUND": "You've no duplicate files that can be cleared", - "CLUB_BY_CAPTURE_TIME": "Club by capture time", - "FILES": "Files", - "EACH": "Each", - "DEDUPLICATE_BASED_ON_SIZE": "The following files were clubbed based on their sizes, please review and delete items you believe are duplicates", - "STOP_ALL_UPLOADS_MESSAGE": "Are you sure that you want to stop all the uploads in progress?", - "STOP_UPLOADS_HEADER": "Stop uploads?", - "YES_STOP_UPLOADS": "Yes, stop uploads", - "STOP_DOWNLOADS_HEADER": "Stop downloads?", - "YES_STOP_DOWNLOADS": "Yes, stop downloads", - "STOP_ALL_DOWNLOADS_MESSAGE": "Are you sure that you want to stop all the downloads in progress?", - "albums_one": "1 Album", - "albums_other": "{{count, number}} Albums", - "ALL_ALBUMS": "All Albums", - "ALBUMS": "Albums", - "ALL_HIDDEN_ALBUMS": "All hidden albums", - "HIDDEN_ALBUMS": "Hidden albums", - "HIDDEN_ITEMS": "Hidden items", - "HIDDEN_ITEMS_SECTION_NAME": "Hidden_items", - "ENTER_TWO_FACTOR_OTP": "Enter the 6-digit code from your authenticator app.", - "CREATE_ACCOUNT": "Create account", - "COPIED": "Copied", - "CANVAS_BLOCKED_TITLE": "Unable to generate thumbnail", - "CANVAS_BLOCKED_MESSAGE": "

It looks like your browser has disabled access to canvas, which is necessary to generate thumbnails for your photos

Please enable access to your browser's canvas, or check out our desktop app

", - "WATCH_FOLDERS": "Watch folders", - "UPGRADE_NOW": "Upgrade now", - "RENEW_NOW": "Renew now", - "STORAGE": "Storage", - "USED": "used", - "YOU": "You", - "FAMILY": "Family", - "FREE": "free", - "OF": "of", - "WATCHED_FOLDERS": "Watched folders", - "NO_FOLDERS_ADDED": "No folders added yet!", - "FOLDERS_AUTOMATICALLY_MONITORED": "The folders you add here will monitored to automatically", - "UPLOAD_NEW_FILES_TO_ENTE": "Upload new files to ente", - "REMOVE_DELETED_FILES_FROM_ENTE": "Remove deleted files from ente", - "ADD_FOLDER": "Add folder", - "STOP_WATCHING": "Stop watching", - "STOP_WATCHING_FOLDER": "Stop watching folder?", - "STOP_WATCHING_DIALOG_MESSAGE": "Your existing files will not be deleted, but ente will stop automatically updating the linked ente album on changes in this folder.", - "YES_STOP": "Yes, stop", - "MONTH_SHORT": "mo", - "YEAR": "year", - "FAMILY_PLAN": "Family plan", - "DOWNLOAD_LOGS": "Download logs", - "DOWNLOAD_LOGS_MESSAGE": "

This will download debug logs, which you can email to us to help debug your issue.

Please note that file names will be included to help track issues with specific files.

", - "CHANGE_FOLDER": "Change Folder", - "TWO_MONTHS_FREE": "Get 2 months free on yearly plans", - "GB": "GB", - "POPULAR": "Popular", - "FREE_PLAN_OPTION_LABEL": "Continue with free trial", - "FREE_PLAN_DESCRIPTION": "1 GB for 1 year", - "CURRENT_USAGE": "Current usage is {{usage}}", - "WEAK_DEVICE": "The web browser you're using is not powerful enough to encrypt your photos. Please try to log in to ente on your computer, or download the ente mobile/desktop app.", - "DRAG_AND_DROP_HINT": "Or drag and drop into the ente window", - "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Your uploaded data will be scheduled for deletion, and your account will be permanently deleted.

This action is not reversible.", - "AUTHENTICATE": "Authenticate", - "UPLOADED_TO_SINGLE_COLLECTION": "Uploaded to single collection", - "UPLOADED_TO_SEPARATE_COLLECTIONS": "Uploaded to separate collections", - "NEVERMIND": "Nevermind", - "UPDATE_AVAILABLE": "Update available", - "UPDATE_INSTALLABLE_MESSAGE": "A new version of ente is ready to be installed.", - "INSTALL_NOW": "Install now", - "INSTALL_ON_NEXT_LAUNCH": "Install on next launch", - "UPDATE_AVAILABLE_MESSAGE": "A new version of ente has been released, but it cannot be automatically downloaded and installed.", - "DOWNLOAD_AND_INSTALL": "Download and install", - "IGNORE_THIS_VERSION": "Ignore this version", - "TODAY": "Today", - "YESTERDAY": "Yesterday", - "NAME_PLACEHOLDER": "Name...", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Cannot create albums from file/folder mix", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

You have dragged and dropped a mixture of files and folders.

Please provide either only files, or only folders when selecting option to create separate albums

", - "CHOSE_THEME": "Choose theme", - "ML_SEARCH": "Face recognition", - "ENABLE_ML_SEARCH_DESCRIPTION": "

This will enable on-device machine learning and face search which will start analyzing your uploaded photos locally.

For the first run after login or enabling this feature, it will download all images on local device to analyze them. So please only enable this if you are ok with bandwidth and local processing of all images in your photo library.

If this is the first time you're enabling this, we'll also ask your permission to process face data.

", - "ML_MORE_DETAILS": "More details", - "ENABLE_FACE_SEARCH": "Enable face recognition", - "ENABLE_FACE_SEARCH_TITLE": "Enable face recognition?", - "ENABLE_FACE_SEARCH_DESCRIPTION": "

If you enable face recognition, ente will extract face geometry from your photos. This will happen on your device, and any generated biometric data will be end-to-encrypted.

Please click here for more details about this feature in our privacy policy

", - "DISABLE_BETA": "Pause recognition", - "DISABLE_FACE_SEARCH": "Disable face recognition", - "DISABLE_FACE_SEARCH_TITLE": "Disable face recognition?", - "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente will stop processing face geometry.

You can reenable face recognition again if you wish, so this operation is safe.

", - "ADVANCED": "Advanced", - "FACE_SEARCH_CONFIRMATION": "I understand, and wish to allow ente to process face geometry", - "LABS": "Labs", - "YOURS": "yours", - "PASSPHRASE_STRENGTH_WEAK": "Password strength: Weak", - "PASSPHRASE_STRENGTH_MODERATE": "Password strength: Moderate", - "PASSPHRASE_STRENGTH_STRONG": "Password strength: Strong", - "PREFERENCES": "Preferences", - "LANGUAGE": "Language", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Invalid export directory", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

The export directory you have selected does not exist.

Please select a valid directory.

", - "SUBSCRIPTION_VERIFICATION_ERROR": "Subscription verification failed", + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", "STORAGE_UNITS": { - "B": "B", - "KB": "KB", - "MB": "MB", - "GB": "GB", - "TB": "TB" + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" }, "AFTER_TIME": { - "HOUR": "after an hour", - "DAY": "after a day", - "WEEK": "after a week", - "MONTH": "after a month", - "YEAR": "after a year" + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" }, - "COPY_LINK": "Copy link", - "DONE": "Done", - "LINK_SHARE_TITLE": "Or share a link", - "REMOVE_LINK": "Remove link", - "CREATE_PUBLIC_SHARING": "Create public link", - "PUBLIC_LINK_CREATED": "Public link created", - "PUBLIC_LINK_ENABLED": "Public link enabled", - "COLLECT_PHOTOS": "Collect photos", - "PUBLIC_COLLECT_SUBTEXT": "Allow people with the link to also add photos to the shared album.", - "STOP_EXPORT": "Stop", - "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} items synced", - "MIGRATING_EXPORT": "Preparing...", - "RENAMING_COLLECTION_FOLDERS": "Renaming album folders...", - "TRASHING_DELETED_FILES": "Trashing deleted files...", - "TRASHING_DELETED_COLLECTIONS": "Trashing deleted albums...", + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", "EXPORT_NOTIFICATION": { - "START": "Export started", - "IN_PROGRESS": "Export already in progress", - "FINISH": "Export finished", - "UP_TO_DATE": "No new files to export" + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" }, - "CONTINUOUS_EXPORT": "Sync continuously", - "TOTAL_ITEMS": "Total items", - "PENDING_ITEMS": "Pending items", - "EXPORT_STARTING": "Export starting...", - "DELETE_ACCOUNT_REASON_LABEL": "What is the main reason you are deleting your account?", - "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Select a reason", + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", "DELETE_REASON": { - "MISSING_FEATURE": "It's missing a key feature that I need", - "BROKEN_BEHAVIOR": "The app or a certain feature does not behave as I think it should", - "FOUND_ANOTHER_SERVICE": "I found another service that I like better", - "NOT_LISTED": "My reason isn't listed" + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" }, - "DELETE_ACCOUNT_FEEDBACK_LABEL": "We are sorry to see you go. Please explain why you are leaving to help us improve.", - "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Feedback", - "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Yes, I want to permanently delete this account and all its data", - "CONFIRM_DELETE_ACCOUNT": "Confirm Account Deletion", - "FEEDBACK_REQUIRED": "Kindly help us with this information", - "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "What does the other service do better?", - "RECOVER_TWO_FACTOR": "Recover two-factor", - "at": "at", - "AUTH_NEXT": "next", - "AUTH_DOWNLOAD_MOBILE_APP": "Download our mobile app to manage your secrets", - "HIDDEN": "Hidden", - "HIDE": "Hide", - "UNHIDE": "Unhide", - "UNHIDE_TO_COLLECTION": "Unhide to album", - "SORT_BY": "Sort by", - "NEWEST_FIRST": "Newest first", - "OLDEST_FIRST": "Oldest first", - "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "This file could not be previewed. Click here to download the original.", - "SELECT_COLLECTION": "Select album", - "PIN_ALBUM": "Pin album", - "UNPIN_ALBUM": "Unpin album", - "DOWNLOAD_COMPLETE": "Download complete", - "DOWNLOADING_COLLECTION": "Downloading {{name}}", - "DOWNLOAD_FAILED": "Download failed", - "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", - "CHRISTMAS": "Christmas", - "CHRISTMAS_EVE": "Christmas Eve", - "NEW_YEAR": "New Year", - "NEW_YEAR_EVE": "New Year's Eve", - "IMAGE": "Image", - "VIDEO": "Video", - "LIVE_PHOTO": "Live Photo", - "CONVERT": "Convert", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Are you sure you want to close the editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Download your edited image or save a copy to ente to persist your changes.", - "BRIGHTNESS": "Brightness", - "CONTRAST": "Contrast", - "SATURATION": "Saturation", - "BLUR": "Blur", - "INVERT_COLORS": "Invert Colors", - "ASPECT_RATIO": "Aspect Ratio", - "SQUARE": "Square", - "ROTATE_LEFT": "Rotate Left", - "ROTATE_RIGHT": "Rotate Right", - "FLIP_VERTICALLY": "Flip Vertically", - "FLIP_HORIZONTALLY": "Flip Horizontally", - "DOWNLOAD_EDITED": "Download Edited", - "SAVE_A_COPY_TO_ENTE": "Save a copy to ente", - "RESTORE_ORIGINAL": "Restore Original", - "TRANSFORM": "Transform", - "COLORS": "Colors", - "FLIP": "Flip", - "ROTATION": "Rotation", - "RESET": "Reset", - "PHOTO_EDITOR": "Photo Editor", - "FASTER_UPLOAD": "Faster uploads", - "FASTER_UPLOAD_DESCRIPTION": "Route uploads through nearby servers", - "MAGIC_SEARCH_STATUS": "Magic Search Status", - "INDEXED_ITEMS": "Indexed items", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", - "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", - "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/ru-RU/translation.json b/web/apps/auth/public/locales/ru-RU/translation.json index 6870df3194..c85db22361 100644 --- a/web/apps/auth/public/locales/ru-RU/translation.json +++ b/web/apps/auth/public/locales/ru-RU/translation.json @@ -1,644 +1,654 @@ { - "HERO_SLIDE_1_TITLE": "
Private backups
for your memories
", - "HERO_SLIDE_1": "End-to-end encrypted by default", - "HERO_SLIDE_2_TITLE": "
Safely stored
at a fallout shelter
", - "HERO_SLIDE_2": "Designed to outlive", - "HERO_SLIDE_3_TITLE": "
Available
everywhere
", - "HERO_SLIDE_3": "Android, iOS, Web, Desktop", - "LOGIN": "Login", - "SIGN_UP": "Signup", - "NEW_USER": "New to ente", - "EXISTING_USER": "Existing user", - "ENTER_NAME": "Enter name", - "PUBLIC_UPLOADER_NAME_MESSAGE": "Add a name so that your friends know who to thank for these great photos!", - "ENTER_EMAIL": "Enter email address", - "EMAIL_ERROR": "Enter a valid email", - "REQUIRED": "Required", - "EMAIL_SENT": "Verification code sent to {{email}}", - "CHECK_INBOX": "Please check your inbox (and spam) to complete verification", - "ENTER_OTT": "Verification code", - "RESEND_MAIL": "Resend code", - "VERIFY": "Verify", - "UNKNOWN_ERROR": "Something went wrong, please try again", - "INVALID_CODE": "Invalid verification code", - "EXPIRED_CODE": "Your verification code has expired", - "SENDING": "Sending...", - "SENT": "Sent!", - "PASSWORD": "Password", - "LINK_PASSWORD": "Enter password to unlock the album", - "RETURN_PASSPHRASE_HINT": "Password", - "SET_PASSPHRASE": "Set password", - "VERIFY_PASSPHRASE": "Sign in", - "INCORRECT_PASSPHRASE": "Incorrect password", - "ENTER_ENC_PASSPHRASE": "Please enter a password that we can use to encrypt your data", - "PASSPHRASE_DISCLAIMER": "We don't store your password, so if you forget it, we will not be able to help you recover your data without a recovery key.", - "WELCOME_TO_ENTE_HEADING": "Welcome to ", - "WELCOME_TO_ENTE_SUBHEADING": "End to end encrypted photo storage and sharing", - "WHERE_YOUR_BEST_PHOTOS_LIVE": "Where your best photos live", - "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generating encryption keys...", - "PASSPHRASE_HINT": "Password", - "CONFIRM_PASSPHRASE": "Confirm password", - "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", - "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", - "PASSPHRASE_MATCH_ERROR": "Passwords don't match", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "This is a browser feature intended for developers. Please don't copy-paste unverified code here.", - "CREATE_COLLECTION": "New album", - "ENTER_ALBUM_NAME": "Album name", - "CLOSE_OPTION": "Close (Esc)", - "ENTER_FILE_NAME": "File name", - "CLOSE": "Close", - "NO": "No", - "NOTHING_HERE": "Nothing to see here yet 👀", - "UPLOAD": "Upload", - "IMPORT": "Import", - "ADD_PHOTOS": "Add photos", - "ADD_MORE_PHOTOS": "Add more photos", - "add_photos_one": "Add 1 item", - "add_photos_other": "Add {{count, number}} items", - "SELECT_PHOTOS": "Select photos", - "FILE_UPLOAD": "File Upload", + "HERO_SLIDE_1_TITLE": "
Личные резервные копии
для твоих воспоминаний
", + "HERO_SLIDE_1": "Сквозное шифрование по умолчанию", + "HERO_SLIDE_2_TITLE": "
Надежно хранится
в убежище от радиоактивных осадков
", + "HERO_SLIDE_2": "Созданный для того, чтобы пережить", + "HERO_SLIDE_3_TITLE": "
Доступно
везде
", + "HERO_SLIDE_3": "Android, iOS, Веб, ПК", + "LOGIN": "Авторизоваться", + "SIGN_UP": "Регистрация", + "NEW_USER": "Новенький в ente", + "EXISTING_USER": "Существующий пользователь", + "ENTER_NAME": "Введите имя", + "PUBLIC_UPLOADER_NAME_MESSAGE": "Добавьте имя, чтобы ваши друзья знали, кого благодарить за эти замечательные фотографии!", + "ENTER_EMAIL": "Введите адрес электронной почты", + "EMAIL_ERROR": "Введите действительный адрес электронной почты", + "REQUIRED": "Требуется", + "EMAIL_SENT": "Проверочный код отправлен на
{{email}}", + "CHECK_INBOX": "Пожалуйста, проверьте свой почтовый ящик (и спам) для завершения проверки", + "ENTER_OTT": "Проверочный код", + "RESEND_MAIL": "Отправить код еще раз", + "VERIFY": "Подтвердить", + "UNKNOWN_ERROR": "Что-то пошло не так, Попробуйте еще раз", + "INVALID_CODE": "Неверный код подтверждения", + "EXPIRED_CODE": "Срок действия вашего проверочного кода истек", + "SENDING": "Отправка...", + "SENT": "Отправлено!", + "PASSWORD": "Пароль", + "LINK_PASSWORD": "Введите пароль, чтобы разблокировать альбом", + "RETURN_PASSPHRASE_HINT": "Пароль", + "SET_PASSPHRASE": "Установить пароль", + "VERIFY_PASSPHRASE": "Войти", + "INCORRECT_PASSPHRASE": "Неверный пароль", + "ENTER_ENC_PASSPHRASE": "Пожалуйста, введите пароль, который мы можем использовать для шифрования ваших данных", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "Добро пожаловать в ", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "Где живут ваши лучшие фотографии", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Генерируем ключи шифрования...", + "PASSPHRASE_HINT": "Пароль", + "CONFIRM_PASSPHRASE": "Подтвердите пароль", + "REFERRAL_CODE_HINT": "Как вы узнали о Ente? (необязательно)", + "REFERRAL_INFO": "Будет полезно, если вы укажете, где нашли нас, так как мы не отслеживаем установки приложения!", + "PASSPHRASE_MATCH_ERROR": "Пароли не совпадают", + "CREATE_COLLECTION": "Новый альбом", + "ENTER_ALBUM_NAME": "Название альбома", + "CLOSE_OPTION": "Закрыть (Esc)", + "ENTER_FILE_NAME": "Имя файла", + "CLOSE": "Закрыть", + "NO": "Нет", + "NOTHING_HERE": "Здесь нечего смотреть! 👀", + "UPLOAD": "Загрузить", + "IMPORT": "Импорт", + "ADD_PHOTOS": "Добавить фотографии", + "ADD_MORE_PHOTOS": "Добавить больше фото", + "add_photos_one": "Добавить 1 элемент", + "add_photos_other": "Добавить {{count, number}} элементов", + "SELECT_PHOTOS": "Выбрать фотографии", + "FILE_UPLOAD": "Загрузка файла", "UPLOAD_STAGE_MESSAGE": { - "0": "Preparing to upload", - "1": "Reading google metadata files", - "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files metadata extracted", - "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files processed", - "4": "Cancelling remaining uploads", - "5": "Backup complete" + "0": "Подготовка к загрузке", + "1": "Чтение файлов метаданных Google", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} файлов извлечены", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} файлов обработано", + "4": "Отмена оставшихся загрузок", + "5": "Резервное копирование завершено" }, - "FILE_NOT_UPLOADED_LIST": "The following files were not uploaded", - "SUBSCRIPTION_EXPIRED": "Subscription expired", - "SUBSCRIPTION_EXPIRED_MESSAGE": "Your subscription has expired, please renew", - "STORAGE_QUOTA_EXCEEDED": "Storage limit exceeded", - "INITIAL_LOAD_DELAY_WARNING": "First load may take some time", - "USER_DOES_NOT_EXIST": "Sorry, could not find a user with that email", - "NO_ACCOUNT": "Don't have an account", - "ACCOUNT_EXISTS": "Already have an account", - "CREATE": "Create", - "DOWNLOAD": "Download", - "DOWNLOAD_OPTION": "Download (D)", - "DOWNLOAD_FAVORITES": "Download favorites", - "DOWNLOAD_UNCATEGORIZED": "Download uncategorized", - "DOWNLOAD_HIDDEN_ITEMS": "Download hidden items", - "COPY_OPTION": "Copy as PNG (Ctrl/Cmd - C)", - "TOGGLE_FULLSCREEN": "Toggle fullscreen (F)", - "ZOOM_IN_OUT": "Zoom in/out", - "PREVIOUS": "Previous (←)", - "NEXT": "Next (→)", - "TITLE_PHOTOS": "Ente Photos", - "TITLE_ALBUMS": "Ente Photos", - "TITLE_AUTH": "Ente Auth", - "UPLOAD_FIRST_PHOTO": "Upload your first photo", - "IMPORT_YOUR_FOLDERS": "Import your folders", - "UPLOAD_DROPZONE_MESSAGE": "Drop to backup your files", - "WATCH_FOLDER_DROPZONE_MESSAGE": "Drop to add watched folder", - "TRASH_FILES_TITLE": "Delete files?", - "TRASH_FILE_TITLE": "Delete file?", - "DELETE_FILES_TITLE": "Delete immediately?", - "DELETE_FILES_MESSAGE": "Selected files will be permanently deleted from your ente account.", - "DELETE": "Delete", - "DELETE_OPTION": "Delete (DEL)", - "FAVORITE_OPTION": "Favorite (L)", - "UNFAVORITE_OPTION": "Unfavorite (L)", - "MULTI_FOLDER_UPLOAD": "Multiple folders detected", - "UPLOAD_STRATEGY_CHOICE": "Would you like to upload them into", - "UPLOAD_STRATEGY_SINGLE_COLLECTION": "A single album", - "OR": "or", - "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Separate albums", - "SESSION_EXPIRED_MESSAGE": "Your session has expired, please login again to continue", - "SESSION_EXPIRED": "Session expired", - "PASSWORD_GENERATION_FAILED": "Your browser was unable to generate a strong key that meets ente's encryption standards, please try using the mobile app or another browser", - "CHANGE_PASSWORD": "Change password", - "GO_BACK": "Go back", - "RECOVERY_KEY": "Recovery key", - "SAVE_LATER": "Do this later", - "SAVE": "Save Key", - "RECOVERY_KEY_DESCRIPTION": "If you forget your password, the only way you can recover your data is with this key.", - "RECOVER_KEY_GENERATION_FAILED": "Recovery code could not be generated, please try again", - "KEY_NOT_STORED_DISCLAIMER": "We don't store this key, so please save this in a safe place", - "FORGOT_PASSWORD": "Forgot password", - "RECOVER_ACCOUNT": "Recover account", - "RECOVERY_KEY_HINT": "Recovery key", - "RECOVER": "Recover", - "NO_RECOVERY_KEY": "No recovery key?", - "INCORRECT_RECOVERY_KEY": "Incorrect recovery key", - "SORRY": "Sorry", - "NO_RECOVERY_KEY_MESSAGE": "Due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Please drop an email to {{emailID}} from your registered email address", - "CONTACT_SUPPORT": "Contact support", - "REQUEST_FEATURE": "Request Feature", - "SUPPORT": "Support", - "CONFIRM": "Confirm", - "CANCEL": "Cancel", - "LOGOUT": "Logout", - "DELETE_ACCOUNT": "Delete account", - "DELETE_ACCOUNT_MESSAGE": "

Please send an email to {{emailID}} from your registered email address.

Your request will be processed within 72 hours.

", - "LOGOUT_MESSAGE": "Are you sure you want to logout?", - "CHANGE_EMAIL": "Change email", - "OK": "OK", - "SUCCESS": "Success", - "ERROR": "Error", - "MESSAGE": "Message", - "INSTALL_MOBILE_APP": "Install our Android or iOS app to automatically backup all your photos", - "DOWNLOAD_APP_MESSAGE": "Sorry, this operation is currently only supported on our desktop app", - "DOWNLOAD_APP": "Download desktop app", - "EXPORT": "Export Data", - "SUBSCRIPTION": "Subscription", - "SUBSCRIBE": "Subscribe", - "MANAGEMENT_PORTAL": "Manage payment method", - "MANAGE_FAMILY_PORTAL": "Manage family", - "LEAVE_FAMILY_PLAN": "Leave family plan", - "LEAVE": "Leave", - "LEAVE_FAMILY_CONFIRM": "Are you sure that you want to leave family plan?", - "CHOOSE_PLAN": "Choose your plan", - "MANAGE_PLAN": "Manage your subscription", - "ACTIVE": "Active", - "OFFLINE_MSG": "You are offline, cached memories are being shown", - "FREE_SUBSCRIPTION_INFO": "You are on the free plan that expires on {{date, dateTime}}", - "FAMILY_SUBSCRIPTION_INFO": "You are on a family plan managed by", - "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Renews on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Ends on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Your subscription will be cancelled on {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", - "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "You have exceeded your storage quota, please upgrade", - "SUBSCRIPTION_PURCHASE_SUCCESS": "

We've received your payment

Your subscription is valid till {{date, dateTime}}

", - "SUBSCRIPTION_PURCHASE_CANCELLED": "Your purchase was canceled, please try again if you want to subscribe", - "SUBSCRIPTION_PURCHASE_FAILED": "Subscription purchase failed , please try again", - "SUBSCRIPTION_UPDATE_FAILED": "Subscription updated failed , please try again", - "UPDATE_PAYMENT_METHOD_MESSAGE": "We are sorry, payment failed when we tried to charge your card, please update your payment method and try again", - "STRIPE_AUTHENTICATION_FAILED": "We are unable to authenticate your payment method. please choose a different payment method and try again", - "UPDATE_PAYMENT_METHOD": "Update payment method", - "MONTHLY": "Monthly", - "YEARLY": "Yearly", - "UPDATE_SUBSCRIPTION_MESSAGE": "Are you sure you want to change your plan?", - "UPDATE_SUBSCRIPTION": "Change plan", - "CANCEL_SUBSCRIPTION": "Cancel subscription", - "CANCEL_SUBSCRIPTION_MESSAGE": "

All of your data will be deleted from our servers at the end of this billing period.

Are you sure that you want to cancel your subscription?

", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

", - "SUBSCRIPTION_CANCEL_FAILED": "Failed to cancel subscription", - "SUBSCRIPTION_CANCEL_SUCCESS": "Subscription canceled successfully", - "REACTIVATE_SUBSCRIPTION": "Reactivate subscription", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "Once reactivated, you will be billed on {{date, dateTime}}", - "SUBSCRIPTION_ACTIVATE_SUCCESS": "Subscription activated successfully ", - "SUBSCRIPTION_ACTIVATE_FAILED": "Failed to reactivate subscription renewals", - "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Thank you", - "CANCEL_SUBSCRIPTION_ON_MOBILE": "Cancel mobile subscription", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Please cancel your subscription from the mobile app to activate a subscription here", - "MAIL_TO_MANAGE_SUBSCRIPTION": "Please contact us at {{emailID}} to manage your subscription", - "RENAME": "Rename", - "RENAME_FILE": "Rename file", - "RENAME_COLLECTION": "Rename album", - "DELETE_COLLECTION_TITLE": "Delete album?", - "DELETE_COLLECTION": "Delete album", - "DELETE_COLLECTION_MESSAGE": "Also delete the photos (and videos) present in this album from all other albums they are part of?", - "DELETE_PHOTOS": "Delete photos", - "KEEP_PHOTOS": "Keep photos", - "SHARE": "Share", - "SHARE_COLLECTION": "Share album", - "SHAREES": "Shared with", - "SHARE_WITH_SELF": "Oops, you cannot share with yourself", - "ALREADY_SHARED": "Oops, you're already sharing this with {{email}}", - "SHARING_BAD_REQUEST_ERROR": "Sharing album not allowed", - "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Sharing is disabled for free accounts", - "DOWNLOAD_COLLECTION": "Download album", - "DOWNLOAD_COLLECTION_MESSAGE": "

Are you sure you want to download the complete album?

All files will be queued for download sequentially

", - "CREATE_ALBUM_FAILED": "Failed to create album , please try again", - "SEARCH": "Search", - "SEARCH_RESULTS": "Search results", - "NO_RESULTS": "No results found", - "SEARCH_HINT": "Search for albums, dates, descriptions, ...", + "FILE_NOT_UPLOADED_LIST": "Следующие файлы не были загружены", + "SUBSCRIPTION_EXPIRED": "Подписка закончилась", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Срок действия вашей подписки истек, пожалуйста, продлите", + "STORAGE_QUOTA_EXCEEDED": "Превышен лимит хранения", + "INITIAL_LOAD_DELAY_WARNING": "Первая загрузка может занять некоторое время", + "USER_DOES_NOT_EXIST": "Пользователь с таким email не найден", + "NO_ACCOUNT": "У вас нет учетной записи", + "ACCOUNT_EXISTS": "Уже есть аккаунт", + "CREATE": "Создать", + "DOWNLOAD": "Скачать", + "DOWNLOAD_OPTION": "Скачать (D)", + "DOWNLOAD_FAVORITES": "Скачать избранные", + "DOWNLOAD_UNCATEGORIZED": "Скачать без категорий", + "DOWNLOAD_HIDDEN_ITEMS": "Скачать скрытые элементы", + "COPY_OPTION": "Скопировать как PNG (Ctrl/Cmd - C)", + "TOGGLE_FULLSCREEN": "Полноэкранный режим (F)", + "ZOOM_IN_OUT": "Увеличить/уменьшить", + "PREVIOUS": "Предыдущий (←)", + "NEXT": "Следующий (→)", + "TITLE_PHOTOS": "Ente Фото", + "TITLE_ALBUMS": "Ente Фото", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "Загрузите своё первое фото", + "IMPORT_YOUR_FOLDERS": "Импортируйте папки", + "UPLOAD_DROPZONE_MESSAGE": "Перетащите для резервного копирования файлов", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Перетащите, чтобы добавить просматриваемую папку", + "TRASH_FILES_TITLE": "Удалить файлы?", + "TRASH_FILE_TITLE": "Удалить файл?", + "DELETE_FILES_TITLE": "Удалить немедленно?", + "DELETE_FILES_MESSAGE": "Выбранные файлы будут безвозвратно удалены из вашей учетной записи ente.", + "DELETE": "Удалить", + "DELETE_OPTION": "Удалить (DEL)", + "FAVORITE_OPTION": "Избранное (L)", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "Обнаружено несколько папок", + "UPLOAD_STRATEGY_CHOICE": "Вы хотите загрузить их в", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Один альбом", + "OR": "или", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Отдельные альбомы", + "SESSION_EXPIRED_MESSAGE": "Истёк срок действия вашей сессии. Для продолжения, пожалуйста, войдите снова", + "SESSION_EXPIRED": "Время сессии истекло", + "PASSWORD_GENERATION_FAILED": "Вашему браузеру не удалось сгенерировать надежный ключ, соответствующий стандартам шифрования ente, пожалуйста, попробуйте использовать мобильное приложение или другой браузер", + "CHANGE_PASSWORD": "Изменить пароль", + "GO_BACK": "Вернуться назад", + "RECOVERY_KEY": "Ключ восстановления", + "SAVE_LATER": "Сделать позже", + "SAVE": "Сохранить ключ", + "RECOVERY_KEY_DESCRIPTION": "Если вы забыли свой пароль, то восстановить данные можно только с помощью этого ключа.", + "RECOVER_KEY_GENERATION_FAILED": "Не удалось сгенерировать код восстановления, пожалуйста, повторите попытку", + "KEY_NOT_STORED_DISCLAIMER": "Мы не храним этот ключ, поэтому, пожалуйста, сохраните его в надежном месте", + "FORGOT_PASSWORD": "Забыл пароль", + "RECOVER_ACCOUNT": "Восстановить аккаунт", + "RECOVERY_KEY_HINT": "Ключ восстановления", + "RECOVER": "Восстановить", + "NO_RECOVERY_KEY": "Нет ключа восстановления?", + "INCORRECT_RECOVERY_KEY": "Неправильный ключ восстановления", + "SORRY": "Извините", + "NO_RECOVERY_KEY_MESSAGE": "Из-за природы нашего сквозного протокола шифрования ваши данные не могут быть расшифрованы без вашего пароля или ключа восстановления", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Пожалуйста, отправьте электронное письмо на адрес {{emailID}} с вашего зарегистрированного адреса электронной почты", + "CONTACT_SUPPORT": "Связаться с поддержкой", + "REQUEST_FEATURE": "Запросить функцию", + "SUPPORT": "Поддержка", + "CONFIRM": "Подтвердить", + "CANCEL": "Отменить", + "LOGOUT": "Выйти", + "DELETE_ACCOUNT": "Удалить аккаунт", + "DELETE_ACCOUNT_MESSAGE": "

Пожалуйста, отправьте письмо по адресу {{emailID}} с вашего зарегистрированного адреса электронной почты.

Ваш запрос будет обработан в течение 72 часов

", + "LOGOUT_MESSAGE": "Вы уверены, что хотите выйти?", + "CHANGE_EMAIL": "Изменить адрес электронной почты", + "OK": "ОК", + "SUCCESS": "Успешно", + "ERROR": "Ошибка", + "MESSAGE": "Сообщение", + "INSTALL_MOBILE_APP": "Установите наше приложение Android или iOS для автоматического резервного копирования всех ваших фотографий", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "Загрузить приложение для компьютера", + "EXPORT": "Экспортировать данные", + "SUBSCRIPTION": "Подписка", + "SUBSCRIBE": "Подписаться", + "MANAGEMENT_PORTAL": "Управлять платёжной информацией", + "MANAGE_FAMILY_PORTAL": "Управление семьёй", + "LEAVE_FAMILY_PLAN": "Покинуть семейный план", + "LEAVE": "Выйти", + "LEAVE_FAMILY_CONFIRM": "Вы уверены, что хотите покинуть семейный план?", + "CHOOSE_PLAN": "Выбери свой план", + "MANAGE_PLAN": "Управление подпиской", + "ACTIVE": "Активный", + "OFFLINE_MSG": "Вы не в сети, кэшированные воспоминания отображаются", + "FREE_SUBSCRIPTION_INFO": "Вы используете бесплатный тарифный план, истекающий {{date, dateTime}}", + "FAMILY_SUBSCRIPTION_INFO": "Вы используете семейный план, управляемый", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Продление {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "Обновить платёжную информацию", + "MONTHLY": "Ежемесячно", + "YEARLY": "Ежегодно", + "UPDATE_SUBSCRIPTION_MESSAGE": "Хотите сменить текущий план?", + "UPDATE_SUBSCRIPTION": "Изменить план", + "CANCEL_SUBSCRIPTION": "Отменить подписку", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Все ваши данные будут удалены с наших серверов в конце этого расчетного периода.

Вы уверены, что хотите отменить свою подписку?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Вы уверены, что хотите отменить свою подписку?

", + "SUBSCRIPTION_CANCEL_FAILED": "Не удалось отменить подписку", + "SUBSCRIPTION_CANCEL_SUCCESS": "Подписка успешно отменена", + "REACTIVATE_SUBSCRIPTION": "Возобновить подписку", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "После повторной активации вам будет выставлен счет в {{date, dateTime}}", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Подписка успешно активирована ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Не удалось повторно активировать продление подписки", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Спасибо", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Отменить мобильную подписку", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Пожалуйста, отмените свою подписку в мобильном приложении, чтобы активировать подписку здесь", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Пожалуйста, свяжитесь с {{emailID}} для управления подпиской", + "RENAME": "Переименовать", + "RENAME_FILE": "Переименовать файл", + "RENAME_COLLECTION": "Переименовать альбом", + "DELETE_COLLECTION_TITLE": "Удалить альбом?", + "DELETE_COLLECTION": "Удалить альбом", + "DELETE_COLLECTION_MESSAGE": "Также удалить фотографии (и видео), которые есть в этом альбоме из всех других альбомов, где они есть?", + "DELETE_PHOTOS": "Удалить фото", + "KEEP_PHOTOS": "Оставить фото", + "SHARE": "Поделиться", + "SHARE_COLLECTION": "Поделиться альбомом", + "SHAREES": "Поделиться с", + "SHARE_WITH_SELF": "Ой, Вы не можете поделиться с самим собой", + "ALREADY_SHARED": "Упс, Вы уже делились этим с {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Делиться альбомом запрещено", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Совместное использование отключено для бесплатных аккаунтов", + "DOWNLOAD_COLLECTION": "Загрузить альбом", + "DOWNLOAD_COLLECTION_MESSAGE": "

Вы уверены, что хотите загрузить альбом полностью?

Все файлы будут последовательно помещены в очередь на загрузку

", + "CREATE_ALBUM_FAILED": "Не удалось создать альбом, пожалуйста, попробуйте еще раз", + "SEARCH": "Поиск", + "SEARCH_RESULTS": "Результаты поиска", + "NO_RESULTS": "Ничего не найдено", + "SEARCH_HINT": "Поиск альбомов, дат, описаний, ...", "SEARCH_TYPE": { - "COLLECTION": "Album", - "LOCATION": "Location", - "CITY": "Location", - "DATE": "Date", - "FILE_NAME": "File name", - "THING": "Content", - "FILE_CAPTION": "Description", - "FILE_TYPE": "File type", - "CLIP": "Magic" + "COLLECTION": "Альбом", + "LOCATION": "Местоположение", + "CITY": "Местоположение", + "DATE": "Дата", + "FILE_NAME": "Имя файла", + "THING": "Содержимое", + "FILE_CAPTION": "Описание", + "FILE_TYPE": "Тип файла", + "CLIP": "" }, - "photos_count_zero": "No memories", - "photos_count_one": "1 memory", - "photos_count_other": "{{count, number}} memories", - "TERMS_AND_CONDITIONS": "I agree to the terms and privacy policy", - "ADD_TO_COLLECTION": "Add to album", - "SELECTED": "selected", - "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "This video cannot be played on your browser", - "PEOPLE": "People", - "INDEXING_SCHEDULED": "Indexing is scheduled...", - "ANALYZING_PHOTOS": "Indexing photos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", - "INDEXING_PEOPLE": "Indexing people in {{indexStatus.nSyncedFiles,number}} photos...", - "INDEXING_DONE": "Indexed {{indexStatus.nSyncedFiles,number}} photos", - "UNIDENTIFIED_FACES": "unidentified faces", - "OBJECTS": "objects", - "TEXT": "text", - "INFO": "Info ", - "INFO_OPTION": "Info (I)", - "FILE_NAME": "File name", - "CAPTION_PLACEHOLDER": "Add a description", - "LOCATION": "Location", - "SHOW_ON_MAP": "View on OpenStreetMap", - "MAP": "Map", - "MAP_SETTINGS": "Map Settings", - "ENABLE_MAPS": "Enable Maps?", - "ENABLE_MAP": "Enable map", - "DISABLE_MAPS": "Disable Maps?", - "ENABLE_MAP_DESCRIPTION": "

This will show your photos on a world map.

The map is hosted by OpenStreetMap, and the exact locations of your photos are never shared.

You can disable this feature anytime from Settings.

", - "DISABLE_MAP_DESCRIPTION": "

This will disable the display of your photos on a world map.

You can enable this feature anytime from Settings.

", - "DISABLE_MAP": "Disable map", - "DETAILS": "Details", - "VIEW_EXIF": "View all EXIF data", - "NO_EXIF": "No EXIF data", - "EXIF": "EXIF", - "ISO": "ISO", - "TWO_FACTOR": "Two-factor", - "TWO_FACTOR_AUTHENTICATION": "Two-factor authentication", - "TWO_FACTOR_QR_INSTRUCTION": "Scan the QR code below with your favorite authenticator app", - "ENTER_CODE_MANUALLY": "Enter the code manually", - "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Please enter this code in your favorite authenticator app", - "SCAN_QR_CODE": "Scan QR code instead", - "ENABLE_TWO_FACTOR": "Enable two-factor", - "ENABLE": "Enable", - "LOST_DEVICE": "Lost two-factor device", - "INCORRECT_CODE": "Incorrect code", - "TWO_FACTOR_INFO": "Add an additional layer of security by requiring more than your email and password to log in to your account", - "DISABLE_TWO_FACTOR_LABEL": "Disable two-factor authentication", - "UPDATE_TWO_FACTOR_LABEL": "Update your authenticator device", - "DISABLE": "Disable", - "RECONFIGURE": "Reconfigure", - "UPDATE_TWO_FACTOR": "Update two-factor", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuing forward will void any previously configured authenticators", - "UPDATE": "Update", - "DISABLE_TWO_FACTOR": "Disable two-factor", - "DISABLE_TWO_FACTOR_MESSAGE": "Are you sure you want to disable your two-factor authentication", - "TWO_FACTOR_DISABLE_FAILED": "Failed to disable two factor, please try again", - "EXPORT_DATA": "Export data", - "SELECT_FOLDER": "Select folder", - "DESTINATION": "Destination", - "START": "Start", - "LAST_EXPORT_TIME": "Last export time", - "EXPORT_AGAIN": "Resync", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "Local storage not accessible", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Your browser or an addon is blocking ente from saving data into local storage. please try loading this page after switching your browsing mode.", - "SEND_OTT": "Send OTP", - "EMAIl_ALREADY_OWNED": "Email already taken", - "ETAGS_BLOCKED": "

We were unable to upload the following files because of your browser configuration.

Please disable any addons that might be preventing ente from using eTags to upload large files, or use our desktop app for a more reliable import experience.

", - "SKIPPED_VIDEOS_INFO": "

Presently we do not support adding videos via public links.

To share videos, please signup for ente and share with the intended recipients using their email.

", - "LIVE_PHOTOS_DETECTED": "The photo and video files from your Live Photos have been merged into a single file", - "RETRY_FAILED": "Retry failed uploads", - "FAILED_UPLOADS": "Failed uploads ", - "SKIPPED_FILES": "Ignored uploads", - "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Thumbnail generation failed", - "UNSUPPORTED_FILES": "Unsupported files", - "SUCCESSFUL_UPLOADS": "Successful uploads", - "SKIPPED_INFO": "Skipped these as there are files with matching names in the same album", - "UNSUPPORTED_INFO": "ente does not support these file formats yet", - "BLOCKED_UPLOADS": "Blocked uploads", - "SKIPPED_VIDEOS": "Skipped videos", - "INPROGRESS_METADATA_EXTRACTION": "In progress", - "INPROGRESS_UPLOADS": "Uploads in progress", - "TOO_LARGE_UPLOADS": "Large files", - "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Insufficient storage", - "LARGER_THAN_AVAILABLE_STORAGE_INFO": "These files were not uploaded as they exceed the maximum size limit for your storage plan", - "TOO_LARGE_INFO": "These files were not uploaded as they exceed our maximum file size limit", - "THUMBNAIL_GENERATION_FAILED_INFO": "These files were uploaded, but unfortunately we could not generate the thumbnails for them.", - "UPLOAD_TO_COLLECTION": "Upload to album", - "UNCATEGORIZED": "Uncategorized", - "ARCHIVE": "Archive", - "FAVORITES": "Favorites", - "ARCHIVE_COLLECTION": "Archive album", - "ARCHIVE_SECTION_NAME": "Archive", - "ALL_SECTION_NAME": "All", - "MOVE_TO_COLLECTION": "Move to album", - "UNARCHIVE": "Unarchive", - "UNARCHIVE_COLLECTION": "Unarchive album", - "HIDE_COLLECTION": "Hide album", - "UNHIDE_COLLECTION": "Unhide album", - "MOVE": "Move", - "ADD": "Add", - "REMOVE": "Remove", - "YES_REMOVE": "Yes, remove", - "REMOVE_FROM_COLLECTION": "Remove from album", - "TRASH": "Trash", - "MOVE_TO_TRASH": "Move to trash", - "TRASH_FILES_MESSAGE": "Selected files will be removed from all albums and moved to trash.", - "TRASH_FILE_MESSAGE": "The file will be removed from all albums and moved to trash.", - "DELETE_PERMANENTLY": "Delete permanently", - "RESTORE": "Restore", - "RESTORE_TO_COLLECTION": "Restore to album", - "EMPTY_TRASH": "Empty trash", - "EMPTY_TRASH_TITLE": "Empty trash?", - "EMPTY_TRASH_MESSAGE": "These files will be permanently deleted from your ente account.", - "LEAVE_SHARED_ALBUM": "Yes, leave", - "LEAVE_ALBUM": "Leave album", - "LEAVE_SHARED_ALBUM_TITLE": "Leave shared album?", - "LEAVE_SHARED_ALBUM_MESSAGE": "You will leave the album, and it will stop being visible to you.", - "NOT_FILE_OWNER": "You cannot delete files in a shared album", - "CONFIRM_SELF_REMOVE_MESSAGE": "Selected items will be removed from this album. Items which are only in this album will be moved to Uncategorized.", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Some of the items you are removing were added by other people, and you will lose access to them.", - "SORT_BY_CREATION_TIME_ASCENDING": "Oldest", - "SORT_BY_UPDATION_TIME_DESCENDING": "Last updated", - "SORT_BY_NAME": "Name", - "COMPRESS_THUMBNAILS": "Compress thumbnails", - "THUMBNAIL_REPLACED": "Thumbnails compressed", - "FIX_THUMBNAIL": "Compress", - "FIX_THUMBNAIL_LATER": "Compress later", - "REPLACE_THUMBNAIL_NOT_STARTED": "Some of your videos thumbnails can be compressed to save space. would you like ente to compress them?", - "REPLACE_THUMBNAIL_COMPLETED": "Successfully compressed all thumbnails", - "REPLACE_THUMBNAIL_NOOP": "You have no thumbnails that can be compressed further", - "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Could not compress some of your thumbnails, please retry", - "FIX_CREATION_TIME": "Fix time", - "FIX_CREATION_TIME_IN_PROGRESS": "Fixing time", - "CREATION_TIME_UPDATED": "File time updated", - "UPDATE_CREATION_TIME_NOT_STARTED": "Select the option you want to use", - "UPDATE_CREATION_TIME_COMPLETED": "Successfully updated all files", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "File time updation failed for some files, please retry", - "CAPTION_CHARACTER_LIMIT": "5000 characters max", - "DATE_TIME_ORIGINAL": "EXIF:DateTimeOriginal", - "DATE_TIME_DIGITIZED": "EXIF:DateTimeDigitized", - "METADATA_DATE": "EXIF:MetadataDate", - "CUSTOM_TIME": "Custom time", - "REOPEN_PLAN_SELECTOR_MODAL": "Re-open plans", - "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Failed to open plans", - "INSTALL": "Install", - "SHARING_DETAILS": "Sharing details", - "MODIFY_SHARING": "Modify sharing", - "ADD_COLLABORATORS": "Add collaborators", - "ADD_NEW_EMAIL": "Add a new email", - "shared_with_people_zero": "Share with specific people", - "shared_with_people_one": "Shared with 1 person", - "shared_with_people_other": "Shared with {{count, number}} people", - "participants_zero": "No participants", - "participants_one": "1 participant", - "participants_other": "{{count, number}} participants", - "ADD_VIEWERS": "Add viewers", - "PARTICIPANTS": "Participants", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} will not be able to add more photos to the album

They will still be able to remove photos added by them

", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} will be able to add photos to the album", - "CONVERT_TO_VIEWER": "Yes, convert to viewer", - "CONVERT_TO_COLLABORATOR": "Yes, convert to collaborator", - "CHANGE_PERMISSION": "Change permission?", - "REMOVE_PARTICIPANT": "Remove?", - "CONFIRM_REMOVE": "Yes, remove", - "MANAGE": "Manage", - "ADDED_AS": "Added as", - "COLLABORATOR_RIGHTS": "Collaborators can add photos and videos to the shared album", - "REMOVE_PARTICIPANT_HEAD": "Remove participant", - "OWNER": "Owner", - "COLLABORATORS": "Collaborators", - "ADD_MORE": "Add more", - "VIEWERS": "Viewers", - "OR_ADD_EXISTING": "Or pick an existing one", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} will be removed from the album

Any photos added by them will also be removed from the album

", - "NOT_FOUND": "404 - not found", - "LINK_EXPIRED": "Link expired", - "LINK_EXPIRED_MESSAGE": "This link has either expired or been disabled!", - "MANAGE_LINK": "Manage link", - "LINK_TOO_MANY_REQUESTS": "Sorry, this album has been viewed on too many devices!", - "FILE_DOWNLOAD": "Allow downloads", - "LINK_PASSWORD_LOCK": "Password lock", - "PUBLIC_COLLECT": "Allow adding photos", - "LINK_DEVICE_LIMIT": "Device limit", - "NO_DEVICE_LIMIT": "None", - "LINK_EXPIRY": "Link expiry", - "NEVER": "Never", - "DISABLE_FILE_DOWNLOAD": "Disable download", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Are you sure that you want to disable the download button for files?

Viewers can still take screenshots or save a copy of your photos using external tools.

", - "MALICIOUS_CONTENT": "Contains malicious content", - "COPYRIGHT": "Infringes on the copyright of someone I am authorized to represent", - "SHARED_USING": "Shared using ", - "ENTE_IO": "ente.io", - "SHARING_REFERRAL_CODE": "Use code {{referralCode}} to get 10 GB free", - "LIVE": "LIVE", - "DISABLE_PASSWORD": "Disable password lock", - "DISABLE_PASSWORD_MESSAGE": "Are you sure that you want to disable the password lock?", - "PASSWORD_LOCK": "Password lock", - "LOCK": "Lock", - "DOWNLOAD_UPLOAD_LOGS": "Debug logs", - "UPLOAD_FILES": "File", - "UPLOAD_DIRS": "Folder", - "UPLOAD_GOOGLE_TAKEOUT": "Google takeout", - "DEDUPLICATE_FILES": "Deduplicate files", - "AUTHENTICATOR_SECTION": "Authenticator", - "NO_DUPLICATES_FOUND": "You've no duplicate files that can be cleared", - "CLUB_BY_CAPTURE_TIME": "Club by capture time", - "FILES": "Files", - "EACH": "Each", - "DEDUPLICATE_BASED_ON_SIZE": "The following files were clubbed based on their sizes, please review and delete items you believe are duplicates", - "STOP_ALL_UPLOADS_MESSAGE": "Are you sure that you want to stop all the uploads in progress?", - "STOP_UPLOADS_HEADER": "Stop uploads?", - "YES_STOP_UPLOADS": "Yes, stop uploads", - "STOP_DOWNLOADS_HEADER": "Stop downloads?", - "YES_STOP_DOWNLOADS": "Yes, stop downloads", - "STOP_ALL_DOWNLOADS_MESSAGE": "Are you sure that you want to stop all the downloads in progress?", - "albums_one": "1 Album", - "albums_other": "{{count, number}} Albums", - "ALL_ALBUMS": "All Albums", - "ALBUMS": "Albums", - "ALL_HIDDEN_ALBUMS": "All hidden albums", - "HIDDEN_ALBUMS": "Hidden albums", - "HIDDEN_ITEMS": "Hidden items", - "HIDDEN_ITEMS_SECTION_NAME": "Hidden_items", - "ENTER_TWO_FACTOR_OTP": "Enter the 6-digit code from your authenticator app.", - "CREATE_ACCOUNT": "Create account", - "COPIED": "Copied", - "CANVAS_BLOCKED_TITLE": "Unable to generate thumbnail", - "CANVAS_BLOCKED_MESSAGE": "

It looks like your browser has disabled access to canvas, which is necessary to generate thumbnails for your photos

Please enable access to your browser's canvas, or check out our desktop app

", - "WATCH_FOLDERS": "Watch folders", - "UPGRADE_NOW": "Upgrade now", - "RENEW_NOW": "Renew now", - "STORAGE": "Storage", - "USED": "used", - "YOU": "You", - "FAMILY": "Family", - "FREE": "free", - "OF": "of", - "WATCHED_FOLDERS": "Watched folders", - "NO_FOLDERS_ADDED": "No folders added yet!", - "FOLDERS_AUTOMATICALLY_MONITORED": "The folders you add here will monitored to automatically", - "UPLOAD_NEW_FILES_TO_ENTE": "Upload new files to ente", - "REMOVE_DELETED_FILES_FROM_ENTE": "Remove deleted files from ente", - "ADD_FOLDER": "Add folder", - "STOP_WATCHING": "Stop watching", - "STOP_WATCHING_FOLDER": "Stop watching folder?", - "STOP_WATCHING_DIALOG_MESSAGE": "Your existing files will not be deleted, but ente will stop automatically updating the linked ente album on changes in this folder.", - "YES_STOP": "Yes, stop", - "MONTH_SHORT": "mo", - "YEAR": "year", - "FAMILY_PLAN": "Family plan", - "DOWNLOAD_LOGS": "Download logs", - "DOWNLOAD_LOGS_MESSAGE": "

This will download debug logs, which you can email to us to help debug your issue.

Please note that file names will be included to help track issues with specific files.

", - "CHANGE_FOLDER": "Change Folder", - "TWO_MONTHS_FREE": "Get 2 months free on yearly plans", - "GB": "GB", - "POPULAR": "Popular", - "FREE_PLAN_OPTION_LABEL": "Continue with free trial", - "FREE_PLAN_DESCRIPTION": "1 GB for 1 year", - "CURRENT_USAGE": "Current usage is {{usage}}", - "WEAK_DEVICE": "The web browser you're using is not powerful enough to encrypt your photos. Please try to log in to ente on your computer, or download the ente mobile/desktop app.", - "DRAG_AND_DROP_HINT": "Or drag and drop into the ente window", - "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Your uploaded data will be scheduled for deletion, and your account will be permanently deleted.

This action is not reversible.", - "AUTHENTICATE": "Authenticate", - "UPLOADED_TO_SINGLE_COLLECTION": "Uploaded to single collection", - "UPLOADED_TO_SEPARATE_COLLECTIONS": "Uploaded to separate collections", - "NEVERMIND": "Nevermind", - "UPDATE_AVAILABLE": "Update available", - "UPDATE_INSTALLABLE_MESSAGE": "A new version of ente is ready to be installed.", - "INSTALL_NOW": "Install now", - "INSTALL_ON_NEXT_LAUNCH": "Install on next launch", - "UPDATE_AVAILABLE_MESSAGE": "A new version of ente has been released, but it cannot be automatically downloaded and installed.", - "DOWNLOAD_AND_INSTALL": "Download and install", - "IGNORE_THIS_VERSION": "Ignore this version", - "TODAY": "Today", - "YESTERDAY": "Yesterday", - "NAME_PLACEHOLDER": "Name...", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Cannot create albums from file/folder mix", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

You have dragged and dropped a mixture of files and folders.

Please provide either only files, or only folders when selecting option to create separate albums

", - "CHOSE_THEME": "Choose theme", - "ML_SEARCH": "Face recognition", - "ENABLE_ML_SEARCH_DESCRIPTION": "

This will enable on-device machine learning and face search which will start analyzing your uploaded photos locally.

For the first run after login or enabling this feature, it will download all images on local device to analyze them. So please only enable this if you are ok with bandwidth and local processing of all images in your photo library.

If this is the first time you're enabling this, we'll also ask your permission to process face data.

", - "ML_MORE_DETAILS": "More details", - "ENABLE_FACE_SEARCH": "Enable face recognition", - "ENABLE_FACE_SEARCH_TITLE": "Enable face recognition?", - "ENABLE_FACE_SEARCH_DESCRIPTION": "

If you enable face recognition, ente will extract face geometry from your photos. This will happen on your device, and any generated biometric data will be end-to-encrypted.

Please click here for more details about this feature in our privacy policy

", - "DISABLE_BETA": "Pause recognition", - "DISABLE_FACE_SEARCH": "Disable face recognition", - "DISABLE_FACE_SEARCH_TITLE": "Disable face recognition?", - "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente will stop processing face geometry.

You can reenable face recognition again if you wish, so this operation is safe.

", - "ADVANCED": "Advanced", - "FACE_SEARCH_CONFIRMATION": "I understand, and wish to allow ente to process face geometry", - "LABS": "Labs", - "YOURS": "yours", - "PASSPHRASE_STRENGTH_WEAK": "Password strength: Weak", - "PASSPHRASE_STRENGTH_MODERATE": "Password strength: Moderate", - "PASSPHRASE_STRENGTH_STRONG": "Password strength: Strong", - "PREFERENCES": "Preferences", - "LANGUAGE": "Language", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Invalid export directory", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

The export directory you have selected does not exist.

Please select a valid directory.

", - "SUBSCRIPTION_VERIFICATION_ERROR": "Subscription verification failed", + "photos_count_zero": "Воспоминания отсутствуют", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "Добавить в альбом", + "SELECTED": "выбрано", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Это видео нельзя воспроизвести в вашем браузере", + "PEOPLE": "Люди", + "INDEXING_SCHEDULED": "Индексация запланирована...", + "ANALYZING_PHOTOS": "Индексирование фотографий ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", + "INDEXING_PEOPLE": "Индексирование людей на {{indexStatus.nSyncedFiles,number}} фотографиях...", + "INDEXING_DONE": "Проиндексировано {{indexStatus.nSyncedFiles,number}} фотографий", + "UNIDENTIFIED_FACES": "нераспознанные лица", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "Двухфакторная аутентификация", + "TWO_FACTOR_QR_INSTRUCTION": "Сканируйте QR-код ниже с вашим любимым приложением для проверки подлинности", + "ENTER_CODE_MANUALLY": "Введите код вручную", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Пожалуйста, введите этот код в вашем любимом приложении для аутентификации", + "SCAN_QR_CODE": "Сканировать QR-код вместо", + "ENABLE_TWO_FACTOR": "Включить двухфакторную аутентификацию", + "ENABLE": "Включить", + "LOST_DEVICE": "Потеряно двухфакторное устройство", + "INCORRECT_CODE": "Неверный код", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "Отключить двухфакторную аутентификацию", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "Отключить", + "RECONFIGURE": "Перенастроить", + "UPDATE_TWO_FACTOR": "Обновить двухфакторную аутентификацию", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "Обновить", + "DISABLE_TWO_FACTOR": "Отключить двухфакторную аутентификацию", + "DISABLE_TWO_FACTOR_MESSAGE": "Вы уверены, что хотите отключить двухфакторную аутентификацию", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "Экспортировать данные", + "SELECT_FOLDER": "Выбрать папку", + "DESTINATION": "Место назначения", + "START": "Начать", + "LAST_EXPORT_TIME": "Время последнего экспорта", + "EXPORT_AGAIN": "Синхронизировать заново", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Локальное хранилище недоступно", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "Отправить одноразовый код", + "EMAIl_ALREADY_OWNED": "Почта уже использована", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", "STORAGE_UNITS": { - "B": "B", - "KB": "KB", - "MB": "MB", - "GB": "GB", - "TB": "TB" + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" }, "AFTER_TIME": { - "HOUR": "after an hour", - "DAY": "after a day", - "WEEK": "after a week", - "MONTH": "after a month", - "YEAR": "after a year" + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" }, - "COPY_LINK": "Copy link", - "DONE": "Done", - "LINK_SHARE_TITLE": "Or share a link", - "REMOVE_LINK": "Remove link", - "CREATE_PUBLIC_SHARING": "Create public link", - "PUBLIC_LINK_CREATED": "Public link created", - "PUBLIC_LINK_ENABLED": "Public link enabled", - "COLLECT_PHOTOS": "Collect photos", - "PUBLIC_COLLECT_SUBTEXT": "Allow people with the link to also add photos to the shared album.", - "STOP_EXPORT": "Stop", - "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} items synced", - "MIGRATING_EXPORT": "Preparing...", - "RENAMING_COLLECTION_FOLDERS": "Renaming album folders...", - "TRASHING_DELETED_FILES": "Trashing deleted files...", - "TRASHING_DELETED_COLLECTIONS": "Trashing deleted albums...", + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", "EXPORT_NOTIFICATION": { - "START": "Export started", - "IN_PROGRESS": "Export already in progress", - "FINISH": "Export finished", - "UP_TO_DATE": "No new files to export" + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" }, - "CONTINUOUS_EXPORT": "Sync continuously", - "TOTAL_ITEMS": "Total items", - "PENDING_ITEMS": "Pending items", - "EXPORT_STARTING": "Export starting...", - "DELETE_ACCOUNT_REASON_LABEL": "What is the main reason you are deleting your account?", - "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Select a reason", + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", "DELETE_REASON": { - "MISSING_FEATURE": "It's missing a key feature that I need", - "BROKEN_BEHAVIOR": "The app or a certain feature does not behave as I think it should", - "FOUND_ANOTHER_SERVICE": "I found another service that I like better", - "NOT_LISTED": "My reason isn't listed" + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" }, - "DELETE_ACCOUNT_FEEDBACK_LABEL": "We are sorry to see you go. Please explain why you are leaving to help us improve.", - "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Feedback", - "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Yes, I want to permanently delete this account and all its data", - "CONFIRM_DELETE_ACCOUNT": "Confirm Account Deletion", - "FEEDBACK_REQUIRED": "Kindly help us with this information", - "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "What does the other service do better?", - "RECOVER_TWO_FACTOR": "Recover two-factor", - "at": "at", - "AUTH_NEXT": "next", - "AUTH_DOWNLOAD_MOBILE_APP": "Download our mobile app to manage your secrets", - "HIDDEN": "Hidden", - "HIDE": "Hide", - "UNHIDE": "Unhide", - "UNHIDE_TO_COLLECTION": "Unhide to album", - "SORT_BY": "Sort by", - "NEWEST_FIRST": "Newest first", - "OLDEST_FIRST": "Oldest first", - "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "This file could not be previewed. Click here to download the original.", - "SELECT_COLLECTION": "Select album", - "PIN_ALBUM": "Pin album", - "UNPIN_ALBUM": "Unpin album", - "DOWNLOAD_COMPLETE": "Download complete", - "DOWNLOADING_COLLECTION": "Downloading {{name}}", - "DOWNLOAD_FAILED": "Download failed", - "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", - "CHRISTMAS": "Christmas", - "CHRISTMAS_EVE": "Christmas Eve", - "NEW_YEAR": "New Year", - "NEW_YEAR_EVE": "New Year's Eve", - "IMAGE": "Image", - "VIDEO": "Video", - "LIVE_PHOTO": "Live Photo", - "CONVERT": "Convert", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Are you sure you want to close the editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Download your edited image or save a copy to ente to persist your changes.", - "BRIGHTNESS": "Brightness", - "CONTRAST": "Contrast", - "SATURATION": "Saturation", - "BLUR": "Blur", - "INVERT_COLORS": "Invert Colors", - "ASPECT_RATIO": "Aspect Ratio", - "SQUARE": "Square", - "ROTATE_LEFT": "Rotate Left", - "ROTATE_RIGHT": "Rotate Right", - "FLIP_VERTICALLY": "Flip Vertically", - "FLIP_HORIZONTALLY": "Flip Horizontally", - "DOWNLOAD_EDITED": "Download Edited", - "SAVE_A_COPY_TO_ENTE": "Save a copy to ente", - "RESTORE_ORIGINAL": "Restore Original", - "TRANSFORM": "Transform", - "COLORS": "Colors", - "FLIP": "Flip", - "ROTATION": "Rotation", - "RESET": "Reset", - "PHOTO_EDITOR": "Photo Editor", - "FASTER_UPLOAD": "Faster uploads", - "FASTER_UPLOAD_DESCRIPTION": "Route uploads through nearby servers", - "MAGIC_SEARCH_STATUS": "Magic Search Status", - "INDEXED_ITEMS": "Indexed items", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", - "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", - "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "Скрыть", + "UNHIDE": "Показать", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "Сортировать по", + "NEWEST_FIRST": "Сначала новые", + "OLDEST_FIRST": "Сначала старые", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "Выбрать альбом", + "PIN_ALBUM": "Закрепить альбом", + "UNPIN_ALBUM": "Открепить альбом", + "DOWNLOAD_COMPLETE": "Загрузка завершена", + "DOWNLOADING_COLLECTION": "Загрузка {{name}}", + "DOWNLOAD_FAILED": "Загрузка не удалась", + "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} файлов", + "CHRISTMAS": "Рождество", + "CHRISTMAS_EVE": "Канун Рождества", + "NEW_YEAR": "Новый год", + "NEW_YEAR_EVE": "Канун Нового года", + "IMAGE": "Изображение", + "VIDEO": "Видео", + "LIVE_PHOTO": "Живое фото", + "CONVERT": "Преобразовать", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "Вы уверены, что хотите закрыть редактор?", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Загрузите отредактированное изображение или сохраните копию в ente, чтобы сохранить внесенные изменения.", + "BRIGHTNESS": "Яркость", + "CONTRAST": "Контраст", + "SATURATION": "Насыщенность", + "BLUR": "Размытие", + "INVERT_COLORS": "Инвертировать Цвета", + "ASPECT_RATIO": "Соотношение Сторон", + "SQUARE": "Квадрат", + "ROTATE_LEFT": "Повернуть влево", + "ROTATE_RIGHT": "Повернуть вправо", + "FLIP_VERTICALLY": "Отразить вертикально", + "FLIP_HORIZONTALLY": "Отразить горизонтально", + "DOWNLOAD_EDITED": "Скачать отредактированный", + "SAVE_A_COPY_TO_ENTE": "Сохранить копию в ente", + "RESTORE_ORIGINAL": "Восстановить оригинал", + "TRANSFORM": "Преобразовать", + "COLORS": "Цвета", + "FLIP": "Перевернуть", + "ROTATION": "", + "RESET": "Сбросить", + "PHOTO_EDITOR": "Редактор фото", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "Статус волшебного поиска", + "INDEXED_ITEMS": "Индексированные элементы", + "CAST_ALBUM_TO_TV": "Воспроизвести альбом на ТВ", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/sv-SE/translation.json b/web/apps/auth/public/locales/sv-SE/translation.json new file mode 100644 index 0000000000..f88535795a --- /dev/null +++ b/web/apps/auth/public/locales/sv-SE/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "Ange namn", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "Ange e-postadress", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "Lösenord", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "Lösenord", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "Logga in", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "Välkommen till ", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "Lösenord", + "CONFIRM_PASSPHRASE": "Bekräfta lösenord", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "Lösenorden matchar inte", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "Filnamn", + "CLOSE": "Stäng", + "NO": "Nej", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "Radera", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "eller", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "Ändra lösenord", + "GO_BACK": "", + "RECOVERY_KEY": "Återställningsnyckel", + "SAVE_LATER": "", + "SAVE": "Spara nyckel", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "Glömt lösenord", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "Ingen återställningsnyckel?", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "Bekräfta", + "CANCEL": "Avbryt", + "LOGOUT": "Logga ut", + "DELETE_ACCOUNT": "Radera konto", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "Meddelande", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "Prenumerera", + "MANAGEMENT_PORTAL": "Hantera betalningsmetod", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "Hantera din prenumeration", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "Sök", + "SEARCH_RESULTS": "Sökresultat", + "NO_RESULTS": "Inga resultat hittades", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "Datum", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "Beskrivning", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "Inga deltagare", + "participants_one": "1 deltagare", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "Deltagare", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "Fil", + "UPLOAD_DIRS": "Mapp", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "Filer", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "1 album", + "albums_other": "{{count, number}} album", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "Lägg till mapp", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "mån", + "YEAR": "år", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "GB", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "Namn...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "Språk", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "Kopiera länk", + "DONE": "Klar", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "Sortera efter", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "Bild", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "Färger", + "FLIP": "", + "ROTATION": "", + "RESET": "Återställ", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/auth/public/locales/th-TH/translation.json b/web/apps/auth/public/locales/th-TH/translation.json new file mode 100644 index 0000000000..888ed7093e --- /dev/null +++ b/web/apps/auth/public/locales/th-TH/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/auth/public/locales/tr-TR/translation.json b/web/apps/auth/public/locales/tr-TR/translation.json index 6870df3194..888ed7093e 100644 --- a/web/apps/auth/public/locales/tr-TR/translation.json +++ b/web/apps/auth/public/locales/tr-TR/translation.json @@ -1,644 +1,654 @@ { - "HERO_SLIDE_1_TITLE": "
Private backups
for your memories
", - "HERO_SLIDE_1": "End-to-end encrypted by default", - "HERO_SLIDE_2_TITLE": "
Safely stored
at a fallout shelter
", - "HERO_SLIDE_2": "Designed to outlive", - "HERO_SLIDE_3_TITLE": "
Available
everywhere
", - "HERO_SLIDE_3": "Android, iOS, Web, Desktop", - "LOGIN": "Login", - "SIGN_UP": "Signup", - "NEW_USER": "New to ente", - "EXISTING_USER": "Existing user", - "ENTER_NAME": "Enter name", - "PUBLIC_UPLOADER_NAME_MESSAGE": "Add a name so that your friends know who to thank for these great photos!", - "ENTER_EMAIL": "Enter email address", - "EMAIL_ERROR": "Enter a valid email", - "REQUIRED": "Required", - "EMAIL_SENT": "Verification code sent to
{{email}}", - "CHECK_INBOX": "Please check your inbox (and spam) to complete verification", - "ENTER_OTT": "Verification code", - "RESEND_MAIL": "Resend code", - "VERIFY": "Verify", - "UNKNOWN_ERROR": "Something went wrong, please try again", - "INVALID_CODE": "Invalid verification code", - "EXPIRED_CODE": "Your verification code has expired", - "SENDING": "Sending...", - "SENT": "Sent!", - "PASSWORD": "Password", - "LINK_PASSWORD": "Enter password to unlock the album", - "RETURN_PASSPHRASE_HINT": "Password", - "SET_PASSPHRASE": "Set password", - "VERIFY_PASSPHRASE": "Sign in", - "INCORRECT_PASSPHRASE": "Incorrect password", - "ENTER_ENC_PASSPHRASE": "Please enter a password that we can use to encrypt your data", - "PASSPHRASE_DISCLAIMER": "We don't store your password, so if you forget it, we will not be able to help you recover your data without a recovery key.", - "WELCOME_TO_ENTE_HEADING": "Welcome to ", - "WELCOME_TO_ENTE_SUBHEADING": "End to end encrypted photo storage and sharing", - "WHERE_YOUR_BEST_PHOTOS_LIVE": "Where your best photos live", - "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generating encryption keys...", - "PASSPHRASE_HINT": "Password", - "CONFIRM_PASSPHRASE": "Confirm password", - "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", - "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", - "PASSPHRASE_MATCH_ERROR": "Passwords don't match", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "This is a browser feature intended for developers. Please don't copy-paste unverified code here.", - "CREATE_COLLECTION": "New album", - "ENTER_ALBUM_NAME": "Album name", - "CLOSE_OPTION": "Close (Esc)", - "ENTER_FILE_NAME": "File name", - "CLOSE": "Close", - "NO": "No", - "NOTHING_HERE": "Nothing to see here yet 👀", - "UPLOAD": "Upload", - "IMPORT": "Import", - "ADD_PHOTOS": "Add photos", - "ADD_MORE_PHOTOS": "Add more photos", - "add_photos_one": "Add 1 item", - "add_photos_other": "Add {{count, number}} items", - "SELECT_PHOTOS": "Select photos", - "FILE_UPLOAD": "File Upload", + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", "UPLOAD_STAGE_MESSAGE": { - "0": "Preparing to upload", - "1": "Reading google metadata files", - "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files metadata extracted", - "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files processed", - "4": "Cancelling remaining uploads", - "5": "Backup complete" + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" }, - "FILE_NOT_UPLOADED_LIST": "The following files were not uploaded", - "SUBSCRIPTION_EXPIRED": "Subscription expired", - "SUBSCRIPTION_EXPIRED_MESSAGE": "Your subscription has expired, please renew", - "STORAGE_QUOTA_EXCEEDED": "Storage limit exceeded", - "INITIAL_LOAD_DELAY_WARNING": "First load may take some time", - "USER_DOES_NOT_EXIST": "Sorry, could not find a user with that email", - "NO_ACCOUNT": "Don't have an account", - "ACCOUNT_EXISTS": "Already have an account", - "CREATE": "Create", - "DOWNLOAD": "Download", - "DOWNLOAD_OPTION": "Download (D)", - "DOWNLOAD_FAVORITES": "Download favorites", - "DOWNLOAD_UNCATEGORIZED": "Download uncategorized", - "DOWNLOAD_HIDDEN_ITEMS": "Download hidden items", - "COPY_OPTION": "Copy as PNG (Ctrl/Cmd - C)", - "TOGGLE_FULLSCREEN": "Toggle fullscreen (F)", - "ZOOM_IN_OUT": "Zoom in/out", - "PREVIOUS": "Previous (←)", - "NEXT": "Next (→)", - "TITLE_PHOTOS": "Ente Photos", - "TITLE_ALBUMS": "Ente Photos", - "TITLE_AUTH": "Ente Auth", - "UPLOAD_FIRST_PHOTO": "Upload your first photo", - "IMPORT_YOUR_FOLDERS": "Import your folders", - "UPLOAD_DROPZONE_MESSAGE": "Drop to backup your files", - "WATCH_FOLDER_DROPZONE_MESSAGE": "Drop to add watched folder", - "TRASH_FILES_TITLE": "Delete files?", - "TRASH_FILE_TITLE": "Delete file?", - "DELETE_FILES_TITLE": "Delete immediately?", - "DELETE_FILES_MESSAGE": "Selected files will be permanently deleted from your ente account.", - "DELETE": "Delete", - "DELETE_OPTION": "Delete (DEL)", - "FAVORITE_OPTION": "Favorite (L)", - "UNFAVORITE_OPTION": "Unfavorite (L)", - "MULTI_FOLDER_UPLOAD": "Multiple folders detected", - "UPLOAD_STRATEGY_CHOICE": "Would you like to upload them into", - "UPLOAD_STRATEGY_SINGLE_COLLECTION": "A single album", - "OR": "or", - "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Separate albums", - "SESSION_EXPIRED_MESSAGE": "Your session has expired, please login again to continue", - "SESSION_EXPIRED": "Session expired", - "PASSWORD_GENERATION_FAILED": "Your browser was unable to generate a strong key that meets ente's encryption standards, please try using the mobile app or another browser", - "CHANGE_PASSWORD": "Change password", - "GO_BACK": "Go back", - "RECOVERY_KEY": "Recovery key", - "SAVE_LATER": "Do this later", - "SAVE": "Save Key", - "RECOVERY_KEY_DESCRIPTION": "If you forget your password, the only way you can recover your data is with this key.", - "RECOVER_KEY_GENERATION_FAILED": "Recovery code could not be generated, please try again", - "KEY_NOT_STORED_DISCLAIMER": "We don't store this key, so please save this in a safe place", - "FORGOT_PASSWORD": "Forgot password", - "RECOVER_ACCOUNT": "Recover account", - "RECOVERY_KEY_HINT": "Recovery key", - "RECOVER": "Recover", - "NO_RECOVERY_KEY": "No recovery key?", - "INCORRECT_RECOVERY_KEY": "Incorrect recovery key", - "SORRY": "Sorry", - "NO_RECOVERY_KEY_MESSAGE": "Due to the nature of our end-to-end encryption protocol, your data cannot be decrypted without your password or recovery key", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Please drop an email to {{emailID}} from your registered email address", - "CONTACT_SUPPORT": "Contact support", - "REQUEST_FEATURE": "Request Feature", - "SUPPORT": "Support", - "CONFIRM": "Confirm", - "CANCEL": "Cancel", - "LOGOUT": "Logout", - "DELETE_ACCOUNT": "Delete account", - "DELETE_ACCOUNT_MESSAGE": "

Please send an email to {{emailID}} from your registered email address.

Your request will be processed within 72 hours.

", - "LOGOUT_MESSAGE": "Are you sure you want to logout?", - "CHANGE_EMAIL": "Change email", - "OK": "OK", - "SUCCESS": "Success", - "ERROR": "Error", - "MESSAGE": "Message", - "INSTALL_MOBILE_APP": "Install our Android or iOS app to automatically backup all your photos", - "DOWNLOAD_APP_MESSAGE": "Sorry, this operation is currently only supported on our desktop app", - "DOWNLOAD_APP": "Download desktop app", - "EXPORT": "Export Data", - "SUBSCRIPTION": "Subscription", - "SUBSCRIBE": "Subscribe", - "MANAGEMENT_PORTAL": "Manage payment method", - "MANAGE_FAMILY_PORTAL": "Manage family", - "LEAVE_FAMILY_PLAN": "Leave family plan", - "LEAVE": "Leave", - "LEAVE_FAMILY_CONFIRM": "Are you sure that you want to leave family plan?", - "CHOOSE_PLAN": "Choose your plan", - "MANAGE_PLAN": "Manage your subscription", - "ACTIVE": "Active", - "OFFLINE_MSG": "You are offline, cached memories are being shown", - "FREE_SUBSCRIPTION_INFO": "You are on the free plan that expires on {{date, dateTime}}", - "FAMILY_SUBSCRIPTION_INFO": "You are on a family plan managed by", - "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Renews on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Ends on {{date, dateTime}}", - "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Your subscription will be cancelled on {{date, dateTime}}", - "ADD_ON_AVAILABLE_TILL": "Your {{storage, string}} add-on is valid till {{date, dateTime}}", - "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "You have exceeded your storage quota, please upgrade", - "SUBSCRIPTION_PURCHASE_SUCCESS": "

We've received your payment

Your subscription is valid till {{date, dateTime}}

", - "SUBSCRIPTION_PURCHASE_CANCELLED": "Your purchase was canceled, please try again if you want to subscribe", - "SUBSCRIPTION_PURCHASE_FAILED": "Subscription purchase failed , please try again", - "SUBSCRIPTION_UPDATE_FAILED": "Subscription updated failed , please try again", - "UPDATE_PAYMENT_METHOD_MESSAGE": "We are sorry, payment failed when we tried to charge your card, please update your payment method and try again", - "STRIPE_AUTHENTICATION_FAILED": "We are unable to authenticate your payment method. please choose a different payment method and try again", - "UPDATE_PAYMENT_METHOD": "Update payment method", - "MONTHLY": "Monthly", - "YEARLY": "Yearly", - "UPDATE_SUBSCRIPTION_MESSAGE": "Are you sure you want to change your plan?", - "UPDATE_SUBSCRIPTION": "Change plan", - "CANCEL_SUBSCRIPTION": "Cancel subscription", - "CANCEL_SUBSCRIPTION_MESSAGE": "

All of your data will be deleted from our servers at the end of this billing period.

Are you sure that you want to cancel your subscription?

", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Are you sure you want to cancel your subscription?

", - "SUBSCRIPTION_CANCEL_FAILED": "Failed to cancel subscription", - "SUBSCRIPTION_CANCEL_SUCCESS": "Subscription canceled successfully", - "REACTIVATE_SUBSCRIPTION": "Reactivate subscription", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "Once reactivated, you will be billed on {{date, dateTime}}", - "SUBSCRIPTION_ACTIVATE_SUCCESS": "Subscription activated successfully ", - "SUBSCRIPTION_ACTIVATE_FAILED": "Failed to reactivate subscription renewals", - "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Thank you", - "CANCEL_SUBSCRIPTION_ON_MOBILE": "Cancel mobile subscription", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Please cancel your subscription from the mobile app to activate a subscription here", - "MAIL_TO_MANAGE_SUBSCRIPTION": "Please contact us at {{emailID}} to manage your subscription", - "RENAME": "Rename", - "RENAME_FILE": "Rename file", - "RENAME_COLLECTION": "Rename album", - "DELETE_COLLECTION_TITLE": "Delete album?", - "DELETE_COLLECTION": "Delete album", - "DELETE_COLLECTION_MESSAGE": "Also delete the photos (and videos) present in this album from all other albums they are part of?", - "DELETE_PHOTOS": "Delete photos", - "KEEP_PHOTOS": "Keep photos", - "SHARE": "Share", - "SHARE_COLLECTION": "Share album", - "SHAREES": "Shared with", - "SHARE_WITH_SELF": "Oops, you cannot share with yourself", - "ALREADY_SHARED": "Oops, you're already sharing this with {{email}}", - "SHARING_BAD_REQUEST_ERROR": "Sharing album not allowed", - "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Sharing is disabled for free accounts", - "DOWNLOAD_COLLECTION": "Download album", - "DOWNLOAD_COLLECTION_MESSAGE": "

Are you sure you want to download the complete album?

All files will be queued for download sequentially

", - "CREATE_ALBUM_FAILED": "Failed to create album , please try again", - "SEARCH": "Search", - "SEARCH_RESULTS": "Search results", - "NO_RESULTS": "No results found", - "SEARCH_HINT": "Search for albums, dates, descriptions, ...", + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", "SEARCH_TYPE": { - "COLLECTION": "Album", - "LOCATION": "Location", - "CITY": "Location", - "DATE": "Date", - "FILE_NAME": "File name", - "THING": "Content", - "FILE_CAPTION": "Description", - "FILE_TYPE": "File type", - "CLIP": "Magic" + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" }, - "photos_count_zero": "No memories", - "photos_count_one": "1 memory", - "photos_count_other": "{{count, number}} memories", - "TERMS_AND_CONDITIONS": "I agree to the terms and privacy policy", - "ADD_TO_COLLECTION": "Add to album", - "SELECTED": "selected", - "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "This video cannot be played on your browser", - "PEOPLE": "People", - "INDEXING_SCHEDULED": "Indexing is scheduled...", - "ANALYZING_PHOTOS": "Indexing photos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", - "INDEXING_PEOPLE": "Indexing people in {{indexStatus.nSyncedFiles,number}} photos...", - "INDEXING_DONE": "Indexed {{indexStatus.nSyncedFiles,number}} photos", - "UNIDENTIFIED_FACES": "unidentified faces", - "OBJECTS": "objects", - "TEXT": "text", - "INFO": "Info ", - "INFO_OPTION": "Info (I)", - "FILE_NAME": "File name", - "CAPTION_PLACEHOLDER": "Add a description", - "LOCATION": "Location", - "SHOW_ON_MAP": "View on OpenStreetMap", - "MAP": "Map", - "MAP_SETTINGS": "Map Settings", - "ENABLE_MAPS": "Enable Maps?", - "ENABLE_MAP": "Enable map", - "DISABLE_MAPS": "Disable Maps?", - "ENABLE_MAP_DESCRIPTION": "

This will show your photos on a world map.

The map is hosted by OpenStreetMap, and the exact locations of your photos are never shared.

You can disable this feature anytime from Settings.

", - "DISABLE_MAP_DESCRIPTION": "

This will disable the display of your photos on a world map.

You can enable this feature anytime from Settings.

", - "DISABLE_MAP": "Disable map", - "DETAILS": "Details", - "VIEW_EXIF": "View all EXIF data", - "NO_EXIF": "No EXIF data", - "EXIF": "EXIF", - "ISO": "ISO", - "TWO_FACTOR": "Two-factor", - "TWO_FACTOR_AUTHENTICATION": "Two-factor authentication", - "TWO_FACTOR_QR_INSTRUCTION": "Scan the QR code below with your favorite authenticator app", - "ENTER_CODE_MANUALLY": "Enter the code manually", - "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Please enter this code in your favorite authenticator app", - "SCAN_QR_CODE": "Scan QR code instead", - "ENABLE_TWO_FACTOR": "Enable two-factor", - "ENABLE": "Enable", - "LOST_DEVICE": "Lost two-factor device", - "INCORRECT_CODE": "Incorrect code", - "TWO_FACTOR_INFO": "Add an additional layer of security by requiring more than your email and password to log in to your account", - "DISABLE_TWO_FACTOR_LABEL": "Disable two-factor authentication", - "UPDATE_TWO_FACTOR_LABEL": "Update your authenticator device", - "DISABLE": "Disable", - "RECONFIGURE": "Reconfigure", - "UPDATE_TWO_FACTOR": "Update two-factor", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuing forward will void any previously configured authenticators", - "UPDATE": "Update", - "DISABLE_TWO_FACTOR": "Disable two-factor", - "DISABLE_TWO_FACTOR_MESSAGE": "Are you sure you want to disable your two-factor authentication", - "TWO_FACTOR_DISABLE_FAILED": "Failed to disable two factor, please try again", - "EXPORT_DATA": "Export data", - "SELECT_FOLDER": "Select folder", - "DESTINATION": "Destination", - "START": "Start", - "LAST_EXPORT_TIME": "Last export time", - "EXPORT_AGAIN": "Resync", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "Local storage not accessible", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Your browser or an addon is blocking ente from saving data into local storage. please try loading this page after switching your browsing mode.", - "SEND_OTT": "Send OTP", - "EMAIl_ALREADY_OWNED": "Email already taken", - "ETAGS_BLOCKED": "

We were unable to upload the following files because of your browser configuration.

Please disable any addons that might be preventing ente from using eTags to upload large files, or use our desktop app for a more reliable import experience.

", - "SKIPPED_VIDEOS_INFO": "

Presently we do not support adding videos via public links.

To share videos, please signup for ente and share with the intended recipients using their email.

", - "LIVE_PHOTOS_DETECTED": "The photo and video files from your Live Photos have been merged into a single file", - "RETRY_FAILED": "Retry failed uploads", - "FAILED_UPLOADS": "Failed uploads ", - "SKIPPED_FILES": "Ignored uploads", - "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Thumbnail generation failed", - "UNSUPPORTED_FILES": "Unsupported files", - "SUCCESSFUL_UPLOADS": "Successful uploads", - "SKIPPED_INFO": "Skipped these as there are files with matching names in the same album", - "UNSUPPORTED_INFO": "ente does not support these file formats yet", - "BLOCKED_UPLOADS": "Blocked uploads", - "SKIPPED_VIDEOS": "Skipped videos", - "INPROGRESS_METADATA_EXTRACTION": "In progress", - "INPROGRESS_UPLOADS": "Uploads in progress", - "TOO_LARGE_UPLOADS": "Large files", - "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Insufficient storage", - "LARGER_THAN_AVAILABLE_STORAGE_INFO": "These files were not uploaded as they exceed the maximum size limit for your storage plan", - "TOO_LARGE_INFO": "These files were not uploaded as they exceed our maximum file size limit", - "THUMBNAIL_GENERATION_FAILED_INFO": "These files were uploaded, but unfortunately we could not generate the thumbnails for them.", - "UPLOAD_TO_COLLECTION": "Upload to album", - "UNCATEGORIZED": "Uncategorized", - "ARCHIVE": "Archive", - "FAVORITES": "Favorites", - "ARCHIVE_COLLECTION": "Archive album", - "ARCHIVE_SECTION_NAME": "Archive", - "ALL_SECTION_NAME": "All", - "MOVE_TO_COLLECTION": "Move to album", - "UNARCHIVE": "Unarchive", - "UNARCHIVE_COLLECTION": "Unarchive album", - "HIDE_COLLECTION": "Hide album", - "UNHIDE_COLLECTION": "Unhide album", - "MOVE": "Move", - "ADD": "Add", - "REMOVE": "Remove", - "YES_REMOVE": "Yes, remove", - "REMOVE_FROM_COLLECTION": "Remove from album", - "TRASH": "Trash", - "MOVE_TO_TRASH": "Move to trash", - "TRASH_FILES_MESSAGE": "Selected files will be removed from all albums and moved to trash.", - "TRASH_FILE_MESSAGE": "The file will be removed from all albums and moved to trash.", - "DELETE_PERMANENTLY": "Delete permanently", - "RESTORE": "Restore", - "RESTORE_TO_COLLECTION": "Restore to album", - "EMPTY_TRASH": "Empty trash", - "EMPTY_TRASH_TITLE": "Empty trash?", - "EMPTY_TRASH_MESSAGE": "These files will be permanently deleted from your ente account.", - "LEAVE_SHARED_ALBUM": "Yes, leave", - "LEAVE_ALBUM": "Leave album", - "LEAVE_SHARED_ALBUM_TITLE": "Leave shared album?", - "LEAVE_SHARED_ALBUM_MESSAGE": "You will leave the album, and it will stop being visible to you.", - "NOT_FILE_OWNER": "You cannot delete files in a shared album", - "CONFIRM_SELF_REMOVE_MESSAGE": "Selected items will be removed from this album. Items which are only in this album will be moved to Uncategorized.", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Some of the items you are removing were added by other people, and you will lose access to them.", - "SORT_BY_CREATION_TIME_ASCENDING": "Oldest", - "SORT_BY_UPDATION_TIME_DESCENDING": "Last updated", - "SORT_BY_NAME": "Name", - "COMPRESS_THUMBNAILS": "Compress thumbnails", - "THUMBNAIL_REPLACED": "Thumbnails compressed", - "FIX_THUMBNAIL": "Compress", - "FIX_THUMBNAIL_LATER": "Compress later", - "REPLACE_THUMBNAIL_NOT_STARTED": "Some of your videos thumbnails can be compressed to save space. would you like ente to compress them?", - "REPLACE_THUMBNAIL_COMPLETED": "Successfully compressed all thumbnails", - "REPLACE_THUMBNAIL_NOOP": "You have no thumbnails that can be compressed further", - "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Could not compress some of your thumbnails, please retry", - "FIX_CREATION_TIME": "Fix time", - "FIX_CREATION_TIME_IN_PROGRESS": "Fixing time", - "CREATION_TIME_UPDATED": "File time updated", - "UPDATE_CREATION_TIME_NOT_STARTED": "Select the option you want to use", - "UPDATE_CREATION_TIME_COMPLETED": "Successfully updated all files", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "File time updation failed for some files, please retry", - "CAPTION_CHARACTER_LIMIT": "5000 characters max", - "DATE_TIME_ORIGINAL": "EXIF:DateTimeOriginal", - "DATE_TIME_DIGITIZED": "EXIF:DateTimeDigitized", - "METADATA_DATE": "EXIF:MetadataDate", - "CUSTOM_TIME": "Custom time", - "REOPEN_PLAN_SELECTOR_MODAL": "Re-open plans", - "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Failed to open plans", - "INSTALL": "Install", - "SHARING_DETAILS": "Sharing details", - "MODIFY_SHARING": "Modify sharing", - "ADD_COLLABORATORS": "Add collaborators", - "ADD_NEW_EMAIL": "Add a new email", - "shared_with_people_zero": "Share with specific people", - "shared_with_people_one": "Shared with 1 person", - "shared_with_people_other": "Shared with {{count, number}} people", - "participants_zero": "No participants", - "participants_one": "1 participant", - "participants_other": "{{count, number}} participants", - "ADD_VIEWERS": "Add viewers", - "PARTICIPANTS": "Participants", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} will not be able to add more photos to the album

They will still be able to remove photos added by them

", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} will be able to add photos to the album", - "CONVERT_TO_VIEWER": "Yes, convert to viewer", - "CONVERT_TO_COLLABORATOR": "Yes, convert to collaborator", - "CHANGE_PERMISSION": "Change permission?", - "REMOVE_PARTICIPANT": "Remove?", - "CONFIRM_REMOVE": "Yes, remove", - "MANAGE": "Manage", - "ADDED_AS": "Added as", - "COLLABORATOR_RIGHTS": "Collaborators can add photos and videos to the shared album", - "REMOVE_PARTICIPANT_HEAD": "Remove participant", - "OWNER": "Owner", - "COLLABORATORS": "Collaborators", - "ADD_MORE": "Add more", - "VIEWERS": "Viewers", - "OR_ADD_EXISTING": "Or pick an existing one", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} will be removed from the album

Any photos added by them will also be removed from the album

", - "NOT_FOUND": "404 - not found", - "LINK_EXPIRED": "Link expired", - "LINK_EXPIRED_MESSAGE": "This link has either expired or been disabled!", - "MANAGE_LINK": "Manage link", - "LINK_TOO_MANY_REQUESTS": "Sorry, this album has been viewed on too many devices!", - "FILE_DOWNLOAD": "Allow downloads", - "LINK_PASSWORD_LOCK": "Password lock", - "PUBLIC_COLLECT": "Allow adding photos", - "LINK_DEVICE_LIMIT": "Device limit", - "NO_DEVICE_LIMIT": "None", - "LINK_EXPIRY": "Link expiry", - "NEVER": "Never", - "DISABLE_FILE_DOWNLOAD": "Disable download", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Are you sure that you want to disable the download button for files?

Viewers can still take screenshots or save a copy of your photos using external tools.

", - "MALICIOUS_CONTENT": "Contains malicious content", - "COPYRIGHT": "Infringes on the copyright of someone I am authorized to represent", - "SHARED_USING": "Shared using ", - "ENTE_IO": "ente.io", - "SHARING_REFERRAL_CODE": "Use code {{referralCode}} to get 10 GB free", - "LIVE": "LIVE", - "DISABLE_PASSWORD": "Disable password lock", - "DISABLE_PASSWORD_MESSAGE": "Are you sure that you want to disable the password lock?", - "PASSWORD_LOCK": "Password lock", - "LOCK": "Lock", - "DOWNLOAD_UPLOAD_LOGS": "Debug logs", - "UPLOAD_FILES": "File", - "UPLOAD_DIRS": "Folder", - "UPLOAD_GOOGLE_TAKEOUT": "Google takeout", - "DEDUPLICATE_FILES": "Deduplicate files", - "AUTHENTICATOR_SECTION": "Authenticator", - "NO_DUPLICATES_FOUND": "You've no duplicate files that can be cleared", - "CLUB_BY_CAPTURE_TIME": "Club by capture time", - "FILES": "Files", - "EACH": "Each", - "DEDUPLICATE_BASED_ON_SIZE": "The following files were clubbed based on their sizes, please review and delete items you believe are duplicates", - "STOP_ALL_UPLOADS_MESSAGE": "Are you sure that you want to stop all the uploads in progress?", - "STOP_UPLOADS_HEADER": "Stop uploads?", - "YES_STOP_UPLOADS": "Yes, stop uploads", - "STOP_DOWNLOADS_HEADER": "Stop downloads?", - "YES_STOP_DOWNLOADS": "Yes, stop downloads", - "STOP_ALL_DOWNLOADS_MESSAGE": "Are you sure that you want to stop all the downloads in progress?", - "albums_one": "1 Album", - "albums_other": "{{count, number}} Albums", - "ALL_ALBUMS": "All Albums", - "ALBUMS": "Albums", - "ALL_HIDDEN_ALBUMS": "All hidden albums", - "HIDDEN_ALBUMS": "Hidden albums", - "HIDDEN_ITEMS": "Hidden items", - "HIDDEN_ITEMS_SECTION_NAME": "Hidden_items", - "ENTER_TWO_FACTOR_OTP": "Enter the 6-digit code from your authenticator app.", - "CREATE_ACCOUNT": "Create account", - "COPIED": "Copied", - "CANVAS_BLOCKED_TITLE": "Unable to generate thumbnail", - "CANVAS_BLOCKED_MESSAGE": "

It looks like your browser has disabled access to canvas, which is necessary to generate thumbnails for your photos

Please enable access to your browser's canvas, or check out our desktop app

", - "WATCH_FOLDERS": "Watch folders", - "UPGRADE_NOW": "Upgrade now", - "RENEW_NOW": "Renew now", - "STORAGE": "Storage", - "USED": "used", - "YOU": "You", - "FAMILY": "Family", - "FREE": "free", - "OF": "of", - "WATCHED_FOLDERS": "Watched folders", - "NO_FOLDERS_ADDED": "No folders added yet!", - "FOLDERS_AUTOMATICALLY_MONITORED": "The folders you add here will monitored to automatically", - "UPLOAD_NEW_FILES_TO_ENTE": "Upload new files to ente", - "REMOVE_DELETED_FILES_FROM_ENTE": "Remove deleted files from ente", - "ADD_FOLDER": "Add folder", - "STOP_WATCHING": "Stop watching", - "STOP_WATCHING_FOLDER": "Stop watching folder?", - "STOP_WATCHING_DIALOG_MESSAGE": "Your existing files will not be deleted, but ente will stop automatically updating the linked ente album on changes in this folder.", - "YES_STOP": "Yes, stop", - "MONTH_SHORT": "mo", - "YEAR": "year", - "FAMILY_PLAN": "Family plan", - "DOWNLOAD_LOGS": "Download logs", - "DOWNLOAD_LOGS_MESSAGE": "

This will download debug logs, which you can email to us to help debug your issue.

Please note that file names will be included to help track issues with specific files.

", - "CHANGE_FOLDER": "Change Folder", - "TWO_MONTHS_FREE": "Get 2 months free on yearly plans", - "GB": "GB", - "POPULAR": "Popular", - "FREE_PLAN_OPTION_LABEL": "Continue with free trial", - "FREE_PLAN_DESCRIPTION": "1 GB for 1 year", - "CURRENT_USAGE": "Current usage is {{usage}}", - "WEAK_DEVICE": "The web browser you're using is not powerful enough to encrypt your photos. Please try to log in to ente on your computer, or download the ente mobile/desktop app.", - "DRAG_AND_DROP_HINT": "Or drag and drop into the ente window", - "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Your uploaded data will be scheduled for deletion, and your account will be permanently deleted.

This action is not reversible.", - "AUTHENTICATE": "Authenticate", - "UPLOADED_TO_SINGLE_COLLECTION": "Uploaded to single collection", - "UPLOADED_TO_SEPARATE_COLLECTIONS": "Uploaded to separate collections", - "NEVERMIND": "Nevermind", - "UPDATE_AVAILABLE": "Update available", - "UPDATE_INSTALLABLE_MESSAGE": "A new version of ente is ready to be installed.", - "INSTALL_NOW": "Install now", - "INSTALL_ON_NEXT_LAUNCH": "Install on next launch", - "UPDATE_AVAILABLE_MESSAGE": "A new version of ente has been released, but it cannot be automatically downloaded and installed.", - "DOWNLOAD_AND_INSTALL": "Download and install", - "IGNORE_THIS_VERSION": "Ignore this version", - "TODAY": "Today", - "YESTERDAY": "Yesterday", - "NAME_PLACEHOLDER": "Name...", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Cannot create albums from file/folder mix", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

You have dragged and dropped a mixture of files and folders.

Please provide either only files, or only folders when selecting option to create separate albums

", - "CHOSE_THEME": "Choose theme", - "ML_SEARCH": "Face recognition", - "ENABLE_ML_SEARCH_DESCRIPTION": "

This will enable on-device machine learning and face search which will start analyzing your uploaded photos locally.

For the first run after login or enabling this feature, it will download all images on local device to analyze them. So please only enable this if you are ok with bandwidth and local processing of all images in your photo library.

If this is the first time you're enabling this, we'll also ask your permission to process face data.

", - "ML_MORE_DETAILS": "More details", - "ENABLE_FACE_SEARCH": "Enable face recognition", - "ENABLE_FACE_SEARCH_TITLE": "Enable face recognition?", - "ENABLE_FACE_SEARCH_DESCRIPTION": "

If you enable face recognition, ente will extract face geometry from your photos. This will happen on your device, and any generated biometric data will be end-to-encrypted.

Please click here for more details about this feature in our privacy policy

", - "DISABLE_BETA": "Pause recognition", - "DISABLE_FACE_SEARCH": "Disable face recognition", - "DISABLE_FACE_SEARCH_TITLE": "Disable face recognition?", - "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente will stop processing face geometry.

You can reenable face recognition again if you wish, so this operation is safe.

", - "ADVANCED": "Advanced", - "FACE_SEARCH_CONFIRMATION": "I understand, and wish to allow ente to process face geometry", - "LABS": "Labs", - "YOURS": "yours", - "PASSPHRASE_STRENGTH_WEAK": "Password strength: Weak", - "PASSPHRASE_STRENGTH_MODERATE": "Password strength: Moderate", - "PASSPHRASE_STRENGTH_STRONG": "Password strength: Strong", - "PREFERENCES": "Preferences", - "LANGUAGE": "Language", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Invalid export directory", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

The export directory you have selected does not exist.

Please select a valid directory.

", - "SUBSCRIPTION_VERIFICATION_ERROR": "Subscription verification failed", + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", "STORAGE_UNITS": { - "B": "B", - "KB": "KB", - "MB": "MB", - "GB": "GB", - "TB": "TB" + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" }, "AFTER_TIME": { - "HOUR": "after an hour", - "DAY": "after a day", - "WEEK": "after a week", - "MONTH": "after a month", - "YEAR": "after a year" + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" }, - "COPY_LINK": "Copy link", - "DONE": "Done", - "LINK_SHARE_TITLE": "Or share a link", - "REMOVE_LINK": "Remove link", - "CREATE_PUBLIC_SHARING": "Create public link", - "PUBLIC_LINK_CREATED": "Public link created", - "PUBLIC_LINK_ENABLED": "Public link enabled", - "COLLECT_PHOTOS": "Collect photos", - "PUBLIC_COLLECT_SUBTEXT": "Allow people with the link to also add photos to the shared album.", - "STOP_EXPORT": "Stop", - "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} items synced", - "MIGRATING_EXPORT": "Preparing...", - "RENAMING_COLLECTION_FOLDERS": "Renaming album folders...", - "TRASHING_DELETED_FILES": "Trashing deleted files...", - "TRASHING_DELETED_COLLECTIONS": "Trashing deleted albums...", + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", "EXPORT_NOTIFICATION": { - "START": "Export started", - "IN_PROGRESS": "Export already in progress", - "FINISH": "Export finished", - "UP_TO_DATE": "No new files to export" + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" }, - "CONTINUOUS_EXPORT": "Sync continuously", - "TOTAL_ITEMS": "Total items", - "PENDING_ITEMS": "Pending items", - "EXPORT_STARTING": "Export starting...", - "DELETE_ACCOUNT_REASON_LABEL": "What is the main reason you are deleting your account?", - "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Select a reason", + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", "DELETE_REASON": { - "MISSING_FEATURE": "It's missing a key feature that I need", - "BROKEN_BEHAVIOR": "The app or a certain feature does not behave as I think it should", - "FOUND_ANOTHER_SERVICE": "I found another service that I like better", - "NOT_LISTED": "My reason isn't listed" + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" }, - "DELETE_ACCOUNT_FEEDBACK_LABEL": "We are sorry to see you go. Please explain why you are leaving to help us improve.", - "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Feedback", - "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Yes, I want to permanently delete this account and all its data", - "CONFIRM_DELETE_ACCOUNT": "Confirm Account Deletion", - "FEEDBACK_REQUIRED": "Kindly help us with this information", - "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "What does the other service do better?", - "RECOVER_TWO_FACTOR": "Recover two-factor", - "at": "at", - "AUTH_NEXT": "next", - "AUTH_DOWNLOAD_MOBILE_APP": "Download our mobile app to manage your secrets", - "HIDDEN": "Hidden", - "HIDE": "Hide", - "UNHIDE": "Unhide", - "UNHIDE_TO_COLLECTION": "Unhide to album", - "SORT_BY": "Sort by", - "NEWEST_FIRST": "Newest first", - "OLDEST_FIRST": "Oldest first", - "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "This file could not be previewed. Click here to download the original.", - "SELECT_COLLECTION": "Select album", - "PIN_ALBUM": "Pin album", - "UNPIN_ALBUM": "Unpin album", - "DOWNLOAD_COMPLETE": "Download complete", - "DOWNLOADING_COLLECTION": "Downloading {{name}}", - "DOWNLOAD_FAILED": "Download failed", - "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", - "CHRISTMAS": "Christmas", - "CHRISTMAS_EVE": "Christmas Eve", - "NEW_YEAR": "New Year", - "NEW_YEAR_EVE": "New Year's Eve", - "IMAGE": "Image", - "VIDEO": "Video", - "LIVE_PHOTO": "Live Photo", - "CONVERT": "Convert", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Are you sure you want to close the editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Download your edited image or save a copy to ente to persist your changes.", - "BRIGHTNESS": "Brightness", - "CONTRAST": "Contrast", - "SATURATION": "Saturation", - "BLUR": "Blur", - "INVERT_COLORS": "Invert Colors", - "ASPECT_RATIO": "Aspect Ratio", - "SQUARE": "Square", - "ROTATE_LEFT": "Rotate Left", - "ROTATE_RIGHT": "Rotate Right", - "FLIP_VERTICALLY": "Flip Vertically", - "FLIP_HORIZONTALLY": "Flip Horizontally", - "DOWNLOAD_EDITED": "Download Edited", - "SAVE_A_COPY_TO_ENTE": "Save a copy to ente", - "RESTORE_ORIGINAL": "Restore Original", - "TRANSFORM": "Transform", - "COLORS": "Colors", - "FLIP": "Flip", - "ROTATION": "Rotation", - "RESET": "Reset", - "PHOTO_EDITOR": "Photo Editor", - "FASTER_UPLOAD": "Faster uploads", - "FASTER_UPLOAD_DESCRIPTION": "Route uploads through nearby servers", - "MAGIC_SEARCH_STATUS": "Magic Search Status", - "INDEXED_ITEMS": "Indexed items", - "CAST_ALBUM_TO_TV": "Play album on TV", - "ENTER_CAST_PIN_CODE": "Enter the code you see on the TV below to pair this device.", - "PAIR_DEVICE_TO_TV": "Pair devices", - "TV_NOT_FOUND": "TV not found. Did you enter the PIN correctly?", - "AUTO_CAST_PAIR": "Auto Pair", - "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "Auto Pair requires connecting to Google servers and only works with Chromecast supported devices. Google will not receive sensitive data, such as your photos.", - "PAIR_WITH_PIN": "Pair with PIN", - "CHOOSE_DEVICE_FROM_BROWSER": "Choose a cast-compatible device from the browser popup.", - "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Pair with PIN works for any large screen device you want to play your album on.", - "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", - "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", - "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", - "FREEHAND": "Freehand", - "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/auth/public/locales/zh-CN/translation.json b/web/apps/auth/public/locales/zh-CN/translation.json index 15ef565ddd..0a72e1c70a 100644 --- a/web/apps/auth/public/locales/zh-CN/translation.json +++ b/web/apps/auth/public/locales/zh-CN/translation.json @@ -9,7 +9,7 @@ "SIGN_UP": "注册", "NEW_USER": "刚来到 ente", "EXISTING_USER": "现有用户", - "ENTER_NAME": "现有用户", + "ENTER_NAME": "输入名字", "PUBLIC_UPLOADER_NAME_MESSAGE": "请添加一个名字,以便您的朋友知晓该感谢谁拍摄了这些精美的照片!", "ENTER_EMAIL": "请输入电子邮件地址", "EMAIL_ERROR": "请输入有效的电子邮件", @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "您是如何知道Ente的? (可选的)", "REFERRAL_INFO": "我们不跟踪应用程序安装情况,如果您告诉我们您是在哪里找到我们的,将会有所帮助!", "PASSPHRASE_MATCH_ERROR": "两次输入的密码不一致", - "CONSOLE_WARNING_STOP": "停止!", - "CONSOLE_WARNING_DESC": "这是专为开发人员设计的浏览器功能。 请不要在此处复制粘贴未经验证的代码。", "CREATE_COLLECTION": "新建相册", "ENTER_ALBUM_NAME": "相册名称", "CLOSE_OPTION": "关闭 (或按Esc键)", @@ -85,9 +83,9 @@ "ZOOM_IN_OUT": "放大/缩小", "PREVIOUS": "上一个 (←)", "NEXT": "下一个 (→)", - "TITLE_PHOTOS": "ente 照片", - "TITLE_ALBUMS": "ente 照片", - "TITLE_AUTH": "ente 验证器", + "TITLE_PHOTOS": "Ente 照片", + "TITLE_ALBUMS": "Ente 照片", + "TITLE_AUTH": "Ente 验证器", "UPLOAD_FIRST_PHOTO": "上传您的第一张照片", "IMPORT_YOUR_FOLDERS": "导入您的文件夹", "UPLOAD_DROPZONE_MESSAGE": "拖放以备份您的文件", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "正在下载 {{name}}", "DOWNLOAD_FAILED": "下载失败", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} 个文件", - "CRASH_REPORTING": "崩溃报告", "CHRISTMAS": "圣诞", "CHRISTMAS_EVE": "平安夜", "NEW_YEAR": "新年", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "在您要配对的设备上访问 cast.ente.io 。", "CAST_AUTO_PAIR_FAILED": "Chromecast 自动配对失败。请再试一次。", "CACHE_DIRECTORY": "缓存文件夹", - "PASSKEYS": "通行密钥", "FREEHAND": "手画", "APPLY_CROP": "应用裁剪", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "保存之前必须至少执行一项转换或颜色调整。" + "PHOTO_EDIT_REQUIRED_TO_SAVE": "保存之前必须至少执行一项转换或颜色调整。", + "PASSKEYS": "通行密钥", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" } diff --git a/web/apps/cast/public/locales/bg-BG/translation.json b/web/apps/cast/public/locales/bg-BG/translation.json new file mode 100644 index 0000000000..03faf16c2d --- /dev/null +++ b/web/apps/cast/public/locales/bg-BG/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Личен бекъп
на твоите спомени
", + "HERO_SLIDE_1": "Криптиран от край до край по подразбиране", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/de-DE/translation.json b/web/apps/cast/public/locales/de-DE/translation.json new file mode 100644 index 0000000000..9a1c4073c6 --- /dev/null +++ b/web/apps/cast/public/locales/de-DE/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Private Sicherungen
für deine Erinnerungen
", + "HERO_SLIDE_1": "Standardmäßig Ende-zu-Ende verschlüsselt", + "HERO_SLIDE_2_TITLE": "
Sicher gespeichert
in einem Luftschutzbunker
", + "HERO_SLIDE_2": "Entwickelt um zu bewahren", + "HERO_SLIDE_3_TITLE": "
Verfügbar
überall
", + "HERO_SLIDE_3": "Android, iOS, Web, Desktop", + "LOGIN": "Anmelden", + "SIGN_UP": "Registrieren", + "NEW_USER": "Neu bei ente", + "EXISTING_USER": "Existierender Benutzer", + "ENTER_NAME": "Name eingeben", + "PUBLIC_UPLOADER_NAME_MESSAGE": "Füge einen Namen hinzu, damit deine Freunde wissen, wem sie für diese tollen Fotos zu danken haben!", + "ENTER_EMAIL": "E-Mail-Adresse eingeben", + "EMAIL_ERROR": "Geben Sie eine gültige E-Mail-Adresse ein", + "REQUIRED": "Erforderlich", + "EMAIL_SENT": "Bestätigungscode an {{email}} gesendet", + "CHECK_INBOX": "Bitte überprüfe deinen E-Mail-Posteingang (und Spam), um die Verifizierung abzuschließen", + "ENTER_OTT": "Bestätigungscode", + "RESEND_MAIL": "Code erneut senden", + "VERIFY": "Überprüfen", + "UNKNOWN_ERROR": "Ein Fehler ist aufgetreten, bitte versuche es erneut", + "INVALID_CODE": "Falscher Bestätigungscode", + "EXPIRED_CODE": "Ihr Bestätigungscode ist abgelaufen", + "SENDING": "Wird gesendet...", + "SENT": "Gesendet!", + "PASSWORD": "Passwort", + "LINK_PASSWORD": "Passwort zum Entsperren des Albums eingeben", + "RETURN_PASSPHRASE_HINT": "Passwort", + "SET_PASSPHRASE": "Passwort setzen", + "VERIFY_PASSPHRASE": "Einloggen", + "INCORRECT_PASSPHRASE": "Falsches Passwort", + "ENTER_ENC_PASSPHRASE": "Bitte gib ein Passwort ein, mit dem wir deine Daten verschlüsseln können", + "PASSPHRASE_DISCLAIMER": "Wir speichern dein Passwort nicht. Wenn du es vergisst, können wir dir nicht helfen, deine Daten ohne einen Wiederherstellungsschlüssel wiederherzustellen.", + "WELCOME_TO_ENTE_HEADING": "Willkommen bei ", + "WELCOME_TO_ENTE_SUBHEADING": "Ende-zu-Ende verschlüsselte Fotospeicherung und Freigabe", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "Wo deine besten Fotos leben", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generierung von Verschlüsselungsschlüsseln...", + "PASSPHRASE_HINT": "Passwort", + "CONFIRM_PASSPHRASE": "Passwort bestätigen", + "REFERRAL_CODE_HINT": "Wie hast du von Ente erfahren? (optional)", + "REFERRAL_INFO": "Wir tracken keine App-Installationen. Es würde uns jedoch helfen, wenn du uns mitteilst, wie du von uns erfahren hast!", + "PASSPHRASE_MATCH_ERROR": "Die Passwörter stimmen nicht überein", + "CREATE_COLLECTION": "Neues Album", + "ENTER_ALBUM_NAME": "Albumname", + "CLOSE_OPTION": "Schließen (Esc)", + "ENTER_FILE_NAME": "Dateiname", + "CLOSE": "Schließen", + "NO": "Nein", + "NOTHING_HERE": "Hier gibt es noch nichts zu sehen 👀", + "UPLOAD": "Hochladen", + "IMPORT": "Importieren", + "ADD_PHOTOS": "Fotos hinzufügen", + "ADD_MORE_PHOTOS": "Mehr Fotos hinzufügen", + "add_photos_one": "Eine Datei hinzufügen", + "add_photos_other": "{{count, number}} Dateien hinzufügen", + "SELECT_PHOTOS": "Foto auswählen", + "FILE_UPLOAD": "Datei hochladen", + "UPLOAD_STAGE_MESSAGE": { + "0": "Hochladen wird vorbereitet", + "1": "Lese Google-Metadaten", + "2": "Metadaten von {{uploadCounter.finished, number}} / {{uploadCounter.total, number}} Dateien extrahiert", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} Dateien verarbeitet", + "4": "Verbleibende Uploads werden abgebrochen", + "5": "Sicherung abgeschlossen" + }, + "FILE_NOT_UPLOADED_LIST": "Die folgenden Dateien wurden nicht hochgeladen", + "SUBSCRIPTION_EXPIRED": "Abonnement abgelaufen", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Dein Abonnement ist abgelaufen, bitte erneuere es", + "STORAGE_QUOTA_EXCEEDED": "Speichergrenze überschritten", + "INITIAL_LOAD_DELAY_WARNING": "Das erste Laden kann einige Zeit in Anspruch nehmen", + "USER_DOES_NOT_EXIST": "Leider konnte kein Benutzer mit dieser E-Mail gefunden werden", + "NO_ACCOUNT": "Kein Konto vorhanden", + "ACCOUNT_EXISTS": "Es ist bereits ein Account vorhanden", + "CREATE": "Erstellen", + "DOWNLOAD": "Herunterladen", + "DOWNLOAD_OPTION": "Herunterladen (D)", + "DOWNLOAD_FAVORITES": "Favoriten herunterladen", + "DOWNLOAD_UNCATEGORIZED": "Download unkategorisiert", + "DOWNLOAD_HIDDEN_ITEMS": "Versteckte Dateien herunterladen", + "COPY_OPTION": "Als PNG kopieren (Strg / Cmd - C)", + "TOGGLE_FULLSCREEN": "Vollbild umschalten (F)", + "ZOOM_IN_OUT": "Herein-/Herauszoomen", + "PREVIOUS": "Vorherige (←)", + "NEXT": "Weitere (→)", + "TITLE_PHOTOS": "Ente Fotos", + "TITLE_ALBUMS": "Ente Fotos", + "TITLE_AUTH": "Ente Auth", + "UPLOAD_FIRST_PHOTO": "Lade dein erstes Foto hoch", + "IMPORT_YOUR_FOLDERS": "Importiere deiner Ordner", + "UPLOAD_DROPZONE_MESSAGE": "Loslassen, um Dateien zu sichern", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Loslassen, um beobachteten Ordner hinzuzufügen", + "TRASH_FILES_TITLE": "Dateien löschen?", + "TRASH_FILE_TITLE": "Datei löschen?", + "DELETE_FILES_TITLE": "Sofort löschen?", + "DELETE_FILES_MESSAGE": "Ausgewählte Dateien werden dauerhaft aus Ihrem Ente-Konto gelöscht.", + "DELETE": "Löschen", + "DELETE_OPTION": "Löschen (DEL)", + "FAVORITE_OPTION": "Zu Favoriten hinzufügen (L)", + "UNFAVORITE_OPTION": "Von Favoriten entfernen (L)", + "MULTI_FOLDER_UPLOAD": "Mehrere Ordner erkannt", + "UPLOAD_STRATEGY_CHOICE": "Möchtest du sie hochladen in", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Ein einzelnes Album", + "OR": "oder", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Getrennte Alben", + "SESSION_EXPIRED_MESSAGE": "Ihre Sitzung ist abgelaufen. Bitte loggen Sie sich erneut ein, um fortzufahren", + "SESSION_EXPIRED": "Sitzung abgelaufen", + "PASSWORD_GENERATION_FAILED": "Dein Browser konnte keinen starken Schlüssel generieren, der den Verschlüsselungsstandards des Entes entspricht, bitte versuche die mobile App oder einen anderen Browser zu verwenden", + "CHANGE_PASSWORD": "Passwort ändern", + "GO_BACK": "Zurück", + "RECOVERY_KEY": "Wiederherstellungsschlüssel", + "SAVE_LATER": "Auf später verschieben", + "SAVE": "Schlüssel speichern", + "RECOVERY_KEY_DESCRIPTION": "Falls du dein Passwort vergisst, kannst du deine Daten nur mit diesem Schlüssel wiederherstellen.", + "RECOVER_KEY_GENERATION_FAILED": "Wiederherstellungsschlüssel konnte nicht generiert werden, bitte versuche es erneut", + "KEY_NOT_STORED_DISCLAIMER": "Wir speichern diesen Schlüssel nicht, also speichere ihn bitte an einem sicheren Ort", + "FORGOT_PASSWORD": "Passwort vergessen", + "RECOVER_ACCOUNT": "Konto wiederherstellen", + "RECOVERY_KEY_HINT": "Wiederherstellungsschlüssel", + "RECOVER": "Wiederherstellen", + "NO_RECOVERY_KEY": "Kein Wiederherstellungsschlüssel?", + "INCORRECT_RECOVERY_KEY": "Falscher Wiederherstellungs-Schlüssel", + "SORRY": "Entschuldigung", + "NO_RECOVERY_KEY_MESSAGE": "Aufgrund unseres Ende-zu-Ende-Verschlüsselungsprotokolls können Ihre Daten nicht ohne Ihr Passwort oder Ihren Wiederherstellungsschlüssel entschlüsselt werden", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Bitte sende eine E-Mail an {{emailID}} von deiner registrierten E-Mail-Adresse", + "CONTACT_SUPPORT": "Support kontaktieren", + "REQUEST_FEATURE": "Feature anfragen", + "SUPPORT": "Support", + "CONFIRM": "Bestätigen", + "CANCEL": "Abbrechen", + "LOGOUT": "Ausloggen", + "DELETE_ACCOUNT": "Konto löschen", + "DELETE_ACCOUNT_MESSAGE": "

Bitte sende eine E-Mail an {{emailID}} mit deiner registrierten E-Mail-Adresse.

Deine Anfrage wird innerhalb von 72 Stunden bearbeitet.

", + "LOGOUT_MESSAGE": "Sind sie sicher, dass sie sich ausloggen möchten?", + "CHANGE_EMAIL": "E-Mail-Adresse ändern", + "OK": "OK", + "SUCCESS": "Erfolgreich", + "ERROR": "Fehler", + "MESSAGE": "Nachricht", + "INSTALL_MOBILE_APP": "Installiere unsere Android oder iOS App, um automatisch alle deine Fotos zu sichern", + "DOWNLOAD_APP_MESSAGE": "Entschuldigung, dieser Vorgang wird derzeit nur von unserer Desktop-App unterstützt", + "DOWNLOAD_APP": "Desktopanwendung herunterladen", + "EXPORT": "Daten exportieren", + "SUBSCRIPTION": "Abonnement", + "SUBSCRIBE": "Abonnieren", + "MANAGEMENT_PORTAL": "Zahlungsmethode verwalten", + "MANAGE_FAMILY_PORTAL": "Familiengruppe verwalten", + "LEAVE_FAMILY_PLAN": "Familienabo verlassen", + "LEAVE": "Verlassen", + "LEAVE_FAMILY_CONFIRM": "Bist du sicher, dass du den Familien-Tarif verlassen möchtest?", + "CHOOSE_PLAN": "Wähle dein Abonnement", + "MANAGE_PLAN": "Verwalte dein Abonnement", + "ACTIVE": "Aktiv", + "OFFLINE_MSG": "Du bist offline, gecachte Erinnerungen werden angezeigt", + "FREE_SUBSCRIPTION_INFO": "Du bist auf dem kostenlosen Plan, der am {{date, dateTime}} ausläuft", + "FAMILY_SUBSCRIPTION_INFO": "Sie haben einen Familienplan verwaltet von", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Erneuert am {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Endet am {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Ihr Abo endet am {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "Dein {{storage, string}} Add-on ist gültig bis {{date, dateTime}}", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Sie haben Ihr Speichervolumen überschritten, bitte upgraden Sie", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

Wir haben deine Zahlung erhalten

Dein Abonnement ist gültig bis {{date, dateTime}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "Dein Kauf wurde abgebrochen. Bitte versuche es erneut, wenn du abonnieren willst", + "SUBSCRIPTION_PURCHASE_FAILED": "Kauf des Abonnements fehlgeschlagen Bitte versuchen Sie es erneut", + "SUBSCRIPTION_UPDATE_FAILED": "Aktualisierung des Abonnements fehlgeschlagen Bitte versuchen Sie es erneut", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Es tut uns leid, die Zahlung ist fehlgeschlagen, als wir versuchten Ihre Karte zu belasten. Bitte aktualisieren Sie Ihre Zahlungsmethode und versuchen Sie es erneut", + "STRIPE_AUTHENTICATION_FAILED": "Wir können deine Zahlungsmethode nicht authentifizieren. Bitte wähle eine andere Zahlungsmethode und versuche es erneut", + "UPDATE_PAYMENT_METHOD": "Zahlungsmethode aktualisieren", + "MONTHLY": "Monatlich", + "YEARLY": "Jährlich", + "UPDATE_SUBSCRIPTION_MESSAGE": "Sind Sie sicher, dass Sie Ihren Tarif ändern möchten?", + "UPDATE_SUBSCRIPTION": "Plan ändern", + "CANCEL_SUBSCRIPTION": "Abonnement kündigen", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Alle deine Daten werden am Ende dieses Abrechnungszeitraums von unseren Servern gelöscht.

Bist du sicher, dass du dein Abonnement kündigen möchtest?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Bist du sicher, dass du dein Abonnement beenden möchtest?

", + "SUBSCRIPTION_CANCEL_FAILED": "Abonnement konnte nicht storniert werden", + "SUBSCRIPTION_CANCEL_SUCCESS": "Abonnement erfolgreich beendet", + "REACTIVATE_SUBSCRIPTION": "Abonnement reaktivieren", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Nach der Reaktivierung wird am {{date, dateTime}} abgerechnet", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Abonnement erfolgreich aktiviert ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Reaktivierung der Abonnementverlängerung fehlgeschlagen", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Vielen Dank", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Mobiles Abonnement kündigen", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Bitte kündige dein Abonnement in der mobilen App, um hier ein Abonnement zu aktivieren", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Bitte kontaktiere uns über {{emailID}}, um dein Abo zu verwalten", + "RENAME": "Umbenennen", + "RENAME_FILE": "Datei umbenennen", + "RENAME_COLLECTION": "Album umbenennen", + "DELETE_COLLECTION_TITLE": "Album löschen?", + "DELETE_COLLECTION": "Album löschen", + "DELETE_COLLECTION_MESSAGE": "Auch die Fotos (und Videos) in diesem Album aus allen anderen Alben löschen, die sie enthalten?", + "DELETE_PHOTOS": "Fotos löschen", + "KEEP_PHOTOS": "Fotos behalten", + "SHARE": "Teilen", + "SHARE_COLLECTION": "Album teilen", + "SHAREES": "Geteilt mit", + "SHARE_WITH_SELF": "Du kannst nicht mit dir selbst teilen", + "ALREADY_SHARED": "Hoppla, Sie teilen dies bereits mit {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Albumfreigabe nicht erlaubt", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Freigabe ist für kostenlose Konten deaktiviert", + "DOWNLOAD_COLLECTION": "Album herunterladen", + "DOWNLOAD_COLLECTION_MESSAGE": "

Bist du sicher, dass du das komplette Album herunterladen möchtest?

Alle Dateien werden der Warteschlange zum sequenziellen Download hinzugefügt

", + "CREATE_ALBUM_FAILED": "Fehler beim Erstellen des Albums, bitte versuche es erneut", + "SEARCH": "Suchen", + "SEARCH_RESULTS": "Ergebnisse durchsuchen", + "NO_RESULTS": "Keine Ergebnisse gefunden", + "SEARCH_HINT": "Suche nach Alben, Datum, Beschreibungen, ...", + "SEARCH_TYPE": { + "COLLECTION": "Album", + "LOCATION": "Standort", + "CITY": "Ort", + "DATE": "Datum", + "FILE_NAME": "Dateiname", + "THING": "Inhalt", + "FILE_CAPTION": "Beschreibung", + "FILE_TYPE": "Dateityp", + "CLIP": "Magie" + }, + "photos_count_zero": "Keine Erinnerungen", + "photos_count_one": "Eine Erinnerung", + "photos_count_other": "{{count, number}} Erinnerungen", + "TERMS_AND_CONDITIONS": "Ich stimme den Bedingungen und Datenschutzrichtlinien zu", + "ADD_TO_COLLECTION": "Zum Album hinzufügen", + "SELECTED": "ausgewählt", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Dieses Video kann in deinem Browser nicht abgespielt werden", + "PEOPLE": "Personen", + "INDEXING_SCHEDULED": "Indizierung ist geplant...", + "ANALYZING_PHOTOS": "Indiziere Fotos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", + "INDEXING_PEOPLE": "Indiziere Personen in {{indexStatus.nSyncedFiles,number}} Fotos...", + "INDEXING_DONE": "{{indexStatus.nSyncedFiles,number}} Fotos wurden indiziert", + "UNIDENTIFIED_FACES": "unidentifizierte Gesichter", + "OBJECTS": "Objekte", + "TEXT": "Text", + "INFO": "Info ", + "INFO_OPTION": "Info (I)", + "FILE_NAME": "Dateiname", + "CAPTION_PLACEHOLDER": "Eine Beschreibung hinzufügen", + "LOCATION": "Standort", + "SHOW_ON_MAP": "In OpenStreetMap öffnen", + "MAP": "Karte", + "MAP_SETTINGS": "Karten\nEinstellungen", + "ENABLE_MAPS": "Karten aktivieren?", + "ENABLE_MAP": "Karte aktivieren", + "DISABLE_MAPS": "Karten deaktivieren?", + "ENABLE_MAP_DESCRIPTION": "

Dies wird deine Fotos auf einer Weltkarte anzeigen.

Die Karte wird von OpenStreetMap gehostet und die genauen Standorte deiner Fotos werden niemals geteilt.

Diese Funktion kannst du jederzeit in den Einstellungen deaktivieren.

", + "DISABLE_MAP_DESCRIPTION": "

Dies wird die Anzeige deiner Fotos auf einer Weltkarte deaktivieren.

Du kannst diese Funktion jederzeit in den Einstellungen aktivieren.

", + "DISABLE_MAP": "Karte deaktivieren", + "DETAILS": "Details", + "VIEW_EXIF": "Alle EXIF-Daten anzeigen", + "NO_EXIF": "Keine EXIF-Daten", + "EXIF": "EXIF", + "ISO": "ISO", + "TWO_FACTOR": "Zwei-Faktor", + "TWO_FACTOR_AUTHENTICATION": "Zwei-Faktor-Authentifizierung", + "TWO_FACTOR_QR_INSTRUCTION": "Scanne den QR-Code unten mit deiner bevorzugten Authentifizierungs-App", + "ENTER_CODE_MANUALLY": "Geben Sie den Code manuell ein", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Bitte gib diesen Code in deiner bevorzugten Authentifizierungs-App ein", + "SCAN_QR_CODE": "QR‐Code stattdessen scannen", + "ENABLE_TWO_FACTOR": "Zwei-Faktor-Authentifizierung aktivieren", + "ENABLE": "Aktivieren", + "LOST_DEVICE": "Zwei-Faktor-Gerät verloren", + "INCORRECT_CODE": "Falscher Code", + "TWO_FACTOR_INFO": "Fügen Sie eine zusätzliche Sicherheitsebene hinzu, indem Sie mehr als Ihre E-Mail und Ihr Passwort benötigen, um sich mit Ihrem Account anzumelden", + "DISABLE_TWO_FACTOR_LABEL": "Deaktiviere die Zwei-Faktor-Authentifizierung", + "UPDATE_TWO_FACTOR_LABEL": "Authentifizierungsgerät aktualisieren", + "DISABLE": "Deaktivieren", + "RECONFIGURE": "Neu einrichten", + "UPDATE_TWO_FACTOR": "Zweiten Faktor aktualisieren", + "UPDATE_TWO_FACTOR_MESSAGE": "Fahren Sie fort, werden alle Ihre zuvor konfigurierten Authentifikatoren ungültig", + "UPDATE": "Aktualisierung", + "DISABLE_TWO_FACTOR": "Zweiten Faktor deaktivieren", + "DISABLE_TWO_FACTOR_MESSAGE": "Bist du sicher, dass du die Zwei-Faktor-Authentifizierung deaktivieren willst", + "TWO_FACTOR_DISABLE_FAILED": "Fehler beim Deaktivieren des zweiten Faktors, bitte versuchen Sie es erneut", + "EXPORT_DATA": "Daten exportieren", + "SELECT_FOLDER": "Ordner auswählen", + "DESTINATION": "Zielort", + "START": "Start", + "LAST_EXPORT_TIME": "Letztes Exportdatum", + "EXPORT_AGAIN": "Neusynchronisation", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Lokaler Speicher nicht zugänglich", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Ihr Browser oder ein Addon blockiert ente vor der Speicherung von Daten im lokalen Speicher. Bitte versuchen Sie, den Browser-Modus zu wechseln und die Seite neu zu laden.", + "SEND_OTT": "OTP senden", + "EMAIl_ALREADY_OWNED": "Diese E-Mail wird bereits verwendet", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "Fehlgeschlagene Uploads erneut probieren", + "FAILED_UPLOADS": "Fehlgeschlagene Uploads ", + "SKIPPED_FILES": "Ignorierte Uploads", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Das Vorschaubild konnte nicht erzeugt werden", + "UNSUPPORTED_FILES": "Nicht unterstützte Dateien", + "SUCCESSFUL_UPLOADS": "Erfolgreiche Uploads", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "ente unterstützt diese Dateiformate noch nicht", + "BLOCKED_UPLOADS": "Blockierte Uploads", + "SKIPPED_VIDEOS": "Übersprungene Videos", + "INPROGRESS_METADATA_EXTRACTION": "In Bearbeitung", + "INPROGRESS_UPLOADS": "Upload läuft", + "TOO_LARGE_UPLOADS": "Große Dateien", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Zu wenig Speicher", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Diese Dateien wurden nicht hochgeladen, da sie die maximale Größe für Ihren Speicherplan überschreiten", + "TOO_LARGE_INFO": "Diese Dateien wurden nicht hochgeladen, da sie unsere maximale Dateigröße überschreiten", + "THUMBNAIL_GENERATION_FAILED_INFO": "Diese Dateien wurden hochgeladen, aber leider konnten wir nicht die Thumbnails für sie generieren.", + "UPLOAD_TO_COLLECTION": "In Album hochladen", + "UNCATEGORIZED": "Unkategorisiert", + "ARCHIVE": "Archiv", + "FAVORITES": "Favoriten", + "ARCHIVE_COLLECTION": "Album archivieren", + "ARCHIVE_SECTION_NAME": "Archiv", + "ALL_SECTION_NAME": "Alle", + "MOVE_TO_COLLECTION": "Zum Album verschieben", + "UNARCHIVE": "Dearchivieren", + "UNARCHIVE_COLLECTION": "Album dearchivieren", + "HIDE_COLLECTION": "Album ausblenden", + "UNHIDE_COLLECTION": "Album wieder einblenden", + "MOVE": "Verschieben", + "ADD": "Hinzufügen", + "REMOVE": "Entfernen", + "YES_REMOVE": "Ja, entfernen", + "REMOVE_FROM_COLLECTION": "Aus Album entfernen", + "TRASH": "Papierkorb", + "MOVE_TO_TRASH": "In Papierkorb verschieben", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "Dauerhaft löschen", + "RESTORE": "Wiederherstellen", + "RESTORE_TO_COLLECTION": "In Album wiederherstellen", + "EMPTY_TRASH": "Papierkorb leeren", + "EMPTY_TRASH_TITLE": "Papierkorb leeren?", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "Ja, verlassen", + "LEAVE_ALBUM": "Album verlassen", + "LEAVE_SHARED_ALBUM_TITLE": "Geteiltes Album verlassen?", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "Dateien in einem freigegebenen Album können nicht gelöscht werden", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Einige der Elemente, die du entfernst, wurden von anderen Nutzern hinzugefügt und du wirst den Zugriff auf sie verlieren.", + "SORT_BY_CREATION_TIME_ASCENDING": "Ältestem", + "SORT_BY_UPDATION_TIME_DESCENDING": "Zuletzt aktualisiert", + "SORT_BY_NAME": "Name", + "COMPRESS_THUMBNAILS": "Vorschaubilder komprimieren", + "THUMBNAIL_REPLACED": "Vorschaubilder komprimiert", + "FIX_THUMBNAIL": "Komprimiere", + "FIX_THUMBNAIL_LATER": "Später komprimieren", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "Zeit reparieren", + "FIX_CREATION_TIME_IN_PROGRESS": "Zeit wird repariert", + "CREATION_TIME_UPDATED": "Datei-Zeit aktualisiert", + "UPDATE_CREATION_TIME_NOT_STARTED": "Wählen Sie die Option, die Sie verwenden möchten", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "Maximal 5000 Zeichen", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "Benutzerdefinierte Zeit", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Fehler beim Öffnen der Pläne", + "INSTALL": "Installieren", + "SHARING_DETAILS": "Details teilen", + "MODIFY_SHARING": "Freigabe ändern", + "ADD_COLLABORATORS": "Bearbeiter hinzufügen", + "ADD_NEW_EMAIL": "Neue E-Mail-Adresse hinzufügen", + "shared_with_people_zero": "Mit bestimmten Personen teilen", + "shared_with_people_one": "Geteilt mit einer Person", + "shared_with_people_other": "Geteilt mit {{count, number}} Personen", + "participants_zero": "Keine Teilnehmer", + "participants_one": "1 Teilnehmer", + "participants_other": "{{count, number}} Teilnehmer", + "ADD_VIEWERS": "Betrachter hinzufügen", + "PARTICIPANTS": "Teilnehmer", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "Ja, zu \"Beobachter\" ändern", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "Berechtigung ändern?", + "REMOVE_PARTICIPANT": "Entfernen?", + "CONFIRM_REMOVE": "Ja, entfernen", + "MANAGE": "Verwalten", + "ADDED_AS": "Hinzugefügt als", + "COLLABORATOR_RIGHTS": "Bearbeiter können Fotos & Videos zu dem geteilten Album hinzufügen", + "REMOVE_PARTICIPANT_HEAD": "Teilnehmer entfernen", + "OWNER": "Besitzer", + "COLLABORATORS": "Bearbeiter", + "ADD_MORE": "Mehr hinzufügen", + "VIEWERS": "Zuschauer", + "OR_ADD_EXISTING": "Oder eine Vorherige auswählen", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "404 - Nicht gefunden", + "LINK_EXPIRED": "Link ist abgelaufen", + "LINK_EXPIRED_MESSAGE": "Dieser Link ist abgelaufen oder wurde deaktiviert!", + "MANAGE_LINK": "Link verwalten", + "LINK_TOO_MANY_REQUESTS": "Sorry, dieses Album wurde auf zu vielen Geräten angezeigt!", + "FILE_DOWNLOAD": "Downloads erlauben", + "LINK_PASSWORD_LOCK": "Passwort Sperre", + "PUBLIC_COLLECT": "Hinzufügen von Fotos erlauben", + "LINK_DEVICE_LIMIT": "Geräte Limit", + "NO_DEVICE_LIMIT": "Keins", + "LINK_EXPIRY": "Ablaufdatum des Links", + "NEVER": "Niemals", + "DISABLE_FILE_DOWNLOAD": "Download deaktivieren", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "Enthält schädliche Inhalte", + "COPYRIGHT": "Verletzung des Urheberrechts von jemandem, den ich repräsentieren darf", + "SHARED_USING": "Freigegeben über ", + "ENTE_IO": "ente.io", + "SHARING_REFERRAL_CODE": "", + "LIVE": "LIVE", + "DISABLE_PASSWORD": "Passwort-Sperre deaktivieren", + "DISABLE_PASSWORD_MESSAGE": "Sind Sie sicher, dass Sie die Passwort-Sperre deaktivieren möchten?", + "PASSWORD_LOCK": "Passwort Sperre", + "LOCK": "Sperren", + "DOWNLOAD_UPLOAD_LOGS": "Debug-Logs", + "UPLOAD_FILES": "Datei", + "UPLOAD_DIRS": "Ordner", + "UPLOAD_GOOGLE_TAKEOUT": "Google Takeout", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "Authenticator", + "NO_DUPLICATES_FOUND": "Du hast keine Duplikate, die gelöscht werden können", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "Dateien", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "Hochladen stoppen?", + "YES_STOP_UPLOADS": "Ja, Hochladen stoppen", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "1 Album", + "albums_other": "", + "ALL_ALBUMS": "Alle Alben", + "ALBUMS": "Alben", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "Gib den 6-stelligen Code aus\ndeiner Authentifizierungs-App ein.", + "CREATE_ACCOUNT": "Account erstellen", + "COPIED": "Kopiert", + "CANVAS_BLOCKED_TITLE": "Vorschaubild konnte nicht erstellt werden", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "Jetzt upgraden", + "RENEW_NOW": "", + "STORAGE": "Speicher", + "USED": "verwendet", + "YOU": "Sie", + "FAMILY": "Familie", + "FREE": "frei", + "OF": "von", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "Ordner hinzufügen", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "Ja, Stopp", + "MONTH_SHORT": "", + "YEAR": "Jahr", + "FAMILY_PLAN": "Familientarif", + "DOWNLOAD_LOGS": "Logs herunterladen", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "Ordner ändern", + "TWO_MONTHS_FREE": "Erhalte 2 Monate kostenlos bei Jahresabonnements", + "GB": "GB", + "POPULAR": "Beliebt", + "FREE_PLAN_OPTION_LABEL": "Mit kostenloser Testversion fortfahren", + "FREE_PLAN_DESCRIPTION": "1 GB für 1 Jahr", + "CURRENT_USAGE": "Aktuelle Nutzung ist {{usage}}", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "AUTHENTICATE": "Authentifizieren", + "UPLOADED_TO_SINGLE_COLLECTION": "", + "UPLOADED_TO_SEPARATE_COLLECTIONS": "", + "NEVERMIND": "Egal", + "UPDATE_AVAILABLE": "Neue Version verfügbar", + "UPDATE_INSTALLABLE_MESSAGE": "", + "INSTALL_NOW": "Jetzt installieren", + "INSTALL_ON_NEXT_LAUNCH": "Beim nächsten Start installieren", + "UPDATE_AVAILABLE_MESSAGE": "", + "DOWNLOAD_AND_INSTALL": "", + "IGNORE_THIS_VERSION": "Diese Version ignorieren", + "TODAY": "Heute", + "YESTERDAY": "Gestern", + "NAME_PLACEHOLDER": "Name...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "Beta deaktivieren", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "Erweitert", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "Passwortstärke: Schwach", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "Passwortstärke: Stark", + "PREFERENCES": "Einstellungen", + "LANGUAGE": "Sprache", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "KB", + "MB": "MB", + "GB": "GB", + "TB": "TB" + }, + "AFTER_TIME": { + "HOUR": "nach einer Stunde", + "DAY": "nach einem Tag", + "WEEK": "nach 1 Woche", + "MONTH": "nach einem Monat", + "YEAR": "nach einem Jahr" + }, + "COPY_LINK": "Link kopieren", + "DONE": "Fertig", + "LINK_SHARE_TITLE": "Oder einen Link teilen", + "REMOVE_LINK": "Link entfernen", + "CREATE_PUBLIC_SHARING": "Öffentlichen Link erstellen", + "PUBLIC_LINK_CREATED": "Öffentlicher Link erstellt", + "PUBLIC_LINK_ENABLED": "Öffentlicher Link aktiviert", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "Stop", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "Export gestartet", + "IN_PROGRESS": "", + "FINISH": "Export abgeschlossen", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "Kontolöschung bestätigen", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "Weiter", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "Versteckt", + "HIDE": "Ausblenden", + "UNHIDE": "Einblenden", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "Sortieren nach", + "NEWEST_FIRST": "Neueste zuerst", + "OLDEST_FIRST": "Älteste zuerst", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "Diese Datei konnte nicht in der Vorschau angezeigt werden. Klicken Sie hier, um das Original herunterzuladen.", + "SELECT_COLLECTION": "Album auswählen", + "PIN_ALBUM": "Album anheften", + "UNPIN_ALBUM": "Album lösen", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/accounts/public/locales/en/translation.json b/web/apps/cast/public/locales/en-US/translation.json similarity index 97% rename from web/apps/accounts/public/locales/en/translation.json rename to web/apps/cast/public/locales/en-US/translation.json index 6870df3194..de8d2fe2a1 100644 --- a/web/apps/accounts/public/locales/en/translation.json +++ b/web/apps/cast/public/locales/en-US/translation.json @@ -41,8 +41,6 @@ "REFERRAL_CODE_HINT": "How did you hear about Ente? (optional)", "REFERRAL_INFO": "We don't track app installs, It'd help us if you told us where you found us!", "PASSPHRASE_MATCH_ERROR": "Passwords don't match", - "CONSOLE_WARNING_STOP": "STOP!", - "CONSOLE_WARNING_DESC": "This is a browser feature intended for developers. Please don't copy-paste unverified code here.", "CREATE_COLLECTION": "New album", "ENTER_ALBUM_NAME": "Album name", "CLOSE_OPTION": "Close (Esc)", @@ -590,7 +588,6 @@ "DOWNLOADING_COLLECTION": "Downloading {{name}}", "DOWNLOAD_FAILED": "Download failed", "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} files", - "CRASH_REPORTING": "Crash reporting", "CHRISTMAS": "Christmas", "CHRISTMAS_EVE": "Christmas Eve", "NEW_YEAR": "New Year", @@ -637,8 +634,21 @@ "VISIT_CAST_ENTE_IO": "Visit cast.ente.io on the device you want to pair.", "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair failed. Please try again.", "CACHE_DIRECTORY": "Cache folder", - "PASSKEYS": "Passkeys", "FREEHAND": "Freehand", "APPLY_CROP": "Apply Crop", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving." + "PHOTO_EDIT_REQUIRED_TO_SAVE": "At least one transformation or color adjustment must be performed before saving.", + "PASSKEYS": "Passkeys", + "DELETE_PASSKEY": "Delete passkey", + "DELETE_PASSKEY_CONFIRMATION": "Are you sure you want to delete this passkey? This action is irreversible.", + "RENAME_PASSKEY": "Rename passkey", + "ADD_PASSKEY": "Add passkey", + "ENTER_PASSKEY_NAME": "Enter passkey name", + "PASSKEYS_DESCRIPTION": "Passkeys are a modern and secure second-factor for your Ente account. They use on-device biometric authentication for convenience and security.", + "CREATED_AT": "Created at", + "PASSKEY_LOGIN_FAILED": "Passkey login failed", + "PASSKEY_LOGIN_URL_INVALID": "The login URL is invalid.", + "PASSKEY_LOGIN_ERRORED": "An error occurred while logging in with passkey.", + "TRY_AGAIN": "Try again", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "Follow the steps from your browser to continue logging in.", + "LOGIN_WITH_PASSKEY": "Login with passkey" } diff --git a/web/apps/cast/public/locales/es-ES/translation.json b/web/apps/cast/public/locales/es-ES/translation.json new file mode 100644 index 0000000000..a29165e4ee --- /dev/null +++ b/web/apps/cast/public/locales/es-ES/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Copias de seguridad privadas
para su recuerdos
", + "HERO_SLIDE_1": "Encriptado de extremo a extremo por defecto", + "HERO_SLIDE_2_TITLE": "
Almacenado de forma segura
en un refugio de llenos
", + "HERO_SLIDE_2": "Diseñado para superar", + "HERO_SLIDE_3_TITLE": "
Disponible
en todas partes
", + "HERO_SLIDE_3": "Android, iOS, web, computadora", + "LOGIN": "Conectar", + "SIGN_UP": "Registro", + "NEW_USER": "Nuevo en ente", + "EXISTING_USER": "Usuario existente", + "ENTER_NAME": "Introducir nombre", + "PUBLIC_UPLOADER_NAME_MESSAGE": "¡Añade un nombre para que tus amigos sepan a quién dar las gracias por estas fotos geniales!", + "ENTER_EMAIL": "Introducir email", + "EMAIL_ERROR": "Introduce un email válido", + "REQUIRED": "Requerido", + "EMAIL_SENT": "Código de verificación enviado al {{email}}", + "CHECK_INBOX": "Revisa tu bandeja de entrada (y spam) para completar la verificación", + "ENTER_OTT": "Código de verificación", + "RESEND_MAIL": "Reenviar el código", + "VERIFY": "Verificar", + "UNKNOWN_ERROR": "Se produjo un error. Por favor, inténtalo de nuevo", + "INVALID_CODE": "Código de verificación inválido", + "EXPIRED_CODE": "Código de verificación expirado", + "SENDING": "Enviando...", + "SENT": "Enviado!", + "PASSWORD": "Contraseña", + "LINK_PASSWORD": "Introducir contraseña para desbloquear el álbum", + "RETURN_PASSPHRASE_HINT": "Contraseña", + "SET_PASSPHRASE": "Definir contraseña", + "VERIFY_PASSPHRASE": "Ingresar", + "INCORRECT_PASSPHRASE": "Contraseña incorrecta", + "ENTER_ENC_PASSPHRASE": "Introducir una contraseña que podamos usar para cifrar sus datos", + "PASSPHRASE_DISCLAIMER": "No guardamos su contraseña, así que si la olvida, no podremos ayudarte a recuperar tus datos sin una clave de recuperación.", + "WELCOME_TO_ENTE_HEADING": "Bienvenido a ", + "WELCOME_TO_ENTE_SUBHEADING": "Almacenamiento y compartición de fotos cifradas de extremo a extremo", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "Donde vivan su mejores fotos", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generando claves de encriptación...", + "PASSPHRASE_HINT": "Contraseña", + "CONFIRM_PASSPHRASE": "Confirmar contraseña", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "Las contraseñas no coinciden", + "CREATE_COLLECTION": "Nuevo álbum", + "ENTER_ALBUM_NAME": "Nombre del álbum", + "CLOSE_OPTION": "Cerrar (Esc)", + "ENTER_FILE_NAME": "Nombre del archivo", + "CLOSE": "Cerrar", + "NO": "No", + "NOTHING_HERE": "Nada para ver aquí aún 👀", + "UPLOAD": "Cargar", + "IMPORT": "Importar", + "ADD_PHOTOS": "Añadir fotos", + "ADD_MORE_PHOTOS": "Añadir más fotos", + "add_photos_one": "Añadir 1 foto", + "add_photos_other": "Añadir {{count}} fotos", + "SELECT_PHOTOS": "Seleccionar fotos", + "FILE_UPLOAD": "Subir archivo", + "UPLOAD_STAGE_MESSAGE": { + "0": "Preparando la subida", + "1": "Leyendo archivos de metadatos de google", + "2": "{{uploadCounter.finished}} / {{uploadCounter.total}} archivos metadatos extraídos", + "3": "{{uploadCounter.finished}} / {{uploadCounter.total}} archivos metadatos extraídos", + "4": "Cancelar subidas restantes", + "5": "Copia de seguridad completa" + }, + "FILE_NOT_UPLOADED_LIST": "Los siguientes archivos no se han subido", + "SUBSCRIPTION_EXPIRED": "Suscripción caducada", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Tu suscripción ha caducado, por favor renuévala", + "STORAGE_QUOTA_EXCEEDED": "Límite de datos excedido", + "INITIAL_LOAD_DELAY_WARNING": "La primera carga puede tomar algún tiempo", + "USER_DOES_NOT_EXIST": "Lo sentimos, no se pudo encontrar un usuario con ese email", + "NO_ACCOUNT": "No tienes una cuenta", + "ACCOUNT_EXISTS": "Ya tienes una cuenta", + "CREATE": "Crear", + "DOWNLOAD": "Descargar", + "DOWNLOAD_OPTION": "Descargar (D)", + "DOWNLOAD_FAVORITES": "Descargar favoritos", + "DOWNLOAD_UNCATEGORIZED": "Descargar no categorizados", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "Copiar como PNG (Ctrl/Cmd - C)", + "TOGGLE_FULLSCREEN": "Alternar pantalla completa (F)", + "ZOOM_IN_OUT": "Acercar/alejar", + "PREVIOUS": "Anterior (←)", + "NEXT": "Siguiente (→)", + "TITLE_PHOTOS": "ente Fotos", + "TITLE_ALBUMS": "ente Fotos", + "TITLE_AUTH": "ente Auth", + "UPLOAD_FIRST_PHOTO": "Carga tu primer archivo", + "IMPORT_YOUR_FOLDERS": "Importar tus carpetas", + "UPLOAD_DROPZONE_MESSAGE": "Soltar para respaldar tus archivos", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Soltar para añadir carpeta vigilada", + "TRASH_FILES_TITLE": "Eliminar archivos?", + "TRASH_FILE_TITLE": "Eliminar archivo?", + "DELETE_FILES_TITLE": "Eliminar inmediatamente?", + "DELETE_FILES_MESSAGE": "Los archivos seleccionados serán eliminados permanentemente de tu cuenta ente.", + "DELETE": "Eliminar", + "DELETE_OPTION": "Eliminar (DEL)", + "FAVORITE_OPTION": "Favorito (L)", + "UNFAVORITE_OPTION": "No favorito (L)", + "MULTI_FOLDER_UPLOAD": "Múltiples carpetas detectadas", + "UPLOAD_STRATEGY_CHOICE": "Quieres subirlos a", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Un solo álbum", + "OR": "o", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Separar álbumes", + "SESSION_EXPIRED_MESSAGE": "Tu sesión ha caducado. Inicia sesión de nuevo para continuar", + "SESSION_EXPIRED": "Sesión caducado", + "PASSWORD_GENERATION_FAILED": "Su navegador no ha podido generar una clave fuerte que cumpla con los estándares de cifrado de la entidad, por favor intente usar la aplicación móvil u otro navegador", + "CHANGE_PASSWORD": "Cambiar contraseña", + "GO_BACK": "Retroceder", + "RECOVERY_KEY": "Clave de recuperación", + "SAVE_LATER": "Hacer más tarde", + "SAVE": "Guardar Clave", + "RECOVERY_KEY_DESCRIPTION": "Si olvida su contraseña, la única forma de recuperar sus datos es con esta clave.", + "RECOVER_KEY_GENERATION_FAILED": "El código de recuperación no pudo ser generado, por favor inténtalo de nuevo", + "KEY_NOT_STORED_DISCLAIMER": "No almacenamos esta clave, así que por favor guarde esto en un lugar seguro", + "FORGOT_PASSWORD": "Contraseña olvidada", + "RECOVER_ACCOUNT": "Recuperar cuenta", + "RECOVERY_KEY_HINT": "Clave de recuperación", + "RECOVER": "Recuperar", + "NO_RECOVERY_KEY": "No hay clave de recuperación?", + "INCORRECT_RECOVERY_KEY": "Clave de recuperación incorrecta", + "SORRY": "Lo sentimos", + "NO_RECOVERY_KEY_MESSAGE": "Debido a la naturaleza de nuestro protocolo de cifrado de extremo a extremo, sus datos no pueden ser descifrados sin su contraseña o clave de recuperación", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Por favor, envíe un email a {{emailID}} desde su dirección de correo electrónico registrada", + "CONTACT_SUPPORT": "Contacta con soporte", + "REQUEST_FEATURE": "Solicitar una función", + "SUPPORT": "Soporte", + "CONFIRM": "Confirmar", + "CANCEL": "Cancelar", + "LOGOUT": "Cerrar sesión", + "DELETE_ACCOUNT": "Eliminar cuenta", + "DELETE_ACCOUNT_MESSAGE": "

Por favor, envíe un email a {{emailID}} desde su dirección de correo electrónico registrada

Su solicitud será procesada en 72 horas.

", + "LOGOUT_MESSAGE": "Seguro que quiere cerrar la sesión?", + "CHANGE_EMAIL": "Cambiar email", + "OK": "OK", + "SUCCESS": "Completado", + "ERROR": "Error", + "MESSAGE": "Mensaje", + "INSTALL_MOBILE_APP": "Instala nuestra aplicación Android o iOS para hacer una copia de seguridad automática de todas usted fotos", + "DOWNLOAD_APP_MESSAGE": "Lo sentimos, esta operación sólo es compatible con nuestra aplicación de computadora", + "DOWNLOAD_APP": "Descargar aplicación de computadora", + "EXPORT": "Exportar datos", + "SUBSCRIPTION": "Suscripción", + "SUBSCRIBE": "Suscribir", + "MANAGEMENT_PORTAL": "Gestionar métodos de pago", + "MANAGE_FAMILY_PORTAL": "Administrar familia", + "LEAVE_FAMILY_PLAN": "Dejar plan familiar", + "LEAVE": "Dejar", + "LEAVE_FAMILY_CONFIRM": "Está seguro de que desea abandonar el plan familiar?", + "CHOOSE_PLAN": "Elije tu plan", + "MANAGE_PLAN": "Administra tu suscripción", + "ACTIVE": "Activo", + "OFFLINE_MSG": "Estás desconectado, se están mostrando recuerdos en caché", + "FREE_SUBSCRIPTION_INFO": "Estás en el plan gratis que expira el {{date, dateTime}}", + "FAMILY_SUBSCRIPTION_INFO": "Estás en un plan familiar administrado por", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Se renueva en {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Termina el {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Tu suscripción será cancelada el {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Ha excedido su cuota de almacenamiento, por favor actualice", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

Hemos recibido tu pago

¡Tu suscripción es válida hasta {{date, dateTime}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "Tu compra ha sido cancelada, por favor inténtalo de nuevo si quieres suscribirte", + "SUBSCRIPTION_PURCHASE_FAILED": "Compra de suscripción fallida, por favor inténtalo de nuevo", + "SUBSCRIPTION_UPDATE_FAILED": "Suscripción actualizada falló, inténtelo de nuevo", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Lo sentimos, el pago falló cuando intentamos cargar a su tarjeta, por favor actualice su método de pago y vuelva a intentarlo", + "STRIPE_AUTHENTICATION_FAILED": "No podemos autenticar tu método de pago. Por favor, elige un método de pago diferente e inténtalo de nuevo", + "UPDATE_PAYMENT_METHOD": "Actualizar medio de pago", + "MONTHLY": "Mensual", + "YEARLY": "Anual", + "UPDATE_SUBSCRIPTION_MESSAGE": "Seguro de que desea cambiar su plan?", + "UPDATE_SUBSCRIPTION": "Cambiar de plan", + "CANCEL_SUBSCRIPTION": "Cancelar suscripción", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Todos tus datos serán eliminados de nuestros servidores al final de este periodo de facturación.

¿Está seguro de que desea cancelar su suscripción?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "No se pudo cancelar la suscripción", + "SUBSCRIPTION_CANCEL_SUCCESS": "Suscripción cancelada correctamente", + "REACTIVATE_SUBSCRIPTION": "Reactivar la suscripción", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Una vez reactivado, serás facturado el {{date, dateTime}}", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Suscripción activada correctamente ", + "SUBSCRIPTION_ACTIVATE_FAILED": "No se pudo reactivar las renovaciones de suscripción", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Gracias", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Cancelar suscripción a móviles", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Por favor, cancele su suscripción de la aplicación móvil para activar una suscripción aquí", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Por favor, contáctenos en {{emailID}} para gestionar su suscripción", + "RENAME": "Renombrar", + "RENAME_FILE": "Renombrar archivo", + "RENAME_COLLECTION": "Renombrar álbum", + "DELETE_COLLECTION_TITLE": "Eliminar álbum?", + "DELETE_COLLECTION": "Eliminar álbum", + "DELETE_COLLECTION_MESSAGE": "También eliminar las fotos (y los vídeos) presentes en este álbum de todos álbumes de los que forman parte?", + "DELETE_PHOTOS": "Eliminar fotos", + "KEEP_PHOTOS": "Conservar fotos", + "SHARE": "Compartir", + "SHARE_COLLECTION": "Compartir álbum", + "SHAREES": "Compartido con", + "SHARE_WITH_SELF": "Uy, no puedes compartir contigo mismo", + "ALREADY_SHARED": "Uy, ya estás compartiendo esto con {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Compartir álbum no permitido", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Compartir está desactivado para cuentas gratis", + "DOWNLOAD_COLLECTION": "Descargar álbum", + "DOWNLOAD_COLLECTION_MESSAGE": "

¿Está seguro de que desea descargar el álbum completo?

Todos los archivos se pondrán en cola para su descarga secuencialmente

", + "CREATE_ALBUM_FAILED": "Error al crear el álbum, inténtalo de nuevo", + "SEARCH": "Buscar", + "SEARCH_RESULTS": "Buscar resultados", + "NO_RESULTS": "No se han encontrado resultados", + "SEARCH_HINT": "Buscar álbumes, fechas...", + "SEARCH_TYPE": { + "COLLECTION": "Álbum", + "LOCATION": "Localización", + "CITY": "", + "DATE": "Fecha", + "FILE_NAME": "Nombre del archivo", + "THING": "Contenido", + "FILE_CAPTION": "Descripción", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "No hay recuerdos", + "photos_count_one": "1 recuerdo", + "photos_count_other": "{{count}} recuerdos", + "TERMS_AND_CONDITIONS": "Acepto los términos y política de privacidad", + "ADD_TO_COLLECTION": "Añadir al álbum", + "SELECTED": "seleccionado", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Este vídeo no se puede reproducir en tu navegador", + "PEOPLE": "Personajes", + "INDEXING_SCHEDULED": "el indexado está programado...", + "ANALYZING_PHOTOS": "analizando nuevas fotos {{indexStatus.nSyncedFiles}} de {{indexStatus.nTotalFiles}} hecho)...", + "INDEXING_PEOPLE": "indexando personas en {{indexStatus.nSyncedFiles}} fotos... ", + "INDEXING_DONE": "fotos {{indexStatus.nSyncedFiles}} indexadas", + "UNIDENTIFIED_FACES": "caras no identificadas", + "OBJECTS": "objetos", + "TEXT": "texto", + "INFO": "Info ", + "INFO_OPTION": "Info (I)", + "FILE_NAME": "Nombre del archivo", + "CAPTION_PLACEHOLDER": "Añadir una descripción", + "LOCATION": "Localización", + "SHOW_ON_MAP": "Ver en OpenStreetMap", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "Detalles", + "VIEW_EXIF": "Ver todos los datos de EXIF", + "NO_EXIF": "No hay datos EXIF", + "EXIF": "EXIF", + "ISO": "ISO", + "TWO_FACTOR": "Dos factores", + "TWO_FACTOR_AUTHENTICATION": "Autenticación de dos factores", + "TWO_FACTOR_QR_INSTRUCTION": "Escanea el código QR de abajo con tu aplicación de autenticación favorita", + "ENTER_CODE_MANUALLY": "Ingrese el código manualmente", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Por favor, introduce este código en tu aplicación de autenticación favorita", + "SCAN_QR_CODE": "Escanear código QR en su lugar", + "ENABLE_TWO_FACTOR": "Activar dos factores", + "ENABLE": "Activar", + "LOST_DEVICE": "Perdido el dispositivo de doble factor", + "INCORRECT_CODE": "Código incorrecto", + "TWO_FACTOR_INFO": "Añade una capa adicional de seguridad al requerir más de tu email y contraseña para iniciar sesión en tu cuenta", + "DISABLE_TWO_FACTOR_LABEL": "Deshabilitar la autenticación de dos factores", + "UPDATE_TWO_FACTOR_LABEL": "Actualice su dispositivo de autenticación", + "DISABLE": "Desactivar", + "RECONFIGURE": "Reconfigurar", + "UPDATE_TWO_FACTOR": "Actualizar doble factor", + "UPDATE_TWO_FACTOR_MESSAGE": "Continuar adelante anulará los autenticadores previamente configurados", + "UPDATE": "Actualizar", + "DISABLE_TWO_FACTOR": "Desactivar doble factor", + "DISABLE_TWO_FACTOR_MESSAGE": "¿Estás seguro de que desea deshabilitar la autenticación de doble factor?", + "TWO_FACTOR_DISABLE_FAILED": "Error al desactivar dos factores, inténtalo de nuevo", + "EXPORT_DATA": "Exportar datos", + "SELECT_FOLDER": "Seleccionar carpeta", + "DESTINATION": "Destinación", + "START": "Inicio", + "LAST_EXPORT_TIME": "Fecha de la última exportación", + "EXPORT_AGAIN": "Resinc", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Almacenamiento local inaccesible", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Su navegador o un addon está bloqueando a ente de guardar datos en almacenamiento local. Por favor, intente cargar esta página después de cambiar su modo de navegación.", + "SEND_OTT": "Enviar OTP", + "EMAIl_ALREADY_OWNED": "Email ya tomado", + "ETAGS_BLOCKED": "

No hemos podido subir los siguientes archivos debido a la configuración de tu navegador.

Por favor, deshabilite cualquier complemento que pueda estar impidiendo que ente utilice eTags para subir archivos grandes, o utilice nuestra aplicación de escritorio para una experiencia de importación más fiable.

", + "SKIPPED_VIDEOS_INFO": "

Actualmente no podemos añadir vídeos a través de enlaces públicos.

Para compartir vídeos, por favor regístrate en ente y comparte con los destinatarios a través de su correo electrónico.

", + "LIVE_PHOTOS_DETECTED": "Los archivos de foto y vídeo de tus fotos en vivo se han fusionado en un solo archivo", + "RETRY_FAILED": "Reintentar subidas fallidas", + "FAILED_UPLOADS": "Subidas fallidas ", + "SKIPPED_FILES": "Subidas ignoradas", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Generación de miniaturas fallida", + "UNSUPPORTED_FILES": "Archivos no soportados", + "SUCCESSFUL_UPLOADS": "Subidas exitosas", + "SKIPPED_INFO": "Se han omitido ya que hay archivos con nombres coincidentes en el mismo álbum", + "UNSUPPORTED_INFO": "ente no soporta estos formatos de archivo aún", + "BLOCKED_UPLOADS": "Subidas bloqueadas", + "SKIPPED_VIDEOS": "Vídeos saltados", + "INPROGRESS_METADATA_EXTRACTION": "En proceso", + "INPROGRESS_UPLOADS": "Subidas en progreso", + "TOO_LARGE_UPLOADS": "Archivos grandes", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Espacio insuficiente", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Estos archivos no se han subido porque exceden el límite de tamaño máximo para tu plan de almacenamiento", + "TOO_LARGE_INFO": "Estos archivos no se han subido porque exceden nuestro límite máximo de tamaño de archivo", + "THUMBNAIL_GENERATION_FAILED_INFO": "Estos archivos fueron cargados, pero por desgracia no pudimos generar las miniaturas para ellos.", + "UPLOAD_TO_COLLECTION": "Subir al álbum", + "UNCATEGORIZED": "No clasificado", + "ARCHIVE": "Archivo", + "FAVORITES": "Favoritos", + "ARCHIVE_COLLECTION": "Archivo álbum", + "ARCHIVE_SECTION_NAME": "Archivo", + "ALL_SECTION_NAME": "Todo", + "MOVE_TO_COLLECTION": "Mover al álbum", + "UNARCHIVE": "Desarchivar", + "UNARCHIVE_COLLECTION": "Desarchivar álbum", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "Mover", + "ADD": "Añadir", + "REMOVE": "Eliminar", + "YES_REMOVE": "Sí, eliminar", + "REMOVE_FROM_COLLECTION": "Eliminar del álbum", + "TRASH": "Papelera", + "MOVE_TO_TRASH": "Mover a la papelera", + "TRASH_FILES_MESSAGE": "Los archivos seleccionados serán eliminados de todos los álbumes y movidos a la papelera.", + "TRASH_FILE_MESSAGE": "El archivo será eliminado de todos los álbumes y movido a la papelera.", + "DELETE_PERMANENTLY": "Eliminar para siempre", + "RESTORE": "Restaurar", + "RESTORE_TO_COLLECTION": "Restaurar al álbum", + "EMPTY_TRASH": "Vaciar papelera", + "EMPTY_TRASH_TITLE": "Vaciar papelera?", + "EMPTY_TRASH_MESSAGE": "Estos archivos serán eliminados permanentemente de su cuenta ente.", + "LEAVE_SHARED_ALBUM": "Sí, dejar", + "LEAVE_ALBUM": "Dejar álbum", + "LEAVE_SHARED_ALBUM_TITLE": "¿Dejar álbum compartido?", + "LEAVE_SHARED_ALBUM_MESSAGE": "Dejará el álbum, y dejará de ser visible para usted.", + "NOT_FILE_OWNER": "No puedes eliminar archivos de un álbum compartido", + "CONFIRM_SELF_REMOVE_MESSAGE": "Los elementos seleccionados serán eliminados de este álbum. Los elementos que estén sólo en este álbum serán movidos a Sin categorizar.", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Algunos de los elementos que estás eliminando fueron añadidos por otras personas, y perderás el acceso a ellos.", + "SORT_BY_CREATION_TIME_ASCENDING": "Antiguo", + "SORT_BY_UPDATION_TIME_DESCENDING": "Última actualización", + "SORT_BY_NAME": "Nombre", + "COMPRESS_THUMBNAILS": "Comprimir las miniaturas", + "THUMBNAIL_REPLACED": "Miniaturas comprimidas", + "FIX_THUMBNAIL": "Comprimir", + "FIX_THUMBNAIL_LATER": "Comprimir más tarde", + "REPLACE_THUMBNAIL_NOT_STARTED": "Algunas de tus miniaturas de vídeos pueden ser comprimidas para ahorrar espacio. ¿Te gustaría que ente las comprima?", + "REPLACE_THUMBNAIL_COMPLETED": "Todas las miniaturas se comprimieron con éxito", + "REPLACE_THUMBNAIL_NOOP": "No tienes miniaturas que se puedan comprimir más", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "No se pudieron comprimir algunas de tus miniaturas, por favor inténtalo de nuevo", + "FIX_CREATION_TIME": "Fijar hora", + "FIX_CREATION_TIME_IN_PROGRESS": "Fijar hora", + "CREATION_TIME_UPDATED": "Hora del archivo actualizada", + "UPDATE_CREATION_TIME_NOT_STARTED": "Seleccione la cartera que desea utilizar", + "UPDATE_CREATION_TIME_COMPLETED": "Todos los archivos se han actualizado correctamente", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "Fallo en la hora del archivo para algunos archivos, por favor inténtelo de nuevo", + "CAPTION_CHARACTER_LIMIT": "Máximo 5000 caracteres", + "DATE_TIME_ORIGINAL": "EXIF: Fecha original", + "DATE_TIME_DIGITIZED": "EXIF: Fecha Digitalizado", + "METADATA_DATE": "", + "CUSTOM_TIME": "Hora personalizada", + "REOPEN_PLAN_SELECTOR_MODAL": "Reabrir planes", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Error al abrir los planes", + "INSTALL": "Instalar", + "SHARING_DETAILS": "Compartir detalles", + "MODIFY_SHARING": "Modificar compartir", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "Propietario", + "COLLABORATORS": "Colaboradores", + "ADD_MORE": "Añadir más", + "VIEWERS": "", + "OR_ADD_EXISTING": "O elige uno existente", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "404 - No Encontrado", + "LINK_EXPIRED": "Enlace expirado", + "LINK_EXPIRED_MESSAGE": "Este enlace ha caducado o ha sido desactivado!", + "MANAGE_LINK": "Administrar enlace", + "LINK_TOO_MANY_REQUESTS": "Este álbum es demasiado popular para que podamos manejarlo!", + "FILE_DOWNLOAD": "Permitir descargas", + "LINK_PASSWORD_LOCK": "Contraseña bloqueada", + "PUBLIC_COLLECT": "Permitir añadir fotos", + "LINK_DEVICE_LIMIT": "Límites del dispositivo", + "NO_DEVICE_LIMIT": "Ninguno", + "LINK_EXPIRY": "Enlace vencio", + "NEVER": "Nunca", + "DISABLE_FILE_DOWNLOAD": "Deshabilitar descarga", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "

¿Está seguro que desea desactivar el botón de descarga de archivos?

Los visualizadores todavía pueden tomar capturas de pantalla o guardar una copia de sus fotos usando herramientas externas.

", + "MALICIOUS_CONTENT": "Contiene contenido malicioso", + "COPYRIGHT": "Infracciones sobre los derechos de autor de alguien que estoy autorizado a representar", + "SHARED_USING": "Compartido usando ", + "ENTE_IO": "ente.io", + "SHARING_REFERRAL_CODE": "Usa el código {{referralCode}} para obtener 10 GB gratis", + "LIVE": "VIVO", + "DISABLE_PASSWORD": "Desactivar contraseña", + "DISABLE_PASSWORD_MESSAGE": "Seguro que quieres cambiar la contrasena?", + "PASSWORD_LOCK": "Contraseña bloqueada", + "LOCK": "Bloquear", + "DOWNLOAD_UPLOAD_LOGS": "Logs de depuración", + "UPLOAD_FILES": "Archivo", + "UPLOAD_DIRS": "Carpeta", + "UPLOAD_GOOGLE_TAKEOUT": "Google Takeout", + "DEDUPLICATE_FILES": "Deduplicar archivos", + "AUTHENTICATOR_SECTION": "Autenticación", + "NO_DUPLICATES_FOUND": "No tienes archivos duplicados que puedan ser borrados", + "CLUB_BY_CAPTURE_TIME": "Club por tiempo de captura", + "FILES": "Archivos", + "EACH": "Cada", + "DEDUPLICATE_BASED_ON_SIZE": "Los siguientes archivos fueron organizados en base a sus tamaños, por favor revise y elimine elementos que cree que son duplicados", + "STOP_ALL_UPLOADS_MESSAGE": "¿Está seguro que desea detener todas las subidas en curso?", + "STOP_UPLOADS_HEADER": "Detener las subidas?", + "YES_STOP_UPLOADS": "Sí, detener las subidas", + "STOP_DOWNLOADS_HEADER": "¿Detener las descargas?", + "YES_STOP_DOWNLOADS": "Sí, detener las descargas", + "STOP_ALL_DOWNLOADS_MESSAGE": "¿Estás seguro de que quieres detener todas las descargas en curso?", + "albums_one": "1 álbum", + "albums_other": "{{count}} álbumes", + "ALL_ALBUMS": "Todos los álbumes", + "ALBUMS": "Álbumes", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "Ingrese el código de seis dígitos de su aplicación de autenticación a continuación.", + "CREATE_ACCOUNT": "Crear cuenta", + "COPIED": "Copiado", + "CANVAS_BLOCKED_TITLE": "No se puede generar la miniatura", + "CANVAS_BLOCKED_MESSAGE": "

Parece que su navegador ha deshabilitado el acceso al lienzo, que es necesario para generar miniaturas para tus fotos

Por favor, activa el acceso al lienzo de tu navegador, o revisa nuestra aplicación de escritorio

", + "WATCH_FOLDERS": "Ver carpetas", + "UPGRADE_NOW": "Mejorar ahora", + "RENEW_NOW": "Renovar ahora", + "STORAGE": "Almacén", + "USED": "usado", + "YOU": "Usted", + "FAMILY": "Familia", + "FREE": "gratis", + "OF": "de", + "WATCHED_FOLDERS": "Ver carpetas", + "NO_FOLDERS_ADDED": "No hay carpetas añadidas!", + "FOLDERS_AUTOMATICALLY_MONITORED": "Las carpetas que añadas aquí serán supervisadas automáticamente", + "UPLOAD_NEW_FILES_TO_ENTE": "Subir nuevos archivos a ente", + "REMOVE_DELETED_FILES_FROM_ENTE": "Eliminar archivos borrados de ente", + "ADD_FOLDER": "Añadir carpeta", + "STOP_WATCHING": "Dejar de ver", + "STOP_WATCHING_FOLDER": "Dejar de ver carpeta?", + "STOP_WATCHING_DIALOG_MESSAGE": "Tus archivos existentes no serán eliminados, pero ente dejará de actualizar automáticamente el álbum enlazado en caso de cambios en esta carpeta.", + "YES_STOP": "Sí, detener", + "MONTH_SHORT": "mes", + "YEAR": "año", + "FAMILY_PLAN": "Plan familiar", + "DOWNLOAD_LOGS": "Descargar logs", + "DOWNLOAD_LOGS_MESSAGE": "

Esto descargará los registros de depuración, que puede enviarnos por correo electrónico para ayudarnos a depurar su problema.

Tenga en cuenta que los nombres de los archivos se incluirán para ayudar al seguimiento de problemas con archivos específicos.

", + "CHANGE_FOLDER": "Cambiar carpeta", + "TWO_MONTHS_FREE": "Obtén 2 meses gratis en planes anuales", + "GB": "GB", + "POPULAR": "Popular", + "FREE_PLAN_OPTION_LABEL": "Continuar con el plan gratuito", + "FREE_PLAN_DESCRIPTION": "1 GB por 1 año", + "CURRENT_USAGE": "El uso actual es {{usage}}", + "WEAK_DEVICE": "El navegador web que está utilizando no es lo suficientemente poderoso para cifrar sus fotos. Por favor, intente iniciar sesión en ente en su computadora, o descargue la aplicación ente para móvil/escritorio.", + "DRAG_AND_DROP_HINT": "O arrastre y suelte en la ventana ente", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Los datos subidos se eliminarán y su cuenta se eliminará de forma permanente.

Esta acción no es reversible.", + "AUTHENTICATE": "Autenticado", + "UPLOADED_TO_SINGLE_COLLECTION": "Subir a una sola colección", + "UPLOADED_TO_SEPARATE_COLLECTIONS": "Subir a colecciones separadas", + "NEVERMIND": "No importa", + "UPDATE_AVAILABLE": "Actualizacion disponible", + "UPDATE_INSTALLABLE_MESSAGE": "Una nueva versión de ente está lista para ser instalada.", + "INSTALL_NOW": "Instalar ahora", + "INSTALL_ON_NEXT_LAUNCH": "Instalar en el próximo lanzamiento", + "UPDATE_AVAILABLE_MESSAGE": "Una nueva versión de ente ha sido lanzada, pero no se puede descargar e instalar automáticamente.", + "DOWNLOAD_AND_INSTALL": "Descargar e instalar", + "IGNORE_THIS_VERSION": "Ignorar esta versión", + "TODAY": "Hoy", + "YESTERDAY": "Ayer", + "NAME_PLACEHOLDER": "Nombre...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "No se puede crear álbumes de mezcla de archivos/carpetas", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

Has arrastrado y soltado una mezcla de archivos y carpetas.

Por favor proporcione sólo archivos o carpetas cuando seleccione la opción de crear álbumes separados

", + "CHOSE_THEME": "Elegir tema", + "ML_SEARCH": "Buscar ML (beta)", + "ENABLE_ML_SEARCH_DESCRIPTION": "

Esto permitirá el aprendizaje automático en el dispositivo y la búsqueda facial que comenzará a analizar las fotos subidas localmente.

Para la primera ejecución después de iniciar sesión o habilitar esta función, se descargarán todas las imágenes en el dispositivo local para analizarlas. Así que por favor actívalo sólo si dispones ancho de banda y el almacenamiento suficiente para el procesamiento local de todas las imágenes en tu biblioteca de fotos.

Si esta es la primera vez que está habilitando, también le pediremos su permiso para procesar los datos faciales.

", + "ML_MORE_DETAILS": "Más detalles", + "ENABLE_FACE_SEARCH": "Activar búsqueda facial", + "ENABLE_FACE_SEARCH_TITLE": "Activar búsqueda facial?", + "ENABLE_FACE_SEARCH_DESCRIPTION": "

Si activas la búsqueda facial, ente extraerá la geometría facial de tus fotos. Esto sucederá en su dispositivo y cualquier dato biométrico generado será cifrado de extremo a extremo.

Haga clic aquí para obtener más detalles sobre esta característica en nuestra política de privacidad

", + "DISABLE_BETA": "Desactivar beta", + "DISABLE_FACE_SEARCH": "Desactivar búsqueda facial", + "DISABLE_FACE_SEARCH_TITLE": "Desactivar búsqueda facial?", + "DISABLE_FACE_SEARCH_DESCRIPTION": "

ente dejará de procesar la geometría facial, y también desactivará la búsqueda ML (beta)

Puede volver a activar la búsqueda facial si lo desea, ya que esta operación es segura.

", + "ADVANCED": "Avanzado", + "FACE_SEARCH_CONFIRMATION": "Comprendo y deseo permitir que ente procese la geometría de la cara", + "LABS": "Labs", + "YOURS": "tuyo", + "PASSPHRASE_STRENGTH_WEAK": "Fortaleza de la contraseña: débil", + "PASSPHRASE_STRENGTH_MODERATE": "Fortaleza de contraseña: Moderar", + "PASSPHRASE_STRENGTH_STRONG": "Fortaleza de contraseña: fuerte", + "PREFERENCES": "Preferencias", + "LANGUAGE": "Idioma", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Archivo de exportación inválido", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

El directorio de exportación seleccionado no existe.

Por favor, seleccione un directorio válido.

", + "SUBSCRIPTION_VERIFICATION_ERROR": "Falló la verificación de la suscripción", + "STORAGE_UNITS": { + "B": "B", + "KB": "KB", + "MB": "MB", + "GB": "GB", + "TB": "TB" + }, + "AFTER_TIME": { + "HOUR": "después de una hora", + "DAY": "después de un día", + "WEEK": "después de una semana", + "MONTH": "después de un mes", + "YEAR": "después de un año" + }, + "COPY_LINK": "Copiar enlace", + "DONE": "Hecho", + "LINK_SHARE_TITLE": "O comparte un enlace", + "REMOVE_LINK": "Eliminar enlace", + "CREATE_PUBLIC_SHARING": "Crear un enlace público", + "PUBLIC_LINK_CREATED": "Enlace público creado", + "PUBLIC_LINK_ENABLED": "Enlace público activado", + "COLLECT_PHOTOS": "Obtener fotos", + "PUBLIC_COLLECT_SUBTEXT": "Permitir a las personas con el enlace añadir fotos al álbum compartido.", + "STOP_EXPORT": "Stop", + "EXPORT_PROGRESS": "{{progress.success}} / {{progress.total}} archivos exportados", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "Exportar iniciando", + "IN_PROGRESS": "Exportación ya en curso", + "FINISH": "Exportación finalizada", + "UP_TO_DATE": "No hay nuevos archivos para exportar" + }, + "CONTINUOUS_EXPORT": "Sincronizar continuamente", + "TOTAL_ITEMS": "Total de elementos", + "PENDING_ITEMS": "Elementos pendientes", + "EXPORT_STARTING": "Exportar iniciando...", + "DELETE_ACCOUNT_REASON_LABEL": "¿Cuál es la razón principal por la que eliminas tu cuenta?", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Selecciona una razón", + "DELETE_REASON": { + "MISSING_FEATURE": "Falta una característica clave que necesito", + "BROKEN_BEHAVIOR": "La aplicación o una característica determinada no se comporta como creo que debería", + "FOUND_ANOTHER_SERVICE": "He encontrado otro servicio que me gusta más", + "NOT_LISTED": "Mi motivo no se encuentra en la lista" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "Lamentamos que te vayas. Explica por qué te vas para ayudarnos a mejorar.", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Sugerencias", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Sí, quiero eliminar permanentemente esta cuenta y todos sus datos", + "CONFIRM_DELETE_ACCOUNT": "Corfirmar borrado de cuenta", + "FEEDBACK_REQUIRED": "Ayúdanos con esta información", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "Qué hace mejor el otro servicio?", + "RECOVER_TWO_FACTOR": "Recuperar dos factores", + "at": "a las", + "AUTH_NEXT": "siguiente", + "AUTH_DOWNLOAD_MOBILE_APP": "Descarga nuestra aplicación móvil para administrar tus secretos", + "HIDDEN": "", + "HIDE": "Ocultar", + "UNHIDE": "Mostrar", + "UNHIDE_TO_COLLECTION": "Hacer visible al álbum", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "Video", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "Transformar", + "COLORS": "Colores", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/fa-IR/translation.json b/web/apps/cast/public/locales/fa-IR/translation.json new file mode 100644 index 0000000000..2d21fcb3d3 --- /dev/null +++ b/web/apps/cast/public/locales/fa-IR/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "به خوش آمدید", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/fi-FI/translation.json b/web/apps/cast/public/locales/fi-FI/translation.json new file mode 100644 index 0000000000..888ed7093e --- /dev/null +++ b/web/apps/cast/public/locales/fi-FI/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/fr-FR/translation.json b/web/apps/cast/public/locales/fr-FR/translation.json new file mode 100644 index 0000000000..43d9590691 --- /dev/null +++ b/web/apps/cast/public/locales/fr-FR/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Sauvegardes privées
pour vos souvenirs
", + "HERO_SLIDE_1": "Chiffrement de bout en bout par défaut", + "HERO_SLIDE_2_TITLE": "
Sécurisé
dans un abri antiatomique
", + "HERO_SLIDE_2": "Conçu pour survivre", + "HERO_SLIDE_3_TITLE": "
Disponible
en tout lieu
", + "HERO_SLIDE_3": "Android, iOS, Web, Ordinateur", + "LOGIN": "Connexion", + "SIGN_UP": "Inscription", + "NEW_USER": "Nouveau sur ente", + "EXISTING_USER": "Utilisateur existant", + "ENTER_NAME": "Saisir un nom", + "PUBLIC_UPLOADER_NAME_MESSAGE": "Ajouter un nom afin que vos amis sachent qui remercier pour ces magnifiques photos!", + "ENTER_EMAIL": "Saisir l'adresse e-mail", + "EMAIL_ERROR": "Saisir un e-mail valide", + "REQUIRED": "Nécessaire", + "EMAIL_SENT": "Code de vérification envoyé à
{{email}}", + "CHECK_INBOX": "Veuillez consulter votre boite de réception (et indésirables) pour poursuivre la vérification", + "ENTER_OTT": "Code de vérification", + "RESEND_MAIL": "Renvoyer le code", + "VERIFY": "Vérifier", + "UNKNOWN_ERROR": "Quelque chose s'est mal passé, veuillez recommencer", + "INVALID_CODE": "Code de vérification non valide", + "EXPIRED_CODE": "Votre code de vérification a expiré", + "SENDING": "Envoi...", + "SENT": "Envoyé!", + "PASSWORD": "Mot de passe", + "LINK_PASSWORD": "Saisir le mot de passe pour déverrouiller l'album", + "RETURN_PASSPHRASE_HINT": "Mot de passe", + "SET_PASSPHRASE": "Définir le mot de passe", + "VERIFY_PASSPHRASE": "Connexion", + "INCORRECT_PASSPHRASE": "Mot de passe non valide", + "ENTER_ENC_PASSPHRASE": "Veuillez saisir un mot de passe que nous pourrons utiliser pour chiffrer vos données", + "PASSPHRASE_DISCLAIMER": "Nous ne stockons pas votre mot de passe, donc si vous le perdez, nous ne pourrons pas vous aider à récupérer vos données sans une clé de récupération.", + "WELCOME_TO_ENTE_HEADING": "Bienvenue sur ", + "WELCOME_TO_ENTE_SUBHEADING": "Stockage et partage photo avec cryptage de bout en bout", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "Là où vivent vos meilleures photos", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Génération des clés de chiffrement...", + "PASSPHRASE_HINT": "Mot de passe", + "CONFIRM_PASSPHRASE": "Confirmer le mot de passe", + "REFERRAL_CODE_HINT": "Comment avez-vous entendu parler de Ente? (facultatif)", + "REFERRAL_INFO": "Nous ne suivons pas les installations d'applications. Il serait utile que vous nous disiez comment vous nous avez trouvés !", + "PASSPHRASE_MATCH_ERROR": "Les mots de passe ne correspondent pas", + "CREATE_COLLECTION": "Nouvel album", + "ENTER_ALBUM_NAME": "Nom de l'album", + "CLOSE_OPTION": "Fermer (Échap)", + "ENTER_FILE_NAME": "Nom du fichier", + "CLOSE": "Fermer", + "NO": "Non", + "NOTHING_HERE": "Il n'y a encore rien à voir ici 👀", + "UPLOAD": "Charger", + "IMPORT": "Importer", + "ADD_PHOTOS": "Ajouter des photos", + "ADD_MORE_PHOTOS": "Ajouter plus de photos", + "add_photos_one": "Ajouter une photo", + "add_photos_other": "Ajouter {{count}} photos", + "SELECT_PHOTOS": "Sélectionner des photos", + "FILE_UPLOAD": "Fichier chargé", + "UPLOAD_STAGE_MESSAGE": { + "0": "Préparation du chargement", + "1": "Lecture des fichiers de métadonnées de Google", + "2": "Métadonnées des fichiers {{uploadCounter.finished}} / {{uploadCounter.total}} extraites", + "3": "{{uploadCounter.finished}} / {{uploadCounter.total}} fichiers sauvegardés", + "4": "Annulation des chargements restants", + "5": "Sauvegarde terminée" + }, + "FILE_NOT_UPLOADED_LIST": "Les fichiers suivants n'ont pas été chargés", + "SUBSCRIPTION_EXPIRED": "Abonnement expiré", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Votre abonnement a expiré, veuillez le renouveler ", + "STORAGE_QUOTA_EXCEEDED": "Limite de stockage atteinte", + "INITIAL_LOAD_DELAY_WARNING": "La première consultation peut prendre du temps", + "USER_DOES_NOT_EXIST": "Désolé, impossible de trouver un utilisateur avec cet e-mail", + "NO_ACCOUNT": "Je n'ai pas de compte", + "ACCOUNT_EXISTS": "J'ai déjà un compte", + "CREATE": "Créer", + "DOWNLOAD": "Télécharger", + "DOWNLOAD_OPTION": "Télécharger (D)", + "DOWNLOAD_FAVORITES": "Télécharger les favoris", + "DOWNLOAD_UNCATEGORIZED": "Télécharger les hors catégories", + "DOWNLOAD_HIDDEN_ITEMS": "Télécharger les fichiers masqués", + "COPY_OPTION": "Copier en PNG (Ctrl/Cmd - C)", + "TOGGLE_FULLSCREEN": "Plein écran (F)", + "ZOOM_IN_OUT": "Zoom +/-", + "PREVIOUS": "Précédent (←)", + "NEXT": "Suivant (→)", + "TITLE_PHOTOS": "Ente Photos", + "TITLE_ALBUMS": "Ente Photos", + "TITLE_AUTH": "Ente Auth", + "UPLOAD_FIRST_PHOTO": "Chargez votre 1ere photo", + "IMPORT_YOUR_FOLDERS": "Importez vos dossiers", + "UPLOAD_DROPZONE_MESSAGE": "Déposez pour sauvegarder vos fichiers", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Déposez pour ajouter un dossier surveillé", + "TRASH_FILES_TITLE": "Supprimer les fichiers ?", + "TRASH_FILE_TITLE": "Supprimer le fichier ?", + "DELETE_FILES_TITLE": "Supprimer immédiatement?", + "DELETE_FILES_MESSAGE": "Les fichiers sélectionnés seront définitivement supprimés de votre compte ente.", + "DELETE": "Supprimer", + "DELETE_OPTION": "Supprimer (DEL)", + "FAVORITE_OPTION": "Favori (L)", + "UNFAVORITE_OPTION": "Non favori (L)", + "MULTI_FOLDER_UPLOAD": "Plusieurs dossiers détectés", + "UPLOAD_STRATEGY_CHOICE": "Voulez-vous les charger dans", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Un seul album", + "OR": "ou", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Albums séparés", + "SESSION_EXPIRED_MESSAGE": "Votre session a expiré, veuillez vous reconnecter pour poursuivre", + "SESSION_EXPIRED": "Session expiré", + "PASSWORD_GENERATION_FAILED": "Votre navigateur ne permet pas de générer une clé forte correspondant aux standards de chiffrement de ente, veuillez réessayer en utilisant l'appli mobile ou un autre navigateur", + "CHANGE_PASSWORD": "Modifier le mot de passe", + "GO_BACK": "Retour", + "RECOVERY_KEY": "Clé de récupération", + "SAVE_LATER": "Plus tard", + "SAVE": "Sauvegarder la clé", + "RECOVERY_KEY_DESCRIPTION": "Si vous oubliez votre mot de passe, la seule façon de récupérer vos données sera grâce à cette clé.", + "RECOVER_KEY_GENERATION_FAILED": "Le code de récupération ne peut être généré, veuillez réessayer", + "KEY_NOT_STORED_DISCLAIMER": "Nous ne stockons pas cette clé, veuillez donc la sauvegarder dans un endroit sûr", + "FORGOT_PASSWORD": "Mot de passe oublié", + "RECOVER_ACCOUNT": "Récupérer le compte", + "RECOVERY_KEY_HINT": "Clé de récupération", + "RECOVER": "Récupérer", + "NO_RECOVERY_KEY": "Pas de clé de récupération?", + "INCORRECT_RECOVERY_KEY": "Clé de récupération non valide", + "SORRY": "Désolé", + "NO_RECOVERY_KEY_MESSAGE": "En raison de notre protocole de chiffrement de bout en bout, vos données ne peuvent être décryptées sans votre mot de passe ou clé de récupération", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Veuillez envoyer un e-mail à {{emailID}} depuis votre adresse enregistrée", + "CONTACT_SUPPORT": "Contacter le support", + "REQUEST_FEATURE": "Soumettre une idée", + "SUPPORT": "Support", + "CONFIRM": "Confirmer", + "CANCEL": "Annuler", + "LOGOUT": "Déconnexion", + "DELETE_ACCOUNT": "Supprimer le compte", + "DELETE_ACCOUNT_MESSAGE": "

Veuillez envoyer un e-mail à {{emailID}}depuis Votre adresse enregistrée.

Votre demande sera traitée dans les 72 heures.

", + "LOGOUT_MESSAGE": "Voulez-vous vraiment vous déconnecter?", + "CHANGE_EMAIL": "Modifier l'e-mail", + "OK": "Ok", + "SUCCESS": "Parfait", + "ERROR": "Erreur", + "MESSAGE": "Message", + "INSTALL_MOBILE_APP": "Installez notre application Android or iOS pour sauvegarder automatiquement toutes vos photos", + "DOWNLOAD_APP_MESSAGE": "Désolé, cette opération est actuellement supportée uniquement sur notre appli pour ordinateur", + "DOWNLOAD_APP": "Télécharger l'appli pour ordinateur", + "EXPORT": "Exporter des données", + "SUBSCRIPTION": "Abonnement", + "SUBSCRIBE": "S'abonner", + "MANAGEMENT_PORTAL": "Gérer le mode de paiement", + "MANAGE_FAMILY_PORTAL": "Gérer la famille", + "LEAVE_FAMILY_PLAN": "Quitter le plan famille", + "LEAVE": "Quitter", + "LEAVE_FAMILY_CONFIRM": "Êtes-vous certains de vouloir quitter le plan famille?", + "CHOOSE_PLAN": "Choisir votre plan", + "MANAGE_PLAN": "Gérer votre abonnement", + "ACTIVE": "Actif", + "OFFLINE_MSG": "Vous êtes hors-ligne, les mémoires cache sont affichées", + "FREE_SUBSCRIPTION_INFO": "Vous êtes sur le plan gratuit qui expire le {{date, dateTime}}", + "FAMILY_SUBSCRIPTION_INFO": "Vous êtes sur le plan famille géré par", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Renouveler le {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Pris fin le {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Votre abonnement sera annulé le {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "Votre module {{storage, string}} est valable jusqu'au {{date, dateTime}}", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Vous avez dépassé votre quota de stockage, veuillez mettre à niveau ", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

Nous avons reçu votre paiement

Votre abonnement est valide jusqu'au {{date, dateTime}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "Votre achat est annulé, veuillez réessayer si vous souhaitez vous abonner", + "SUBSCRIPTION_PURCHASE_FAILED": "Échec lors de l'achat de l'abonnement, veuillez réessayer", + "SUBSCRIPTION_UPDATE_FAILED": "Échec lors de la mise à niveau de l'abonnement, veuillez réessayer", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Désolé, échec de paiement lors de la saisie de votre carte, veuillez mettr eà jour votre moyen de paiement et réessayer", + "STRIPE_AUTHENTICATION_FAILED": "Nous n'avons pas pu authentifier votre moyen de paiement. Veuillez choisir un moyen différent et réessayer", + "UPDATE_PAYMENT_METHOD": "Mise à jour du moyen de paiement", + "MONTHLY": "Mensuel", + "YEARLY": "Annuel", + "UPDATE_SUBSCRIPTION_MESSAGE": "Êtes-vous certains de vouloir changer de plan?", + "UPDATE_SUBSCRIPTION": "Changer de plan", + "CANCEL_SUBSCRIPTION": "Annuler l'abonnement", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Toutes vos données seront supprimées de nos serveurs à la fin de cette période d'abonnement.

Voulez-vous vraiment annuler votre abonnement?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "Êtes-vous sûr de vouloir annuler votre abonnement ", + "SUBSCRIPTION_CANCEL_FAILED": "Échec lors de l'annulation de l'abonnement", + "SUBSCRIPTION_CANCEL_SUCCESS": "Votre abonnement a bien été annulé", + "REACTIVATE_SUBSCRIPTION": "Réactiver l'abonnement", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Une fois réactivée, vous serrez facturé de {{val, datetime}}", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Votre abonnement est bien activé ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Échec lors de la réactivation de l'abonnement", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Merci", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Annuler l'abonnement mobile", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Veuillez annuler votre abonnement depuis l'appli mobile pour activer un abonnement ici", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Veuillez nous contacter à {{emailID}} pour gérer votre abonnement", + "RENAME": "Renommer", + "RENAME_FILE": "Renommer le fichier", + "RENAME_COLLECTION": "Renommer l'album", + "DELETE_COLLECTION_TITLE": "Supprimer l'album?", + "DELETE_COLLECTION": "Supprimer l'album", + "DELETE_COLLECTION_MESSAGE": "Supprimer aussi les photos (et vidéos) présentes dans cet album depuis tous les autres albums dont ils font partie?", + "DELETE_PHOTOS": "Supprimer des photos", + "KEEP_PHOTOS": "Conserver des photos", + "SHARE": "Partager", + "SHARE_COLLECTION": "Partager l'album", + "SHAREES": "Partager avec", + "SHARE_WITH_SELF": "Oups, vous ne pouvez pas partager avec vous-même", + "ALREADY_SHARED": "Oups, vous partager déjà cela avec {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Partage d'album non autorisé", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Le partage est désactivé pour les comptes gratuits", + "DOWNLOAD_COLLECTION": "Télécharger l'album", + "DOWNLOAD_COLLECTION_MESSAGE": "

Êtes-vous certains de vouloir télécharger l'album complet?

Tous les fichiers seront mis en file d'attente pour un téléchargement fractionné

", + "CREATE_ALBUM_FAILED": "Échec de création de l'album , veuillez réessayer", + "SEARCH": "Recherche", + "SEARCH_RESULTS": "Résultats de la recherche", + "NO_RESULTS": "Aucun résultat trouvé", + "SEARCH_HINT": "Recherche d'albums, dates, descriptions, ...", + "SEARCH_TYPE": { + "COLLECTION": "l'album", + "LOCATION": "Emplacement", + "CITY": "Adresse", + "DATE": "Date", + "FILE_NAME": "Nom de fichier", + "THING": "Chose", + "FILE_CAPTION": "Description", + "FILE_TYPE": "Type de fichier", + "CLIP": "Magique" + }, + "photos_count_zero": "Pas de souvenirs", + "photos_count_one": "1 souvenir", + "photos_count_other": "{{count}} souvenirs", + "TERMS_AND_CONDITIONS": "J'accepte les conditions et la politique de confidentialité", + "ADD_TO_COLLECTION": "Ajouter à l'album", + "SELECTED": "Sélectionné", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Cette vidéo ne peut pas être lue sur votre navigateur", + "PEOPLE": "Visages", + "INDEXING_SCHEDULED": "L'indexation est planifiée...", + "ANALYZING_PHOTOS": "analyse des nouvelles photos {{indexStatus.nSyncedFiles}} sur {{indexStatus.nTotalFiles}} effectué)...", + "INDEXING_PEOPLE": "indexation des visages dans {{indexStatus.nSyncedFiles}} photos...", + "INDEXING_DONE": "{{indexStatus.nSyncedFiles}} photos indexées", + "UNIDENTIFIED_FACES": "visages non-identifiés", + "OBJECTS": "objets", + "TEXT": "texte", + "INFO": "Info ", + "INFO_OPTION": "Info (I)", + "FILE_NAME": "Nom de fichier", + "CAPTION_PLACEHOLDER": "Ajouter une description", + "LOCATION": "Emplacement", + "SHOW_ON_MAP": "Visualiser sur OpenStreetMap", + "MAP": "Carte", + "MAP_SETTINGS": "Paramètres de la carte", + "ENABLE_MAPS": "Activer la carte?", + "ENABLE_MAP": "Activer la carte", + "DISABLE_MAPS": "Désactiver la carte?", + "ENABLE_MAP_DESCRIPTION": "

Cette fonction affiche vos photos sur une carte du monde.

La carte est hébergée par OpenStreetMap, et les emplacements exacts de vos photos ne sont jamais partagés.

Vous pouvez désactiver cette fonction à tout moment dans des paramètres.

", + "DISABLE_MAP_DESCRIPTION": "

Cette fonction désactive l'affichage de vos photos sur une carte du monde.

Vous pouvez activer cette fonction à tout moment dans les Paramètres.

", + "DISABLE_MAP": "Désactiver la carte", + "DETAILS": "Détails", + "VIEW_EXIF": "Visualiser toutes les données EXIF", + "NO_EXIF": "Aucune donnée EXIF", + "EXIF": "EXIF", + "ISO": "ISO", + "TWO_FACTOR": "Double authentification", + "TWO_FACTOR_AUTHENTICATION": "Authentification double-facteur", + "TWO_FACTOR_QR_INSTRUCTION": "Scannez le QRCode ci-dessous avec une appli d'authentification", + "ENTER_CODE_MANUALLY": "Saisir le code manuellement", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Veuillez saisir ce code dans votre appli d'authentification", + "SCAN_QR_CODE": "Scannez le QRCode de préférence", + "ENABLE_TWO_FACTOR": "Activer la double-authentification", + "ENABLE": "Activer", + "LOST_DEVICE": "Perte de l'appareil identificateur", + "INCORRECT_CODE": "Code non valide", + "TWO_FACTOR_INFO": "Rajoutez une couche de sécurité supplémentaire afin de pas utiliser simplement votre e-mail et mot de passe pour vous connecter à votre compte", + "DISABLE_TWO_FACTOR_LABEL": "Désactiver la double-authentification", + "UPDATE_TWO_FACTOR_LABEL": "Mise à jour de votre appareil identificateur", + "DISABLE": "Désactiver", + "RECONFIGURE": "Reconfigurer", + "UPDATE_TWO_FACTOR": "Mise à jour de la double-authentification", + "UPDATE_TWO_FACTOR_MESSAGE": "Continuer annulera tous les identificateurs précédemment configurés", + "UPDATE": "Mise à jour", + "DISABLE_TWO_FACTOR": "Désactiver la double-authentification", + "DISABLE_TWO_FACTOR_MESSAGE": "Êtes-vous certains de vouloir désactiver la double-authentification", + "TWO_FACTOR_DISABLE_FAILED": "Échec de désactivation de la double-authentification, veuillez réessayer", + "EXPORT_DATA": "Exporter les données", + "SELECT_FOLDER": "Sélectionner un dossier", + "DESTINATION": "Destination", + "START": "Démarrer", + "LAST_EXPORT_TIME": "Horaire du dernier export", + "EXPORT_AGAIN": "Resynchro", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Stockage local non accessible", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Votre navigateur ou un complément bloque ente qui ne peut sauvegarder les données sur votre stockage local. Veuillez relancer cette page après avoir changé de mode de navigation.", + "SEND_OTT": "Envoyer l'OTP", + "EMAIl_ALREADY_OWNED": "Cet e-mail est déjà pris", + "ETAGS_BLOCKED": "

Nosu n'avons pas pu charger les fichiers suivants à cause de la configuration de votre navigateur.

Veuillez désactiver tous les compléments qui pourraient empêcher ente d'utiliser les eTags pour charger de larges fichiers, ou bien utilisez notre appli pour ordinateurpour une meilleure expérience lors des chargements.

", + "SKIPPED_VIDEOS_INFO": "

Actuellement, nous ne supportons pas l'ajout de videos via des liens publics.

Pour partager des vidéos, veuillez vous connecter àente et partager en utilisant l'e-mail concerné.

", + "LIVE_PHOTOS_DETECTED": "Les fichiers photos et vidéos depuis votre espace Live Photos ont été fusionnés en un seul fichier", + "RETRY_FAILED": "Réessayer les chargements ayant échoués", + "FAILED_UPLOADS": "Chargements échoués ", + "SKIPPED_FILES": "Chargements ignorés", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Échec de création d'une miniature", + "UNSUPPORTED_FILES": "Fichiers non supportés", + "SUCCESSFUL_UPLOADS": "Chargements réussis", + "SKIPPED_INFO": "Ignorés car il y a des fichiers avec des noms identiques dans le même album", + "UNSUPPORTED_INFO": "ente ne supporte pas encore ces formats de fichiers", + "BLOCKED_UPLOADS": "Chargements bloqués", + "SKIPPED_VIDEOS": "Vidéos ignorées", + "INPROGRESS_METADATA_EXTRACTION": "En cours", + "INPROGRESS_UPLOADS": "Chargements en cours", + "TOO_LARGE_UPLOADS": "Gros fichiers", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Stockage insuffisant", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Ces fichiers n'ont pas été chargés car ils dépassent la taille maximale de votre plan de stockage", + "TOO_LARGE_INFO": "Ces fichiers n'ont pas été chargés car ils dépassent notre taille limite par fichier", + "THUMBNAIL_GENERATION_FAILED_INFO": "Ces fichiers sont bien chargés, mais nous ne pouvons pas créer de miniatures pour eux.", + "UPLOAD_TO_COLLECTION": "Charger dans l'album", + "UNCATEGORIZED": "Aucune catégorie", + "ARCHIVE": "Archiver", + "FAVORITES": "Favoris", + "ARCHIVE_COLLECTION": "Archiver l'album", + "ARCHIVE_SECTION_NAME": "Archivé", + "ALL_SECTION_NAME": "Tous", + "MOVE_TO_COLLECTION": "Déplacer vers l'album", + "UNARCHIVE": "Désarchiver", + "UNARCHIVE_COLLECTION": "Désarchiver l'album", + "HIDE_COLLECTION": "Masquer l'album", + "UNHIDE_COLLECTION": "Dévoiler l'album", + "MOVE": "Déplacer", + "ADD": "Ajouter", + "REMOVE": "Retirer", + "YES_REMOVE": "Oui, retirer", + "REMOVE_FROM_COLLECTION": "Retirer de l'album", + "TRASH": "Corbeille", + "MOVE_TO_TRASH": "Déplacer vers la corbeille", + "TRASH_FILES_MESSAGE": "Les fichiers sélectionnés seront retirés de tous les albums puis déplacés dans la corbeille.", + "TRASH_FILE_MESSAGE": "Le fichier sera retiré de tous les albums puis déplacé dans la corbeille.", + "DELETE_PERMANENTLY": "Supprimer définitivement", + "RESTORE": "Restaurer", + "RESTORE_TO_COLLECTION": "Restaurer vers l'album", + "EMPTY_TRASH": "Corbeille vide", + "EMPTY_TRASH_TITLE": "Vider la corbeille ?", + "EMPTY_TRASH_MESSAGE": "Ces fichiers seront définitivement supprimés de votre compte ente.", + "LEAVE_SHARED_ALBUM": "Oui, quitter", + "LEAVE_ALBUM": "Quitter l'album", + "LEAVE_SHARED_ALBUM_TITLE": "Quitter l'album partagé?", + "LEAVE_SHARED_ALBUM_MESSAGE": "Vous allez quitter cet album, il ne sera plus visible pour vous.", + "NOT_FILE_OWNER": "Vous ne pouvez pas supprimer les fichiers d'un album partagé", + "CONFIRM_SELF_REMOVE_MESSAGE": "Choisir les objets qui seront retirés de cet album. Ceux qui sont présents uniquement dans cet album seront déplacés comme hors catégorie.", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Certains des objets que vous êtes en train de retirer ont été ajoutés par d'autres personnes, vous perdrez l'accès vers ces objets.", + "SORT_BY_CREATION_TIME_ASCENDING": "Plus anciens", + "SORT_BY_UPDATION_TIME_DESCENDING": "Dernière mise à jour", + "SORT_BY_NAME": "Nom", + "COMPRESS_THUMBNAILS": "Compresser les miniatures", + "THUMBNAIL_REPLACED": "Les miniatures sont compressées", + "FIX_THUMBNAIL": "Compresser", + "FIX_THUMBNAIL_LATER": "Compresser plus tard", + "REPLACE_THUMBNAIL_NOT_STARTED": "Certaines miniatures de vidéos peuvent être compressées pour gagner de la place. Voulez-vous que ente les compresse?", + "REPLACE_THUMBNAIL_COMPLETED": "Toutes les miniatures ont été compressées", + "REPLACE_THUMBNAIL_NOOP": "Vous n'avez aucune miniature qui peut être encore plus compressée", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Impossible de compresser certaines miniatures, veuillez réessayer", + "FIX_CREATION_TIME": "Réajuster l'heure", + "FIX_CREATION_TIME_IN_PROGRESS": "Réajustement de l'heure", + "CREATION_TIME_UPDATED": "L'heure du fichier a été réajustée", + "UPDATE_CREATION_TIME_NOT_STARTED": "Sélectionnez l'option que vous souhaitez utiliser", + "UPDATE_CREATION_TIME_COMPLETED": "Mise à jour effectuée pour tous les fichiers", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "L'heure du fichier n'a pas été mise à jour pour certains fichiers, veuillez réessayer", + "CAPTION_CHARACTER_LIMIT": "5000 caractères max", + "DATE_TIME_ORIGINAL": "EXIF:DateTimeOriginal", + "DATE_TIME_DIGITIZED": "EXIF:DateTimeDigitized", + "METADATA_DATE": "EXIF:MetadataDate", + "CUSTOM_TIME": "Heure personnalisée", + "REOPEN_PLAN_SELECTOR_MODAL": "Rouvrir les plans", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Échec pour rouvrir les plans", + "INSTALL": "Installer", + "SHARING_DETAILS": "Détails du partage", + "MODIFY_SHARING": "Modifier le partage", + "ADD_COLLABORATORS": "Ajouter des collaborateurs", + "ADD_NEW_EMAIL": "Ajouter un nouvel email", + "shared_with_people_zero": "Partager avec des personnes spécifiques", + "shared_with_people_one": "Partagé avec 1 personne", + "shared_with_people_other": "Partagé avec {{count, number}} personnes", + "participants_zero": "Aucun participant", + "participants_one": "1 participant", + "participants_other": "{{count, number}} participants", + "ADD_VIEWERS": "Ajouter un observateur", + "PARTICIPANTS": "Participants", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} ne pourra plus ajouter de photos à l'album

Il pourra toujours supprimer les photos qu'il a ajoutées

", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} pourra ajouter des photos à l'album", + "CONVERT_TO_VIEWER": "Oui, convertir en observateur", + "CONVERT_TO_COLLABORATOR": "Oui, convertir en collaborateur", + "CHANGE_PERMISSION": "Modifier la permission?", + "REMOVE_PARTICIPANT": "Retirer?", + "CONFIRM_REMOVE": "Oui, supprimer", + "MANAGE": "Gérer", + "ADDED_AS": "Ajouté comme", + "COLLABORATOR_RIGHTS": "Les collaborateurs peuvent ajouter des photos et des vidéos à l'album partagé", + "REMOVE_PARTICIPANT_HEAD": "Supprimer le participant", + "OWNER": "Propriétaire", + "COLLABORATORS": "Collaborateurs", + "ADD_MORE": "Ajouter plus", + "VIEWERS": "Visionneurs", + "OR_ADD_EXISTING": "ou sélectionner un fichier existant", + "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} sera supprimé de l'album

Toutes les photos ajoutées par cette personne seront également supprimées de l'album

", + "NOT_FOUND": "404 - non trouvé", + "LINK_EXPIRED": "Lien expiré", + "LINK_EXPIRED_MESSAGE": "Ce lien à soit expiré soit est supprimé!", + "MANAGE_LINK": "Gérer le lien", + "LINK_TOO_MANY_REQUESTS": "Désolé, cet album a été consulté sur trop d'appareils !", + "FILE_DOWNLOAD": "Autoriser les téléchargements", + "LINK_PASSWORD_LOCK": "Verrou par mot de passe", + "PUBLIC_COLLECT": "Autoriser l'ajout de photos", + "LINK_DEVICE_LIMIT": "Limite d'appareil", + "NO_DEVICE_LIMIT": "Aucune", + "LINK_EXPIRY": "Expiration du lien", + "NEVER": "Jamais", + "DISABLE_FILE_DOWNLOAD": "Désactiver le téléchargement", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Êtes-vous certains de vouloir désactiver le bouton de téléchargement pour les fichiers?

Ceux qui les visualisent pourront tout de même faire des captures d'écrans ou sauvegarder une copie de vos photos en utilisant des outils externes.

", + "MALICIOUS_CONTENT": "Contient du contenu malveillant", + "COPYRIGHT": "Enfreint les droits d'une personne que je réprésente", + "SHARED_USING": "Partagé en utilisant ", + "ENTE_IO": "ente.io", + "SHARING_REFERRAL_CODE": "Utilisez le code {{referralCode}} pour obtenir 10 Go gratuits", + "LIVE": "LIVE", + "DISABLE_PASSWORD": "Désactiver le verrouillage par mot de passe", + "DISABLE_PASSWORD_MESSAGE": "Êtes-vous certains de vouloir désactiver le verrouillage par mot de passe ?", + "PASSWORD_LOCK": "Mot de passe verrou", + "LOCK": "Verrouiller", + "DOWNLOAD_UPLOAD_LOGS": "Journaux de débugs", + "UPLOAD_FILES": "Fichier", + "UPLOAD_DIRS": "Dossier", + "UPLOAD_GOOGLE_TAKEOUT": "Google Takeout", + "DEDUPLICATE_FILES": "Déduplication de fichiers", + "AUTHENTICATOR_SECTION": "Authentificateur", + "NO_DUPLICATES_FOUND": "Vous n'avez aucun fichier dédupliqué pouvant être nettoyé", + "CLUB_BY_CAPTURE_TIME": "Durée de la capture par club", + "FILES": "Fichiers", + "EACH": "Chacun", + "DEDUPLICATE_BASED_ON_SIZE": "Les fichiers suivants ont été clubbed, basé sur leurs tailles, veuillez corriger et supprimer les objets que vous pensez être dupliqués", + "STOP_ALL_UPLOADS_MESSAGE": "Êtes-vous certains de vouloir arrêter tous les chargements en cours?", + "STOP_UPLOADS_HEADER": "Arrêter les chargements ?", + "YES_STOP_UPLOADS": "Oui, arrêter tout", + "STOP_DOWNLOADS_HEADER": "Arrêter le téléchargement ?", + "YES_STOP_DOWNLOADS": "Oui, arrêter les téléchargements", + "STOP_ALL_DOWNLOADS_MESSAGE": "Êtes-vous certains de vouloir arrêter tous les chargements en cours?", + "albums_one": "1 album", + "albums_other": "{{count}} albums", + "ALL_ALBUMS": "Tous les albums", + "ALBUMS": "Albums", + "ALL_HIDDEN_ALBUMS": "Tous les albums masqués", + "HIDDEN_ALBUMS": "Albums masqués", + "HIDDEN_ITEMS": "Éléments masqués", + "HIDDEN_ITEMS_SECTION_NAME": "Éléments masqués", + "ENTER_TWO_FACTOR_OTP": "Saisir le code à 6 caractères de votre appli d'authentification.", + "CREATE_ACCOUNT": "Créer un compte", + "COPIED": "Copié", + "CANVAS_BLOCKED_TITLE": "Impossible de créer une miniature", + "CANVAS_BLOCKED_MESSAGE": "

Il semblerait que votre navigateur ait désactivé l'accès au canevas, qui est nécessaire pour créer les miniatures de vos photos

Veuillez activer l'accès au canevas du navigateur, ou consulter notre appli pour ordinateur

", + "WATCH_FOLDERS": "Voir les dossiers", + "UPGRADE_NOW": "Mettre à niveau maintenant", + "RENEW_NOW": "Renouveler maintenant", + "STORAGE": "Stockage", + "USED": "utilisé", + "YOU": "Vous", + "FAMILY": "Famille", + "FREE": "gratuit", + "OF": "de", + "WATCHED_FOLDERS": "Voir les dossiers", + "NO_FOLDERS_ADDED": "Aucun dossiers d'ajouté!", + "FOLDERS_AUTOMATICALLY_MONITORED": "Les dossiers que vous ajoutez ici seront supervisés automatiquement", + "UPLOAD_NEW_FILES_TO_ENTE": "Charger de nouveaux fichiers sur ente", + "REMOVE_DELETED_FILES_FROM_ENTE": "Retirer de ente les fichiers supprimés", + "ADD_FOLDER": "Ajouter un dossier", + "STOP_WATCHING": "Arrêter de voir", + "STOP_WATCHING_FOLDER": "Arrêter de voir le dossier?", + "STOP_WATCHING_DIALOG_MESSAGE": "Vos fichiers existants ne seront pas supprimés, mais ente arrêtera automatiquement de mettre à jour le lien de l'album à chaque changements sur ce dossier.", + "YES_STOP": "Oui, arrêter", + "MONTH_SHORT": "mo", + "YEAR": "année", + "FAMILY_PLAN": "Plan famille", + "DOWNLOAD_LOGS": "Télécharger les logs", + "DOWNLOAD_LOGS_MESSAGE": "

Cela va télécharger les journaux de débug, que vous pourrez nosu envoyer par e-mail pour nous aider à résoudre votre problàme .

Veuillez noter que les noms de fichiers seront inclus .

", + "CHANGE_FOLDER": "Modifier le dossier", + "TWO_MONTHS_FREE": "Obtenir 2 mois gratuits sur les plans annuels", + "GB": "Go", + "POPULAR": "Populaire", + "FREE_PLAN_OPTION_LABEL": "Poursuivre avec la version d'essai gratuite", + "FREE_PLAN_DESCRIPTION": "1 Go pour 1 an", + "CURRENT_USAGE": "L'utilisation actuelle est de {{usage}}", + "WEAK_DEVICE": "Le navigateur que vous utilisez n'est pas assez puissant pour chiffrer vos photos. Veuillez essayer de vous connecter à ente sur votre ordinateur, ou télécharger l'appli ente mobile/ordinateur.", + "DRAG_AND_DROP_HINT": "Sinon glissez déposez dans la fenêtre ente", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "

Vos données chargées seront programmées pour suppression, et votre comptre sera supprimé définitivement .

Cette action n'est pas reversible.

", + "AUTHENTICATE": "Authentification", + "UPLOADED_TO_SINGLE_COLLECTION": "Chargé dans une seule collection", + "UPLOADED_TO_SEPARATE_COLLECTIONS": "Chargé dans des collections séparées", + "NEVERMIND": "Peu-importe", + "UPDATE_AVAILABLE": "Une mise à jour est disponible", + "UPDATE_INSTALLABLE_MESSAGE": "Une nouvelle version de ente est prête à être installée.", + "INSTALL_NOW": "Installer maintenant", + "INSTALL_ON_NEXT_LAUNCH": "Installer au prochain démarrage", + "UPDATE_AVAILABLE_MESSAGE": "Une nouvelle version de ente est sortie, mais elle ne peut pas être automatiquement téléchargée puis installée.", + "DOWNLOAD_AND_INSTALL": "Télécharger et installer", + "IGNORE_THIS_VERSION": "Ignorer cette version", + "TODAY": "Aujourd'hui", + "YESTERDAY": "Hier", + "NAME_PLACEHOLDER": "Nom...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Impossible de créer des albums depuis un mix fichier/dossier", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

Vous avez glissé déposé un mélange de fichiers et dossiers.

Veuillez sélectionner soit uniquement des fichiers, ou des dossiers lors du choix d'options pour créer des albums séparés

", + "CHOSE_THEME": "Choisir un thème", + "ML_SEARCH": "ML search (beta)", + "ENABLE_ML_SEARCH_DESCRIPTION": "

Ceci activera l'apprentissage automatique sur l'appareil et la recherche faciale qui commencera à analyser vos photos chargées.

Pour la première exécution après la connexion ou l'activation de cette fonctionnalité, cela téléchargera toutes les images sur l'appareil local pour les analyser. Veuillez donc activer ceci uniquement si vous avez de la bande passante et le traitement local de toutes les images dans votre photothèque.

Si c'est la première fois que vous activez ceci, nous vous demanderons également la permission de traiter les données faciales.

", + "ML_MORE_DETAILS": "Plus de détails", + "ENABLE_FACE_SEARCH": "Activer la recherche faciale", + "ENABLE_FACE_SEARCH_TITLE": "Activer la recherche faciale ?", + "ENABLE_FACE_SEARCH_DESCRIPTION": "

If you enable face search, ente will extract face geometry from your photos. This will happen on your device, and any generated biometric data will be end-to-encrypted.

Please click here for more details about this feature in our privacy policy

", + "DISABLE_BETA": "Désactiver la bêta", + "DISABLE_FACE_SEARCH": "Désactiver la recherche faciale", + "DISABLE_FACE_SEARCH_TITLE": "Désactiver la recherche faciale ?", + "DISABLE_FACE_SEARCH_DESCRIPTION": "

ente will stop processing face geometry, and will also disable ML search (beta)

You can reenable face search again if you wish, so this operation is safe

", + "ADVANCED": "Avancé", + "FACE_SEARCH_CONFIRMATION": "Je comprends, et je souhaite permettre à ente de traiter la géométrie faciale", + "LABS": "Labs", + "YOURS": "Le vôtre", + "PASSPHRASE_STRENGTH_WEAK": "Sécurité du mot de passe : faible", + "PASSPHRASE_STRENGTH_MODERATE": "Sécurité du mot de passe : moyenne", + "PASSPHRASE_STRENGTH_STRONG": "Sécurité du mot de passe : forte", + "PREFERENCES": "Préférences", + "LANGUAGE": "Langue", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Dossier d'export invalide", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

Le dossier d'export que vous avez sélectionné n'existe pas

Veuillez sélectionner un dossier valide

", + "SUBSCRIPTION_VERIFICATION_ERROR": "Échec de la vérification de l'abonnement", + "STORAGE_UNITS": { + "B": "o", + "KB": "Ko", + "MB": "Mo", + "GB": "Go", + "TB": "To" + }, + "AFTER_TIME": { + "HOUR": "dans une heure", + "DAY": "dans un jour", + "WEEK": "dans une semaine", + "MONTH": "dans un mois", + "YEAR": "dans un an" + }, + "COPY_LINK": "Copier le lien", + "DONE": "Terminé", + "LINK_SHARE_TITLE": "Ou partager un lien", + "REMOVE_LINK": "Supprimer le lien", + "CREATE_PUBLIC_SHARING": "Créer un lien public", + "PUBLIC_LINK_CREATED": "Lien public créé", + "PUBLIC_LINK_ENABLED": "Lien public activé", + "COLLECT_PHOTOS": "Récupérer les photos", + "PUBLIC_COLLECT_SUBTEXT": "Autoriser les personnes ayant le lien d'ajouter des photos à l'album partagé.", + "STOP_EXPORT": "Stop", + "EXPORT_PROGRESS": "{{progress.success}} / {{progress.total}} fichiers exportés", + "MIGRATING_EXPORT": "Préparations...", + "RENAMING_COLLECTION_FOLDERS": "Renommage des dossiers de l'album en cours...", + "TRASHING_DELETED_FILES": "Mise à la corbeille des fichiers supprimés...", + "TRASHING_DELETED_COLLECTIONS": "Mise à la corbeille des albums supprimés...", + "EXPORT_NOTIFICATION": { + "START": "L'export a démarré", + "IN_PROGRESS": "Un export est déjà en cours", + "FINISH": "Export terminé", + "UP_TO_DATE": "Aucun nouveau fichier à exporter" + }, + "CONTINUOUS_EXPORT": "Synchronisation en continu", + "TOTAL_ITEMS": "Total d'objets", + "PENDING_ITEMS": "Objets en attente", + "EXPORT_STARTING": "Démarrage de l'export...", + "DELETE_ACCOUNT_REASON_LABEL": "Quelle est la raison principale de la suppression de votre compte ?", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Choisir une raison", + "DELETE_REASON": { + "MISSING_FEATURE": "Il manque une fonctionnalité essentielle dont j'ai besoin", + "BROKEN_BEHAVIOR": "L'application ou une certaine fonctionnalité ne se comporte pas comme je pense qu'elle devrait", + "FOUND_ANOTHER_SERVICE": "J'ai trouvé un autre service que je préfère", + "NOT_LISTED": "Ma raison n'est pas listée" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "Nous sommes désolés de vous voir partir. Expliquez-nous les raisons de votre départ pour que nous puissions nous améliorer.", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Vos commentaires", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Oui, je veux supprimer définitivement ce compte et toutes ses données", + "CONFIRM_DELETE_ACCOUNT": "Confirmer la suppression du compte", + "FEEDBACK_REQUIRED": "Merci de nous aider avec cette information", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "Qu'est-ce que l'autre service fait de mieux ?", + "RECOVER_TWO_FACTOR": "Récupérer la double-authentification", + "at": "à", + "AUTH_NEXT": "suivant", + "AUTH_DOWNLOAD_MOBILE_APP": "Téléchargez notre application mobile pour gérer vos secrets", + "HIDDEN": "Masqué", + "HIDE": "Masquer", + "UNHIDE": "Dévoiler", + "UNHIDE_TO_COLLECTION": "Afficher dans l'album", + "SORT_BY": "Trier par", + "NEWEST_FIRST": "Plus récent en premier", + "OLDEST_FIRST": "Plus ancien en premier", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "Ce fichier n'a pas pu être aperçu. Cliquez ici pour télécharger l'original.", + "SELECT_COLLECTION": "Sélectionner album", + "PIN_ALBUM": "Épingler l'album", + "UNPIN_ALBUM": "Désépingler l'album", + "DOWNLOAD_COMPLETE": "Téléchargement terminé", + "DOWNLOADING_COLLECTION": "Téléchargement de {{name}}", + "DOWNLOAD_FAILED": "Échec du téléchargement", + "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} fichiers", + "CHRISTMAS": "Noël", + "CHRISTMAS_EVE": "Réveillon de Noël", + "NEW_YEAR": "Nouvel an", + "NEW_YEAR_EVE": "Réveillon de Nouvel An", + "IMAGE": "Image", + "VIDEO": "Vidéo", + "LIVE_PHOTO": "Photos en direct", + "CONVERT": "Convertir", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "Êtes-vous sûr de vouloir fermer l'éditeur ?", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Téléchargez votre image modifiée ou enregistrez une copie sur ente pour maintenir vos modifications.", + "BRIGHTNESS": "Luminosité", + "CONTRAST": "Contraste", + "SATURATION": "Saturation", + "BLUR": "Flou", + "INVERT_COLORS": "Inverser les couleurs", + "ASPECT_RATIO": "Ratio de l'image", + "SQUARE": "Carré", + "ROTATE_LEFT": "Pivoter vers la gauche", + "ROTATE_RIGHT": "Pivoter vers la droite", + "FLIP_VERTICALLY": "Basculer verticalement", + "FLIP_HORIZONTALLY": "Retourner horizontalement", + "DOWNLOAD_EDITED": "Téléchargement modifié", + "SAVE_A_COPY_TO_ENTE": "Enregistrer une copie dans ente", + "RESTORE_ORIGINAL": "Restaurer l'original", + "TRANSFORM": "Transformer", + "COLORS": "Couleurs", + "FLIP": "Retourner", + "ROTATION": "Rotation", + "RESET": "Réinitialiser", + "PHOTO_EDITOR": "Éditeur de photos", + "FASTER_UPLOAD": "Chargements plus rapides", + "FASTER_UPLOAD_DESCRIPTION": "Router les chargements vers les serveurs à proximité", + "MAGIC_SEARCH_STATUS": "Statut de la recherche magique", + "INDEXED_ITEMS": "Éléments indexés", + "CAST_ALBUM_TO_TV": "Jouer l'album sur la TV", + "ENTER_CAST_PIN_CODE": "Entrez le code que vous voyez sur la TV ci-dessous pour appairer cet appareil.", + "PAIR_DEVICE_TO_TV": "Associer les appareils", + "TV_NOT_FOUND": "TV introuvable. Avez-vous entré le code PIN correctement ?", + "AUTO_CAST_PAIR": "Paire automatique", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "La paire automatique nécessite la connexion aux serveurs Google et ne fonctionne qu'avec les appareils pris en charge par Chromecast. Google ne recevra pas de données sensibles, telles que vos photos.", + "PAIR_WITH_PIN": "Associer avec le code PIN", + "CHOOSE_DEVICE_FROM_BROWSER": "Choisissez un périphérique compatible avec la caste à partir de la fenêtre pop-up du navigateur.", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "L'association avec le code PIN fonctionne pour tout appareil grand écran sur lequel vous voulez lire votre album.", + "VISIT_CAST_ENTE_IO": "Visitez cast.ente.io sur l'appareil que vous voulez associer.", + "CAST_AUTO_PAIR_FAILED": "La paire automatique de Chromecast a échoué. Veuillez réessayer.", + "CACHE_DIRECTORY": "Dossier du cache", + "FREEHAND": "Main levée", + "APPLY_CROP": "Appliquer le recadrage", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Au moins une transformation ou un ajustement de couleur doit être effectué avant de sauvegarder.", + "PASSKEYS": "Clés d'accès", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/it-IT/translation.json b/web/apps/cast/public/locales/it-IT/translation.json new file mode 100644 index 0000000000..ae450e5fef --- /dev/null +++ b/web/apps/cast/public/locales/it-IT/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Backup privati
dei tuoi ricordi
", + "HERO_SLIDE_1": "Crittografia end-to-end", + "HERO_SLIDE_2_TITLE": "
Salvati in modo sicuro
in un rifugio antiatomico
", + "HERO_SLIDE_2": "Progettato per sopravvivere", + "HERO_SLIDE_3_TITLE": "
Disponibile
ovunque
", + "HERO_SLIDE_3": "Android, iOS, Web, Desktop", + "LOGIN": "Accedi", + "SIGN_UP": "Registrati", + "NEW_USER": "Nuovo utente", + "EXISTING_USER": "Accedi", + "ENTER_NAME": "Inserisci il nome", + "PUBLIC_UPLOADER_NAME_MESSAGE": "Aggiungi un nome in modo che i tuoi amici sappiano chi ringraziare per queste fantastiche foto!", + "ENTER_EMAIL": "Inserisci l'indirizzo email", + "EMAIL_ERROR": "Inserisci un indirizzo email valido", + "REQUIRED": "Campo obbligatorio", + "EMAIL_SENT": "Codice di verifica inviato a {{email}}", + "CHECK_INBOX": "Controlla la tua casella di posta (e lo spam) per completare la verifica", + "ENTER_OTT": "Codice di verifica", + "RESEND_MAIL": "Reinvia codice", + "VERIFY": "Verifica", + "UNKNOWN_ERROR": "Qualcosa è andato storto, per favore riprova", + "INVALID_CODE": "Codice di verifica non valido", + "EXPIRED_CODE": "Il tuo codice di verifica è scaduto", + "SENDING": "Invio in corso...", + "SENT": "Inviato!", + "PASSWORD": "Password", + "LINK_PASSWORD": "Inserisci la password per sbloccare l'album", + "RETURN_PASSPHRASE_HINT": "Password", + "SET_PASSPHRASE": "Imposta una password", + "VERIFY_PASSPHRASE": "Accedi", + "INCORRECT_PASSPHRASE": "Password sbagliata", + "ENTER_ENC_PASSPHRASE": "Inserisci una password per crittografare i tuoi dati", + "PASSPHRASE_DISCLAIMER": "Non memorizziamo la tua password, quindi se la dimentichi, non saremo in grado di aiutarti a recuperare i tuoi dati senza una chiave di recupero.", + "WELCOME_TO_ENTE_HEADING": "Benvenuto su ", + "WELCOME_TO_ENTE_SUBHEADING": "Archiviazione e condivisione di foto crittografate end-to-end", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "Dove vivono le tue migliori foto", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Generazione delle chiavi di crittografia...", + "PASSPHRASE_HINT": "Password", + "CONFIRM_PASSPHRASE": "Conferma la password", + "REFERRAL_CODE_HINT": "Come hai conosciuto Ente? (opzionale)", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "Le password non corrispondono", + "CREATE_COLLECTION": "Nuovo album", + "ENTER_ALBUM_NAME": "Nome album", + "CLOSE_OPTION": "Chiudi (Esc)", + "ENTER_FILE_NAME": "Nome del file", + "CLOSE": "Chiudi", + "NO": "No", + "NOTHING_HERE": "Nulla da vedere qui! 👀", + "UPLOAD": "Carica", + "IMPORT": "Importa", + "ADD_PHOTOS": "Aggiungi foto", + "ADD_MORE_PHOTOS": "Aggiungi altre foto", + "add_photos_one": "Aggiungi elemento", + "add_photos_other": "Aggiungi {{count, number}} elementi", + "SELECT_PHOTOS": "Seleziona foto", + "FILE_UPLOAD": "Carica file", + "UPLOAD_STAGE_MESSAGE": { + "0": "Preparazione all'upload", + "1": "Lettura dei file metadati di google", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} file metadati estratti", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} file salvati", + "4": "Annullamento dei caricamenti rimanenti", + "5": "Backup completato" + }, + "FILE_NOT_UPLOADED_LIST": "I seguenti file non sono stati caricati", + "SUBSCRIPTION_EXPIRED": "Abbonamento scaduto", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Il tuo abbonamento è scaduto, per favore rinnova", + "STORAGE_QUOTA_EXCEEDED": "Limite d'archiviazione superato", + "INITIAL_LOAD_DELAY_WARNING": "Il primo caricamento potrebbe richiedere del tempo", + "USER_DOES_NOT_EXIST": "Purtroppo non abbiamo trovato nessun account con quell'indirizzo e-mail", + "NO_ACCOUNT": "Non ho un account", + "ACCOUNT_EXISTS": "Ho già un account", + "CREATE": "Crea", + "DOWNLOAD": "Scarica", + "DOWNLOAD_OPTION": "Scarica (D)", + "DOWNLOAD_FAVORITES": "Scarica i preferiti", + "DOWNLOAD_UNCATEGORIZED": "Scarica i file senza categoria", + "DOWNLOAD_HIDDEN_ITEMS": "Scarica gli elementi nascosti", + "COPY_OPTION": "Copia come PNG (Ctrl/Cmd - C)", + "TOGGLE_FULLSCREEN": "Attiva/disattiva schermo intero (F)", + "ZOOM_IN_OUT": "Zoom in/out", + "PREVIOUS": "Precedente (←)", + "NEXT": "Successivo (→)", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "Carica la tua prima foto", + "IMPORT_YOUR_FOLDERS": "Importa una cartella", + "UPLOAD_DROPZONE_MESSAGE": "Rilascia per eseguire il backup dei file", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Rilascia per aggiungere la cartella osservata", + "TRASH_FILES_TITLE": "Elimina file?", + "TRASH_FILE_TITLE": "Eliminare il file?", + "DELETE_FILES_TITLE": "Eliminare immediatamente?", + "DELETE_FILES_MESSAGE": "I file selezionati verranno eliminati definitivamente dal tuo account ente.", + "DELETE": "Cancella", + "DELETE_OPTION": "Cancella (DEL)", + "FAVORITE_OPTION": "Preferito (L)", + "UNFAVORITE_OPTION": "Rimuovi dai preferiti (L)", + "MULTI_FOLDER_UPLOAD": "Selezionate più cartelle", + "UPLOAD_STRATEGY_CHOICE": "Vuoi caricarli in", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Un album singolo", + "OR": "o", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Album separati", + "SESSION_EXPIRED_MESSAGE": "La sessione è scaduta. Per continuare, esegui nuovamente l'accesso", + "SESSION_EXPIRED": "Sessione scaduta", + "PASSWORD_GENERATION_FAILED": "Il tuo browser non è stato in grado di generare una chiave forte che soddisfa gli standard di crittografia ente, prova ad usare l'app per dispositivi mobili o un altro browser", + "CHANGE_PASSWORD": "Cambia password", + "GO_BACK": "Torna indietro", + "RECOVERY_KEY": "Chiave di recupero", + "SAVE_LATER": "Fallo più tardi", + "SAVE": "Salva Chiave", + "RECOVERY_KEY_DESCRIPTION": "Se dimentichi la tua password, l'unico modo per recuperare i tuoi dati è con questa chiave.", + "RECOVER_KEY_GENERATION_FAILED": "Impossibile generare il codice di recupero, riprova", + "KEY_NOT_STORED_DISCLAIMER": "Non memorizziamo questa chiave, quindi salvala in un luogo sicuro", + "FORGOT_PASSWORD": "Password dimenticata", + "RECOVER_ACCOUNT": "Recupera account", + "RECOVERY_KEY_HINT": "Chiave di recupero", + "RECOVER": "Recupera", + "NO_RECOVERY_KEY": "Nessuna chiave di recupero?", + "INCORRECT_RECOVERY_KEY": "Chiave di recupero errata", + "SORRY": "Siamo spiacenti", + "NO_RECOVERY_KEY_MESSAGE": "A causa della natura del nostro protocollo di crittografia end-to-end, i tuoi dati non possono essere decifrati senza la tua password o chiave di ripristino", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Per favore invia un'email a {{emailID}} dal tuo indirizzo email registrato", + "CONTACT_SUPPORT": "Contatta il supporto", + "REQUEST_FEATURE": "Richiedi una funzionalità", + "SUPPORT": "Supporto", + "CONFIRM": "Conferma", + "CANCEL": "Annulla", + "LOGOUT": "Disconnettiti", + "DELETE_ACCOUNT": "Elimina account", + "DELETE_ACCOUNT_MESSAGE": "

Per favore invia una email a {{emailID}} dal tuo indirizzo email registrato.

La tua richiesta verrà elaborata entro 72 ore.

", + "LOGOUT_MESSAGE": "Sei sicuro di volerti disconnettere?", + "CHANGE_EMAIL": "Cambia email", + "OK": "OK", + "SUCCESS": "Operazione riuscita", + "ERROR": "Errore", + "MESSAGE": "Messaggio", + "INSTALL_MOBILE_APP": "Installa la nostra app Android o iOS per eseguire il backup automatico di tutte le tue foto", + "DOWNLOAD_APP_MESSAGE": "Siamo spiacenti, questa operazione è attualmente supportata solo sulla nostra app desktop", + "DOWNLOAD_APP": "Scarica l'app per desktop", + "EXPORT": "Esporta Dati", + "SUBSCRIPTION": "Abbonamento", + "SUBSCRIBE": "Iscriviti", + "MANAGEMENT_PORTAL": "Gestisci i metodi di pagamento", + "MANAGE_FAMILY_PORTAL": "Gestisci piano famiglia", + "LEAVE_FAMILY_PLAN": "Abbandona il piano famiglia", + "LEAVE": "Lascia", + "LEAVE_FAMILY_CONFIRM": "Sei sicuro di voler uscire dal piano famiglia?", + "CHOOSE_PLAN": "Scegli il tuo piano", + "MANAGE_PLAN": "Gestisci il tuo abbonamento", + "ACTIVE": "Attivo", + "OFFLINE_MSG": "Sei offline, i ricordi memorizzati nella cache vengono mostrati", + "FREE_SUBSCRIPTION_INFO": "Sei sul piano gratuito che scade il {{date, dateTime}}", + "FAMILY_SUBSCRIPTION_INFO": "Fai parte di un piano famiglia gestito da", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Si rinnova il {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Termina il {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Il tuo abbonamento verrà annullato il {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Hai superato la quota di archiviazione assegnata, si prega di aggiornare ", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

Abbiamo ricevuto il tuo pagamento

Il tuo abbonamento è valido fino a {{date, dateTime}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "Il tuo acquisto è stato annullato, riprova se vuoi iscriverti", + "SUBSCRIPTION_PURCHASE_FAILED": "Acquisto abbonamento non riuscito, riprova", + "SUBSCRIPTION_UPDATE_FAILED": "L'aggiornamento dell'abbonamento non è riuscito, riprova", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Siamo spiacenti, il pagamento non è andato a buon fine quando abbiamo provato ad addebitare alla sua carta, la preghiamo di aggiornare il suo metodo di pagamento e riprovare", + "STRIPE_AUTHENTICATION_FAILED": "Non siamo in grado di autenticare il tuo metodo di pagamento. Per favore scegli un metodo di pagamento diverso e riprova", + "UPDATE_PAYMENT_METHOD": "Aggiorna metodo di pagamento", + "MONTHLY": "Mensile", + "YEARLY": "Annuale", + "UPDATE_SUBSCRIPTION_MESSAGE": "Sei sicuro di voler cambiare il piano?", + "UPDATE_SUBSCRIPTION": "Cambia piano", + "CANCEL_SUBSCRIPTION": "Annulla abbonamento", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Tutti i tuoi dati saranno cancellati dai nostri server alla fine di questo periodo di fatturazione.

Sei sicuro di voler annullare il tuo abbonamento?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "Impossibile annullare l'abbonamento", + "SUBSCRIPTION_CANCEL_SUCCESS": "Abbonamento annullato con successo", + "REACTIVATE_SUBSCRIPTION": "Riattiva abbonamento", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Una volta riattivato, ti verrà addebitato il valore di {{date, dateTime}}", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Iscrizione attivata con successo ", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Grazie", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Annulla abbonamento mobile", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Per favore contattaci su {{emailID}} per gestire il tuo abbonamento", + "RENAME": "Rinomina", + "RENAME_FILE": "Rinomina file", + "RENAME_COLLECTION": "Rinomina album", + "DELETE_COLLECTION_TITLE": "Eliminare l'album?", + "DELETE_COLLECTION": "Elimina album", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "Elimina foto", + "KEEP_PHOTOS": "Mantieni foto", + "SHARE": "Condividi", + "SHARE_COLLECTION": "Condividi album", + "SHAREES": "Condividi con", + "SHARE_WITH_SELF": "Ops, non puoi condividere a te stesso", + "ALREADY_SHARED": "Ops, lo stai già condividendo con {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Condividere gli album non è consentito", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "La condivisione è disabilitata per gli account free", + "DOWNLOAD_COLLECTION": "Scarica album", + "DOWNLOAD_COLLECTION_MESSAGE": "

Sei sicuro di volere scaricare l'album interamente?

Tutti i file saranno messi in coda per il download

", + "CREATE_ALBUM_FAILED": "Operazione di creazione dell'album fallita, per favore riprova", + "SEARCH": "Ricerca", + "SEARCH_RESULTS": "Risultati della ricerca", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "Album", + "LOCATION": "Posizione", + "CITY": "Posizione", + "DATE": "Data", + "FILE_NAME": "Nome file", + "THING": "Contenuto", + "FILE_CAPTION": "Descrizione", + "FILE_TYPE": "Tipo del file", + "CLIP": "" + }, + "photos_count_zero": "Nessuna memoria", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "Aggiungi all'album", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Questo video non può essere riprodotto nel tuo browser", + "PEOPLE": "Persone", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "volti non identificati", + "OBJECTS": "", + "TEXT": "testo", + "INFO": "Info ", + "INFO_OPTION": "", + "FILE_NAME": "Nome file", + "CAPTION_PLACEHOLDER": "Aggiungi una descrizione", + "LOCATION": "Posizione", + "SHOW_ON_MAP": "Guarda su OpenStreetMap", + "MAP": "Mappa", + "MAP_SETTINGS": "Impostazioni Mappa", + "ENABLE_MAPS": "Attivare Mappa?", + "ENABLE_MAP": "Attivare mappa", + "DISABLE_MAPS": "Disattivare Mappa?", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "EXIF", + "ISO": "ISO", + "TWO_FACTOR": "Due fattori", + "TWO_FACTOR_AUTHENTICATION": "Autenticazione a due fattori", + "TWO_FACTOR_QR_INSTRUCTION": "Scansiona il codice QR qui sotto con la tua app di autenticazione preferita", + "ENTER_CODE_MANUALLY": "Inserisci il codice manualmente", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Inserisci questo codice nella tua app di autenticazione preferita", + "SCAN_QR_CODE": "Oppure scansiona il codice QR", + "ENABLE_TWO_FACTOR": "Attiva due fattori", + "ENABLE": "Attiva", + "LOST_DEVICE": "", + "INCORRECT_CODE": "Codice errato", + "TWO_FACTOR_INFO": "Aggiungi un ulteriore livello di sicurezza richiedendo più informazioni rispetto a email e password per eseguire l'accesso al tuo account", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "Esporta dati", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "Invia OTP", + "EMAIl_ALREADY_OWNED": "Email già in uso", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "Caricamento fallito ", + "SKIPPED_FILES": "Ignora caricamenti", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "Caricamenti eseguiti con successo", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "Video saltati", + "INPROGRESS_METADATA_EXTRACTION": "In corso", + "INPROGRESS_UPLOADS": "Caricamenti in corso", + "TOO_LARGE_UPLOADS": "File pesanti", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Spazio insufficiente", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Questi file non sono stati caricati perché supererebbero la capacità massima del tuo piano di spazio d'archiviazione", + "TOO_LARGE_INFO": "Questi file non sono stati caricati perché superano il nostro limite di pesantezza di un file", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "Archivio", + "FAVORITES": "Preferiti", + "ARCHIVE_COLLECTION": "Album archiviato", + "ARCHIVE_SECTION_NAME": "Archivio", + "ALL_SECTION_NAME": "Tutto", + "MOVE_TO_COLLECTION": "Sposta nell'album", + "UNARCHIVE": "Rimuovi dall'archivio", + "UNARCHIVE_COLLECTION": "Rimuovi album dall'archivio", + "HIDE_COLLECTION": "Nascondi album", + "UNHIDE_COLLECTION": "Rimuovi album dai nascosti", + "MOVE": "Sposta", + "ADD": "Aggiungi", + "REMOVE": "Rimuovi", + "YES_REMOVE": "Sì, rimuovi", + "REMOVE_FROM_COLLECTION": "Rimuovi dall'album", + "TRASH": "Cestino", + "MOVE_TO_TRASH": "Sposta nel cestino", + "TRASH_FILES_MESSAGE": "Gli elementi selezionati verranno eliminati da tutti gli album e spostati nel cestino.", + "TRASH_FILE_MESSAGE": "Il file verrà eliminato da tutti gli album e spostato nel cestino.", + "DELETE_PERMANENTLY": "Elimina definitivamente", + "RESTORE": "Ripristina", + "RESTORE_TO_COLLECTION": "Ripristina nell'album", + "EMPTY_TRASH": "Svuota il cestino", + "EMPTY_TRASH_TITLE": "Vuoi svuotare il cestino?", + "EMPTY_TRASH_MESSAGE": "I file selezionati verranno eliminati definitivamente dal tuo account ente.", + "LEAVE_SHARED_ALBUM": "Sì, esci", + "LEAVE_ALBUM": "Abbandona l'album", + "LEAVE_SHARED_ALBUM_TITLE": "Abbandonare l'album condiviso?", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "Meno recente", + "SORT_BY_UPDATION_TIME_DESCENDING": "Ultimo aggiornamento", + "SORT_BY_NAME": "Nome", + "COMPRESS_THUMBNAILS": "Comprimi miniature", + "THUMBNAIL_REPLACED": "Miniature compresse", + "FIX_THUMBNAIL": "Comprimi", + "FIX_THUMBNAIL_LATER": "Comprimi più tardi", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "Installa", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "Nessun partecipante", + "participants_one": "1 partecipante", + "participants_other": "{{count, number}} partecipanti", + "ADD_VIEWERS": "", + "PARTICIPANTS": "Partecipanti", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "Rimuovere?", + "CONFIRM_REMOVE": "Sì, rimuovi", + "MANAGE": "Gestisci", + "ADDED_AS": "Aggiunto come", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "Rimuovi partecipante", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "404 - non trovato", + "LINK_EXPIRED": "Link scaduto", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "ente.io", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "Cartella", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "1 Album", + "albums_other": "{{count, number}} Album", + "ALL_ALBUMS": "Tutti gli Album", + "ALBUMS": "Album", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "Crea account", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "Tu", + "FAMILY": "Famiglia", + "FREE": "gratis", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "Ancora nessuna cartella aggiunta!", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "Cambia Cartella", + "TWO_MONTHS_FREE": "Ottieni 2 mesi gratis sui piani annuali", + "GB": "GB", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "1 GB per 1 anno", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "AUTHENTICATE": "Autenticati", + "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": "Oggi", + "YESTERDAY": "Ieri", + "NAME_PLACEHOLDER": "Nome...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "Seleziona tema", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "Più dettagli", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "Avanzate", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "Sicurezza password: Debole", + "PASSPHRASE_STRENGTH_MODERATE": "Sicurezza password: Moderata", + "PASSPHRASE_STRENGTH_STRONG": "Sicurezza password: Forte", + "PREFERENCES": "", + "LANGUAGE": "Lingua", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "B", + "KB": "KB", + "MB": "MB", + "GB": "GB", + "TB": "TB" + }, + "AFTER_TIME": { + "HOUR": "dopo un'ora", + "DAY": "dopo un giorno", + "WEEK": "dopo una settimana", + "MONTH": "dopo un mese", + "YEAR": "dopo un anno" + }, + "COPY_LINK": "Copia link", + "DONE": "Fatto", + "LINK_SHARE_TITLE": "O condividi un link", + "REMOVE_LINK": "Rimuovi link", + "CREATE_PUBLIC_SHARING": "Crea link pubblico", + "PUBLIC_LINK_CREATED": "Link pubblick creato", + "PUBLIC_LINK_ENABLED": "Link pubblico attivato", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Seleziona un motivo", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/ko-KR/translation.json b/web/apps/cast/public/locales/ko-KR/translation.json new file mode 100644 index 0000000000..4fbe6c0777 --- /dev/null +++ b/web/apps/cast/public/locales/ko-KR/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "추억을 안전하게 백업하세요", + "HERO_SLIDE_1": "종단간 암호화가 기본지원입니다", + "HERO_SLIDE_2_TITLE": "낙진대피소에 안전하게 보관됩니다", + "HERO_SLIDE_2": "오랫동안 보존할 수 있도록한 설계", + "HERO_SLIDE_3_TITLE": "
어디에서나
이용가능
", + "HERO_SLIDE_3": "안드로이드, iOS, 웹, 데스크탑", + "LOGIN": "로그인", + "SIGN_UP": "회원가입", + "NEW_USER": "ente의 새소식", + "EXISTING_USER": "기존 사용자", + "ENTER_NAME": "이름 입력", + "PUBLIC_UPLOADER_NAME_MESSAGE": "친구들이 이 멋진 사진에 대해 고마워할 수 있도록 이름을 추가하세요!", + "ENTER_EMAIL": "이메일 주소를 입력하세요", + "EMAIL_ERROR": "올바른 이메일을 입력하세요", + "REQUIRED": "필수", + "EMAIL_SENT": "{{email}} 로 인증 코드가 전송되었습니다", + "CHECK_INBOX": "인증을 완료하기 위해 당신의 메일 수신함(그리고 스팸 수신함)을 확인하세요.", + "ENTER_OTT": "인증 코드", + "RESEND_MAIL": "코드 재전송하기", + "VERIFY": "인증", + "UNKNOWN_ERROR": "문제가 생긴 것 같아요. 다시 시도하세요", + "INVALID_CODE": "잘못된 인증 코드", + "EXPIRED_CODE": "입력한 인증 코드가 만료되었습니다", + "SENDING": "전송 중...", + "SENT": "발송 완료!", + "PASSWORD": "비밀번호", + "LINK_PASSWORD": "앨범 잠금해제를 위해 비밀번호를 입력하세요", + "RETURN_PASSPHRASE_HINT": "비밀번호", + "SET_PASSPHRASE": "비밀번호 설정", + "VERIFY_PASSPHRASE": "로그인", + "INCORRECT_PASSPHRASE": "잘못된 비밀번호입니다", + "ENTER_ENC_PASSPHRASE": "당신의 데이터를 암호화하는 데 사용할 수 있는 비밀번호를 입력하세요", + "PASSPHRASE_DISCLAIMER": "우리는 귀하의 비밀번호를 저장하지 않습니다. 만약 비밀번호를 잊어버린 경우 복구 키 없다면 데이터 복구를 도와드릴 수 없습니다.", + "WELCOME_TO_ENTE_HEADING": "환영합니다 ", + "WELCOME_TO_ENTE_SUBHEADING": "End-to-End 암호화된 사진 저장 및 공유", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "당신 최고의 사진이 있는 곳", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "암호 키 생성 중...", + "PASSPHRASE_HINT": "비밀번호", + "CONFIRM_PASSPHRASE": "비밀번호 확인", + "REFERRAL_CODE_HINT": "어떻게 Ente에 대해 들으셨나요? (선택사항)", + "REFERRAL_INFO": "우리는 앱 설치를 추적하지 않습니다. 우리를 알게 된 곳을 남겨주시면 우리에게 도움이 될꺼에요!", + "PASSPHRASE_MATCH_ERROR": "비밀번호가 일치하지 않습니다", + "CREATE_COLLECTION": "새 앨범", + "ENTER_ALBUM_NAME": "앨범 이름", + "CLOSE_OPTION": "닫기 (Esc)", + "ENTER_FILE_NAME": "파일 이름", + "CLOSE": "닫기", + "NO": "아니오", + "NOTHING_HERE": "아직 볼 수 있는 것이 없어요 👀", + "UPLOAD": "업로드", + "IMPORT": "가져오기", + "ADD_PHOTOS": "사진 추가", + "ADD_MORE_PHOTOS": "사진 더 추가하기", + "add_photos_one": "아이템 하나 추가", + "add_photos_other": "아이템 {{count, number}} 개 추가하기", + "SELECT_PHOTOS": "사진 선택하기", + "FILE_UPLOAD": "파일 업로드", + "UPLOAD_STAGE_MESSAGE": { + "0": "업로드 준비중", + "1": "구글 메타데이타 파일들 읽는중", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} 파일 메타데이터가 추출되었습니다", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} 파일이 처리되었습니다", + "4": "남은 업로드 취소중", + "5": "백업 완료" + }, + "FILE_NOT_UPLOADED_LIST": "아래 파일들은 업로드 되지 않았습니다", + "SUBSCRIPTION_EXPIRED": "구독 만료", + "SUBSCRIPTION_EXPIRED_MESSAGE": "당신 구독이 만료되었으니, 구독을 갱신해주세요", + "STORAGE_QUOTA_EXCEEDED": "스토리지 제한이 초과되었습니다", + "INITIAL_LOAD_DELAY_WARNING": "처음 로딩시 다소 시간이 걸릴 수 있습니다", + "USER_DOES_NOT_EXIST": "죄송합니다. 해당 이메일을 사용하는 사용자를 찾을 수 없습니다", + "NO_ACCOUNT": "계정이 없습니다", + "ACCOUNT_EXISTS": "이미 계정이 있습니다", + "CREATE": "만들기", + "DOWNLOAD": "다운로드", + "DOWNLOAD_OPTION": "다운로드 (D)", + "DOWNLOAD_FAVORITES": "즐겨찾기 다운로드", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/nl-NL/translation.json b/web/apps/cast/public/locales/nl-NL/translation.json new file mode 100644 index 0000000000..15d9bfdba0 --- /dev/null +++ b/web/apps/cast/public/locales/nl-NL/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Privé back-ups
voor uw herinneringen
", + "HERO_SLIDE_1": "Standaard end-to-end versleuteld", + "HERO_SLIDE_2_TITLE": "
Veilig opgeslagen
in een kernbunker
", + "HERO_SLIDE_2": "Ontworpen om levenslang mee te gaan", + "HERO_SLIDE_3_TITLE": "
Overal
beschikbaar
", + "HERO_SLIDE_3": "Android, iOS, Web, Desktop", + "LOGIN": "Inloggen", + "SIGN_UP": "Registreren", + "NEW_USER": "Nieuw bij ente", + "EXISTING_USER": "Bestaande gebruiker", + "ENTER_NAME": "Naam invoeren", + "PUBLIC_UPLOADER_NAME_MESSAGE": "Voeg een naam toe zodat je vrienden weten wie ze moeten bedanken voor deze geweldige foto's!", + "ENTER_EMAIL": "Vul e-mailadres in", + "EMAIL_ERROR": "Vul een geldig e-mailadres in", + "REQUIRED": "Vereist", + "EMAIL_SENT": "Verificatiecode verzonden naar {{email}}", + "CHECK_INBOX": "Controleer je inbox (en spam) om verificatie te voltooien", + "ENTER_OTT": "Verificatiecode", + "RESEND_MAIL": "Code opnieuw versturen", + "VERIFY": "Verifiëren", + "UNKNOWN_ERROR": "Er is iets fout gegaan, probeer het opnieuw", + "INVALID_CODE": "Ongeldige verificatiecode", + "EXPIRED_CODE": "Uw verificatiecode is verlopen", + "SENDING": "Verzenden...", + "SENT": "Verzonden!", + "PASSWORD": "Wachtwoord", + "LINK_PASSWORD": "Voer wachtwoord in om het album te ontgrendelen", + "RETURN_PASSPHRASE_HINT": "Wachtwoord", + "SET_PASSPHRASE": "Wachtwoord instellen", + "VERIFY_PASSPHRASE": "Aanmelden", + "INCORRECT_PASSPHRASE": "Onjuist wachtwoord", + "ENTER_ENC_PASSPHRASE": "Voer een wachtwoord in dat we kunnen gebruiken om je gegevens te versleutelen", + "PASSPHRASE_DISCLAIMER": "We slaan je wachtwoord niet op, dus als je het vergeet, zullen we u niet kunnen helpen uw data te herstellen zonder een herstelcode.", + "WELCOME_TO_ENTE_HEADING": "Welkom bij ", + "WELCOME_TO_ENTE_SUBHEADING": "Foto opslag en delen met end to end encryptie", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "Waar je beste foto's leven", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Encryptiecodes worden gegenereerd...", + "PASSPHRASE_HINT": "Wachtwoord", + "CONFIRM_PASSPHRASE": "Wachtwoord bevestigen", + "REFERRAL_CODE_HINT": "Hoe hoorde je over Ente? (optioneel)", + "REFERRAL_INFO": "Wij gebruiken geen tracking. Het zou helpen als je ons vertelt waar je ons gevonden hebt!", + "PASSPHRASE_MATCH_ERROR": "Wachtwoorden komen niet overeen", + "CREATE_COLLECTION": "Nieuw album", + "ENTER_ALBUM_NAME": "Album naam", + "CLOSE_OPTION": "Sluiten (Esc)", + "ENTER_FILE_NAME": "Bestandsnaam", + "CLOSE": "Sluiten", + "NO": "Nee", + "NOTHING_HERE": "Nog niets te zien hier 👀", + "UPLOAD": "Uploaden", + "IMPORT": "Importeren", + "ADD_PHOTOS": "Foto's toevoegen", + "ADD_MORE_PHOTOS": "Meer foto's toevoegen", + "add_photos_one": "1 foto toevoegen", + "add_photos_other": "{{count, number}} foto's toevoegen", + "SELECT_PHOTOS": "Selecteer foto's", + "FILE_UPLOAD": "Bestand uploaden", + "UPLOAD_STAGE_MESSAGE": { + "0": "Upload wordt voorbereid", + "1": "Lezen van Google metadata bestanden", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} bestanden metadata uitgepakt", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} bestanden geback-upt", + "4": "Resterende uploads worden geannuleerd", + "5": "Back-up voltooid" + }, + "FILE_NOT_UPLOADED_LIST": "De volgende bestanden zijn niet geüpload", + "SUBSCRIPTION_EXPIRED": "Abonnement verlopen", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Uw abonnement is verlopen, gelieve vernieuwen", + "STORAGE_QUOTA_EXCEEDED": "Opslaglimiet overschreden", + "INITIAL_LOAD_DELAY_WARNING": "Eerste keer laden kan enige tijd duren", + "USER_DOES_NOT_EXIST": "Sorry, we konden geen account met dat e-mailadres vinden", + "NO_ACCOUNT": "Heb nog geen account", + "ACCOUNT_EXISTS": "Heb al een account", + "CREATE": "Creëren", + "DOWNLOAD": "Downloaden", + "DOWNLOAD_OPTION": "Downloaden (D)", + "DOWNLOAD_FAVORITES": "Favorieten downloaden", + "DOWNLOAD_UNCATEGORIZED": "Ongecategoriseerd downloaden", + "DOWNLOAD_HIDDEN_ITEMS": "Verborgen bestanden downloaden", + "COPY_OPTION": "Kopiëren als PNG (Ctrl/Cmd - C)", + "TOGGLE_FULLSCREEN": "Schakelen volledig scherm modus (F)", + "ZOOM_IN_OUT": "In/uitzoomen", + "PREVIOUS": "Vorige (←)", + "NEXT": "Volgende (→)", + "TITLE_PHOTOS": "Ente Foto's", + "TITLE_ALBUMS": "Ente Foto's", + "TITLE_AUTH": "Ente Auth", + "UPLOAD_FIRST_PHOTO": "Je eerste foto uploaden", + "IMPORT_YOUR_FOLDERS": "Importeer uw mappen", + "UPLOAD_DROPZONE_MESSAGE": "Sleep om een back-up van je bestanden te maken", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Sleep om map aan watched folders toe te voegen", + "TRASH_FILES_TITLE": "Bestanden verwijderen?", + "TRASH_FILE_TITLE": "Verwijder bestand?", + "DELETE_FILES_TITLE": "Onmiddellijk verwijderen?", + "DELETE_FILES_MESSAGE": "Geselecteerde bestanden zullen permanent worden verwijderd van je ente account.", + "DELETE": "Verwijderen", + "DELETE_OPTION": "Verwijderen (DEL)", + "FAVORITE_OPTION": "Favoriet (L)", + "UNFAVORITE_OPTION": "Verwijderen uit Favorieten (L)", + "MULTI_FOLDER_UPLOAD": "Meerdere mappen gedetecteerd", + "UPLOAD_STRATEGY_CHOICE": "Wilt u deze uploaden naar", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Één enkel album", + "OR": "of", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Aparte albums maken", + "SESSION_EXPIRED_MESSAGE": "Uw sessie is verlopen. Meld u opnieuw aan om verder te gaan", + "SESSION_EXPIRED": "Sessie verlopen", + "PASSWORD_GENERATION_FAILED": "Uw browser kon geen sterke sleutel genereren die voldoet aan onze versleutelingsstandaarden. Probeer de mobiele app of een andere browser te gebruiken", + "CHANGE_PASSWORD": "Wachtwoord wijzigen", + "GO_BACK": "Ga terug", + "RECOVERY_KEY": "Herstelsleutel", + "SAVE_LATER": "Doe dit later", + "SAVE": "Sleutel opslaan", + "RECOVERY_KEY_DESCRIPTION": "Als je je wachtwoord vergeet, kun je alleen met deze sleutel je gegevens herstellen.", + "RECOVER_KEY_GENERATION_FAILED": "Herstelcode kon niet worden gegenereerd, probeer het opnieuw", + "KEY_NOT_STORED_DISCLAIMER": "We slaan deze sleutel niet op, bewaar dit op een veilige plaats", + "FORGOT_PASSWORD": "Wachtwoord vergeten", + "RECOVER_ACCOUNT": "Account herstellen", + "RECOVERY_KEY_HINT": "Herstelsleutel", + "RECOVER": "Herstellen", + "NO_RECOVERY_KEY": "Geen herstelsleutel?", + "INCORRECT_RECOVERY_KEY": "Onjuiste herstelsleutel", + "SORRY": "Sorry", + "NO_RECOVERY_KEY_MESSAGE": "Door de aard van ons end-to-end encryptieprotocol kunnen je gegevens niet worden ontsleuteld zonder je wachtwoord of herstelsleutel", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Stuur een e-mail naar {{emailID}} vanaf het door jou geregistreerde e-mailadres", + "CONTACT_SUPPORT": "Klantenservice", + "REQUEST_FEATURE": "Vraag nieuwe functie aan", + "SUPPORT": "Ondersteuning", + "CONFIRM": "Bevestigen", + "CANCEL": "Annuleren", + "LOGOUT": "Uitloggen", + "DELETE_ACCOUNT": "Account verwijderen", + "DELETE_ACCOUNT_MESSAGE": "

Stuur een e-mail naar {{emailID}} vanaf uw geregistreerde e-mailadres.

Uw aanvraag wordt binnen 72 uur verwerkt.

", + "LOGOUT_MESSAGE": "Weet u zeker dat u wilt uitloggen?", + "CHANGE_EMAIL": "E-mail wijzigen", + "OK": "Oké", + "SUCCESS": "Succes", + "ERROR": "Foutmelding", + "MESSAGE": "Melding", + "INSTALL_MOBILE_APP": "Installeer onze Android of iOS app om automatisch een back-up te maken van al uw foto's", + "DOWNLOAD_APP_MESSAGE": "Sorry, deze bewerking wordt momenteel alleen ondersteund op onze desktop app", + "DOWNLOAD_APP": "Download de desktop app", + "EXPORT": "Data exporteren", + "SUBSCRIPTION": "Abonnement", + "SUBSCRIBE": "Abonneren", + "MANAGEMENT_PORTAL": "Betaalmethode beheren", + "MANAGE_FAMILY_PORTAL": "Familie abonnement beheren", + "LEAVE_FAMILY_PLAN": "Familie abonnement verlaten", + "LEAVE": "Verlaten", + "LEAVE_FAMILY_CONFIRM": "Weet je zeker dat je het familie-plan wilt verlaten?", + "CHOOSE_PLAN": "Kies uw abonnement", + "MANAGE_PLAN": "Beheer uw abonnement", + "ACTIVE": "Actief", + "OFFLINE_MSG": "Je bent offline, lokaal opgeslagen herinneringen worden getoond", + "FREE_SUBSCRIPTION_INFO": "Je hebt het gratis abonnement dat verloopt op {{date, dateTime}}", + "FAMILY_SUBSCRIPTION_INFO": "U hebt een familieplan dat beheerd wordt door", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Vernieuwt op {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Eindigt op {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Uw abonnement loopt af op {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "Jouw {{storage, string}} add-on is geldig tot {{date, dateTime}}", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "U heeft uw opslaglimiet overschreden, gelieve upgraden", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

We hebben uw betaling ontvangen

Uw abonnement is geldig tot {{date, dateTime}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "Uw aankoop is geannuleerd, probeer het opnieuw als u zich wilt abonneren", + "SUBSCRIPTION_PURCHASE_FAILED": "Betaling van abonnement mislukt Probeer het opnieuw", + "SUBSCRIPTION_UPDATE_FAILED": "Niet gelukt om abonnement bij te werken, probeer het opnieuw", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Het spijt ons, maar de betaling is mislukt bij het in rekening brengen van uw kaart, gelieve uw betaalmethode bij te werken en het opnieuw te proberen", + "STRIPE_AUTHENTICATION_FAILED": "We zijn niet in staat om uw betaalmethode te verifiëren. Kies een andere betaalmethode en probeer het opnieuw", + "UPDATE_PAYMENT_METHOD": "Betalingsmethode bijwerken", + "MONTHLY": "Maandelijks", + "YEARLY": "Jaarlijks", + "UPDATE_SUBSCRIPTION_MESSAGE": "Weet u zeker dat u uw abonnement wilt wijzigen?", + "UPDATE_SUBSCRIPTION": "Abonnement wijzigen", + "CANCEL_SUBSCRIPTION": "Abonnement opzeggen", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Al je gegevens zullen worden verwijderd van onze servers aan het einde van deze factureringsperiode.

Weet u zeker dat u uw abonnement wilt opzeggen?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Weet je zeker dat je je abonnement wilt opzeggen?

", + "SUBSCRIPTION_CANCEL_FAILED": "Abonnement opzeggen mislukt", + "SUBSCRIPTION_CANCEL_SUCCESS": "Abonnement succesvol geannuleerd", + "REACTIVATE_SUBSCRIPTION": "Abonnement opnieuw activeren", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Zodra je weer bent geactiveerd, zal je worden gefactureerd op {{date, dateTime}}", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Abonnement succesvol geactiveerd ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Heractiveren van abonnementsverlenging is mislukt", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Bedankt", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Mobiel abonnement opzeggen", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Annuleer je abonnement via de mobiele app om je abonnement hier te activeren", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Neem contact met ons op via {{emailID}} om uw abonnement te beheren", + "RENAME": "Naam wijzigen", + "RENAME_FILE": "Bestandsnaam wijzigen", + "RENAME_COLLECTION": "Albumnaam wijzigen", + "DELETE_COLLECTION_TITLE": "Verwijder album?", + "DELETE_COLLECTION": "Verwijder album", + "DELETE_COLLECTION_MESSAGE": "Verwijder de foto's (en video's) van dit album ook uit alle andere albums waar deze deel van uitmaken?", + "DELETE_PHOTOS": "Foto's verwijderen", + "KEEP_PHOTOS": "Foto's behouden", + "SHARE": "Delen", + "SHARE_COLLECTION": "Album delen", + "SHAREES": "Gedeeld met", + "SHARE_WITH_SELF": "Oeps, je kunt niet met jezelf delen", + "ALREADY_SHARED": "Oeps, je deelt dit al met {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Album delen niet toegestaan", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Delen is uitgeschakeld voor gratis accounts", + "DOWNLOAD_COLLECTION": "Download album", + "DOWNLOAD_COLLECTION_MESSAGE": "

Weet je zeker dat je het volledige album wilt downloaden?

Alle bestanden worden in de wachtrij geplaatst voor downloaden

", + "CREATE_ALBUM_FAILED": "Aanmaken van album mislukt, probeer het opnieuw", + "SEARCH": "Zoeken", + "SEARCH_RESULTS": "Zoekresultaten", + "NO_RESULTS": "Geen resultaten gevonden", + "SEARCH_HINT": "Zoeken naar albums, datums ...", + "SEARCH_TYPE": { + "COLLECTION": "Album", + "LOCATION": "Locatie", + "CITY": "Locatie", + "DATE": "Datum", + "FILE_NAME": "Bestandsnaam", + "THING": "Inhoud", + "FILE_CAPTION": "Omschrijving", + "FILE_TYPE": "Bestandstype", + "CLIP": "Magische" + }, + "photos_count_zero": "Geen herinneringen", + "photos_count_one": "1 herinnering", + "photos_count_other": "{{count, number}} herinneringen", + "TERMS_AND_CONDITIONS": "Ik ga akkoord met de gebruiksvoorwaarden en privacybeleid", + "ADD_TO_COLLECTION": "Toevoegen aan album", + "SELECTED": "geselecteerd", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Deze video kan niet afgespeeld worden op uw browser", + "PEOPLE": "Personen", + "INDEXING_SCHEDULED": "indexering is gepland...", + "ANALYZING_PHOTOS": "analyseren van nieuwe foto's {{indexStatus.nSyncedFiles}} van {{indexStatus.nTotalFiles}} gedaan)...", + "INDEXING_PEOPLE": "mensen indexeren in {{indexStatus.nSyncedFiles}} foto's...", + "INDEXING_DONE": "{{indexStatus.nSyncedFiles}} geïndexeerde foto's", + "UNIDENTIFIED_FACES": "ongeïdentificeerde gezichten", + "OBJECTS": "objecten", + "TEXT": "tekst", + "INFO": "Info ", + "INFO_OPTION": "Info (I)", + "FILE_NAME": "Bestandsnaam", + "CAPTION_PLACEHOLDER": "Voeg een beschrijving toe", + "LOCATION": "Locatie", + "SHOW_ON_MAP": "Bekijk op OpenStreetMap", + "MAP": "Kaart", + "MAP_SETTINGS": "Kaart instellingen", + "ENABLE_MAPS": "Kaarten inschakelen?", + "ENABLE_MAP": "Kaarten inschakelen", + "DISABLE_MAPS": "Kaarten uitzetten?", + "ENABLE_MAP_DESCRIPTION": "

Dit toont jouw foto's op een wereldkaart.

Deze kaart wordt gehost door Open Street Map, en de exacte locaties van jouw foto's worden nooit gedeeld.

Je kunt deze functie op elk gewenst moment uitschakelen via de instellingen.

", + "DISABLE_MAP_DESCRIPTION": "

Dit schakelt de weergave van je foto's op een wereldkaart uit.

Je kunt deze functie op elk gewenst moment inschakelen via Instellingen.

", + "DISABLE_MAP": "Kaarten uitzetten", + "DETAILS": "Details", + "VIEW_EXIF": "Bekijk alle EXIF gegevens", + "NO_EXIF": "Geen EXIF gegevens", + "EXIF": "EXIF", + "ISO": "ISO", + "TWO_FACTOR": "Tweestaps", + "TWO_FACTOR_AUTHENTICATION": "Tweestapsverificatie", + "TWO_FACTOR_QR_INSTRUCTION": "Scan de onderstaande QR-code met uw favoriete verificatie app", + "ENTER_CODE_MANUALLY": "Voer de code handmatig in", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Voer deze code in in uw favoriete verificatie app", + "SCAN_QR_CODE": "Scan QR-code in plaats daarvan", + "ENABLE_TWO_FACTOR": "Tweestapsverificatie inschakelen", + "ENABLE": "Inschakelen", + "LOST_DEVICE": "Tweestapsverificatie apparaat verloren", + "INCORRECT_CODE": "Onjuiste code", + "TWO_FACTOR_INFO": "Voeg een extra beveiligingslaag toe door meer dan uw e-mailadres en wachtwoord te vereisen om in te loggen op uw account", + "DISABLE_TWO_FACTOR_LABEL": "Schakel tweestapsverificatie uit", + "UPDATE_TWO_FACTOR_LABEL": "Update uw verificatie apparaat", + "DISABLE": "Uitschakelen", + "RECONFIGURE": "Herconfigureren", + "UPDATE_TWO_FACTOR": "Tweestapsverificatie bijwerken", + "UPDATE_TWO_FACTOR_MESSAGE": "Verder gaan zal elk eerder geconfigureerde verificatie apparaat ontzeggen", + "UPDATE": "Bijwerken", + "DISABLE_TWO_FACTOR": "Tweestapsverificatie uitschakelen", + "DISABLE_TWO_FACTOR_MESSAGE": "Weet u zeker dat u tweestapsverificatie wilt uitschakelen", + "TWO_FACTOR_DISABLE_FAILED": "Uitschakelen van tweestapsverificatie is mislukt, probeer het opnieuw", + "EXPORT_DATA": "Gegevens exporteren", + "SELECT_FOLDER": "Map selecteren", + "DESTINATION": "Bestemming", + "START": "Start", + "LAST_EXPORT_TIME": "Tijd laatste export", + "EXPORT_AGAIN": "Opnieuw synchroniseren", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Lokale opslag niet toegankelijk", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Je browser of een extensie blokkeert ente om gegevens op te slaan in de lokale opslag. Probeer deze pagina te laden na het aanpassen van de browser surfmodus.", + "SEND_OTT": "Stuur OTP", + "EMAIl_ALREADY_OWNED": "E-mail al in gebruik", + "ETAGS_BLOCKED": "

We kunnen de volgende bestanden niet uploaden vanwege uw browserconfiguratie.

Schakel alle extensies uit die mogelijk voorkomen dat ente eTags kan gebruiken om grote bestanden te uploaden, of gebruik onze desktop app voor een betrouwbaardere import ervaring.

", + "SKIPPED_VIDEOS_INFO": "

We ondersteunen het toevoegen van video's via openbare links momenteel niet.

Om video's te delen, meld je aan bij ente en deel met de beoogde ontvangers via hun e-mail

", + "LIVE_PHOTOS_DETECTED": "De foto en video bestanden van je Live Photos zijn samengevoegd tot één enkel bestand", + "RETRY_FAILED": "Probeer mislukte uploads nogmaals", + "FAILED_UPLOADS": "Mislukte uploads ", + "SKIPPED_FILES": "Genegeerde uploads", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Thumbnail generatie mislukt", + "UNSUPPORTED_FILES": "Niet-ondersteunde bestanden", + "SUCCESSFUL_UPLOADS": "Succesvolle uploads", + "SKIPPED_INFO": "Deze zijn overgeslagen omdat er bestanden zijn met overeenkomende namen in hetzelfde album", + "UNSUPPORTED_INFO": "ente ondersteunt deze bestandsformaten nog niet", + "BLOCKED_UPLOADS": "Geblokkeerde uploads", + "SKIPPED_VIDEOS": "Overgeslagen video's", + "INPROGRESS_METADATA_EXTRACTION": "In behandeling", + "INPROGRESS_UPLOADS": "Bezig met uploaden", + "TOO_LARGE_UPLOADS": "Grote bestanden", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Onvoldoende opslagruimte", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Deze bestanden zijn niet geüpload omdat ze de maximale grootte van uw opslagplan overschrijden", + "TOO_LARGE_INFO": "Deze bestanden zijn niet geüpload omdat ze onze limiet voor bestandsgrootte overschrijden", + "THUMBNAIL_GENERATION_FAILED_INFO": "Deze bestanden zijn geüpload, maar helaas konden we geen thumbnails voor ze genereren.", + "UPLOAD_TO_COLLECTION": "Uploaden naar album", + "UNCATEGORIZED": "Ongecategoriseerd", + "ARCHIVE": "Archiveren", + "FAVORITES": "Favorieten", + "ARCHIVE_COLLECTION": "Album archiveren", + "ARCHIVE_SECTION_NAME": "Archief", + "ALL_SECTION_NAME": "Alle", + "MOVE_TO_COLLECTION": "Verplaats naar album", + "UNARCHIVE": "Uit archief halen", + "UNARCHIVE_COLLECTION": "Album uit archief halen", + "HIDE_COLLECTION": "Verberg album", + "UNHIDE_COLLECTION": "Album zichtbaar maken", + "MOVE": "Verplaatsen", + "ADD": "Toevoegen", + "REMOVE": "Verwijderen", + "YES_REMOVE": "Ja, verwijderen", + "REMOVE_FROM_COLLECTION": "Verwijderen uit album", + "TRASH": "Prullenbak", + "MOVE_TO_TRASH": "Verplaatsen naar prullenbak", + "TRASH_FILES_MESSAGE": "De geselecteerde bestanden worden verwijderd uit alle albums en verplaatst naar de prullenbak.", + "TRASH_FILE_MESSAGE": "Het bestand wordt uit alle albums verwijderd en verplaatst naar de prullenbak.", + "DELETE_PERMANENTLY": "Permanent verwijderen", + "RESTORE": "Herstellen", + "RESTORE_TO_COLLECTION": "Terugzetten naar album", + "EMPTY_TRASH": "Prullenbak leegmaken", + "EMPTY_TRASH_TITLE": "Prullenbak leegmaken?", + "EMPTY_TRASH_MESSAGE": "Geselecteerde bestanden zullen permanent worden verwijderd van uw ente account.", + "LEAVE_SHARED_ALBUM": "Ja, verwijderen", + "LEAVE_ALBUM": "Album verlaten", + "LEAVE_SHARED_ALBUM_TITLE": "Gedeeld album verwijderen?", + "LEAVE_SHARED_ALBUM_MESSAGE": "Je verlaat het album, en het zal niet meer zichtbaar voor je zijn.", + "NOT_FILE_OWNER": "U kunt bestanden niet verwijderen in een gedeeld album", + "CONFIRM_SELF_REMOVE_MESSAGE": "De geselecteerde items worden verwijderd uit dit album. De items die alleen in dit album staan, worden verplaatst naar 'Niet gecategoriseerd'.", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Sommige van de items die u verwijdert zijn door andere mensen toegevoegd, en u verliest de toegang daartoe.", + "SORT_BY_CREATION_TIME_ASCENDING": "Oudste", + "SORT_BY_UPDATION_TIME_DESCENDING": "Laatst gewijzigd op", + "SORT_BY_NAME": "Naam", + "COMPRESS_THUMBNAILS": "Comprimeren van thumbnails", + "THUMBNAIL_REPLACED": "Thumbnails gecomprimeerd", + "FIX_THUMBNAIL": "Comprimeren", + "FIX_THUMBNAIL_LATER": "Later comprimeren", + "REPLACE_THUMBNAIL_NOT_STARTED": "Sommige van uw video thumbnails kunnen worden gecomprimeerd om ruimte te besparen. Wilt u dat ente ze comprimeert?", + "REPLACE_THUMBNAIL_COMPLETED": "Alle thumbnails zijn gecomprimeerd", + "REPLACE_THUMBNAIL_NOOP": "Je hebt geen thumbnails die verder gecomprimeerd kunnen worden", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Kon sommige van uw thumbnails niet comprimeren, probeer het opnieuw", + "FIX_CREATION_TIME": "Herstel tijd", + "FIX_CREATION_TIME_IN_PROGRESS": "Tijd aan het herstellen", + "CREATION_TIME_UPDATED": "Bestandstijd bijgewerkt", + "UPDATE_CREATION_TIME_NOT_STARTED": "Selecteer de optie die u wilt gebruiken", + "UPDATE_CREATION_TIME_COMPLETED": "Alle bestanden succesvol bijgewerkt", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "Bestandstijd update mislukt voor sommige bestanden, probeer het opnieuw", + "CAPTION_CHARACTER_LIMIT": "5000 tekens max", + "DATE_TIME_ORIGINAL": "EXIF:DatumTijdOrigineel", + "DATE_TIME_DIGITIZED": "EXIF:DatumTijdDigitaliseerd", + "METADATA_DATE": "EXIF:MetadataDatum", + "CUSTOM_TIME": "Aangepaste tijd", + "REOPEN_PLAN_SELECTOR_MODAL": "Abonnementen heropenen", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Kon abonnementen niet openen", + "INSTALL": "Installeren", + "SHARING_DETAILS": "Delen van informatie", + "MODIFY_SHARING": "Delen wijzigen", + "ADD_COLLABORATORS": "Samenwerker toevoegen", + "ADD_NEW_EMAIL": "Nieuw e-mailadres toevoegen", + "shared_with_people_zero": "Delen met specifieke mensen", + "shared_with_people_one": "Gedeeld met 1 persoon", + "shared_with_people_other": "Gedeeld met {{count, number}} mensen", + "participants_zero": "Geen deelnemers", + "participants_one": "1 deelnemer", + "participants_other": "{{count, number}} deelnemers", + "ADD_VIEWERS": "Voeg kijkers toe", + "PARTICIPANTS": "Deelnemers", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} zullen geen foto's meer kunnen toevoegen aan dit album

Ze zullen nog steeds bestaande foto's kunnen verwijderen die door hen zijn toegevoegd

", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} zal foto's aan het album kunnen toevoegen", + "CONVERT_TO_VIEWER": "Ja, converteren naar kijker", + "CONVERT_TO_COLLABORATOR": "Ja, converteren naar samenwerker", + "CHANGE_PERMISSION": "Rechten aanpassen?", + "REMOVE_PARTICIPANT": "Verwijderen?", + "CONFIRM_REMOVE": "Ja, verwijderen", + "MANAGE": "Beheren", + "ADDED_AS": "Toegevoegd als", + "COLLABORATOR_RIGHTS": "Samenwerkers kunnen foto's en video's toevoegen aan het gedeelde album", + "REMOVE_PARTICIPANT_HEAD": "Deelnemer verwijderen", + "OWNER": "Eigenaar", + "COLLABORATORS": "Samenwerker", + "ADD_MORE": "Meer toevoegen", + "VIEWERS": "Kijkers", + "OR_ADD_EXISTING": "Of kies een bestaande", + "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} zullen worden verwijderd uit het gedeelde album

Alle door hen toegevoegde foto's worden ook uit het album verwijderd

", + "NOT_FOUND": "404 - niet gevonden", + "LINK_EXPIRED": "Link verlopen", + "LINK_EXPIRED_MESSAGE": "Deze link is verlopen of uitgeschakeld!", + "MANAGE_LINK": "Link beheren", + "LINK_TOO_MANY_REQUESTS": "Dit album is te populair voor ons om te verwerken!", + "FILE_DOWNLOAD": "Downloads toestaan", + "LINK_PASSWORD_LOCK": "Wachtwoord versleuteling", + "PUBLIC_COLLECT": "Foto's toevoegen toestaan", + "LINK_DEVICE_LIMIT": "Apparaat limiet", + "NO_DEVICE_LIMIT": "Geen", + "LINK_EXPIRY": "Vervaldatum link", + "NEVER": "Nooit", + "DISABLE_FILE_DOWNLOAD": "Download uitschakelen", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Weet u zeker dat u de downloadknop voor bestanden wilt uitschakelen?

Kijkers kunnen nog steeds screenshots maken of een kopie van uw foto's opslaan met behulp van externe hulpmiddelen.

", + "MALICIOUS_CONTENT": "Bevat kwaadwillende inhoud", + "COPYRIGHT": "Schending van het auteursrecht van iemand die ik mag vertegenwoordigen", + "SHARED_USING": "Gedeeld via ", + "ENTE_IO": "ente.io", + "SHARING_REFERRAL_CODE": "Gebruik code {{referralCode}} om 10 GB gratis te krijgen", + "LIVE": "LIVE", + "DISABLE_PASSWORD": "Schakel cijfercode vergrendeling uit", + "DISABLE_PASSWORD_MESSAGE": "Weet u zeker dat u de cijfercode vergrendeling wilt uitschakelen?", + "PASSWORD_LOCK": "Cijfercode vergrendeling", + "LOCK": "Vergrendeling", + "DOWNLOAD_UPLOAD_LOGS": "Logboeken voor foutmeldingen", + "UPLOAD_FILES": "Bestand", + "UPLOAD_DIRS": "Map", + "UPLOAD_GOOGLE_TAKEOUT": "Google takeout", + "DEDUPLICATE_FILES": "Dubbele bestanden verwijderen", + "AUTHENTICATOR_SECTION": "Verificatie apparaat", + "NO_DUPLICATES_FOUND": "Je hebt geen dubbele bestanden die kunnen worden gewist", + "CLUB_BY_CAPTURE_TIME": "Samenvoegen op tijd", + "FILES": "Bestanden", + "EACH": "Elke", + "DEDUPLICATE_BASED_ON_SIZE": "De volgende bestanden zijn samengevoegd op basis van hun groottes. Controleer en verwijder items waarvan je denkt dat ze dubbel zijn", + "STOP_ALL_UPLOADS_MESSAGE": "Weet u zeker dat u wilt stoppen met alle uploads die worden uitgevoerd?", + "STOP_UPLOADS_HEADER": "Stoppen met uploaden?", + "YES_STOP_UPLOADS": "Ja, stop uploaden", + "STOP_DOWNLOADS_HEADER": "Downloaden stoppen?", + "YES_STOP_DOWNLOADS": "Ja, downloads stoppen", + "STOP_ALL_DOWNLOADS_MESSAGE": "Weet je zeker dat je wilt stoppen met alle downloads die worden uitgevoerd?", + "albums_one": "1 Album", + "albums_other": "{{count, number}} Albums", + "ALL_ALBUMS": "Alle albums", + "ALBUMS": "Albums", + "ALL_HIDDEN_ALBUMS": "Alle verborgen albums", + "HIDDEN_ALBUMS": "Verborgen albums", + "HIDDEN_ITEMS": "Verborgen bestanden", + "HIDDEN_ITEMS_SECTION_NAME": "Verborgen_items", + "ENTER_TWO_FACTOR_OTP": "Voer de 6-cijferige code van uw verificatie app in.", + "CREATE_ACCOUNT": "Account aanmaken", + "COPIED": "Gekopieerd", + "CANVAS_BLOCKED_TITLE": "Kan thumbnail niet genereren", + "CANVAS_BLOCKED_MESSAGE": "

Het lijkt erop dat uw browser geen toegang heeft tot canvas, die nodig is om thumbnails voor uw foto's te genereren

Schakel toegang tot het canvas van uw browser in, of bekijk onze desktop app

", + "WATCH_FOLDERS": "Monitor mappen", + "UPGRADE_NOW": "Nu upgraden", + "RENEW_NOW": "Nu verlengen", + "STORAGE": "Opslagruimte", + "USED": "gebruikt", + "YOU": "Jij", + "FAMILY": "Familie", + "FREE": "free", + "OF": "van", + "WATCHED_FOLDERS": "Gemonitorde mappen", + "NO_FOLDERS_ADDED": "Nog geen mappen toegevoegd!", + "FOLDERS_AUTOMATICALLY_MONITORED": "De mappen die u hier toevoegt worden automatisch gemonitord", + "UPLOAD_NEW_FILES_TO_ENTE": "Nieuwe bestanden uploaden naar ente", + "REMOVE_DELETED_FILES_FROM_ENTE": "Verwijderde bestanden van ente opruimen", + "ADD_FOLDER": "Map toevoegen", + "STOP_WATCHING": "Stop monitoren", + "STOP_WATCHING_FOLDER": "Stop monitoren van map?", + "STOP_WATCHING_DIALOG_MESSAGE": "Uw bestaande bestanden zullen niet worden verwijderd, maar ente stopt met het automatisch bijwerken van het gekoppelde ente album bij wijzigingen in deze map.", + "YES_STOP": "Ja, stop", + "MONTH_SHORT": "mo", + "YEAR": "jaar", + "FAMILY_PLAN": "Familie abonnement", + "DOWNLOAD_LOGS": "Logboek downloaden", + "DOWNLOAD_LOGS_MESSAGE": "

Dit zal logboeken downloaden, die u ons kunt e-mailen om te helpen bij het debuggen van uw probleem.

Houd er rekening mee dat bestandsnamen worden opgenomen om problemen met specifieke bestanden bij te houden.

", + "CHANGE_FOLDER": "Map wijzigen", + "TWO_MONTHS_FREE": "Krijg 2 maanden gratis op jaarlijkse abonnementen", + "GB": "GB", + "POPULAR": "Populair", + "FREE_PLAN_OPTION_LABEL": "Doorgaan met gratis account", + "FREE_PLAN_DESCRIPTION": "1 GB voor 1 jaar", + "CURRENT_USAGE": "Huidig gebruik is {{usage}}", + "WEAK_DEVICE": "De webbrowser die u gebruikt is niet krachtig genoeg om uw foto's te versleutelen. Probeer in te loggen op uw computer, of download de ente mobiel/desktop app.", + "DRAG_AND_DROP_HINT": "Of sleep en plaats in het ente venster", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Uw geüploade gegevens worden gepland voor verwijdering, en uw account zal permanent worden verwijderd.

Deze actie is onomkeerbaar.", + "AUTHENTICATE": "Verifiëren", + "UPLOADED_TO_SINGLE_COLLECTION": "Geüpload naar enkele collectie", + "UPLOADED_TO_SEPARATE_COLLECTIONS": "Geüpload naar verschillende collecties", + "NEVERMIND": "Laat maar", + "UPDATE_AVAILABLE": "Update beschikbaar", + "UPDATE_INSTALLABLE_MESSAGE": "Er staat een nieuwe versie van ente klaar om te worden geïnstalleerd.", + "INSTALL_NOW": "Nu installeren", + "INSTALL_ON_NEXT_LAUNCH": "Installeren bij volgende start", + "UPDATE_AVAILABLE_MESSAGE": "Er is een nieuwe versie van ente vrijgegeven, maar deze kan niet automatisch worden gedownload en geïnstalleerd.", + "DOWNLOAD_AND_INSTALL": "Downloaden en installeren", + "IGNORE_THIS_VERSION": "Negeer deze versie", + "TODAY": "Vandaag", + "YESTERDAY": "Gisteren", + "NAME_PLACEHOLDER": "Naam...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Kan geen albums maken uit bestand/map mix", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

Je hebt een mix van bestanden en mappen gesleept en laten vallen.

Geef ofwel alleen bestanden aan, of alleen mappen bij het selecteren van de optie om afzonderlijke albums te maken

", + "CHOSE_THEME": "Kies thema", + "ML_SEARCH": "ML zoeken (bèta)", + "ENABLE_ML_SEARCH_DESCRIPTION": "

Dit zal algoritmes op het apparaat inschakelen die zullen beginnen met het lokaal analyseren van uw geüploade foto's.

Voor het eerst na inloggen of het inschakelen van deze functie zal het alle afbeeldingen op het lokale apparaat downloaden om ze te analyseren. Schakel dit dus alleen in als je akkoord bent met gegevensverbruik en lokale verwerking van alle afbeeldingen in uw fotobibliotheek.

Als dit de eerste keer is dat uw dit inschakelt, vragen we u ook om toestemming om gegevens te verwerken.

", + "ML_MORE_DETAILS": "Meer details", + "ENABLE_FACE_SEARCH": "Zoeken op gezichten inschakelen", + "ENABLE_FACE_SEARCH_TITLE": "Zoeken op gezichten inschakelen?", + "ENABLE_FACE_SEARCH_DESCRIPTION": "

Als u zoeken op gezichten inschakelt, analyseert ente de gezichtsgeometrie uit uw foto's. Dit gebeurt op uw apparaat en alle gegenereerde biometrische gegevens worden end-to-end versleuteld.

Klik hier voor meer informatie over deze functie in ons privacybeleid

", + "DISABLE_BETA": "Bèta uitschakelen", + "DISABLE_FACE_SEARCH": "Zoeken op gezichten uitschakelen", + "DISABLE_FACE_SEARCH_TITLE": "Zoeken op gezichten uitschakelen?", + "DISABLE_FACE_SEARCH_DESCRIPTION": "

ente zal stoppen met het analyseren van de gezichtsgeometrie, en zal ML zoeken (beta) uitschakelen

U kan zoeken op gezichten opnieuw inschakelen wanneer u wilt, dus deze handeling is veilig.

", + "ADVANCED": "Geavanceerd", + "FACE_SEARCH_CONFIRMATION": "Ik begrijp het, en wil ente toestaan om gezichten te analyseren", + "LABS": "Lab's", + "YOURS": "jouw", + "PASSPHRASE_STRENGTH_WEAK": "Wachtwoord sterkte: Zwak", + "PASSPHRASE_STRENGTH_MODERATE": "Wachtwoord sterkte: Matig", + "PASSPHRASE_STRENGTH_STRONG": "Wachtwoord sterkte: Sterk", + "PREFERENCES": "Instellingen", + "LANGUAGE": "Taal", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Ongeldige export map", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

De export map die u heeft geselecteerd bestaat niet.

Selecteer een geldige map.

", + "SUBSCRIPTION_VERIFICATION_ERROR": "Abonnementsverificatie mislukt", + "STORAGE_UNITS": { + "B": "B", + "KB": "KB", + "MB": "MB", + "GB": "GB", + "TB": "TB" + }, + "AFTER_TIME": { + "HOUR": "na één uur", + "DAY": "na één dag", + "WEEK": "na één week", + "MONTH": "na één maand", + "YEAR": "na één jaar" + }, + "COPY_LINK": "Link kopiëren", + "DONE": "Voltooid", + "LINK_SHARE_TITLE": "Of deel een link", + "REMOVE_LINK": "Link verwijderen", + "CREATE_PUBLIC_SHARING": "Maak publieke link", + "PUBLIC_LINK_CREATED": "Publieke link aangemaakt", + "PUBLIC_LINK_ENABLED": "Publieke link ingeschakeld", + "COLLECT_PHOTOS": "Foto's verzamelen", + "PUBLIC_COLLECT_SUBTEXT": "Sta toe dat mensen met de link ook foto's kunnen toevoegen aan het gedeelde album.", + "STOP_EXPORT": "Stoppen", + "EXPORT_PROGRESS": "{{progress.success}} / {{progress.total}} bestanden geëxporteerd", + "MIGRATING_EXPORT": "Voorbereiden...", + "RENAMING_COLLECTION_FOLDERS": "Albumnamen hernoemen...", + "TRASHING_DELETED_FILES": "Verwijderde bestanden naar prullenbak...", + "TRASHING_DELETED_COLLECTIONS": "Verwijderde albums naar prullenbak...", + "EXPORT_NOTIFICATION": { + "START": "Exporteren begonnen", + "IN_PROGRESS": "Exporteren is al bezig", + "FINISH": "Exporteren voltooid", + "UP_TO_DATE": "Geen nieuwe bestanden om te exporteren" + }, + "CONTINUOUS_EXPORT": "Continue synchroniseren", + "TOTAL_ITEMS": "Totaal aantal bestanden", + "PENDING_ITEMS": "Bestanden in behandeling", + "EXPORT_STARTING": "Exporteren begonnen...", + "DELETE_ACCOUNT_REASON_LABEL": "Wat is de belangrijkste reden waarom je jouw account verwijdert?", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Kies een reden", + "DELETE_REASON": { + "MISSING_FEATURE": "Ik mis een belangrijke functie", + "BROKEN_BEHAVIOR": "De app of een bepaalde functie functioneert niet zoals ik verwacht", + "FOUND_ANOTHER_SERVICE": "Ik heb een andere dienst gevonden die me beter bevalt", + "NOT_LISTED": "Mijn reden wordt niet vermeld" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "We vinden het jammer je te zien gaan. Deel alsjeblieft je feedback om ons te helpen verbeteren.", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Feedback", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Ja, ik wil permanent mijn account inclusief alle gegevens verwijderen", + "CONFIRM_DELETE_ACCOUNT": "Account verwijderen bevestigen", + "FEEDBACK_REQUIRED": "Help ons alsjeblieft met deze informatie", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "Wat doet de andere dienst beter?", + "RECOVER_TWO_FACTOR": "Herstel tweestaps", + "at": "om", + "AUTH_NEXT": "volgende", + "AUTH_DOWNLOAD_MOBILE_APP": "Download onze mobiele app om uw geheimen te beheren", + "HIDDEN": "Verborgen", + "HIDE": "Verbergen", + "UNHIDE": "Zichtbaar maken", + "UNHIDE_TO_COLLECTION": "Zichtbaar maken in album", + "SORT_BY": "Sorteren op", + "NEWEST_FIRST": "Nieuwste eerst", + "OLDEST_FIRST": "Oudste eerst", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "Dit bestand kan niet worden bekeken in de app, klik hier om het origineel te downloaden", + "SELECT_COLLECTION": "Album selecteren", + "PIN_ALBUM": "Album bovenaan vastzetten", + "UNPIN_ALBUM": "Album losmaken", + "DOWNLOAD_COMPLETE": "Download compleet", + "DOWNLOADING_COLLECTION": "{{name}} downloaden", + "DOWNLOAD_FAILED": "Download mislukt", + "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} bestanden", + "CHRISTMAS": "Kerst", + "CHRISTMAS_EVE": "Kerstavond", + "NEW_YEAR": "Nieuwjaar", + "NEW_YEAR_EVE": "Oudjaarsavond", + "IMAGE": "Afbeelding", + "VIDEO": "Video", + "LIVE_PHOTO": "Live foto", + "CONVERT": "Converteren", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "Weet u zeker dat u de editor wilt afsluiten?", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Download uw bewerkte afbeelding of sla een kopie op in ente om uw wijzigingen te behouden.", + "BRIGHTNESS": "Helderheid", + "CONTRAST": "Contrast", + "SATURATION": "Saturatie", + "BLUR": "Vervagen", + "INVERT_COLORS": "Kleuren omkeren", + "ASPECT_RATIO": "Beeldverhouding", + "SQUARE": "Vierkant", + "ROTATE_LEFT": "Roteer links", + "ROTATE_RIGHT": "Roteer rechts", + "FLIP_VERTICALLY": "Verticaal spiegelen", + "FLIP_HORIZONTALLY": "Horizontaal spiegelen", + "DOWNLOAD_EDITED": "Download Bewerkt", + "SAVE_A_COPY_TO_ENTE": "Kopie in ente opslaan", + "RESTORE_ORIGINAL": "Origineel herstellen", + "TRANSFORM": "Transformeer", + "COLORS": "Kleuren", + "FLIP": "Omdraaien", + "ROTATION": "Draaiing", + "RESET": "Herstellen", + "PHOTO_EDITOR": "Fotobewerker", + "FASTER_UPLOAD": "Snellere uploads", + "FASTER_UPLOAD_DESCRIPTION": "Uploaden door nabije servers", + "MAGIC_SEARCH_STATUS": "Magische Zoekfunctie Status", + "INDEXED_ITEMS": "Geïndexeerde bestanden", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "Cache map", + "FREEHAND": "Losse hand", + "APPLY_CROP": "Bijsnijden toepassen", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Tenminste één transformatie of kleuraanpassing moet worden uitgevoerd voordat u opslaat.", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/pt-BR/translation.json b/web/apps/cast/public/locales/pt-BR/translation.json new file mode 100644 index 0000000000..0da001742f --- /dev/null +++ b/web/apps/cast/public/locales/pt-BR/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Backups privados
para as suas memórias
", + "HERO_SLIDE_1": "Criptografia de ponta a ponta por padrão", + "HERO_SLIDE_2_TITLE": "
Armazenado com segurança
em um abrigo avançado
", + "HERO_SLIDE_2": "Feito para ter logenvidade", + "HERO_SLIDE_3_TITLE": "
Disponível
em qualquer lugar
", + "HERO_SLIDE_3": "Android, iOS, Web, Desktop", + "LOGIN": "Entrar", + "SIGN_UP": "Registrar", + "NEW_USER": "Novo no ente", + "EXISTING_USER": "Usuário existente", + "ENTER_NAME": "Insira o nome", + "PUBLIC_UPLOADER_NAME_MESSAGE": "Adicione um nome para que os seus amigos saibam a quem agradecer por estas ótimas fotos!", + "ENTER_EMAIL": "Insira o endereço de e-mail", + "EMAIL_ERROR": "Inserir um endereço de e-mail válido", + "REQUIRED": "Obrigatório", + "EMAIL_SENT": "Código de verificação enviado para {{email}}", + "CHECK_INBOX": "Verifique a sua caixa de entrada (e spam) para concluir a verificação", + "ENTER_OTT": "Código de verificação", + "RESEND_MAIL": "Reenviar código", + "VERIFY": "Verificar", + "UNKNOWN_ERROR": "Ocorreu um erro. Tente novamente", + "INVALID_CODE": "Código de verificação inválido", + "EXPIRED_CODE": "O seu código de verificação expirou", + "SENDING": "Enviando...", + "SENT": "Enviado!", + "PASSWORD": "Senha", + "LINK_PASSWORD": "Insira a senha para desbloquear o álbum", + "RETURN_PASSPHRASE_HINT": "Senha", + "SET_PASSPHRASE": "Definir senha", + "VERIFY_PASSPHRASE": "Iniciar sessão", + "INCORRECT_PASSPHRASE": "Palavra-passe incorreta", + "ENTER_ENC_PASSPHRASE": "Por favor, digite uma senha que podemos usar para criptografar seus dados", + "PASSPHRASE_DISCLAIMER": "Não armazenamos sua senha, portanto, se você esquecê-la, não poderemos ajudarna recuperação de seus dados sem uma chave de recuperação.", + "WELCOME_TO_ENTE_HEADING": "Bem-vindo ao ", + "WELCOME_TO_ENTE_SUBHEADING": "Armazenamento criptografado de ponta a ponta de fotos e compartilhamento", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "Onde suas melhores fotos vivem", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Gerando chaves de criptografia...", + "PASSPHRASE_HINT": "Senha", + "CONFIRM_PASSPHRASE": "Confirmar senha", + "REFERRAL_CODE_HINT": "Como você ouviu sobre o Ente? (opcional)", + "REFERRAL_INFO": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!", + "PASSPHRASE_MATCH_ERROR": "As senhas não coincidem", + "CREATE_COLLECTION": "Novo álbum", + "ENTER_ALBUM_NAME": "Nome do álbum", + "CLOSE_OPTION": "Fechar (Esc)", + "ENTER_FILE_NAME": "Nome do arquivo", + "CLOSE": "Fechar", + "NO": "Não", + "NOTHING_HERE": "Nada para ver aqui! 👀", + "UPLOAD": "Enviar", + "IMPORT": "Importar", + "ADD_PHOTOS": "Adicionar fotos", + "ADD_MORE_PHOTOS": "Adicionar mais fotos", + "add_photos_one": "Adicionar item", + "add_photos_other": "Adicionar {{count, number}} itens", + "SELECT_PHOTOS": "Selecionar fotos", + "FILE_UPLOAD": "Envio de Arquivo", + "UPLOAD_STAGE_MESSAGE": { + "0": "Preparando para enviar", + "1": "Lendo arquivos de metadados do google", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} metadados dos arquivos extraídos", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} arquivos processados", + "4": "Cancelando envios restante", + "5": "Backup concluído" + }, + "FILE_NOT_UPLOADED_LIST": "Os seguintes arquivos não foram enviados", + "SUBSCRIPTION_EXPIRED": "Assinatura expirada", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Sua assinatura expirou, por favor renove-a", + "STORAGE_QUOTA_EXCEEDED": "Limite de armazenamento excedido", + "INITIAL_LOAD_DELAY_WARNING": "Primeiro carregamento pode levar algum tempo", + "USER_DOES_NOT_EXIST": "Desculpe, não foi possível encontrar um usuário com este e-mail", + "NO_ACCOUNT": "Não possui uma conta", + "ACCOUNT_EXISTS": "Já possui uma conta", + "CREATE": "Criar", + "DOWNLOAD": "Baixar", + "DOWNLOAD_OPTION": "Baixar (D)", + "DOWNLOAD_FAVORITES": "Baixar favoritos", + "DOWNLOAD_UNCATEGORIZED": "Baixar não categorizado", + "DOWNLOAD_HIDDEN_ITEMS": "Baixar itens ocultos", + "COPY_OPTION": "Copiar como PNG (Ctrl/Cmd - C)", + "TOGGLE_FULLSCREEN": "Mudar para tela cheia (F)", + "ZOOM_IN_OUT": "Ampliar/Reduzir", + "PREVIOUS": "Anterior (←)", + "NEXT": "Próximo (→)", + "TITLE_PHOTOS": "Ente Fotos", + "TITLE_ALBUMS": "Ente Fotos", + "TITLE_AUTH": "Ente Auth", + "UPLOAD_FIRST_PHOTO": "Envie sua primeira foto", + "IMPORT_YOUR_FOLDERS": "Importar suas pastas", + "UPLOAD_DROPZONE_MESSAGE": "Arraste para salvar seus arquivos", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Arraste para adicionar pasta monitorada", + "TRASH_FILES_TITLE": "Excluir arquivos?", + "TRASH_FILE_TITLE": "Excluir arquivo?", + "DELETE_FILES_TITLE": "Excluir imediatamente?", + "DELETE_FILES_MESSAGE": "Os arquivos selecionados serão excluídos permanentemente da sua conta ente.", + "DELETE": "Excluir", + "DELETE_OPTION": "Excluir (DEL)", + "FAVORITE_OPTION": "Favorito (L)", + "UNFAVORITE_OPTION": "Remover Favorito (L)", + "MULTI_FOLDER_UPLOAD": "Várias pastas detectadas", + "UPLOAD_STRATEGY_CHOICE": "Gostaria de enviá-los para", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Um único álbum", + "OR": "ou", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Álbuns separados", + "SESSION_EXPIRED_MESSAGE": "A sua sessão expirou. Por favor inicie sessão novamente para continuar", + "SESSION_EXPIRED": "Sessão expirada", + "PASSWORD_GENERATION_FAILED": "Seu navegador foi incapaz de gerar uma chave forte que atende aos padrões de criptografia, por favor, tente usar o aplicativo móvel ou outro navegador", + "CHANGE_PASSWORD": "Alterar senha", + "GO_BACK": "Voltar", + "RECOVERY_KEY": "Chave de recuperação", + "SAVE_LATER": "Fazer isso mais tarde", + "SAVE": "Salvar Chave", + "RECOVERY_KEY_DESCRIPTION": "Caso você esqueça sua senha, a única maneira de recuperar seus dados é com essa chave.", + "RECOVER_KEY_GENERATION_FAILED": "Não foi possível gerar o código de recuperação, tente novamente", + "KEY_NOT_STORED_DISCLAIMER": "Não armazenamos essa chave, por favor, salve essa chave de palavras em um lugar seguro", + "FORGOT_PASSWORD": "Esqueci a senha", + "RECOVER_ACCOUNT": "Recuperar conta", + "RECOVERY_KEY_HINT": "Chave de recuperação", + "RECOVER": "Recuperar", + "NO_RECOVERY_KEY": "Não possui a chave de recuperação?", + "INCORRECT_RECOVERY_KEY": "Chave de recuperação incorreta", + "SORRY": "Desculpe", + "NO_RECOVERY_KEY_MESSAGE": "Devido à natureza do nosso protocolo de criptografia de ponta a ponta, seus dados não podem ser descriptografados sem sua senha ou chave de recuperação", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Por favor, envie um e-mail para {{emailID}} a partir do seu endereço de e-mail registrado", + "CONTACT_SUPPORT": "Falar com o suporte", + "REQUEST_FEATURE": "Solicitar Funcionalidade", + "SUPPORT": "Suporte", + "CONFIRM": "Confirmar", + "CANCEL": "Cancelar", + "LOGOUT": "Encerrar sessão", + "DELETE_ACCOUNT": "Excluir conta", + "DELETE_ACCOUNT_MESSAGE": "

Por favor, envie um e-mail para {{emailID}} a partir do seu endereço de e-mail registrado.

Seu pedido será processado dentro de 72 horas.

", + "LOGOUT_MESSAGE": "Você tem certeza que deseja encerrar a sessão?", + "CHANGE_EMAIL": "Mudar e-mail", + "OK": "Aceitar", + "SUCCESS": "Bem-sucedido", + "ERROR": "Erro", + "MESSAGE": "Mensagem", + "INSTALL_MOBILE_APP": "Instale nosso aplicativo Android ou iOS para fazer backup automático de todas as suas fotos", + "DOWNLOAD_APP_MESSAGE": "Desculpe, esta operação só é suportada em nosso aplicativo para computador", + "DOWNLOAD_APP": "Baixar aplicativo para computador", + "EXPORT": "Exportar dados", + "SUBSCRIPTION": "Assinatura", + "SUBSCRIBE": "Assinar", + "MANAGEMENT_PORTAL": "Gerenciar métodos de pagamento", + "MANAGE_FAMILY_PORTAL": "Gerenciar Família", + "LEAVE_FAMILY_PLAN": "Sair do plano familiar", + "LEAVE": "Sair", + "LEAVE_FAMILY_CONFIRM": "Tem certeza que deseja sair do plano familiar?", + "CHOOSE_PLAN": "Escolha seu plano", + "MANAGE_PLAN": "Gerenciar sua assinatura", + "ACTIVE": "Ativo", + "OFFLINE_MSG": "Você está offline, memórias em cache estão sendo mostradas", + "FREE_SUBSCRIPTION_INFO": "Você está no plano gratuito que expira em {{date, dateTime}}", + "FAMILY_SUBSCRIPTION_INFO": "Você está em um plano familiar gerenciado por", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Renovações em {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "Termina em {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "Sua assinatura será cancelada em {{date, dateTime}}", + "ADD_ON_AVAILABLE_TILL": "Seu complemento {{storage, string}} é válido até o dia {{date, dateTime}}", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "Você excedeu sua cota de armazenamento, por favor atualize", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

Recebemos o seu pagamento

Sua assinatura é válida até {{date, dateTime}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "Sua compra foi cancelada, por favor, tente novamente se quiser assinar", + "SUBSCRIPTION_PURCHASE_FAILED": "Falha na compra de assinatura, tente novamente", + "SUBSCRIPTION_UPDATE_FAILED": "Falha ao atualizar assinatura, tente novamente", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Desculpe-nos, o pagamento falhou quando tentamos cobrar o seu cartão, por favor atualize seu método de pagamento e tente novamente", + "STRIPE_AUTHENTICATION_FAILED": "Não foi possível autenticar seu método de pagamento. Por favor, escolha outro método de pagamento e tente novamente", + "UPDATE_PAYMENT_METHOD": "Atualizar forma de pagamento", + "MONTHLY": "Mensal", + "YEARLY": "Anual", + "UPDATE_SUBSCRIPTION_MESSAGE": "Tem certeza que deseja trocar de plano?", + "UPDATE_SUBSCRIPTION": "Mudar de plano", + "CANCEL_SUBSCRIPTION": "Cancelar assinatura", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Todos os seus dados serão excluídos dos nossos servidores no final deste período de cobrança.

Você tem certeza que deseja cancelar sua assinatura?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Tem certeza que deseja cancelar sua assinatura?

", + "SUBSCRIPTION_CANCEL_FAILED": "Falha ao cancelar a assinatura", + "SUBSCRIPTION_CANCEL_SUCCESS": "Assinatura cancelada com sucesso", + "REACTIVATE_SUBSCRIPTION": "Reativar assinatura", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Uma vez reativado, você será cobrado em {{date, dateTime}}", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Assinatura ativada com sucesso ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Falha ao reativar as renovações de assinaturas", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Obrigado", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Cancelar assinatura móvel", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Por favor, cancele sua assinatura do aplicativo móvel para ativar uma assinatura aqui", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Entre em contato com {{emailID}} para gerenciar sua assinatura", + "RENAME": "Renomear", + "RENAME_FILE": "Renomear arquivo", + "RENAME_COLLECTION": "Renomear álbum", + "DELETE_COLLECTION_TITLE": "Excluir álbum?", + "DELETE_COLLECTION": "Excluir álbum", + "DELETE_COLLECTION_MESSAGE": "Também excluir as fotos (e vídeos) presentes neste álbum de todos os outros álbuns dos quais eles fazem parte?", + "DELETE_PHOTOS": "Excluir fotos", + "KEEP_PHOTOS": "Manter fotos", + "SHARE": "Compartilhar", + "SHARE_COLLECTION": "Compartilhar álbum", + "SHAREES": "Compartilhado com", + "SHARE_WITH_SELF": "Você não pode compartilhar consigo mesmo", + "ALREADY_SHARED": "Ops, você já está compartilhando isso com {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Álbum compartilhado não permitido", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Compartilhamento está desabilitado para contas gratuitas", + "DOWNLOAD_COLLECTION": "Baixar álbum", + "DOWNLOAD_COLLECTION_MESSAGE": "

Tem certeza que deseja baixar o álbum completo?

Todos os arquivos serão colocados na fila para baixar sequencialmente

", + "CREATE_ALBUM_FAILED": "Falha ao criar álbum, por favor tente novamente", + "SEARCH": "Pesquisar", + "SEARCH_RESULTS": "Resultados de pesquisa", + "NO_RESULTS": "Nenhum resultado encontrado", + "SEARCH_HINT": "Pesquisar por álbuns, datas, descrições, ...", + "SEARCH_TYPE": { + "COLLECTION": "Álbum", + "LOCATION": "Local", + "CITY": "Local", + "DATE": "Data", + "FILE_NAME": "Nome do arquivo", + "THING": "Conteúdo", + "FILE_CAPTION": "Descrição", + "FILE_TYPE": "Tipo de arquivo", + "CLIP": "Mágica" + }, + "photos_count_zero": "Sem memórias", + "photos_count_one": "1 memória", + "photos_count_other": "{{count, number}} memórias", + "TERMS_AND_CONDITIONS": "Eu concordo com os termos e a política de privacidade", + "ADD_TO_COLLECTION": "Adicionar ao álbum", + "SELECTED": "selecionado", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Este vídeo não pode ser reproduzido no seu navegador", + "PEOPLE": "Pessoas", + "INDEXING_SCHEDULED": "Indexação está programada...", + "ANALYZING_PHOTOS": "Indexando fotos ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", + "INDEXING_PEOPLE": "Indexando pessoas em {{indexStatus.nSyncedFiles,number}} fotos...", + "INDEXING_DONE": "Foram indexadas {{indexStatus.nSyncedFiles,number}} fotos", + "UNIDENTIFIED_FACES": "rostos não identificados", + "OBJECTS": "objetos", + "TEXT": "texto", + "INFO": "Informação ", + "INFO_OPTION": "Informação (I)", + "FILE_NAME": "Nome do arquivo", + "CAPTION_PLACEHOLDER": "Adicionar uma descrição", + "LOCATION": "Local", + "SHOW_ON_MAP": "Ver no OpenStreetMap", + "MAP": "Mapa", + "MAP_SETTINGS": "Ajustes do mapa", + "ENABLE_MAPS": "Habilitar mapa?", + "ENABLE_MAP": "Habilitar mapa", + "DISABLE_MAPS": "Desativar Mapas?", + "ENABLE_MAP_DESCRIPTION": "Isto mostrará suas fotos em um mapa do mundo.

Este mapa é hospedado pelo OpenStreetMap , e os exatos locais de suas fotos nunca são compartilhados.

Você pode desativar esse recurso a qualquer momento nas Configurações.

", + "DISABLE_MAP_DESCRIPTION": "

Isto irá desativar a exibição de suas fotos em um mapa mundial.

Você pode ativar este recurso a qualquer momento nas Configurações.

", + "DISABLE_MAP": "Desabilitar mapa", + "DETAILS": "Detalhes", + "VIEW_EXIF": "Ver todos os dados EXIF", + "NO_EXIF": "Sem dados EXIF", + "EXIF": "EXIF", + "ISO": "ISO", + "TWO_FACTOR": "Dois fatores", + "TWO_FACTOR_AUTHENTICATION": "Autenticação de dois fatores", + "TWO_FACTOR_QR_INSTRUCTION": "Digitalize o código QR abaixo com o seu aplicativo de autenticador favorito", + "ENTER_CODE_MANUALLY": "Inserir código manualmente", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Por favor, insira este código no seu aplicativo autenticador favorito", + "SCAN_QR_CODE": "Em vez disso, escaneie um Código QR", + "ENABLE_TWO_FACTOR": "Ativar autenticação de dois fatores", + "ENABLE": "Habilitar", + "LOST_DEVICE": "Dispositivo de dois fatores perdido", + "INCORRECT_CODE": "Código incorreto", + "TWO_FACTOR_INFO": "Adicione uma camada adicional de segurança, exigindo mais do que seu e-mail e senha para entrar na sua conta", + "DISABLE_TWO_FACTOR_LABEL": "Desativar autenticação de dois fatores", + "UPDATE_TWO_FACTOR_LABEL": "Atualize seu dispositivo autenticador", + "DISABLE": "Desativar", + "RECONFIGURE": "Reconfigurar", + "UPDATE_TWO_FACTOR": "Atualizar dois fatores", + "UPDATE_TWO_FACTOR_MESSAGE": "Continuar adiante anulará qualquer autenticador configurado anteriormente", + "UPDATE": "Atualização", + "DISABLE_TWO_FACTOR": "Desativar autenticação de dois fatores", + "DISABLE_TWO_FACTOR_MESSAGE": "Você tem certeza de que deseja desativar a autenticação de dois fatores", + "TWO_FACTOR_DISABLE_FAILED": "Não foi possível desativar dois fatores, por favor tente novamente", + "EXPORT_DATA": "Exportar dados", + "SELECT_FOLDER": "Selecione a pasta", + "DESTINATION": "Destino", + "START": "Iniciar", + "LAST_EXPORT_TIME": "Data da última exportação", + "EXPORT_AGAIN": "Resincronizar", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Armazenamento local não acessível", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Seu navegador ou uma extensão está bloqueando o ente de salvar os dados no armazenamento local. Por favor, tente carregar esta página depois de alternar o modo de navegação.", + "SEND_OTT": "Enviar códigos OTP", + "EMAIl_ALREADY_OWNED": "Este e-mail já está em uso", + "ETAGS_BLOCKED": "

Não foi possível fazer o envio dos seguintes arquivos devido à configuração do seu navegador.

Por favor, desative quaisquer complementos que possam estar impedindo o ente de utilizar eTags para enviar arquivos grandes, ou utilize nosso aplicativo para computador para uma experiência de importação mais confiável.

", + "SKIPPED_VIDEOS_INFO": "

Atualmente, não oferecemos suporte para adicionar vídeos através de links públicos.

Para compartilhar vídeos, por favor, faça cadastro no ente e compartilhe com os destinatários pretendidos usando seus e-mails.

", + "LIVE_PHOTOS_DETECTED": "Os arquivos de foto e vídeo das suas Fotos em Movimento foram mesclados em um único arquivo", + "RETRY_FAILED": "Repetir envios que falharam", + "FAILED_UPLOADS": "Envios com falhas ", + "SKIPPED_FILES": "Envios ignorados", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Falha ao gerar miniaturas", + "UNSUPPORTED_FILES": "Arquivos não suportados", + "SUCCESSFUL_UPLOADS": "Envios bem sucedidos", + "SKIPPED_INFO": "Ignorar estes como existem arquivos com nomes correspondentes no mesmo álbum", + "UNSUPPORTED_INFO": "ente ainda não suporta estes formatos de arquivo", + "BLOCKED_UPLOADS": "Envios bloqueados", + "SKIPPED_VIDEOS": "Vídeos ignorados", + "INPROGRESS_METADATA_EXTRACTION": "Em andamento", + "INPROGRESS_UPLOADS": "Envios em andamento", + "TOO_LARGE_UPLOADS": "Arquivos grandes", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Armazenamento insuficiente", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Estes arquivos não foram carregados pois excedem o tamanho máximo para seu plano de armazenamento", + "TOO_LARGE_INFO": "Estes arquivos não foram carregados pois excedem nosso limite máximo de tamanho de arquivo", + "THUMBNAIL_GENERATION_FAILED_INFO": "Estes arquivos foram enviados, mas infelizmente não conseguimos gerar as miniaturas para eles.", + "UPLOAD_TO_COLLECTION": "Enviar para o álbum", + "UNCATEGORIZED": "Sem categoria", + "ARCHIVE": "Arquivar", + "FAVORITES": "Favoritos", + "ARCHIVE_COLLECTION": "Arquivar álbum", + "ARCHIVE_SECTION_NAME": "Arquivar", + "ALL_SECTION_NAME": "Todos", + "MOVE_TO_COLLECTION": "Mover para álbum", + "UNARCHIVE": "Desarquivar", + "UNARCHIVE_COLLECTION": "Desarquivar álbum", + "HIDE_COLLECTION": "Ocultar álbum", + "UNHIDE_COLLECTION": "Reexibir álbum", + "MOVE": "Mover", + "ADD": "Adicionar", + "REMOVE": "Remover", + "YES_REMOVE": "Sim, remover", + "REMOVE_FROM_COLLECTION": "Remover do álbum", + "TRASH": "Lixeira", + "MOVE_TO_TRASH": "Mover para a lixeira", + "TRASH_FILES_MESSAGE": "Os itens selecionados serão excluídos de todos os álbuns e movidos para o lixo.", + "TRASH_FILE_MESSAGE": "Os itens selecionados serão excluídos de todos os álbuns e movidos para o lixo.", + "DELETE_PERMANENTLY": "Excluir permanentemente", + "RESTORE": "Restaurar", + "RESTORE_TO_COLLECTION": "Restaurar para álbum", + "EMPTY_TRASH": "Esvaziar a lixeira", + "EMPTY_TRASH_TITLE": "Esvaziar a lixeira?", + "EMPTY_TRASH_MESSAGE": "Estes arquivos serão excluídos permanentemente da sua conta do ente.", + "LEAVE_SHARED_ALBUM": "Sim, sair", + "LEAVE_ALBUM": "Sair do álbum", + "LEAVE_SHARED_ALBUM_TITLE": "Sair do álbum compartilhado?", + "LEAVE_SHARED_ALBUM_MESSAGE": "Você deixará o álbum e ele deixará de ser visível para você.", + "NOT_FILE_OWNER": "Você não pode excluir arquivos em um álbum compartilhado", + "CONFIRM_SELF_REMOVE_MESSAGE": "Os itens selecionados serão removidos deste álbum. Itens que estão somente neste álbum serão movidos a aba Sem Categoria.", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Alguns dos itens que você está removendo foram adicionados por outras pessoas, e você perderá o acesso a eles.", + "SORT_BY_CREATION_TIME_ASCENDING": "Mais antigo", + "SORT_BY_UPDATION_TIME_DESCENDING": "Última atualização", + "SORT_BY_NAME": "Nome", + "COMPRESS_THUMBNAILS": "Compactar miniaturas", + "THUMBNAIL_REPLACED": "Miniaturas compactadas", + "FIX_THUMBNAIL": "Compactar", + "FIX_THUMBNAIL_LATER": "Compactar depois", + "REPLACE_THUMBNAIL_NOT_STARTED": "Algumas miniaturas de seus vídeos podem ser compactadas para economizar espaço. Você gostaria de compactá-las?", + "REPLACE_THUMBNAIL_COMPLETED": "Miniaturas compactadas com sucesso", + "REPLACE_THUMBNAIL_NOOP": "Você não tem nenhuma miniatura que possa ser compactadas mais", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "Não foi possível compactar algumas das suas miniaturas, por favor tente novamente", + "FIX_CREATION_TIME": "Corrigir hora", + "FIX_CREATION_TIME_IN_PROGRESS": "Corrigindo horário", + "CREATION_TIME_UPDATED": "Hora do arquivo atualizado", + "UPDATE_CREATION_TIME_NOT_STARTED": "Selecione a carteira que você deseja usar", + "UPDATE_CREATION_TIME_COMPLETED": "Todos os arquivos atualizados com sucesso", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "A atualização do horário falhou para alguns arquivos, por favor, tente novamente", + "CAPTION_CHARACTER_LIMIT": "5000 caracteres no máximo", + "DATE_TIME_ORIGINAL": "Data e Hora Original", + "DATE_TIME_DIGITIZED": "Data e Hora Digitalizada", + "METADATA_DATE": "Data de Metadados", + "CUSTOM_TIME": "Tempo personalizado", + "REOPEN_PLAN_SELECTOR_MODAL": "Reabrir planos", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "Falha ao abrir planos", + "INSTALL": "Instalar", + "SHARING_DETAILS": "Detalhes de compartilhamento", + "MODIFY_SHARING": "Modificar compartilhamento", + "ADD_COLLABORATORS": "Adicionar colaboradores", + "ADD_NEW_EMAIL": "Adicionar um novo email", + "shared_with_people_zero": "Compartilhar com pessoas específicas", + "shared_with_people_one": "Compartilhado com 1 pessoa", + "shared_with_people_other": "Compartilhado com {{count, number}} pessoas", + "participants_zero": "Nenhum participante", + "participants_one": "1 participante", + "participants_other": "{{count, number}} participantes", + "ADD_VIEWERS": "Adicionar visualizações", + "PARTICIPANTS": "Participantes", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} Não poderá adicionar mais fotos a este álbum

Eles ainda poderão remover as fotos existentes adicionadas por eles

", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} poderá adicionar fotos ao álbum", + "CONVERT_TO_VIEWER": "Sim, converter para visualizador", + "CONVERT_TO_COLLABORATOR": "Sim, converter para colaborador", + "CHANGE_PERMISSION": "Alterar permissões?", + "REMOVE_PARTICIPANT": "Remover?", + "CONFIRM_REMOVE": "Sim, remover", + "MANAGE": "Gerenciar", + "ADDED_AS": "Adicionado como", + "COLLABORATOR_RIGHTS": "Os colaboradores podem adicionar fotos e vídeos ao álbum compartilhado", + "REMOVE_PARTICIPANT_HEAD": "Remover participante", + "OWNER": "Proprietário", + "COLLABORATORS": "Colaboradores", + "ADD_MORE": "Adicionar mais", + "VIEWERS": "Visualizações", + "OR_ADD_EXISTING": "Ou escolha um existente", + "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} será removido deste álbum compartilhado

Quaisquer fotos adicionadas por eles também serão removidas do álbum

", + "NOT_FOUND": "404 Página não encontrada", + "LINK_EXPIRED": "Link expirado", + "LINK_EXPIRED_MESSAGE": "Este link expirou ou foi desativado!", + "MANAGE_LINK": "Gerenciar link", + "LINK_TOO_MANY_REQUESTS": "Desculpe, este álbum foi visualizado em muitos dispositivos!", + "FILE_DOWNLOAD": "Permitir transferências", + "LINK_PASSWORD_LOCK": "Bloqueio de senha", + "PUBLIC_COLLECT": "Permitir adicionar fotos", + "LINK_DEVICE_LIMIT": "Limite de dispositivos", + "NO_DEVICE_LIMIT": "Nenhum", + "LINK_EXPIRY": "Expiração do link", + "NEVER": "Nunca", + "DISABLE_FILE_DOWNLOAD": "Desabilitar transferência", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Tem certeza de que deseja desativar o botão de download para arquivos?

Os visualizadores ainda podem capturar imagens da tela ou salvar uma cópia de suas fotos usando ferramentas externas.

", + "MALICIOUS_CONTENT": "Contém conteúdo malicioso", + "COPYRIGHT": "Viola os direitos autorais de alguém que estou autorizado a representar", + "SHARED_USING": "Compartilhar usando ", + "ENTE_IO": "ente.io", + "SHARING_REFERRAL_CODE": "Use o código {{referralCode}} para obter 10 GB de graça", + "LIVE": "AO VIVO", + "DISABLE_PASSWORD": "Desativar bloqueio por senha", + "DISABLE_PASSWORD_MESSAGE": "Tem certeza que deseja desativar o bloqueio por senha?", + "PASSWORD_LOCK": "Bloqueio de senha", + "LOCK": "Bloquear", + "DOWNLOAD_UPLOAD_LOGS": "Logs de depuração", + "UPLOAD_FILES": "Arquivo", + "UPLOAD_DIRS": "Pasta", + "UPLOAD_GOOGLE_TAKEOUT": "Google Takeout", + "DEDUPLICATE_FILES": "Arquivos Deduplicados", + "AUTHENTICATOR_SECTION": "Autenticação", + "NO_DUPLICATES_FOUND": "Você não tem arquivos duplicados que possam ser limpos", + "CLUB_BY_CAPTURE_TIME": "Agrupar por tempo de captura", + "FILES": "Arquivos", + "EACH": "Cada", + "DEDUPLICATE_BASED_ON_SIZE": "Os seguintes arquivos foram listados com base em seus tamanhos, por favor, reveja e exclua os itens que você acredita que são duplicados", + "STOP_ALL_UPLOADS_MESSAGE": "Tem certeza que deseja parar todos os envios em andamento?", + "STOP_UPLOADS_HEADER": "Parar envios?", + "YES_STOP_UPLOADS": "Sim, parar envios", + "STOP_DOWNLOADS_HEADER": "Parar transferências?", + "YES_STOP_DOWNLOADS": "Sim, parar transferências", + "STOP_ALL_DOWNLOADS_MESSAGE": "Tem certeza que deseja parar todos as transferências em andamento?", + "albums_one": "1 Álbum", + "albums_other": "{{count, number}} Álbuns", + "ALL_ALBUMS": "Todos os álbuns", + "ALBUMS": "Álbuns", + "ALL_HIDDEN_ALBUMS": "Todos os álbuns ocultos", + "HIDDEN_ALBUMS": "Álbuns ocultos", + "HIDDEN_ITEMS": "Itens ocultos", + "HIDDEN_ITEMS_SECTION_NAME": "Itens_ocultos", + "ENTER_TWO_FACTOR_OTP": "Digite o código de 6 dígitos de\nseu aplicativo autenticador.", + "CREATE_ACCOUNT": "Criar uma conta", + "COPIED": "Copiado", + "CANVAS_BLOCKED_TITLE": "Não foi possível gerar miniatura", + "CANVAS_BLOCKED_MESSAGE": "

Parece que o seu navegador desativou o acesso à tela que é necessário para gerar miniaturas para as suas fotos

Por favor, habilite o acesso à tela do seu navegador, ou veja nosso aplicativo para computador

", + "WATCH_FOLDERS": "Pastas monitoradas", + "UPGRADE_NOW": "Aprimorar agora", + "RENEW_NOW": "Renovar agora", + "STORAGE": "Armazenamento", + "USED": "usado", + "YOU": "Você", + "FAMILY": "Família", + "FREE": "grátis", + "OF": "de", + "WATCHED_FOLDERS": "Pastas monitoradas", + "NO_FOLDERS_ADDED": "Nenhuma pasta adicionada ainda!", + "FOLDERS_AUTOMATICALLY_MONITORED": "As pastas que você adicionar aqui serão monitoradas automaticamente", + "UPLOAD_NEW_FILES_TO_ENTE": "Enviar novos arquivos para o ente", + "REMOVE_DELETED_FILES_FROM_ENTE": "Remover arquivos excluídos do ente", + "ADD_FOLDER": "Adicionar pasta", + "STOP_WATCHING": "Parar de acompanhar", + "STOP_WATCHING_FOLDER": "Parar de acompanhar a pasta?", + "STOP_WATCHING_DIALOG_MESSAGE": "Seus arquivos existentes não serão excluídos, mas ente irá parar de atualizar automaticamente o álbum associado em alterações nesta pasta.", + "YES_STOP": "Sim, parar", + "MONTH_SHORT": "mês", + "YEAR": "ano", + "FAMILY_PLAN": "Plano familiar", + "DOWNLOAD_LOGS": "Baixar logs", + "DOWNLOAD_LOGS_MESSAGE": "

Isto irá baixar os logs de depuração, que você pode enviar para nós para ajudar a depurar seu problema.

Por favor, note que os nomes de arquivos serão incluídos para ajudar a rastrear problemas com arquivos específicos.

", + "CHANGE_FOLDER": "Alterar pasta", + "TWO_MONTHS_FREE": "Obtenha 2 meses gratuitos em planos anuais", + "GB": "GB", + "POPULAR": "Popular", + "FREE_PLAN_OPTION_LABEL": "Continuar com teste gratuito", + "FREE_PLAN_DESCRIPTION": "1 GB por 1 ano", + "CURRENT_USAGE": "O uso atual é {{usage}}", + "WEAK_DEVICE": "O navegador da web que você está usando não é poderoso o suficiente para criptografar suas fotos. Por favor, tente entrar para o ente no computador ou baixe o aplicativo móvel.", + "DRAG_AND_DROP_HINT": "Ou arraste e solte na janela ente", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "Seus dados enviados serão agendados para exclusão e sua conta será excluída permanentemente.

Essa ação não é reversível.", + "AUTHENTICATE": "Autenticar", + "UPLOADED_TO_SINGLE_COLLECTION": "Enviado para coleção única", + "UPLOADED_TO_SEPARATE_COLLECTIONS": "Enviada para separar coleções", + "NEVERMIND": "Esquecer", + "UPDATE_AVAILABLE": "Atualização disponível", + "UPDATE_INSTALLABLE_MESSAGE": "Uma nova versão do ente está pronta para ser instalada.", + "INSTALL_NOW": "Instalar agora", + "INSTALL_ON_NEXT_LAUNCH": "Instalar na próxima inicialização", + "UPDATE_AVAILABLE_MESSAGE": "Uma nova versão do ente foi lançada, mas não pode ser baixada e instalada automaticamente.", + "DOWNLOAD_AND_INSTALL": "Baixar e instalar", + "IGNORE_THIS_VERSION": "Ignorar esta versão", + "TODAY": "Hoje", + "YESTERDAY": "Ontem", + "NAME_PLACEHOLDER": "Nome...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Não foi possível criar álbuns a partir da mistura de arquivos/pastas", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

Você arrastou e deixou uma mistura de arquivos e pastas.

Por favor, forneça apenas arquivos ou apenas pastas ao selecionar a opção para criar álbuns separados

", + "CHOSE_THEME": "Escolher tema", + "ML_SEARCH": "Reconhecimento facial", + "ENABLE_ML_SEARCH_DESCRIPTION": "

Isso permitirá aprendizado de máquina no dispositivo e busca facial, iniciando a análise de suas fotos enviadas localmente.

Na primeira execução após o login ou habilitação desta funcionalidade, será feito o download de todas as imagens no dispositivo local para análise. Portanto, ative isso apenas se estiver confortável com o consumo de largura de banda e processamento local de todas as imagens em sua biblioteca de fotos.

Se esta for a primeira vez que você está habilitando isso, também solicitaremos sua permissão para processar dados faciais.

", + "ML_MORE_DETAILS": "Mais detalhes", + "ENABLE_FACE_SEARCH": "Habilitar reconhecimento facial", + "ENABLE_FACE_SEARCH_TITLE": "Habilitar reconhecimento facial?", + "ENABLE_FACE_SEARCH_DESCRIPTION": "

Se você habilitar o reconhecimento facial, o aplicativo extrairá a geometria do rosto de suas fotos. Isso ocorrerá em seu dispositivo, e quaisquer dados biométricos gerados serão criptografados de ponta a ponta.

Por favor, clique aqui para obter mais detalhes sobre esta funcionalidade em nossa política de privacidade

", + "DISABLE_BETA": "Pausar reconhecimento", + "DISABLE_FACE_SEARCH": "Desativar reconhecimento facial", + "DISABLE_FACE_SEARCH_TITLE": "Desativar reconhecimento facial?", + "DISABLE_FACE_SEARCH_DESCRIPTION": "

Ente irá parar de processar geometria facial.

Você pode reativar o reconhecimento facial novamente, se desejar, então esta operação está segura.

", + "ADVANCED": "Avançado", + "FACE_SEARCH_CONFIRMATION": "Eu entendo, e desejo permitir que o ente processe a geometria do rosto", + "LABS": "Laboratórios", + "YOURS": "seu", + "PASSPHRASE_STRENGTH_WEAK": "Força da senha: fraca", + "PASSPHRASE_STRENGTH_MODERATE": "Força da senha: moderada", + "PASSPHRASE_STRENGTH_STRONG": "Força da senha: forte", + "PREFERENCES": "Preferências", + "LANGUAGE": "Idioma", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Diretório de exportação inválido", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

O diretório de exportação que você selecionou não existe.

Por favor, selecione um diretório válido.

", + "SUBSCRIPTION_VERIFICATION_ERROR": "Falha na verificação de assinatura", + "STORAGE_UNITS": { + "B": "B", + "KB": "KB", + "MB": "MB", + "GB": "GB", + "TB": "TB" + }, + "AFTER_TIME": { + "HOUR": "após uma hora", + "DAY": "após um dia", + "WEEK": "após uma semana", + "MONTH": "após um mês", + "YEAR": "após um ano" + }, + "COPY_LINK": "Copiar link", + "DONE": "Concluído", + "LINK_SHARE_TITLE": "Ou compartilhe um link", + "REMOVE_LINK": "Remover link", + "CREATE_PUBLIC_SHARING": "Criar link público", + "PUBLIC_LINK_CREATED": "Link público criado", + "PUBLIC_LINK_ENABLED": "Link público ativado", + "COLLECT_PHOTOS": "Coletar fotos", + "PUBLIC_COLLECT_SUBTEXT": "Permita que as pessoas com o link também adicionem fotos ao álbum compartilhado.", + "STOP_EXPORT": "Parar", + "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} itens sincronizados", + "MIGRATING_EXPORT": "Preparando...", + "RENAMING_COLLECTION_FOLDERS": "Renomeando pastas do álbum...", + "TRASHING_DELETED_FILES": "Descartando arquivos excluídos...", + "TRASHING_DELETED_COLLECTIONS": "Descartando álbuns excluídos...", + "EXPORT_NOTIFICATION": { + "START": "Exportação iniciada", + "IN_PROGRESS": "Exportação já em andamento", + "FINISH": "Exportação finalizada", + "UP_TO_DATE": "Não há arquivos novos para exportar" + }, + "CONTINUOUS_EXPORT": "Sincronizar continuamente", + "TOTAL_ITEMS": "Total de itens", + "PENDING_ITEMS": "Itens pendentes", + "EXPORT_STARTING": "Iniciando a exportação...", + "DELETE_ACCOUNT_REASON_LABEL": "Qual é o principal motivo para você excluir sua conta?", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "Selecione um motivo", + "DELETE_REASON": { + "MISSING_FEATURE": "Está faltando um recurso que eu preciso", + "BROKEN_BEHAVIOR": "O aplicativo ou um determinado recurso não está funcionando como eu acredito que deveria", + "FOUND_ANOTHER_SERVICE": "Encontrei outro serviço que gosto mais", + "NOT_LISTED": "Meu motivo não está listado" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "Sentimos muito em vê-lo partir. Explique por que você está partindo para nos ajudar a melhorar.", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "Comentários", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "Sim, desejo excluir permanentemente esta conta e todos os seus dados", + "CONFIRM_DELETE_ACCOUNT": "Confirmar exclusão da conta", + "FEEDBACK_REQUIRED": "Por favor, ajude-nos com esta informação", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "O que o outro serviço faz melhor?", + "RECOVER_TWO_FACTOR": "Recuperar dois fatores", + "at": "em", + "AUTH_NEXT": "próximo", + "AUTH_DOWNLOAD_MOBILE_APP": "Baixe nosso aplicativo móvel para gerenciar seus segredos", + "HIDDEN": "Escondido", + "HIDE": "Ocultar", + "UNHIDE": "Desocultar", + "UNHIDE_TO_COLLECTION": "Reexibir para o álbum", + "SORT_BY": "Ordenar por", + "NEWEST_FIRST": "Mais recentes primeiro", + "OLDEST_FIRST": "Mais antigo primeiro", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "Este arquivo não pôde ser pré-visualizado. Clique aqui para baixar o original.", + "SELECT_COLLECTION": "Selecionar álbum", + "PIN_ALBUM": "Fixar álbum", + "UNPIN_ALBUM": "Desafixar álbum", + "DOWNLOAD_COMPLETE": "Transferência concluída", + "DOWNLOADING_COLLECTION": "Transferindo {{name}}", + "DOWNLOAD_FAILED": "Falha ao baixar", + "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} arquivos", + "CHRISTMAS": "Natal", + "CHRISTMAS_EVE": "Véspera de Natal", + "NEW_YEAR": "Ano Novo", + "NEW_YEAR_EVE": "Véspera de Ano Novo", + "IMAGE": "Imagem", + "VIDEO": "Vídeo", + "LIVE_PHOTO": "Fotos em movimento", + "CONVERT": "Converter", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "Tem certeza de que deseja fechar o editor?", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Baixe sua imagem editada ou salve uma cópia para o ente para persistir nas alterações.", + "BRIGHTNESS": "Brilho", + "CONTRAST": "Contraste", + "SATURATION": "Saturação", + "BLUR": "Desfoque", + "INVERT_COLORS": "Inverter Cores", + "ASPECT_RATIO": "Proporção da imagem", + "SQUARE": "Quadrado", + "ROTATE_LEFT": "Girar para a Esquerda", + "ROTATE_RIGHT": "Girar para a Direita", + "FLIP_VERTICALLY": "Inverter verticalmente", + "FLIP_HORIZONTALLY": "Inverter horizontalmente", + "DOWNLOAD_EDITED": "Transferência Editada", + "SAVE_A_COPY_TO_ENTE": "Salvar uma cópia para o ente", + "RESTORE_ORIGINAL": "Restaurar original", + "TRANSFORM": "Transformar", + "COLORS": "Cores", + "FLIP": "Inverter", + "ROTATION": "Rotação", + "RESET": "Redefinir", + "PHOTO_EDITOR": "Editor de Fotos", + "FASTER_UPLOAD": "Envios mais rápidos", + "FASTER_UPLOAD_DESCRIPTION": "Rotas enviam em servidores próximos", + "MAGIC_SEARCH_STATUS": "Estado da busca mágica", + "INDEXED_ITEMS": "Itens indexados", + "CAST_ALBUM_TO_TV": "Reproduzir álbum na TV", + "ENTER_CAST_PIN_CODE": "Digite o código que você vê na TV abaixo para parear este dispositivo.", + "PAIR_DEVICE_TO_TV": "Parear dispositivos", + "TV_NOT_FOUND": "TV não encontrada. Você inseriu o PIN correto?", + "AUTO_CAST_PAIR": "Pareamento automático", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "O Auto Pair requer a conexão com servidores do Google e só funciona com dispositivos Chromecast. O Google não receberá dados confidenciais, como suas fotos.", + "PAIR_WITH_PIN": "Parear com PIN", + "CHOOSE_DEVICE_FROM_BROWSER": "Escolha um dispositivo compatível com casts no navegador popup.", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "Parear com o PIN funciona para qualquer dispositivo de tela grande onde você deseja reproduzir seu álbum.", + "VISIT_CAST_ENTE_IO": "Acesse cast.ente.io no dispositivo que você deseja parear.", + "CAST_AUTO_PAIR_FAILED": "Chromecast Auto Pair falhou. Por favor, tente novamente.", + "CACHE_DIRECTORY": "Pasta de Cache", + "FREEHAND": "Mão livre", + "APPLY_CROP": "Aplicar Recorte", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Pelo menos uma transformação ou ajuste de cor deve ser feito antes de salvar.", + "PASSKEYS": "Chaves de acesso", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/pt-PT/translation.json b/web/apps/cast/public/locales/pt-PT/translation.json new file mode 100644 index 0000000000..2309803267 --- /dev/null +++ b/web/apps/cast/public/locales/pt-PT/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Backups privados
para as suas memórias
", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "
Disponível
em qualquer lugar
", + "HERO_SLIDE_3": "Android, iOS, Web, Desktop", + "LOGIN": "Entrar", + "SIGN_UP": "Registar", + "NEW_USER": "Novo no ente", + "EXISTING_USER": "Utilizador existente", + "ENTER_NAME": "Insira o nome", + "PUBLIC_UPLOADER_NAME_MESSAGE": "Adicione um nome para que os seus amigos saibam a quem agradecer por estas ótimas fotos!", + "ENTER_EMAIL": "Insira o endereço de email", + "EMAIL_ERROR": "Inserir um endereço de email válido", + "REQUIRED": "Obrigatório", + "EMAIL_SENT": "Código de verificação enviado para {{email}}", + "CHECK_INBOX": "Verifique a sua caixa de entrada (e spam) para concluir a verificação", + "ENTER_OTT": "Código de verificação", + "RESEND_MAIL": "Reenviar código", + "VERIFY": "Verificar", + "UNKNOWN_ERROR": "Ocorreu um erro. Tente novamente", + "INVALID_CODE": "Código de verificação inválido", + "EXPIRED_CODE": "O seu código de verificação expirou", + "SENDING": "A enviar...", + "SENT": "Enviado!", + "PASSWORD": "Palavra-passe", + "LINK_PASSWORD": "Introduza a palavra-passe para desbloquear o álbum", + "RETURN_PASSPHRASE_HINT": "Palavra-passe", + "SET_PASSPHRASE": "Definir palavra-passe", + "VERIFY_PASSPHRASE": "Entrar", + "INCORRECT_PASSPHRASE": "Palavra-passe incorreta", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "Bem-vindo ao ", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "Novo álbum", + "ENTER_ALBUM_NAME": "Nome do álbum", + "CLOSE_OPTION": "Fechar (Esc)", + "ENTER_FILE_NAME": "Nome do ficheiro", + "CLOSE": "Fechar", + "NO": "Não", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "Importar", + "ADD_PHOTOS": "Adicionar fotos", + "ADD_MORE_PHOTOS": "Adicionar mais fotos", + "add_photos_one": "Adicionar item", + "add_photos_other": "Adicionar {{count, number}} itens", + "SELECT_PHOTOS": "Selecionar fotos", + "FILE_UPLOAD": "Enviar Ficheiro", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "Não possui uma conta", + "ACCOUNT_EXISTS": "Já possui uma conta", + "CREATE": "Criar", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/ru-RU/translation.json b/web/apps/cast/public/locales/ru-RU/translation.json new file mode 100644 index 0000000000..c85db22361 --- /dev/null +++ b/web/apps/cast/public/locales/ru-RU/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
Личные резервные копии
для твоих воспоминаний
", + "HERO_SLIDE_1": "Сквозное шифрование по умолчанию", + "HERO_SLIDE_2_TITLE": "
Надежно хранится
в убежище от радиоактивных осадков
", + "HERO_SLIDE_2": "Созданный для того, чтобы пережить", + "HERO_SLIDE_3_TITLE": "
Доступно
везде
", + "HERO_SLIDE_3": "Android, iOS, Веб, ПК", + "LOGIN": "Авторизоваться", + "SIGN_UP": "Регистрация", + "NEW_USER": "Новенький в ente", + "EXISTING_USER": "Существующий пользователь", + "ENTER_NAME": "Введите имя", + "PUBLIC_UPLOADER_NAME_MESSAGE": "Добавьте имя, чтобы ваши друзья знали, кого благодарить за эти замечательные фотографии!", + "ENTER_EMAIL": "Введите адрес электронной почты", + "EMAIL_ERROR": "Введите действительный адрес электронной почты", + "REQUIRED": "Требуется", + "EMAIL_SENT": "Проверочный код отправлен на
{{email}}", + "CHECK_INBOX": "Пожалуйста, проверьте свой почтовый ящик (и спам) для завершения проверки", + "ENTER_OTT": "Проверочный код", + "RESEND_MAIL": "Отправить код еще раз", + "VERIFY": "Подтвердить", + "UNKNOWN_ERROR": "Что-то пошло не так, Попробуйте еще раз", + "INVALID_CODE": "Неверный код подтверждения", + "EXPIRED_CODE": "Срок действия вашего проверочного кода истек", + "SENDING": "Отправка...", + "SENT": "Отправлено!", + "PASSWORD": "Пароль", + "LINK_PASSWORD": "Введите пароль, чтобы разблокировать альбом", + "RETURN_PASSPHRASE_HINT": "Пароль", + "SET_PASSPHRASE": "Установить пароль", + "VERIFY_PASSPHRASE": "Войти", + "INCORRECT_PASSPHRASE": "Неверный пароль", + "ENTER_ENC_PASSPHRASE": "Пожалуйста, введите пароль, который мы можем использовать для шифрования ваших данных", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "Добро пожаловать в ", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "Где живут ваши лучшие фотографии", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "Генерируем ключи шифрования...", + "PASSPHRASE_HINT": "Пароль", + "CONFIRM_PASSPHRASE": "Подтвердите пароль", + "REFERRAL_CODE_HINT": "Как вы узнали о Ente? (необязательно)", + "REFERRAL_INFO": "Будет полезно, если вы укажете, где нашли нас, так как мы не отслеживаем установки приложения!", + "PASSPHRASE_MATCH_ERROR": "Пароли не совпадают", + "CREATE_COLLECTION": "Новый альбом", + "ENTER_ALBUM_NAME": "Название альбома", + "CLOSE_OPTION": "Закрыть (Esc)", + "ENTER_FILE_NAME": "Имя файла", + "CLOSE": "Закрыть", + "NO": "Нет", + "NOTHING_HERE": "Здесь нечего смотреть! 👀", + "UPLOAD": "Загрузить", + "IMPORT": "Импорт", + "ADD_PHOTOS": "Добавить фотографии", + "ADD_MORE_PHOTOS": "Добавить больше фото", + "add_photos_one": "Добавить 1 элемент", + "add_photos_other": "Добавить {{count, number}} элементов", + "SELECT_PHOTOS": "Выбрать фотографии", + "FILE_UPLOAD": "Загрузка файла", + "UPLOAD_STAGE_MESSAGE": { + "0": "Подготовка к загрузке", + "1": "Чтение файлов метаданных Google", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} файлов извлечены", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} файлов обработано", + "4": "Отмена оставшихся загрузок", + "5": "Резервное копирование завершено" + }, + "FILE_NOT_UPLOADED_LIST": "Следующие файлы не были загружены", + "SUBSCRIPTION_EXPIRED": "Подписка закончилась", + "SUBSCRIPTION_EXPIRED_MESSAGE": "Срок действия вашей подписки истек, пожалуйста, продлите", + "STORAGE_QUOTA_EXCEEDED": "Превышен лимит хранения", + "INITIAL_LOAD_DELAY_WARNING": "Первая загрузка может занять некоторое время", + "USER_DOES_NOT_EXIST": "Пользователь с таким email не найден", + "NO_ACCOUNT": "У вас нет учетной записи", + "ACCOUNT_EXISTS": "Уже есть аккаунт", + "CREATE": "Создать", + "DOWNLOAD": "Скачать", + "DOWNLOAD_OPTION": "Скачать (D)", + "DOWNLOAD_FAVORITES": "Скачать избранные", + "DOWNLOAD_UNCATEGORIZED": "Скачать без категорий", + "DOWNLOAD_HIDDEN_ITEMS": "Скачать скрытые элементы", + "COPY_OPTION": "Скопировать как PNG (Ctrl/Cmd - C)", + "TOGGLE_FULLSCREEN": "Полноэкранный режим (F)", + "ZOOM_IN_OUT": "Увеличить/уменьшить", + "PREVIOUS": "Предыдущий (←)", + "NEXT": "Следующий (→)", + "TITLE_PHOTOS": "Ente Фото", + "TITLE_ALBUMS": "Ente Фото", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "Загрузите своё первое фото", + "IMPORT_YOUR_FOLDERS": "Импортируйте папки", + "UPLOAD_DROPZONE_MESSAGE": "Перетащите для резервного копирования файлов", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Перетащите, чтобы добавить просматриваемую папку", + "TRASH_FILES_TITLE": "Удалить файлы?", + "TRASH_FILE_TITLE": "Удалить файл?", + "DELETE_FILES_TITLE": "Удалить немедленно?", + "DELETE_FILES_MESSAGE": "Выбранные файлы будут безвозвратно удалены из вашей учетной записи ente.", + "DELETE": "Удалить", + "DELETE_OPTION": "Удалить (DEL)", + "FAVORITE_OPTION": "Избранное (L)", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "Обнаружено несколько папок", + "UPLOAD_STRATEGY_CHOICE": "Вы хотите загрузить их в", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "Один альбом", + "OR": "или", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "Отдельные альбомы", + "SESSION_EXPIRED_MESSAGE": "Истёк срок действия вашей сессии. Для продолжения, пожалуйста, войдите снова", + "SESSION_EXPIRED": "Время сессии истекло", + "PASSWORD_GENERATION_FAILED": "Вашему браузеру не удалось сгенерировать надежный ключ, соответствующий стандартам шифрования ente, пожалуйста, попробуйте использовать мобильное приложение или другой браузер", + "CHANGE_PASSWORD": "Изменить пароль", + "GO_BACK": "Вернуться назад", + "RECOVERY_KEY": "Ключ восстановления", + "SAVE_LATER": "Сделать позже", + "SAVE": "Сохранить ключ", + "RECOVERY_KEY_DESCRIPTION": "Если вы забыли свой пароль, то восстановить данные можно только с помощью этого ключа.", + "RECOVER_KEY_GENERATION_FAILED": "Не удалось сгенерировать код восстановления, пожалуйста, повторите попытку", + "KEY_NOT_STORED_DISCLAIMER": "Мы не храним этот ключ, поэтому, пожалуйста, сохраните его в надежном месте", + "FORGOT_PASSWORD": "Забыл пароль", + "RECOVER_ACCOUNT": "Восстановить аккаунт", + "RECOVERY_KEY_HINT": "Ключ восстановления", + "RECOVER": "Восстановить", + "NO_RECOVERY_KEY": "Нет ключа восстановления?", + "INCORRECT_RECOVERY_KEY": "Неправильный ключ восстановления", + "SORRY": "Извините", + "NO_RECOVERY_KEY_MESSAGE": "Из-за природы нашего сквозного протокола шифрования ваши данные не могут быть расшифрованы без вашего пароля или ключа восстановления", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Пожалуйста, отправьте электронное письмо на адрес {{emailID}} с вашего зарегистрированного адреса электронной почты", + "CONTACT_SUPPORT": "Связаться с поддержкой", + "REQUEST_FEATURE": "Запросить функцию", + "SUPPORT": "Поддержка", + "CONFIRM": "Подтвердить", + "CANCEL": "Отменить", + "LOGOUT": "Выйти", + "DELETE_ACCOUNT": "Удалить аккаунт", + "DELETE_ACCOUNT_MESSAGE": "

Пожалуйста, отправьте письмо по адресу {{emailID}} с вашего зарегистрированного адреса электронной почты.

Ваш запрос будет обработан в течение 72 часов

", + "LOGOUT_MESSAGE": "Вы уверены, что хотите выйти?", + "CHANGE_EMAIL": "Изменить адрес электронной почты", + "OK": "ОК", + "SUCCESS": "Успешно", + "ERROR": "Ошибка", + "MESSAGE": "Сообщение", + "INSTALL_MOBILE_APP": "Установите наше приложение Android или iOS для автоматического резервного копирования всех ваших фотографий", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "Загрузить приложение для компьютера", + "EXPORT": "Экспортировать данные", + "SUBSCRIPTION": "Подписка", + "SUBSCRIBE": "Подписаться", + "MANAGEMENT_PORTAL": "Управлять платёжной информацией", + "MANAGE_FAMILY_PORTAL": "Управление семьёй", + "LEAVE_FAMILY_PLAN": "Покинуть семейный план", + "LEAVE": "Выйти", + "LEAVE_FAMILY_CONFIRM": "Вы уверены, что хотите покинуть семейный план?", + "CHOOSE_PLAN": "Выбери свой план", + "MANAGE_PLAN": "Управление подпиской", + "ACTIVE": "Активный", + "OFFLINE_MSG": "Вы не в сети, кэшированные воспоминания отображаются", + "FREE_SUBSCRIPTION_INFO": "Вы используете бесплатный тарифный план, истекающий {{date, dateTime}}", + "FAMILY_SUBSCRIPTION_INFO": "Вы используете семейный план, управляемый", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "Продление {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "Обновить платёжную информацию", + "MONTHLY": "Ежемесячно", + "YEARLY": "Ежегодно", + "UPDATE_SUBSCRIPTION_MESSAGE": "Хотите сменить текущий план?", + "UPDATE_SUBSCRIPTION": "Изменить план", + "CANCEL_SUBSCRIPTION": "Отменить подписку", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Все ваши данные будут удалены с наших серверов в конце этого расчетного периода.

Вы уверены, что хотите отменить свою подписку?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Вы уверены, что хотите отменить свою подписку?

", + "SUBSCRIPTION_CANCEL_FAILED": "Не удалось отменить подписку", + "SUBSCRIPTION_CANCEL_SUCCESS": "Подписка успешно отменена", + "REACTIVATE_SUBSCRIPTION": "Возобновить подписку", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "После повторной активации вам будет выставлен счет в {{date, dateTime}}", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Подписка успешно активирована ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Не удалось повторно активировать продление подписки", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Спасибо", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Отменить мобильную подписку", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Пожалуйста, отмените свою подписку в мобильном приложении, чтобы активировать подписку здесь", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Пожалуйста, свяжитесь с {{emailID}} для управления подпиской", + "RENAME": "Переименовать", + "RENAME_FILE": "Переименовать файл", + "RENAME_COLLECTION": "Переименовать альбом", + "DELETE_COLLECTION_TITLE": "Удалить альбом?", + "DELETE_COLLECTION": "Удалить альбом", + "DELETE_COLLECTION_MESSAGE": "Также удалить фотографии (и видео), которые есть в этом альбоме из всех других альбомов, где они есть?", + "DELETE_PHOTOS": "Удалить фото", + "KEEP_PHOTOS": "Оставить фото", + "SHARE": "Поделиться", + "SHARE_COLLECTION": "Поделиться альбомом", + "SHAREES": "Поделиться с", + "SHARE_WITH_SELF": "Ой, Вы не можете поделиться с самим собой", + "ALREADY_SHARED": "Упс, Вы уже делились этим с {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Делиться альбомом запрещено", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Совместное использование отключено для бесплатных аккаунтов", + "DOWNLOAD_COLLECTION": "Загрузить альбом", + "DOWNLOAD_COLLECTION_MESSAGE": "

Вы уверены, что хотите загрузить альбом полностью?

Все файлы будут последовательно помещены в очередь на загрузку

", + "CREATE_ALBUM_FAILED": "Не удалось создать альбом, пожалуйста, попробуйте еще раз", + "SEARCH": "Поиск", + "SEARCH_RESULTS": "Результаты поиска", + "NO_RESULTS": "Ничего не найдено", + "SEARCH_HINT": "Поиск альбомов, дат, описаний, ...", + "SEARCH_TYPE": { + "COLLECTION": "Альбом", + "LOCATION": "Местоположение", + "CITY": "Местоположение", + "DATE": "Дата", + "FILE_NAME": "Имя файла", + "THING": "Содержимое", + "FILE_CAPTION": "Описание", + "FILE_TYPE": "Тип файла", + "CLIP": "" + }, + "photos_count_zero": "Воспоминания отсутствуют", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "Добавить в альбом", + "SELECTED": "выбрано", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "Это видео нельзя воспроизвести в вашем браузере", + "PEOPLE": "Люди", + "INDEXING_SCHEDULED": "Индексация запланирована...", + "ANALYZING_PHOTOS": "Индексирование фотографий ({{indexStatus.nSyncedFiles,number}} / {{indexStatus.nTotalFiles,number}})", + "INDEXING_PEOPLE": "Индексирование людей на {{indexStatus.nSyncedFiles,number}} фотографиях...", + "INDEXING_DONE": "Проиндексировано {{indexStatus.nSyncedFiles,number}} фотографий", + "UNIDENTIFIED_FACES": "нераспознанные лица", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "Двухфакторная аутентификация", + "TWO_FACTOR_QR_INSTRUCTION": "Сканируйте QR-код ниже с вашим любимым приложением для проверки подлинности", + "ENTER_CODE_MANUALLY": "Введите код вручную", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Пожалуйста, введите этот код в вашем любимом приложении для аутентификации", + "SCAN_QR_CODE": "Сканировать QR-код вместо", + "ENABLE_TWO_FACTOR": "Включить двухфакторную аутентификацию", + "ENABLE": "Включить", + "LOST_DEVICE": "Потеряно двухфакторное устройство", + "INCORRECT_CODE": "Неверный код", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "Отключить двухфакторную аутентификацию", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "Отключить", + "RECONFIGURE": "Перенастроить", + "UPDATE_TWO_FACTOR": "Обновить двухфакторную аутентификацию", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "Обновить", + "DISABLE_TWO_FACTOR": "Отключить двухфакторную аутентификацию", + "DISABLE_TWO_FACTOR_MESSAGE": "Вы уверены, что хотите отключить двухфакторную аутентификацию", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "Экспортировать данные", + "SELECT_FOLDER": "Выбрать папку", + "DESTINATION": "Место назначения", + "START": "Начать", + "LAST_EXPORT_TIME": "Время последнего экспорта", + "EXPORT_AGAIN": "Синхронизировать заново", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Локальное хранилище недоступно", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "Отправить одноразовый код", + "EMAIl_ALREADY_OWNED": "Почта уже использована", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "Скрыть", + "UNHIDE": "Показать", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "Сортировать по", + "NEWEST_FIRST": "Сначала новые", + "OLDEST_FIRST": "Сначала старые", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "Выбрать альбом", + "PIN_ALBUM": "Закрепить альбом", + "UNPIN_ALBUM": "Открепить альбом", + "DOWNLOAD_COMPLETE": "Загрузка завершена", + "DOWNLOADING_COLLECTION": "Загрузка {{name}}", + "DOWNLOAD_FAILED": "Загрузка не удалась", + "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} файлов", + "CHRISTMAS": "Рождество", + "CHRISTMAS_EVE": "Канун Рождества", + "NEW_YEAR": "Новый год", + "NEW_YEAR_EVE": "Канун Нового года", + "IMAGE": "Изображение", + "VIDEO": "Видео", + "LIVE_PHOTO": "Живое фото", + "CONVERT": "Преобразовать", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "Вы уверены, что хотите закрыть редактор?", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Загрузите отредактированное изображение или сохраните копию в ente, чтобы сохранить внесенные изменения.", + "BRIGHTNESS": "Яркость", + "CONTRAST": "Контраст", + "SATURATION": "Насыщенность", + "BLUR": "Размытие", + "INVERT_COLORS": "Инвертировать Цвета", + "ASPECT_RATIO": "Соотношение Сторон", + "SQUARE": "Квадрат", + "ROTATE_LEFT": "Повернуть влево", + "ROTATE_RIGHT": "Повернуть вправо", + "FLIP_VERTICALLY": "Отразить вертикально", + "FLIP_HORIZONTALLY": "Отразить горизонтально", + "DOWNLOAD_EDITED": "Скачать отредактированный", + "SAVE_A_COPY_TO_ENTE": "Сохранить копию в ente", + "RESTORE_ORIGINAL": "Восстановить оригинал", + "TRANSFORM": "Преобразовать", + "COLORS": "Цвета", + "FLIP": "Перевернуть", + "ROTATION": "", + "RESET": "Сбросить", + "PHOTO_EDITOR": "Редактор фото", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "Статус волшебного поиска", + "INDEXED_ITEMS": "Индексированные элементы", + "CAST_ALBUM_TO_TV": "Воспроизвести альбом на ТВ", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/sv-SE/translation.json b/web/apps/cast/public/locales/sv-SE/translation.json new file mode 100644 index 0000000000..f88535795a --- /dev/null +++ b/web/apps/cast/public/locales/sv-SE/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "Ange namn", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "Ange e-postadress", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "Lösenord", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "Lösenord", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "Logga in", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "Välkommen till ", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "Lösenord", + "CONFIRM_PASSPHRASE": "Bekräfta lösenord", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "Lösenorden matchar inte", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "Filnamn", + "CLOSE": "Stäng", + "NO": "Nej", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "Radera", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "eller", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "Ändra lösenord", + "GO_BACK": "", + "RECOVERY_KEY": "Återställningsnyckel", + "SAVE_LATER": "", + "SAVE": "Spara nyckel", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "Glömt lösenord", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "Ingen återställningsnyckel?", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "Bekräfta", + "CANCEL": "Avbryt", + "LOGOUT": "Logga ut", + "DELETE_ACCOUNT": "Radera konto", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "Meddelande", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "Prenumerera", + "MANAGEMENT_PORTAL": "Hantera betalningsmetod", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "Hantera din prenumeration", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "Sök", + "SEARCH_RESULTS": "Sökresultat", + "NO_RESULTS": "Inga resultat hittades", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "Datum", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "Beskrivning", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "Inga deltagare", + "participants_one": "1 deltagare", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "Deltagare", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "Fil", + "UPLOAD_DIRS": "Mapp", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "Filer", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "1 album", + "albums_other": "{{count, number}} album", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "Lägg till mapp", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "mån", + "YEAR": "år", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "GB", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "Namn...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "Språk", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "Kopiera länk", + "DONE": "Klar", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "Sortera efter", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "Bild", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "Färger", + "FLIP": "", + "ROTATION": "", + "RESET": "Återställ", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/th-TH/translation.json b/web/apps/cast/public/locales/th-TH/translation.json new file mode 100644 index 0000000000..888ed7093e --- /dev/null +++ b/web/apps/cast/public/locales/th-TH/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/tr-TR/translation.json b/web/apps/cast/public/locales/tr-TR/translation.json new file mode 100644 index 0000000000..888ed7093e --- /dev/null +++ b/web/apps/cast/public/locales/tr-TR/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "", + "HERO_SLIDE_1": "", + "HERO_SLIDE_2_TITLE": "", + "HERO_SLIDE_2": "", + "HERO_SLIDE_3_TITLE": "", + "HERO_SLIDE_3": "", + "LOGIN": "", + "SIGN_UP": "", + "NEW_USER": "", + "EXISTING_USER": "", + "ENTER_NAME": "", + "PUBLIC_UPLOADER_NAME_MESSAGE": "", + "ENTER_EMAIL": "", + "EMAIL_ERROR": "", + "REQUIRED": "", + "EMAIL_SENT": "", + "CHECK_INBOX": "", + "ENTER_OTT": "", + "RESEND_MAIL": "", + "VERIFY": "", + "UNKNOWN_ERROR": "", + "INVALID_CODE": "", + "EXPIRED_CODE": "", + "SENDING": "", + "SENT": "", + "PASSWORD": "", + "LINK_PASSWORD": "", + "RETURN_PASSPHRASE_HINT": "", + "SET_PASSPHRASE": "", + "VERIFY_PASSPHRASE": "", + "INCORRECT_PASSPHRASE": "", + "ENTER_ENC_PASSPHRASE": "", + "PASSPHRASE_DISCLAIMER": "", + "WELCOME_TO_ENTE_HEADING": "", + "WELCOME_TO_ENTE_SUBHEADING": "", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "", + "PASSPHRASE_HINT": "", + "CONFIRM_PASSPHRASE": "", + "REFERRAL_CODE_HINT": "", + "REFERRAL_INFO": "", + "PASSPHRASE_MATCH_ERROR": "", + "CREATE_COLLECTION": "", + "ENTER_ALBUM_NAME": "", + "CLOSE_OPTION": "", + "ENTER_FILE_NAME": "", + "CLOSE": "", + "NO": "", + "NOTHING_HERE": "", + "UPLOAD": "", + "IMPORT": "", + "ADD_PHOTOS": "", + "ADD_MORE_PHOTOS": "", + "add_photos_one": "", + "add_photos_other": "", + "SELECT_PHOTOS": "", + "FILE_UPLOAD": "", + "UPLOAD_STAGE_MESSAGE": { + "0": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "" + }, + "FILE_NOT_UPLOADED_LIST": "", + "SUBSCRIPTION_EXPIRED": "", + "SUBSCRIPTION_EXPIRED_MESSAGE": "", + "STORAGE_QUOTA_EXCEEDED": "", + "INITIAL_LOAD_DELAY_WARNING": "", + "USER_DOES_NOT_EXIST": "", + "NO_ACCOUNT": "", + "ACCOUNT_EXISTS": "", + "CREATE": "", + "DOWNLOAD": "", + "DOWNLOAD_OPTION": "", + "DOWNLOAD_FAVORITES": "", + "DOWNLOAD_UNCATEGORIZED": "", + "DOWNLOAD_HIDDEN_ITEMS": "", + "COPY_OPTION": "", + "TOGGLE_FULLSCREEN": "", + "ZOOM_IN_OUT": "", + "PREVIOUS": "", + "NEXT": "", + "TITLE_PHOTOS": "", + "TITLE_ALBUMS": "", + "TITLE_AUTH": "", + "UPLOAD_FIRST_PHOTO": "", + "IMPORT_YOUR_FOLDERS": "", + "UPLOAD_DROPZONE_MESSAGE": "", + "WATCH_FOLDER_DROPZONE_MESSAGE": "", + "TRASH_FILES_TITLE": "", + "TRASH_FILE_TITLE": "", + "DELETE_FILES_TITLE": "", + "DELETE_FILES_MESSAGE": "", + "DELETE": "", + "DELETE_OPTION": "", + "FAVORITE_OPTION": "", + "UNFAVORITE_OPTION": "", + "MULTI_FOLDER_UPLOAD": "", + "UPLOAD_STRATEGY_CHOICE": "", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "", + "OR": "", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "", + "SESSION_EXPIRED_MESSAGE": "", + "SESSION_EXPIRED": "", + "PASSWORD_GENERATION_FAILED": "", + "CHANGE_PASSWORD": "", + "GO_BACK": "", + "RECOVERY_KEY": "", + "SAVE_LATER": "", + "SAVE": "", + "RECOVERY_KEY_DESCRIPTION": "", + "RECOVER_KEY_GENERATION_FAILED": "", + "KEY_NOT_STORED_DISCLAIMER": "", + "FORGOT_PASSWORD": "", + "RECOVER_ACCOUNT": "", + "RECOVERY_KEY_HINT": "", + "RECOVER": "", + "NO_RECOVERY_KEY": "", + "INCORRECT_RECOVERY_KEY": "", + "SORRY": "", + "NO_RECOVERY_KEY_MESSAGE": "", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "CONTACT_SUPPORT": "", + "REQUEST_FEATURE": "", + "SUPPORT": "", + "CONFIRM": "", + "CANCEL": "", + "LOGOUT": "", + "DELETE_ACCOUNT": "", + "DELETE_ACCOUNT_MESSAGE": "", + "LOGOUT_MESSAGE": "", + "CHANGE_EMAIL": "", + "OK": "", + "SUCCESS": "", + "ERROR": "", + "MESSAGE": "", + "INSTALL_MOBILE_APP": "", + "DOWNLOAD_APP_MESSAGE": "", + "DOWNLOAD_APP": "", + "EXPORT": "", + "SUBSCRIPTION": "", + "SUBSCRIBE": "", + "MANAGEMENT_PORTAL": "", + "MANAGE_FAMILY_PORTAL": "", + "LEAVE_FAMILY_PLAN": "", + "LEAVE": "", + "LEAVE_FAMILY_CONFIRM": "", + "CHOOSE_PLAN": "", + "MANAGE_PLAN": "", + "ACTIVE": "", + "OFFLINE_MSG": "", + "FREE_SUBSCRIPTION_INFO": "", + "FAMILY_SUBSCRIPTION_INFO": "", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "", + "ADD_ON_AVAILABLE_TILL": "", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "", + "SUBSCRIPTION_PURCHASE_SUCCESS": "", + "SUBSCRIPTION_PURCHASE_CANCELLED": "", + "SUBSCRIPTION_PURCHASE_FAILED": "", + "SUBSCRIPTION_UPDATE_FAILED": "", + "UPDATE_PAYMENT_METHOD_MESSAGE": "", + "STRIPE_AUTHENTICATION_FAILED": "", + "UPDATE_PAYMENT_METHOD": "", + "MONTHLY": "", + "YEARLY": "", + "UPDATE_SUBSCRIPTION_MESSAGE": "", + "UPDATE_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION": "", + "CANCEL_SUBSCRIPTION_MESSAGE": "", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", + "SUBSCRIPTION_CANCEL_FAILED": "", + "SUBSCRIPTION_CANCEL_SUCCESS": "", + "REACTIVATE_SUBSCRIPTION": "", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "", + "SUBSCRIPTION_ACTIVATE_FAILED": "", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", + "MAIL_TO_MANAGE_SUBSCRIPTION": "", + "RENAME": "", + "RENAME_FILE": "", + "RENAME_COLLECTION": "", + "DELETE_COLLECTION_TITLE": "", + "DELETE_COLLECTION": "", + "DELETE_COLLECTION_MESSAGE": "", + "DELETE_PHOTOS": "", + "KEEP_PHOTOS": "", + "SHARE": "", + "SHARE_COLLECTION": "", + "SHAREES": "", + "SHARE_WITH_SELF": "", + "ALREADY_SHARED": "", + "SHARING_BAD_REQUEST_ERROR": "", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", + "DOWNLOAD_COLLECTION": "", + "DOWNLOAD_COLLECTION_MESSAGE": "", + "CREATE_ALBUM_FAILED": "", + "SEARCH": "", + "SEARCH_RESULTS": "", + "NO_RESULTS": "", + "SEARCH_HINT": "", + "SEARCH_TYPE": { + "COLLECTION": "", + "LOCATION": "", + "CITY": "", + "DATE": "", + "FILE_NAME": "", + "THING": "", + "FILE_CAPTION": "", + "FILE_TYPE": "", + "CLIP": "" + }, + "photos_count_zero": "", + "photos_count_one": "", + "photos_count_other": "", + "TERMS_AND_CONDITIONS": "", + "ADD_TO_COLLECTION": "", + "SELECTED": "", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "", + "PEOPLE": "", + "INDEXING_SCHEDULED": "", + "ANALYZING_PHOTOS": "", + "INDEXING_PEOPLE": "", + "INDEXING_DONE": "", + "UNIDENTIFIED_FACES": "", + "OBJECTS": "", + "TEXT": "", + "INFO": "", + "INFO_OPTION": "", + "FILE_NAME": "", + "CAPTION_PLACEHOLDER": "", + "LOCATION": "", + "SHOW_ON_MAP": "", + "MAP": "", + "MAP_SETTINGS": "", + "ENABLE_MAPS": "", + "ENABLE_MAP": "", + "DISABLE_MAPS": "", + "ENABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP_DESCRIPTION": "", + "DISABLE_MAP": "", + "DETAILS": "", + "VIEW_EXIF": "", + "NO_EXIF": "", + "EXIF": "", + "ISO": "", + "TWO_FACTOR": "", + "TWO_FACTOR_AUTHENTICATION": "", + "TWO_FACTOR_QR_INSTRUCTION": "", + "ENTER_CODE_MANUALLY": "", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", + "SCAN_QR_CODE": "", + "ENABLE_TWO_FACTOR": "", + "ENABLE": "", + "LOST_DEVICE": "", + "INCORRECT_CODE": "", + "TWO_FACTOR_INFO": "", + "DISABLE_TWO_FACTOR_LABEL": "", + "UPDATE_TWO_FACTOR_LABEL": "", + "DISABLE": "", + "RECONFIGURE": "", + "UPDATE_TWO_FACTOR": "", + "UPDATE_TWO_FACTOR_MESSAGE": "", + "UPDATE": "", + "DISABLE_TWO_FACTOR": "", + "DISABLE_TWO_FACTOR_MESSAGE": "", + "TWO_FACTOR_DISABLE_FAILED": "", + "EXPORT_DATA": "", + "SELECT_FOLDER": "", + "DESTINATION": "", + "START": "", + "LAST_EXPORT_TIME": "", + "EXPORT_AGAIN": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", + "SEND_OTT": "", + "EMAIl_ALREADY_OWNED": "", + "ETAGS_BLOCKED": "", + "SKIPPED_VIDEOS_INFO": "", + "LIVE_PHOTOS_DETECTED": "", + "RETRY_FAILED": "", + "FAILED_UPLOADS": "", + "SKIPPED_FILES": "", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", + "UNSUPPORTED_FILES": "", + "SUCCESSFUL_UPLOADS": "", + "SKIPPED_INFO": "", + "UNSUPPORTED_INFO": "", + "BLOCKED_UPLOADS": "", + "SKIPPED_VIDEOS": "", + "INPROGRESS_METADATA_EXTRACTION": "", + "INPROGRESS_UPLOADS": "", + "TOO_LARGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", + "TOO_LARGE_INFO": "", + "THUMBNAIL_GENERATION_FAILED_INFO": "", + "UPLOAD_TO_COLLECTION": "", + "UNCATEGORIZED": "", + "ARCHIVE": "", + "FAVORITES": "", + "ARCHIVE_COLLECTION": "", + "ARCHIVE_SECTION_NAME": "", + "ALL_SECTION_NAME": "", + "MOVE_TO_COLLECTION": "", + "UNARCHIVE": "", + "UNARCHIVE_COLLECTION": "", + "HIDE_COLLECTION": "", + "UNHIDE_COLLECTION": "", + "MOVE": "", + "ADD": "", + "REMOVE": "", + "YES_REMOVE": "", + "REMOVE_FROM_COLLECTION": "", + "TRASH": "", + "MOVE_TO_TRASH": "", + "TRASH_FILES_MESSAGE": "", + "TRASH_FILE_MESSAGE": "", + "DELETE_PERMANENTLY": "", + "RESTORE": "", + "RESTORE_TO_COLLECTION": "", + "EMPTY_TRASH": "", + "EMPTY_TRASH_TITLE": "", + "EMPTY_TRASH_MESSAGE": "", + "LEAVE_SHARED_ALBUM": "", + "LEAVE_ALBUM": "", + "LEAVE_SHARED_ALBUM_TITLE": "", + "LEAVE_SHARED_ALBUM_MESSAGE": "", + "NOT_FILE_OWNER": "", + "CONFIRM_SELF_REMOVE_MESSAGE": "", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", + "SORT_BY_CREATION_TIME_ASCENDING": "", + "SORT_BY_UPDATION_TIME_DESCENDING": "", + "SORT_BY_NAME": "", + "COMPRESS_THUMBNAILS": "", + "THUMBNAIL_REPLACED": "", + "FIX_THUMBNAIL": "", + "FIX_THUMBNAIL_LATER": "", + "REPLACE_THUMBNAIL_NOT_STARTED": "", + "REPLACE_THUMBNAIL_COMPLETED": "", + "REPLACE_THUMBNAIL_NOOP": "", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "", + "FIX_CREATION_TIME": "", + "FIX_CREATION_TIME_IN_PROGRESS": "", + "CREATION_TIME_UPDATED": "", + "UPDATE_CREATION_TIME_NOT_STARTED": "", + "UPDATE_CREATION_TIME_COMPLETED": "", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", + "CAPTION_CHARACTER_LIMIT": "", + "DATE_TIME_ORIGINAL": "", + "DATE_TIME_DIGITIZED": "", + "METADATA_DATE": "", + "CUSTOM_TIME": "", + "REOPEN_PLAN_SELECTOR_MODAL": "", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "", + "INSTALL": "", + "SHARING_DETAILS": "", + "MODIFY_SHARING": "", + "ADD_COLLABORATORS": "", + "ADD_NEW_EMAIL": "", + "shared_with_people_zero": "", + "shared_with_people_one": "", + "shared_with_people_other": "", + "participants_zero": "", + "participants_one": "", + "participants_other": "", + "ADD_VIEWERS": "", + "PARTICIPANTS": "", + "CHANGE_PERMISSIONS_TO_VIEWER": "", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", + "CONVERT_TO_VIEWER": "", + "CONVERT_TO_COLLABORATOR": "", + "CHANGE_PERMISSION": "", + "REMOVE_PARTICIPANT": "", + "CONFIRM_REMOVE": "", + "MANAGE": "", + "ADDED_AS": "", + "COLLABORATOR_RIGHTS": "", + "REMOVE_PARTICIPANT_HEAD": "", + "OWNER": "", + "COLLABORATORS": "", + "ADD_MORE": "", + "VIEWERS": "", + "OR_ADD_EXISTING": "", + "REMOVE_PARTICIPANT_MESSAGE": "", + "NOT_FOUND": "", + "LINK_EXPIRED": "", + "LINK_EXPIRED_MESSAGE": "", + "MANAGE_LINK": "", + "LINK_TOO_MANY_REQUESTS": "", + "FILE_DOWNLOAD": "", + "LINK_PASSWORD_LOCK": "", + "PUBLIC_COLLECT": "", + "LINK_DEVICE_LIMIT": "", + "NO_DEVICE_LIMIT": "", + "LINK_EXPIRY": "", + "NEVER": "", + "DISABLE_FILE_DOWNLOAD": "", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "", + "MALICIOUS_CONTENT": "", + "COPYRIGHT": "", + "SHARED_USING": "", + "ENTE_IO": "", + "SHARING_REFERRAL_CODE": "", + "LIVE": "", + "DISABLE_PASSWORD": "", + "DISABLE_PASSWORD_MESSAGE": "", + "PASSWORD_LOCK": "", + "LOCK": "", + "DOWNLOAD_UPLOAD_LOGS": "", + "UPLOAD_FILES": "", + "UPLOAD_DIRS": "", + "UPLOAD_GOOGLE_TAKEOUT": "", + "DEDUPLICATE_FILES": "", + "AUTHENTICATOR_SECTION": "", + "NO_DUPLICATES_FOUND": "", + "CLUB_BY_CAPTURE_TIME": "", + "FILES": "", + "EACH": "", + "DEDUPLICATE_BASED_ON_SIZE": "", + "STOP_ALL_UPLOADS_MESSAGE": "", + "STOP_UPLOADS_HEADER": "", + "YES_STOP_UPLOADS": "", + "STOP_DOWNLOADS_HEADER": "", + "YES_STOP_DOWNLOADS": "", + "STOP_ALL_DOWNLOADS_MESSAGE": "", + "albums_one": "", + "albums_other": "", + "ALL_ALBUMS": "", + "ALBUMS": "", + "ALL_HIDDEN_ALBUMS": "", + "HIDDEN_ALBUMS": "", + "HIDDEN_ITEMS": "", + "HIDDEN_ITEMS_SECTION_NAME": "", + "ENTER_TWO_FACTOR_OTP": "", + "CREATE_ACCOUNT": "", + "COPIED": "", + "CANVAS_BLOCKED_TITLE": "", + "CANVAS_BLOCKED_MESSAGE": "", + "WATCH_FOLDERS": "", + "UPGRADE_NOW": "", + "RENEW_NOW": "", + "STORAGE": "", + "USED": "", + "YOU": "", + "FAMILY": "", + "FREE": "", + "OF": "", + "WATCHED_FOLDERS": "", + "NO_FOLDERS_ADDED": "", + "FOLDERS_AUTOMATICALLY_MONITORED": "", + "UPLOAD_NEW_FILES_TO_ENTE": "", + "REMOVE_DELETED_FILES_FROM_ENTE": "", + "ADD_FOLDER": "", + "STOP_WATCHING": "", + "STOP_WATCHING_FOLDER": "", + "STOP_WATCHING_DIALOG_MESSAGE": "", + "YES_STOP": "", + "MONTH_SHORT": "", + "YEAR": "", + "FAMILY_PLAN": "", + "DOWNLOAD_LOGS": "", + "DOWNLOAD_LOGS_MESSAGE": "", + "CHANGE_FOLDER": "", + "TWO_MONTHS_FREE": "", + "GB": "", + "POPULAR": "", + "FREE_PLAN_OPTION_LABEL": "", + "FREE_PLAN_DESCRIPTION": "", + "CURRENT_USAGE": "", + "WEAK_DEVICE": "", + "DRAG_AND_DROP_HINT": "", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "", + "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": "", + "NAME_PLACEHOLDER": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", + "CHOSE_THEME": "", + "ML_SEARCH": "", + "ENABLE_ML_SEARCH_DESCRIPTION": "", + "ML_MORE_DETAILS": "", + "ENABLE_FACE_SEARCH": "", + "ENABLE_FACE_SEARCH_TITLE": "", + "ENABLE_FACE_SEARCH_DESCRIPTION": "", + "DISABLE_BETA": "", + "DISABLE_FACE_SEARCH": "", + "DISABLE_FACE_SEARCH_TITLE": "", + "DISABLE_FACE_SEARCH_DESCRIPTION": "", + "ADVANCED": "", + "FACE_SEARCH_CONFIRMATION": "", + "LABS": "", + "YOURS": "", + "PASSPHRASE_STRENGTH_WEAK": "", + "PASSPHRASE_STRENGTH_MODERATE": "", + "PASSPHRASE_STRENGTH_STRONG": "", + "PREFERENCES": "", + "LANGUAGE": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", + "SUBSCRIPTION_VERIFICATION_ERROR": "", + "STORAGE_UNITS": { + "B": "", + "KB": "", + "MB": "", + "GB": "", + "TB": "" + }, + "AFTER_TIME": { + "HOUR": "", + "DAY": "", + "WEEK": "", + "MONTH": "", + "YEAR": "" + }, + "COPY_LINK": "", + "DONE": "", + "LINK_SHARE_TITLE": "", + "REMOVE_LINK": "", + "CREATE_PUBLIC_SHARING": "", + "PUBLIC_LINK_CREATED": "", + "PUBLIC_LINK_ENABLED": "", + "COLLECT_PHOTOS": "", + "PUBLIC_COLLECT_SUBTEXT": "", + "STOP_EXPORT": "", + "EXPORT_PROGRESS": "", + "MIGRATING_EXPORT": "", + "RENAMING_COLLECTION_FOLDERS": "", + "TRASHING_DELETED_FILES": "", + "TRASHING_DELETED_COLLECTIONS": "", + "EXPORT_NOTIFICATION": { + "START": "", + "IN_PROGRESS": "", + "FINISH": "", + "UP_TO_DATE": "" + }, + "CONTINUOUS_EXPORT": "", + "TOTAL_ITEMS": "", + "PENDING_ITEMS": "", + "EXPORT_STARTING": "", + "DELETE_ACCOUNT_REASON_LABEL": "", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "", + "DELETE_REASON": { + "MISSING_FEATURE": "", + "BROKEN_BEHAVIOR": "", + "FOUND_ANOTHER_SERVICE": "", + "NOT_LISTED": "" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "", + "CONFIRM_DELETE_ACCOUNT": "", + "FEEDBACK_REQUIRED": "", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "", + "RECOVER_TWO_FACTOR": "", + "at": "", + "AUTH_NEXT": "", + "AUTH_DOWNLOAD_MOBILE_APP": "", + "HIDDEN": "", + "HIDE": "", + "UNHIDE": "", + "UNHIDE_TO_COLLECTION": "", + "SORT_BY": "", + "NEWEST_FIRST": "", + "OLDEST_FIRST": "", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", + "SELECT_COLLECTION": "", + "PIN_ALBUM": "", + "UNPIN_ALBUM": "", + "DOWNLOAD_COMPLETE": "", + "DOWNLOADING_COLLECTION": "", + "DOWNLOAD_FAILED": "", + "DOWNLOAD_PROGRESS": "", + "CHRISTMAS": "", + "CHRISTMAS_EVE": "", + "NEW_YEAR": "", + "NEW_YEAR_EVE": "", + "IMAGE": "", + "VIDEO": "", + "LIVE_PHOTO": "", + "CONVERT": "", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "BRIGHTNESS": "", + "CONTRAST": "", + "SATURATION": "", + "BLUR": "", + "INVERT_COLORS": "", + "ASPECT_RATIO": "", + "SQUARE": "", + "ROTATE_LEFT": "", + "ROTATE_RIGHT": "", + "FLIP_VERTICALLY": "", + "FLIP_HORIZONTALLY": "", + "DOWNLOAD_EDITED": "", + "SAVE_A_COPY_TO_ENTE": "", + "RESTORE_ORIGINAL": "", + "TRANSFORM": "", + "COLORS": "", + "FLIP": "", + "ROTATION": "", + "RESET": "", + "PHOTO_EDITOR": "", + "FASTER_UPLOAD": "", + "FASTER_UPLOAD_DESCRIPTION": "", + "MAGIC_SEARCH_STATUS": "", + "INDEXED_ITEMS": "", + "CAST_ALBUM_TO_TV": "", + "ENTER_CAST_PIN_CODE": "", + "PAIR_DEVICE_TO_TV": "", + "TV_NOT_FOUND": "", + "AUTO_CAST_PAIR": "", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "", + "PAIR_WITH_PIN": "", + "CHOOSE_DEVICE_FROM_BROWSER": "", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "", + "VISIT_CAST_ENTE_IO": "", + "CAST_AUTO_PAIR_FAILED": "", + "CACHE_DIRECTORY": "", + "FREEHAND": "", + "APPLY_CROP": "", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "", + "PASSKEYS": "", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} diff --git a/web/apps/cast/public/locales/zh-CN/translation.json b/web/apps/cast/public/locales/zh-CN/translation.json new file mode 100644 index 0000000000..0a72e1c70a --- /dev/null +++ b/web/apps/cast/public/locales/zh-CN/translation.json @@ -0,0 +1,654 @@ +{ + "HERO_SLIDE_1_TITLE": "
私人备份
为您的回忆
", + "HERO_SLIDE_1": "默认端到端加密", + "HERO_SLIDE_2_TITLE": "
安全地存放
在一个掩护所中
", + "HERO_SLIDE_2": "经久耐用", + "HERO_SLIDE_3_TITLE": "
可用于
各处
", + "HERO_SLIDE_3": "安卓, iOS, 网页端, 桌面端", + "LOGIN": "登录", + "SIGN_UP": "注册", + "NEW_USER": "刚来到 ente", + "EXISTING_USER": "现有用户", + "ENTER_NAME": "输入名字", + "PUBLIC_UPLOADER_NAME_MESSAGE": "请添加一个名字,以便您的朋友知晓该感谢谁拍摄了这些精美的照片!", + "ENTER_EMAIL": "请输入电子邮件地址", + "EMAIL_ERROR": "请输入有效的电子邮件", + "REQUIRED": "必需的", + "EMAIL_SENT": "验证码已发送至
{{email}}", + "CHECK_INBOX": "请检查您的收件箱 (或者是在您的“垃圾邮件”列表内) 以完成验证", + "ENTER_OTT": "验证码", + "RESEND_MAIL": "重新发送验证码", + "VERIFY": "验证", + "UNKNOWN_ERROR": "出了点问题,请重试", + "INVALID_CODE": "验证码无效", + "EXPIRED_CODE": "您的验证码已过期", + "SENDING": "发送中……", + "SENT": "已发送!", + "PASSWORD": "密码", + "LINK_PASSWORD": "输入密码来解锁相册", + "RETURN_PASSPHRASE_HINT": "密码", + "SET_PASSPHRASE": "设置密码", + "VERIFY_PASSPHRASE": "登录", + "INCORRECT_PASSPHRASE": "密码错误", + "ENTER_ENC_PASSPHRASE": "请输入我们可以用来加密您数据的密码", + "PASSPHRASE_DISCLAIMER": "我们不会存储您的密码,因此如果您忘记密码, 我们将无法帮助您在没有恢复密钥的情况下恢复您的数据。", + "WELCOME_TO_ENTE_HEADING": "欢迎来到 ", + "WELCOME_TO_ENTE_SUBHEADING": "端到端加密的照片存储和共享", + "WHERE_YOUR_BEST_PHOTOS_LIVE": "可以让您存放照片的最好的地方", + "KEY_GENERATION_IN_PROGRESS_MESSAGE": "正在生成加密密钥...", + "PASSPHRASE_HINT": "密码", + "CONFIRM_PASSPHRASE": "请确认密码", + "REFERRAL_CODE_HINT": "您是如何知道Ente的? (可选的)", + "REFERRAL_INFO": "我们不跟踪应用程序安装情况,如果您告诉我们您是在哪里找到我们的,将会有所帮助!", + "PASSPHRASE_MATCH_ERROR": "两次输入的密码不一致", + "CREATE_COLLECTION": "新建相册", + "ENTER_ALBUM_NAME": "相册名称", + "CLOSE_OPTION": "关闭 (或按Esc键)", + "ENTER_FILE_NAME": "文件名", + "CLOSE": "关闭", + "NO": "否", + "NOTHING_HERE": "这里空空如也 👀", + "UPLOAD": "上传", + "IMPORT": "导入", + "ADD_PHOTOS": "添加照片", + "ADD_MORE_PHOTOS": "添加更多的照片", + "add_photos_one": "添加1个项目", + "add_photos_other": "添加 {{count, number}} 个项目", + "SELECT_PHOTOS": "选择图片", + "FILE_UPLOAD": "上传文件", + "UPLOAD_STAGE_MESSAGE": { + "0": "正在准备上传", + "1": "正在读取 Google 元数据文件", + "2": "文件元数据提取状态:已完成 {{uploadCounter.finished, number}} / 共 {{uploadCounter.total, number}}", + "3": "文件备份状态:已完成 {{uploadCounter.finished, number}} / 共 {{uploadCounter.total, number}}", + "4": "正在取消剩余的上传内容", + "5": "备份完成" + }, + "FILE_NOT_UPLOADED_LIST": "以下文件未上传", + "SUBSCRIPTION_EXPIRED": "您的订阅已过期", + "SUBSCRIPTION_EXPIRED_MESSAGE": "您的订阅已过期,请 续期", + "STORAGE_QUOTA_EXCEEDED": "已超出存储限制", + "INITIAL_LOAD_DELAY_WARNING": "第一次加载可能需要一些时间", + "USER_DOES_NOT_EXIST": "抱歉,找不到该电子邮件的用户", + "NO_ACCOUNT": "没有账号", + "ACCOUNT_EXISTS": "已有账户", + "CREATE": "创建", + "DOWNLOAD": "下载", + "DOWNLOAD_OPTION": "下载 (D)", + "DOWNLOAD_FAVORITES": "下载收藏", + "DOWNLOAD_UNCATEGORIZED": "下载未分类的", + "DOWNLOAD_HIDDEN_ITEMS": "下载隐藏项目", + "COPY_OPTION": "复制为 PNG (Ctrl/Cmd - C)", + "TOGGLE_FULLSCREEN": "切换至全屏 (F)", + "ZOOM_IN_OUT": "放大/缩小", + "PREVIOUS": "上一个 (←)", + "NEXT": "下一个 (→)", + "TITLE_PHOTOS": "Ente 照片", + "TITLE_ALBUMS": "Ente 照片", + "TITLE_AUTH": "Ente 验证器", + "UPLOAD_FIRST_PHOTO": "上传您的第一张照片", + "IMPORT_YOUR_FOLDERS": "导入您的文件夹", + "UPLOAD_DROPZONE_MESSAGE": "拖放以备份您的文件", + "WATCH_FOLDER_DROPZONE_MESSAGE": "拖放以添加观看的文件夹", + "TRASH_FILES_TITLE": "要删除文件吗?", + "TRASH_FILE_TITLE": "要删除文件吗?", + "DELETE_FILES_TITLE": "要立即删除吗?", + "DELETE_FILES_MESSAGE": "所选文件将从您的账户中永久删除。", + "DELETE": "删除", + "DELETE_OPTION": "删除(DEL)", + "FAVORITE_OPTION": "收藏 (L)", + "UNFAVORITE_OPTION": "取消收藏 (L)", + "MULTI_FOLDER_UPLOAD": "检测到多个文件夹", + "UPLOAD_STRATEGY_CHOICE": "你想要上传他们到", + "UPLOAD_STRATEGY_SINGLE_COLLECTION": "单个相册", + "OR": "或者", + "UPLOAD_STRATEGY_COLLECTION_PER_FOLDER": "独立相册", + "SESSION_EXPIRED_MESSAGE": "您的会话已过期,请重新登录以继续", + "SESSION_EXPIRED": "会话已过期", + "PASSWORD_GENERATION_FAILED": "您的浏览器无法生成一个符合ente加密标准的强密钥,请尝试使用移动应用程序或其他浏览器", + "CHANGE_PASSWORD": "修改密码", + "GO_BACK": "返回", + "RECOVERY_KEY": "恢复密钥", + "SAVE_LATER": "稍后再做", + "SAVE": "保存密钥", + "RECOVERY_KEY_DESCRIPTION": "如果您忘记了密码,恢复数据的唯一方法就是使用此密钥。", + "RECOVER_KEY_GENERATION_FAILED": "无法生成恢复代码,请重试", + "KEY_NOT_STORED_DISCLAIMER": "我们不存储此密钥,因此请将其保存在安全的地方", + "FORGOT_PASSWORD": "忘记密码", + "RECOVER_ACCOUNT": "恢复账户", + "RECOVERY_KEY_HINT": "恢复密钥", + "RECOVER": "恢复", + "NO_RECOVERY_KEY": "没有恢复密钥?", + "INCORRECT_RECOVERY_KEY": "不正确的恢复密钥", + "SORRY": "抱歉", + "NO_RECOVERY_KEY_MESSAGE": "由于我们端到端加密协议的性质,如果没有您的密码或恢复密钥,您的数据将无法解密", + "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "请用您注册ente账户的电子邮箱发一封邮件给 {{emailID}}", + "CONTACT_SUPPORT": "联系支持", + "REQUEST_FEATURE": "功能建议", + "SUPPORT": "支持", + "CONFIRM": "确认", + "CANCEL": "取消", + "LOGOUT": "退出登录", + "DELETE_ACCOUNT": "删除账户", + "DELETE_ACCOUNT_MESSAGE": "

请从您注册的电子邮件地址发送一封电子邮件到 {{emailID}}

。您的请求将在72小时内处理。

", + "LOGOUT_MESSAGE": "你确定要退出登录吗?", + "CHANGE_EMAIL": "更换邮箱", + "OK": "确定", + "SUCCESS": "成功", + "ERROR": "错误", + "MESSAGE": "消息", + "INSTALL_MOBILE_APP": "安装我们的 AndroidiOS 应用程序来自动备份您的所有照片", + "DOWNLOAD_APP_MESSAGE": "抱歉,目前只有我们的桌面应用程序支持此操作", + "DOWNLOAD_APP": "下载桌面应用程序", + "EXPORT": "导出数据", + "SUBSCRIPTION": "订阅", + "SUBSCRIBE": "订阅", + "MANAGEMENT_PORTAL": "管理付款方式", + "MANAGE_FAMILY_PORTAL": "管理家庭", + "LEAVE_FAMILY_PLAN": "离开家庭计划", + "LEAVE": "离开", + "LEAVE_FAMILY_CONFIRM": "您确定要离开家庭计划吗?", + "CHOOSE_PLAN": "选择您的计划", + "MANAGE_PLAN": "管理您的订阅", + "ACTIVE": "已激活", + "OFFLINE_MSG": "您处于离线状态,正在显示已缓存的回忆", + "FREE_SUBSCRIPTION_INFO": "您使用的是将于{{date, dateTime}} 过期的免费计划", + "FAMILY_SUBSCRIPTION_INFO": "您正在使用由 管理的家庭计划", + "RENEWAL_ACTIVE_SUBSCRIPTION_STATUS": "于 {{date, dateTime}} 续费", + "RENEWAL_CANCELLED_SUBSCRIPTION_STATUS": "结束于 {{date, dateTime}}", + "RENEWAL_CANCELLED_SUBSCRIPTION_INFO": "您的订阅将于 {{date, dateTime}} 取消", + "ADD_ON_AVAILABLE_TILL": "您的 {{storage, string}} 插件有效期至 {{date, dateTime}}", + "STORAGE_QUOTA_EXCEEDED_SUBSCRIPTION_INFO": "您已超过您的存储配额,请 升级", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

我们已经收到您的付款

您的订阅有效期至 {{date, dateTime}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "您的购买已取消,如果您想订阅,请重试", + "SUBSCRIPTION_PURCHASE_FAILED": "订阅购买失败,请重试", + "SUBSCRIPTION_UPDATE_FAILED": "订阅更新失败,请重试", + "UPDATE_PAYMENT_METHOD_MESSAGE": "很抱歉,我们尝试从您的卡中扣款时支付失败,请更新您的付款方式并重试", + "STRIPE_AUTHENTICATION_FAILED": "我们无法验证您的付款方式。请选择不同的付款方式并重试", + "UPDATE_PAYMENT_METHOD": "更新付款方式", + "MONTHLY": "每月", + "YEARLY": "每年", + "UPDATE_SUBSCRIPTION_MESSAGE": "您确定要更改您的计划吗?", + "UPDATE_SUBSCRIPTION": "更改计划", + "CANCEL_SUBSCRIPTION": "取消订阅", + "CANCEL_SUBSCRIPTION_MESSAGE": "

您的所有数据将在此计费期结束时从我们的服务器中删除。

您确定要取消您的订阅吗?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

您确定要取消订阅吗?

", + "SUBSCRIPTION_CANCEL_FAILED": "取消订阅失败", + "SUBSCRIPTION_CANCEL_SUCCESS": "订阅成功取消", + "REACTIVATE_SUBSCRIPTION": "重新激活订阅", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "重新激活后,您将在 {{date, dateTime}} 前支付费用", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "订阅已成功激活 ", + "SUBSCRIPTION_ACTIVATE_FAILED": "无法重新激活订阅续费", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "非常感谢您", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "取消手机订阅", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "请从手机应用取消您的订阅以激活这里的订阅", + "MAIL_TO_MANAGE_SUBSCRIPTION": "请联系我们 {{emailID}} 来管理您的订阅", + "RENAME": "重命名", + "RENAME_FILE": "重命名文件", + "RENAME_COLLECTION": "重命名相册", + "DELETE_COLLECTION_TITLE": "要删除相册吗?", + "DELETE_COLLECTION": "删除相册", + "DELETE_COLLECTION_MESSAGE": "也删除此相册中存在的照片(和视频),从 他们所加入的所有 个其他相册?", + "DELETE_PHOTOS": "删除照片", + "KEEP_PHOTOS": "保留照片", + "SHARE": "分享", + "SHARE_COLLECTION": "分享相册", + "SHAREES": "已分享给", + "SHARE_WITH_SELF": "哎呀,您不能与自己分享", + "ALREADY_SHARED": "哎呀,您已经和 {{email}} 分享了", + "SHARING_BAD_REQUEST_ERROR": "不允许分享相册", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "免费账户禁用共享", + "DOWNLOAD_COLLECTION": "下载相册", + "DOWNLOAD_COLLECTION_MESSAGE": "

您确定要下载完整相册吗?

所有文件都将按顺序排队进行下载

", + "CREATE_ALBUM_FAILED": "相册创建失败,请重试", + "SEARCH": "搜索", + "SEARCH_RESULTS": "搜索结果", + "NO_RESULTS": "未找到任何结果", + "SEARCH_HINT": "搜索相册、日期...", + "SEARCH_TYPE": { + "COLLECTION": "相册", + "LOCATION": "地理位置", + "CITY": "位置", + "DATE": "日期", + "FILE_NAME": "文件名", + "THING": "内容", + "FILE_CAPTION": "说明", + "FILE_TYPE": "文件类型", + "CLIP": "魔法" + }, + "photos_count_zero": "没有回忆", + "photos_count_one": "1个回忆", + "photos_count_other": "{{count, number}} 个回忆", + "TERMS_AND_CONDITIONS": "我同意 条款隐私政策", + "ADD_TO_COLLECTION": "添加到相册", + "SELECTED": "已选", + "VIDEO_PLAYBACK_FAILED_DOWNLOAD_INSTEAD": "此视频无法在您的浏览器中播放", + "PEOPLE": "人物", + "INDEXING_SCHEDULED": "索引已安排...", + "ANALYZING_PHOTOS": "分析 {{indexStatus.nTotalFiles}} 的新照片{{indexStatus.nSyncedFiles}} 已完成)...", + "INDEXING_PEOPLE": "正在为 {{indexStatus.nSyncedFiles}} 张照片中的人物建立索引...", + "INDEXING_DONE": "已索引 {{indexStatus.nSyncedFiles}} 张照片", + "UNIDENTIFIED_FACES": "身份不明的面孔", + "OBJECTS": "对象", + "TEXT": "文本", + "INFO": "图片信息 ", + "INFO_OPTION": "图片信息 (I)", + "FILE_NAME": "文件名", + "CAPTION_PLACEHOLDER": "添加说明", + "LOCATION": "地理位置", + "SHOW_ON_MAP": "在 OpenStreetMap 上查看", + "MAP": "地图", + "MAP_SETTINGS": "地图设置", + "ENABLE_MAPS": "要启用地图吗?", + "ENABLE_MAP": "启用地图", + "DISABLE_MAPS": "要禁用地图吗?", + "ENABLE_MAP_DESCRIPTION": "

这将在世界地图上显示您的照片。

该地图由 OpenStreetMap 托管,并且您照片的确切位置永远不会共享。

您可以随时从“设置”中禁用此功能。

", + "DISABLE_MAP_DESCRIPTION": "

这将禁止在世界地图上显示您的照片。

您可以随时从“设置”中启用此功能。

", + "DISABLE_MAP": "禁用地图", + "DETAILS": "详情", + "VIEW_EXIF": "查看所有 EXIF 数据", + "NO_EXIF": "无 EXIF 数据", + "EXIF": "EXIF", + "ISO": "ISO", + "TWO_FACTOR": "双因素", + "TWO_FACTOR_AUTHENTICATION": "双因素认证", + "TWO_FACTOR_QR_INSTRUCTION": "使用您最喜欢的身份验证器应用程序(2FA)扫描下面的二维码", + "ENTER_CODE_MANUALLY": "请手动输入代码", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "请在您最喜欢的验证器应用中输入此代码", + "SCAN_QR_CODE": "改为扫描二维码", + "ENABLE_TWO_FACTOR": "启用双因素认证", + "ENABLE": "启用", + "LOST_DEVICE": "丢失了双因素认证设备", + "INCORRECT_CODE": "代码错误", + "TWO_FACTOR_INFO": "登录您的账户不仅需要您的电子邮件和密码,还需要额外的安全层", + "DISABLE_TWO_FACTOR_LABEL": "禁用双因素认证", + "UPDATE_TWO_FACTOR_LABEL": "更新您的身份验证器设备", + "DISABLE": "禁用", + "RECONFIGURE": "重新配置", + "UPDATE_TWO_FACTOR": "更新双因素认证", + "UPDATE_TWO_FACTOR_MESSAGE": "向前继续将使之前配置的任何身份验证器无效", + "UPDATE": "更新", + "DISABLE_TWO_FACTOR": "禁用双因素认证", + "DISABLE_TWO_FACTOR_MESSAGE": "您确定要禁用您的双因素认证吗?", + "TWO_FACTOR_DISABLE_FAILED": "禁用双因素认证失败,请再试一次", + "EXPORT_DATA": "导出数据", + "SELECT_FOLDER": "选择文件夹", + "DESTINATION": "目标位置", + "START": "开始", + "LAST_EXPORT_TIME": "最后一次导出时间", + "EXPORT_AGAIN": "重新同步", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "无法访问本地存储", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "您的浏览器或插件阻止 ente 将数据保存到本地存储。 请在切换浏览模式后再尝试加载此页面。", + "SEND_OTT": "发送 OTP", + "EMAIl_ALREADY_OWNED": "电子邮箱已被注册", + "ETAGS_BLOCKED": "

由于您的浏览器配置,我们无法上传以下文件。

请禁用任何可能阻止ente 使用 eTags 上传大文件的附加组件, 或者使用我们的 桌面应用程序 获取更可靠的导入体验。

", + "SKIPPED_VIDEOS_INFO": "

目前,我们不支持在公共链接内添加视频。

若要分享视频,请 注册 并通过电子邮件与预定收件人分享。

", + "LIVE_PHOTOS_DETECTED": "Live Photos 中的照片和视频文件已合并为一个文件", + "RETRY_FAILED": "重试上传失败的文件", + "FAILED_UPLOADS": "上传失败 ", + "SKIPPED_FILES": "已忽略的上传内容", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "缩略图生成失败", + "UNSUPPORTED_FILES": "不支持的文件", + "SUCCESSFUL_UPLOADS": "上传成功", + "SKIPPED_INFO": "跳过这些,因为在同一相册中有具有匹配名称的文件", + "UNSUPPORTED_INFO": "ente 尚不支持这些文件格式", + "BLOCKED_UPLOADS": "已阻止上传", + "SKIPPED_VIDEOS": "已跳过的视频", + "INPROGRESS_METADATA_EXTRACTION": "进行中", + "INPROGRESS_UPLOADS": "上传进行中", + "TOO_LARGE_UPLOADS": "大文件", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "存储空间不足", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "这些文件没有上传,因为它们超过了您的存储计划的最大大小限制", + "TOO_LARGE_INFO": "这些文件没有上传,因为它们超过了我们的最大文件大小限制", + "THUMBNAIL_GENERATION_FAILED_INFO": "这些文件已上传,但遗憾的是,我们无法为它们生成缩略图。", + "UPLOAD_TO_COLLECTION": "上传至相册", + "UNCATEGORIZED": "未分类的", + "ARCHIVE": "存档", + "FAVORITES": "收藏", + "ARCHIVE_COLLECTION": "存档相册", + "ARCHIVE_SECTION_NAME": "存档", + "ALL_SECTION_NAME": "全部", + "MOVE_TO_COLLECTION": "移动到相册", + "UNARCHIVE": "取消存档", + "UNARCHIVE_COLLECTION": "取消存档相册", + "HIDE_COLLECTION": "隐藏相册", + "UNHIDE_COLLECTION": "取消隐藏相册", + "MOVE": "移动", + "ADD": "添加", + "REMOVE": "移除", + "YES_REMOVE": "是,移除", + "REMOVE_FROM_COLLECTION": "从相册中移除", + "TRASH": "回收站", + "MOVE_TO_TRASH": "移动到回收站", + "TRASH_FILES_MESSAGE": "选中的文件将从所有相册中删除并移动到回收站。", + "TRASH_FILE_MESSAGE": "该文件将从所有相册中删除并移动到回收站。", + "DELETE_PERMANENTLY": "永久删除", + "RESTORE": "恢复", + "RESTORE_TO_COLLECTION": "恢复到相册", + "EMPTY_TRASH": "清空回收站", + "EMPTY_TRASH_TITLE": "要清空回收站吗?", + "EMPTY_TRASH_MESSAGE": "这些文件将从您的 ente 账户中永久删除。", + "LEAVE_SHARED_ALBUM": "是,离开", + "LEAVE_ALBUM": "离开相册", + "LEAVE_SHARED_ALBUM_TITLE": "要离开共享相册吗?", + "LEAVE_SHARED_ALBUM_MESSAGE": "您将离开相册,它将不再对您可见。", + "NOT_FILE_OWNER": "您不能删除共享相册中的文件", + "CONFIRM_SELF_REMOVE_MESSAGE": "所选项目将从该相册中删除。 仅在此相册中的项目将移至未分类。", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "您要删除的某些项目是由其他人添加的,您将无法访问它们。", + "SORT_BY_CREATION_TIME_ASCENDING": "最早的", + "SORT_BY_UPDATION_TIME_DESCENDING": "最后更新", + "SORT_BY_NAME": "名称", + "COMPRESS_THUMBNAILS": "压缩缩略图", + "THUMBNAIL_REPLACED": "缩略图已压缩", + "FIX_THUMBNAIL": "压缩", + "FIX_THUMBNAIL_LATER": "稍后压缩", + "REPLACE_THUMBNAIL_NOT_STARTED": "您的一些视频缩略图可以被压缩以节省空间,您想要ente 压缩它们吗?", + "REPLACE_THUMBNAIL_COMPLETED": "已成功压缩所有缩略图", + "REPLACE_THUMBNAIL_NOOP": "您没有可以进一步压缩的缩略图", + "REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR": "无法压缩您的一些缩略图,请重试", + "FIX_CREATION_TIME": "固定时间", + "FIX_CREATION_TIME_IN_PROGRESS": "正在固定时间", + "CREATION_TIME_UPDATED": "文件时间已更新", + "UPDATE_CREATION_TIME_NOT_STARTED": "选择您想要使用的选项", + "UPDATE_CREATION_TIME_COMPLETED": "已成功更新所有文件", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "部分文件的文件时间更新失败,请重试", + "CAPTION_CHARACTER_LIMIT": "5000个字符上限", + "DATE_TIME_ORIGINAL": "EXIF:日期 时间 原始文件", + "DATE_TIME_DIGITIZED": "EXIF:日期 时间 数字化", + "METADATA_DATE": "EXIF:元数据日期", + "CUSTOM_TIME": "自定义时间", + "REOPEN_PLAN_SELECTOR_MODAL": "重新启动计划", + "OPEN_PLAN_SELECTOR_MODAL_FAILED": "未能打开计划", + "INSTALL": "安装", + "SHARING_DETAILS": "共享的详细信息", + "MODIFY_SHARING": "更改共享", + "ADD_COLLABORATORS": "添加协作者", + "ADD_NEW_EMAIL": "添加新的电子邮件", + "shared_with_people_zero": "与特定人员分享", + "shared_with_people_one": "已与1个人共享", + "shared_with_people_other": "已与 {count, number} 个人共享", + "participants_zero": "暂无参与者", + "participants_one": "1 名参与者", + "participants_other": "{{count, number}} 名参与者", + "ADD_VIEWERS": "添加查看者", + "PARTICIPANTS": "参与者", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} 将无法向相册添加更多照片

他们仍然可以删除他们添加的照片

", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} 将能够将照片添加到相册", + "CONVERT_TO_VIEWER": "是的,转换为查看者", + "CONVERT_TO_COLLABORATOR": "是,转换为协作者", + "CHANGE_PERMISSION": "要修改权限吗?", + "REMOVE_PARTICIPANT": "要移除吗?", + "CONFIRM_REMOVE": "是,移除", + "MANAGE": "管理", + "ADDED_AS": "已添加为", + "COLLABORATOR_RIGHTS": "协作者可以将照片和视频添加到共享相册中", + "REMOVE_PARTICIPANT_HEAD": "移除参与者", + "OWNER": "所有者", + "COLLABORATORS": "协作者", + "ADD_MORE": "添加更多", + "VIEWERS": "查看者", + "OR_ADD_EXISTING": "或选择一个现有的", + "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} 将从相册中删除

他们添加的所有照片也将从相册中删除

", + "NOT_FOUND": "404 - 未找到", + "LINK_EXPIRED": "链接已过期", + "LINK_EXPIRED_MESSAGE": "此链接已过期或已被禁用!", + "MANAGE_LINK": "管理链接", + "LINK_TOO_MANY_REQUESTS": "这个相册太受欢迎,我们无法处理!", + "FILE_DOWNLOAD": "允许下载", + "LINK_PASSWORD_LOCK": "密码锁", + "PUBLIC_COLLECT": "允许添加照片", + "LINK_DEVICE_LIMIT": "设备限制", + "NO_DEVICE_LIMIT": "无", + "LINK_EXPIRY": "链接过期", + "NEVER": "永不", + "DISABLE_FILE_DOWNLOAD": "禁止下载", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "

您确定要禁用文件下载按钮吗?

观看者仍然可以使用外部工具进行屏幕截图或保存您的照片副本。

", + "MALICIOUS_CONTENT": "哈哈哈急急急", + "COPYRIGHT": "不不不急急急就是", + "SHARED_USING": "分享方式 ", + "ENTE_IO": "ente.io", + "SHARING_REFERRAL_CODE": "使用代码 {{referralCode}} 获得 10 GB 免费空间", + "LIVE": "LIVE", + "DISABLE_PASSWORD": "禁用密码锁", + "DISABLE_PASSWORD_MESSAGE": "您确定要禁用密码锁吗?", + "PASSWORD_LOCK": "密码锁", + "LOCK": "锁定", + "DOWNLOAD_UPLOAD_LOGS": "调试日志", + "UPLOAD_FILES": "文件", + "UPLOAD_DIRS": "文件夹", + "UPLOAD_GOOGLE_TAKEOUT": "Google Takeout", + "DEDUPLICATE_FILES": "删除重复文件", + "AUTHENTICATOR_SECTION": "身份验证器", + "NO_DUPLICATES_FOUND": "您没有可以清除的重复文件", + "CLUB_BY_CAPTURE_TIME": "按抓取时间断开", + "FILES": "文件", + "EACH": "每个", + "DEDUPLICATE_BASED_ON_SIZE": "以下文件根据大小进行了合并,请检查并删除您认为重复的项目", + "STOP_ALL_UPLOADS_MESSAGE": "您确定要停止所有正在进行的上传吗?", + "STOP_UPLOADS_HEADER": "要停止上传吗?", + "YES_STOP_UPLOADS": "是的,停止上传", + "STOP_DOWNLOADS_HEADER": "要停止下载吗?", + "YES_STOP_DOWNLOADS": "是,停止下载", + "STOP_ALL_DOWNLOADS_MESSAGE": "您确定要停止所有正在进行的下载?", + "albums_one": "1个相册", + "albums_other": "{{count, number}} 个相册", + "ALL_ALBUMS": "所有相册", + "ALBUMS": "相册", + "ALL_HIDDEN_ALBUMS": "所有隐藏的相册", + "HIDDEN_ALBUMS": "隐藏的相册", + "HIDDEN_ITEMS": "隐藏的项目", + "HIDDEN_ITEMS_SECTION_NAME": "隐藏的项目", + "ENTER_TWO_FACTOR_OTP": "请输入您从身份验证应用上获得的6位数代码", + "CREATE_ACCOUNT": "创建账户", + "COPIED": "已复制", + "CANVAS_BLOCKED_TITLE": "无法生成缩略图", + "CANVAS_BLOCKED_MESSAGE": "

看起来您的浏览器已禁用了需要为您的照片生成缩略图的canvas访问权限

请允许访问您浏览器的canvas, 或使用我们的桌面应用程序

", + "WATCH_FOLDERS": "观看文件夹", + "UPGRADE_NOW": "立即升级", + "RENEW_NOW": "立即续费", + "STORAGE": "存储空间", + "USED": "已使用", + "YOU": "您", + "FAMILY": "家庭", + "FREE": "空闲", + "OF": "/", + "WATCHED_FOLDERS": "观看文件夹", + "NO_FOLDERS_ADDED": "尚未添加任何文件夹!", + "FOLDERS_AUTOMATICALLY_MONITORED": "您在此处添加的文件夹将自动监控", + "UPLOAD_NEW_FILES_TO_ENTE": "上传新文件至 ente", + "REMOVE_DELETED_FILES_FROM_ENTE": "从ente 移除已删除的文件", + "ADD_FOLDER": "添加文件夹", + "STOP_WATCHING": "停止监控", + "STOP_WATCHING_FOLDER": "要停止监控文件夹?", + "STOP_WATCHING_DIALOG_MESSAGE": "您现有的文件不会被删除,但 ente 将停止自动更新链接的 ente 相册在此文件夹中的更改。", + "YES_STOP": "是的,停止", + "MONTH_SHORT": "月", + "YEAR": "年", + "FAMILY_PLAN": "家庭计划", + "DOWNLOAD_LOGS": "下载日志", + "DOWNLOAD_LOGS_MESSAGE": "

这将下载调试日志,您可以发送电子邮件给我们来帮助调试您的问题。

请注意文件名将被包含,以帮助跟踪特定文件中的问题。

", + "CHANGE_FOLDER": "更改文件夹", + "TWO_MONTHS_FREE": "在年度计划上免费获得 2 个月", + "GB": "GB", + "POPULAR": "流行的", + "FREE_PLAN_OPTION_LABEL": "继续免费试用", + "FREE_PLAN_DESCRIPTION": "1 GB 1年", + "CURRENT_USAGE": "当前使用量是 {{usage}}", + "WEAK_DEVICE": "您使用的网络浏览器功能不够强大,无法加密您的照片。 请尝试在电脑上登录ente,或下载ente移动/桌面应用程序。", + "DRAG_AND_DROP_HINT": "或者拖动并拖动到 ente 窗口", + "CONFIRM_ACCOUNT_DELETION_MESSAGE": "您上传的数据将被安排删除,您的账户将被永久删除。

此操作不可逆。", + "AUTHENTICATE": "身份认证", + "UPLOADED_TO_SINGLE_COLLECTION": "已上传到单个收藏", + "UPLOADED_TO_SEPARATE_COLLECTIONS": "已上传到单独收藏", + "NEVERMIND": "没关系", + "UPDATE_AVAILABLE": "有可用的更新", + "UPDATE_INSTALLABLE_MESSAGE": "新版本的 ente 已准备好安装。", + "INSTALL_NOW": "立即安装", + "INSTALL_ON_NEXT_LAUNCH": "在下次启动时安装", + "UPDATE_AVAILABLE_MESSAGE": "新版本的 ente 已发布,但无法自动下载和安装。", + "DOWNLOAD_AND_INSTALL": "下载并安装", + "IGNORE_THIS_VERSION": "忽略该版本", + "TODAY": "今天", + "YESTERDAY": "昨天", + "NAME_PLACEHOLDER": "名称...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "无法从文件/文件夹组合中创建相册", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

你已拖放了文件和文件夹的组合。

选择创建单独相册的选项时,请只提供文件或只提供文件夹

", + "CHOSE_THEME": "选择主题", + "ML_SEARCH": "ML 搜索 (测试版)", + "ENABLE_ML_SEARCH_DESCRIPTION": "

这将启用设备上的机器学习和面部搜索,这将开始分析您上传的本地照片。

在登录或启用此功能后第一次运行时,它将下载本地设备上的所有图像来分析。 所以请只在您可以使用带宽和本地处理您的照片库中的所有图像时启用此功能。

如果这是您首次启用此功能,我们也会请求您处理面部数据的许可。

", + "ML_MORE_DETAILS": "更多详情", + "ENABLE_FACE_SEARCH": "启用面部搜索", + "ENABLE_FACE_SEARCH_TITLE": "要启用面部搜索吗?", + "ENABLE_FACE_SEARCH_DESCRIPTION": "

如果您启用面部搜索,ente 将从照片中提取脸部几何形状。 这将发生在您的设备上,任何生成的生物测定数据都将是端到端加密的。

请单击此处以在我们的隐私政策中了解有关此功能的更多详细信息

", + "DISABLE_BETA": "禁用beta", + "DISABLE_FACE_SEARCH": "禁用面部搜索", + "DISABLE_FACE_SEARCH_TITLE": "要禁用面部搜索吗?", + "DISABLE_FACE_SEARCH_DESCRIPTION": "

ente 将停止处理面部的几何形状, 并将禁用 ML 搜索 (测试版)

如果您愿意,您可以重新启用面部搜索,因此该操作是安全的。

", + "ADVANCED": "高级设置", + "FACE_SEARCH_CONFIRMATION": "我理解,并希望允许ente处理面部几何形状", + "LABS": "实验室", + "YOURS": "你的", + "PASSPHRASE_STRENGTH_WEAK": "密码强度:较弱", + "PASSPHRASE_STRENGTH_MODERATE": "密码强度:中度", + "PASSPHRASE_STRENGTH_STRONG": "密码强度:强", + "PREFERENCES": "首选项", + "LANGUAGE": "语言", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "无效的导出目录", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

您选择的导出目录不存在。

请选择一个有效的目录。

", + "SUBSCRIPTION_VERIFICATION_ERROR": "订阅验证失败", + "STORAGE_UNITS": { + "B": "B", + "KB": "KB", + "MB": "MB", + "GB": "GB", + "TB": "TB" + }, + "AFTER_TIME": { + "HOUR": "1小时后", + "DAY": "一天后", + "WEEK": "一周后", + "MONTH": "一个月后", + "YEAR": "一年后" + }, + "COPY_LINK": "复制链接", + "DONE": "已完成", + "LINK_SHARE_TITLE": "或共享一个链接", + "REMOVE_LINK": "移除链接", + "CREATE_PUBLIC_SHARING": "创建公开链接", + "PUBLIC_LINK_CREATED": "公开链接已创建", + "PUBLIC_LINK_ENABLED": "公开链接已启用", + "COLLECT_PHOTOS": "收集照片", + "PUBLIC_COLLECT_SUBTEXT": "允许具有链接的人也将照片添加到共享相册。", + "STOP_EXPORT": "停止", + "EXPORT_PROGRESS": "{{progress.success}} / {{progress.total}} 个文件已导出", + "MIGRATING_EXPORT": "准备中...", + "RENAMING_COLLECTION_FOLDERS": "正在重命名相册文件夹...", + "TRASHING_DELETED_FILES": "正在回收删除的文件...", + "TRASHING_DELETED_COLLECTIONS": "正在回收已删除的相册...", + "EXPORT_NOTIFICATION": { + "START": "导出已开始", + "IN_PROGRESS": "导出已在进行中", + "FINISH": "导出完成", + "UP_TO_DATE": "没有新文件可导出" + }, + "CONTINUOUS_EXPORT": "持续同步", + "TOTAL_ITEMS": "项目总计", + "PENDING_ITEMS": "待处理的项目", + "EXPORT_STARTING": "导出开始...", + "DELETE_ACCOUNT_REASON_LABEL": "您删除账户的主要原因是什么?", + "DELETE_ACCOUNT_REASON_PLACEHOLDER": "选择一个原因", + "DELETE_REASON": { + "MISSING_FEATURE": "找不到我想要的功能", + "BROKEN_BEHAVIOR": "该应用或某个功能不符合我认为应该做的行为", + "FOUND_ANOTHER_SERVICE": "我发现另一个产品更好用", + "NOT_LISTED": "我的原因未被列出" + }, + "DELETE_ACCOUNT_FEEDBACK_LABEL": "我们很抱歉看到您离开。请解释您为什么要离开来帮助我们改进。", + "DELETE_ACCOUNT_FEEDBACK_PLACEHOLDER": "反馈", + "CONFIRM_DELETE_ACCOUNT_CHECKBOX_LABEL": "是的,我想永久删除此账户及其相关数据", + "CONFIRM_DELETE_ACCOUNT": "确认删除账户", + "FEEDBACK_REQUIRED": "请帮助我们了解这个信息", + "FEEDBACK_REQUIRED_FOUND_ANOTHER_SERVICE": "其他服务做得更好?", + "RECOVER_TWO_FACTOR": "恢复双因素认证", + "at": "在", + "AUTH_NEXT": "下一个", + "AUTH_DOWNLOAD_MOBILE_APP": "下载我们的移动应用程序来管理您的密钥", + "HIDDEN": "已隐藏", + "HIDE": "隐藏", + "UNHIDE": "取消隐藏", + "UNHIDE_TO_COLLECTION": "取消隐藏到相册", + "SORT_BY": "排序方式", + "NEWEST_FIRST": "最新在前", + "OLDEST_FIRST": "最旧在前", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "无法预览此文件。点击这里下载原始文件。", + "SELECT_COLLECTION": "选择相册", + "PIN_ALBUM": "置顶相册", + "UNPIN_ALBUM": "取消置顶相册", + "DOWNLOAD_COMPLETE": "下载完成", + "DOWNLOADING_COLLECTION": "正在下载 {{name}}", + "DOWNLOAD_FAILED": "下载失败", + "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} 个文件", + "CHRISTMAS": "圣诞", + "CHRISTMAS_EVE": "平安夜", + "NEW_YEAR": "新年", + "NEW_YEAR_EVE": "除夕", + "IMAGE": "图像", + "VIDEO": "视频", + "LIVE_PHOTO": "实况照片", + "CONVERT": "转换", + "CONFIRM_EDITOR_CLOSE_MESSAGE": "您确定要关闭编辑器吗?", + "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "下载已编辑的图片或将副本保存到 ente 以保留您的更改。", + "BRIGHTNESS": "亮度", + "CONTRAST": "对比度", + "SATURATION": "饱和度", + "BLUR": "模糊", + "INVERT_COLORS": "反相颜色", + "ASPECT_RATIO": "长宽比", + "SQUARE": "面积", + "ROTATE_LEFT": "向左旋转", + "ROTATE_RIGHT": "向右旋转", + "FLIP_VERTICALLY": "垂直翻转", + "FLIP_HORIZONTALLY": "水平翻转", + "DOWNLOAD_EDITED": "下载已编辑图片", + "SAVE_A_COPY_TO_ENTE": "保存副本到 ente", + "RESTORE_ORIGINAL": "复原", + "TRANSFORM": "转换", + "COLORS": "颜色", + "FLIP": "上下翻转", + "ROTATION": "回转", + "RESET": "重设", + "PHOTO_EDITOR": "照片编辑器", + "FASTER_UPLOAD": "更快上传", + "FASTER_UPLOAD_DESCRIPTION": "通过附近的服务器路由上传", + "MAGIC_SEARCH_STATUS": "魔法搜索状态", + "INDEXED_ITEMS": "索引项目", + "CAST_ALBUM_TO_TV": "在电视上播放相册", + "ENTER_CAST_PIN_CODE": "输入您在下面的电视上看到的代码来配对此设备。", + "PAIR_DEVICE_TO_TV": "配对设备", + "TV_NOT_FOUND": "未找到电视。您输入的 PIN 码正确吗?", + "AUTO_CAST_PAIR": "自动配对", + "AUTO_CAST_PAIR_REQUIRES_CONNECTION_TO_GOOGLE": "自动配对需要连接到 Google 服务器,且仅适用于支持 Chromecast 的设备。Google 不会接收敏感数据,例如您的照片。", + "PAIR_WITH_PIN": "用 PIN 配对", + "CHOOSE_DEVICE_FROM_BROWSER": "从浏览器弹出窗口中选择兼容 Cast 的设备。", + "PAIR_WITH_PIN_WORKS_FOR_ANY_LARGE_SCREEN_DEVICE": "用 PIN 配对适用于任何大屏幕设备,您可以在这些设备上播放您的相册。", + "VISIT_CAST_ENTE_IO": "在您要配对的设备上访问 cast.ente.io 。", + "CAST_AUTO_PAIR_FAILED": "Chromecast 自动配对失败。请再试一次。", + "CACHE_DIRECTORY": "缓存文件夹", + "FREEHAND": "手画", + "APPLY_CROP": "应用裁剪", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "保存之前必须至少执行一项转换或颜色调整。", + "PASSKEYS": "通行密钥", + "DELETE_PASSKEY": "", + "DELETE_PASSKEY_CONFIRMATION": "", + "RENAME_PASSKEY": "", + "ADD_PASSKEY": "", + "ENTER_PASSKEY_NAME": "", + "PASSKEYS_DESCRIPTION": "", + "CREATED_AT": "", + "PASSKEY_LOGIN_FAILED": "", + "PASSKEY_LOGIN_URL_INVALID": "", + "PASSKEY_LOGIN_ERRORED": "", + "TRY_AGAIN": "", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", + "LOGIN_WITH_PASSKEY": "" +} From 2486a94d2198dcd122edf4b13b61062f2c329f80 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 21:19:42 +0530 Subject: [PATCH 376/391] Add the service the serves status.ente.io --- infra/services/status/README.md | 39 +++++++++++++++++++++++ infra/services/status/uptime-kuma.conf | 19 +++++++++++ infra/services/status/uptime-kuma.service | 16 ++++++++++ 3 files changed, 74 insertions(+) create mode 100644 infra/services/status/README.md create mode 100644 infra/services/status/uptime-kuma.conf create mode 100644 infra/services/status/uptime-kuma.service diff --git a/infra/services/status/README.md b/infra/services/status/README.md new file mode 100644 index 0000000000..51166f424a --- /dev/null +++ b/infra/services/status/README.md @@ -0,0 +1,39 @@ +# Status + +Our status page ([status.ente.io](https://status.ente.io)) is a self-hosted +[Uptime Kuma](https://github.com/louislam/uptime-kuma). + +## Installing + +Install [nginx](../nginx/README.md). + +Create a directory where Uptime Kuma will keep its state. This is the directory +we can optionally backup if we wish to preserve history and settings when moving +instances in the future. + +```sh +sudo mkdir -p /root/uptime-kuma +``` + +Add the service definition and nginx configuration. + +```sh +scp services/status/uptime-kuma.* : + +sudo mv uptime-kuma.service /etc/systemd/system/uptime-kuma.service +sudo mv uptime-kuma.nginx.conf /root/nginx/conf.d +``` + +Tell systemd to pick up new service definitions, enable the unit (so that it +automatically starts on boot), and start it this time around. + +```sh +sudo systemctl daemon-reload +sudo systemctl enable --now uptime-kuma +``` + +Restart nginx + +```sh +sudo systemctl restart nginx +``` diff --git a/infra/services/status/uptime-kuma.conf b/infra/services/status/uptime-kuma.conf new file mode 100644 index 0000000000..6c3b08b332 --- /dev/null +++ b/infra/services/status/uptime-kuma.conf @@ -0,0 +1,19 @@ +# This file gets loaded in a top level http block by the default nginx.conf +# See infra/services/nginx/README.md for more details. + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + ssl_certificate /etc/ssl/certs/cert.pem; + ssl_certificate_key /etc/ssl/private/key.pem; + + server_name status.ente.io; + + location / { + proxy_pass http://host.docker.internal:3001; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/infra/services/status/uptime-kuma.service b/infra/services/status/uptime-kuma.service new file mode 100644 index 0000000000..11789d8c48 --- /dev/null +++ b/infra/services/status/uptime-kuma.service @@ -0,0 +1,16 @@ +[Unit] +Documentation=https://github.com/louislam/uptime-kuma +Requires=docker.service +After=docker.service + +[Install] +WantedBy=multi-user.target + +[Service] +ExecStartPre=docker pull louislam/uptime-kuma:1 +ExecStartPre=-docker stop uptime-kuma +ExecStartPre=-docker rm uptime-kuma +ExecStart=docker run --name uptime-kuma \ + -p 3001:3001 \ + -v /root/uptime-kuma:/app/data \ + louislam/uptime-kuma:1 From 64c95d239747c8dbd12c66601b953981781a1b6d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 21:34:24 +0530 Subject: [PATCH 377/391] Tweak formatting --- infra/services/nginx/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/infra/services/nginx/README.md b/infra/services/nginx/README.md index 6d46b4de18..75c2c77980 100644 --- a/infra/services/nginx/README.md +++ b/infra/services/nginx/README.md @@ -16,12 +16,16 @@ sudo mv nginx.service /etc/systemd/system/nginx.service Create a directory to house service specific configuration - sudo mkdir -p /root/nginx/conf.d +```sh +sudo mkdir -p /root/nginx/conf.d +``` Add the SSL certificate provided by Cloudflare - sudo tee /root/nginx/cert.pem - sudo tee /root/nginx/key.pem +```sh +sudo tee /root/nginx/cert.pem +sudo tee /root/nginx/key.pem +``` Tell systemd to pick up new service definition, enable it (so that it automatically starts on boot going forward), and start it. From ba896f2f3af50b77e97bce242a1fa68cfb6633d3 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 21:36:01 +0530 Subject: [PATCH 378/391] Match file name convention --- .../services/status/{uptime-kuma.conf => uptime-kuma.nginx.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename infra/services/status/{uptime-kuma.conf => uptime-kuma.nginx.conf} (100%) diff --git a/infra/services/status/uptime-kuma.conf b/infra/services/status/uptime-kuma.nginx.conf similarity index 100% rename from infra/services/status/uptime-kuma.conf rename to infra/services/status/uptime-kuma.nginx.conf From 19724367dfb3c56e72124b9830b9d5793911b009 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 21:45:02 +0530 Subject: [PATCH 379/391] Support nginx configuration reloads --- infra/services/nginx/README.md | 7 ++++--- infra/services/nginx/nginx.service | 2 ++ infra/services/status/README.md | 4 ++-- server/scripts/deploy/README.md | 2 +- server/scripts/deploy/museum.nginx.service | 1 + 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/infra/services/nginx/README.md b/infra/services/nginx/README.md index 75c2c77980..7239a56104 100644 --- a/infra/services/nginx/README.md +++ b/infra/services/nginx/README.md @@ -2,7 +2,7 @@ This is a base Nginx service that terminates TLS, and can be used as a reverse proxy for arbitrary services by adding new entries in `/root/nginx/conf.d` and -`sudo systemctl restart nginx`. +`sudo systemctl reload nginx`. ## Installation @@ -41,7 +41,7 @@ When adding new services that sit behind Nginx, 1. Add its nginx conf file to `/root/nginx/conf.d` -2. Restart nginx (`sudo systemctl restart nginx`) +2. Restart nginx (`sudo systemctl reload nginx`) ## Configuration files @@ -60,4 +60,5 @@ We can see this in the default configuration of nginx: > docker run --rm --entrypoint=cat nginx /etc/nginx/nginx.conf > /tmp/nginx.conf This is a [handy tool](https://nginx-playground.wizardzines.com) to check the -syntax of the configuration files. +syntax of the configuration files. Alternatively, you can run `docker exec nginx +nginx -t` on the instance to ask nginx to check the configuration. diff --git a/infra/services/nginx/nginx.service b/infra/services/nginx/nginx.service index 4f772d38dd..958bb6e06a 100644 --- a/infra/services/nginx/nginx.service +++ b/infra/services/nginx/nginx.service @@ -2,6 +2,7 @@ Documentation=https://www.docker.com/blog/how-to-use-the-official-nginx-docker-image/ Requires=docker.service After=docker.service +Requires=nginx.service [Install] WantedBy=multi-user.target @@ -17,3 +18,4 @@ ExecStart=docker run --name nginx \ -v /root/nginx/key.pem:/etc/ssl/private/key.pem:ro \ -v /root/nginx/conf.d:/etc/nginx/conf.d:ro \ nginx +ExecReload=docker exec nginx nginx -s reload diff --git a/infra/services/status/README.md b/infra/services/status/README.md index 51166f424a..d2e4b55e32 100644 --- a/infra/services/status/README.md +++ b/infra/services/status/README.md @@ -32,8 +32,8 @@ sudo systemctl daemon-reload sudo systemctl enable --now uptime-kuma ``` -Restart nginx +Tell nginx to pick up the new configuration. ```sh -sudo systemctl restart nginx +sudo systemctl reload nginx ``` diff --git a/server/scripts/deploy/README.md b/server/scripts/deploy/README.md index 04d1212109..35e1ec079f 100644 --- a/server/scripts/deploy/README.md +++ b/server/scripts/deploy/README.md @@ -87,7 +87,7 @@ To bring up an additional museum node: scp scripts/deploy/museum.nginx.conf : sudo mv museum.nginx.conf /root/nginx/conf.d - sudo systemctl restart nginx + sudo systemctl reload nginx ## Starting diff --git a/server/scripts/deploy/museum.nginx.service b/server/scripts/deploy/museum.nginx.service index 73cdd3ff1c..566c6c0486 100644 --- a/server/scripts/deploy/museum.nginx.service +++ b/server/scripts/deploy/museum.nginx.service @@ -2,6 +2,7 @@ Documentation=https://github.com/ente-io/ente/tree/main/server#readme Requires=docker.service After=docker.service +Requires=nginx.service [Service] Restart=on-failure From 9fe8d1fd531d1293e5cb907abb92ccbaf7a4a44e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 18 Mar 2024 21:56:39 +0530 Subject: [PATCH 380/391] Add recommended headers --- infra/services/status/README.md | 2 +- infra/services/status/uptime-kuma.nginx.conf | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/infra/services/status/README.md b/infra/services/status/README.md index d2e4b55e32..b9da80092d 100644 --- a/infra/services/status/README.md +++ b/infra/services/status/README.md @@ -20,7 +20,7 @@ Add the service definition and nginx configuration. ```sh scp services/status/uptime-kuma.* : -sudo mv uptime-kuma.service /etc/systemd/system/uptime-kuma.service +sudo mv uptime-kuma.service /etc/systemd/system/ sudo mv uptime-kuma.nginx.conf /root/nginx/conf.d ``` diff --git a/infra/services/status/uptime-kuma.nginx.conf b/infra/services/status/uptime-kuma.nginx.conf index 6c3b08b332..2f5b6ecc4e 100644 --- a/infra/services/status/uptime-kuma.nginx.conf +++ b/infra/services/status/uptime-kuma.nginx.conf @@ -15,5 +15,11 @@ server { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; + + # Recommended options from Uptime Kuma Wiki + # https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy#nginx + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; } } From f6e575885d9bb3f883f26cb3c3c8364f500c0f01 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 19 Mar 2024 05:38:02 +0530 Subject: [PATCH 381/391] Note the dashboard URL --- infra/services/status/README.md | 4 ++++ infra/services/status/uptime-kuma.nginx.conf | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/infra/services/status/README.md b/infra/services/status/README.md index b9da80092d..78d12001e2 100644 --- a/infra/services/status/README.md +++ b/infra/services/status/README.md @@ -37,3 +37,7 @@ Tell nginx to pick up the new configuration. ```sh sudo systemctl reload nginx ``` + +## Administration + +Login into the [dashboard](https://status.ente.io/dashboard) for administration. diff --git a/infra/services/status/uptime-kuma.nginx.conf b/infra/services/status/uptime-kuma.nginx.conf index 2f5b6ecc4e..c45c7b6606 100644 --- a/infra/services/status/uptime-kuma.nginx.conf +++ b/infra/services/status/uptime-kuma.nginx.conf @@ -16,7 +16,8 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - # Recommended options from Uptime Kuma Wiki + # Recommended options from Uptime Kuma Wiki for Websockets. + # # https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy#nginx proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; From f0236acf8f4678345c01a6d4e6a46d60b859f4d3 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 19 Mar 2024 06:15:55 +0530 Subject: [PATCH 382/391] [server] Minor bug fixes in embedding/files API --- server/pkg/api/embedding.go | 2 +- server/pkg/repo/embedding/repository.go | 3 ++- server/pkg/utils/array/array.go | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/server/pkg/api/embedding.go b/server/pkg/api/embedding.go index 4b072b0b70..5b06503318 100644 --- a/server/pkg/api/embedding.go +++ b/server/pkg/api/embedding.go @@ -53,7 +53,7 @@ func (h *EmbeddingHandler) GetDiff(c *gin.Context) { // GetFilesEmbedding returns the embeddings for the files func (h *EmbeddingHandler) GetFilesEmbedding(c *gin.Context) { var request ente.GetFilesEmbeddingRequest - if err := c.ShouldBindQuery(&request); err != nil { + if err := c.ShouldBindJSON(&request); err != nil { handler.Error(c, stacktrace.Propagate(ente.ErrBadRequest, fmt.Sprintf("Request binding failed %s", err))) return diff --git a/server/pkg/repo/embedding/repository.go b/server/pkg/repo/embedding/repository.go index 90e8a82642..c90dd8743e 100644 --- a/server/pkg/repo/embedding/repository.go +++ b/server/pkg/repo/embedding/repository.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "fmt" + "github.com/lib/pq" "github.com/ente-io/museum/ente" "github.com/ente-io/stacktrace" @@ -58,7 +59,7 @@ func (r *Repository) GetDiff(ctx context.Context, ownerID int64, model ente.Mode func (r *Repository) GetFilesEmbedding(ctx context.Context, ownerID int64, model ente.Model, fileIDs []int64) ([]ente.Embedding, error) { rows, err := r.DB.QueryContext(ctx, `SELECT file_id, model, encrypted_embedding, decryption_header, updated_at FROM embeddings - WHERE owner_id = $1 AND model = $2 AND file_id = ANY($3)`, ownerID, model, fileIDs) + WHERE owner_id = $1 AND model = $2 AND file_id = ANY($3)`, ownerID, model, pq.Array(fileIDs)) if err != nil { return nil, stacktrace.Propagate(err, "") } diff --git a/server/pkg/utils/array/array.go b/server/pkg/utils/array/array.go index 46d1e31132..0c2d25d90f 100644 --- a/server/pkg/utils/array/array.go +++ b/server/pkg/utils/array/array.go @@ -71,7 +71,7 @@ func FindMissingElementsInSecondList(sourceList []int64, targetList []int64) []i targetSet[item] = struct{}{} } - var missingElements []int64 + var missingElements = make([]int64, 0) for _, item := range sourceList { if _, found := targetSet[item]; !found { missingElements = append(missingElements, item) From 9e44f5cc20dc1674059245d90af8a71cbd7b1c67 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 19 Mar 2024 01:37:04 +0000 Subject: [PATCH 383/391] New Crowdin translations by GitHub Action --- .../public/locales/zh-CN/translation.json | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/web/apps/photos/public/locales/zh-CN/translation.json b/web/apps/photos/public/locales/zh-CN/translation.json index 0a72e1c70a..ed304f4ac9 100644 --- a/web/apps/photos/public/locales/zh-CN/translation.json +++ b/web/apps/photos/public/locales/zh-CN/translation.json @@ -638,17 +638,17 @@ "APPLY_CROP": "应用裁剪", "PHOTO_EDIT_REQUIRED_TO_SAVE": "保存之前必须至少执行一项转换或颜色调整。", "PASSKEYS": "通行密钥", - "DELETE_PASSKEY": "", - "DELETE_PASSKEY_CONFIRMATION": "", - "RENAME_PASSKEY": "", - "ADD_PASSKEY": "", - "ENTER_PASSKEY_NAME": "", - "PASSKEYS_DESCRIPTION": "", - "CREATED_AT": "", - "PASSKEY_LOGIN_FAILED": "", - "PASSKEY_LOGIN_URL_INVALID": "", - "PASSKEY_LOGIN_ERRORED": "", - "TRY_AGAIN": "", - "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "", - "LOGIN_WITH_PASSKEY": "" + "DELETE_PASSKEY": "删除通行密钥", + "DELETE_PASSKEY_CONFIRMATION": "您确定要删除此通行密钥吗?此操作是不可逆的。", + "RENAME_PASSKEY": "重命名通行密钥", + "ADD_PASSKEY": "添加通行密钥", + "ENTER_PASSKEY_NAME": "输入该通行密钥的名称", + "PASSKEYS_DESCRIPTION": "通行密钥是您 Ente 账户的现代、安全的第二因素。通行密钥使用设备上的生物识别认证,这既方便又安全。", + "CREATED_AT": "创建于", + "PASSKEY_LOGIN_FAILED": "通行密钥登录失败", + "PASSKEY_LOGIN_URL_INVALID": "该登录 URL 无效", + "PASSKEY_LOGIN_ERRORED": "使用通行密钥登录时出错。", + "TRY_AGAIN": "重试", + "PASSKEY_FOLLOW_THE_STEPS_FROM_YOUR_BROWSER": "按照浏览器中提示的步骤继续登录。", + "LOGIN_WITH_PASSKEY": "使用通行密钥来登录" } From 303b12c7096bc32b7e00887ae89b06046237b843 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 19 Mar 2024 09:31:51 +0530 Subject: [PATCH 384/391] Fix the dependency on nginx --- infra/services/nginx/nginx.service | 1 - server/scripts/deploy/museum.nginx.service | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/services/nginx/nginx.service b/infra/services/nginx/nginx.service index 958bb6e06a..e14e7840da 100644 --- a/infra/services/nginx/nginx.service +++ b/infra/services/nginx/nginx.service @@ -2,7 +2,6 @@ Documentation=https://www.docker.com/blog/how-to-use-the-official-nginx-docker-image/ Requires=docker.service After=docker.service -Requires=nginx.service [Install] WantedBy=multi-user.target diff --git a/server/scripts/deploy/museum.nginx.service b/server/scripts/deploy/museum.nginx.service index 566c6c0486..3a8b0b653e 100644 --- a/server/scripts/deploy/museum.nginx.service +++ b/server/scripts/deploy/museum.nginx.service @@ -3,6 +3,7 @@ Documentation=https://github.com/ente-io/ente/tree/main/server#readme Requires=docker.service After=docker.service Requires=nginx.service +After=nginx.service [Service] Restart=on-failure From 7634b2c153faf6ed3b36261ef8042a3205ba44d0 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 19 Mar 2024 10:30:32 +0530 Subject: [PATCH 385/391] [server] DB migration scripts for emedding table changes --- server/migrations/81_embeddings_type_and_size.down.sql | 3 +++ server/migrations/81_embeddings_type_and_size.up.sql | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 server/migrations/81_embeddings_type_and_size.down.sql create mode 100644 server/migrations/81_embeddings_type_and_size.up.sql diff --git a/server/migrations/81_embeddings_type_and_size.down.sql b/server/migrations/81_embeddings_type_and_size.down.sql new file mode 100644 index 0000000000..1d0bd7cf43 --- /dev/null +++ b/server/migrations/81_embeddings_type_and_size.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE embeddings + DROP COLUMN IF EXISTS size, + DROP COLUMN IF EXISTS version; diff --git a/server/migrations/81_embeddings_type_and_size.up.sql b/server/migrations/81_embeddings_type_and_size.up.sql new file mode 100644 index 0000000000..870e52a231 --- /dev/null +++ b/server/migrations/81_embeddings_type_and_size.up.sql @@ -0,0 +1,4 @@ +ALTER TYPE model ADD VALUE IF NOT EXISTS 'file-ml-clip-face'; +ALTER TABLE embeddings + ADD COLUMN size int DEFAULT NULL, + ADD COLUMN version int DEFAULT 1; From 05b0f1649fb3507d8a090756f70941a17becbd39 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:02:22 +0530 Subject: [PATCH 386/391] [server] store embedding objSize & version --- server/ente/embedding.go | 8 ++++--- server/pkg/controller/embedding/controller.go | 24 ++++++++++++------- server/pkg/repo/embedding/repository.go | 14 +++++++---- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/server/ente/embedding.go b/server/ente/embedding.go index 2a92adf792..ca1a671dac 100644 --- a/server/ente/embedding.go +++ b/server/ente/embedding.go @@ -14,6 +14,7 @@ type InsertOrUpdateEmbeddingRequest struct { Model string `json:"model" binding:"required"` EncryptedEmbedding string `json:"encryptedEmbedding" binding:"required"` DecryptionHeader string `json:"decryptionHeader" binding:"required"` + Version *int `json:"version,omitempty"` } type GetEmbeddingDiffRequest struct { @@ -37,9 +38,10 @@ type GetFilesEmbeddingResponse struct { type Model string const ( - OnnxClip Model = "onnx-clip" - GgmlClip Model = "ggml-clip" - OnnxYolo5MobileNet Model = "onnx-yolo5-mobile" + OnnxClip Model = "onnx-clip" + GgmlClip Model = "ggml-clip" + OnnxYoloV5MobileNet Model = "onnx-yolov5-mobile" + FileMlClipFace Model = "file-ml-clip-face" ) type EmbeddingObject struct { diff --git a/server/pkg/controller/embedding/controller.go b/server/pkg/controller/embedding/controller.go index fd124e12ac..8bd0794c9c 100644 --- a/server/pkg/controller/embedding/controller.go +++ b/server/pkg/controller/embedding/controller.go @@ -58,19 +58,23 @@ func (c *Controller) InsertOrUpdate(ctx *gin.Context, req ente.InsertOrUpdateEmb if count < 1 { return nil, stacktrace.Propagate(ente.ErrNotFound, "") } + version := 1 + if req.Version != nil { + version = *req.Version + } obj := ente.EmbeddingObject{ - Version: 1, + Version: version, EncryptedEmbedding: req.EncryptedEmbedding, DecryptionHeader: req.DecryptionHeader, Client: network.GetPrettyUA(ctx.GetHeader("User-Agent")) + "/" + ctx.GetHeader("X-Client-Version"), } - err = c.uploadObject(obj, c.getObjectKey(userID, req.FileID, req.Model)) - if err != nil { - log.Error(err) - return nil, stacktrace.Propagate(err, "") + size, uploadErr := c.uploadObject(obj, c.getObjectKey(userID, req.FileID, req.Model)) + if uploadErr != nil { + log.Error(uploadErr) + return nil, stacktrace.Propagate(uploadErr, "") } - embedding, err := c.Repo.InsertOrUpdate(ctx, userID, req) + embedding, err := c.Repo.InsertOrUpdate(ctx, userID, req, size) if err != nil { return nil, stacktrace.Propagate(err, "") } @@ -258,7 +262,8 @@ func (c *Controller) getEmbeddingObjectPrefix(userID int64, fileID int64) string return strconv.FormatInt(userID, 10) + "/ml-data/" + strconv.FormatInt(fileID, 10) + "/" } -func (c *Controller) uploadObject(obj ente.EmbeddingObject, key string) error { +// uploadObject uploads the embedding object to the object store and returns the object size +func (c *Controller) uploadObject(obj ente.EmbeddingObject, key string) (int, error) { embeddingObj, _ := json.Marshal(obj) uploader := s3manager.NewUploaderWithClient(c.S3Config.GetHotS3Client()) up := s3manager.UploadInput{ @@ -269,10 +274,11 @@ func (c *Controller) uploadObject(obj ente.EmbeddingObject, key string) error { result, err := uploader.Upload(&up) if err != nil { log.Error(err) - return stacktrace.Propagate(err, "") + return -1, stacktrace.Propagate(err, "") } + log.Infof("Uploaded to bucket %s", result.Location) - return nil + return len(embeddingObj), nil } var globalFetchSemaphore = make(chan struct{}, 300) diff --git a/server/pkg/repo/embedding/repository.go b/server/pkg/repo/embedding/repository.go index c90dd8743e..f3fcb16cb2 100644 --- a/server/pkg/repo/embedding/repository.go +++ b/server/pkg/repo/embedding/repository.go @@ -19,14 +19,18 @@ type Repository struct { // Create inserts a new embedding -func (r *Repository) InsertOrUpdate(ctx context.Context, ownerID int64, entry ente.InsertOrUpdateEmbeddingRequest) (ente.Embedding, error) { +func (r *Repository) InsertOrUpdate(ctx context.Context, ownerID int64, entry ente.InsertOrUpdateEmbeddingRequest, size int) (ente.Embedding, error) { var updatedAt int64 + version := 1 + if entry.Version != nil { + version = *entry.Version + } err := r.DB.QueryRowContext(ctx, `INSERT INTO embeddings - (file_id, owner_id, model) - VALUES ($1, $2, $3) + (file_id, owner_id, model, size, version) + VALUES ($1, $2, $3, $4, $5) ON CONFLICT ON CONSTRAINT unique_embeddings_file_id_model - DO UPDATE SET updated_at = now_utc_micro_seconds() - RETURNING updated_at`, entry.FileID, ownerID, entry.Model).Scan(&updatedAt) + DO UPDATE SET updated_at = now_utc_micro_seconds(), size = $4, version = $5 + RETURNING updated_at`, entry.FileID, ownerID, entry.Model, size, version).Scan(&updatedAt) if err != nil { // check if error is due to model enum invalid value if err.Error() == fmt.Sprintf("pq: invalid input value for enum model: \"%s\"", entry.Model) { From 3df49beb0715c8e8d881bdd7d58814a3c702bb67 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:04:25 +0530 Subject: [PATCH 387/391] [server] Remove unused model name --- server/ente/embedding.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/ente/embedding.go b/server/ente/embedding.go index ca1a671dac..efde0aae86 100644 --- a/server/ente/embedding.go +++ b/server/ente/embedding.go @@ -38,10 +38,11 @@ type GetFilesEmbeddingResponse struct { type Model string const ( - OnnxClip Model = "onnx-clip" - GgmlClip Model = "ggml-clip" - OnnxYoloV5MobileNet Model = "onnx-yolov5-mobile" - FileMlClipFace Model = "file-ml-clip-face" + OnnxClip Model = "onnx-clip" + GgmlClip Model = "ggml-clip" + + // FileMlClipFace is a model for face embeddings, it is used in request validation. + FileMlClipFace Model = "file-ml-clip-face" ) type EmbeddingObject struct { From e8756a8cf7a2c4a8f8f5ab75b70db33c9b225a31 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:06:36 +0530 Subject: [PATCH 388/391] [server] Remove unused code --- server/pkg/controller/embedding/controller.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/server/pkg/controller/embedding/controller.go b/server/pkg/controller/embedding/controller.go index 8bd0794c9c..905a29ece8 100644 --- a/server/pkg/controller/embedding/controller.go +++ b/server/pkg/controller/embedding/controller.go @@ -141,13 +141,6 @@ func (c *Controller) GetFilesEmbedding(ctx *gin.Context, req ente.GetFilesEmbedd missingFileIds := array.FindMissingElementsInSecondList(req.FileIDs, dbFileIds) errFileIds := make([]int64, 0) - // Collect object keys for userFileEmbeddings with missing data - var objectKeys []string - for i := range userFileEmbeddings { - objectKey := c.getObjectKey(userID, userFileEmbeddings[i].FileID, userFileEmbeddings[i].Model) - objectKeys = append(objectKeys, objectKey) - } - // Fetch missing userFileEmbeddings in parallel embeddingObjects, err := c.getEmbeddingObjectsParallelV2(userID, userFileEmbeddings) if err != nil { From fc3aea76941ba932b006df9aeeae2cd318c7475a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 19 Mar 2024 11:24:42 +0530 Subject: [PATCH 389/391] [web] Update yarn.lock --- web/yarn.lock | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/web/yarn.lock b/web/yarn.lock index 4e31afe7e5..f20c959553 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1979,7 +1979,11 @@ fastq@^1.6.0: reusify "^1.0.4" "ffmpeg-wasm@file:./apps/photos/thirdparty/ffmpeg-wasm": - version "0.0.0" + version "0.10.1" + dependencies: + is-url "^1.2.4" + node-fetch "^2.6.1" + regenerator-runtime "^0.13.7" file-entry-cache@^6.0.1: version "6.0.1" @@ -2614,6 +2618,11 @@ is-typed-array@^1.1.13: dependencies: which-typed-array "^1.1.14" +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + is-weakmap@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" @@ -3244,7 +3253,7 @@ peek-readable@^4.1.0: integrity sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg== "photoswipe@file:./apps/photos/thirdparty/photoswipe": - version "0.0.0" + version "4.1.6" picocolors@^1.0.0: version "1.0.0" @@ -3576,6 +3585,11 @@ reflect.getprototypeof@^1.0.4: globalthis "^1.0.3" which-builtin-type "^1.1.3" +regenerator-runtime@^0.13.7: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + regenerator-runtime@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" From 2b3494e61ce1338620618d9f06bd4ba0ebdafd72 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:25:00 +0530 Subject: [PATCH 390/391] [server] Return embedding version in API response --- server/ente/embedding.go | 12 ++++++------ server/pkg/controller/embedding/controller.go | 5 +++-- server/pkg/repo/embedding/repository.go | 18 ++++++++++-------- server/pkg/utils/array/array.go | 9 --------- 4 files changed, 19 insertions(+), 25 deletions(-) diff --git a/server/ente/embedding.go b/server/ente/embedding.go index efde0aae86..2990a779a3 100644 --- a/server/ente/embedding.go +++ b/server/ente/embedding.go @@ -1,12 +1,12 @@ package ente type Embedding struct { - FileID int64 `json:"fileID"` - Model string `json:"model"` - EncryptedEmbedding string `json:"encryptedEmbedding"` - DecryptionHeader string `json:"decryptionHeader"` - UpdatedAt int64 `json:"updatedAt"` - Client *string `json:"client,omitempty"` + FileID int64 `json:"fileID"` + Model string `json:"model"` + EncryptedEmbedding string `json:"encryptedEmbedding"` + DecryptionHeader string `json:"decryptionHeader"` + UpdatedAt int64 `json:"updatedAt"` + Version *int `json:"version,omitempty"` } type InsertOrUpdateEmbeddingRequest struct { diff --git a/server/pkg/controller/embedding/controller.go b/server/pkg/controller/embedding/controller.go index 905a29ece8..7f2f5dd805 100644 --- a/server/pkg/controller/embedding/controller.go +++ b/server/pkg/controller/embedding/controller.go @@ -74,7 +74,8 @@ func (c *Controller) InsertOrUpdate(ctx *gin.Context, req ente.InsertOrUpdateEmb log.Error(uploadErr) return nil, stacktrace.Propagate(uploadErr, "") } - embedding, err := c.Repo.InsertOrUpdate(ctx, userID, req, size) + embedding, err := c.Repo.InsertOrUpdate(ctx, userID, req, size, version) + embedding.Version = &version if err != nil { return nil, stacktrace.Propagate(err, "") } @@ -159,7 +160,7 @@ func (c *Controller) GetFilesEmbedding(ctx *gin.Context, req ente.GetFilesEmbedd EncryptedEmbedding: obj.embeddingObject.EncryptedEmbedding, DecryptionHeader: obj.embeddingObject.DecryptionHeader, UpdatedAt: obj.dbEmbeddingRow.UpdatedAt, - Client: obj.dbEmbeddingRow.Client, + Version: obj.dbEmbeddingRow.Version, }) } } diff --git a/server/pkg/repo/embedding/repository.go b/server/pkg/repo/embedding/repository.go index f3fcb16cb2..80b5ae9cc3 100644 --- a/server/pkg/repo/embedding/repository.go +++ b/server/pkg/repo/embedding/repository.go @@ -19,12 +19,8 @@ type Repository struct { // Create inserts a new embedding -func (r *Repository) InsertOrUpdate(ctx context.Context, ownerID int64, entry ente.InsertOrUpdateEmbeddingRequest, size int) (ente.Embedding, error) { +func (r *Repository) InsertOrUpdate(ctx context.Context, ownerID int64, entry ente.InsertOrUpdateEmbeddingRequest, size int, version int) (ente.Embedding, error) { var updatedAt int64 - version := 1 - if entry.Version != nil { - version = *entry.Version - } err := r.DB.QueryRowContext(ctx, `INSERT INTO embeddings (file_id, owner_id, model, size, version) VALUES ($1, $2, $3, $4, $5) @@ -49,7 +45,7 @@ func (r *Repository) InsertOrUpdate(ctx context.Context, ownerID int64, entry en // GetDiff returns the embeddings that have been updated since the given time func (r *Repository) GetDiff(ctx context.Context, ownerID int64, model ente.Model, sinceTime int64, limit int16) ([]ente.Embedding, error) { - rows, err := r.DB.QueryContext(ctx, `SELECT file_id, model, encrypted_embedding, decryption_header, updated_at + rows, err := r.DB.QueryContext(ctx, `SELECT file_id, model, encrypted_embedding, decryption_header, updated_at, version, FROM embeddings WHERE owner_id = $1 AND model = $2 AND updated_at > $3 ORDER BY updated_at ASC @@ -61,7 +57,7 @@ func (r *Repository) GetDiff(ctx context.Context, ownerID int64, model ente.Mode } func (r *Repository) GetFilesEmbedding(ctx context.Context, ownerID int64, model ente.Model, fileIDs []int64) ([]ente.Embedding, error) { - rows, err := r.DB.QueryContext(ctx, `SELECT file_id, model, encrypted_embedding, decryption_header, updated_at + rows, err := r.DB.QueryContext(ctx, `SELECT file_id, model, encrypted_embedding, decryption_header, updated_at, version FROM embeddings WHERE owner_id = $1 AND model = $2 AND file_id = ANY($3)`, ownerID, model, pq.Array(fileIDs)) if err != nil { @@ -97,13 +93,19 @@ func convertRowsToEmbeddings(rows *sql.Rows) ([]ente.Embedding, error) { for rows.Next() { embedding := ente.Embedding{} var encryptedEmbedding, decryptionHeader sql.NullString - err := rows.Scan(&embedding.FileID, &embedding.Model, &encryptedEmbedding, &decryptionHeader, &embedding.UpdatedAt) + var version sql.NullInt32 + err := rows.Scan(&embedding.FileID, &embedding.Model, &encryptedEmbedding, &decryptionHeader, &embedding.UpdatedAt, &version) if encryptedEmbedding.Valid && len(encryptedEmbedding.String) > 0 { embedding.EncryptedEmbedding = encryptedEmbedding.String } if decryptionHeader.Valid && len(decryptionHeader.String) > 0 { embedding.DecryptionHeader = decryptionHeader.String } + v := 1 + if version.Valid { + v = int(version.Int32) + } + embedding.Version = &v if err != nil { return nil, stacktrace.Propagate(err, "") } diff --git a/server/pkg/utils/array/array.go b/server/pkg/utils/array/array.go index 0c2d25d90f..42b6b8fa96 100644 --- a/server/pkg/utils/array/array.go +++ b/server/pkg/utils/array/array.go @@ -49,15 +49,6 @@ func Int64InList(a int64, list []int64) bool { } // FindMissingElementsInSecondList identifies elements in 'sourceList' that are not present in 'targetList'. -// -// This function creates a set from 'targetList' for efficient lookup, then iterates through 'sourceList' -// to identify which elements are missing in 'targetList'. This method is particularly efficient for large -// lists, as it avoids the quadratic complexity of nested iterations by utilizing a hash set for O(1) lookups. -// -// Parameters: -// - sourceList: An array of int64 elements to check against 'targetList'. -// - targetList: An array of int64 elements used as the reference set to identify missing elements from 'sourceList'. -// // Returns: // - A slice of int64 representing the elements found in 'sourceList' but not in 'targetList'. // If all elements of 'sourceList' are present in 'targetList', an empty slice is returned. From 685e1b82c932bf1550eb21e5e9ab3153e0b49559 Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:09:39 +0530 Subject: [PATCH 391/391] [server] Fix query for diff API --- server/pkg/repo/embedding/repository.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/pkg/repo/embedding/repository.go b/server/pkg/repo/embedding/repository.go index 80b5ae9cc3..f21e3b4f19 100644 --- a/server/pkg/repo/embedding/repository.go +++ b/server/pkg/repo/embedding/repository.go @@ -45,7 +45,7 @@ func (r *Repository) InsertOrUpdate(ctx context.Context, ownerID int64, entry en // GetDiff returns the embeddings that have been updated since the given time func (r *Repository) GetDiff(ctx context.Context, ownerID int64, model ente.Model, sinceTime int64, limit int16) ([]ente.Embedding, error) { - rows, err := r.DB.QueryContext(ctx, `SELECT file_id, model, encrypted_embedding, decryption_header, updated_at, version, + rows, err := r.DB.QueryContext(ctx, `SELECT file_id, model, encrypted_embedding, decryption_header, updated_at, version FROM embeddings WHERE owner_id = $1 AND model = $2 AND updated_at > $3 ORDER BY updated_at ASC