From 0a5d0f515fa07c50c4d45be36b91c907f9c48517 Mon Sep 17 00:00:00 2001 From: connor Date: Sun, 29 Sep 2024 20:33:04 -0500 Subject: [PATCH 001/438] [auth] updated icons for dark/light modes --- auth/assets/custom-icons/icons/IDme.svg | 14 ++++++++------ auth/assets/custom-icons/icons/coinbase.svg | 12 ++++-------- auth/assets/custom-icons/icons/forusall.svg | 7 ++++--- auth/assets/custom-icons/icons/guideline.svg | 6 +++++- auth/assets/custom-icons/icons/gusto.svg | 9 ++------- auth/assets/custom-icons/icons/login_gov.svg | 7 ++++++- auth/assets/custom-icons/icons/t-mobile.svg | 18 +++++++++++++++++- auth/assets/custom-icons/icons/titan.svg | 20 +++++++++++++++++++- 8 files changed, 65 insertions(+), 28 deletions(-) diff --git a/auth/assets/custom-icons/icons/IDme.svg b/auth/assets/custom-icons/icons/IDme.svg index 5761405962..dacc2d7970 100644 --- a/auth/assets/custom-icons/icons/IDme.svg +++ b/auth/assets/custom-icons/icons/IDme.svg @@ -1,6 +1,8 @@ - - - - - - + + + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/coinbase.svg b/auth/assets/custom-icons/icons/coinbase.svg index 9ae1bb7fca..b0f3078541 100644 --- a/auth/assets/custom-icons/icons/coinbase.svg +++ b/auth/assets/custom-icons/icons/coinbase.svg @@ -2,13 +2,9 @@ - - - + + C473.2,351.4,440,380.6,399.9,380.6z" style="fill:#FFFFFF;"/> diff --git a/auth/assets/custom-icons/icons/forusall.svg b/auth/assets/custom-icons/icons/forusall.svg index 0590642318..4b81ec1993 100644 --- a/auth/assets/custom-icons/icons/forusall.svg +++ b/auth/assets/custom-icons/icons/forusall.svg @@ -1,3 +1,4 @@ - - - + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/guideline.svg b/auth/assets/custom-icons/icons/guideline.svg index 9a0252aa3c..f75f8beaab 100644 --- a/auth/assets/custom-icons/icons/guideline.svg +++ b/auth/assets/custom-icons/icons/guideline.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/gusto.svg b/auth/assets/custom-icons/icons/gusto.svg index 9d1b4d7380..65c4453d45 100644 --- a/auth/assets/custom-icons/icons/gusto.svg +++ b/auth/assets/custom-icons/icons/gusto.svg @@ -1,9 +1,5 @@ - - - + c10.9-0.2,17.6-6.1,20.4-8.5l0.4-0.3l-10.7-13.2C248.2,71.8,247.5,72.4,247,72.7L247,72.7z M247,72.7" style="fill:#F45D48;"> - \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/login_gov.svg b/auth/assets/custom-icons/icons/login_gov.svg index 8f632955fc..619c049403 100644 --- a/auth/assets/custom-icons/icons/login_gov.svg +++ b/auth/assets/custom-icons/icons/login_gov.svg @@ -1 +1,6 @@ - \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/t-mobile.svg b/auth/assets/custom-icons/icons/t-mobile.svg index 5beb1f5aa2..171143e3b5 100644 --- a/auth/assets/custom-icons/icons/t-mobile.svg +++ b/auth/assets/custom-icons/icons/t-mobile.svg @@ -1 +1,17 @@ - \ No newline at end of file + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/titan.svg b/auth/assets/custom-icons/icons/titan.svg index 38f8325dd3..993d8ef315 100644 --- a/auth/assets/custom-icons/icons/titan.svg +++ b/auth/assets/custom-icons/icons/titan.svg @@ -1 +1,19 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 7357d0599b1fb7dcb36d965f9732d24a6dda4a99 Mon Sep 17 00:00:00 2001 From: wiki-Bird <41028518+wiki-Bird@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:02:29 +1300 Subject: [PATCH 002/438] Update custom-icons.json / custom icons with Simplicity, RealMe, and PBTech --- auth/assets/custom-icons/_data/custom-icons.json | 16 ++++++++++++++++ auth/assets/custom-icons/icons/pbtech.svg | 10 ++++++++++ auth/assets/custom-icons/icons/realme.svg | 13 +++++++++++++ auth/assets/custom-icons/icons/simplicity.svg | 1 + 4 files changed, 40 insertions(+) create mode 100644 auth/assets/custom-icons/icons/pbtech.svg create mode 100644 auth/assets/custom-icons/icons/realme.svg create mode 100644 auth/assets/custom-icons/icons/simplicity.svg diff --git a/auth/assets/custom-icons/_data/custom-icons.json b/auth/assets/custom-icons/_data/custom-icons.json index 14ccef985e..f007deb690 100644 --- a/auth/assets/custom-icons/_data/custom-icons.json +++ b/auth/assets/custom-icons/_data/custom-icons.json @@ -495,6 +495,11 @@ { "title": "PayPal" }, + { + "title": "PBTech", + "slug": "pbtech", + "hex": "f08222" + }, { "title": "pCloud" }, @@ -535,6 +540,10 @@ "title": "Real-Debrid", "slug": "real_debrid" }, + { + "title": "RealMe", + "slug": "realme" + }, { "title": "Registro br", "slug": "registro_br", @@ -580,6 +589,13 @@ { "title": "SimpleLogin" }, + { + "title": "Simplicity", + "altNames": [ + "simplicitynz", + "simplicity.kiwi" + ] + }, { "title": "Sipgate" }, diff --git a/auth/assets/custom-icons/icons/pbtech.svg b/auth/assets/custom-icons/icons/pbtech.svg new file mode 100644 index 0000000000..7d4006b152 --- /dev/null +++ b/auth/assets/custom-icons/icons/pbtech.svg @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/realme.svg b/auth/assets/custom-icons/icons/realme.svg new file mode 100644 index 0000000000..b284ba657d --- /dev/null +++ b/auth/assets/custom-icons/icons/realme.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/auth/assets/custom-icons/icons/simplicity.svg b/auth/assets/custom-icons/icons/simplicity.svg new file mode 100644 index 0000000000..ba772de0af --- /dev/null +++ b/auth/assets/custom-icons/icons/simplicity.svg @@ -0,0 +1 @@ + \ No newline at end of file From 2dbbff01858109fa5d14170a612de45687da8980 Mon Sep 17 00:00:00 2001 From: Prateek Sunal Date: Fri, 4 Oct 2024 23:30:20 +0530 Subject: [PATCH 003/438] fix(auth): remove win http client --- auth/lib/core/win_http_client.dart | 146 ----------------------------- auth/lib/main.dart | 4 - 2 files changed, 150 deletions(-) delete mode 100644 auth/lib/core/win_http_client.dart diff --git a/auth/lib/core/win_http_client.dart b/auth/lib/core/win_http_client.dart deleted file mode 100644 index 26bbff2178..0000000000 --- a/auth/lib/core/win_http_client.dart +++ /dev/null @@ -1,146 +0,0 @@ -// Inspired from https://github.com/netfarm/lehttp_overrides - -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - -// expired -const String kSha1DstX3 = 'DAC9024F54D8F6DF94935FB1732638CA6AD77C13'; - -// ISRG Root X1 -const String kIsrgRootX1 = '''-----BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 -WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu -ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY -MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc -h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ -0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U -A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW -T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH -B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC -B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv -KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn -OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn -jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw -qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI -rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq -hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL -ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ -3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK -NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 -ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur -TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC -jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc -oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq -4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA -mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d -emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= ------END CERTIFICATE-----'''; - -const String kIsrgRootX1Alt = '''-----BEGIN CERTIFICATE----- -MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC -ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL -wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D -LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK -4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5 -bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y -sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ -Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4 -FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc -SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql -PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND -TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw -SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1 -c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx -+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB -ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu -b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E -U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu -MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC -5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW -9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG -WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O -he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC -Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5 ------END CERTIFICATE----- -'''; - -const String kLetsEncryptCert = '''-----BEGIN CERTIFICATE----- -MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw -TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh -cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw -WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg -RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP -R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx -sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm -NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg -Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG -/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB -Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA -FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw -AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw -Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB -gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W -PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl -ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz -CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm -lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 -avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 -yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O -yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids -hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ -HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv -MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX -nLRbwHOoq7hHwg== ------END CERTIFICATE----- -'''; - -String _hexConverter(Uint8List bytes) { - final StringBuffer buffer = StringBuffer(); - for (int part in bytes) { - buffer.write('${part < 16 ? '0' : ''}${part.toRadixString(16)}'); - } - return buffer.toString().toUpperCase(); -} - -class WindowsHttpOverrides extends HttpOverrides { - static bool? _initRootCert; - final bool allowExpiredDSTX3; - - static bool _addRootCert() { - if (Platform.isWindows) { - final List cert = ascii.encode(kIsrgRootX1); - SecurityContext.defaultContext.setTrustedCertificatesBytes(cert); - final List certAlt = ascii.encode(kIsrgRootX1Alt); - SecurityContext.defaultContext.setTrustedCertificatesBytes(certAlt); - final List certAlt2 = ascii.encode(kLetsEncryptCert); - SecurityContext.defaultContext.setTrustedCertificatesBytes(certAlt2); - } - return true; - } - - WindowsHttpOverrides({this.allowExpiredDSTX3 = false}) { - _initRootCert ??= _addRootCert(); - } - - @override - HttpClient createHttpClient(SecurityContext? context) { - final HttpClient client = super.createHttpClient(context); - if (allowExpiredDSTX3) { - client.badCertificateCallback = - (X509Certificate cert, String host, int port) => - _hexConverter(cert.sha1) == kSha1DstX3; - } - return client; - } -} diff --git a/auth/lib/main.dart b/auth/lib/main.dart index 452f2a90f8..6d21f371d6 100644 --- a/auth/lib/main.dart +++ b/auth/lib/main.dart @@ -7,7 +7,6 @@ import 'package:ente_auth/core/configuration.dart'; import 'package:ente_auth/core/constants.dart'; import 'package:ente_auth/core/logging/super_logging.dart'; import 'package:ente_auth/core/network.dart'; -import 'package:ente_auth/core/win_http_client.dart'; import 'package:ente_auth/ente_theme_data.dart'; import 'package:ente_auth/locale.dart'; import 'package:ente_auth/services/authenticator_service.dart'; @@ -65,9 +64,6 @@ Future initSystemTray() async { void main() async { WidgetsFlutterBinding.ensureInitialized(); - if (Platform.isWindows) { - HttpOverrides.global = WindowsHttpOverrides(); - } if (PlatformUtil.isDesktop()) { await windowManager.ensureInitialized(); From 0d4d39a959588372bebe93e64de0d9ea43637052 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 7 Oct 2024 01:05:09 +0000 Subject: [PATCH 004/438] New Crowdin translations by GitHub Action --- .../metadata/android/pt/full_description.txt | 42 ++--- mobile/fastlane/metadata/android/pt/title.txt | 2 +- mobile/fastlane/metadata/ios/hi/name.txt | 1 + mobile/fastlane/metadata/ios/lt/keywords.txt | 1 + mobile/fastlane/metadata/ios/lt/name.txt | 1 + mobile/fastlane/metadata/ios/lt/subtitle.txt | 1 + .../fastlane/metadata/ios/pt/description.txt | 32 ++-- mobile/fastlane/metadata/ios/pt/keywords.txt | 2 +- .../playstore/lt/short_description.txt | 1 + .../fastlane/metadata/playstore/lt/title.txt | 1 + .../playstore/pt/full_description.txt | 32 ++-- .../playstore/pt/short_description.txt | 2 +- mobile/lib/l10n/intl_ja.arb | 16 +- mobile/lib/l10n/intl_lt.arb | 138 +++++++++++++++ mobile/lib/l10n/intl_pt.arb | 166 +++++++++--------- 15 files changed, 291 insertions(+), 147 deletions(-) create mode 100644 mobile/fastlane/metadata/ios/hi/name.txt create mode 100644 mobile/fastlane/metadata/ios/lt/keywords.txt create mode 100644 mobile/fastlane/metadata/ios/lt/name.txt create mode 100644 mobile/fastlane/metadata/ios/lt/subtitle.txt create mode 100644 mobile/fastlane/metadata/playstore/lt/short_description.txt create mode 100644 mobile/fastlane/metadata/playstore/lt/title.txt create mode 100644 mobile/lib/l10n/intl_lt.arb diff --git a/mobile/fastlane/metadata/android/pt/full_description.txt b/mobile/fastlane/metadata/android/pt/full_description.txt index 8e6bc4833e..08da532506 100644 --- a/mobile/fastlane/metadata/android/pt/full_description.txt +++ b/mobile/fastlane/metadata/android/pt/full_description.txt @@ -1,36 +1,36 @@ -ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos. +ente é um aplicativo simples para fazer cópia de segurança e compartilhar suas fotos e vídeos. -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. +Se você está procurando por uma alternativa ao Google Fotos focado 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). +Nós temos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos vão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee). -ente também torna simples compartilhar seus álbuns com seus entes queridos, mesmo que eles não estejam no ente. Você pode compartilhar links para visualização pública, onde eles podem visualizar seu álbum e colaborar adicionando fotos a ele, mesmo sem uma conta ou app. +ente também torna simples compartilhar seus álbuns com seus entes queridos, mesmo que eles não estejam no ente. Você pode compartilhar links para o público, em que eles podem visualizar seu álbum e colaborar adicionando fotos a ele, mesmo sem uma conta ou aplicativo. -Seus dados criptografados são replicados em 3 locais diferentes, incluindo um abrigo avançado em Paris. Levamos a sério a nossa postura e fazemos com que seja fácil garantir que suas memórias vivam. +Seus dados criptografados são replicados em 3 locais diferentes, incluindo um abrigo avançado em Paris. Nós levamos a sério a nossa postura e fazemos que seja fácil garantir que suas memórias vivam. -Estamos aqui para se tornar o app de fotos mais seguro de todos, venha entrar em nossa jornada! +Estamos aqui para se tornar o aplicativo de fotos mais seguro de todos, venha e participe de nossa jornada! RECURSOS -- Cópia de qualidade original, porque cada pixel é importante -- Planos de família, para que você possa compartilhar o armazenamento com sua família -- Álbuns colaborativos, para que você possa agrupar fotos após uma corrida -- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques da "Câmera" +— Cópia de resolução original, por cada pixel ser importante +- Planos familiares, para você poder compartilhar o armazenamento com sua família +- Álbuns colaborativos, para você agrupar fotos após uma corrida +- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques na "Câmera" - Links de álbuns, que podem ser protegidos com uma senha e definidos para expirar -- Capacidade de liberar espaço, removendo arquivos que foram salvos com segurança -- Suporte humano, porque você vale a pena -- Descrições, para que você possa captar suas memórias e encontrá-las facilmente -- Editor de imagens, para adicionar toques finais -- Favoritar, esconder e reviver suas memórias, pois elas são preciosas -- Importar com um clique do Google, Apple, seu disco rígido e muito mais +- Capacidade de liberar espaço, removendo arquivos salvos com segurança +- Apoio humano, porque você vale a pena +- Descrições, para você poder captar suas memórias e encontrá-las com facilidade +- Editor de imagens, para adicionar últimos toques +- Favoritar, ocultar e reviver suas memórias, pois elas são preciosas +- Importar num só clique do Google, Apple, seu disco rígido e muito mais - Tema escuro, porque suas fotos parecem bem nele - 2FA, 3FA, Autenticação biométrica -- e MUITO MAIS! +- 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/ente/blob/f-droid/mobile/android/permissions.md +ente solicita certas permissões para servir o propósito de um fornecedor 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. +Nós não oferecemos planos grátis 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 seus familiares. Você pode encontrar mais informações em ente.io. -SUPORTE -Temos orgulho em oferecer apoio humano. Se você é nosso cliente pago, você pode entrar em contato com o team@ente.io e esperar uma resposta da nossa equipe dentro de 24 horas. +AJUDA +Nós temos orgulho em oferecer apoio humano. Se você é um cliente pago, você pode contatar em team@ente.io e esperar uma resposta de nossa equipe dentro de 1 dia. diff --git a/mobile/fastlane/metadata/android/pt/title.txt b/mobile/fastlane/metadata/android/pt/title.txt index dc953a866d..8d04a2f96e 100644 --- a/mobile/fastlane/metadata/android/pt/title.txt +++ b/mobile/fastlane/metadata/android/pt/title.txt @@ -1 +1 @@ -ente - armazenamento criptografado de fotos \ No newline at end of file +ente - armazenamento de fotos criptografado \ No newline at end of file diff --git a/mobile/fastlane/metadata/ios/hi/name.txt b/mobile/fastlane/metadata/ios/hi/name.txt new file mode 100644 index 0000000000..20fdba2448 --- /dev/null +++ b/mobile/fastlane/metadata/ios/hi/name.txt @@ -0,0 +1 @@ +एंटे तस्वीरें diff --git a/mobile/fastlane/metadata/ios/lt/keywords.txt b/mobile/fastlane/metadata/ios/lt/keywords.txt new file mode 100644 index 0000000000..8f2f06cb8f --- /dev/null +++ b/mobile/fastlane/metadata/ios/lt/keywords.txt @@ -0,0 +1 @@ +nuotraukos,fotografija,šeima,privatumas,debesis,atsarginė kopija,vaizdo įrašai,nuotrauka,šifravimas,saugykla,albumas,alternatyva diff --git a/mobile/fastlane/metadata/ios/lt/name.txt b/mobile/fastlane/metadata/ios/lt/name.txt new file mode 100644 index 0000000000..e2f32e5f34 --- /dev/null +++ b/mobile/fastlane/metadata/ios/lt/name.txt @@ -0,0 +1 @@ +„Ente“ nuotraukos diff --git a/mobile/fastlane/metadata/ios/lt/subtitle.txt b/mobile/fastlane/metadata/ios/lt/subtitle.txt new file mode 100644 index 0000000000..c095fec004 --- /dev/null +++ b/mobile/fastlane/metadata/ios/lt/subtitle.txt @@ -0,0 +1 @@ +Užšifruota nuotraukų saugykla diff --git a/mobile/fastlane/metadata/ios/pt/description.txt b/mobile/fastlane/metadata/ios/pt/description.txt index 3d948a2b2c..23ec5ffbfa 100644 --- a/mobile/fastlane/metadata/ios/pt/description.txt +++ b/mobile/fastlane/metadata/ios/pt/description.txt @@ -1,33 +1,33 @@ -Ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos. +Ente é um aplicativo simples para copiar com segurança automaticamente e organizar 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, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las. +Se você esteve procurando por uma alternativa amigável à privacidade para preservar suas memórias, você veio no 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). +Temos aplicativos de código aberto em Android, iOS, web e desktop, e suas fotos vão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee). Ente também torna simples compartilhar seus álbuns com seus entes queridos. Você pode compartilhá-los diretamente com outros usuários do Ente, criptografados de ponta a ponta; ou com links publicamente visíveis. -Seus dados criptografados são replicados em locais diferentes, incluindo um abrigo avançado em Paris. Levamos a sério a nossa postura e fazemos com que seja fácil garantir que suas memórias vivam. +Seus dados criptografados são replicados em locais diferentes, incluindo um abrigo avançado em Paris. Nós levamos a sério a nossa postura e fazemos que seja fácil garantir que suas memórias vivam. -Estamos aqui para se tornar o app de fotos mais seguro de todos, venha entrar em nossa jornada! +Estamos aqui para se tornar o aplicativo de fotos mais seguro de todos, venha e participe de nossa jornada! RECURSOS -- Cópia de qualidade original, porque cada pixel é importante -- Planos de família, para que você possa compartilhar o armazenamento com sua família -- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques da "Câmera" +— Cópia de resolução original, por cada pixel ser importante +- Planos familiares, para você poder compartilhar o armazenamento com sua família +- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques na "Câmera" - Links de álbuns, que podem ser protegidos com uma senha e definidos para expirar -- Capacidade de liberar espaço, removendo arquivos que foram salvos com segurança -- Editor de imagens, para adicionar toques finais -- Favoritar, esconder e reviver suas memórias, pois elas são preciosas -- Importar com um clique de todos os principais provedores de armazenamento +- Capacidade de liberar espaço, removendo arquivos salvos com segurança +- Editor de imagens, para adicionar últimos toques +- Favoritar, ocultar e reviver suas memórias, pois elas são preciosas +- Importar num clique só para todos os fornecedores principais de armazenamento - Tema escuro, porque suas fotos parecem bem nele - 2FA, 3FA, Autenticação biométrica -- e MUITO MAIS! +- e MUITO mais! 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. +Nós não oferecemos planos grátis 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 seus familiares. Você pode encontrar mais informações em ente.io. -SUPORTE -Temos orgulho em oferecer apoio humano. Se você é nosso cliente pago, você pode entrar em contato com o team@ente.io e esperar uma resposta da nossa equipe dentro de 24 horas. +AJUDA +Nós temos orgulho em oferecer apoio humano. Se você é um cliente pago, você pode contatar em team@ente.io e esperar uma resposta de nossa equipe dentro de 1 dia. TERMOS https://ente.io/terms diff --git a/mobile/fastlane/metadata/ios/pt/keywords.txt b/mobile/fastlane/metadata/ios/pt/keywords.txt index 4b98c2fdf3..e8081a0336 100644 --- a/mobile/fastlane/metadata/ios/pt/keywords.txt +++ b/mobile/fastlane/metadata/ios/pt/keywords.txt @@ -1 +1 @@ -fotos,fotografia,família,privacidade,nuvem,backup,vídeos,foto,criptografia,armazenamento,álbum,alternativa +fotos,fotografia,família,privacidade,nuvem,cópiadesegurança,vídeos,foto,criptografia,armazenamento,álbum,alternativa diff --git a/mobile/fastlane/metadata/playstore/lt/short_description.txt b/mobile/fastlane/metadata/playstore/lt/short_description.txt new file mode 100644 index 0000000000..295b220f41 --- /dev/null +++ b/mobile/fastlane/metadata/playstore/lt/short_description.txt @@ -0,0 +1 @@ +Užšifruota nuotraukų saugykla – kurkite atsargines kopijas, tvarkykite ir bendrinkite nuotraukas bei vaizdo įrašus \ No newline at end of file diff --git a/mobile/fastlane/metadata/playstore/lt/title.txt b/mobile/fastlane/metadata/playstore/lt/title.txt new file mode 100644 index 0000000000..1150a9f69d --- /dev/null +++ b/mobile/fastlane/metadata/playstore/lt/title.txt @@ -0,0 +1 @@ +„Ente“ nuotraukos \ No newline at end of file diff --git a/mobile/fastlane/metadata/playstore/pt/full_description.txt b/mobile/fastlane/metadata/playstore/pt/full_description.txt index fc02bad108..6e731237ea 100644 --- a/mobile/fastlane/metadata/playstore/pt/full_description.txt +++ b/mobile/fastlane/metadata/playstore/pt/full_description.txt @@ -1,30 +1,30 @@ -Ente é um aplicativo simples para fazer backup e compartilhar suas fotos e vídeos. +Ente é um aplicativo simples para copiar com segurança automaticamente e organizar 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, elas são armazenadas com criptografia de ponta a ponta (e2ee). Isso significa que só você pode vê-las. +Se você esteve procurando por uma alternativa amigável à privacidade para preservar suas memórias, você veio no 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). +Nós rmos aplicativos de código aberto em todas as plataformas, Android, iOS, web e desktop, e suas fotos vão sincronizar perfeitamente entre todas elas de forma criptografada (e2ee). Ente também torna simples compartilhar seus álbuns com seus entes queridos. Você pode compartilhá-los diretamente com outros usuários do Ente, criptografados de ponta a ponta; ou com links publicamente visíveis. -Seus dados criptografados são replicados em locais diferentes, incluindo um abrigo avançado em Paris. Levamos a sério a nossa postura e fazemos com que seja fácil garantir que suas memórias vivam. +Seus dados criptografados são replicados em locais diferentes, incluindo um abrigo avançado em Paris. Nós levamos a sério a nossa postura e fazemos que seja fácil garantir que suas memórias vivam. -Estamos aqui para se tornar o app de fotos mais seguro de todos, venha entrar em nossa jornada! +Estamos aqui para se tornar o aplicativo de fotos mais seguro de todos, venha e participe de nossa jornada! ✨ RECURSOS -- Cópia de qualidade original, porque cada pixel é importante -- Planos de família, para que você possa compartilhar o armazenamento com sua família -- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques da "Câmera" +- Cópia de resolução original, por cada pixel é importante +- Planos familiares, para você poder compartilhar o armazenamento com sua família +- Pastas compartilhadas, caso você queira que seu parceiro aproveite seus cliques na "Câmera" - Links de álbuns, que podem ser protegidos com uma senha e definidos para expirar -- Capacidade de liberar espaço, removendo arquivos que foram salvos com segurança -- Editor de imagens, para adicionar toques finais -- Favoritar, esconder e reviver suas memórias, pois elas são preciosas -- Importar com um clique do Google, Apple, seu disco rígido e muito mais +- Capacidade de liberar espaço, removendo arquivos salvos com segurança +- Editor de imagens, para adicionar últimos toques +- Favoritar, ocultar e reviver suas memórias, pois elas são preciosas +- Importar num só clique do Google, Apple, seu disco rígido e muito mais - Tema escuro, porque suas fotos parecem bem nele - 2FA, 3FA, Autenticação biométrica -- e MUITO MAIS! +- e MUITO mais! 💲 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. +Nós não oferecemos planos grátis 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 seus familiares. Você pode encontrar mais informações em ente.io. -🙋 SUPORTE -Temos orgulho em oferecer apoio humano. Se você é nosso cliente pago, você pode entrar em contato com o team@ente.io e esperar uma resposta da nossa equipe dentro de 24 horas. \ No newline at end of file +🙋 AJUDA +Nós temos orgulho em oferecer apoio humano. Se você é um cliente pago, você pode contatar em team@ente.io e esperar uma resposta de nossa equipe dentro de 1 dia. \ No newline at end of file diff --git a/mobile/fastlane/metadata/playstore/pt/short_description.txt b/mobile/fastlane/metadata/playstore/pt/short_description.txt index 8c2471e26f..92211eb927 100644 --- a/mobile/fastlane/metadata/playstore/pt/short_description.txt +++ b/mobile/fastlane/metadata/playstore/pt/short_description.txt @@ -1 +1 @@ -Armazenamento de fotos criptografado - backup, organize e compartilhe suas fotos e vídeos \ No newline at end of file +Armazenamento de fotos criptografado - copie com segurança, organize e compartilhe suas fotos e vídeos \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ja.arb b/mobile/lib/l10n/intl_ja.arb index 2bf2f71fed..2f49285f3e 100644 --- a/mobile/lib/l10n/intl_ja.arb +++ b/mobile/lib/l10n/intl_ja.arb @@ -265,7 +265,7 @@ "shareTextConfirmOthersVerificationID": "これがあなたのente.io確認用IDであることを確認できますか? {verificationID}", "somethingWentWrong": "エラーが発生しました", "sendInvite": "招待を送る", - "shareTextRecommendUsingEnte": "Enteをダウンロードして、写真や動画の共有を簡単にしよう\n\nhttps://ente.io", + "shareTextRecommendUsingEnte": "Enteをダウンロードして、写真や動画の共有を簡単に!\n\nhttps://ente.io", "done": "完了", "applyCodeTitle": "コードを適用", "enterCodeDescription": "もらったコードを入力して、無料のストレージを入手してください", @@ -557,7 +557,7 @@ "sharedPhotoNotifications": "新しい共有写真", "sharedPhotoNotificationsExplanation": "誰かが写真を共有アルバムに追加した時に通知を受け取る", "advanced": "詳細", - "general": "一般", + "general": "設定", "security": "セキュリティ", "authToViewYourRecoveryKey": "リカバリーキーを表示するためには認証が必要です", "twofactor": "二段階認証", @@ -735,9 +735,9 @@ "type": "text" }, "onEnte": "Enteで保管", - "name": "名前", - "newest": "最新", - "lastUpdated": "最終更新", + "name": "名前順", + "newest": "新しい順", + "lastUpdated": "更新された順", "deleteEmptyAlbums": "空のアルバムを削除", "deleteEmptyAlbumsWithQuestionMark": "空のアルバムを削除しますか?", "deleteAlbumsDialogBody": "空のアルバムはすべて削除されます。", @@ -812,8 +812,8 @@ "sharedWith": "{emailIDs} と共有中", "sharedWithMe": "あなたと共有されたアルバム", "sharedByMe": "あなたが共有しました", - "doubleYourStorage": "ストレージを倍にしましょう", - "referFriendsAnd2xYourPlan": "友達に紹介してあなたのプランを2倍にしよう", + "doubleYourStorage": "ストレージを倍にしよう", + "referFriendsAnd2xYourPlan": "友達に紹介して2倍", "shareAlbumHint": "アルバムを開いて右上のシェアボタンをタップ", "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": "完全に削除されるまでの日数が項目に表示されます", "trashDaysLeft": "{count, plural, =0 {} =1 {1日} other {{count} 日}}", @@ -1076,7 +1076,7 @@ "@storageBreakupYou": { "description": "Label to indicate how much storage you are using when you are part of a family plan" }, - "storageUsageInfo": "{usedAmount} {usedStorageUnit} の {totalAmount} {totalStorageUnit} が使用されました", + "storageUsageInfo": "{usedAmount} {usedStorageUnit} / {totalAmount} {totalStorageUnit} 使用", "@storageUsageInfo": { "description": "Example: 1.2 GB of 2 GB used or 100 GB or 2TB used" }, diff --git a/mobile/lib/l10n/intl_lt.arb b/mobile/lib/l10n/intl_lt.arb new file mode 100644 index 0000000000..9c20587c5d --- /dev/null +++ b/mobile/lib/l10n/intl_lt.arb @@ -0,0 +1,138 @@ +{ + "@@locale ": "en", + "enterYourEmailAddress": "Įveskite savo el. pašto adresą", + "accountWelcomeBack": "Sveiki sugrįžę!", + "email": "El. paštas", + "cancel": "Atšaukti", + "verify": "Patvirtinti", + "invalidEmailAddress": "Netinkamas el. pašto adresas.", + "enterValidEmail": "Įveskite tinkamą el. pašto adresą.", + "deleteAccount": "Ištrinti paskyrą", + "askDeleteReason": "Kokia yra pagrindinė priežastis, dėl kurios ištrinate savo paskyrą?", + "deleteAccountFeedbackPrompt": "Apgailestaujame, kad išeinate. Pasidalykite savo atsiliepimais, kad padėtumėte mums tobulėti.", + "feedback": "Atsiliepimai", + "kindlyHelpUsWithThisInformation": "Maloniai padėkite mums su šia informacija", + "confirmDeletePrompt": "Taip, noriu negrįžtamai ištrinti šią paskyrą ir jos duomenis per visas programas.", + "confirmAccountDeletion": "Patvirtinti paskyros ištrynimą", + "deleteAccountPermanentlyButton": "Ištrinti paskyrą negrįžtamai", + "yourAccountHasBeenDeleted": "Jūsų paskyra buvo ištrinta", + "selectReason": "Pasirinkti priežastį", + "deleteReason1": "Trūksta pagrindinės funkcijos, kurios man reikia", + "deleteReason2": "Programa arba tam tikra funkcija nesielgia taip, kaip, mano manymu, turėtų elgtis", + "deleteReason3": "Radau kitą paslaugą, kuri man patinka labiau", + "deleteReason4": "Mano priežastis nenurodyta", + "sendEmail": "Siųsti el. laišką", + "deleteRequestSLAText": "Jūsų prašymas bus apdorotas per 72 valandas.", + "deleteEmailRequest": "Iš savo registruoto el. pašto adreso siųskite el. laišką adresu account-deletion@ente.io.", + "entePhotosPerm": "„Ente“ reikia leidimo išsaugoti jūsų nuotraukas", + "ok": "Gerai", + "createAccount": "Kurti paskyrą", + "createNewAccount": "Kurti naują paskyrą", + "password": "Slaptažodis", + "confirmPassword": "Patvirtinti slaptažodį", + "activeSessions": "Aktyvūs seansai", + "oops": "Ups", + "somethingWentWrongPleaseTryAgain": "Kažkas nutiko ne taip. Bandykite dar kartą.", + "thisWillLogYouOutOfThisDevice": "Tai jus atjungs nuo šio įrenginio.", + "thisWillLogYouOutOfTheFollowingDevice": "Tai jus atjungs nuo toliau nurodyto įrenginio:", + "thisDevice": "Šis įrenginys", + "recoverButton": "Atkurti", + "recoverySuccessful": "Atkūrimas sėkmingas.", + "decrypting": "Iššifruojama...", + "sorry": "Atsiprašome", + "noRecoveryKeyNoDecryption": "Dėl mūsų visapusio šifravimo protokolo pobūdžio jūsų duomenų negalima iššifruoti be slaptažodžio arba atkūrimo rakto", + "verifyEmail": "Patvirtinti el. paštą", + "howItWorks": "Kaip tai veikia", + "encryption": "Šifravimas", + "ackPasswordLostWarning": "Suprantu, kad jei prarasiu slaptažodį, galiu prarasti savo duomenis, kadangi mano duomenys yra visapusiškai užšifruota.", + "privacyPolicyTitle": "Privatumo politika", + "termsOfServicesTitle": "Sąlygos", + "signUpTerms": "Sutinku su paslaugų sąlygomis ir privatumo politika", + "logInLabel": "Prisijungti", + "loginTerms": "Spustelėjus Prisijungti sutinku su paslaugų sąlygomis ir privatumo politika", + "changeEmail": "Keisti el. paštą", + "enterYourPassword": "Įveskite savo slaptažodį", + "welcomeBack": "Sveiki sugrįžę!", + "contactSupport": "Susisiekti su palaikymo komanda", + "incorrectPasswordTitle": "Neteisingas slaptažodis.", + "storageInGB": "{storageAmountInGB} GB", + "faq": "DUK", + "subscribeToEnableSharing": "Kad įjungtumėte bendrinimą, reikia aktyvios mokamos prenumeratos.", + "subscribe": "Prenumeruoti", + "keepPhotos": "Palikti nuotraukas", + "deletePhotos": "Ištrinti nuotraukas", + "inviteToEnte": "Kviesti į „Ente“", + "photoSmallCase": "nuotrauka", + "machineLearning": "Kompiuterinis mokymasis", + "magicSearch": "Magiška paieška", + "discover": "Atraskite", + "@discover": { + "description": "The text to display for the discover section under which we show receipts, screenshots, sunsets, greenery, etc." + }, + "discover_identity": "Tapatybė", + "discover_screenshots": "Ekrano kopijos", + "discover_receipts": "Kvitai", + "discover_notes": "Užrašai", + "discover_visiting_cards": "Lankymo kortelės", + "discover_babies": "Kūdikiai", + "discover_pets": "Gyvūnai", + "discover_selfies": "Asmenukės", + "discover_wallpapers": "Ekrano fonai", + "discover_food": "Maistas", + "discover_celebrations": "Šventės", + "discover_sunset": "Saulėlydis", + "discover_hills": "Kalvos", + "discover_greenery": "Žaluma", + "social": "Socialinės", + "blog": "Tinklaraštis", + "merchandise": "Atributika", + "twitter": "„Twitter“", + "mastodon": "„Mastodon“", + "matrix": "„Matrix“", + "discord": "„Discord“", + "reddit": "„Reddit“", + "yourStorageDetailsCouldNotBeFetched": "Nepavyko gauti jūsų saugyklos duomenų.", + "reportABug": "Pranešti apie riktą", + "reportBug": "Pranešti apie riktą", + "suggestFeatures": "Siūlyti funkcijas", + "support": "Palaikymas", + "theme": "Tema", + "lightTheme": "Šviesi", + "darkTheme": "Tamsi", + "systemTheme": "Sistemos", + "upgrade": "Atnaujinti", + "noExifData": "Nėra EXIF duomenų", + "thisImageHasNoExifData": "Šis vaizdas neturi EXIF duomenų", + "exif": "EXIF", + "noResults": "Rezultatų nėra", + "kiloMeterUnit": "km", + "addLocationButton": "Pridėti", + "light": "Šviesi", + "color": "Spalva", + "distanceInKMUnit": "km", + "@distanceInKMUnit": { + "description": "Unit for distance in km" + }, + "dayToday": "Šiandien", + "dayYesterday": "Vakar", + "storage": "Saugykla", + "usedSpace": "Naudojama vieta", + "storageBreakupYou": "Jūs", + "@storageBreakupYou": { + "description": "Label to indicate how much storage you are using when you are part of a family plan" + }, + "appVersion": "Versija: {versionValue}", + "verifyIDLabel": "Patvirtinti", + "passkey": "Slaptaraktas", + "collect": "Rinkti", + "appLockDescriptions": "Pasirinkite tarp numatytojo įrenginio užrakinimo ekrano ir pasirinktinio užrakinimo ekrano su PIN kodu arba slaptažodžiu.", + "toEnableAppLockPleaseSetupDevicePasscodeOrScreen": "Kad įjungtumėte programos užraktą, sistemos nustatymuose nustatykite įrenginio prieigos kodą arba ekrano užraktą.", + "authToViewPasskey": "Nustatykite tapatybę, kad peržiūrėtumėte savo slaptaraktą", + "localSyncErrorMessage": "Atrodo, kad kažkas nutiko ne taip, nes vietinių nuotraukų sinchronizavimas trunka ilgiau nei tikėtasi. Susisiekite su mūsų palaikymo komanda.", + "showPerson": "Rodyti asmenį", + "sort": "Rikiuoti", + "mostRecent": "Naujausia", + "mostRelevant": "Aktualiausia", + "loadingYourPhotos": "Įkeliamos nuotraukos...", + "processingImport": "Apdorojama {folderName}..." +} \ No newline at end of file diff --git a/mobile/lib/l10n/intl_pt.arb b/mobile/lib/l10n/intl_pt.arb index 3a96171092..dc5fe3d3c3 100644 --- a/mobile/lib/l10n/intl_pt.arb +++ b/mobile/lib/l10n/intl_pt.arb @@ -1,59 +1,59 @@ { "@@locale ": "en", "enterYourEmailAddress": "Insira seu endereço de e-mail", - "accountWelcomeBack": "Seja bem-vindo de volta!", + "accountWelcomeBack": "Bem-vindo(a) de volta!", "email": "E-mail", "cancel": "Cancelar", "verify": "Verificar", - "invalidEmailAddress": "Endereço de e-mail invalido", - "enterValidEmail": "Por, favor insira um endereço de e-mail válido.", + "invalidEmailAddress": "Endereço de e-mail inválido", + "enterValidEmail": "Insira um endereço de e-mail válido.", "deleteAccount": "Excluir conta", - "askDeleteReason": "Qual é o principal motivo para você excluir sua conta?", - "deleteAccountFeedbackPrompt": "Lamentamos ver você partir. Por favor, compartilhe seus comentários para nos ajudar a melhorar.", - "feedback": "Comentários", + "askDeleteReason": "Por que você quer excluir sua conta?", + "deleteAccountFeedbackPrompt": "Lamentamos você ir. Compartilhe seu feedback para nos ajudar a melhorar.", + "feedback": "Feedback", "kindlyHelpUsWithThisInformation": "Ajude-nos com esta informação", - "confirmDeletePrompt": "Sim, eu quero excluir permanentemente esta conta e seus dados em todos os aplicativos.", + "confirmDeletePrompt": "Sim, eu quero permanentemente excluir esta conta e os dados em todos os aplicativos.", "confirmAccountDeletion": "Confirmar exclusão da conta", "deleteAccountPermanentlyButton": "Excluir conta permanentemente", "yourAccountHasBeenDeleted": "Sua conta foi excluída", - "selectReason": "Selecione o motivo", + "selectReason": "Diga o motivo", "deleteReason1": "Está faltando um recurso-chave que eu preciso", - "deleteReason2": "O aplicativo ou um determinado recurso não está funcionando como eu acredito que deveria", - "deleteReason3": "Encontrei outro serviço que gosto mais", + "deleteReason2": "O aplicativo ou um certo recurso não funciona da maneira que eu acredito que deveria funcionar", + "deleteReason3": "Encontrei outro serviço que considero melhor", "deleteReason4": "Meu motivo não está listado", "sendEmail": "Enviar e-mail", - "deleteRequestSLAText": "Sua solicitação será processada em até 72 horas.", - "deleteEmailRequest": "Por favor, envie um e-mail para account-deletion@ente.io a partir do seu endereço de e-mail registrado.", - "entePhotosPerm": "Ente precisa de permissão para preservar suas fotos", + "deleteRequestSLAText": "Sua solicitação será revisada em até 72 horas.", + "deleteEmailRequest": "Por favor, envie um e-mail à account-deletion@ente.io do seu endereço de e-mail registrado.", + "entePhotosPerm": "Ente precisa de sua permissão para preservar suas fotos", "ok": "OK", - "createAccount": "Criar uma conta", + "createAccount": "Criar conta", "createNewAccount": "Criar nova conta", "password": "Senha", - "confirmPassword": "Confirme sua senha", + "confirmPassword": "Confirmar senha", "activeSessions": "Sessões ativas", - "oops": "Opa", - "somethingWentWrongPleaseTryAgain": "Algo deu errado. Por favor, tente outra vez", - "thisWillLogYouOutOfThisDevice": "Isso fará com que você saia deste dispositivo!", - "thisWillLogYouOutOfTheFollowingDevice": "Isso fará com que você saia do seguinte dispositivo:", - "terminateSession": "Encerrar sessão?", + "oops": "Ops", + "somethingWentWrongPleaseTryAgain": "Algo deu errado. Tente outra vez", + "thisWillLogYouOutOfThisDevice": "Isso fará você sair deste dispositivo!", + "thisWillLogYouOutOfTheFollowingDevice": "Isso fará você sair do dispositivo a seguir:", + "terminateSession": "Sair?", "terminate": "Encerrar", - "thisDevice": "Este aparelho", + "thisDevice": "Este dispositivo", "recoverButton": "Recuperar", - "recoverySuccessful": "Recuperação bem sucedida!", + "recoverySuccessful": "Recuperação com sucesso!", "decrypting": "Descriptografando...", "incorrectRecoveryKeyTitle": "Chave de recuperação incorreta", - "incorrectRecoveryKeyBody": "A chave de recuperação que você digitou está incorreta", - "forgotPassword": "Esqueceu sua senha", - "enterYourRecoveryKey": "Digite sua chave de recuperação", - "noRecoveryKey": "Nenhuma chave de recuperação?", + "incorrectRecoveryKeyBody": "A chave de recuperação inserida está incorreta", + "forgotPassword": "Esqueci a senha", + "enterYourRecoveryKey": "Insira sua chave de recuperação", + "noRecoveryKey": "Sem chave de recuperação?", "sorry": "Desculpe", "noRecoveryKeyNoDecryption": "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", "verifyEmail": "Verificar e-mail", - "toResetVerifyEmail": "Para redefinir a sua senha, por favor verifique o seu e-mail primeiro.", + "toResetVerifyEmail": "Para redefinir sua senha, verifique seu e-mail primeiramente.", "checkInboxAndSpamFolder": "Verifique sua caixa de entrada (e spam) para concluir a verificação", "tapToEnterCode": "Toque para inserir código", "resendEmail": "Reenviar e-mail", - "weHaveSendEmailTo": "Enviamos um e-mail à {email}", + "weHaveSendEmailTo": "Nós enviamos um e-mail à {email}", "@weHaveSendEmailTo": { "description": "Text to indicate that we have sent a mail to the user", "placeholders": { @@ -68,13 +68,13 @@ "changePasswordTitle": "Alterar senha", "resetPasswordTitle": "Redefinir senha", "encryptionKeys": "Chaves de criptografia", - "passwordWarning": "Nós não salvamos essa senha, se você esquecer nós não poderemos descriptografar seus dados", - "enterPasswordToEncrypt": "Insira a senha para criptografar seus dados", + "passwordWarning": "Nós não armazenamos esta senha, se você esquecer, nós não poderemos descriptografar seus dados", + "enterPasswordToEncrypt": "Insira uma senha que podemos usar para criptografar seus dados", "enterNewPasswordToEncrypt": "Insira uma senha nova para criptografar seus dados", "weakStrength": "Fraca", "strongStrength": "Forte", - "moderateStrength": "Moderada", - "passwordStrength": "Segurança da senha: {passwordStrengthValue}", + "moderateStrength": "Moderado", + "passwordStrength": "Força da senha: {passwordStrengthValue}", "@passwordStrength": { "description": "Text to indicate the password strength", "placeholders": { @@ -88,10 +88,10 @@ }, "passwordChangedSuccessfully": "Senha alterada com sucesso", "generatingEncryptionKeys": "Gerando chaves de criptografia...", - "pleaseWait": "Por favor, aguarde...", + "pleaseWait": "Aguarde...", "continueLabel": "Continuar", "insecureDevice": "Dispositivo inseguro", - "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Desculpe, não foi possível gerar chaves seguras neste dispositivo.\n\npor favor, inicie sessão com um dispositivo diferente.", + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Desculpe, não foi possível gerar chaves seguras neste dispositivo.\n\ninicie sessão com um dispositivo diferente.", "howItWorks": "Como funciona", "encryption": "Criptografia", "ackPasswordLostWarning": "Eu entendo que se eu perder minha senha, posso perder meus dados, já que meus dados são criptografados de ponta a ponta.", @@ -100,25 +100,25 @@ "signUpTerms": "Eu concordo com os termos de serviço e a política de privacidade", "logInLabel": "Entrar", "loginTerms": "Ao clicar em entrar, eu concordo com os termos de serviço e a política de privacidade", - "changeEmail": "Mudar e-mail", + "changeEmail": "Alterar e-mail", "enterYourPassword": "Insira sua senha", - "welcomeBack": "Bem-vindo de volta!", - "contactSupport": "Contate o suporte", + "welcomeBack": "Bem-vindo(a) de volta!", + "contactSupport": "Contatar suporte", "incorrectPasswordTitle": "Senha incorreta", - "pleaseTryAgain": "Por favor, tente novamente", + "pleaseTryAgain": "Tente novamente", "recreatePasswordTitle": "Redefinir senha", "useRecoveryKey": "Usar chave de recuperação", - "recreatePasswordBody": "O dispositivo atual não é poderoso o suficiente para verificar sua senha, mas podemos regenerar de uma forma que funcione com todos os dispositivos.\n\nPor favor, inicie sessão usando sua chave de recuperação e recrie sua senha (você pode usar o mesmo novamente se desejar).", + "recreatePasswordBody": "O dispositivo atual não é poderoso o suficiente para verificar sua senha, no entanto, nós podemos regenerar numa maneira que funciona em todos os dispositivos.\n\nEntre usando a chave de recuperação e regenere sua senha (você pode usar a mesma novamente se desejar).", "verifyPassword": "Verificar senha", "recoveryKey": "Chave de recuperação", - "recoveryKeyOnForgotPassword": "Caso você esqueça sua senha, a única maneira de recuperar seus dados é com essa chave.", - "recoveryKeySaveDescription": "Não armazenamos essa chave, por favor, salve essa chave de 24 palavras em um lugar seguro.", - "doThisLater": "Fazer isso mais tarde", + "recoveryKeyOnForgotPassword": "Caso você esqueça sua senha, a única maneira de recuperar seus dados é com esta chave.", + "recoveryKeySaveDescription": "Não armazenamos esta chave, salve esta chave de 24 palavras em um lugar seguro.", + "doThisLater": "Fazer isso depois", "saveKey": "Salvar chave", - "recoveryKeyCopiedToClipboard": "Chaves de recuperação foram copiadas para a área de transferência", + "recoveryKeyCopiedToClipboard": "Chave de recuperação copiada para a área de transferência", "recoverAccount": "Recuperar conta", "recover": "Recuperar", - "dropSupportEmail": "Por favor, envie um e-mail para {supportEmail} a partir do seu endereço de e-mail registrado", + "dropSupportEmail": "Envie um e-mail para {supportEmail} a partir do seu endereço de e-mail registrado", "@dropSupportEmail": { "placeholders": { "supportEmail": { @@ -129,42 +129,42 @@ } }, "twofactorSetup": "Configuração de dois fatores", - "enterCode": "Coloque o código", + "enterCode": "Insira o código", "scanCode": "Escanear código", "codeCopiedToClipboard": "Código copiado para a área de transferência", - "copypasteThisCodentoYourAuthenticatorApp": "Copie e cole este código\npara seu aplicativo autenticador", + "copypasteThisCodentoYourAuthenticatorApp": "Copie e cole este código\npara o aplicativo autenticador", "tapToCopy": "toque para copiar", - "scanThisBarcodeWithnyourAuthenticatorApp": "Escaneie este código de barras com\nseu aplicativo autenticador", - "enterThe6digitCodeFromnyourAuthenticatorApp": "Digite o código de 6 dígitos de\nseu aplicativo autenticador", - "confirm": "Confirme", + "scanThisBarcodeWithnyourAuthenticatorApp": "Escaneie este código de barras com\no aplicativo autenticador", + "enterThe6digitCodeFromnyourAuthenticatorApp": "Digite o código de 6 dígitos do\naplicativo de autenticador", + "confirm": "Confirmar", "setupComplete": "Configuração concluída", - "saveYourRecoveryKeyIfYouHaventAlready": "Salve sua chave de recuperação, caso ainda não o tenha feito", + "saveYourRecoveryKeyIfYouHaventAlready": "Salve sua chave de recuperação, se você ainda não fez", "thisCanBeUsedToRecoverYourAccountIfYou": "Isso pode ser usado para recuperar sua conta se você perder seu segundo fator", "twofactorAuthenticationPageTitle": "Autenticação de dois fatores", - "lostDevice": "Dispositivo perdido?", + "lostDevice": "Perdeu o dispositivo?", "verifyingRecoveryKey": "Verificando chave de recuperação...", "recoveryKeyVerified": "Chave de recuperação verificada", - "recoveryKeySuccessBody": "Ótimo! Sua chave de recuperação é válida. Obrigado por verificar.\n\nLembre-se de manter o backup seguro de sua chave de recuperação.", - "invalidRecoveryKey": "A chave de recuperação que você digitou não é válida. Certifique-se de que contém 24 palavras e verifique a ortografia de cada uma.\n\nSe você inseriu um código de recuperação mais antigo, verifique se ele tem 64 caracteres e verifique cada um deles.", + "recoveryKeySuccessBody": "Ótimo! Sua chave de recuperação é válida. Obrigada por verificar.\n\nLembre-se de manter sua chave de recuperação copiada com segurança.", + "invalidRecoveryKey": "A chave de recuperação que você inseriu não é válida. Certifique-se de conter 24 caracteres, e verifique a ortografia de cada um deles.\n\nSe você inseriu um código de recuperação mais antigo, verifique se ele tem 64 caracteres e verifique cada um deles.", "invalidKey": "Chave inválida", "tryAgain": "Tente novamente", "viewRecoveryKey": "Ver chave de recuperação", - "confirmRecoveryKey": "Confirme a chave de recuperação", - "recoveryKeyVerifyReason": "Sua chave de recuperação é a única maneira de recuperar suas fotos se você esquecer sua senha. Você pode encontrar sua chave de recuperação em Configurações > Conta.\n\nDigite sua chave de recuperação aqui para verificar se você a salvou corretamente.", + "confirmRecoveryKey": "Confirmar chave de recuperação", + "recoveryKeyVerifyReason": "Sua chave de recuperação é a única maneira de recuperar suas fotos se você esqueceu a senha. Se você não consegue encontrar sua chave de recuperação em Opções > Segurança.\n\nInsira sua chave de recuperação aqui para verificar que você salvou corretamente.", "confirmYourRecoveryKey": "Confirme sua chave de recuperação", "addViewer": "Adicionar visualizador", "addCollaborator": "Adicionar colaborador", "addANewEmail": "Adicionar um novo e-mail", "orPickAnExistingOne": "Ou escolha um existente", "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": "Os colaboradores podem adicionar fotos e vídeos ao álbum compartilhado.", - "enterEmail": "Insira o e-mail", + "enterEmail": "Inserir e-mail", "albumOwner": "Proprietário", "@albumOwner": { "description": "Role of the album owner" }, "you": "Você", "collaborator": "Colaborador", - "addMore": "Adicione mais", + "addMore": "Adicionar mais", "@addMore": { "description": "Button text to add more collaborators/viewers" }, @@ -178,15 +178,15 @@ "addedAs": "Adicionado como", "changePermissions": "Alterar permissões?", "yesConvertToViewer": "Sim, converter para visualizador", - "cannotAddMorePhotosAfterBecomingViewer": "{user} Não poderá adicionar mais fotos a este álbum\n\nEles ainda poderão remover as fotos existentes adicionadas por eles", + "cannotAddMorePhotosAfterBecomingViewer": "{user} Não poderá adicionar mais fotos a este álbum\n\nEles ainda conseguirão remover fotos existentes adicionadas por eles", "allowAddingPhotos": "Permitir adicionar fotos", "@allowAddingPhotos": { "description": "Switch button to enable uploading photos to a public link" }, - "allowAddPhotosDescription": "Permita que as pessoas com o link também adicionem fotos ao álbum compartilhado.", + "allowAddPhotosDescription": "Permitir que as pessoas com link também adicionem fotos ao álbum compartilhado.", "passwordLock": "Bloqueio por senha", - "disableDownloadWarningTitle": "Observe", - "disableDownloadWarningBody": "Os espectadores ainda podem tirar screenshots ou salvar uma cópia de suas fotos usando ferramentas externas", + "disableDownloadWarningTitle": "Por favor, saiba que", + "disableDownloadWarningBody": "Os visualizadores podem fazer capturas de tela ou salvar uma cópia de suas fotos usando ferramentas externas", "allowDownloads": "Permitir downloads", "linkDeviceLimit": "Limite do dispositivo", "noDeviceLimit": "Nenhum", @@ -195,15 +195,15 @@ }, "linkExpiry": "Expiração do link", "linkExpired": "Expirado", - "linkEnabled": "Habilitado", + "linkEnabled": "Ativado", "linkNeverExpires": "Nunca", - "expiredLinkInfo": "Este link expirou. Por favor, selecione um novo tempo de expiração ou desabilite a expiração do link.", - "setAPassword": "Defina uma senha", + "expiredLinkInfo": "O link expirou. Selecione um novo tempo de expiração ou desative a expiração do link.", + "setAPassword": "Definir senha", "lockButtonLabel": "Bloquear", - "enterPassword": "Digite a senha", + "enterPassword": "Inserir senha", "removeLink": "Remover link", "manageLink": "Gerenciar link", - "linkExpiresOn": "O link irá expirar em {expiryTime}", + "linkExpiresOn": "O link expirará em {expiryTime}", "albumUpdated": "Álbum atualizado", "never": "Nunca", "custom": "Personalizado", @@ -216,7 +216,7 @@ "after1Month": "Após 1 mês", "after1Year": "Após 1 ano", "manageParticipants": "Gerenciar", - "albumParticipantsCount": "{count, plural, =0 {Nenhum Participante} =1 {1 Participante} other {{count} Participantes}}", + "albumParticipantsCount": "{count, plural, =0 {Nenhum participante} =1 {1 participante} other {{count} participantes}}", "@albumParticipantsCount": { "placeholders": { "count": { @@ -227,14 +227,14 @@ "description": "Number of participants in an album, including the album owner." }, "collabLinkSectionDescription": "Crie um link para permitir que as pessoas adicionem e vejam fotos no seu álbum compartilhado sem a necessidade do aplicativo ou uma conta Ente. Ótimo para colecionar fotos de eventos.", - "collectPhotos": "Colete fotos", - "collaborativeLink": "Link Colaborativo", - "shareWithNonenteUsers": "Compartilhar com usuários não-Ente", + "collectPhotos": "Coletar fotos", + "collaborativeLink": "Link colaborativo", + "shareWithNonenteUsers": "Compartilhar com usuários não ente", "createPublicLink": "Criar link público", "sendLink": "Enviar link", "copyLink": "Copiar link", "linkHasExpired": "O link expirou", - "publicLinkEnabled": "Link público ativado", + "publicLinkEnabled": "Link público ativo", "shareALink": "Compartilhar link", "sharedAlbumSectionDescription": "Criar álbuns compartilhados e colaborativos com outros usuários Ente, incluindo usuários em planos gratuitos.", "shareWithPeopleSectionTitle": "{numberOfPeople, plural, =0 {Compartilhe com pessoas específicas} =1 {Compartilhado com 1 pessoa} other {Compartilhado com {numberOfPeople} pessoas}}", @@ -266,7 +266,7 @@ "somethingWentWrong": "Algo deu errado", "sendInvite": "Enviar convite", "shareTextRecommendUsingEnte": "Baixe o Ente para que possamos compartilhar facilmente fotos e vídeos de qualidade original\n\nhttps://ente.io", - "done": "Pronto", + "done": "Concluído", "applyCodeTitle": "Aplicar código", "enterCodeDescription": "Digite o código fornecido pelo seu amigo para reivindicar o armazenamento gratuito para vocês dois", "apply": "Aplicar", @@ -446,15 +446,15 @@ "indexedItems": "Itens indexados", "pendingItems": "Itens pendentes", "clearIndexes": "Limpar índices", - "selectFoldersForBackup": "Selecione pastas para backup", - "selectedFoldersWillBeEncryptedAndBackedUp": "As pastas selecionadas serão criptografadas e armazenadas em backup", + "selectFoldersForBackup": "Selecionar pastas para copiar com segurança", + "selectedFoldersWillBeEncryptedAndBackedUp": "As pastas selecionadas serão criptografadas e armazenadas em copiadas com segurança", "unselectAll": "Desmarcar tudo", "selectAll": "Selecionar tudo", "skip": "Pular", "updatingFolderSelection": "Atualizando seleção de pasta...", - "itemCount": "{count, plural, one{{count} item} other{{count} items}}", + "itemCount": "{count, plural, one{{count} item} other{{count} itens}}", "deleteItemCount": "{count, plural, =1 {Excluir {count} item} other {Excluir {count} itens}}", - "duplicateItemsGroup": "{count} Arquivos, {formattedSize} cada", + "duplicateItemsGroup": "{count} arquivos, {formattedSize} cada", "@duplicateItemsGroup": { "description": "Display the number of duplicate files and their size", "type": "text", @@ -470,11 +470,11 @@ } }, "showMemories": "Mostrar memórias", - "yearsAgo": "{count, plural, one{{count} anos atrás} other{{count} anos atrás}}", - "backupSettings": "Configurações de backup", - "backupStatus": "Status do Backup", - "backupStatusDescription": "Os itens que foram salvos no backup aparecerão aqui", - "backupOverMobileData": "Backup usando dados móveis", + "yearsAgo": "{count, plural, one{{count} ano atrás} other{{count} anos atrás}}", + "backupSettings": "Opções de cópia de segurança", + "backupStatus": "Status da cópia de segurança", + "backupStatusDescription": "Os itens que foram salvos com segurança aparecerão aqui", + "backupOverMobileData": "Salvamento com segurança usando dados móveis", "backupVideos": "Backup de vídeos", "disableAutoLock": "Desativar bloqueio automático", "deviceLockExplanation": "Desative o bloqueio de tela do dispositivo quando o Ente estiver em primeiro plano e houver um backup em andamento. Isso normalmente não é necessário, mas pode ajudar nos envios grandes e importações iniciais de grandes bibliotecas a serem concluídos mais rapidamente.", @@ -1085,7 +1085,7 @@ "verifyIDLabel": "Verificar", "fileInfoAddDescHint": "Adicionar descrição...", "editLocationTagTitle": "Editar local", - "setLabel": "Aplicar", + "setLabel": "Definir", "@setLabel": { "description": "Label of confirm button to add a new custom radius to the radius selector of a location tag" }, @@ -1140,7 +1140,7 @@ "@iOSGoToSettingsDescription": { "description": "Message advising the user to go to the settings and configure Biometrics for their device. It shows in a dialog on iOS side." }, - "iOSOkButton": "Tudo bem", + "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." }, From 90b994c752955e6a5da8a1b24d0924926f236335 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 7 Oct 2024 01:17:23 +0000 Subject: [PATCH 005/438] New Crowdin translations by GitHub Action --- auth/lib/l10n/arb/app_cs.arb | 1 + auth/lib/l10n/arb/app_lt.arb | 1 + auth/lib/l10n/arb/app_pt.arb | 122 +++++++++++++++++------------------ auth/lib/l10n/arb/app_ru.arb | 31 ++++++++- 4 files changed, 93 insertions(+), 62 deletions(-) create mode 100644 auth/lib/l10n/arb/app_cs.arb create mode 100644 auth/lib/l10n/arb/app_lt.arb diff --git a/auth/lib/l10n/arb/app_cs.arb b/auth/lib/l10n/arb/app_cs.arb new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/auth/lib/l10n/arb/app_cs.arb @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/auth/lib/l10n/arb/app_lt.arb b/auth/lib/l10n/arb/app_lt.arb new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/auth/lib/l10n/arb/app_lt.arb @@ -0,0 +1 @@ +{} \ 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 61a4de559e..19e2795e91 100644 --- a/auth/lib/l10n/arb/app_pt.arb +++ b/auth/lib/l10n/arb/app_pt.arb @@ -6,20 +6,20 @@ "@counterAppBarTitle": { "description": "Text shown in the AppBar of the Counter Page" }, - "onBoardingBody": "Proteja os seus códigos 2FA", + "onBoardingBody": "Copie com segurança seus códigos 2FA", "onBoardingGetStarted": "Introdução", "setupFirstAccount": "Configure sua primeira conta", "importScanQrCode": "Escanear QR code", "qrCode": "QR Code", "importEnterSetupKey": "Insira uma chave de configuração", - "importAccountPageTitle": "Inserir dados da conta", - "secretCanNotBeEmpty": "A chave secreta não pode ser vazia", + "importAccountPageTitle": "Inserir detalhes da conta", + "secretCanNotBeEmpty": "O segredo não pode estar vazio", "bothIssuerAndAccountCanNotBeEmpty": "O emissor e a conta não podem estar vazios", "incorrectDetails": "Detalhes incorretos", - "pleaseVerifyDetails": "Por favor, verifique os detalhes e tente novamente", + "pleaseVerifyDetails": "Verifique os detalhes e tente novamente", "codeIssuerHint": "Emissor", "codeSecretKeyHint": "Chave secreta", - "secret": "Secreto", + "secret": "Segredo", "all": "Todos", "notes": "Notas", "notesLengthLimit": "Notas tem um limite de até {count} caracteres", @@ -33,7 +33,7 @@ } } }, - "codeAccountHint": "Conta (você@domínio.com)", + "codeAccountHint": "Conta (voce@dominio.com)", "codeTagHint": "Etiqueta", "accountKeyType": "Tipo de chave", "sessionExpired": "Sessão expirada", @@ -46,16 +46,16 @@ "counterBasedKeyType": "Baseado num contador (HOTP)", "saveAction": "Salvar", "nextTotpTitle": "avançar", - "deleteCodeTitle": "Apagar código?", + "deleteCodeTitle": "Excluir código?", "deleteCodeMessage": "Deseja mesmo excluir este código? Esta ação é irreversível.", "trashCode": "Excluir código?", "trashCodeMessage": "Você tem certeza de que quer excluir o código para {account}?", "trash": "Excluir", - "viewLogsAction": "Ver logs", - "sendLogsDescription": "Isto compartilhará seus dados para nos ajudarmos a resolver seu problema. Enquanto tomamos precauções para ter certeza que as informações sensíveis não estejam registradas, nós encorajamos você a visualizar esses dados antes de compartilhá-los.", - "preparingLogsTitle": "Preparando logs...", - "emailLogsTitle": "Logs (e-mail)", - "emailLogsMessage": "Envie os logs para {email}", + "viewLogsAction": "Ver registros", + "sendLogsDescription": "Isso compartilhará seus dados para lhe ajudarmos a resolver seu problema. Enquanto tomamos precauções para ter certeza que as informações sensíveis não estejam registradas, nós encorajamos você a visualizar esses dados antes de compartilhá-los.", + "preparingLogsTitle": "Preparando registros...", + "emailLogsTitle": "Registros (e-mail)", + "emailLogsMessage": "Envie os registros para {email}", "@emailLogsMessage": { "placeholders": { "email": { @@ -64,9 +64,9 @@ } }, "copyEmailAction": "Copiar e-mail", - "exportLogsAction": "Exportar logs", + "exportLogsAction": "Exportar registros", "reportABug": "Informe um erro", - "crashAndErrorReporting": "Relatórios de erros", + "crashAndErrorReporting": "Relatórios de erros e falhas", "reportBug": "Informar erro", "emailUsMessage": "Envie um e-mail para {email}", "@emailUsMessage": { @@ -76,8 +76,8 @@ } } }, - "contactSupport": "Falar com o Suporte", - "rateUsOnStore": "Avalie-nos na {storeName}", + "contactSupport": "Contatar suporte", + "rateUsOnStore": "Avalie nós na {storeName}", "blog": "Blog", "merchandise": "Produtos", "verifyPassword": "Verificar senha", @@ -100,29 +100,29 @@ "passwordForDecryptingExport": "Senha para descriptografar a exportação", "passwordEmptyError": "A senha não pode estar vazia", "importFromApp": "Importar códigos do {appName}", - "importGoogleAuthGuide": "Exporte suas contas do Google Authenticator para um QR code usando a opção \"Transferir contas\". Então, usando outro dispositivo, escaneie o QR code.\n\nDica: você pode usar a câmera do notebook para fotografar o QR code.", + "importGoogleAuthGuide": "Exporte suas contas do Google Authenticator para um QR code usando a opção \"Transferir Contas\". Então, usando outro dispositivo, escaneie o código.\n\nDica: Você pode usar a câmera do seu notebook para fotografar o QR code.", "importSelectJsonFile": "Selecionar arquivo JSON", "importSelectAppExport": "Selecione o arquivo de exportação do aplicativo {appName}", "importEnteEncGuide": "Selecione o arquivo JSON criptografado exportado do Ente", - "importRaivoGuide": "Use a opção \"Exportar OTPs para arquivo Zip\" nas configurações do Raivo.\n\nExtraia o arquivo zip e importe o arquivo JSON.", - "importBitwardenGuide": "Use a opção \"Exportar cofre\" nas configurações do Bitwarden e importe o arquivo JSON não criptografado.", - "importAegisGuide": "Use a opção \"Exportar cofre\" nas Configurações do Aegis.\n\nSe o seu cofre estiver criptografado, você precisará inserir a senha do cofre para descriptografá-lo.", - "import2FasGuide": "Use a opção \"Configurações->Exportar cópia de segurança\" no aplicativo 2FAS.\n\nSe a cópia de segurança estiver criptografada, será necessário inserir a senha para descriptografá-la", - "importLastpassGuide": "Use a opção \"Transferir contas\" nas configurações do LastPass Authenticator e pressione \"Exportar contas para arquivo\". Importe o arquivo JSON baixado.", + "importRaivoGuide": "Use a opção \"Exportar OTPs para arquivo zip\" nas opções de Raivo.\n\nExtraia o arquivo zip e importe o arquivo JSON.", + "importBitwardenGuide": "Use a opção \"Exportar cofre\" nas ferramentas do Bitwarden e importe o arquivo JSON não criptografado.", + "importAegisGuide": "Use a opção \"Exportar cofre\" nas opções de Aegis\n\nSe o cofre estiver criptografado, você precisará inserir a senha do cofre para descriptografá-lo.", + "import2FasGuide": "Use a opção \"Opções-> Exportar cópia de segurança\" em 2FAS.\n\nSe a cópia de segurança estiver criptografada, você precisará inserir a senha para descriptografá-la", + "importLastpassGuide": "Use a opção \"Transferir contas\" nas opções do LastPass Authenticator e pressione \"Exportar contas para arquivo\". Importe o arquivo JSON baixado.", "exportCodes": "Exportar códigos", "importLabel": "Importar", - "importInstruction": "Por favor, selecione um arquivo que contenha uma lista de códigos no seguinte formato", + "importInstruction": "Selecione um arquivo que contenha uma lista de códigos no formato a seguir", "importCodeDelimiterInfo": "Os códigos podem ser separados por uma vírgula ou uma nova linha", "selectFile": "Selecionar arquivo", "emailVerificationToggle": "Verificação por e-mail", - "emailVerificationEnableWarning": "Para evitar ficar bloqueado do acesso a sua conta, certifique-se de armazenar uma cópia do código 2FA do seu e-mail fora do Ente Auth antes de habilitar a verificação por e-mail.", - "authToChangeEmailVerificationSetting": "Por favor, autentique-se para alterar a verificação por e-mail", - "authenticateGeneric": "Por favor, autentique", - "authToViewYourRecoveryKey": "Por favor, autentique-se para visualizar sua chave de recuperação", - "authToChangeYourEmail": "Por favor, autentique-se para alterar o seu e-mail", - "authToChangeYourPassword": "Por favor, autentique-se para alterar sua senha", - "authToViewSecrets": "Por favor, autentique-se para ver as suas chaves secretas", - "authToInitiateSignIn": "Por favor, autentique-se para iniciar o login para um backup.", + "emailVerificationEnableWarning": "Para evitar ser bloqueado da sua conta, certifique-se de guardar uma cópia do seu e-mail 2FA fora do Ente Auth antes de ativar a verificação de e-mail.", + "authToChangeEmailVerificationSetting": "Autentique-se para altere o e-mail de verificação", + "authenticateGeneric": "Autentique", + "authToViewYourRecoveryKey": "Autentique para ver sua chave de recuperação", + "authToChangeYourEmail": "Autentique para alterar o seu e-mail", + "authToChangeYourPassword": "Autentique para alterar sua senha", + "authToViewSecrets": "Autentique para ver suas chaves secretas", + "authToInitiateSignIn": "Autentique para iniciar sessão para fazer uma cópia de segurança.", "ok": "OK", "cancel": "Cancelar", "yes": "Sim", @@ -159,7 +159,7 @@ "recoverAccount": "Recuperar conta", "enterRecoveryKeyHint": "Digite a chave de recuperação", "recover": "Recuperar", - "contactSupportViaEmailMessage": "Por favor, envie um e-mail para {email} a partir do seu endereço de e-mail registrado", + "contactSupportViaEmailMessage": "Envie um e-mail para {email} a partir do seu endereço de e-mail registrado", "@contactSupportViaEmailMessage": { "placeholders": { "email": { @@ -176,7 +176,7 @@ "deleteAccountQuery": "Estamos tristes com sua decisão. Você encontrou algum problema?", "yesSendFeedbackAction": "Sim, enviar feedback", "noDeleteAccountAction": "Não, excluir conta", - "initiateAccountDeleteTitle": "Por favor, autentique-se para iniciar a exclusão de conta", + "initiateAccountDeleteTitle": "Autentique para iniciar a exclusão de conta", "sendEmail": "Enviar e-mail", "createNewAccount": "Criar nova conta", "weakStrength": "Fraca", @@ -190,10 +190,10 @@ "social": "Redes sociais", "security": "Segurança", "lockscreen": "Tela de bloqueio", - "authToChangeLockscreenSetting": "Por favor, autentique-se para alterar a configuração da tela de bloqueio", + "authToChangeLockscreenSetting": "Autentique para alterar a opção de tela de bloqueio", "deviceLockEnablePreSteps": "Para ativar o bloqueio do dispositivo, configure a senha do dispositivo ou o bloqueio de tela nas configurações do seu sistema.", "viewActiveSessions": "Ver sessões ativas", - "authToViewYourActiveSessions": "Por favor, autentique-se para ver as sessões ativas", + "authToViewYourActiveSessions": "Autentique para ver suas sessões ativas", "searchHint": "Buscar...", "search": "Buscar", "sorryUnableToGenCode": "Desculpe, não foi possível gerar um código para {issuerName}", @@ -242,16 +242,16 @@ "resetPasswordTitle": "Redefinir senha", "encryptionKeys": "Chaves de criptografia", "passwordWarning": "Não salvamos esta senha, então se você esquecê-la, não podemos descriptografar seus dados", - "enterPasswordToEncrypt": "Digite uma senha que podemos usar para criptografar seus dados", + "enterPasswordToEncrypt": "Insira uma senha que podemos usar para criptografar seus dados", "enterNewPasswordToEncrypt": "Insira uma nova senha para criptografar seus dados", "passwordChangedSuccessfully": "A senha foi alterada", "generatingEncryptionKeys": "Gerando chaves de criptografia...", "continueLabel": "Continuar", "insecureDevice": "Dispositivo inseguro", - "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Desculpe, não foi possível gerar chaves seguras neste dispositivo.\n\npor favor, faça o login com um dispositivo diferente.", + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Desculpe, não foi possível gerar chaves de segurança nesse dispositivo.\n\ninicie sessão em um dispositivo diferente.", "howItWorks": "Como funciona", "ackPasswordLostWarning": "Eu entendo que se eu perder minha senha, posso perder meus dados, já que meus dados são criptografados de ponta a ponta.", - "loginTerms": "Ao clicar em login, eu concordo com os termos de serviço e a política de privacidade", + "loginTerms": "Ao clicar em iniciar sessão, eu concordo com os termos de serviço e a política de privacidade", "logInLabel": "Entrar", "logout": "Sair", "areYouSureYouWantToLogout": "Deseja mesmo sair?", @@ -259,15 +259,15 @@ "exit": "Sair", "verifyingRecoveryKey": "Verificando chave de recuperação...", "recoveryKeyVerified": "Chave de recuperação verificada", - "recoveryKeySuccessBody": "Ótimo! Sua chave de recuperação é válida. Obrigado por verificar.\n\nLembre-se de manter o backup seguro de sua chave de recuperação.", - "invalidRecoveryKey": "A chave de recuperação que você digitou não é válida. Certifique-se de que contém 24 palavras e verifique a ortografia de cada uma.\n\nSe você inseriu um código de recuperação mais antigo, verifique se ele tem 64 caracteres e verifique cada um deles.", + "recoveryKeySuccessBody": "Ótimo! Sua chave de recuperação é válida. Obrigada por verificar.\n\nLembre-se de manter sua chave de recuperação copiada com segurança.", + "invalidRecoveryKey": "A chave de recuperação que você inseriu não é válida. Certifique-se de conter 24 caracteres, e verifique a ortografia de cada um deles.\n\nSe você inseriu um código de recuperação mais antigo, verifique se ele tem 64 caracteres e verifique cada um deles.", "recreatePasswordTitle": "Redefinir senha", "recreatePasswordBody": "Não é possível verificar a sua senha no dispositivo atual, mas podemos regenerá-la para que funcione em todos os dispositivos. \n\nEntre com a sua chave de recuperação e regenere sua senha (você pode usar a mesma se quiser).", "invalidKey": "Chave inválida", "tryAgain": "Tente novamente", "viewRecoveryKey": "Ver chave de recuperação", "confirmRecoveryKey": "Confirme a chave de recuperação", - "recoveryKeyVerifyReason": "Sua chave de recuperação é a única maneira de recuperar suas fotos se você esquecer sua senha. Você pode encontrar sua chave de recuperação em Configurações > Conta.\n\nDigite sua chave de recuperação aqui para verificar se você a salvou corretamente.", + "recoveryKeyVerifyReason": "Sua chave de recuperação é a única maneira de recuperar suas fotos se você esqueceu sua senha. Você pode encontrar sua chave de recuperação em Opções > Conta.\n\nInsira sua chave de recuperação aqui para verificar se você a salvou corretamente.", "confirmYourRecoveryKey": "Confirme sua chave de recuperação", "confirm": "Confirmar", "emailYourLogs": "Enviar logs por e-mail", @@ -275,10 +275,10 @@ "copyEmailAddress": "Copiar endereço de e-mail", "exportLogs": "Exportar logs", "enterYourRecoveryKey": "Digite a chave de recuperação", - "tempErrorContactSupportIfPersists": "Parece que algo deu errado. Por favor, tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de suporte.", + "tempErrorContactSupportIfPersists": "Parece que algo deu errado. Tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de ajuda.", "networkHostLookUpErr": "Não foi possível conectar-se ao Ente, verifique suas configurações de rede e entre em contato com o suporte se o erro persistir.", "networkConnectionRefusedErr": "Não foi possível conectar ao Ente, tente novamente após algum tempo. Se o erro persistir, entre em contato com o suporte.", - "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Parece que algo deu errado. Por favor, tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de suporte.", + "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Parece que algo deu errado. Tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de ajuda.", "about": "Sobre", "weAreOpenSource": "Nosso código é aberto!", "privacy": "Privacidade", @@ -292,12 +292,12 @@ "checking": "Verificando...", "youAreOnTheLatestVersion": "Você está na versão mais recente", "warning": "Atenção", - "exportWarningDesc": "O arquivo exportado contém informações confidenciais. Por favor, armazene-o com segurança.", + "exportWarningDesc": "O arquivo exportado contém informações confidenciais. Armazene-o com segurança.", "iUnderStand": "Entendo", "@iUnderStand": { "description": "Text for the button to confirm the user understands the warning" }, - "authToExportCodes": "Por favor, autentique-se para exportar seus códigos", + "authToExportCodes": "Autentique para exportar seus códigos", "importSuccessTitle": "Oba!", "importSuccessDesc": "Você importou {count} códigos!", "@importSuccessDesc": { @@ -310,9 +310,9 @@ } }, "sorry": "Desculpe", - "importFailureDesc": "Não foi possível analisar o arquivo selecionado.\nPor favor, escreva para support@ente.io se precisar de ajuda!", + "importFailureDesc": "Não foi possível analisar o arquivo selecionado. Escreva para support@ente.io se precisar de ajuda!", "pendingSyncs": "Atenção", - "pendingSyncsWarningBody": "Alguns de seus códigos não foram salvos.\n\nPor favor, certifique-se que você possui um backup para esses códigos antes de sair.", + "pendingSyncsWarningBody": "Alguns de seus códigos não foram salvos.\n\nCertifique-se que você possui uma cópia desses códigos antes de sair.", "checkInboxAndSpamFolder": "Verifique sua caixa de entrada (e spam) para concluir a verificação", "tapToEnterCode": "Toque para inserir código", "resendEmail": "Reenviar e-mail", @@ -328,20 +328,20 @@ } }, "activeSessions": "Sessões ativas", - "somethingWentWrongPleaseTryAgain": "Algo deu errado. Por favor, tente outra vez", + "somethingWentWrongPleaseTryAgain": "Algo deu errado. Tente outra vez", "thisWillLogYouOutOfThisDevice": "Isso fará com que você saia deste dispositivo!", - "thisWillLogYouOutOfTheFollowingDevice": "Isso fará com que você saia do seguinte dispositivo:", + "thisWillLogYouOutOfTheFollowingDevice": "Isso fará você sair do dispositivo a seguir:", "terminateSession": "Sair?", "terminate": "Encerrar", "thisDevice": "Esse dispositivo", - "toResetVerifyEmail": "Para redefinir a sua senha, por favor verifique o seu email primeiro.", + "toResetVerifyEmail": "Para redefinir sua senha, verifique seu e-mail primeiramente.", "thisEmailIsAlreadyInUse": "Este e-mail já está em uso", "verificationFailedPleaseTryAgain": "Falha na verificação. Tente novamente", "yourVerificationCodeHasExpired": "Seu código de verificação expirou", "incorrectCode": "Código incorreto", - "sorryTheCodeYouveEnteredIsIncorrect": "Desculpe, o código que você inseriu está incorreto", + "sorryTheCodeYouveEnteredIsIncorrect": "O código inserido está incorreto", "emailChangedTo": "E-mail alterado para {newEmail}", - "authenticationFailedPleaseTryAgain": "Falha na autenticação. Por favor, tente novamente", + "authenticationFailedPleaseTryAgain": "A autenticação falhou. Tente novamente", "authenticationSuccessful": "Autenticado!", "twofactorAuthenticationSuccessfullyReset": "Autenticação de dois fatores redefinida com sucesso", "incorrectRecoveryKey": "Chave de recuperação incorreta", @@ -356,8 +356,8 @@ "useOffline": "Usar sem backups", "signInToBackup": "Entre para fazer backup de seus códigos", "singIn": "Entrar", - "sigInBackupReminder": "Por favor, exporte seus códigos para garantir que você tenha um backup do qual você possa restaurar.", - "offlineModeWarning": "Você escolheu prosseguir sem backups. Por favor, faça backups manuais para ter certeza de que seus códigos estão seguros.", + "sigInBackupReminder": "Exporte seus códigos para garantir que você tenha uma cópia para restaurar.", + "offlineModeWarning": "Você decidiu prosseguir sem cópias. Faça cópias manuais para garantir que seus códigos estejam seguros.", "showLargeIcons": "Mostrar ícones grandes", "compactMode": "Modo compacto", "shouldHideCode": "Ocultar códigos", @@ -406,15 +406,15 @@ "@goToSettings": { "description": "Message showed on a button that the user can click to go to settings pages from the current dialog. It is used on both Android and iOS side. Maximum 30 characters." }, - "androidGoToSettingsDescription": "A autenticação biométrica não está configurada no seu dispositivo. Vá em 'Configurações > Segurança' para adicionar autenticação biométrica.", + "androidGoToSettingsDescription": "A autenticação biométrica não está configurada no seu dispositivo. Vá em 'Configurações > Segurança' para adicionar a autenticação biométrica.", "@androidGoToSettingsDescription": { "description": "Message advising the user to go to the settings and configure biometric on their device. It shows in a dialog on Android side." }, - "iOSLockOut": "A Autenticação Biométrica está desativada. Por favor, bloqueie e desbloqueie sua tela para ativá-la.", + "iOSLockOut": "A autenticação biométrica está desativada. Bloqueie e desbloqueie sua tela para ativá-la.", "@iOSLockOut": { "description": "Message advising the user to re-enable biometrics on their device. It shows in a dialog on iOS side." }, - "iOSGoToSettingsDescription": "A autenticação biométrica não está configurada no seu dispositivo. Por favor, ative o Touch ID ou o Face ID no seu telefone.", + "iOSGoToSettingsDescription": "A autenticação biométrica não está configurada no seu dispositivo. Ative o ID de toque ou ID de rosto em seu celular.", "@iOSGoToSettingsDescription": { "description": "Message advising the user to go to the settings and configure Biometrics for their device. It shows in a dialog on iOS side." }, @@ -425,10 +425,10 @@ "noInternetConnection": "Não conectado à internet", "pleaseCheckYourInternetConnectionAndTryAgain": "Verifique sua conexão com a internet e tente novamente.", "signOutFromOtherDevices": "Sair da conta em outros dispositivos", - "signOutOtherBody": "Se você acha que alguém pode saber sua senha, você pode forçar todos os outros dispositivos que estão com sua conta a desconectar.", + "signOutOtherBody": "Se você acha que alguém possa saber da sua senha, você pode forçar desconectar sua conta de outros dispositivos.", "signOutOtherDevices": "Sair em outros dispositivos", "doNotSignOut": "Não sair", - "hearUsWhereTitle": "Como você ouviu sobre o Ente? (opcional)", + "hearUsWhereTitle": "Como você descobriu o Ente? (opcional)", "hearUsExplanation": "Não sabemos como você encontrou nosso app. Seria útil se você nos contasse!", "recoveryKeySaved": "Chave de recuperação salva na pasta Downloads!", "waitingForBrowserRequest": "Aguardando solicitação do navegador...", @@ -436,12 +436,12 @@ "passkey": "Chave de acesso", "passKeyPendingVerification": "A verificação ainda está pendente", "loginSessionExpired": "Sessão expirada", - "loginSessionExpiredDetails": "Sua sessão expirou. Por favor, entre novamente.", + "loginSessionExpiredDetails": "Sua sessão expirou. Registre-se novamente.", "developerSettingsWarning": "Deseja mesmo alterar os ajustes de Desenvolvedor?", "developerSettings": "Ajustes 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.", + "invalidEndpointMessage": "Desculpe, o ponto de acesso inserido é inválido. Insira um ponto de acesso válido e tente novamente.", "endpointUpdatedMessage": "O endpoint foi atualizado", "customEndpoint": "Conectado a {endpoint}", "pinText": "Fixar", diff --git a/auth/lib/l10n/arb/app_ru.arb b/auth/lib/l10n/arb/app_ru.arb index aa320299ea..6f3a88eb63 100644 --- a/auth/lib/l10n/arb/app_ru.arb +++ b/auth/lib/l10n/arb/app_ru.arb @@ -19,6 +19,20 @@ "pleaseVerifyDetails": "Пожалуйста, проверьте детали и попробуйте еще раз", "codeIssuerHint": "Эмитент", "codeSecretKeyHint": "Секретный ключ", + "secret": "Секрет", + "all": "Все", + "notes": "Заметки", + "notesLengthLimit": "Заметки могут быть не более {count} символов", + "@notesLengthLimit": { + "description": "Text to indicate the maximum number of characters allowed for notes", + "placeholders": { + "count": { + "description": "The maximum number of characters allowed for notes", + "type": "int", + "example": "100" + } + } + }, "codeAccountHint": "Аккаунт (you@domain.com)", "codeTagHint": "Метка", "accountKeyType": "Тип ключа", @@ -34,6 +48,9 @@ "nextTotpTitle": "далее", "deleteCodeTitle": "Удалить код?", "deleteCodeMessage": "Вы уверены, что хотите удалить этот код? Это действие необратимо.", + "trashCode": "Удалить код?", + "trashCodeMessage": "Вы уверены, что хотите удалить код для {account}?", + "trash": "Удалить", "viewLogsAction": "Посмотреть журнал", "sendLogsDescription": "Это отправит все журналы, чтобы помочь нам отладить вашу проблему. Хотя мы принимаем меры предосторожности, чтобы конфиденциальная информация не регистрировалась, мы рекомендуем вам просмотреть эти журналы, прежде чем делиться ими.", "preparingLogsTitle": "Подготовка журналов...", @@ -100,6 +117,7 @@ "emailVerificationToggle": "Подтверждение электронной почты", "emailVerificationEnableWarning": "Если вы храните у нас двухфакторную аутентификацию в своей электронной почте, включение проверки электронной почты может привести к тупиковой ситуации. Если у вас заблокирован доступ к одной службе, возможно, вы не сможете войти в другую.", "authToChangeEmailVerificationSetting": "Авторизуйтесь, чтобы изменить подтверждение электронной почты", + "authenticateGeneric": "Пожалуйста, авторизуйтесь", "authToViewYourRecoveryKey": "Пожалуйста, авторизуйтесь для просмотра вашего ключа восстановления", "authToChangeYourEmail": "Пожалуйста, авторизуйтесь, чтобы изменить адрес электронной почты", "authToChangeYourPassword": "Пожалуйста, авторизуйтесь, чтобы изменить пароль", @@ -127,6 +145,8 @@ "leaveFamily": "Покинуть семью", "leaveFamilyMessage": "Вы уверены, что хотите отказаться от семейного плана?", "inFamilyPlanMessage": "Вы на семейном плане!", + "hintForMobile": "Длительное нажмите на код для редактирования или удаления.", + "hintForDesktop": "Щелкните правой кнопкой мыши по коду, чтобы изменить или удалить.", "scan": "Сканировать", "scanACode": "Сканировать QR-код", "verify": "Подтвердить", @@ -171,6 +191,7 @@ "security": "Безопасность", "lockscreen": "Экран блокировки", "authToChangeLockscreenSetting": "Пожалуйста, авторизуйтесь, чтобы изменить настройки экрана блокировки", + "deviceLockEnablePreSteps": "Чтобы включить блокировку устройства, пожалуйста, настройте пароль или блокировку экрана в настройках системы.", "viewActiveSessions": "Просмотр активных сессий", "authToViewYourActiveSessions": "Пожалуйста, авторизуйтесь для просмотра активных сессий", "searchHint": "Поиск...", @@ -181,6 +202,10 @@ "scanAQrCode": "Сканировать QR-код", "enterDetailsManually": "Ввести детали вручную", "edit": "Редактировать", + "share": "Поделиться", + "shareCodes": "Поделиться кодами", + "shareCodesDuration": "Выберите продолжительность, на которую вы хотите поделиться кодами.", + "restore": "Восстановить", "copiedToClipboard": "Скопировано", "copiedNextToClipboard": "Следующий код скопирован в буфер обмена", "error": "Ошибка", @@ -334,6 +359,7 @@ "sigInBackupReminder": "Экспортируйте свои коды, чтобы убедиться, что у вас есть резервная копия, из которой можно восстановить.", "offlineModeWarning": "Вы решили продолжить без резервных копий. Пожалуйста, создайте резервные копии вручную, чтобы убедиться, что ваши коды в безопасности.", "showLargeIcons": "Использовать большие значки", + "compactMode": "Компактный режим", "shouldHideCode": "Скрыть коды", "doubleTapToViewHiddenCode": "Вы можете нажать дважды на запись для просмотра кода", "focusOnSearchBar": "Фокусировать поиск при запуске приложения", @@ -454,5 +480,8 @@ "pinLock": "Pin Замок", "enterPin": "Введите PIN", "setNewPin": "Установите новый PIN", - "importFailureDescNew": "Не удалось обработать выбранный файл." + "importFailureDescNew": "Не удалось обработать выбранный файл.", + "appLockNotEnabled": "Блокировка приложения отключена", + "appLockNotEnabledDescription": "Пожалуйста, включите блокировку приложения в безопасности > Блокировка приложений", + "authToViewPasskey": "Пожалуйста, авторизуйтесь, чтобы просмотреть пароль" } \ No newline at end of file From 46134b3b9a4561b17706b4ecbbcaa0d950b1d940 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 10:00:41 +0530 Subject: [PATCH 006/438] related --- .../src/components/pages/gallery/SelectedFileOptions.tsx | 4 ++-- .../new/photos/components/CollectionSelector.tsx | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/web/apps/photos/src/components/pages/gallery/SelectedFileOptions.tsx b/web/apps/photos/src/components/pages/gallery/SelectedFileOptions.tsx index a876ae4ae3..01d1cf7e87 100644 --- a/web/apps/photos/src/components/pages/gallery/SelectedFileOptions.tsx +++ b/web/apps/photos/src/components/pages/gallery/SelectedFileOptions.tsx @@ -85,7 +85,7 @@ const SelectedFileOptions = ({ onCreateCollection: showCreateCollectionModal( COLLECTION_OPS_TYPE.ADD, ), - ignoredCollectionID: + relatedCollectionID: isInSearchMode || peopleMode ? undefined : activeCollectionID, }); @@ -158,7 +158,7 @@ const SelectedFileOptions = ({ onCreateCollection: showCreateCollectionModal( COLLECTION_OPS_TYPE.MOVE, ), - ignoredCollectionID: + relatedCollectionID: isInSearchMode || peopleMode ? undefined : activeCollectionID, }); }; diff --git a/web/packages/new/photos/components/CollectionSelector.tsx b/web/packages/new/photos/components/CollectionSelector.tsx index e7690be1bb..2d3cd1cb9f 100644 --- a/web/packages/new/photos/components/CollectionSelector.tsx +++ b/web/packages/new/photos/components/CollectionSelector.tsx @@ -59,11 +59,10 @@ export interface CollectionSelectorAttributes { onCancel?: () => void; /** * Some actions, like "add" and "move", happen in the context of an existing - * collection. In such cases, their ID can be set as the - * {@link ignoredCollectionID} to omit showing them again in the list of - * collections. + * collection. In such cases, the ID of this collection can be set as the + * {@link relatedCollectionID} to omit showing it in the list again. */ - ignoredCollectionID?: number | undefined; + relatedCollectionID?: number | undefined; } type CollectionSelectorProps = DialogVisibilityProps & { @@ -111,7 +110,7 @@ export const CollectionSelector: React.FC = ({ const collections = [...collectionSummaries.values()] .filter(({ id, type }) => { - if (id === attributes.ignoredCollectionID) { + if (id === attributes.relatedCollectionID) { return false; } else if (attributes.action == "add") { return canAddToCollection(type); From 70051b66b72e0412ab4ee8db654582d72fbc494b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 10:06:45 +0530 Subject: [PATCH 007/438] Scaffold --- .../Collections/GalleryBarAndListHeader.tsx | 13 ++++++++++ .../new/photos/components/PeopleSelector.tsx | 24 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 web/packages/new/photos/components/PeopleSelector.tsx diff --git a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx index fdc2900fc8..53646284a5 100644 --- a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx +++ b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx @@ -4,6 +4,7 @@ import { type GalleryBarImplProps, } from "@/new/photos/components/Gallery/BarImpl"; import { PeopleHeader } from "@/new/photos/components/Gallery/PeopleHeader"; +import { PeopleSelector } from "@/new/photos/components/PeopleSelector"; import { areOnlySystemCollections, collectionsSortBy, @@ -107,6 +108,7 @@ export const GalleryBarAndListHeader: React.FC = ({ const [openCollectionShareView, setOpenCollectionShareView] = useState(false); const [openAlbumCastDialog, setOpenAlbumCastDialog] = useState(false); + const [openPeopleSelector, setOpenPeopleSelector] = useState(false); const [collectionsSortBy, setCollectionsSortBy] = useCollectionsSortByLocalState("updation-time-desc"); @@ -189,6 +191,13 @@ export const GalleryBarAndListHeader: React.FC = ({ activePerson, ]); + // TODO-Cluster + useEffect(() => { + if (process.env.NEXT_PUBLIC_ENTE_WIP_CL) { + setOpenPeopleSelector(true); + } + }, []); + if (shouldBeHidden) { return <>; } @@ -238,6 +247,10 @@ export const GalleryBarAndListHeader: React.FC = ({ onClose={() => setOpenAlbumCastDialog(false)} collection={activeCollection} /> + setOpenPeopleSelector(false)} + /> ); }; diff --git a/web/packages/new/photos/components/PeopleSelector.tsx b/web/packages/new/photos/components/PeopleSelector.tsx new file mode 100644 index 0000000000..cff12f9359 --- /dev/null +++ b/web/packages/new/photos/components/PeopleSelector.tsx @@ -0,0 +1,24 @@ +import { useIsMobileWidth } from "@/base/hooks"; +import { Dialog } from "@mui/material"; +import React from "react"; +import type { DialogVisibilityProps } from "./mui/Dialog"; + +type PeopleSelectorProps = DialogVisibilityProps; + +export const PeopleSelector: React.FC = ({ + open, + onClose, +}) => { + const isFullScreen = useIsMobileWidth(); + + return ( + + Hello + + ); +}; From 8e79884e314bbe7c46cb40fe7a2e1c630dafab15 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 11:15:48 +0530 Subject: [PATCH 008/438] Better match the design --- web/packages/new/photos/components/CollectionSelector.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/packages/new/photos/components/CollectionSelector.tsx b/web/packages/new/photos/components/CollectionSelector.tsx index 2d3cd1cb9f..936e776a77 100644 --- a/web/packages/new/photos/components/CollectionSelector.tsx +++ b/web/packages/new/photos/components/CollectionSelector.tsx @@ -97,7 +97,7 @@ export const CollectionSelector: React.FC = ({ collectionForCollectionID, }) => { // Make the dialog fullscreen if the screen is <= the dialog's max width. - const isFullScreen = useMediaQuery("(max-width: 494px)"); + const isFullScreen = useMediaQuery("(max-width: 490px)"); const [filteredCollections, setFilteredCollections] = useState< CollectionSummary[] @@ -167,9 +167,9 @@ export const CollectionSelector: React.FC = ({ onClose={handleClose} fullWidth fullScreen={isFullScreen} - PaperProps={{ sx: { maxWidth: "494px" } }} + PaperProps={{ sx: { maxWidth: "490px" } }} > - + {titleForAction(action)} From ec115b3f8b1796b8e9d0e37992548a0f05401fb3 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 11:27:56 +0530 Subject: [PATCH 009/438] Dup --- .../Collections/AllCollections/content.tsx | 4 +- .../photos/components/CollectionSelector.tsx | 27 ++---- .../new/photos/components/PeopleSelector.tsx | 88 +++++++++++++++++-- web/packages/new/photos/components/Tiles.tsx | 30 +++++-- .../new/photos/components/mui/index.tsx | 5 ++ 5 files changed, 117 insertions(+), 37 deletions(-) diff --git a/web/apps/photos/src/components/Collections/AllCollections/content.tsx b/web/apps/photos/src/components/Collections/AllCollections/content.tsx index 5b8be1e863..019c52065b 100644 --- a/web/apps/photos/src/components/Collections/AllCollections/content.tsx +++ b/web/apps/photos/src/components/Collections/AllCollections/content.tsx @@ -1,6 +1,6 @@ import { - CollectionTileButton, ItemCard, + LargeTileButton, LargeTileTextOverlay, } from "@/new/photos/components/Tiles"; import type { CollectionSummary } from "@/new/photos/services/collection/ui"; @@ -166,7 +166,7 @@ const CollectionButton: React.FC = ({ isScrolling, }) => ( onCollectionClick(collectionSummary.id)} isScrolling={isScrolling} diff --git a/web/packages/new/photos/components/CollectionSelector.tsx b/web/packages/new/photos/components/CollectionSelector.tsx index 936e776a77..48bfd70b88 100644 --- a/web/packages/new/photos/components/CollectionSelector.tsx +++ b/web/packages/new/photos/components/CollectionSelector.tsx @@ -1,8 +1,8 @@ import type { Collection } from "@/media/collection"; import { - CollectionTileButton, ItemCard, - ItemTileOverlay, + LargeTileButton, + LargeTilePlusOverlay, LargeTileTextOverlay, } from "@/new/photos/components/Tiles"; import { @@ -23,7 +23,7 @@ import { } from "@mui/material"; import { t } from "i18next"; import React, { useEffect, useState } from "react"; -import { SpaceBetweenFlex } from "./mui"; +import { SpaceBetweenFlex, type ButtonishProps } from "./mui"; import { DialogCloseIconButton, type DialogVisibilityProps, @@ -221,7 +221,7 @@ const CollectionButton: React.FC = ({ onCollectionClick, }) => ( onCollectionClick(collectionSummary.id)} > @@ -231,22 +231,9 @@ const CollectionButton: React.FC = ({ ); -interface AddCollectionButtonProps { - onClick: () => void; -} - -const AddCollectionButton: React.FC = ({ - onClick, -}) => ( - +const AddCollectionButton: React.FC = ({ onClick }) => ( + {t("create_albums")} - + + + ); - -const PlusOverlay = styled(ItemTileOverlay)` - display: flex; - justify-content: center; - align-items: center; - font-size: 42px; -`; diff --git a/web/packages/new/photos/components/PeopleSelector.tsx b/web/packages/new/photos/components/PeopleSelector.tsx index cff12f9359..5b98ce9868 100644 --- a/web/packages/new/photos/components/PeopleSelector.tsx +++ b/web/packages/new/photos/components/PeopleSelector.tsx @@ -1,7 +1,26 @@ -import { useIsMobileWidth } from "@/base/hooks"; -import { Dialog } from "@mui/material"; +import { pt } from "@/base/i18n"; +import { + Dialog, + DialogContent, + DialogTitle, + styled, + Typography, + useMediaQuery, +} from "@mui/material"; +import { t } from "i18next"; import React from "react"; -import type { DialogVisibilityProps } from "./mui/Dialog"; +import type { CollectionSummary } from "../services/collection/ui"; +import { SpaceBetweenFlex, type ButtonishProps } from "./mui"; +import { + DialogCloseIconButton, + type DialogVisibilityProps, +} from "./mui/Dialog"; +import { + ItemCard, + LargeTileButton, + LargeTilePlusOverlay, + LargeTileTextOverlay, +} from "./Tiles"; type PeopleSelectorProps = DialogVisibilityProps; @@ -9,16 +28,73 @@ export const PeopleSelector: React.FC = ({ open, onClose, }) => { - const isFullScreen = useIsMobileWidth(); + const isFullScreen = useMediaQuery("(max-width: 490px)"); + + const filteredCollections: CollectionSummary[] = []; + const handleAddPerson = () => { + console.log("handleAddPerson"); + }; + const handleSelectPerson = (id: string) => { + console.log("handleSelectPerson", id); + }; return ( - Hello + + + {pt("Add name")} + + + + + + + {filteredCollections.map((person) => ( + + ))} + ); }; + +const DialogContent_ = styled(DialogContent)` + display: flex; + flex-wrap: wrap; + gap: 4px; +`; + +interface PersonButtonProps { + person: CollectionSummary; + onPersonClick: (personID: string) => void; +} + +const PersonButton: React.FC = ({ + person, + onPersonClick, +}) => ( + onPersonClick(person.id.toString())} + > + + {person.name} + + +); + +const AddPerson: React.FC = ({ onClick }) => ( + + {t("New person")} + + + +); diff --git a/web/packages/new/photos/components/Tiles.tsx b/web/packages/new/photos/components/Tiles.tsx index c687f26224..cb0a340d85 100644 --- a/web/packages/new/photos/components/Tiles.tsx +++ b/web/packages/new/photos/components/Tiles.tsx @@ -102,7 +102,7 @@ export const ItemCard: React.FC> = ({ * Use {@link ItemTileOverlay} (usually via one of its presets) to overlay * content on top of the tile. */ -export const ItemTile = styled("div")` +export const BaseTile = styled("div")` display: flex; /* Act as container for the absolutely positioned ItemTileOverlays. */ position: relative; @@ -122,7 +122,7 @@ export const ItemTile = styled("div")` * A 48x48 TileComponent used in search result dropdown's preview files and * other places. */ -export const PreviewItemTile = styled(ItemTile)` +export const PreviewItemTile = styled(BaseTile)` width: 48px; height: 48px; `; @@ -130,15 +130,15 @@ export const PreviewItemTile = styled(ItemTile)` /** * A rectangular, TV-ish tile used in the gallery bar. */ -export const BarItemTile = styled(ItemTile)` +export const BarItemTile = styled(BaseTile)` width: 90px; height: 64px; `; /** - * A variant of {@link ItemTile} meant for use when the tile is interactable. + * A variant of {@link BaseTile} meant for use when the tile is interactable. */ -export const ItemTileButton = styled(UnstyledButton)` +export const BaseTileButton = styled(UnstyledButton)` /* Buttons reset this to center */ text-align: inherit; @@ -158,10 +158,10 @@ export const ItemTileButton = styled(UnstyledButton)` `; /** - * A large 150x150 TileComponent used when showing the list of collections in - * the all collections view and in the collection selector. + * A large 150x150 TileComponent used when, for example, when showing the list + * of collections in the all collections view and in the collection selector. */ -export const CollectionTileButton = styled(ItemTileButton)` +export const LargeTileButton = styled(BaseTileButton)` width: 150px; height: 150px; `; @@ -169,7 +169,8 @@ export const CollectionTileButton = styled(ItemTileButton)` /** * An empty overlay on top of the nearest relative positioned ancestor. * - * This is meant to be used in tandem with {@link ItemTile}. + * This is meant to be used in tandem with a derivate of {@link BaseTile} or + * {@link BaseTileButton}. */ export const ItemTileOverlay = styled("div")` position: absolute; @@ -204,3 +205,14 @@ export const LargeTileTextOverlay = styled(ItemTileOverlay)` rgba(0, 0, 0, 0.5) 86.46% ); `; + +/** + * A container for "+", suitable for use with a {@link LargeTileTextOverlay}. + */ +export const LargeTilePlusOverlay = styled(ItemTileOverlay)` + display: flex; + justify-content: center; + align-items: center; + font-size: 42px; + color: ${({ theme }) => theme.colors.stroke.muted}; +`; diff --git a/web/packages/new/photos/components/mui/index.tsx b/web/packages/new/photos/components/mui/index.tsx index bb88e71bb0..735de83bd4 100644 --- a/web/packages/new/photos/components/mui/index.tsx +++ b/web/packages/new/photos/components/mui/index.tsx @@ -1,5 +1,10 @@ import { Box, IconButton, styled } from "@mui/material"; +/** Convenience typed props for a component that acts like a push button. */ +export interface ButtonishProps { + onClick: () => void; +} + /** * A MUI {@link IconButton} filled in with at faint background. */ From bb13d1d98f441caea5b1752e3f06e88ada301697 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 12:18:08 +0530 Subject: [PATCH 010/438] Segue --- .../new/photos/components/NameInputDialog.tsx | 12 +++- .../new/photos/components/PeopleSelector.tsx | 71 ++++++++++++------- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/web/packages/new/photos/components/NameInputDialog.tsx b/web/packages/new/photos/components/NameInputDialog.tsx index a270a861a8..c6d01fd362 100644 --- a/web/packages/new/photos/components/NameInputDialog.tsx +++ b/web/packages/new/photos/components/NameInputDialog.tsx @@ -21,7 +21,7 @@ type NameInputDialogProps = DialogVisibilityProps & { * * @param name The current value of the text input. * */ - onSubmit: (name: string) => Promise; + onSubmit: ((name: string) => void) | ((name: string) => Promise); }; /** @@ -53,7 +53,13 @@ export const NameInputDialog: React.FC = ({ }; return ( - + {title} = ({ initialValue={initialValue} callback={handleSubmit} buttonText={submitButtonTitle} - submitButtonProps={{ sx: { mt: 1, mb: 2 } }} + submitButtonProps={{ sx: { mt: 2, mb: 1 } }} secondaryButtonAction={onClose} /> diff --git a/web/packages/new/photos/components/PeopleSelector.tsx b/web/packages/new/photos/components/PeopleSelector.tsx index 5b98ce9868..8ed5138d45 100644 --- a/web/packages/new/photos/components/PeopleSelector.tsx +++ b/web/packages/new/photos/components/PeopleSelector.tsx @@ -8,13 +8,14 @@ import { useMediaQuery, } from "@mui/material"; import { t } from "i18next"; -import React from "react"; +import React, { useState } from "react"; import type { CollectionSummary } from "../services/collection/ui"; import { SpaceBetweenFlex, type ButtonishProps } from "./mui"; import { DialogCloseIconButton, type DialogVisibilityProps, } from "./mui/Dialog"; +import { NameInputDialog } from "./NameInputDialog"; import { ItemCard, LargeTileButton, @@ -30,39 +31,59 @@ export const PeopleSelector: React.FC = ({ }) => { const isFullScreen = useMediaQuery("(max-width: 490px)"); + const [openNameInput, setOpenNameInput] = useState(false); + const filteredCollections: CollectionSummary[] = []; + const handleAddPerson = () => { console.log("handleAddPerson"); + setOpenNameInput(true); }; + const handleSelectPerson = (id: string) => { console.log("handleSelectPerson", id); }; - return ( - - - - {pt("Add name")} - - - + const handleAddPersonWithName = (name: string) => { + console.log("handleAddPersonWithName", name); + }; - - - {filteredCollections.map((person) => ( - - ))} - - + return ( + <> + + + + {pt("Add name")} + + + + + + {filteredCollections.map((person) => ( + + ))} + + + + setOpenNameInput(false)} + title={pt("New person") /* TODO-Cluster */} + placeholder={t("enter_name")} + initialValue={""} + submitButtonTitle={t("add")} + onSubmit={handleAddPersonWithName} + /> + ); }; From 72842e8c361736a1e6601d6eddec81e05cf7a40d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 13:51:34 +0530 Subject: [PATCH 011/438] Shortcircuit --- .../new/photos/components/PeopleSelector.tsx | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/web/packages/new/photos/components/PeopleSelector.tsx b/web/packages/new/photos/components/PeopleSelector.tsx index 8ed5138d45..78be8b99a8 100644 --- a/web/packages/new/photos/components/PeopleSelector.tsx +++ b/web/packages/new/photos/components/PeopleSelector.tsx @@ -33,7 +33,7 @@ export const PeopleSelector: React.FC = ({ const [openNameInput, setOpenNameInput] = useState(false); - const filteredCollections: CollectionSummary[] = []; + const people: CollectionSummary[] = []; const handleAddPerson = () => { console.log("handleAddPerson"); @@ -48,6 +48,27 @@ export const PeopleSelector: React.FC = ({ console.log("handleAddPersonWithName", name); }; + // [Note: Calling setState during rendering] + // + // Calling setState during rendering should be avoided when there are + // cleaner alternatives, but it is not completely verboten, and it has + // documented semantics: + // + // > React will discard the currently rendering component's output and + // > immediately attempt to render it again with the new state. + // > + // > https://react.dev/reference/react/useState + + // If we're opened without any existing people that can be selected, jump + // directly to the add person dialog. + // + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (open && !openNameInput && !people.length) { + onClose(); + setOpenNameInput(true); + return <>; + } + return ( <> = ({ - {filteredCollections.map((person) => ( + {people.map((person) => ( = ({ const AddPerson: React.FC = ({ onClick }) => ( - {t("New person")} + {pt("New person")} + ); From 62f1713a1ae76c7407f733d34d163486c6629d5e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 14:01:12 +0530 Subject: [PATCH 012/438] People --- .../new/photos/components/NameInputDialog.tsx | 2 +- .../new/photos/components/PeopleSelector.tsx | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/web/packages/new/photos/components/NameInputDialog.tsx b/web/packages/new/photos/components/NameInputDialog.tsx index c6d01fd362..ae7c499eaf 100644 --- a/web/packages/new/photos/components/NameInputDialog.tsx +++ b/web/packages/new/photos/components/NameInputDialog.tsx @@ -13,7 +13,7 @@ type NameInputDialogProps = DialogVisibilityProps & { /** Placeholder string to show in the text input when it is empty. */ placeholder: string; /** The existing value, if any, of the text input. */ - initialValue: string | undefined; + initialValue?: string | undefined; /** Title of the submit button */ submitButtonTitle: string; /** diff --git a/web/packages/new/photos/components/PeopleSelector.tsx b/web/packages/new/photos/components/PeopleSelector.tsx index 78be8b99a8..52fa8382fe 100644 --- a/web/packages/new/photos/components/PeopleSelector.tsx +++ b/web/packages/new/photos/components/PeopleSelector.tsx @@ -9,7 +9,7 @@ import { } from "@mui/material"; import { t } from "i18next"; import React, { useState } from "react"; -import type { CollectionSummary } from "../services/collection/ui"; +import type { Person } from "../services/ml/people"; import { SpaceBetweenFlex, type ButtonishProps } from "./mui"; import { DialogCloseIconButton, @@ -33,10 +33,9 @@ export const PeopleSelector: React.FC = ({ const [openNameInput, setOpenNameInput] = useState(false); - const people: CollectionSummary[] = []; + const people: Person[] = []; const handleAddPerson = () => { - console.log("handleAddPerson"); setOpenNameInput(true); }; @@ -100,7 +99,6 @@ export const PeopleSelector: React.FC = ({ onClose={() => setOpenNameInput(false)} title={pt("New person") /* TODO-Cluster */} placeholder={t("enter_name")} - initialValue={""} submitButtonTitle={t("add")} onSubmit={handleAddPersonWithName} /> @@ -115,7 +113,7 @@ const DialogContent_ = styled(DialogContent)` `; interface PersonButtonProps { - person: CollectionSummary; + person: Person; onPersonClick: (personID: string) => void; } @@ -125,8 +123,9 @@ const PersonButton: React.FC = ({ }) => ( onPersonClick(person.id.toString())} + coverFile={person.displayFaceFile} + coverFaceID={person.displayFaceID} + onClick={() => onPersonClick(person.id)} > {person.name} From 7227a4b0840dc951cc8899be8ba8f381930f7d15 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 14:22:12 +0530 Subject: [PATCH 013/438] Remove workaround --- web/packages/new/photos/services/ml/index.ts | 8 ++----- web/packages/new/photos/services/ml/people.ts | 23 +++++++++++++++++++ .../new/photos/services/search/index.ts | 4 ++-- .../new/photos/services/search/types.ts | 13 ----------- .../new/photos/services/search/worker.ts | 14 +++++------ 5 files changed, 34 insertions(+), 28 deletions(-) diff --git a/web/packages/new/photos/services/ml/index.ts b/web/packages/new/photos/services/ml/index.ts index 0c841e643d..b2b33a26e2 100644 --- a/web/packages/new/photos/services/ml/index.ts +++ b/web/packages/new/photos/services/ml/index.ts @@ -27,7 +27,7 @@ import { deleteUserEntity } from "../user-entity/remote"; import type { FaceCluster } from "./cluster"; import { regenerateFaceCrops } from "./crop"; import { clearMLDB, getFaceIndex, getIndexableAndIndexedCounts } from "./db"; -import { reconstructPeople, type Person } from "./people"; +import { filterNamedPeople, reconstructPeople, type Person } from "./people"; import { MLWorker } from "./worker"; import type { CLIPMatches } from "./worker-types"; @@ -575,11 +575,7 @@ const updatePeople = async () => { const people = await reconstructPeople(); // Notify the search subsystem of the update (search only uses named ones). - setSearchPeople( - people - .map((p) => (p.name ? { name: p.name, person: p } : undefined)) - .filter((p) => !!p), - ); + setSearchPeople(filterNamedPeople(people)); // Update our in-memory list of people. setPeopleSnapshot(people); diff --git a/web/packages/new/photos/services/ml/people.ts b/web/packages/new/photos/services/ml/people.ts index ef30e36707..a5e6b80733 100644 --- a/web/packages/new/photos/services/ml/people.ts +++ b/web/packages/new/photos/services/ml/people.ts @@ -125,6 +125,13 @@ export type Person = ( displayFaceFile: EnteFile; }; +/** + * A {@link Person} whose name is not empty. + */ +export type NamedPerson = Person & { + name: string; +}; + /** * Construct in-memory people using the data present locally, ignoring faces * belonging to deleted and hidden files. @@ -272,3 +279,19 @@ export const reconstructPeople = async (): Promise => { */ const resolvedAvatarFaceID = (avatarFaceID: string | undefined) => avatarFaceID?.split("_").length == 1 ? undefined : avatarFaceID; + +/** + * Return only those from amongst {@link people} that have a name defined. + * + * @param people List of all people, named and unnamed. + */ +export const filterNamedPeople = (people: Person[]): NamedPerson[] => { + const namedPeople: NamedPerson[] = []; + for (const person of people) { + const name = person.name; + if (name) { + namedPeople.push({ ...person, name }); + } + } + return namedPeople; +}; diff --git a/web/packages/new/photos/services/search/index.ts b/web/packages/new/photos/services/search/index.ts index e18b91f837..07e3cd326d 100644 --- a/web/packages/new/photos/services/search/index.ts +++ b/web/packages/new/photos/services/search/index.ts @@ -4,12 +4,12 @@ import { ComlinkWorker } from "@/base/worker/comlink-worker"; import { FileType } from "@/media/file-type"; import i18n, { t } from "i18next"; import { clipMatches, isMLEnabled, isMLSupported } from "../ml"; +import type { NamedPerson } from "../ml/people"; import type { LabelledFileType, LabelledSearchDateComponents, LocalizedSearchData, SearchCollectionsAndFiles, - SearchPerson, SearchSuggestion, } from "./types"; import type { SearchWorker } from "./worker"; @@ -60,7 +60,7 @@ export const setSearchCollectionsAndFiles = (cf: SearchCollectionsAndFiles) => /** * Set the (named) people that we should search across. */ -export const setSearchPeople = (people: SearchPerson[]) => +export const setSearchPeople = (people: NamedPerson[]) => void worker().then((w) => w.setPeople(people)); /** diff --git a/web/packages/new/photos/services/search/types.ts b/web/packages/new/photos/services/search/types.ts index 49b2c35839..9c9123366f 100644 --- a/web/packages/new/photos/services/search/types.ts +++ b/web/packages/new/photos/services/search/types.ts @@ -114,16 +114,3 @@ export type City = Location & { /** Name of the city. */ name: string; }; - -export type NamedPerson = Person & { - name: string; -}; - -/** - * What we want is NamedPerson, but I can't get it to TypeScript to accept it in - * our usage contexts. This is a workaround. - */ -export interface SearchPerson { - person: Person; - name: string; -} diff --git a/web/packages/new/photos/services/search/worker.ts b/web/packages/new/photos/services/search/worker.ts index 03e39c1d4c..ca12c27168 100644 --- a/web/packages/new/photos/services/search/worker.ts +++ b/web/packages/new/photos/services/search/worker.ts @@ -10,6 +10,7 @@ import type { Component } from "chrono-node"; import * as chrono from "chrono-node"; import { expose } from "comlink"; import { z } from "zod"; +import type { NamedPerson } from "../ml/people"; import { pullUserEntities, savedLocationTags, @@ -22,7 +23,6 @@ import type { LocalizedSearchData, SearchCollectionsAndFiles, SearchDateComponents, - SearchPerson, SearchSuggestion, } from "./types"; @@ -37,7 +37,7 @@ export class SearchWorker { collections: [], files: [], }; - private people: SearchPerson[] = []; + private people: NamedPerson[] = []; /** * Fetch any state we might need when the actual search happens. @@ -64,7 +64,7 @@ export class SearchWorker { /** * Set the (named) people that we should search across. */ - setPeople(people: SearchPerson[]) { + setPeople(people: NamedPerson[]) { this.people = people; } @@ -122,7 +122,7 @@ const suggestionsForString = ( re: RegExp, searchString: string, { collections, files }: SearchCollectionsAndFiles, - people: SearchPerson[], + people: NamedPerson[], { locale, holidays, labelledFileTypes }: LocalizedSearchData, locationTags: LocationTag[], cities: City[], @@ -198,11 +198,11 @@ const fileCaptionSuggestion = ( const peopleSuggestions = ( re: RegExp, - people: SearchPerson[], + people: NamedPerson[], ): SearchSuggestion[] => people - .filter((sp) => re.test(sp.name)) - .map((sp) => ({ type: "person", person: sp.person, label: sp.name })); + .filter(({ name }) => re.test(name)) + .map((person) => ({ type: "person", person, label: person.name })); const dateSuggestions = ( s: string, From fbc68f114334af851273b0ba387477add1894d71 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 15:13:18 +0530 Subject: [PATCH 014/438] [doc] Mention the location of the exported JSON --- docs/docs/photos/faq/photo-dates.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/docs/photos/faq/photo-dates.md b/docs/docs/photos/faq/photo-dates.md index cf2ea54b47..10710caa80 100644 --- a/docs/docs/photos/faq/photo-dates.md +++ b/docs/docs/photos/faq/photo-dates.md @@ -71,6 +71,23 @@ not modify the original. > functionality within the app itself) for customers who intentionally wish to > modify their originals to reflect the associated metadata JSON. +As an example: suppose you have `flower.png`. When you export your library, you +will end up with: + +``` +flower.png +metadata/flower.png.json +``` + +Ente writes this JSON in the same format as Google Takeout so that if a tool +supports Google Takeout import, it should be able to read the JSON written by +Ente too + +> One small difference is that, to avoid clutter, Ente puts the JSON in the +> `metadata/` subfolder, while Google puts it next to the file.
+> +>
Ente itself will read it from either place. + ### File creation time. The photo's data will be preserved verbatim, however when it is written out to From 3d994a5f078a21201e7222693672cc3dc8cf894d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 15:14:42 +0530 Subject: [PATCH 015/438] yarn pretty --- docs/docs/auth/faq/index.md | 7 +++++-- docs/docs/auth/migration-guides/authy/index.md | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/docs/auth/faq/index.md b/docs/docs/auth/faq/index.md index 1ea023c18c..e913ebd793 100644 --- a/docs/docs/auth/faq/index.md +++ b/docs/docs/auth/faq/index.md @@ -13,7 +13,8 @@ been externally audited. ### How can I delete or edit codes? -You can delete or edit a code long press (or right click on desktop) on that item. +You can delete or edit a code long press (or right click on desktop) on that +item. ### How can I support this project? @@ -51,7 +52,9 @@ end-to-end encrypted. ### What information about my codes is stored on Ente server? -Due to E2EE, the server doesn't know anything about the code. Everything is encrypted, including the tags, type, account, issuer, notes, and pinned or trash status, etc." +Due to E2EE, the server doesn't know anything about the code. Everything is +encrypted, including the tags, type, account, issuer, notes, and pinned or trash +status, etc." ### What does it mean when I receive a message saying my current device is not powerful enough to verify my password? diff --git a/docs/docs/auth/migration-guides/authy/index.md b/docs/docs/auth/migration-guides/authy/index.md index 64d5fb4db4..f1eb51d00a 100644 --- a/docs/docs/auth/migration-guides/authy/index.md +++ b/docs/docs/auth/migration-guides/authy/index.md @@ -212,7 +212,7 @@ If this didn't work, refer to 1. Open Ente Authenticator on your phone 2. Log in to your account (if you haven't already), or press "Use without - backups". + backups". 3. Click the add button in the bottom right of the app. 4. Select "Scan a QR code" and scan the code from the browser. From a13f3020ca59c78149d5139699ed553cd1c73390 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 16:07:39 +0530 Subject: [PATCH 016/438] Tie into the flow --- .../Collections/GalleryBarAndListHeader.tsx | 16 ++------- ...PeopleSelector.tsx => AddPersonDialog.tsx} | 33 +++++++++++++---- .../components/Gallery/PeopleHeader.tsx | 36 +++++++++++-------- .../new/photos/components/SearchBar.tsx | 17 +++++---- 4 files changed, 58 insertions(+), 44 deletions(-) rename web/packages/new/photos/components/{PeopleSelector.tsx => AddPersonDialog.tsx} (79%) diff --git a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx index 53646284a5..ed7ae74945 100644 --- a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx +++ b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx @@ -4,7 +4,6 @@ import { type GalleryBarImplProps, } from "@/new/photos/components/Gallery/BarImpl"; import { PeopleHeader } from "@/new/photos/components/Gallery/PeopleHeader"; -import { PeopleSelector } from "@/new/photos/components/PeopleSelector"; import { areOnlySystemCollections, collectionsSortBy, @@ -108,7 +107,6 @@ export const GalleryBarAndListHeader: React.FC = ({ const [openCollectionShareView, setOpenCollectionShareView] = useState(false); const [openAlbumCastDialog, setOpenAlbumCastDialog] = useState(false); - const [openPeopleSelector, setOpenPeopleSelector] = useState(false); const [collectionsSortBy, setCollectionsSortBy] = useCollectionsSortByLocalState("updation-time-desc"); @@ -174,7 +172,7 @@ export const GalleryBarAndListHeader: React.FC = ({ ) : activePerson ? ( ) : ( <> @@ -189,15 +187,9 @@ export const GalleryBarAndListHeader: React.FC = ({ activeCollectionID, isActiveCollectionDownloadInProgress, activePerson, + people, ]); - // TODO-Cluster - useEffect(() => { - if (process.env.NEXT_PUBLIC_ENTE_WIP_CL) { - setOpenPeopleSelector(true); - } - }, []); - if (shouldBeHidden) { return <>; } @@ -247,10 +239,6 @@ export const GalleryBarAndListHeader: React.FC = ({ onClose={() => setOpenAlbumCastDialog(false)} collection={activeCollection} /> - setOpenPeopleSelector(false)} - /> ); }; diff --git a/web/packages/new/photos/components/PeopleSelector.tsx b/web/packages/new/photos/components/AddPersonDialog.tsx similarity index 79% rename from web/packages/new/photos/components/PeopleSelector.tsx rename to web/packages/new/photos/components/AddPersonDialog.tsx index 52fa8382fe..776ad2d549 100644 --- a/web/packages/new/photos/components/PeopleSelector.tsx +++ b/web/packages/new/photos/components/AddPersonDialog.tsx @@ -9,6 +9,7 @@ import { } from "@mui/material"; import { t } from "i18next"; import React, { useState } from "react"; +import type { FaceCluster } from "../services/ml/cluster"; import type { Person } from "../services/ml/people"; import { SpaceBetweenFlex, type ButtonishProps } from "./mui"; import { @@ -23,24 +24,42 @@ import { LargeTileTextOverlay, } from "./Tiles"; -type PeopleSelectorProps = DialogVisibilityProps; +type AddPersonDialogProps = DialogVisibilityProps & { + /** + * The list of people from show the existing named people. + */ + people: Person[]; + /** + * The cluster to add to the selected person (existing or new). + */ + cluster: FaceCluster; +}; -export const PeopleSelector: React.FC = ({ +/** + * A dialog allowing the user to select one of the existing named persons they + * have, or create a new one, and then associate the provided cluster to it, + * creating or updating a remote "person". + */ +export const AddPersonDialog: React.FC = ({ open, onClose, + people, + cluster, }) => { const isFullScreen = useMediaQuery("(max-width: 490px)"); const [openNameInput, setOpenNameInput] = useState(false); - const people: Person[] = []; + const cgroupPeople: Exclude[] = people.filter( + (p) => p.type != "cluster", + ); const handleAddPerson = () => { setOpenNameInput(true); }; const handleSelectPerson = (id: string) => { - console.log("handleSelectPerson", id); + console.log("handleSelectPerson", id, cluster); }; const handleAddPersonWithName = (name: string) => { @@ -62,7 +81,7 @@ export const PeopleSelector: React.FC = ({ // directly to the add person dialog. // // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (open && !openNameInput && !people.length) { + if (open && !openNameInput && !cgroupPeople.length) { onClose(); setOpenNameInput(true); return <>; @@ -84,7 +103,7 @@ export const PeopleSelector: React.FC = ({
- {people.map((person) => ( + {cgroupPeople.map((person) => ( = ({ onClick={() => onPersonClick(person.id)} > - {person.name} + {person.name ?? ""} ); diff --git a/web/packages/new/photos/components/Gallery/PeopleHeader.tsx b/web/packages/new/photos/components/Gallery/PeopleHeader.tsx index 9c5b5d3c74..472e205b3b 100644 --- a/web/packages/new/photos/components/Gallery/PeopleHeader.tsx +++ b/web/packages/new/photos/components/Gallery/PeopleHeader.tsx @@ -26,6 +26,7 @@ import React, { useState } from "react"; import type { FaceCluster } from "../../services/ml/cluster"; import type { CGroup } from "../../services/user-entity"; import type { NewAppContextPhotos } from "../../types/context"; +import { AddPersonDialog } from "../AddPersonDialog"; import { SpaceBetweenFlex } from "../mui"; import { NameInputDialog } from "../NameInputDialog"; import type { GalleryBarImplProps } from "./BarImpl"; @@ -52,15 +53,19 @@ export interface GalleryPeopleState { people: Person[]; } -type PeopleHeaderProps = Pick & { +type PeopleHeaderProps = Pick< + GalleryBarImplProps, + "people" | "onSelectPerson" +> & { person: Person; appContext: NewAppContextPhotos; }; export const PeopleHeader: React.FC = ({ + people, + onSelectPerson, person, appContext, - onSelectPerson, }) => { return ( @@ -80,7 +85,7 @@ export const PeopleHeader: React.FC = ({ ) : ( )} @@ -182,20 +187,25 @@ const CGroupPersonOptions: React.FC = ({ ); }; -type ClusterPersonOptionsProps = Pick & { +type ClusterPersonOptionsProps = Pick< + PeopleHeaderProps, + "people" | "appContext" +> & { cluster: FaceCluster; }; const ClusterPersonOptions: React.FC = ({ + people, cluster, appContext, }) => { const { startLoading, finishLoading } = appContext; - const [openNameInput, setOpenNameInput] = useState(false); + const [openAddPersonDialog, setOpenAddPersonDialog] = useState(false); - const handleAddPerson = () => setOpenNameInput(true); + const handleAddPerson = () => setOpenAddPersonDialog(true); + // TODO-Cluster const addPersonWithName = async (name: string) => { startLoading(); try { @@ -205,6 +215,8 @@ const ClusterPersonOptions: React.FC = ({ } }; + if (process.env.NEXT_PUBLIC_ENTE_WIP_CL) console.log(addPersonWithName); + return ( <> @@ -228,14 +240,10 @@ const ClusterPersonOptions: React.FC = ({ - setOpenNameInput(false)} - title={pt("Add person") /* TODO-Cluster */} - placeholder={t("enter_name")} - initialValue={""} - submitButtonTitle={t("add")} - onSubmit={addPersonWithName} + setOpenAddPersonDialog(false)} + {...{ people, cluster }} /> ); diff --git a/web/packages/new/photos/components/SearchBar.tsx b/web/packages/new/photos/components/SearchBar.tsx index cb78f649a7..0c733e92fc 100644 --- a/web/packages/new/photos/components/SearchBar.tsx +++ b/web/packages/new/photos/components/SearchBar.tsx @@ -43,6 +43,7 @@ import { import AsyncSelect from "react-select/async"; import { SearchPeopleList } from "./PeopleList"; import { UnstyledButton } from "./UnstyledButton"; +import type { ButtonishProps } from "./mui"; export interface SearchBarProps { /** @@ -414,7 +415,9 @@ const EmptyState: React.FC> = ({ {people && people.length > 0 && ( <> - onSelectPerson(undefined)} /> + onSelectPerson(undefined)} + /> )} @@ -425,22 +428,18 @@ const EmptyState: React.FC> = ({ ); }; -interface PeopleHeaderProps { - onClick: () => void; -} - -const PeopleHeader: React.FC = ({ onClick }) => ( - +const SearchPeopleHeader: React.FC = ({ onClick }) => ( + {t("people")} - + ); -const PeopleHeaderButton = styled(UnstyledButton)( +const SearchPeopleHeaderButton = styled(UnstyledButton)( ({ theme }) => ` /* The color for the chevron */ color: ${theme.colors.stroke.muted}; From 1c306bf7b5b0dfd67f1798c4e3c8f01b5bd37a4d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 16:20:49 +0530 Subject: [PATCH 017/438] Scaffold --- .../Collections/GalleryBarAndListHeader.tsx | 13 +++++ .../photos/components/SingleInputFormV2.tsx | 47 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 web/packages/new/photos/components/SingleInputFormV2.tsx diff --git a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx index ed7ae74945..eefbfd572c 100644 --- a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx +++ b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx @@ -4,6 +4,7 @@ import { type GalleryBarImplProps, } from "@/new/photos/components/Gallery/BarImpl"; import { PeopleHeader } from "@/new/photos/components/Gallery/PeopleHeader"; +import { SingleInputDialogTest } from "@/new/photos/components/SingleInputFormV2"; import { areOnlySystemCollections, collectionsSortBy, @@ -107,6 +108,7 @@ export const GalleryBarAndListHeader: React.FC = ({ const [openCollectionShareView, setOpenCollectionShareView] = useState(false); const [openAlbumCastDialog, setOpenAlbumCastDialog] = useState(false); + const [openPeopleSelector, setOpenPeopleSelector] = useState(false); const [collectionsSortBy, setCollectionsSortBy] = useCollectionsSortByLocalState("updation-time-desc"); @@ -190,6 +192,13 @@ export const GalleryBarAndListHeader: React.FC = ({ people, ]); + // TODO-Cluster + useEffect(() => { + if (process.env.NEXT_PUBLIC_ENTE_WIP_CL) { + setOpenPeopleSelector(true); + } + }, []); + if (shouldBeHidden) { return <>; } @@ -239,6 +248,10 @@ export const GalleryBarAndListHeader: React.FC = ({ onClose={() => setOpenAlbumCastDialog(false)} collection={activeCollection} /> + setOpenPeopleSelector(false)} + /> ); }; diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx new file mode 100644 index 0000000000..2d747f6026 --- /dev/null +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -0,0 +1,47 @@ +import { Dialog, DialogContent, DialogTitle, TextField } from "@mui/material"; +import React from "react"; +import type { DialogVisibilityProps } from "./mui/Dialog"; + +/** + * A TextField and two buttons. + */ +export const SingleInputFormV2: React.FC = () => { + return ( +
+ +
+ ); +}; + +export const SingleInputDialogTest: React.FC = ({ + open, + onClose, +}) => { + // const handleSubmit: SingleInputFormProps["callback"] = async ( + // inputValue, + // setFieldError, + // ) => { + // try { + // await onSubmit(inputValue); + // onClose(); + // } catch (e) { + // log.error(`Error when submitting value ${inputValue}`, e); + // setFieldError(t("UNKNOWN_ERROR")); + // } + // }; + + return ( + + {"Title"} + + + + + ); +}; From 63b3732f822cbc7151d5762d291911b1cfbb6c0f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 17:09:36 +0530 Subject: [PATCH 018/438] Fill in --- .../photos/components/SingleInputFormV2.tsx | 46 +++++++++++++++++-- web/packages/shared/themes/components.ts | 13 ++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 2d747f6026..5e1ed579b3 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -1,4 +1,13 @@ -import { Dialog, DialogContent, DialogTitle, TextField } from "@mui/material"; +import { + Box, + Button, + Dialog, + DialogContent, + DialogTitle, + TextField, +} from "@mui/material"; +import { useFormik } from "formik"; +import { t } from "i18next"; import React from "react"; import type { DialogVisibilityProps } from "./mui/Dialog"; @@ -6,10 +15,37 @@ import type { DialogVisibilityProps } from "./mui/Dialog"; * A TextField and two buttons. */ export const SingleInputFormV2: React.FC = () => { + const formik = useFormik({ + initialValues: { + name: "", + }, + onSubmit: (values) => { + console.log(JSON.stringify(values)); + }, + }); return ( -
- -
+
+ + + + + + ); }; @@ -38,7 +74,7 @@ export const SingleInputDialogTest: React.FC = ({ fullWidth PaperProps={{ sx: { padding: "8px 4px 4px 4px" } }} > - {"Title"} + {"New person"} diff --git a/web/packages/shared/themes/components.ts b/web/packages/shared/themes/components.ts index a401a79bb9..349c3b2586 100644 --- a/web/packages/shared/themes/components.ts +++ b/web/packages/shared/themes/components.ts @@ -132,7 +132,17 @@ export const getComponents = ( MuiInputBase: { styleOverrides: { formControl: { + // Give a symmetric border to the input field, by default the + // border radius is only applied to the top for the "filled" + // variant of input used inside TextFields. borderRadius: "8px", + // TODO: Should we also add overflow hidden so that there is no + // gap between the filled area and the (full width) border. Not + // sure how this might interact with selects. + // overflow: "hidden", + + // Hide the bottom border that always appears for the "filled" + // variant of input used inside TextFields. "::before": { borderBottom: "none !important", }, @@ -150,7 +160,10 @@ export const getComponents = ( }, MuiTextField: { defaultProps: { + // The MUI default variant is "outlined", override it to use the + // "filled" one by default. variant: "filled", + // Reduce the vertical margins that MUI adds to the TextField. margin: "dense", }, styleOverrides: { From 157cefd657af5051ef545c0edbf5e05edba924d9 Mon Sep 17 00:00:00 2001 From: Vishnu Mohandas Date: Mon, 7 Oct 2024 17:15:20 +0530 Subject: [PATCH 019/438] Update intl_en.arb --- mobile/lib/l10n/intl_en.arb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/lib/l10n/intl_en.arb b/mobile/lib/l10n/intl_en.arb index 7f71e724ff..23949d9ab0 100644 --- a/mobile/lib/l10n/intl_en.arb +++ b/mobile/lib/l10n/intl_en.arb @@ -150,7 +150,7 @@ "tryAgain": "Try again", "viewRecoveryKey": "View recovery key", "confirmRecoveryKey": "Confirm recovery key", - "recoveryKeyVerifyReason": "Your recovery key is the only way to recover your photos if you forget your password. You can find your recovery key in Settings > Security.\n\nPlease enter your recovery key here to verify that you have saved it correctly.", + "recoveryKeyVerifyReason": "Your recovery key is the only way to recover your photos if you forget your password. You can find your recovery key in Settings > Account.\n\nPlease enter your recovery key here to verify that you have saved it correctly.", "confirmYourRecoveryKey": "Confirm your recovery key", "addViewer": "Add viewer", "addCollaborator": "Add collaborator", @@ -1344,4 +1344,4 @@ "mostRelevant": "Most relevant", "loadingYourPhotos": "Loading your photos...", "processingImport": "Processing {folderName}..." -} \ No newline at end of file +} From 373d25e2d64c486b5c40de5ecbcd2cbf6df2cf96 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 17:58:03 +0530 Subject: [PATCH 020/438] More --- .../photos/components/SingleInputFormV2.tsx | 46 +++++++++++++++---- web/packages/shared/themes/components.ts | 3 ++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 5e1ed579b3..870a130f6d 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -1,6 +1,6 @@ +import { wait } from "@/utils/promise"; import { Box, - Button, Dialog, DialogContent, DialogTitle, @@ -9,7 +9,9 @@ import { import { useFormik } from "formik"; import { t } from "i18next"; import React from "react"; +import { FocusVisibleButton } from "./FocusVisibleButton"; import type { DialogVisibilityProps } from "./mui/Dialog"; +import log from "@/base/log"; /** * A TextField and two buttons. @@ -19,10 +21,29 @@ export const SingleInputFormV2: React.FC = () => { initialValues: { name: "", }, - onSubmit: (values) => { + onSubmit: async (values, { setFieldError }) => { + const name = values.name; + if (!name) { + setFieldError("name", t("required")); + return; + } + try { + await wait(1000); + if (values.name == "t") throw new Error("test"); + } catch (e) { + log.error(`Failed to submit input ${name}`, e) + setFieldError("name", t("UNKNOWN_ERROR")) + } console.log(JSON.stringify(values)); }, }); + + // Note: [Use space as default TextField helperText] + // + // For MUI text fields that use a conditional helperText, e.g. in case of + // errors, use an space as the default helperText in the other cases to + // avoid a layout shift when the helperText is conditionally shown. + return (
{ autoFocus fullWidth label="Add name" + margin="normal" placeholder="Enter name" - helperText=" " + error={!!formik.errors.name} + helperText={formik.errors.name ?? " "} /> - - - + ); @@ -75,7 +103,7 @@ export const SingleInputDialogTest: React.FC = ({ PaperProps={{ sx: { padding: "8px 4px 4px 4px" } }} > {"New person"} - + diff --git a/web/packages/shared/themes/components.ts b/web/packages/shared/themes/components.ts index 349c3b2586..d117d9043a 100644 --- a/web/packages/shared/themes/components.ts +++ b/web/packages/shared/themes/components.ts @@ -164,6 +164,9 @@ export const getComponents = ( // "filled" one by default. variant: "filled", // Reduce the vertical margins that MUI adds to the TextField. + // + // Note that this causes things to be too tight when the helper text + // is shown, so this is not recommended for new code that we write. margin: "dense", }, styleOverrides: { From c37e5afed112c13b2b6774a8579bbec524cd65d9 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 18:26:03 +0530 Subject: [PATCH 021/438] Up --- .../photos/components/SingleInputFormV2.tsx | 101 ++++++++++++++---- 1 file changed, 79 insertions(+), 22 deletions(-) diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 870a130f6d..9c40c9b38d 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -1,3 +1,4 @@ +import log from "@/base/log"; import { wait } from "@/utils/promise"; import { Box, @@ -5,36 +6,77 @@ import { DialogContent, DialogTitle, TextField, + type TextFieldProps, } from "@mui/material"; import { useFormik } from "formik"; import { t } from "i18next"; import React from "react"; import { FocusVisibleButton } from "./FocusVisibleButton"; import type { DialogVisibilityProps } from "./mui/Dialog"; -import log from "@/base/log"; + +type SingleInputFormProps = Pick< + TextFieldProps, + "label" | "placeholder" | "autoComplete" | "autoFocus" +> & { + /** + * The initial value, if any, to prefill in the input. + */ + initialValue?: string; + /** + * Title for the submit button. + */ + submitButtonTitle: string; + /** + * Cancellation handler. + * + * This function is called when the user activates the cancel button in the + * form. + */ + onCancel: () => void; + /** + * Submission handler. + * + * During submission, the text input and the submit button are disabled, and + * an indeterminate progress indicator is shown. + */ + onSubmit: ((name: string) => void) | ((name: string) => Promise); +}; /** * A TextField and two buttons. + * + * A common requirement is taking a single textual input from the user. This is + * a form suitable for that purpose - it is form containing a single MUI + * {@link TextField}, with two accompanying buttons; one to submit, and one to + * cancel. + * + * Submission is handled as an async function, during which the input is + * disabled and a loading indicator is shown. Errors during submission are shown + * as the helper text associated with the text field. */ -export const SingleInputFormV2: React.FC = () => { +export const SingleInputFormV2: React.FC = ({ + initialValue, + submitButtonTitle, + onCancel, + onSubmit, + ...rest +}) => { const formik = useFormik({ initialValues: { - name: "", + value: initialValue ?? "", }, onSubmit: async (values, { setFieldError }) => { - const name = values.name; - if (!name) { - setFieldError("name", t("required")); + const value = values.value; + if (!value) { + setFieldError("value", t("required")); return; } try { - await wait(1000); - if (values.name == "t") throw new Error("test"); + await onSubmit(value); } catch (e) { - log.error(`Failed to submit input ${name}`, e) - setFieldError("name", t("UNKNOWN_ERROR")) + log.error(`Failed to submit input ${value}`, e); + setFieldError("value", t("UNKNOWN_ERROR")); } - console.log(JSON.stringify(values)); }, }); @@ -47,21 +89,23 @@ export const SingleInputFormV2: React.FC = () => { return (
- + {t("cancel")} { type="submit" disabled={formik.isSubmitting} > - Add person + {submitButtonTitle} @@ -94,6 +138,11 @@ export const SingleInputDialogTest: React.FC = ({ // } // }; + const handleSubmit = async (value: string) => { + await wait(1000); + if (value == "t") throw new Error("test"); + }; + return ( = ({ > {"New person"} - + ); From bfdda59b3977256de4e010b2615985905238127f Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Mon, 7 Oct 2024 18:42:33 +0530 Subject: [PATCH 022/438] Add doc for installation --- docs/docs/.vitepress/sidebar.ts | 1 + docs/docs/photos/faq/installing.md | 90 ++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 docs/docs/photos/faq/installing.md diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index 96bf619e8f..cd2b364feb 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -109,6 +109,7 @@ export const sidebar = [ collapsed: true, items: [ { text: "General", link: "/photos/faq/general" }, + { text: "Installation", link: "/photos/faq/installing" }, { text: "Export", link: "/photos/faq/export", diff --git a/docs/docs/photos/faq/installing.md b/docs/docs/photos/faq/installing.md new file mode 100644 index 0000000000..6e52e8375f --- /dev/null +++ b/docs/docs/photos/faq/installing.md @@ -0,0 +1,90 @@ +--- +title: Installing Ente Photos +description: Steps to install Ente Photos +--- + +# Android + +Our Android apps are distributed over the following channels. + +### PlayStore + +You can install Ente directly from +[PlayStore](https://play.google.com/store/apps/details?id=io.ente.photos). + +### F-Droid + +Reproducible builds for Ente are available on +[F-Droid](https://f-droid.org/packages/io.ente.photos.fdroid/). + + +> [!NOTE] +> +> Releases over F-Droid are generally slower since they run their own build +> servers. You can donate to F-Droid [here](https://f-droid.org/en/donate). + +### GitHub + +Latest releases are built straight from the source and made available over +[GitHub](https://github.com/ente-io/ente/releases?q=tag%253Aphotos-v0). + +These builds will notify you whenever a new release is available and will help +you stay updated. + +### Obtanium + +You can setup [Obtanium](https://github.com/ImranR98/Obtainium) to track our +GitHub releases by following these steps. + +1. Click **Add App** to open a new app config screen +2. Enter `https://github.com/ente-io/ente` in the **App Source URL** field +3. Enable the **Retain release order** from API toggle +4. Scroll down to the **Filter APKs by Regular Expression** field and enter `ente-photos*` +5. Enable the **Attempt to filter APKs by CPU architecture** if possible toggle +6. Select any applicable app category labels you may have setup +7. Enable the **Try inferring app ID from source code** toggle +8. Scroll back to the top and click **Add** to complete the setup + + +
+ +--- + +
+ +# iOS + +You can install Ente on Apple devices from +[AppStore](https://apps.apple.com/app/id1542026904). + +
+ +--- + +
+ +# Desktop + +You can grab the latest version of Ente for Mac, Windows and Linux from +[ente.io/download/desktop](https://ente.io/download/desktop). + +
+ +--- + +
+ +# Web + +Latest versions of our web app are available at [web.ente.io](https://web.ente.io). + +
+ +--- + +
+ +# CLI + +Ente's CLI is distributed directly over +[GitHub](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0). From cb404637cf35720f9300822c2b2e39a1788d8ea3 Mon Sep 17 00:00:00 2001 From: vishnukvmd Date: Mon, 7 Oct 2024 18:48:57 +0530 Subject: [PATCH 023/438] Add installation instructions for Auth --- docs/docs/.vitepress/sidebar.ts | 1 + docs/docs/auth/faq/installing.md | 90 ++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 docs/docs/auth/faq/installing.md diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index cd2b364feb..22d817675f 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -173,6 +173,7 @@ export const sidebar = [ collapsed: true, items: [ { text: "General", link: "/auth/faq/" }, + { text: "Installation", link: "/auth/faq/installing" }, { text: "Enteception", link: "/auth/faq/enteception/", diff --git a/docs/docs/auth/faq/installing.md b/docs/docs/auth/faq/installing.md new file mode 100644 index 0000000000..78756ec04f --- /dev/null +++ b/docs/docs/auth/faq/installing.md @@ -0,0 +1,90 @@ +--- +title: Installing Ente Auth +description: Steps to install Ente Auth +--- + +# Android + +Our Android apps are distributed over the following channels. + +### PlayStore + +You can install Auth directly from +[PlayStore](https://play.google.com/store/apps/details?id=io.ente.auth). + +### F-Droid + +Reproducible builds for Auth are available on +[F-Droid](https://f-droid.org/packages/io.ente.auth/). + + +> [!NOTE] +> +> Releases over F-Droid are generally slower since they run their own build +> servers. You can donate to F-Droid [here](https://f-droid.org/en/donate). + +### GitHub + +Latest releases are built straight from the source and made available over +[GitHub](https://github.com/ente-io/ente/releases?q=tag%3Aauth-v4). + +These builds will notify you whenever a new release is available and will help +you stay updated. + +### Obtanium + +You can setup [Obtanium](https://github.com/ImranR98/Obtainium) to track our +GitHub releases by following these steps. + +1. Click **Add App** to open a new app config screen +2. Enter `https://github.com/ente-io/ente` in the **App Source URL** field +3. Enable the **Retain release order** from API toggle +4. Scroll down to the **Filter APKs by Regular Expression** field and enter `ente-auth*` +5. Enable the **Attempt to filter APKs by CPU architecture** if possible toggle +6. Select any applicable app category labels you may have setup +7. Enable the **Try inferring app ID from source code** toggle +8. Scroll back to the top and click **Add** to complete the setup + + +
+ +--- + +
+ +# iOS + +You can install Ente Auth on Apple devices from +[AppStore](https://apps.apple.com/us/app/ente-auth/id6444121398). + +
+ +--- + +
+ +# Desktop + +You can grab the latest version of Ente Auth for Mac, Windows and Linux from +[GitHub](https://github.com/ente-io/ente/releases?q=tag%3Aauth-v4). + +
+ +--- + +
+ +# Web + +Latest versions of our web app are available at [auth.ente.io](https://auth.ente.io). + +
+ +--- + +
+ +# CLI + +Ente's CLI is distributed directly over +[GitHub](https://github.com/ente-io/ente/releases?q=tag%3Acli-v0). From 2e5c678690d7e0c406da3a67bf1633a013858127 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 18:56:05 +0530 Subject: [PATCH 024/438] Success --- .../photos/components/SingleInputFormV2.tsx | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 9c40c9b38d..44e533eea0 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -1,7 +1,9 @@ import log from "@/base/log"; import { wait } from "@/utils/promise"; +import Done from "@mui/icons-material/Done"; import { Box, + CircularProgress, Dialog, DialogContent, DialogTitle, @@ -10,7 +12,7 @@ import { } from "@mui/material"; import { useFormik } from "formik"; import { t } from "i18next"; -import React from "react"; +import React, { useState } from "react"; import { FocusVisibleButton } from "./FocusVisibleButton"; import type { DialogVisibilityProps } from "./mui/Dialog"; @@ -40,6 +42,14 @@ type SingleInputFormProps = Pick< * an indeterminate progress indicator is shown. */ onSubmit: ((name: string) => void) | ((name: string) => Promise); + /** + * Completion handler. + * + * After a successful completion, the form waits a bit to show a brief + * "success indicator" to the user. Post that, it calls this completion + * handler to allow the caller to proceed to the next step. + */ + onComplete: () => void; }; /** @@ -59,8 +69,11 @@ export const SingleInputFormV2: React.FC = ({ submitButtonTitle, onCancel, onSubmit, + onComplete, ...rest }) => { + const [isDone, setIsDone] = useState(false); + const formik = useFormik({ initialValues: { value: initialValue ?? "", @@ -73,6 +86,9 @@ export const SingleInputFormV2: React.FC = ({ } try { await onSubmit(value); + setIsDone(true); + await wait(1000); + onComplete(); } catch (e) { log.error(`Failed to submit input ${value}`, e); setFieldError("value", t("UNKNOWN_ERROR")); @@ -113,8 +129,21 @@ export const SingleInputFormV2: React.FC = ({ color="accent" type="submit" disabled={formik.isSubmitting} + sx={{ + "&.Mui-disabled": { + backgroundColor: (theme) => + theme.colors.accent.A500, + color: (theme) => theme.colors.text.base, + }, + }} > - {submitButtonTitle} + {isDone ? ( + + ) : formik.isSubmitting ? ( + + ) : ( + submitButtonTitle + )}
@@ -139,7 +168,7 @@ export const SingleInputDialogTest: React.FC = ({ // }; const handleSubmit = async (value: string) => { - await wait(1000); + await wait(3000); if (value == "t") throw new Error("test"); }; @@ -161,6 +190,7 @@ export const SingleInputDialogTest: React.FC = ({ submitButtonTitle="Add person" onCancel={onClose} onSubmit={handleSubmit} + onComplete={onClose} /> From 3a9582325658e8096e47db7688db6b3aff34af08 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 19:18:58 +0530 Subject: [PATCH 025/438] Adding an artificial delay is perhaps not the best? Need to think more --- .../photos/components/SingleInputFormV2.tsx | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 44e533eea0..6972074d31 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -1,6 +1,5 @@ import log from "@/base/log"; import { wait } from "@/utils/promise"; -import Done from "@mui/icons-material/Done"; import { Box, CircularProgress, @@ -12,7 +11,7 @@ import { } from "@mui/material"; import { useFormik } from "formik"; import { t } from "i18next"; -import React, { useState } from "react"; +import React from "react"; import { FocusVisibleButton } from "./FocusVisibleButton"; import type { DialogVisibilityProps } from "./mui/Dialog"; @@ -42,14 +41,6 @@ type SingleInputFormProps = Pick< * an indeterminate progress indicator is shown. */ onSubmit: ((name: string) => void) | ((name: string) => Promise); - /** - * Completion handler. - * - * After a successful completion, the form waits a bit to show a brief - * "success indicator" to the user. Post that, it calls this completion - * handler to allow the caller to proceed to the next step. - */ - onComplete: () => void; }; /** @@ -69,11 +60,8 @@ export const SingleInputFormV2: React.FC = ({ submitButtonTitle, onCancel, onSubmit, - onComplete, ...rest }) => { - const [isDone, setIsDone] = useState(false); - const formik = useFormik({ initialValues: { value: initialValue ?? "", @@ -86,9 +74,6 @@ export const SingleInputFormV2: React.FC = ({ } try { await onSubmit(value); - setIsDone(true); - await wait(1000); - onComplete(); } catch (e) { log.error(`Failed to submit input ${value}`, e); setFieldError("value", t("UNKNOWN_ERROR")); @@ -131,15 +116,12 @@ export const SingleInputFormV2: React.FC = ({ disabled={formik.isSubmitting} sx={{ "&.Mui-disabled": { - backgroundColor: (theme) => - theme.colors.accent.A500, - color: (theme) => theme.colors.text.base, + backgroundColor: "accent.main", + color: "accent.contrastText", }, }} > - {isDone ? ( - - ) : formik.isSubmitting ? ( + {formik.isSubmitting ? ( ) : ( submitButtonTitle @@ -190,7 +172,6 @@ export const SingleInputDialogTest: React.FC = ({ submitButtonTitle="Add person" onCancel={onClose} onSubmit={handleSubmit} - onComplete={onClose} /> From 1c3f560cb005f95e59740e6358a0789c6be21963 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 19:26:40 +0530 Subject: [PATCH 026/438] Prep for main merge --- .../Collections/GalleryBarAndListHeader.tsx | 4 +++- .../components/Gallery/PeopleHeader.tsx | 24 ++++++++++++++++--- .../photos/components/SingleInputFormV2.tsx | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx index eefbfd572c..f384c7a70d 100644 --- a/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx +++ b/web/apps/photos/src/components/Collections/GalleryBarAndListHeader.tsx @@ -189,7 +189,9 @@ export const GalleryBarAndListHeader: React.FC = ({ activeCollectionID, isActiveCollectionDownloadInProgress, activePerson, - people, + // TODO-Cluster + // This causes a loop since it is an array dep + // people, ]); // TODO-Cluster diff --git a/web/packages/new/photos/components/Gallery/PeopleHeader.tsx b/web/packages/new/photos/components/Gallery/PeopleHeader.tsx index 472e205b3b..1e02c8e65b 100644 --- a/web/packages/new/photos/components/Gallery/PeopleHeader.tsx +++ b/web/packages/new/photos/components/Gallery/PeopleHeader.tsx @@ -201,9 +201,19 @@ const ClusterPersonOptions: React.FC = ({ }) => { const { startLoading, finishLoading } = appContext; + const [openNameInput, setOpenNameInput] = useState(false); const [openAddPersonDialog, setOpenAddPersonDialog] = useState(false); - const handleAddPerson = () => setOpenAddPersonDialog(true); + const handleAddPerson = () => { + // TODO-Cluster + if (process.env.NEXT_PUBLIC_ENTE_WIP_CL) { + // WIP path + setOpenAddPersonDialog(true); + } else { + // Existing path + setOpenNameInput(true); + } + }; // TODO-Cluster const addPersonWithName = async (name: string) => { @@ -215,8 +225,6 @@ const ClusterPersonOptions: React.FC = ({ } }; - if (process.env.NEXT_PUBLIC_ENTE_WIP_CL) console.log(addPersonWithName); - return ( <> @@ -240,6 +248,16 @@ const ClusterPersonOptions: React.FC = ({ + setOpenNameInput(false)} + title={pt("Add person") /* TODO-Cluster */} + placeholder={t("enter_name")} + initialValue={""} + submitButtonTitle={t("add")} + onSubmit={addPersonWithName} + /> + setOpenAddPersonDialog(false)} diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 6972074d31..cdc56ea7cf 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -69,7 +69,7 @@ export const SingleInputFormV2: React.FC = ({ onSubmit: async (values, { setFieldError }) => { const value = values.value; if (!value) { - setFieldError("value", t("required")); + setFieldError("value", t("REQUIRED")); return; } try { From 17948e836459ac8cf19753a560fd46b50d99d3a1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 19:39:12 +0530 Subject: [PATCH 027/438] Rename --- web/apps/auth/src/pages/_app.tsx | 2 +- web/apps/photos/src/components/AuthenticateUserModal.tsx | 2 +- .../photos/src/components/Collections/AlbumCastDialog.tsx | 2 +- .../photos/src/components/Collections/CollectionHeader.tsx | 2 +- .../photos/src/components/Collections/CollectionNamer.tsx | 2 +- web/apps/photos/src/components/DeleteAccountModal.tsx | 2 +- web/apps/photos/src/components/MemberSubscriptionManage.tsx | 2 +- .../components/PhotoViewer/FileInfo/FileNameEditDialog.tsx | 2 +- web/apps/photos/src/components/Upload/Uploader.tsx | 2 +- .../photos/src/components/pages/gallery/PlanSelector.tsx | 4 ++-- web/apps/photos/src/pages/_app.tsx | 4 ++-- web/apps/photos/src/pages/deduplicate.tsx | 2 +- web/apps/photos/src/pages/gallery.tsx | 6 +++--- web/apps/photos/src/pages/shared-albums.tsx | 4 ++-- web/apps/photos/src/utils/billing/index.ts | 2 +- web/apps/photos/src/utils/error/ui.ts | 2 +- web/packages/accounts/components/Login.tsx | 6 ++++-- web/packages/accounts/components/SetPasswordForm.tsx | 2 +- web/packages/accounts/components/SignUp.tsx | 5 ++++- web/packages/accounts/components/two-factor/VerifyForm.tsx | 2 +- web/packages/accounts/pages/verify.tsx | 4 +++- web/packages/base/locales/ar-SA/translation.json | 2 +- web/packages/base/locales/bg-BG/translation.json | 2 +- web/packages/base/locales/ca-ES/translation.json | 2 +- web/packages/base/locales/da-DK/translation.json | 2 +- web/packages/base/locales/de-DE/translation.json | 2 +- web/packages/base/locales/el-GR/translation.json | 2 +- web/packages/base/locales/en-US/translation.json | 2 +- web/packages/base/locales/es-ES/translation.json | 2 +- web/packages/base/locales/et-EE/translation.json | 2 +- web/packages/base/locales/fa-IR/translation.json | 2 +- web/packages/base/locales/fi-FI/translation.json | 2 +- web/packages/base/locales/fr-FR/translation.json | 2 +- web/packages/base/locales/gu-IN/translation.json | 2 +- web/packages/base/locales/hi-IN/translation.json | 2 +- web/packages/base/locales/id-ID/translation.json | 2 +- web/packages/base/locales/is-IS/translation.json | 2 +- web/packages/base/locales/it-IT/translation.json | 2 +- web/packages/base/locales/ja-JP/translation.json | 2 +- web/packages/base/locales/km-KH/translation.json | 2 +- web/packages/base/locales/ko-KR/translation.json | 2 +- web/packages/base/locales/lt-LT/translation.json | 2 +- web/packages/base/locales/nl-NL/translation.json | 2 +- web/packages/base/locales/pl-PL/translation.json | 2 +- web/packages/base/locales/pt-BR/translation.json | 2 +- web/packages/base/locales/pt-PT/translation.json | 2 +- web/packages/base/locales/ru-RU/translation.json | 2 +- web/packages/base/locales/sv-SE/translation.json | 2 +- web/packages/base/locales/ta-IN/translation.json | 2 +- web/packages/base/locales/te-IN/translation.json | 2 +- web/packages/base/locales/th-TH/translation.json | 2 +- web/packages/base/locales/ti-ER/translation.json | 2 +- web/packages/base/locales/tr-TR/translation.json | 2 +- web/packages/base/locales/zh-CN/translation.json | 2 +- web/packages/new/photos/components/NameInputDialog.tsx | 2 +- web/packages/new/photos/components/SingleInputFormV2.tsx | 4 ++-- web/packages/shared/components/ErrorComponents.tsx | 2 +- web/packages/shared/components/VerifyMasterPasswordForm.tsx | 4 +++- 58 files changed, 74 insertions(+), 65 deletions(-) diff --git a/web/apps/auth/src/pages/_app.tsx b/web/apps/auth/src/pages/_app.tsx index fed6445bf9..415264fcdb 100644 --- a/web/apps/auth/src/pages/_app.tsx +++ b/web/apps/auth/src/pages/_app.tsx @@ -132,7 +132,7 @@ const App: React.FC = ({ Component, pageProps }) => { setDialogBoxAttributesV2({ title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }); const logout = () => { diff --git a/web/apps/photos/src/components/AuthenticateUserModal.tsx b/web/apps/photos/src/components/AuthenticateUserModal.tsx index 942fa38cd9..71d8871a35 100644 --- a/web/apps/photos/src/components/AuthenticateUserModal.tsx +++ b/web/apps/photos/src/components/AuthenticateUserModal.tsx @@ -31,7 +31,7 @@ export default function AuthenticateUserModal({ setDialogMessage({ title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }); // This is a altered version of the check we do on the password verification diff --git a/web/apps/photos/src/components/Collections/AlbumCastDialog.tsx b/web/apps/photos/src/components/Collections/AlbumCastDialog.tsx index 138c3042b4..f09544a4e5 100644 --- a/web/apps/photos/src/components/Collections/AlbumCastDialog.tsx +++ b/web/apps/photos/src/components/Collections/AlbumCastDialog.tsx @@ -55,7 +55,7 @@ export const AlbumCastDialog: React.FC = ({ if (e instanceof Error && e.message == "tv-not-found") { setFieldError(t("tv_not_found")); } else { - setFieldError(t("UNKNOWN_ERROR")); + setFieldError(t("generic_error_retry")); } } }; diff --git a/web/apps/photos/src/components/Collections/CollectionHeader.tsx b/web/apps/photos/src/components/Collections/CollectionHeader.tsx index 2ea91ca6aa..3a934d371f 100644 --- a/web/apps/photos/src/components/Collections/CollectionHeader.tsx +++ b/web/apps/photos/src/components/Collections/CollectionHeader.tsx @@ -146,7 +146,7 @@ const CollectionOptions: React.FC = ({ log.error("Collection action failed", e); setDialogMessage({ title: t("error"), - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), close: { variant: "critical" }, }); }, diff --git a/web/apps/photos/src/components/Collections/CollectionNamer.tsx b/web/apps/photos/src/components/Collections/CollectionNamer.tsx index 17e090dbc7..05ea5140a8 100644 --- a/web/apps/photos/src/components/Collections/CollectionNamer.tsx +++ b/web/apps/photos/src/components/Collections/CollectionNamer.tsx @@ -34,7 +34,7 @@ export default function CollectionNamer({ attributes, ...props }: Props) { attributes.callback(albumName); props.onHide(); } catch (e) { - setFieldError(t("UNKNOWN_ERROR")); + setFieldError(t("generic_error_retry")); } }; diff --git a/web/apps/photos/src/components/DeleteAccountModal.tsx b/web/apps/photos/src/components/DeleteAccountModal.tsx index b82a7fb6d3..7cd536bbdf 100644 --- a/web/apps/photos/src/components/DeleteAccountModal.tsx +++ b/web/apps/photos/src/components/DeleteAccountModal.tsx @@ -42,7 +42,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { setDialogBoxAttributesV2({ title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }); const initiateDelete = async ( diff --git a/web/apps/photos/src/components/MemberSubscriptionManage.tsx b/web/apps/photos/src/components/MemberSubscriptionManage.tsx index 85901c7a71..86af6223a6 100644 --- a/web/apps/photos/src/components/MemberSubscriptionManage.tsx +++ b/web/apps/photos/src/components/MemberSubscriptionManage.tsx @@ -22,7 +22,7 @@ export function MemberSubscriptionManage({ open, userDetails, onClose }) { setDialogMessage({ title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }); } } diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx index b4d2d16916..d6c11fbf6b 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx @@ -19,7 +19,7 @@ export const FileNameEditDialog = ({ await saveEdits(filename); closeEditMode(); } catch (e) { - setFieldError(t("UNKNOWN_ERROR")); + setFieldError(t("generic_error_retry")); } }; return ( diff --git a/web/apps/photos/src/components/Upload/Uploader.tsx b/web/apps/photos/src/components/Upload/Uploader.tsx index 65e6b6ed62..12bc5a5085 100644 --- a/web/apps/photos/src/components/Upload/Uploader.tsx +++ b/web/apps/photos/src/components/Upload/Uploader.tsx @@ -671,7 +671,7 @@ export default function Uploader({ default: notification = { variant: "critical", - message: t("UNKNOWN_ERROR"), + message: t("generic_error_retry"), onClick: () => null, }; } diff --git a/web/apps/photos/src/components/pages/gallery/PlanSelector.tsx b/web/apps/photos/src/components/pages/gallery/PlanSelector.tsx index fe3c8f8cb6..e4aab43f92 100644 --- a/web/apps/photos/src/components/pages/gallery/PlanSelector.tsx +++ b/web/apps/photos/src/components/pages/gallery/PlanSelector.tsx @@ -161,7 +161,7 @@ function PlanSelectorCard(props: PlanSelectorCardProps) { props.closeModal(); appContext.setDialogMessage({ title: t("OPEN_PLAN_SELECTOR_MODAL_FAILED"), - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), close: { text: t("close"), variant: "secondary" }, proceed: { text: t("REOPEN_PLAN_SELECTOR_MODAL"), @@ -696,7 +696,7 @@ function ManageSubscription({ log.error("Could not redirect to family portal", e); setDialogMessage({ title: t("error"), - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), close: { variant: "critical" }, }); } diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index 295fa8637e..73bfd1a6af 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -283,7 +283,7 @@ export default function App({ Component, pageProps }: AppProps) { setDialogMessage({ title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }), [setDialogMessage], ); @@ -293,7 +293,7 @@ export default function App({ Component, pageProps }: AppProps) { log.error("Error", e), setDialogBoxAttributesV2({ title: t("error"), - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), close: { variant: "critical" }, }) ), diff --git a/web/apps/photos/src/pages/deduplicate.tsx b/web/apps/photos/src/pages/deduplicate.tsx index 52b1620959..b725ae5cf0 100644 --- a/web/apps/photos/src/pages/deduplicate.tsx +++ b/web/apps/photos/src/pages/deduplicate.tsx @@ -149,7 +149,7 @@ export default function Deduplicate() { title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }); } } finally { diff --git a/web/apps/photos/src/pages/gallery.tsx b/web/apps/photos/src/pages/gallery.tsx index 34b004ce9f..e0274298fb 100644 --- a/web/apps/photos/src/pages/gallery.tsx +++ b/web/apps/photos/src/pages/gallery.tsx @@ -965,7 +965,7 @@ export default function Gallery() { title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }); } finally { finishLoading(); @@ -1002,7 +1002,7 @@ export default function Gallery() { title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }); } finally { finishLoading(); @@ -1021,7 +1021,7 @@ export default function Gallery() { title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }); } finally { finishLoading(); diff --git a/web/apps/photos/src/pages/shared-albums.tsx b/web/apps/photos/src/pages/shared-albums.tsx index 15fb04898a..38cd6abefe 100644 --- a/web/apps/photos/src/pages/shared-albums.tsx +++ b/web/apps/photos/src/pages/shared-albums.tsx @@ -404,7 +404,7 @@ export default function PublicCollectionGallery() { ); } catch (e) { log.error("failed to derive key for verifyLinkPassword", e); - setFieldError(`${t("UNKNOWN_ERROR")} ${e.message}`); + setFieldError(`${t("generic_error_retry")} ${e.message}`); return; } const collectionUID = getPublicCollectionUID(token.current); @@ -431,7 +431,7 @@ export default function PublicCollectionGallery() { appContext.finishLoading(); } catch (e) { log.error("failed to verifyLinkPassword", e); - setFieldError(`${t("UNKNOWN_ERROR")} ${e.message}`); + setFieldError(`${t("generic_error_retry")} ${e.message}`); } }; diff --git a/web/apps/photos/src/utils/billing/index.ts b/web/apps/photos/src/utils/billing/index.ts index 9492ed4e7c..a1ff2c7b56 100644 --- a/web/apps/photos/src/utils/billing/index.ts +++ b/web/apps/photos/src/utils/billing/index.ts @@ -239,7 +239,7 @@ export async function updatePaymentMethod( setLoading(false); setDialogMessage({ title: t("error"), - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), close: { variant: "critical" }, }); } diff --git a/web/apps/photos/src/utils/error/ui.ts b/web/apps/photos/src/utils/error/ui.ts index fd7f09c0e8..563d0c2717 100644 --- a/web/apps/photos/src/utils/error/ui.ts +++ b/web/apps/photos/src/utils/error/ui.ts @@ -16,7 +16,7 @@ export const handleSharingErrors = (error) => { errorMessage = t("USER_DOES_NOT_EXIST"); break; default: - errorMessage = `${t("UNKNOWN_ERROR")} ${parsedError.message}`; + errorMessage = `${t("generic_error_retry")} ${parsedError.message}`; } return errorMessage; }; diff --git a/web/packages/accounts/components/Login.tsx b/web/packages/accounts/components/Login.tsx index 6236552cb4..6d6ede9c51 100644 --- a/web/packages/accounts/components/Login.tsx +++ b/web/packages/accounts/components/Login.tsx @@ -39,10 +39,12 @@ export const Login: React.FC = ({ signUp, host }) => { } } catch (e) { if (e instanceof Error) { - setFieldError(`${t("UNKNOWN_ERROR")} (reason:${e.message})`); + setFieldError( + `${t("generic_error_retry")} (reason:${e.message})`, + ); } else { setFieldError( - `${t("UNKNOWN_ERROR")} (reason:${JSON.stringify(e)})`, + `${t("generic_error_retry")} (reason:${JSON.stringify(e)})`, ); } } diff --git a/web/packages/accounts/components/SetPasswordForm.tsx b/web/packages/accounts/components/SetPasswordForm.tsx index 9de5d2c770..c98c0735d3 100644 --- a/web/packages/accounts/components/SetPasswordForm.tsx +++ b/web/packages/accounts/components/SetPasswordForm.tsx @@ -59,7 +59,7 @@ function SetPasswordForm(props: SetPasswordFormProps) { } } catch (e) { const message = e instanceof Error ? e.message : ""; - setFieldError("confirm", `${t("UNKNOWN_ERROR")} ${message}`); + setFieldError("confirm", `${t("generic_error_retry")} ${message}`); } finally { setLoading(false); } diff --git a/web/packages/accounts/components/SignUp.tsx b/web/packages/accounts/components/SignUp.tsx index e69a08497d..0df3710c6d 100644 --- a/web/packages/accounts/components/SignUp.tsx +++ b/web/packages/accounts/components/SignUp.tsx @@ -87,7 +87,10 @@ export const SignUp: React.FC = ({ router, login, host }) => { await sendOtt(email); } catch (e) { const message = e instanceof Error ? e.message : ""; - setFieldError("confirm", `${t("UNKNOWN_ERROR")} ${message}`); + setFieldError( + "confirm", + `${t("generic_error_retry")} ${message}`, + ); throw e; } try { diff --git a/web/packages/accounts/components/two-factor/VerifyForm.tsx b/web/packages/accounts/components/two-factor/VerifyForm.tsx index 14fe89c58c..be1224b0d8 100644 --- a/web/packages/accounts/components/two-factor/VerifyForm.tsx +++ b/web/packages/accounts/components/two-factor/VerifyForm.tsx @@ -48,7 +48,7 @@ export default function VerifyTwoFactor(props: Props) { otpInputRef.current?.focusPrevInput(); } const message = e instanceof Error ? e.message : ""; - setFieldError("otp", `${t("UNKNOWN_ERROR")} ${message}`); + setFieldError("otp", `${t("generic_error_retry")} ${message}`); } setWaiting(false); }; diff --git a/web/packages/accounts/pages/verify.tsx b/web/packages/accounts/pages/verify.tsx index d6b0d574c1..d71fe40700 100644 --- a/web/packages/accounts/pages/verify.tsx +++ b/web/packages/accounts/pages/verify.tsx @@ -155,7 +155,9 @@ const Page: React.FC = ({ appContext }) => { } } else { log.error("OTT verification failed", e); - setFieldError(`${t("UNKNOWN_ERROR")} ${JSON.stringify(e)}`); + setFieldError( + `${t("generic_error_retry")} ${JSON.stringify(e)}`, + ); } } }; diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index 717bdcfb47..2638b252b7 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "رمز التحقق", "RESEND_MAIL": "إعادة إرسال الرمز", "VERIFY": "تحقق", - "UNKNOWN_ERROR": "حدث خطأ ما، يرجى المحاولة مرة أخرى", + "generic_error_retry": "حدث خطأ ما، يرجى المحاولة مرة أخرى", "INVALID_CODE": "رمز التحقق غير صالح", "EXPIRED_CODE": "انتهت صلاحية رمز التحقق الخاص بك", "SENDING": "إرسال...", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index d0cf837ba5..76bee21825 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index 479eabb499..87e98b62e8 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index fdeef4a197..ac6b201675 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index 8ce4c68f00..38e526bf05 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Bestätigungscode", "RESEND_MAIL": "Code erneut senden", "VERIFY": "Überprüfen", - "UNKNOWN_ERROR": "Ein Fehler ist aufgetreten, bitte versuche es erneut", + "generic_error_retry": "Ein Fehler ist aufgetreten, bitte versuche es erneut", "INVALID_CODE": "Falscher Bestätigungscode", "EXPIRED_CODE": "Ihr Bestätigungscode ist abgelaufen", "SENDING": "Wird gesendet...", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index a1df505928..862d280965 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Κωδικός επαλήθευσης", "RESEND_MAIL": "Επαναποστολή κωδικού", "VERIFY": "Επαλήθευση", - "UNKNOWN_ERROR": "Κάτι πήγε στραβά, παρακαλώ προσπαθήστε ξανά", + "generic_error_retry": "Κάτι πήγε στραβά, παρακαλώ προσπαθήστε ξανά", "INVALID_CODE": "Μη έγκυρος κωδικός επαλήθευσης", "EXPIRED_CODE": "Ο κωδικός επαλήθευσης σας έχει λήξει", "SENDING": "Αποστολή...", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index fbf70c191d..1d2821dfc1 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Verification code", "RESEND_MAIL": "Resend code", "VERIFY": "Verify", - "UNKNOWN_ERROR": "Something went wrong, please try again", + "generic_error_retry": "Something went wrong, please try again", "INVALID_CODE": "Invalid verification code", "EXPIRED_CODE": "Your verification code has expired", "SENDING": "Sending...", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index 471de4837f..b5dabbc7f1 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -19,7 +19,7 @@ "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", + "generic_error_retry": "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...", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index 479eabb499..87e98b62e8 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index bd9a8266eb..a7f2d05433 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index 76a1131324..dcc3d0131a 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Vahvistuskoodi", "RESEND_MAIL": "Lähetä koodi uudelleen", "VERIFY": "Vahvista", - "UNKNOWN_ERROR": "Jokin meni vikaan. Yritä uudelleen", + "generic_error_retry": "Jokin meni vikaan. Yritä uudelleen", "INVALID_CODE": "Virheellinen vahvistuskoodi", "EXPIRED_CODE": "Vahvistuskoodisi on vanhentunut", "SENDING": "Lähetetään...", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 78aa680cc8..531c6689d2 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Code de vérification", "RESEND_MAIL": "Renvoyer le code", "VERIFY": "Vérifier", - "UNKNOWN_ERROR": "Quelque chose s'est mal passé, veuillez recommencer", + "generic_error_retry": "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...", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index 479eabb499..87e98b62e8 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index 479eabb499..87e98b62e8 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index 2360c2d5e2..f9950ddc9c 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Kode verifikasi", "RESEND_MAIL": "Kirim ulang kode", "VERIFY": "Verifikasi", - "UNKNOWN_ERROR": "Terjadi kesalahan, silakan coba lagi", + "generic_error_retry": "Terjadi kesalahan, silakan coba lagi", "INVALID_CODE": "Kode verifikasi tidak valid", "EXPIRED_CODE": "Kode verifikasi Anda telah kedaluwarsa", "SENDING": "Mengirim...", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index a48d156cca..c4746ae8f7 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index 88f901de0f..2937c1d4f1 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Codice di verifica", "RESEND_MAIL": "Reinvia codice", "VERIFY": "Verifica", - "UNKNOWN_ERROR": "Qualcosa è andato storto, per favore riprova", + "generic_error_retry": "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...", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index 3d442892cf..fab9edd7be 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index 479eabb499..87e98b62e8 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 3b09d239ca..1dffed20c2 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "인증 코드", "RESEND_MAIL": "코드 재전송하기", "VERIFY": "인증", - "UNKNOWN_ERROR": "문제가 생긴 것 같아요. 다시 시도하세요", + "generic_error_retry": "문제가 생긴 것 같아요. 다시 시도하세요", "INVALID_CODE": "잘못된 인증 코드", "EXPIRED_CODE": "입력한 인증 코드가 만료되었습니다", "SENDING": "전송 중...", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 99b1aa7c27..0f8ce856e5 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Patvirtinimo kodas", "RESEND_MAIL": "Siųsti kodą iš naujo", "VERIFY": "Patvirtinti", - "UNKNOWN_ERROR": "Kažkas nutiko ne taip. Bandykite dar kartą.", + "generic_error_retry": "Kažkas nutiko ne taip. Bandykite dar kartą.", "INVALID_CODE": "Netinkamas patvirtinimo kodas.", "EXPIRED_CODE": "Jūsų patvirtinimo kodo laikas nebegaliojantis.", "SENDING": "Siunčiama...", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index a68ed92f69..1204c94c90 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Verificatiecode", "RESEND_MAIL": "Code opnieuw versturen", "VERIFY": "Verifiëren", - "UNKNOWN_ERROR": "Er is iets fout gegaan, probeer het opnieuw", + "generic_error_retry": "Er is iets fout gegaan, probeer het opnieuw", "INVALID_CODE": "Ongeldige verificatiecode", "EXPIRED_CODE": "Uw verificatiecode is verlopen", "SENDING": "Verzenden...", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 39a7fb98ce..421f781c71 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Kod weryfikacyjny", "RESEND_MAIL": "Wyślij ponownie kod", "VERIFY": "Zweryfikuj", - "UNKNOWN_ERROR": "Coś poszło nie tak, spróbuj ponownie", + "generic_error_retry": "Coś poszło nie tak, spróbuj ponownie", "INVALID_CODE": "Nieprawidłowy kod weryfikacyjny", "EXPIRED_CODE": "Twój kod weryfikacyjny wygasł", "SENDING": "Wysyłanie...", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index 379c93bf08..82628159c3 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Código de verificação", "RESEND_MAIL": "Reenviar código", "VERIFY": "Verificar", - "UNKNOWN_ERROR": "Algo deu errado. Tente novamente", + "generic_error_retry": "Algo deu errado. Tente novamente", "INVALID_CODE": "Código de verificação inválido", "EXPIRED_CODE": "Seu código de verificação expirou", "SENDING": "Enviando...", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 2a3861105b..443662b2d3 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Código de verificação", "RESEND_MAIL": "Reenviar código", "VERIFY": "Verificar", - "UNKNOWN_ERROR": "Ocorreu um erro. Tente novamente", + "generic_error_retry": "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...", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index f5ddae34b4..81292e4f50 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Проверочный код", "RESEND_MAIL": "Отправить код еще раз", "VERIFY": "Подтвердить", - "UNKNOWN_ERROR": "Что-то пошло не так, попробуйте еще раз", + "generic_error_retry": "Что-то пошло не так, попробуйте еще раз", "INVALID_CODE": "Неверный код подтверждения", "EXPIRED_CODE": "Срок действия вашего проверочного кода истек", "SENDING": "Отправка...", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index 46ab220091..58a24fe2e0 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Verifieringskod", "RESEND_MAIL": "Skicka kod igen", "VERIFY": "Bekräfta", - "UNKNOWN_ERROR": "Något gick fel, vänligen försök igen", + "generic_error_retry": "Något gick fel, vänligen försök igen", "INVALID_CODE": "Ogiltig verifieringskod", "EXPIRED_CODE": "Din verifieringskod har löpt ut", "SENDING": "Skickar...", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index 479eabb499..87e98b62e8 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index 479eabb499..87e98b62e8 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index 479eabb499..87e98b62e8 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index 479eabb499..87e98b62e8 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", - "UNKNOWN_ERROR": "", + "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", "SENDING": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index 4ed420e651..935d08f372 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "Doğrulama kodu", "RESEND_MAIL": "Kodu yeniden gönder", "VERIFY": "Doğrula", - "UNKNOWN_ERROR": "Bir şeyler ters gitti, lütfen tekrar dene", + "generic_error_retry": "Bir şeyler ters gitti, lütfen tekrar dene", "INVALID_CODE": "Geçersiz doğrulama kodu", "EXPIRED_CODE": "Doğrulama kodunun süresi doldu", "SENDING": "Gönderiliyor...", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index 4472c897c4..bb8c1b8a73 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -19,7 +19,7 @@ "ENTER_OTT": "验证码", "RESEND_MAIL": "重新发送验证码", "VERIFY": "验证", - "UNKNOWN_ERROR": "出了点问题,请重试", + "generic_error_retry": "出了点问题,请重试", "INVALID_CODE": "验证码无效", "EXPIRED_CODE": "您的验证码已过期", "SENDING": "发送中……", diff --git a/web/packages/new/photos/components/NameInputDialog.tsx b/web/packages/new/photos/components/NameInputDialog.tsx index ae7c499eaf..ac76f7f16b 100644 --- a/web/packages/new/photos/components/NameInputDialog.tsx +++ b/web/packages/new/photos/components/NameInputDialog.tsx @@ -48,7 +48,7 @@ export const NameInputDialog: React.FC = ({ onClose(); } catch (e) { log.error(`Error when submitting value ${inputValue}`, e); - setFieldError(t("UNKNOWN_ERROR")); + setFieldError(t("generic_error_retry")); } }; diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index cdc56ea7cf..77716ca186 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -76,7 +76,7 @@ export const SingleInputFormV2: React.FC = ({ await onSubmit(value); } catch (e) { log.error(`Failed to submit input ${value}`, e); - setFieldError("value", t("UNKNOWN_ERROR")); + setFieldError("value", t("generic_error_retry")); } }, }); @@ -145,7 +145,7 @@ export const SingleInputDialogTest: React.FC = ({ // onClose(); // } catch (e) { // log.error(`Error when submitting value ${inputValue}`, e); - // setFieldError(t("UNKNOWN_ERROR")); + // setFieldError(t("generic_error_retry")); // } // }; diff --git a/web/packages/shared/components/ErrorComponents.tsx b/web/packages/shared/components/ErrorComponents.tsx index 6826cecacf..fb564c9ba1 100644 --- a/web/packages/shared/components/ErrorComponents.tsx +++ b/web/packages/shared/components/ErrorComponents.tsx @@ -7,5 +7,5 @@ import type { DialogBoxAttributesV2 } from "./DialogBoxV2/types"; export const genericErrorAttributes = (): DialogBoxAttributesV2 => ({ title: t("error"), close: { variant: "critical" }, - content: t("UNKNOWN_ERROR"), + content: t("generic_error_retry"), }); diff --git a/web/packages/shared/components/VerifyMasterPasswordForm.tsx b/web/packages/shared/components/VerifyMasterPasswordForm.tsx index 86eff40417..557847d45f 100644 --- a/web/packages/shared/components/VerifyMasterPasswordForm.tsx +++ b/web/packages/shared/components/VerifyMasterPasswordForm.tsx @@ -100,7 +100,9 @@ export default function VerifyMasterPasswordForm({ setFieldError(t("INCORRECT_PASSPHRASE")); break; default: - setFieldError(`${t("UNKNOWN_ERROR")} ${e.message}`); + setFieldError( + `${t("generic_error_retry")} ${e.message}`, + ); } } } From c88fb258be284ce959aaa9f2d22468d4b6f51c1e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 19:40:50 +0530 Subject: [PATCH 028/438] Add variant --- web/packages/base/locales/en-US/translation.json | 1 + web/packages/new/photos/components/SingleInputFormV2.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 1d2821dfc1..7ec4039071 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Verification code", "RESEND_MAIL": "Resend code", "VERIFY": "Verify", + "generic_error": "Something went wrong", "generic_error_retry": "Something went wrong, please try again", "INVALID_CODE": "Invalid verification code", "EXPIRED_CODE": "Your verification code has expired", diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 77716ca186..1315c7b9d5 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -76,7 +76,7 @@ export const SingleInputFormV2: React.FC = ({ await onSubmit(value); } catch (e) { log.error(`Failed to submit input ${value}`, e); - setFieldError("value", t("generic_error_retry")); + setFieldError("value", t("generic_error")); } }, }); From aedbbeb3215251377279f8dbc0a0f8ed6cdce13e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 19:42:01 +0530 Subject: [PATCH 029/438] Rename --- .../CollectionShare/emailShare/AddParticipantForm.tsx | 2 +- web/apps/photos/src/components/DeleteAccountModal.tsx | 2 +- web/packages/accounts/components/SetPasswordForm.tsx | 4 ++-- web/packages/accounts/components/SignUp.tsx | 6 +++--- web/packages/accounts/pages/change-email.tsx | 6 +++--- web/packages/base/locales/ar-SA/translation.json | 2 +- web/packages/base/locales/bg-BG/translation.json | 2 +- web/packages/base/locales/ca-ES/translation.json | 2 +- web/packages/base/locales/da-DK/translation.json | 2 +- web/packages/base/locales/de-DE/translation.json | 2 +- web/packages/base/locales/el-GR/translation.json | 2 +- web/packages/base/locales/en-US/translation.json | 2 +- web/packages/base/locales/es-ES/translation.json | 2 +- web/packages/base/locales/et-EE/translation.json | 2 +- web/packages/base/locales/fa-IR/translation.json | 2 +- web/packages/base/locales/fi-FI/translation.json | 2 +- web/packages/base/locales/fr-FR/translation.json | 2 +- web/packages/base/locales/gu-IN/translation.json | 2 +- web/packages/base/locales/hi-IN/translation.json | 2 +- web/packages/base/locales/id-ID/translation.json | 2 +- web/packages/base/locales/is-IS/translation.json | 2 +- web/packages/base/locales/it-IT/translation.json | 2 +- web/packages/base/locales/ja-JP/translation.json | 2 +- web/packages/base/locales/km-KH/translation.json | 2 +- web/packages/base/locales/ko-KR/translation.json | 2 +- web/packages/base/locales/lt-LT/translation.json | 2 +- web/packages/base/locales/nl-NL/translation.json | 2 +- web/packages/base/locales/pl-PL/translation.json | 2 +- web/packages/base/locales/pt-BR/translation.json | 2 +- web/packages/base/locales/pt-PT/translation.json | 2 +- web/packages/base/locales/ru-RU/translation.json | 2 +- web/packages/base/locales/sv-SE/translation.json | 2 +- web/packages/base/locales/ta-IN/translation.json | 2 +- web/packages/base/locales/te-IN/translation.json | 2 +- web/packages/base/locales/th-TH/translation.json | 2 +- web/packages/base/locales/ti-ER/translation.json | 2 +- web/packages/base/locales/tr-TR/translation.json | 2 +- web/packages/base/locales/zh-CN/translation.json | 2 +- web/packages/new/photos/components/SingleInputFormV2.tsx | 2 +- web/packages/shared/components/SingleInputForm.tsx | 6 +++--- 40 files changed, 47 insertions(+), 47 deletions(-) diff --git a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipantForm.tsx b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipantForm.tsx index 4f987be015..76219b0ef8 100644 --- a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipantForm.tsx +++ b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipantForm.tsx @@ -68,7 +68,7 @@ export default function AddParticipantForm(props: AddParticipantFormProps) { switch (props.fieldType) { case "text": return Yup.object().shape({ - inputValue: Yup.string().required(t("REQUIRED")), + inputValue: Yup.string().required(t("required")), }); case "email": return Yup.object().shape({ diff --git a/web/apps/photos/src/components/DeleteAccountModal.tsx b/web/apps/photos/src/components/DeleteAccountModal.tsx index 7cd536bbdf..b94d313773 100644 --- a/web/apps/photos/src/components/DeleteAccountModal.tsx +++ b/web/apps/photos/src/components/DeleteAccountModal.tsx @@ -156,7 +156,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { feedback: "", }} validationSchema={Yup.object().shape({ - reason: Yup.string().required(t("REQUIRED")), + reason: Yup.string().required(t("required")), })} validateOnChange={false} validateOnBlur={false} diff --git a/web/packages/accounts/components/SetPasswordForm.tsx b/web/packages/accounts/components/SetPasswordForm.tsx index c98c0735d3..8c05d7ce52 100644 --- a/web/packages/accounts/components/SetPasswordForm.tsx +++ b/web/packages/accounts/components/SetPasswordForm.tsx @@ -69,8 +69,8 @@ function SetPasswordForm(props: SetPasswordFormProps) { initialValues={{ passphrase: "", confirm: "" }} validationSchema={Yup.object().shape({ - passphrase: Yup.string().required(t("REQUIRED")), - confirm: Yup.string().required(t("REQUIRED")), + passphrase: Yup.string().required(t("required")), + confirm: Yup.string().required(t("required")), })} validateOnChange={false} validateOnBlur={false} diff --git a/web/packages/accounts/components/SignUp.tsx b/web/packages/accounts/components/SignUp.tsx index 0df3710c6d..c0262df9f5 100644 --- a/web/packages/accounts/components/SignUp.tsx +++ b/web/packages/accounts/components/SignUp.tsx @@ -134,9 +134,9 @@ export const SignUp: React.FC = ({ router, login, host }) => { validationSchema={Yup.object().shape({ email: Yup.string() .email(t("EMAIL_ERROR")) - .required(t("REQUIRED")), - passphrase: Yup.string().required(t("REQUIRED")), - confirm: Yup.string().required(t("REQUIRED")), + .required(t("required")), + passphrase: Yup.string().required(t("required")), + confirm: Yup.string().required(t("required")), })} validateOnChange={false} validateOnBlur={false} diff --git a/web/packages/accounts/pages/change-email.tsx b/web/packages/accounts/pages/change-email.tsx index 1560829bba..b50bad3e5e 100644 --- a/web/packages/accounts/pages/change-email.tsx +++ b/web/packages/accounts/pages/change-email.tsx @@ -103,13 +103,13 @@ const ChangeEmailForm: React.FC = () => { ? Yup.object().shape({ email: Yup.string() .email(t("EMAIL_ERROR")) - .required(t("REQUIRED")), - ott: Yup.string().required(t("REQUIRED")), + .required(t("required")), + ott: Yup.string().required(t("required")), }) : Yup.object().shape({ email: Yup.string() .email(t("EMAIL_ERROR")) - .required(t("REQUIRED")), + .required(t("required")), }) } validateOnChange={false} diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index 2638b252b7..81fa2511ec 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "أضف اسما حتى يتمكن أصدقاؤك من معرفة من يشكرون على هذه الصور الرائعة!", "ENTER_EMAIL": "أدخل عنوان البريد الإلكتروني", "EMAIL_ERROR": "أدخل بريد إلكتروني صالح", - "REQUIRED": "مطلوب", + "required": "مطلوب", "EMAIL_SENT": "تم إرسال رمز التحقق إلى {{email}}", "CHECK_INBOX": "الرجاء التحقق من صندوق الوارد (والرسائل غير المرغوب فيها) لإكمال التحقق", "ENTER_OTT": "رمز التحقق", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index 76bee21825..1ae2420170 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index 87e98b62e8..75cc7205c9 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index ac6b201675..50a8d18ea1 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index 38e526bf05..238a720cc1 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -13,7 +13,7 @@ "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", + "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", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index 862d280965..69bea5214c 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "Προσθέστε ένα όνομα, ώστε οι φίλοι σας να γνωρίζουν ποιον να ευχαριστήσουν για αυτές τις υπέροχες φωτογραφίες!", "ENTER_EMAIL": "Εισάγετε διεύθυνση ηλ. ταχυδρομείου", "EMAIL_ERROR": "Εισάγετε μία έγκυρη διεύθυνση ηλ. ταχυδρομείου", - "REQUIRED": "Υποχρεωτικό", + "required": "Υποχρεωτικό", "EMAIL_SENT": "Ο κωδικός επαλήθευσης στάλθηκε στο {{email}}", "CHECK_INBOX": "Παρακαλώ ελέγξτε τα εισερχόμενά σας (και τα ανεπιθύμητα) για να ολοκληρώσετε την επαλήθευση", "ENTER_OTT": "Κωδικός επαλήθευσης", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 7ec4039071..a22cc14aab 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -13,7 +13,7 @@ "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", + "required": "required", "EMAIL_SENT": "Verification code sent to {{email}}", "CHECK_INBOX": "Please check your inbox (and spam) to complete verification", "ENTER_OTT": "Verification code", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index b5dabbc7f1..18ea4df545 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -13,7 +13,7 @@ "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", + "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", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index 87e98b62e8..75cc7205c9 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index a7f2d05433..f3d8992cab 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index dcc3d0131a..30ea4a3aed 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "Lisää nimi, jotta ystäväsi tietävät, ketä kiittää näistä hienoista kuvista!", "ENTER_EMAIL": "Syötä sähköpostiosoite", "EMAIL_ERROR": "Syötä voimassa oleva sähköpostiosoite", - "REQUIRED": "Pakollinen", + "required": "Pakollinen", "EMAIL_SENT": "Vahvistuskoodi lähetetty osoitteeseen {{email}}", "CHECK_INBOX": "Tarkista saapuneet-kansiosi (ja roskaposti) suorittaaksesi vahvistuksen", "ENTER_OTT": "Vahvistuskoodi", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 531c6689d2..1886da1939 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -13,7 +13,7 @@ "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", + "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", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index 87e98b62e8..75cc7205c9 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index 87e98b62e8..75cc7205c9 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index f9950ddc9c..892dcfa39d 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "Tambahkan nama agar teman Anda tahu kepada siapa harus berterima kasih atas foto-foto hebat ini!", "ENTER_EMAIL": "Masukkan alamat email", "EMAIL_ERROR": "Masukkan email yang sah", - "REQUIRED": "Wajib", + "required": "Wajib", "EMAIL_SENT": "Kode verifikasi dikirim ke {{email}}", "CHECK_INBOX": "Silakan periksa kotak masuk (serta kotak spam) untuk menyelesaikan verifikasi", "ENTER_OTT": "Kode verifikasi", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index c4746ae8f7..bef032fbd0 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index 2937c1d4f1..a6b2fefd59 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -13,7 +13,7 @@ "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", + "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", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index fab9edd7be..681e73fb27 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index 87e98b62e8..75cc7205c9 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 1dffed20c2..4554db2cfb 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "친구들이 이 멋진 사진에 대해 고마워할 수 있도록 이름을 추가하세요!", "ENTER_EMAIL": "이메일 주소를 입력하세요", "EMAIL_ERROR": "올바른 이메일을 입력하세요", - "REQUIRED": "필수", + "required": "필수", "EMAIL_SENT": "{{email}} 로 인증 코드가 전송되었습니다", "CHECK_INBOX": "인증을 완료하기 위해 당신의 메일 수신함(그리고 스팸 수신함)을 확인하세요.", "ENTER_OTT": "인증 코드", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 0f8ce856e5..064666baaa 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "Pridėkite vardą, kad draugai žinotų, kam padėkoti už šias puikias nuotraukas!", "ENTER_EMAIL": "Įveskite el. pašto adresą", "EMAIL_ERROR": "Įveskite tinkamą el. paštą.", - "REQUIRED": "Privaloma", + "required": "Privaloma", "EMAIL_SENT": "Patvirtinimo kodas išsiųstas į {{email}}", "CHECK_INBOX": "Patikrinkite savo gautieją (ir šlamštą), kad užbaigtumėte patvirtinimą", "ENTER_OTT": "Patvirtinimo kodas", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 1204c94c90..48b55f4c35 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -13,7 +13,7 @@ "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", + "required": "Vereist", "EMAIL_SENT": "Verificatiecode verzonden naar {{email}}", "CHECK_INBOX": "Controleer je inbox (en spam) om verificatie te voltooien", "ENTER_OTT": "Verificatiecode", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 421f781c71..659f0afbea 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "Dodaj imię, aby Twoi znajomi wiedzieli, kto będzie mógł podziękować za te wspaniałe zdjęcia!", "ENTER_EMAIL": "Wprowadź adres e-mail", "EMAIL_ERROR": "Wprowadź prawidłowy adres e-mail", - "REQUIRED": "Wymagane", + "required": "Wymagane", "EMAIL_SENT": "Kod weryfikacyjny wysłany do {{email}}", "CHECK_INBOX": "Sprawdź swoją skrzynkę odbiorczą (i spam), aby zakończyć weryfikację", "ENTER_OTT": "Kod weryfikacyjny", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index 82628159c3..0234fe4840 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "Adicione um nome para seus amigos saberem 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": "Requerido", + "required": "Requerido", "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", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 443662b2d3..3a2fad80e1 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -13,7 +13,7 @@ "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", + "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", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 81292e4f50..d0dd09b734 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "Добавьте имя, чтобы ваши друзья знали, кого благодарить за эти замечательные фотографии!", "ENTER_EMAIL": "Введите адрес электронной почты", "EMAIL_ERROR": "Введите действительный адрес электронной почты", - "REQUIRED": "Требуется", + "required": "Требуется", "EMAIL_SENT": "Проверочный код отправлен на {{email}}", "CHECK_INBOX": "Пожалуйста, проверьте свой почтовый ящик (и спам) для завершения проверки", "ENTER_OTT": "Проверочный код", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index 58a24fe2e0..e6621e3a8d 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "Lägg till ett namn så att dina vänner vet vem de ska tacka för dessa fantastiska bilder!", "ENTER_EMAIL": "Ange e-postadress", "EMAIL_ERROR": "Ange en giltig e-postadress", - "REQUIRED": "Obligatoriskt", + "required": "Obligatoriskt", "EMAIL_SENT": "Verifikationskoden skickad till {{email}}", "CHECK_INBOX": "Kontrollera din inkorg (och skräppost) för att slutföra verifieringen", "ENTER_OTT": "Verifieringskod", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index 87e98b62e8..75cc7205c9 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index 87e98b62e8..75cc7205c9 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index 87e98b62e8..75cc7205c9 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index 87e98b62e8..75cc7205c9 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "", "ENTER_EMAIL": "", "EMAIL_ERROR": "", - "REQUIRED": "", + "required": "", "EMAIL_SENT": "", "CHECK_INBOX": "", "ENTER_OTT": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index 935d08f372..d60754ddf2 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "Arkadaşlarının bu harika fotoğraflar için kime teşekkür etmeleri gerektiğini bilmeleri için bir isim ekle!", "ENTER_EMAIL": "E-posta adresini girin", "EMAIL_ERROR": "Geçerli bir e-posta gir", - "REQUIRED": "Gerekli", + "required": "Gerekli", "EMAIL_SENT": "Doğrulama kodu {{email}} adresine gönderildi", "CHECK_INBOX": "Lütfen doğrulama işlemini tamamlamak için gelen kutusunu (veya spam) kontrol et", "ENTER_OTT": "Doğrulama kodu", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index bb8c1b8a73..431017e2ac 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -13,7 +13,7 @@ "PUBLIC_UPLOADER_NAME_MESSAGE": "请添加一个名字,以便您的朋友知晓该感谢谁拍摄了这些精美的照片!", "ENTER_EMAIL": "请输入电子邮件地址", "EMAIL_ERROR": "请输入有效的电子邮件", - "REQUIRED": "必需的", + "required": "必需的", "EMAIL_SENT": "验证码已发送至 {{email}}", "CHECK_INBOX": "请检查您的收件箱 (或者是在您的“垃圾邮件”列表内) 以完成验证", "ENTER_OTT": "验证码", diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 1315c7b9d5..1caa137090 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -69,7 +69,7 @@ export const SingleInputFormV2: React.FC = ({ onSubmit: async (values, { setFieldError }) => { const value = values.value; if (!value) { - setFieldError("value", t("REQUIRED")); + setFieldError("value", t("required")); return; } try { diff --git a/web/packages/shared/components/SingleInputForm.tsx b/web/packages/shared/components/SingleInputForm.tsx index ad77e70c43..82e42edd22 100644 --- a/web/packages/shared/components/SingleInputForm.tsx +++ b/web/packages/shared/components/SingleInputForm.tsx @@ -87,17 +87,17 @@ export default function SingleInputForm(props: SingleInputFormProps) { switch (props.fieldType) { case "text": return Yup.object().shape({ - inputValue: Yup.string().required(t("REQUIRED")), + inputValue: Yup.string().required(t("required")), }); case "password": return Yup.object().shape({ - inputValue: Yup.string().required(t("REQUIRED")), + inputValue: Yup.string().required(t("required")), }); case "email": return Yup.object().shape({ inputValue: Yup.string() .email(t("EMAIL_ERROR")) - .required(t("REQUIRED")), + .required(t("required")), }); } }, [props.fieldType]); From c0e9642d9733590da6e1881070ad1b18f8991ccb Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 19:49:44 +0530 Subject: [PATCH 030/438] lf --- web/packages/new/photos/components/AddPersonDialog.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/packages/new/photos/components/AddPersonDialog.tsx b/web/packages/new/photos/components/AddPersonDialog.tsx index 776ad2d549..9b62d5b35d 100644 --- a/web/packages/new/photos/components/AddPersonDialog.tsx +++ b/web/packages/new/photos/components/AddPersonDialog.tsx @@ -79,8 +79,6 @@ export const AddPersonDialog: React.FC = ({ // If we're opened without any existing people that can be selected, jump // directly to the add person dialog. - // - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (open && !openNameInput && !cgroupPeople.length) { onClose(); setOpenNameInput(true); From 127172938b41c08fbe88f09766bf20b1c865e873 Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Mon, 7 Oct 2024 14:29:04 +0000 Subject: [PATCH 031/438] New Crowdin translations by GitHub Action --- web/packages/base/locales/ar-SA/translation.json | 1 + web/packages/base/locales/bg-BG/translation.json | 1 + web/packages/base/locales/ca-ES/translation.json | 1 + web/packages/base/locales/da-DK/translation.json | 1 + web/packages/base/locales/de-DE/translation.json | 1 + web/packages/base/locales/el-GR/translation.json | 1 + web/packages/base/locales/es-ES/translation.json | 1 + web/packages/base/locales/et-EE/translation.json | 1 + web/packages/base/locales/fa-IR/translation.json | 1 + web/packages/base/locales/fi-FI/translation.json | 1 + web/packages/base/locales/fr-FR/translation.json | 1 + web/packages/base/locales/gu-IN/translation.json | 1 + web/packages/base/locales/hi-IN/translation.json | 1 + web/packages/base/locales/id-ID/translation.json | 1 + web/packages/base/locales/is-IS/translation.json | 1 + web/packages/base/locales/it-IT/translation.json | 1 + web/packages/base/locales/ja-JP/translation.json | 1 + web/packages/base/locales/km-KH/translation.json | 1 + web/packages/base/locales/ko-KR/translation.json | 1 + web/packages/base/locales/lt-LT/translation.json | 7 ++++--- web/packages/base/locales/nl-NL/translation.json | 1 + web/packages/base/locales/pl-PL/translation.json | 1 + web/packages/base/locales/pt-BR/translation.json | 1 + web/packages/base/locales/pt-PT/translation.json | 1 + web/packages/base/locales/ru-RU/translation.json | 1 + web/packages/base/locales/sv-SE/translation.json | 1 + web/packages/base/locales/ta-IN/translation.json | 1 + web/packages/base/locales/te-IN/translation.json | 1 + web/packages/base/locales/th-TH/translation.json | 1 + web/packages/base/locales/ti-ER/translation.json | 1 + web/packages/base/locales/tr-TR/translation.json | 1 + web/packages/base/locales/zh-CN/translation.json | 1 + 32 files changed, 35 insertions(+), 3 deletions(-) diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index 81fa2511ec..efe9ea4fa3 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "رمز التحقق", "RESEND_MAIL": "إعادة إرسال الرمز", "VERIFY": "تحقق", + "generic_error": "", "generic_error_retry": "حدث خطأ ما، يرجى المحاولة مرة أخرى", "INVALID_CODE": "رمز التحقق غير صالح", "EXPIRED_CODE": "انتهت صلاحية رمز التحقق الخاص بك", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index 1ae2420170..1ff6c05b37 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index 75cc7205c9..d616ad7a13 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index 50a8d18ea1..3b51681102 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index 238a720cc1..ffac89dd18 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Bestätigungscode", "RESEND_MAIL": "Code erneut senden", "VERIFY": "Überprüfen", + "generic_error": "", "generic_error_retry": "Ein Fehler ist aufgetreten, bitte versuche es erneut", "INVALID_CODE": "Falscher Bestätigungscode", "EXPIRED_CODE": "Ihr Bestätigungscode ist abgelaufen", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index 69bea5214c..fc1b801d2b 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Κωδικός επαλήθευσης", "RESEND_MAIL": "Επαναποστολή κωδικού", "VERIFY": "Επαλήθευση", + "generic_error": "", "generic_error_retry": "Κάτι πήγε στραβά, παρακαλώ προσπαθήστε ξανά", "INVALID_CODE": "Μη έγκυρος κωδικός επαλήθευσης", "EXPIRED_CODE": "Ο κωδικός επαλήθευσης σας έχει λήξει", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index 18ea4df545..d10504c4bc 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Código de verificación", "RESEND_MAIL": "Reenviar el código", "VERIFY": "Verificar", + "generic_error": "", "generic_error_retry": "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", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index 75cc7205c9..d616ad7a13 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index f3d8992cab..6730717a03 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index 30ea4a3aed..b38b1c7c4d 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Vahvistuskoodi", "RESEND_MAIL": "Lähetä koodi uudelleen", "VERIFY": "Vahvista", + "generic_error": "", "generic_error_retry": "Jokin meni vikaan. Yritä uudelleen", "INVALID_CODE": "Virheellinen vahvistuskoodi", "EXPIRED_CODE": "Vahvistuskoodisi on vanhentunut", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 1886da1939..7722d1f542 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Code de vérification", "RESEND_MAIL": "Renvoyer le code", "VERIFY": "Vérifier", + "generic_error": "", "generic_error_retry": "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é", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index 75cc7205c9..d616ad7a13 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index 75cc7205c9..d616ad7a13 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index 892dcfa39d..22d591bf54 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Kode verifikasi", "RESEND_MAIL": "Kirim ulang kode", "VERIFY": "Verifikasi", + "generic_error": "", "generic_error_retry": "Terjadi kesalahan, silakan coba lagi", "INVALID_CODE": "Kode verifikasi tidak valid", "EXPIRED_CODE": "Kode verifikasi Anda telah kedaluwarsa", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index bef032fbd0..162f7f78be 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index a6b2fefd59..804182de17 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Codice di verifica", "RESEND_MAIL": "Reinvia codice", "VERIFY": "Verifica", + "generic_error": "", "generic_error_retry": "Qualcosa è andato storto, per favore riprova", "INVALID_CODE": "Codice di verifica non valido", "EXPIRED_CODE": "Il tuo codice di verifica è scaduto", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index 681e73fb27..5a4fcb1952 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index 75cc7205c9..d616ad7a13 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 4554db2cfb..3ac7e493ff 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "인증 코드", "RESEND_MAIL": "코드 재전송하기", "VERIFY": "인증", + "generic_error": "", "generic_error_retry": "문제가 생긴 것 같아요. 다시 시도하세요", "INVALID_CODE": "잘못된 인증 코드", "EXPIRED_CODE": "입력한 인증 코드가 만료되었습니다", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 064666baaa..d27c252b2a 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Patvirtinimo kodas", "RESEND_MAIL": "Siųsti kodą iš naujo", "VERIFY": "Patvirtinti", + "generic_error": "", "generic_error_retry": "Kažkas nutiko ne taip. Bandykite dar kartą.", "INVALID_CODE": "Netinkamas patvirtinimo kodas.", "EXPIRED_CODE": "Jūsų patvirtinimo kodo laikas nebegaliojantis.", @@ -207,9 +208,9 @@ "SHARING_BAD_REQUEST_ERROR": "Neleidžiama bendrinti albumo.", "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Bendrinimas išjungtas nemokamoms paskyroms.", "CREATE_ALBUM_FAILED": "Nepavyko sukurti albumo. Bandykite dar kartą.", - "search": "", - "search_results": "", - "no_results": "", + "search": "ieškoti", + "search_results": "Paieškos rezultatai", + "no_results": "Rezultatų nerasta.", "search_hint": "", "album": "", "date": "", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 48b55f4c35..8a9b10729f 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Verificatiecode", "RESEND_MAIL": "Code opnieuw versturen", "VERIFY": "Verifiëren", + "generic_error": "", "generic_error_retry": "Er is iets fout gegaan, probeer het opnieuw", "INVALID_CODE": "Ongeldige verificatiecode", "EXPIRED_CODE": "Uw verificatiecode is verlopen", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 659f0afbea..d6aaac4d52 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Kod weryfikacyjny", "RESEND_MAIL": "Wyślij ponownie kod", "VERIFY": "Zweryfikuj", + "generic_error": "Coś poszło nie tak", "generic_error_retry": "Coś poszło nie tak, spróbuj ponownie", "INVALID_CODE": "Nieprawidłowy kod weryfikacyjny", "EXPIRED_CODE": "Twój kod weryfikacyjny wygasł", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index 0234fe4840..00c36e7c9a 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Código de verificação", "RESEND_MAIL": "Reenviar código", "VERIFY": "Verificar", + "generic_error": "", "generic_error_retry": "Algo deu errado. Tente novamente", "INVALID_CODE": "Código de verificação inválido", "EXPIRED_CODE": "Seu código de verificação expirou", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 3a2fad80e1..cb879e456e 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Código de verificação", "RESEND_MAIL": "Reenviar código", "VERIFY": "Verificar", + "generic_error": "", "generic_error_retry": "Ocorreu um erro. Tente novamente", "INVALID_CODE": "Código de verificação inválido", "EXPIRED_CODE": "O seu código de verificação expirou", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index d0dd09b734..02ef622112 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Проверочный код", "RESEND_MAIL": "Отправить код еще раз", "VERIFY": "Подтвердить", + "generic_error": "", "generic_error_retry": "Что-то пошло не так, попробуйте еще раз", "INVALID_CODE": "Неверный код подтверждения", "EXPIRED_CODE": "Срок действия вашего проверочного кода истек", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index e6621e3a8d..e92993ae05 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Verifieringskod", "RESEND_MAIL": "Skicka kod igen", "VERIFY": "Bekräfta", + "generic_error": "", "generic_error_retry": "Något gick fel, vänligen försök igen", "INVALID_CODE": "Ogiltig verifieringskod", "EXPIRED_CODE": "Din verifieringskod har löpt ut", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index 75cc7205c9..d616ad7a13 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index 75cc7205c9..d616ad7a13 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index 75cc7205c9..d616ad7a13 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index 75cc7205c9..d616ad7a13 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "", "RESEND_MAIL": "", "VERIFY": "", + "generic_error": "", "generic_error_retry": "", "INVALID_CODE": "", "EXPIRED_CODE": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index d60754ddf2..87084bc50f 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "Doğrulama kodu", "RESEND_MAIL": "Kodu yeniden gönder", "VERIFY": "Doğrula", + "generic_error": "", "generic_error_retry": "Bir şeyler ters gitti, lütfen tekrar dene", "INVALID_CODE": "Geçersiz doğrulama kodu", "EXPIRED_CODE": "Doğrulama kodunun süresi doldu", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index 431017e2ac..7f5acc654b 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -19,6 +19,7 @@ "ENTER_OTT": "验证码", "RESEND_MAIL": "重新发送验证码", "VERIFY": "验证", + "generic_error": "", "generic_error_retry": "出了点问题,请重试", "INVALID_CODE": "验证码无效", "EXPIRED_CODE": "您的验证码已过期", From 02f42a0bb781340536bcce2612379432664997b2 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 20:40:25 +0530 Subject: [PATCH 032/438] [web] Reset scroll state on mode/person change Fixes https://github.com/ente-io/ente/issues/3603 --- web/apps/photos/src/components/PhotoFrame.tsx | 12 +++++++-- .../photos/src/components/PhotoList/index.tsx | 27 +++++++++++++++---- web/apps/photos/src/pages/gallery.tsx | 1 + 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/web/apps/photos/src/components/PhotoFrame.tsx b/web/apps/photos/src/components/PhotoFrame.tsx index ccf0908a2b..9d81684af6 100644 --- a/web/apps/photos/src/components/PhotoFrame.tsx +++ b/web/apps/photos/src/components/PhotoFrame.tsx @@ -44,12 +44,18 @@ const Container = styled("div")` const PHOTOSWIPE_HASH_SUFFIX = "&opened"; -interface Props { +export interface PhotoFrameProps { page: | PHOTOS_PAGES.GALLERY | PHOTOS_PAGES.DEDUPLICATE | PHOTOS_PAGES.SHARED_ALBUMS; mode?: GalleryBarMode; + /** + * This is an experimental prop, to see if we can merge the separate + * "isInSearchMode" state kept by the gallery to be instead provided as a + * another mode in which the gallery operates. + */ + modePlus?: GalleryBarMode | "search"; files: EnteFile[]; duplicates?: Duplicate[]; syncWithRemote: () => Promise; @@ -79,6 +85,7 @@ const PhotoFrame = ({ page, duplicates, mode, + modePlus, files, syncWithRemote, favItemIds, @@ -97,7 +104,7 @@ const PhotoFrame = ({ setFilesDownloadProgressAttributesCreator, selectable, onSelectPerson, -}: Props) => { +}: PhotoFrameProps) => { const [open, setOpen] = useState(false); const [currentIndex, setCurrentIndex] = useState(0); const [fetching, setFetching] = useState<{ [k: number]: boolean }>({}); @@ -556,6 +563,7 @@ const PhotoFrame = ({ height={height} getThumbnail={getThumbnail} mode={mode} + modePlus={modePlus} displayFiles={displayFiles} activeCollectionID={activeCollectionID} activePersonID={activePersonID} diff --git a/web/apps/photos/src/components/PhotoList/index.tsx b/web/apps/photos/src/components/PhotoList/index.tsx index e9777a8166..f40aa7887d 100644 --- a/web/apps/photos/src/components/PhotoList/index.tsx +++ b/web/apps/photos/src/components/PhotoList/index.tsx @@ -1,4 +1,3 @@ -import type { GalleryBarMode } from "@/new/photos/components/Gallery/BarImpl"; import { EnteFile } from "@/new/photos/types/file"; import { formattedByteSize } from "@/new/photos/utils/units"; import { FlexWrapper } from "@ente/shared/components/Container"; @@ -17,12 +16,14 @@ import { import { handleSelectCreator } from "utils/photoFrame"; import { PublicCollectionGalleryContext } from "utils/publicCollectionGallery"; +import { assertionFailed } from "@/base/assert"; import { GAP_BTW_TILES, IMAGE_CONTAINER_MAX_HEIGHT, IMAGE_CONTAINER_MAX_WIDTH, MIN_COLUMNS, } from "@/new/photos/components/PhotoList"; +import type { PhotoFrameProps } from "components/PhotoFrame"; export const DATE_CONTAINER_HEIGHT = 48; export const SIZE_AND_COUNT_CONTAINER_HEIGHT = 72; @@ -187,10 +188,9 @@ const NothingContainer = styled(ListItemContainer)` justify-content: center; `; -interface Props { +type Props = Pick & { height: number; width: number; - mode?: GalleryBarMode; displayFiles: EnteFile[]; showAppDownloadBanner: boolean; getThumbnail: ( @@ -200,7 +200,7 @@ interface Props { ) => JSX.Element; activeCollectionID: number; activePersonID?: string; -} +}; interface ItemData { timeStampList: TimeStampListItem[]; @@ -257,6 +257,7 @@ export function PhotoList({ height, width, mode, + modePlus, displayFiles, showAppDownloadBanner, getThumbnail, @@ -890,9 +891,25 @@ export function PhotoList({ renderListItem, ); + // The old, mode unaware, behaviour. + let key = `${activeCollectionID}`; + if (modePlus) { + // If the new experimental modePlus prop is provided, use it to derive a + // mode specific key. + if (modePlus == "search") { + key = "search"; + } else if (modePlus == "people") { + if (!activePersonID) { + assertionFailed(); + } else { + key = activePersonID; + } + } + } + return ( Date: Mon, 7 Oct 2024 21:05:28 +0530 Subject: [PATCH 033/438] Loading button --- .../photos/components/SingleInputFormV2.tsx | 52 ++++++++++++++----- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 1caa137090..5e7117e03a 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -7,6 +7,7 @@ import { DialogContent, DialogTitle, TextField, + type ButtonProps, type TextFieldProps, } from "@mui/material"; import { useFormik } from "formik"; @@ -109,29 +110,51 @@ export const SingleInputFormV2: React.FC = ({ > {t("cancel")} - - {formik.isSubmitting ? ( - - ) : ( - submitButtonTitle - )} - + {submitButtonTitle} + ); }; +/** + * A button that shows a indeterminate progress indicator if the {@link loading} + * prop is set. + * + * TODO: This duplicates the existing SubmitButton and EnteButton. Merge these + * three gradually (didn't want to break existing layouts, so will do it + * piecewise). + */ +export const LoadingButton: React.FC = ({ + loading, + disabled, + color, + sx, + children, + ...rest +}) => ( + + {loading ? : children} + +); + export const SingleInputDialogTest: React.FC = ({ open, onClose, @@ -169,6 +192,7 @@ export const SingleInputDialogTest: React.FC = ({ autoFocus label="Add name" placeholder="Enter name" + initialValue="tt" submitButtonTitle="Add person" onCancel={onClose} onSubmit={handleSubmit} From ca08b3eb5fb7aadfae7e04dbb43add31655bd81f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 21:11:17 +0530 Subject: [PATCH 034/438] Move --- .../photos/components/SingleInputFormV2.tsx | 35 +----------------- .../photos/components/mui/LoadingButton.tsx | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 34 deletions(-) create mode 100644 web/packages/new/photos/components/mui/LoadingButton.tsx diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index 5e7117e03a..bf72f19e13 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -2,12 +2,10 @@ import log from "@/base/log"; import { wait } from "@/utils/promise"; import { Box, - CircularProgress, Dialog, DialogContent, DialogTitle, TextField, - type ButtonProps, type TextFieldProps, } from "@mui/material"; import { useFormik } from "formik"; @@ -15,6 +13,7 @@ import { t } from "i18next"; import React from "react"; import { FocusVisibleButton } from "./FocusVisibleButton"; import type { DialogVisibilityProps } from "./mui/Dialog"; +import { LoadingButton } from "./mui/LoadingButton"; type SingleInputFormProps = Pick< TextFieldProps, @@ -123,38 +122,6 @@ export const SingleInputFormV2: React.FC = ({ ); }; -/** - * A button that shows a indeterminate progress indicator if the {@link loading} - * prop is set. - * - * TODO: This duplicates the existing SubmitButton and EnteButton. Merge these - * three gradually (didn't want to break existing layouts, so will do it - * piecewise). - */ -export const LoadingButton: React.FC = ({ - loading, - disabled, - color, - sx, - children, - ...rest -}) => ( - - {loading ? : children} - -); - export const SingleInputDialogTest: React.FC = ({ open, onClose, diff --git a/web/packages/new/photos/components/mui/LoadingButton.tsx b/web/packages/new/photos/components/mui/LoadingButton.tsx new file mode 100644 index 0000000000..a129c32cac --- /dev/null +++ b/web/packages/new/photos/components/mui/LoadingButton.tsx @@ -0,0 +1,37 @@ +import { CircularProgress, type ButtonProps } from "@mui/material"; +import React from "react"; +import { FocusVisibleButton } from "../FocusVisibleButton"; + +/** + * A button that shows a indeterminate progress indicator if the {@link loading} + * prop is set. + * + * The button is also disabled when in the loading state. + * + * TODO: This duplicates the existing SubmitButton and EnteButton. Merge these + * three gradually (didn't want to break existing layouts, so will do it + * piecewise). + */ +export const LoadingButton: React.FC = ({ + loading, + disabled, + color, + sx, + children, + ...rest +}) => ( + + {loading ? : children} + +); From 28529560f09b240b70dadc575208ddd9e1756919 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Oct 2024 21:12:09 +0530 Subject: [PATCH 035/438] Move --- web/apps/photos/src/components/Upload/UploadTypeSelector.tsx | 2 +- .../new/photos/components/CollectionMappingChoiceDialog.tsx | 2 +- web/packages/new/photos/components/DevSettings.tsx | 2 +- web/packages/new/photos/components/SingleInputFormV2.tsx | 2 +- web/packages/new/photos/components/WhatsNew.tsx | 2 +- .../new/photos/components/{ => mui}/FocusVisibleButton.tsx | 0 web/packages/new/photos/components/mui/LoadingButton.tsx | 2 +- web/packages/shared/components/DialogBox/index.tsx | 2 +- 8 files changed, 7 insertions(+), 7 deletions(-) rename web/packages/new/photos/components/{ => mui}/FocusVisibleButton.tsx (100%) diff --git a/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx b/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx index 0a055764ec..b989983f20 100644 --- a/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx +++ b/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx @@ -1,7 +1,7 @@ import { useIsTouchscreen } from "@/base/hooks"; -import { FocusVisibleButton } from "@/new/photos/components/FocusVisibleButton"; import { SpaceBetweenFlex } from "@/new/photos/components/mui"; import { DialogCloseIconButton } from "@/new/photos/components/mui/Dialog"; +import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; import DialogTitleWithCloseButton, { dialogCloseHandler, } from "@ente/shared/components/DialogBox/TitleWithCloseButton"; diff --git a/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx b/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx index 5c16915dc9..89ea187304 100644 --- a/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx +++ b/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx @@ -1,5 +1,4 @@ import type { CollectionMapping } from "@/base/types/ipc"; -import { FocusVisibleButton } from "@/new/photos/components/FocusVisibleButton"; import FolderIcon from "@mui/icons-material/Folder"; import FolderCopyIcon from "@mui/icons-material/FolderCopy"; import { @@ -16,6 +15,7 @@ import { DialogCloseIconButton, type DialogVisibilityProps, } from "./mui/Dialog"; +import { FocusVisibleButton } from "./mui/FocusVisibleButton"; type CollectionMappingChoiceModalProps = DialogVisibilityProps & { didSelect: (mapping: CollectionMapping) => void; diff --git a/web/packages/new/photos/components/DevSettings.tsx b/web/packages/new/photos/components/DevSettings.tsx index 2235a1b60d..89e0273fb7 100644 --- a/web/packages/new/photos/components/DevSettings.tsx +++ b/web/packages/new/photos/components/DevSettings.tsx @@ -18,7 +18,7 @@ import { useFormik } from "formik"; import { t } from "i18next"; import React, { useEffect, useState } from "react"; import { z } from "zod"; -import { FocusVisibleButton } from "./FocusVisibleButton"; +import { FocusVisibleButton } from "./mui/FocusVisibleButton"; import { SlideUpTransition } from "./mui/SlideUpTransition"; interface DevSettingsProps { diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index bf72f19e13..a13287683e 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -11,8 +11,8 @@ import { import { useFormik } from "formik"; import { t } from "i18next"; import React from "react"; -import { FocusVisibleButton } from "./FocusVisibleButton"; import type { DialogVisibilityProps } from "./mui/Dialog"; +import { FocusVisibleButton } from "./mui/FocusVisibleButton"; import { LoadingButton } from "./mui/LoadingButton"; type SingleInputFormProps = Pick< diff --git a/web/packages/new/photos/components/WhatsNew.tsx b/web/packages/new/photos/components/WhatsNew.tsx index 997afc30e8..1a8555d244 100644 --- a/web/packages/new/photos/components/WhatsNew.tsx +++ b/web/packages/new/photos/components/WhatsNew.tsx @@ -14,7 +14,7 @@ import { } from "@mui/material"; import React, { useEffect } from "react"; import { didShowWhatsNew } from "../services/changelog"; -import { FocusVisibleButton } from "./FocusVisibleButton"; +import { FocusVisibleButton } from "./mui/FocusVisibleButton"; import { SlideUpTransition } from "./mui/SlideUpTransition"; interface WhatsNewProps { diff --git a/web/packages/new/photos/components/FocusVisibleButton.tsx b/web/packages/new/photos/components/mui/FocusVisibleButton.tsx similarity index 100% rename from web/packages/new/photos/components/FocusVisibleButton.tsx rename to web/packages/new/photos/components/mui/FocusVisibleButton.tsx diff --git a/web/packages/new/photos/components/mui/LoadingButton.tsx b/web/packages/new/photos/components/mui/LoadingButton.tsx index a129c32cac..af328e3457 100644 --- a/web/packages/new/photos/components/mui/LoadingButton.tsx +++ b/web/packages/new/photos/components/mui/LoadingButton.tsx @@ -1,6 +1,6 @@ import { CircularProgress, type ButtonProps } from "@mui/material"; import React from "react"; -import { FocusVisibleButton } from "../FocusVisibleButton"; +import { FocusVisibleButton } from "./FocusVisibleButton"; /** * A button that shows a indeterminate progress indicator if the {@link loading} diff --git a/web/packages/shared/components/DialogBox/index.tsx b/web/packages/shared/components/DialogBox/index.tsx index 74fca76b77..b0f4b67928 100644 --- a/web/packages/shared/components/DialogBox/index.tsx +++ b/web/packages/shared/components/DialogBox/index.tsx @@ -1,4 +1,4 @@ -import { FocusVisibleButton } from "@/new/photos/components/FocusVisibleButton"; +import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; import { Breakpoint, DialogActions, From d781d2c2fc209fad557b597f0bded2a9ed9aca89 Mon Sep 17 00:00:00 2001 From: Apalepex Date: Mon, 7 Oct 2024 19:12:20 +0200 Subject: [PATCH 036/438] web client : add fav icon to picture thumbnails --- web/apps/photos/src/components/PhotoFrame.tsx | 1 + .../src/components/pages/gallery/PreviewCard.tsx | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/web/apps/photos/src/components/PhotoFrame.tsx b/web/apps/photos/src/components/PhotoFrame.tsx index 9d81684af6..e9c91345c8 100644 --- a/web/apps/photos/src/components/PhotoFrame.tsx +++ b/web/apps/photos/src/components/PhotoFrame.tsx @@ -323,6 +323,7 @@ const PhotoFrame = ({ } activeCollectionID={activeCollectionID} showPlaceholder={isScrolling} + isFav={favItemIds.has(item.id)} /> ); diff --git a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx index 114351788f..241d15d0db 100644 --- a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx +++ b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx @@ -23,6 +23,7 @@ import React, { useContext, useEffect, useRef, useState } from "react"; import { TRASH_SECTION } from "utils/collection"; import { shouldShowAvatar } from "utils/file"; import Avatar from "./Avatar"; +import Favorite from "@mui/icons-material/FavoriteRounded"; interface IProps { file: EnteFile; @@ -38,6 +39,7 @@ interface IProps { isInsSelectRange: boolean; activeCollectionID: number; showPlaceholder: boolean; + isFav: boolean; } const Check = styled("input")<{ $active: boolean }>` @@ -121,6 +123,14 @@ export const AvatarOverlay = styled(Overlay)` padding-top: 5px; `; +export const FavOverlay = styled(Overlay)` + display: flex; + justify-content: flex-start; + align-items: flex-end; + padding-left: 5px; + padding-bottom: 5px; +`; + export const InSelectRangeOverLay = styled("div")<{ $active: boolean }>` opacity: ${(props) => (!props.$active ? 0 : 1)}; left: 0; @@ -351,6 +361,11 @@ export default function PreviewCard(props: IProps) { )} + {props.isFav && ( + + + + )} Date: Tue, 8 Oct 2024 08:42:30 +0530 Subject: [PATCH 037/438] Fix lints --- web/apps/photos/src/components/pages/gallery/PreviewCard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx index 241d15d0db..d4486afadc 100644 --- a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx +++ b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx @@ -14,6 +14,7 @@ import { Overlay } from "@ente/shared/components/Container"; import { CustomError } from "@ente/shared/error"; import useLongPress from "@ente/shared/hooks/useLongPress"; import AlbumOutlined from "@mui/icons-material/AlbumOutlined"; +import Favorite from "@mui/icons-material/FavoriteRounded"; import PlayCircleOutlineOutlinedIcon from "@mui/icons-material/PlayCircleOutlineOutlined"; import { Tooltip, styled } from "@mui/material"; import i18n from "i18next"; @@ -23,7 +24,6 @@ import React, { useContext, useEffect, useRef, useState } from "react"; import { TRASH_SECTION } from "utils/collection"; import { shouldShowAvatar } from "utils/file"; import Avatar from "./Avatar"; -import Favorite from "@mui/icons-material/FavoriteRounded"; interface IProps { file: EnteFile; @@ -363,7 +363,7 @@ export default function PreviewCard(props: IProps) { )} {props.isFav && ( - + )} From fb2fd7d9860f0e6232f2e9fff80a34b21e090e32 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 08:52:25 +0530 Subject: [PATCH 038/438] Switch --- .../photos/src/components/DeleteAccountModal.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/web/apps/photos/src/components/DeleteAccountModal.tsx b/web/apps/photos/src/components/DeleteAccountModal.tsx index b94d313773..4dae3be7a1 100644 --- a/web/apps/photos/src/components/DeleteAccountModal.tsx +++ b/web/apps/photos/src/components/DeleteAccountModal.tsx @@ -1,8 +1,9 @@ import log from "@/base/log"; +import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; +import { LoadingButton } from "@/new/photos/components/mui/LoadingButton"; import { initiateEmail } from "@/new/photos/utils/web"; import DialogBoxV2 from "@ente/shared/components/DialogBoxV2"; -import EnteButton from "@ente/shared/components/EnteButton"; -import { Button, Link, Stack, useMediaQuery } from "@mui/material"; +import { Link, Stack, useMediaQuery } from "@mui/material"; import { Formik, type FormikHelpers } from "formik"; import { t } from "i18next"; import { AppContext } from "pages/_app"; @@ -200,7 +201,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { )} /> - { loading={loading} > {t("delete_account_confirm")} - - + From a0f0333f5fb8e44721975602803751713d92979f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 08:57:51 +0530 Subject: [PATCH 039/438] Switch --- .../shared/components/DialogBoxV2/index.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/web/packages/shared/components/DialogBoxV2/index.tsx b/web/packages/shared/components/DialogBoxV2/index.tsx index 3f9bdd2d7d..698f9c8609 100644 --- a/web/packages/shared/components/DialogBoxV2/index.tsx +++ b/web/packages/shared/components/DialogBoxV2/index.tsx @@ -1,8 +1,8 @@ +import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; +import { LoadingButton } from "@/new/photos/components/mui/LoadingButton"; import { dialogCloseHandler } from "@ente/shared/components/DialogBox/TitleWithCloseButton"; -import EnteButton from "@ente/shared/components/EnteButton"; import { Box, - Button, Dialog, Stack, Typography, @@ -91,7 +91,7 @@ export default function DialogBoxV2({ flex={1} > {attributes.proceed && ( - {attributes.proceed.text} - + )} {attributes.close && ( - + )} {attributes.buttons && attributes.buttons.map((b) => ( - + ))} )} From f0ea95e141d1398cfdb991d25517b873f1d5e7f5 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 09:01:55 +0530 Subject: [PATCH 040/438] Extract --- .../PhotoViewer/ImageEditorOverlay/index.tsx | 58 ++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx index 5674984e8e..531c86469a 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx @@ -493,6 +493,30 @@ const ImageEditorOverlay = (props: IProps) => { log.error("Error saving copy to ente", e); } }; + + const applyCrop = () => { + if (!cropBoxRef.current || !canvasRef.current) return; + + const { x1, x2, y1, y2 } = getCropRegionArgs( + cropBoxRef.current, + canvasRef.current, + ); + setCanvasLoading(true); + setTransformationPerformed(true); + cropRegionOfCanvas(canvasRef.current, x1, y1, x2, y2); + cropRegionOfCanvas( + originalSizeCanvasRef.current, + x1 / previewCanvasScale, + y1 / previewCanvasScale, + x2 / previewCanvasScale, + y2 / previewCanvasScale, + ); + resetCropBox(); + setCanvasLoading(false); + + setCurrentTab("transform"); + }; + return ( <> { } - onClick={() => { - if ( - !cropBoxRef.current || - !canvasRef.current - ) - return; - - const { x1, x2, y1, y2 } = - getCropRegionArgs( - cropBoxRef.current, - canvasRef.current, - ); - setCanvasLoading(true); - setTransformationPerformed(true); - cropRegionOfCanvas( - canvasRef.current, - x1, - y1, - x2, - y2, - ); - cropRegionOfCanvas( - originalSizeCanvasRef.current, - x1 / previewCanvasScale, - y1 / previewCanvasScale, - x2 / previewCanvasScale, - y2 / previewCanvasScale, - ); - resetCropBox(); - setCanvasLoading(false); - - setCurrentTab("transform"); - }} + onClick={applyCrop} > {t("APPLY_CROP")} From 51be8e0622fbbc9d8c8883781a85a49faf465bb1 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 09:02:44 +0530 Subject: [PATCH 041/438] It is not using the loader --- .../src/components/PhotoViewer/ImageEditorOverlay/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx index 531c86469a..92c1dd8f01 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx @@ -26,6 +26,7 @@ import MenuIcon from "@mui/icons-material/Menu"; import { Backdrop, Box, + Button, CircularProgress, IconButton, Tab, @@ -604,13 +605,13 @@ const ImageEditorOverlay = (props: IProps) => { {currentTab === "crop" && ( - } onClick={applyCrop} > {t("APPLY_CROP")} - + )} From d8f98b4daa10a427a6a4b2422a9c5b4699ad3ca3 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 09:10:31 +0530 Subject: [PATCH 042/438] Give more space for the crop button --- .../src/components/PhotoViewer/ImageEditorOverlay/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx index 92c1dd8f01..0b868f4b9a 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx @@ -565,7 +565,7 @@ const ImageEditorOverlay = (props: IProps) => { }} > Date: Tue, 8 Oct 2024 09:20:30 +0530 Subject: [PATCH 043/438] Slightly less obtrusive Need proper designs --- web/apps/photos/src/components/pages/gallery/PreviewCard.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx index d4486afadc..f339daaf5c 100644 --- a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx +++ b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx @@ -129,6 +129,7 @@ export const FavOverlay = styled(Overlay)` align-items: flex-end; padding-left: 5px; padding-bottom: 5px; + opacity: 0.9; `; export const InSelectRangeOverLay = styled("div")<{ $active: boolean }>` From 3be7abf3814cda65e5314ea3d7f557aac90eb6a9 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 10:25:45 +0530 Subject: [PATCH 044/438] Use new one --- .../accounts/src/pages/passkeys/verify.tsx | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/web/apps/accounts/src/pages/passkeys/verify.tsx b/web/apps/accounts/src/pages/passkeys/verify.tsx index 2ee11e1d29..b3b98b1df9 100644 --- a/web/apps/accounts/src/pages/passkeys/verify.tsx +++ b/web/apps/accounts/src/pages/passkeys/verify.tsx @@ -1,9 +1,9 @@ import log from "@/base/log"; import type { TwoFactorAuthorizationResponse } from "@/base/types/credentials"; +import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; import { ensure } from "@/utils/ensure"; import { nullToUndefined } from "@/utils/transform"; import { VerticallyCentered } from "@ente/shared/components/Container"; -import EnteButton from "@ente/shared/components/EnteButton"; import EnteSpinner from "@ente/shared/components/EnteSpinner"; import InfoIcon from "@mui/icons-material/Info"; import KeyIcon from "@mui/icons-material/Key"; @@ -366,15 +366,9 @@ const Verify: React.FC = ({ onVerify }) => { {t("passkey_verify_description")} - + {t("VERIFY")} - + ); @@ -416,25 +410,22 @@ const RetriableFailed: React.FC = ({ : t("passkey_login_generic_error")} - {t("try_again")} - + {onRecover && ( - {t("RECOVER_TWO_FACTOR")} - + )} @@ -504,15 +495,14 @@ const RedirectingApp: React.FC = ({ onRetry }) => { {t("redirect_close_instructions")} - {t("redirect_again")} - + ); From d7fd432f6e5f5f5fc3a662d6977409cab875ed4d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 10:32:43 +0530 Subject: [PATCH 045/438] Move to base (since it in used in accounts) --- web/apps/accounts/src/pages/passkeys/verify.tsx | 2 +- web/apps/photos/src/components/DeleteAccountModal.tsx | 4 ++-- .../src/components/PhotoViewer/ImageEditorOverlay/index.tsx | 1 - web/apps/photos/src/components/Upload/UploadTypeSelector.tsx | 2 +- .../photos => base}/components/mui/FocusVisibleButton.tsx | 0 .../{new/photos => base}/components/mui/LoadingButton.tsx | 2 +- .../new/photos/components/CollectionMappingChoiceDialog.tsx | 2 +- web/packages/new/photos/components/DevSettings.tsx | 2 +- web/packages/new/photos/components/SingleInputFormV2.tsx | 4 ++-- web/packages/new/photos/components/WhatsNew.tsx | 2 +- web/packages/shared/components/DialogBox/index.tsx | 2 +- web/packages/shared/components/DialogBoxV2/index.tsx | 4 ++-- 12 files changed, 13 insertions(+), 14 deletions(-) rename web/packages/{new/photos => base}/components/mui/FocusVisibleButton.tsx (100%) rename web/packages/{new/photos => base}/components/mui/LoadingButton.tsx (92%) diff --git a/web/apps/accounts/src/pages/passkeys/verify.tsx b/web/apps/accounts/src/pages/passkeys/verify.tsx index b3b98b1df9..a533d0f645 100644 --- a/web/apps/accounts/src/pages/passkeys/verify.tsx +++ b/web/apps/accounts/src/pages/passkeys/verify.tsx @@ -1,6 +1,6 @@ +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import log from "@/base/log"; import type { TwoFactorAuthorizationResponse } from "@/base/types/credentials"; -import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; import { ensure } from "@/utils/ensure"; import { nullToUndefined } from "@/utils/transform"; import { VerticallyCentered } from "@ente/shared/components/Container"; diff --git a/web/apps/photos/src/components/DeleteAccountModal.tsx b/web/apps/photos/src/components/DeleteAccountModal.tsx index 4dae3be7a1..bea1098000 100644 --- a/web/apps/photos/src/components/DeleteAccountModal.tsx +++ b/web/apps/photos/src/components/DeleteAccountModal.tsx @@ -1,6 +1,6 @@ +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; +import { LoadingButton } from "@/base/components/mui/LoadingButton"; import log from "@/base/log"; -import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; -import { LoadingButton } from "@/new/photos/components/mui/LoadingButton"; import { initiateEmail } from "@/new/photos/utils/web"; import DialogBoxV2 from "@ente/shared/components/DialogBoxV2"; import { Link, Stack, useMediaQuery } from "@mui/material"; diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx index 0b868f4b9a..a1c62ac86c 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx @@ -13,7 +13,6 @@ import { CenteredFlex, HorizontalFlex, } from "@ente/shared/components/Container"; -import EnteButton from "@ente/shared/components/EnteButton"; import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem"; import { downloadUsingAnchor } from "@ente/shared/utils"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; diff --git a/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx b/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx index b989983f20..e353ee69f7 100644 --- a/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx +++ b/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx @@ -1,7 +1,7 @@ +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { useIsTouchscreen } from "@/base/hooks"; import { SpaceBetweenFlex } from "@/new/photos/components/mui"; import { DialogCloseIconButton } from "@/new/photos/components/mui/Dialog"; -import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; import DialogTitleWithCloseButton, { dialogCloseHandler, } from "@ente/shared/components/DialogBox/TitleWithCloseButton"; diff --git a/web/packages/new/photos/components/mui/FocusVisibleButton.tsx b/web/packages/base/components/mui/FocusVisibleButton.tsx similarity index 100% rename from web/packages/new/photos/components/mui/FocusVisibleButton.tsx rename to web/packages/base/components/mui/FocusVisibleButton.tsx diff --git a/web/packages/new/photos/components/mui/LoadingButton.tsx b/web/packages/base/components/mui/LoadingButton.tsx similarity index 92% rename from web/packages/new/photos/components/mui/LoadingButton.tsx rename to web/packages/base/components/mui/LoadingButton.tsx index af328e3457..319c8538bf 100644 --- a/web/packages/new/photos/components/mui/LoadingButton.tsx +++ b/web/packages/base/components/mui/LoadingButton.tsx @@ -1,6 +1,6 @@ +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { CircularProgress, type ButtonProps } from "@mui/material"; import React from "react"; -import { FocusVisibleButton } from "./FocusVisibleButton"; /** * A button that shows a indeterminate progress indicator if the {@link loading} diff --git a/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx b/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx index 89ea187304..c862fed2ee 100644 --- a/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx +++ b/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx @@ -1,3 +1,4 @@ +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import type { CollectionMapping } from "@/base/types/ipc"; import FolderIcon from "@mui/icons-material/Folder"; import FolderCopyIcon from "@mui/icons-material/FolderCopy"; @@ -15,7 +16,6 @@ import { DialogCloseIconButton, type DialogVisibilityProps, } from "./mui/Dialog"; -import { FocusVisibleButton } from "./mui/FocusVisibleButton"; type CollectionMappingChoiceModalProps = DialogVisibilityProps & { didSelect: (mapping: CollectionMapping) => void; diff --git a/web/packages/new/photos/components/DevSettings.tsx b/web/packages/new/photos/components/DevSettings.tsx index 89e0273fb7..1c17b9cabc 100644 --- a/web/packages/new/photos/components/DevSettings.tsx +++ b/web/packages/new/photos/components/DevSettings.tsx @@ -1,3 +1,4 @@ +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { useIsMobileWidth } from "@/base/hooks"; import { ensureOk } from "@/base/http"; import { getKVS, removeKV, setKV } from "@/base/kv"; @@ -18,7 +19,6 @@ import { useFormik } from "formik"; import { t } from "i18next"; import React, { useEffect, useState } from "react"; import { z } from "zod"; -import { FocusVisibleButton } from "./mui/FocusVisibleButton"; import { SlideUpTransition } from "./mui/SlideUpTransition"; interface DevSettingsProps { diff --git a/web/packages/new/photos/components/SingleInputFormV2.tsx b/web/packages/new/photos/components/SingleInputFormV2.tsx index a13287683e..eeb4b47fe8 100644 --- a/web/packages/new/photos/components/SingleInputFormV2.tsx +++ b/web/packages/new/photos/components/SingleInputFormV2.tsx @@ -1,3 +1,5 @@ +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; +import { LoadingButton } from "@/base/components/mui/LoadingButton"; import log from "@/base/log"; import { wait } from "@/utils/promise"; import { @@ -12,8 +14,6 @@ import { useFormik } from "formik"; import { t } from "i18next"; import React from "react"; import type { DialogVisibilityProps } from "./mui/Dialog"; -import { FocusVisibleButton } from "./mui/FocusVisibleButton"; -import { LoadingButton } from "./mui/LoadingButton"; type SingleInputFormProps = Pick< TextFieldProps, diff --git a/web/packages/new/photos/components/WhatsNew.tsx b/web/packages/new/photos/components/WhatsNew.tsx index 1a8555d244..30bcb1f81a 100644 --- a/web/packages/new/photos/components/WhatsNew.tsx +++ b/web/packages/new/photos/components/WhatsNew.tsx @@ -1,3 +1,4 @@ +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { ensureElectron } from "@/base/electron"; import { useIsMobileWidth } from "@/base/hooks"; import { ut } from "@/base/i18n"; @@ -14,7 +15,6 @@ import { } from "@mui/material"; import React, { useEffect } from "react"; import { didShowWhatsNew } from "../services/changelog"; -import { FocusVisibleButton } from "./mui/FocusVisibleButton"; import { SlideUpTransition } from "./mui/SlideUpTransition"; interface WhatsNewProps { diff --git a/web/packages/shared/components/DialogBox/index.tsx b/web/packages/shared/components/DialogBox/index.tsx index b0f4b67928..5393e1112d 100644 --- a/web/packages/shared/components/DialogBox/index.tsx +++ b/web/packages/shared/components/DialogBox/index.tsx @@ -1,4 +1,4 @@ -import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { Breakpoint, DialogActions, diff --git a/web/packages/shared/components/DialogBoxV2/index.tsx b/web/packages/shared/components/DialogBoxV2/index.tsx index 698f9c8609..ecec83f7a5 100644 --- a/web/packages/shared/components/DialogBoxV2/index.tsx +++ b/web/packages/shared/components/DialogBoxV2/index.tsx @@ -1,5 +1,5 @@ -import { FocusVisibleButton } from "@/new/photos/components/mui/FocusVisibleButton"; -import { LoadingButton } from "@/new/photos/components/mui/LoadingButton"; +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; +import { LoadingButton } from "@/base/components/mui/LoadingButton"; import { dialogCloseHandler } from "@ente/shared/components/DialogBox/TitleWithCloseButton"; import { Box, From 851ca1afe28242c86792754931b540f236bdd7d9 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 10:43:11 +0530 Subject: [PATCH 046/438] Fin --- .../base/components/mui/LoadingButton.tsx | 5 +-- web/packages/shared/components/EnteButton.tsx | 43 ------------------- .../shared/components/LoginComponents.tsx | 12 +++--- 3 files changed, 7 insertions(+), 53 deletions(-) delete mode 100644 web/packages/shared/components/EnteButton.tsx diff --git a/web/packages/base/components/mui/LoadingButton.tsx b/web/packages/base/components/mui/LoadingButton.tsx index 319c8538bf..dddb2b1b07 100644 --- a/web/packages/base/components/mui/LoadingButton.tsx +++ b/web/packages/base/components/mui/LoadingButton.tsx @@ -8,9 +8,8 @@ import React from "react"; * * The button is also disabled when in the loading state. * - * TODO: This duplicates the existing SubmitButton and EnteButton. Merge these - * three gradually (didn't want to break existing layouts, so will do it - * piecewise). + * TODO: This duplicates the existing SubmitButton. Merge these two gradually + * (didn't want to break existing layouts, so will do it piecewise). */ export const LoadingButton: React.FC = ({ loading, diff --git a/web/packages/shared/components/EnteButton.tsx b/web/packages/shared/components/EnteButton.tsx deleted file mode 100644 index 365d648a3c..0000000000 --- a/web/packages/shared/components/EnteButton.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { ensure } from "@/utils/ensure"; -import Done from "@mui/icons-material/Done"; -import { Button, CircularProgress, type ButtonProps } from "@mui/material"; - -interface Iprops extends ButtonProps { - loading?: boolean; - success?: boolean; -} - -export default function EnteButton({ - children, - loading, - success, - disabled, - sx, - ...props -}: Iprops) { - return ( - - ); -} diff --git a/web/packages/shared/components/LoginComponents.tsx b/web/packages/shared/components/LoginComponents.tsx index cbe828cba7..528399fc98 100644 --- a/web/packages/shared/components/LoginComponents.tsx +++ b/web/packages/shared/components/LoginComponents.tsx @@ -3,9 +3,9 @@ import { passkeySessionExpiredErrorMessage, saveCredentialsAndNavigateTo, } from "@/accounts/services/passkey"; +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import log from "@/base/log"; import { customAPIHost } from "@/base/origins"; -import EnteButton from "@ente/shared/components/EnteButton"; import { CircularProgress, Stack, Typography, styled } from "@mui/material"; import { t } from "i18next"; import { useRouter } from "next/router"; @@ -140,23 +140,21 @@ export const VerifyingPasskey: React.FC = ({ - {t("try_again")} - + - {t("check_status")} - + From 50f924e3c5c6a6d88185544144b801b8688a7c33 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 10:56:59 +0530 Subject: [PATCH 047/438] Switch --- web/packages/accounts/pages/change-email.tsx | 23 ++++++++------------ 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/web/packages/accounts/pages/change-email.tsx b/web/packages/accounts/pages/change-email.tsx index b50bad3e5e..fb781e76c5 100644 --- a/web/packages/accounts/pages/change-email.tsx +++ b/web/packages/accounts/pages/change-email.tsx @@ -1,12 +1,11 @@ import { changeEmail, sendOTTForEmailChange } from "@/accounts/api/user"; +import { LoadingButton } from "@/base/components/mui/LoadingButton"; import { ensure } from "@/utils/ensure"; -import { wait } from "@/utils/promise"; import { VerticallyCentered } from "@ente/shared/components/Container"; import FormPaper from "@ente/shared/components/Form/FormPaper"; import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer"; import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title"; import LinkButton from "@ente/shared/components/LinkButton"; -import SubmitButton from "@ente/shared/components/SubmitButton"; import { LS_KEYS, getData, setLSUser } from "@ente/shared/storage/localStorage"; import { Alert, Box, TextField } from "@mui/material"; import { Formik, type FormikHelpers } from "formik"; @@ -50,7 +49,6 @@ const ChangeEmailForm: React.FC = () => { const [ottInputVisible, setShowOttInputVisibility] = useState(false); const [email, setEmail] = useState(null); const [showMessage, setShowMessage] = useState(false); - const [success, setSuccess] = useState(false); const router = useRouter(); @@ -84,8 +82,6 @@ const ChangeEmailForm: React.FC = () => { await changeEmail(email, ensure(ott)); await setLSUser({ ...getData(LS_KEYS.USER), email }); setLoading(false); - setSuccess(true); - await wait(1000); goToApp(); } catch (e) { setLoading(false); @@ -165,16 +161,15 @@ const ChangeEmailForm: React.FC = () => { disabled={loading} /> )} - + > + {!ottInputVisible ? t("SEND_OTT") : t("VERIFY")} + From 5746ad19426bb6ceb5ca72a7348b222a490acc91 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 11:13:37 +0530 Subject: [PATCH 048/438] Switch --- .../components/two-factor/VerifyForm.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/web/packages/accounts/components/two-factor/VerifyForm.tsx b/web/packages/accounts/components/two-factor/VerifyForm.tsx index be1224b0d8..3a3d7ac7f3 100644 --- a/web/packages/accounts/components/two-factor/VerifyForm.tsx +++ b/web/packages/accounts/components/two-factor/VerifyForm.tsx @@ -1,10 +1,9 @@ import InvalidInputMessage from "@/accounts/components/two-factor/InvalidInputMessage"; -import { wait } from "@/utils/promise"; +import { LoadingButton } from "@/base/components/mui/LoadingButton"; import { CenteredFlex, VerticallyCentered, } from "@ente/shared/components/Container"; -import SubmitButton from "@ente/shared/components/SubmitButton"; import { Box, Typography } from "@mui/material"; import { Formik, type FormikHelpers } from "formik"; import { t } from "i18next"; @@ -27,12 +26,9 @@ export type VerifyTwoFactorCallback = ( export default function VerifyTwoFactor(props: Props) { const [waiting, setWaiting] = useState(false); const otpInputRef = useRef(null); - const [success, setSuccess] = useState(false); const markSuccessful = async () => { setWaiting(false); - setSuccess(true); - await wait(1000); }; const submitForm = async ( @@ -95,12 +91,16 @@ export default function VerifyTwoFactor(props: Props) { )} - + > + {props.buttonText} + )} From bd9cb1ac86e4fdf401808a05bf671554c1c8e678 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 11:27:33 +0530 Subject: [PATCH 049/438] Use --- .../emailShare/AddParticipantForm.tsx | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipantForm.tsx b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipantForm.tsx index 76219b0ef8..ca2b242856 100644 --- a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipantForm.tsx +++ b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipantForm.tsx @@ -3,11 +3,12 @@ import { MenuItemGroup, MenuSectionTitle, } from "@/base/components/Menu"; +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; +import { LoadingButton } from "@/base/components/mui/LoadingButton"; import { FlexWrapper } from "@ente/shared/components/Container"; import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem"; -import SubmitButton from "@ente/shared/components/SubmitButton"; import DoneIcon from "@mui/icons-material/Done"; -import { Button, FormHelperText, Stack } from "@mui/material"; +import { FormHelperText, Stack } from "@mui/material"; import TextField from "@mui/material/TextField"; import Avatar from "components/pages/gallery/Avatar"; import { Formik, type FormikHelpers } from "formik"; @@ -204,7 +205,7 @@ export default function AddParticipantForm(props: AddParticipantFormProps) { > {props.secondaryButtonAction && ( - + )} - + > + {props.buttonText} + From 3bfe4711103e768be4568cc7ad116a5107ac69fb Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 11:32:01 +0530 Subject: [PATCH 050/438] Use --- .../shared/components/SingleInputForm.tsx | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/web/packages/shared/components/SingleInputForm.tsx b/web/packages/shared/components/SingleInputForm.tsx index 82e42edd22..99981bed35 100644 --- a/web/packages/shared/components/SingleInputForm.tsx +++ b/web/packages/shared/components/SingleInputForm.tsx @@ -1,12 +1,13 @@ +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; +import { LoadingButton } from "@/base/components/mui/LoadingButton"; import { FlexWrapper } from "@ente/shared/components/Container"; import ShowHidePassword from "@ente/shared/components/Form/ShowHidePassword"; -import { Button, FormHelperText } from "@mui/material"; +import { FormHelperText } from "@mui/material"; import TextField from "@mui/material/TextField"; import { Formik, type FormikHelpers, type FormikState } from "formik"; import { t } from "i18next"; import React, { useMemo, useState } from "react"; import * as Yup from "yup"; -import SubmitButton from "./SubmitButton"; interface formValues { inputValue: string; @@ -170,7 +171,7 @@ export default function SingleInputForm(props: SingleInputFormProps) { flexWrap={props.blockButton ? "wrap-reverse" : "nowrap"} > {props.secondaryButtonAction && ( - + )} - + > + {props.buttonText} + )} From ac9e9079619fb8968a6ef254b1ddc4d4b13c778d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 11:37:27 +0530 Subject: [PATCH 051/438] Fix crash --- web/apps/photos/src/components/PhotoFrame.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/apps/photos/src/components/PhotoFrame.tsx b/web/apps/photos/src/components/PhotoFrame.tsx index e9c91345c8..1930435cb5 100644 --- a/web/apps/photos/src/components/PhotoFrame.tsx +++ b/web/apps/photos/src/components/PhotoFrame.tsx @@ -323,7 +323,7 @@ const PhotoFrame = ({ } activeCollectionID={activeCollectionID} showPlaceholder={isScrolling} - isFav={favItemIds.has(item.id)} + isFav={favItemIds?.has(item.id)} /> ); From ac9648e88509328908abe8e4c3f6e0489786f82b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 13:05:45 +0530 Subject: [PATCH 052/438] Conv --- web/packages/accounts/components/SignUp.tsx | 13 ++++++++----- .../base/components/mui/LoadingButton.tsx | 15 ++++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/web/packages/accounts/components/SignUp.tsx b/web/packages/accounts/components/SignUp.tsx index c0262df9f5..303f0347af 100644 --- a/web/packages/accounts/components/SignUp.tsx +++ b/web/packages/accounts/components/SignUp.tsx @@ -3,6 +3,7 @@ import { PasswordStrengthHint } from "@/accounts/components/PasswordStrength"; import { PAGES } from "@/accounts/constants/pages"; import { isWeakPassword } from "@/accounts/utils"; import { generateKeyAndSRPAttributes } from "@/accounts/utils/srp"; +import { LoadingButton } from "@/base/components/mui/LoadingButton"; import log from "@/base/log"; import { LS_KEYS, setLSUser } from "@ente/shared//storage/localStorage"; import { VerticallyCentered } from "@ente/shared/components/Container"; @@ -10,7 +11,6 @@ import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer"; import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title"; import ShowHidePassword from "@ente/shared/components/Form/ShowHidePassword"; import LinkButton from "@ente/shared/components/LinkButton"; -import SubmitButton from "@ente/shared/components/SubmitButton"; import { generateAndSaveIntermediateKeyAttributes, saveKeyInSessionStore, @@ -289,15 +289,18 @@ export const SignUp: React.FC = ({ router, login, host }) => { - + > + {t("CREATE_ACCOUNT")} + {loading && ( = ({ }) => ( Date: Tue, 8 Oct 2024 13:10:52 +0530 Subject: [PATCH 053/438] Up --- .../base/components/mui/LoadingButton.tsx | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/web/packages/base/components/mui/LoadingButton.tsx b/web/packages/base/components/mui/LoadingButton.tsx index 60053262d2..d90e668ff4 100644 --- a/web/packages/base/components/mui/LoadingButton.tsx +++ b/web/packages/base/components/mui/LoadingButton.tsx @@ -18,24 +18,24 @@ export const LoadingButton: React.FC = ({ sx, children, ...rest -}) => ( - - {loading ? : children} - -); +}) => + loading ? ( + + + + ) : ( + + {children} + + ); From 8b64c6d2bc3a6e4fe925ebcf81bd0c43d00a93dc Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 13:14:29 +0530 Subject: [PATCH 054/438] Switch --- .../accounts/components/SetPasswordForm.tsx | 13 ++++++++----- web/packages/accounts/components/SignUp.tsx | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/web/packages/accounts/components/SetPasswordForm.tsx b/web/packages/accounts/components/SetPasswordForm.tsx index 8c05d7ce52..1ddfa5ff1f 100644 --- a/web/packages/accounts/components/SetPasswordForm.tsx +++ b/web/packages/accounts/components/SetPasswordForm.tsx @@ -1,6 +1,6 @@ import { isWeakPassword } from "@/accounts/utils"; +import { LoadingButton } from "@/base/components/mui/LoadingButton"; import ShowHidePassword from "@ente/shared/components/Form/ShowHidePassword"; -import SubmitButton from "@ente/shared/components/SubmitButton"; import { Box, Input, TextField, Typography } from "@mui/material"; import { Formik } from "formik"; import { t } from "i18next"; @@ -137,12 +137,15 @@ function SetPasswordForm(props: SetPasswordFormProps) { - + > + {props.buttonText} + {loading && ( = ({ router, login, host }) => { Date: Tue, 8 Oct 2024 13:15:27 +0530 Subject: [PATCH 055/438] Fin --- .../base/components/mui/LoadingButton.tsx | 3 -- .../shared/components/SubmitButton.tsx | 53 ------------------- 2 files changed, 56 deletions(-) delete mode 100644 web/packages/shared/components/SubmitButton.tsx diff --git a/web/packages/base/components/mui/LoadingButton.tsx b/web/packages/base/components/mui/LoadingButton.tsx index d90e668ff4..ca7cdfbbd4 100644 --- a/web/packages/base/components/mui/LoadingButton.tsx +++ b/web/packages/base/components/mui/LoadingButton.tsx @@ -7,9 +7,6 @@ import React from "react"; * prop is set. * * The button is also disabled when in the loading state. - * - * TODO: This duplicates the existing SubmitButton. Merge these two gradually - * (didn't want to break existing layouts, so will do it piecewise). */ export const LoadingButton: React.FC = ({ loading, diff --git a/web/packages/shared/components/SubmitButton.tsx b/web/packages/shared/components/SubmitButton.tsx deleted file mode 100644 index e2e3721957..0000000000 --- a/web/packages/shared/components/SubmitButton.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import Done from "@mui/icons-material/Done"; -import { Button, CircularProgress, type ButtonProps } from "@mui/material"; -import React from "react"; - -export interface SubmitButtonProps { - loading: boolean; - buttonText: string; - - disabled?: boolean; - success?: boolean; -} -const SubmitButton: React.FC> = ({ - loading, - buttonText, - disabled, - success, - sx, - ...props -}) => { - return ( - - ); -}; - -export default SubmitButton; From bc84ea7529230fbf2fe7dcca469d71238f10c5bf Mon Sep 17 00:00:00 2001 From: ashilkn Date: Tue, 8 Oct 2024 14:05:10 +0530 Subject: [PATCH 056/438] [mob][photos] bump up photo_manager version in pubspec.yaml. Note: the version is already 3.5.0 in pubspec.lock, just updating it in pubspec.yaml --- mobile/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 9e06c34c22..b12104ede5 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -144,7 +144,7 @@ dependencies: path_provider: ^2.1.1 pedantic: ^1.9.2 permission_handler: ^11.0.1 - photo_manager: ^3.2.0 + photo_manager: ^3.5.0 photo_view: ^0.14.0 pinput: ^5.0.0 pointycastle: ^3.7.3 From 978f82c809da7b173d31b9a595aafaf904e15a3a Mon Sep 17 00:00:00 2001 From: ashilkn Date: Tue, 8 Oct 2024 14:12:34 +0530 Subject: [PATCH 057/438] [mob][photos] Bump up version to v0.9.47 --- mobile/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index b12104ede5..0019e80b22 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.9.46+946 +version: 0.9.47+947 publish_to: none environment: From ca5ac8da6b20cf98987b7fac9f468cdc615d5280 Mon Sep 17 00:00:00 2001 From: ashilkn Date: Tue, 8 Oct 2024 14:12:54 +0530 Subject: [PATCH 058/438] [mob][photos] Run flutter pub upgrade --- mobile/pubspec.lock | 76 +++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index e1c7c7aea7..7d50136206 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -821,10 +821,10 @@ packages: dependency: transitive description: name: flutter_inappwebview_windows - sha256: "0615da4cf9a8d2c0dbe3791e2861fa5b6f72eb60e2e2c4b47d73f0d8922df62a" + sha256: "95ebc65aecfa63b2084c822aec6ba0545f0a0afaa3899f2c752ec96c09108db5" url: "https://pub.dev" source: hosted - version: "0.5.0+1" + version: "0.5.0+2" flutter_launcher_icons: dependency: "direct main" description: @@ -914,10 +914,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda" + sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398" url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.0.23" flutter_secure_storage: dependency: "direct main" description: @@ -1209,10 +1209,10 @@ packages: dependency: transitive description: name: image_picker_android - sha256: dbd24fc963d2e3e8dd55d9a965a50bab437f15c9d7015b38ceb70c858f9655bb + sha256: d3e5e00fdfeca8fd4ffb3227001264d449cc8950414c2ff70b0e06b9c628e643 url: "https://pub.dev" source: hosted - version: "0.8.12+14" + version: "0.8.12+15" image_picker_for_web: dependency: transitive description: @@ -1273,10 +1273,10 @@ packages: dependency: transitive description: name: in_app_purchase_android - sha256: "25eb8694819caca282a527c26d5a1775164965c554ee99b9c10f3a0e44675c75" + sha256: bee60266e443d4ae0e4809bae7f9cd4d6be75ab5ec6bb3d2ca737774a274a3bd url: "https://pub.dev" source: hosted - version: "0.3.6+8" + version: "0.3.6+9" in_app_purchase_platform_interface: dependency: transitive description: @@ -1422,10 +1422,10 @@ packages: dependency: "direct main" description: name: local_auth_android - sha256: "5351c7eea8823de28e37d8b7b3e386d944b80f2a77edb91a5707fb97a41fc1b1" + sha256: "6763aaf8965f21822624cb2fd3c03d2a8b3791037b5efb0fe4b13e110f5afc92" url: "https://pub.dev" source: hosted - version: "1.0.45" + version: "1.0.46" local_auth_darwin: dependency: transitive description: @@ -1834,10 +1834,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a url: "https://pub.dev" source: hosted - version: "2.2.10" + version: "2.2.12" path_provider_foundation: dependency: transitive description: @@ -1946,10 +1946,10 @@ packages: dependency: transitive description: name: photo_manager_image_provider - sha256: b0a6d59f34e48c2b9aa52a4a655308c29b0fc4b3931607f9e0e252bc49aef974 + sha256: b6015b67b32f345f57cf32c126f871bced2501236c405aafaefa885f7c821e4f url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.2.0" photo_view: dependency: "direct main" description: @@ -2202,10 +2202,10 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" + sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" shared_preferences_foundation: dependency: transitive description: @@ -2343,18 +2343,34 @@ packages: dependency: "direct main" description: name: sqflite - sha256: ff5a2436ef8ebdfda748fbfe957f9981524cb5ff11e7bafa8c42771840e8a788 + sha256: "79a297dc3cc137e758c6a4baf83342b039e5a6d2436fcdf3f96a00adaaf2ad62" url: "https://pub.dev" source: hosted - version: "2.3.3+2" + version: "2.4.0" + sqflite_android: + dependency: transitive + description: + name: sqflite_android + sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" + url: "https://pub.dev" + source: hosted + version: "2.4.0" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "2d8e607db72e9cb7748c9c6e739e2c9618320a5517de693d5a24609c4671b1a4" + sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490" url: "https://pub.dev" source: hosted - version: "2.5.4+4" + version: "2.5.4+5" + sqflite_darwin: + dependency: transitive + description: + name: sqflite_darwin + sha256: "769733dddf94622d5541c73e4ddc6aa7b252d865285914b6fcd54a63c4b4f027" + url: "https://pub.dev" + source: hosted + version: "2.4.1-1" sqflite_migration: dependency: "direct main" description: @@ -2363,6 +2379,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.0" + sqflite_platform_interface: + dependency: transitive + description: + name: sqflite_platform_interface + sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + url: "https://pub.dev" + source: hosted + version: "2.4.0" sqlite3: dependency: transitive description: @@ -2607,10 +2631,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: a4e5f34f2fadf1fa7b4e69db89189056e313c9c98e8ad420e6b53677b6abc334 + sha256: "8fc3bae0b68c02c47c5c86fa8bfa74471d42687b0eded01b78de87872db745e2" url: "https://pub.dev" source: hosted - version: "6.3.11" + version: "6.3.12" url_launcher_ios: dependency: transitive description: @@ -2729,18 +2753,18 @@ packages: dependency: transitive description: name: video_player_android - sha256: b5f318087fb009a1425eee29079eb99fbcbd9e2dc480aaa36dc5b6f40f5f8ae1 + sha256: ae5287ca367e206eb74d7b3dc1ce0b8912ab9a3fc0597b6a101a0a5239f229d3 url: "https://pub.dev" source: hosted - version: "2.7.7" + version: "2.7.9" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation - sha256: d1e9a824f2b324000dc8fb2dcb2a3285b6c1c7c487521c63306cc5b394f68a7c + sha256: cd5ab8a8bc0eab65ab0cea40304097edc46da574c8c1ecdee96f28cd8ef3792f url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "2.6.2" video_player_platform_interface: dependency: transitive description: From 8606f431733652ce012646a6b2b21b0cfa047021 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 8 Oct 2024 14:25:45 +0530 Subject: [PATCH 059/438] Move to base --- web/apps/accounts/src/pages/_app.tsx | 4 ++-- web/apps/accounts/src/pages/passkeys/verify.tsx | 4 ++-- web/apps/auth/src/pages/_app.tsx | 4 ++-- web/apps/auth/src/pages/auth.tsx | 4 ++-- web/apps/cast/src/pages/index.tsx | 4 ++-- .../src/components/Collections/AlbumCastDialog.tsx | 4 ++-- .../src/components/Collections/CollectionHeader.tsx | 6 +++--- web/apps/photos/src/components/EnteSpinner.tsx | 7 ------- .../src/components/PhotoViewer/FileInfo/index.tsx | 4 ++-- .../photos/src/components/PhotoViewer/index.tsx | 4 ++-- .../styledComponents/SmallLoadingSpinner.tsx | 4 ++-- web/apps/photos/src/components/Sidebar/index.tsx | 4 ++-- web/apps/photos/src/pages/_app.tsx | 4 ++-- web/apps/photos/src/pages/deduplicate.tsx | 4 ++-- web/apps/photos/src/pages/gallery.tsx | 4 ++-- web/apps/photos/src/pages/index.tsx | 4 ++-- web/apps/photos/src/pages/shared-albums.tsx | 6 +++--- .../accounts/components/two-factor/setup/QRMode.tsx | 7 +++---- web/packages/accounts/pages/credentials.tsx | 6 +++--- web/packages/accounts/pages/generate.tsx | 4 ++-- web/packages/accounts/pages/login.tsx | 4 ++-- web/packages/accounts/pages/passkeys/finish.tsx | 4 ++-- web/packages/accounts/pages/signup.tsx | 4 ++-- web/packages/accounts/pages/verify.tsx | 6 +++--- .../base/components/mui/ActivityIndicator.tsx | 13 +++++++++++++ web/packages/new/photos/components/MLSettings.tsx | 4 ++-- web/packages/shared/components/CodeBlock/index.tsx | 4 ++-- web/packages/shared/components/EnteSpinner.tsx | 7 ------- .../styledComponents/SmallLoadingSpinner.tsx | 4 ++-- 29 files changed, 70 insertions(+), 72 deletions(-) delete mode 100644 web/apps/photos/src/components/EnteSpinner.tsx create mode 100644 web/packages/base/components/mui/ActivityIndicator.tsx delete mode 100644 web/packages/shared/components/EnteSpinner.tsx diff --git a/web/apps/accounts/src/pages/_app.tsx b/web/apps/accounts/src/pages/_app.tsx index 31ceecf32d..a9a64937cc 100644 --- a/web/apps/accounts/src/pages/_app.tsx +++ b/web/apps/accounts/src/pages/_app.tsx @@ -1,5 +1,6 @@ import { staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; +import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; import { setupI18n } from "@/base/i18n"; import { disableDiskLogs } from "@/base/log"; @@ -7,7 +8,6 @@ import { logUnhandledErrorsAndRejections } from "@/base/log-web"; import { Overlay } from "@ente/shared/components/Container"; import DialogBoxV2 from "@ente/shared/components/DialogBoxV2"; import type { DialogBoxAttributesV2 } from "@ente/shared/components/DialogBoxV2/types"; -import EnteSpinner from "@ente/shared/components/EnteSpinner"; import { getTheme } from "@ente/shared/themes"; import { THEME_COLOR } from "@ente/shared/themes/constants"; import { CssBaseline } from "@mui/material"; @@ -71,7 +71,7 @@ const App: React.FC = ({ Component, pageProps }) => { backgroundColor: theme.colors.background.base, })} > - + )} {showNavbar && } diff --git a/web/apps/accounts/src/pages/passkeys/verify.tsx b/web/apps/accounts/src/pages/passkeys/verify.tsx index a533d0f645..196682be28 100644 --- a/web/apps/accounts/src/pages/passkeys/verify.tsx +++ b/web/apps/accounts/src/pages/passkeys/verify.tsx @@ -1,10 +1,10 @@ +import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import log from "@/base/log"; import type { TwoFactorAuthorizationResponse } from "@/base/types/credentials"; import { ensure } from "@/utils/ensure"; import { nullToUndefined } from "@/utils/transform"; import { VerticallyCentered } from "@ente/shared/components/Container"; -import EnteSpinner from "@ente/shared/components/EnteSpinner"; import InfoIcon from "@mui/icons-material/Info"; import KeyIcon from "@mui/icons-material/Key"; import { Paper, Typography, styled } from "@mui/material"; @@ -272,7 +272,7 @@ const redirectToURL = (url: URL) => { const Loading: React.FC = () => { return ( - + ); }; diff --git a/web/apps/auth/src/pages/_app.tsx b/web/apps/auth/src/pages/_app.tsx index 415264fcdb..8474047c72 100644 --- a/web/apps/auth/src/pages/_app.tsx +++ b/web/apps/auth/src/pages/_app.tsx @@ -2,6 +2,7 @@ import { accountLogout } from "@/accounts/services/logout"; import type { AccountsContextT } from "@/accounts/types/context"; import { clientPackageName, staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; +import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; import { setupI18n } from "@/base/i18n"; import { @@ -12,7 +13,6 @@ import { ensure } from "@/utils/ensure"; import { Overlay } from "@ente/shared/components/Container"; import DialogBoxV2 from "@ente/shared/components/DialogBoxV2"; import type { DialogBoxAttributesV2 } from "@ente/shared/components/DialogBoxV2/types"; -import EnteSpinner from "@ente/shared/components/EnteSpinner"; import { MessageContainer } from "@ente/shared/components/MessageContainer"; import { useLocalState } from "@ente/shared/hooks/useLocalState"; import HTTPService from "@ente/shared/network/HTTPService"; @@ -183,7 +183,7 @@ const App: React.FC = ({ Component, pageProps }) => { backgroundColor: theme.colors.background.base, })} > - + )} {isI18nReady && ( diff --git a/web/apps/auth/src/pages/auth.tsx b/web/apps/auth/src/pages/auth.tsx index 1360ee1cec..e60083658b 100644 --- a/web/apps/auth/src/pages/auth.tsx +++ b/web/apps/auth/src/pages/auth.tsx @@ -1,4 +1,5 @@ import { stashRedirect } from "@/accounts/services/redirect"; +import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { NavbarBase } from "@/base/components/Navbar"; import { ensure } from "@/utils/ensure"; import { @@ -6,7 +7,6 @@ import { VerticallyCentered, } from "@ente/shared/components/Container"; import { EnteLogo } from "@ente/shared/components/EnteLogo"; -import EnteSpinner from "@ente/shared/components/EnteSpinner"; import { sessionExpiredDialogAttributes } from "@ente/shared/components/LoginComponents"; import OverflowMenu from "@ente/shared/components/OverflowMenu/menu"; import { OverflowMenuOption } from "@ente/shared/components/OverflowMenu/option"; @@ -68,7 +68,7 @@ const Page: React.FC = () => { if (!hasFetched) { return ( - + ); } diff --git a/web/apps/cast/src/pages/index.tsx b/web/apps/cast/src/pages/index.tsx index 2a49e3d43f..c3782be674 100644 --- a/web/apps/cast/src/pages/index.tsx +++ b/web/apps/cast/src/pages/index.tsx @@ -1,5 +1,5 @@ +import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import log from "@/base/log"; -import EnteSpinner from "@ente/shared/components/EnteSpinner"; import { styled } from "@mui/material"; import { PairingCode } from "components/PairingCode"; import { useRouter } from "next/router"; @@ -102,7 +102,7 @@ const Container = styled("div")` const Spinner: React.FC = () => ( - + ); diff --git a/web/apps/photos/src/components/Collections/AlbumCastDialog.tsx b/web/apps/photos/src/components/Collections/AlbumCastDialog.tsx index f09544a4e5..18253c351d 100644 --- a/web/apps/photos/src/components/Collections/AlbumCastDialog.tsx +++ b/web/apps/photos/src/components/Collections/AlbumCastDialog.tsx @@ -1,9 +1,9 @@ +import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { boxSeal } from "@/base/crypto/libsodium"; import log from "@/base/log"; import type { Collection } from "@/media/collection"; import { loadCast } from "@/new/photos/utils/chromecast-sender"; import DialogBoxV2 from "@ente/shared/components/DialogBoxV2"; -import EnteSpinner from "@ente/shared/components/EnteSpinner"; import SingleInputForm, { type SingleInputFormProps, } from "@ente/shared/components/SingleInputForm"; @@ -167,7 +167,7 @@ export const AlbumCastDialog: React.FC = ({ {view == "auto" && (
- +
{t("choose_device_from_browser")} )} - + ); }; diff --git a/web/apps/photos/src/components/Collections/CollectionNamer.tsx b/web/apps/photos/src/components/Collections/CollectionNamer.tsx index 0374b8dc14..bf64267499 100644 --- a/web/apps/photos/src/components/Collections/CollectionNamer.tsx +++ b/web/apps/photos/src/components/Collections/CollectionNamer.tsx @@ -1,4 +1,4 @@ -import { DialogBoxV2 } from "@/base/components/MiniDialog"; +import { TitledMiniDialog } from "@/base/components/MiniDialog"; import SingleInputForm, { type SingleInputFormProps, } from "@ente/shared/components/SingleInputForm"; @@ -39,7 +39,7 @@ export default function CollectionNamer({ attributes, ...props }: Props) { }; return ( - - + ); } diff --git a/web/apps/photos/src/components/DeleteAccountModal.tsx b/web/apps/photos/src/components/DeleteAccountModal.tsx index ba2d6488f1..72494f9455 100644 --- a/web/apps/photos/src/components/DeleteAccountModal.tsx +++ b/web/apps/photos/src/components/DeleteAccountModal.tsx @@ -1,4 +1,4 @@ -import { DialogBoxV2 } from "@/base/components/MiniDialog"; +import { TitledMiniDialog } from "@/base/components/MiniDialog"; import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { LoadingButton } from "@/base/components/mui/LoadingButton"; import log from "@/base/log"; @@ -138,7 +138,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { return ( <> - { )} - + ); }; diff --git a/web/apps/photos/src/components/ExportPendingList.tsx b/web/apps/photos/src/components/ExportPendingList.tsx index 667926afdd..087f31d3d0 100644 --- a/web/apps/photos/src/components/ExportPendingList.tsx +++ b/web/apps/photos/src/components/ExportPendingList.tsx @@ -1,4 +1,4 @@ -import { DialogBoxV2 } from "@/base/components/MiniDialog"; +import { TitledMiniDialog } from "@/base/components/MiniDialog"; import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { ItemCard, PreviewItemTile } from "@/new/photos/components/Tiles"; import { EnteFile } from "@/new/photos/types/file"; @@ -55,10 +55,9 @@ const ExportPendingList = (props: Iprops) => { }; return ( - { > {t("close")} - + ); }; diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx index b21a3ac58d..886328ddbf 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx @@ -1,4 +1,4 @@ -import { DialogBoxV2 } from "@/base/components/MiniDialog"; +import { TitledMiniDialog } from "@/base/components/MiniDialog"; import SingleInputForm, { type SingleInputFormProps, } from "@ente/shared/components/SingleInputForm"; @@ -23,7 +23,7 @@ export const FileNameEditDialog = ({ } }; return ( - - + ); }; diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index cc628bacdb..8ddabc611b 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -223,55 +223,50 @@ export function MiniDialog({ // } // } -type DialogBoxV2Props = React.PropsWithChildren< - Omit & { - onClose: () => void; - /** - * The dialog's title. - * - * Usually this will be a string, but it can be any {@link ReactNode}. Note - * that it always gets wrapped in a Typography element to set the font - * style, so if your ReactNode wants to do its own thing, it'll need to - * reset or override these customizations. - */ - title?: React.ReactNode; - } ->; +type TitledMiniDialogProps = Omit & { + onClose: () => void; + /** + * The dialog's title. + */ + title?: React.ReactNode; +}; /** - * TODO This is a duplicate of MiniDialog. This is for use by call sites that - * were using the MiniDialog not as a dialog but as a base container. Such use - * cases are better served by directly using the MUI {@link Dialog}, so these - * are considered deprecated. Splitting these here so that we can streamline the - * API for the notify/confirm case separately. + * MiniDialog in a "shell" form. + * + * This is a {@link Dialog} for use at places which need more customization than + * what {@link MiniDialog} provides, but wish to retain the same size and + * general look without duplicating the MiniDialog code. + * + * It does three things: + * + * - Sets a fixed size same as {@link MiniDialog}, and sets up similar padding. + * - Takes the title as a prop, and wraps it in a {@link DialogTitle}. + * - Wraps children in a scrollable {@link DialogContent}. */ -export function DialogBoxV2({ - title, - children, - open, - onClose, - ...props -}: DialogBoxV2Props) { +export const TitledMiniDialog: React.FC< + React.PropsWithChildren +> = ({ title, children, open, onClose, ...props }) => { const { PaperProps, ...rest } = props; return ( - + {title} {children} ); -} +}; From 126904c68f1d8540e7f54d65eda835feb2a51798 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 09:42:27 +0530 Subject: [PATCH 146/438] Move --- .../new/photos/components/{PhotoViewer.tsx => z-index.tsx} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename web/packages/new/photos/components/{PhotoViewer.tsx => z-index.tsx} (63%) diff --git a/web/packages/new/photos/components/PhotoViewer.tsx b/web/packages/new/photos/components/z-index.tsx similarity index 63% rename from web/packages/new/photos/components/PhotoViewer.tsx rename to web/packages/new/photos/components/z-index.tsx index c320a73cf5..e66e8435c8 100644 --- a/web/packages/new/photos/components/PhotoViewer.tsx +++ b/web/packages/new/photos/components/z-index.tsx @@ -1,5 +1,5 @@ /** * PhotoSwipe sets the zIndex of its "pswp" class to 1500. We need to go higher - * than that for our drawers and dialogs to show above it. + * than that for our drawers and dialogs to get them to show above it. */ export const photoSwipeZIndex = 1500; From c7dd5dcbcaa26a53d66aa00f8dc31f8a3a58db93 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 09:59:08 +0530 Subject: [PATCH 147/438] zi --- web/apps/accounts/src/pages/_app.tsx | 1 - web/apps/auth/src/pages/_app.tsx | 1 - .../src/components/Collections/AlbumCastDialog.tsx | 3 ++- .../photos/src/components/FilesDownloadProgress.tsx | 3 ++- .../PhotoViewer/FileInfo/FileNameEditDialog.tsx | 3 ++- .../src/components/PhotoViewer/FileInfo/index.tsx | 4 ++-- .../PhotoViewer/ImageEditorOverlay/index.tsx | 3 ++- web/apps/photos/src/pages/_app.tsx | 5 +++-- .../new/photos/components/PhotoDateTimePicker.tsx | 4 ++-- web/packages/new/photos/components/z-index.tsx | 12 ++++++++++++ 10 files changed, 27 insertions(+), 12 deletions(-) diff --git a/web/apps/accounts/src/pages/_app.tsx b/web/apps/accounts/src/pages/_app.tsx index e23692b86e..4c46ed4e56 100644 --- a/web/apps/accounts/src/pages/_app.tsx +++ b/web/apps/accounts/src/pages/_app.tsx @@ -56,7 +56,6 @@ const App: React.FC = ({ Component, pageProps }) => { = ({ Component, pageProps }) => { = ({ open={open} onClose={onClose} title={t("cast_album_to_tv")} - sx={{ zIndex: 1600 }} + sx={{ zIndex: photosDialogZIndex }} > {view == "choose" && ( diff --git a/web/apps/photos/src/components/FilesDownloadProgress.tsx b/web/apps/photos/src/components/FilesDownloadProgress.tsx index 86e5e0508c..7b82b17ee4 100644 --- a/web/apps/photos/src/components/FilesDownloadProgress.tsx +++ b/web/apps/photos/src/components/FilesDownloadProgress.tsx @@ -1,3 +1,4 @@ +import { photosDialogZIndex } from "@/new/photos/components/z-index"; import { AppContext } from "@/new/photos/types/context"; import Notification from "components/Notification"; import { t } from "i18next"; @@ -123,7 +124,7 @@ export const FilesDownloadProgress: React.FC = ({ horizontal="left" sx={{ "&&": { bottom: `${index * 80 + 20}px` }, - zIndex: 1600, + zIndex: photosDialogZIndex, }} open={isFilesDownloadStarted(attributes)} onClose={handleClose(attributes)} diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx index 886328ddbf..555b52ad0c 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/FileNameEditDialog.tsx @@ -1,4 +1,5 @@ import { TitledMiniDialog } from "@/base/components/MiniDialog"; +import { photosDialogZIndex } from "@/new/photos/components/z-index"; import SingleInputForm, { type SingleInputFormProps, } from "@ente/shared/components/SingleInputForm"; @@ -24,7 +25,7 @@ export const FileNameEditDialog = ({ }; return ( ( ))({ - zIndex: photoSwipeZIndex + 1, + zIndex: fileInfoDrawerZIndex, "& .MuiPaper-root": { padding: 8, }, diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx index 7be07c08e4..02cd636e09 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx @@ -6,6 +6,7 @@ import { } from "@/base/components/Menu"; import { nameAndExtension } from "@/base/file"; import log from "@/base/log"; +import { photosDialogZIndex } from "@/new/photos/components/z-index"; import downloadManager from "@/new/photos/services/download"; import { AppContext } from "@/new/photos/types/context"; import { EnteFile } from "@/new/photos/types/file"; @@ -522,7 +523,7 @@ const ImageEditorOverlay = (props: IProps) => { = ({ photo viewer and the info drawer */ dialog: { sx: { - zIndex: photoSwipeZIndex + 2, + zIndex: fileInfoDrawerZIndex + 1, }, }, }} diff --git a/web/packages/new/photos/components/z-index.tsx b/web/packages/new/photos/components/z-index.tsx index e66e8435c8..a988a362b6 100644 --- a/web/packages/new/photos/components/z-index.tsx +++ b/web/packages/new/photos/components/z-index.tsx @@ -3,3 +3,15 @@ * than that for our drawers and dialogs to get them to show above it. */ export const photoSwipeZIndex = 1500; + +/** + * The file info drawer needs to be higher than the photo viewer. + */ +export const fileInfoDrawerZIndex = photoSwipeZIndex + 1; + +/** + * Dialogs (not necessarily always) need to be higher still so to ensure they + * are visible above the drawer in case they are shown in response to some + * action taken in the file info drawer. + */ +export const photosDialogZIndex = 1600; From 84798091099beb17e391525318c85e54fac5e537 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 09:59:45 +0530 Subject: [PATCH 148/438] Rename --- web/apps/accounts/src/pages/_app.tsx | 4 +-- web/apps/photos/src/pages/_app.tsx | 4 +-- web/packages/base/components/MiniDialog.tsx | 34 ++++++++++----------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/web/apps/accounts/src/pages/_app.tsx b/web/apps/accounts/src/pages/_app.tsx index 4c46ed4e56..02d27bd390 100644 --- a/web/apps/accounts/src/pages/_app.tsx +++ b/web/apps/accounts/src/pages/_app.tsx @@ -2,7 +2,7 @@ import { staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; import { type MiniDialogAttributes, - MiniDialog, + AttributedMiniDialog, } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; @@ -55,7 +55,7 @@ const App: React.FC = ({ Component, pageProps }) => { - - component. */ title?: React.ReactNode; staticBackdrop?: boolean; nonClosable?: boolean; /** - * The dialog's content. + * The dialog's message. + * + * Similar to {@link title}, this is usually provided, and a string. */ content?: React.ReactNode; /** @@ -93,10 +93,10 @@ type MiniDialogProps = React.PropsWithChildren< * user, or ask for confirmation before actions. * * The rendered dialog can be customized by modifying the {@link attributes} - * prop. If you find yourself wanting to customize it further, consider just - * creating a new bespoke instantiation of a {@link Dialog}. + * prop. If you find yourself wanting to customize it further, consider either + * using a {@link TitledMiniDialog} or {@link Dialog}. */ -export function MiniDialog({ +export function AttributedMiniDialog({ attributes, children, open, @@ -235,18 +235,18 @@ type TitledMiniDialogProps = Omit & { * MiniDialog in a "shell" form. * * This is a {@link Dialog} for use at places which need more customization than - * what {@link MiniDialog} provides, but wish to retain the same size and - * general look without duplicating the MiniDialog code. + * what {@link AttributedMiniDialog} provides, but wish to retain a similar look + * and feel without duplicating code. * * It does three things: * - * - Sets a fixed size same as {@link MiniDialog}, and sets up similar padding. + * - Sets a fixed size and padding similar to {@link AttributedMiniDialog}. * - Takes the title as a prop, and wraps it in a {@link DialogTitle}. * - Wraps children in a scrollable {@link DialogContent}. */ export const TitledMiniDialog: React.FC< React.PropsWithChildren -> = ({ title, children, open, onClose, ...props }) => { +> = ({ open, onClose, title, children, ...props }) => { const { PaperProps, ...rest } = props; return ( From d5d015c13c466c9950f95f4563710012e69b4862 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 10:25:17 +0530 Subject: [PATCH 149/438] Tweak --- web/packages/base/components/MiniDialog.tsx | 22 ++++++++------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index ffd78745fb..197ce808da 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -81,12 +81,10 @@ export interface MiniDialogAttributes { buttonDirection?: "row" | "column"; } -type MiniDialogProps = React.PropsWithChildren< - Omit & { - onClose: () => void; - attributes?: MiniDialogAttributes; - } ->; +type MiniDialogProps = Omit & { + onClose: () => void; + attributes?: MiniDialogAttributes; +}; /** * A small, mostly predefined, MUI {@link Dialog} that can be used to notify the @@ -96,13 +94,9 @@ type MiniDialogProps = React.PropsWithChildren< * prop. If you find yourself wanting to customize it further, consider either * using a {@link TitledMiniDialog} or {@link Dialog}. */ -export function AttributedMiniDialog({ - attributes, - children, - open, - onClose, - ...props -}: MiniDialogProps) { +export const AttributedMiniDialog: React.FC< + React.PropsWithChildren +> = ({ open, onClose, attributes, children, ...props }) => { const [loading, setLoading] = useState(false); if (!attributes) { return <>; @@ -201,7 +195,7 @@ export function AttributedMiniDialog({ ); -} +}; // TODO: Sketch of a possible approach to using this. Haven't throught this // through, just noting down the outline inspired by an API I saw. From 8999c7045a8e66cf798cbfa2a35c7c844dabe239 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 10:35:39 +0530 Subject: [PATCH 150/438] Avoid a useEffect (eventually) --- web/apps/photos/src/pages/_app.tsx | 6 ++++++ web/packages/new/photos/types/context.ts | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index f71d370626..e39ba3562c 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -237,6 +237,11 @@ export default function App({ Component, pageProps }: AppProps) { ); const closeDialogBoxV2 = () => setDialogBoxV2View(false); + const showMiniDialog = useCallback((attributes: MiniDialogAttributes) => { + setDialogBoxAttributesV2(attributes); + setDialogBoxV2View(true); + }, []); + // Use `onGenericError` instead. const somethingWentWrong = useCallback( () => @@ -277,6 +282,7 @@ export default function App({ Component, pageProps }: AppProps) { setNotificationAttributes, themeColor, setThemeColor, + showMiniDialog, somethingWentWrong, onGenericError, setDialogBoxAttributesV2, diff --git a/web/packages/new/photos/types/context.ts b/web/packages/new/photos/types/context.ts index 2235c35c11..4c11a9bb01 100644 --- a/web/packages/new/photos/types/context.ts +++ b/web/packages/new/photos/types/context.ts @@ -4,6 +4,7 @@ import type { SetDialogBoxAttributes } from "@ente/shared/components/DialogBox/t import { THEME_COLOR } from "@ente/shared/themes/constants"; import { createContext, useContext } from "react"; import type { SetNotificationAttributes } from "./notification"; +import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; /** * The type of the React context available to all pages in the photos app. @@ -17,6 +18,14 @@ export type AppContextT = AccountsContextT & { * Hide the global activity indicator. */ finishLoading: () => void; + /** + * Show a "mini dialog" with the given attributes. + * + * Mini dialogs (see {@link AttributedMiniDialog}) are meant for simple + * confirmation or notication dialogs. Their appearance and functionality + * can be customized by providing relevant {@link MiniDialogAttributes}. + */ + showMiniDialog: (attributes: MiniDialogAttributes) => void; somethingWentWrong: () => void; setDialogMessage: SetDialogBoxAttributes; setNotificationAttributes: SetNotificationAttributes; From d2d5f630aa59a6c0039078fe77cb1929ced267b2 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 10:43:15 +0530 Subject: [PATCH 151/438] Use --- web/apps/photos/src/components/Sidebar/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/apps/photos/src/components/Sidebar/index.tsx b/web/apps/photos/src/components/Sidebar/index.tsx index ca4fad9fa7..f1e2ba8b2b 100644 --- a/web/apps/photos/src/components/Sidebar/index.tsx +++ b/web/apps/photos/src/components/Sidebar/index.tsx @@ -7,7 +7,7 @@ import log from "@/base/log"; import { savedLogs } from "@/base/log-web"; import { customAPIHost } from "@/base/origins"; import type { CollectionSummaries } from "@/new/photos/services/collection/ui"; -import { AppContext } from "@/new/photos/types/context"; +import { AppContext, useAppContext } from "@/new/photos/types/context"; import { initiateEmail, openURL } from "@/new/photos/utils/web"; import { SpaceBetweenFlex } from "@ente/shared/components/Container"; import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem"; @@ -667,7 +667,7 @@ const ExitSection: React.FC = () => { }; const DebugSection: React.FC = () => { - const appContext = useContext(AppContext); + const { showMiniDialog } = useAppContext(); const [appVersion, setAppVersion] = useState(); const [host, setHost] = useState(); @@ -679,7 +679,7 @@ const DebugSection: React.FC = () => { }); const confirmLogDownload = () => - appContext.setDialogMessage({ + showMiniDialog({ title: t("DOWNLOAD_LOGS"), content: , proceed: { From 49086481371f180730303326136ba4a04179c3a2 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 11:08:52 +0530 Subject: [PATCH 152/438] Similar to TitledMiniDialog --- web/packages/base/components/MiniDialog.tsx | 60 +++++++++++---------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index 197ce808da..bf5408ca70 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -98,6 +98,7 @@ export const AttributedMiniDialog: React.FC< React.PropsWithChildren > = ({ open, onClose, attributes, children, ...props }) => { const [loading, setLoading] = useState(false); + if (!attributes) { return <>; } @@ -118,47 +119,48 @@ export const AttributedMiniDialog: React.FC< PaperProps={{ ...PaperProps, sx: { - padding: "8px 12px", maxWidth: "360px", ...PaperProps?.sx, }, }} {...rest} > - - - {attributes.icon && ( - svg": { - fontSize: "32px", - }, - }} - > - {attributes.icon} - - )} - {attributes.title && ( - - {attributes.title} - - )} - {children || - (attributes?.content && ( - - {attributes.content} - - ))} - + {attributes.icon && ( + svg": { + fontSize: "32px", + }, + color: "text.muted", + padding: "20px 16px 0px 16px", + }} + > + {attributes.icon} + + )} + {attributes.title && ( + + {attributes.title} + + )} + + {attributes.content && ( + + {attributes.content} + + )} + {children} {(attributes.proceed || attributes.close) && ( {attributes.proceed && ( )} - + ); }; From f5ebecfa699bb49336252e39215dace0befd1112 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 11:30:24 +0530 Subject: [PATCH 153/438] Move icon to the right --- web/packages/base/components/MiniDialog.tsx | 35 +++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index bf5408ca70..29a5b7243e 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -22,24 +22,24 @@ import React, { useState } from "react"; * Customize the contents of an {@link AttributedMiniDialog}. */ export interface MiniDialogAttributes { - /** - * An optional icon shown above the title. - */ - icon?: React.ReactNode; /** * The dialog's title. * - * While optional, it is usually provided. It will almost always be a - * string, but the prop accepts any React node to allow passing a i18next - * component. + * This will be usually be a string, but the prop accepts any React node to + * allow passing a i18next component. */ title?: React.ReactNode; + /** + * An optional component shown next to the title. + */ + icon?: React.ReactNode; staticBackdrop?: boolean; nonClosable?: boolean; /** * The dialog's message. * - * Similar to {@link title}, this is usually provided, and a string. + * This will be usually be a string, but the prop accepts any React node to + * allow passing a i18next component. */ content?: React.ReactNode; /** @@ -125,24 +125,27 @@ export const AttributedMiniDialog: React.FC< }} {...rest} > - {attributes.icon && ( + {(attributes.icon || attributes.title) && ( svg": { fontSize: "32px", + color: "text.faint", }, - color: "text.muted", - padding: "20px 16px 0px 16px", + padding: "24px 16px 16px 16px", }} > + {attributes.title && ( + + {attributes.title} + + )} {attributes.icon} )} - {attributes.title && ( - - {attributes.title} - - )} + {attributes.content && ( From 0e46287eeebd76da880c28a94fcb2a22ffed3d0b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 11:40:09 +0530 Subject: [PATCH 154/438] Add icon to error --- web/apps/photos/src/pages/_app.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index e39ba3562c..c0047b83eb 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -5,6 +5,7 @@ import { AttributedMiniDialog } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; import { setupI18n } from "@/base/i18n"; +import ErrorOutline from "@mui/icons-material/ErrorOutline"; import log from "@/base/log"; import { logStartupBanner, @@ -258,6 +259,7 @@ export default function App({ Component, pageProps }: AppProps) { log.error("Error", e), setDialogBoxAttributesV2({ title: t("error"), + icon: , content: t("generic_error"), close: { variant: "critical" }, }) From d904b9318a3fbf59c6137e57e7ec4a724b0bdea0 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 11:41:39 +0530 Subject: [PATCH 155/438] Remove unnecessary setter deps > React guarantees that setState function identity is stable and won't change on > re-renders. Thus it is safe to omit it from the useEffect or useCallback > dependency list. > > https://legacy.reactjs.org/docs/hooks-reference.html#usestate --- web/apps/photos/src/pages/_app.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index c0047b83eb..5b68b6839b 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -5,7 +5,6 @@ import { AttributedMiniDialog } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; import { setupI18n } from "@/base/i18n"; -import ErrorOutline from "@mui/icons-material/ErrorOutline"; import log from "@/base/log"; import { logStartupBanner, @@ -37,6 +36,7 @@ import { getTheme } from "@ente/shared/themes"; import { THEME_COLOR } from "@ente/shared/themes/constants"; import type { User } from "@ente/shared/user/types"; import ArrowForward from "@mui/icons-material/ArrowForward"; +import ErrorOutline from "@mui/icons-material/ErrorOutline"; import { CssBaseline } from "@mui/material"; import { ThemeProvider } from "@mui/material/styles"; import Notification from "components/Notification"; @@ -251,7 +251,7 @@ export default function App({ Component, pageProps }: AppProps) { close: { variant: "critical" }, content: t("generic_error_retry"), }), - [setDialogMessage], + [], ); const onGenericError = useCallback( @@ -264,7 +264,7 @@ export default function App({ Component, pageProps }: AppProps) { close: { variant: "critical" }, }) ), - [setDialogBoxAttributesV2], + [], ); const logout = useCallback(() => { From 86f0dbb6205bb45ca73cd091d00a562fc25c602e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 11:49:54 +0530 Subject: [PATCH 156/438] Rename --- .../accounts/src/pages/passkeys/index.tsx | 4 +- .../src/components/AuthenticateUserModal.tsx | 2 +- .../src/components/DeleteAccountModal.tsx | 6 +- .../photos/src/components/Sidebar/index.tsx | 2 +- web/apps/photos/src/pages/_app.tsx | 2 +- web/packages/accounts/pages/recover.tsx | 2 +- .../accounts/pages/two-factor/recover.tsx | 2 +- web/packages/base/components/MiniDialog.tsx | 71 +++++++++++-------- .../new/photos/components/MLSettings.tsx | 2 +- .../components/gallery/PeopleHeader.tsx | 2 +- .../shared/components/LoginComponents.tsx | 4 +- 11 files changed, 55 insertions(+), 44 deletions(-) diff --git a/web/apps/accounts/src/pages/passkeys/index.tsx b/web/apps/accounts/src/pages/passkeys/index.tsx index 56d09d0fbd..d365af0b6d 100644 --- a/web/apps/accounts/src/pages/passkeys/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/index.tsx @@ -46,7 +46,7 @@ const Page: React.FC = () => { const showPasskeyFetchFailedErrorDialog = useCallback(() => { setDialogBoxAttributesV2({ title: t("error"), - content: t("passkey_fetch_failed"), + message: t("passkey_fetch_failed"), close: {}, }); }, [setDialogBoxAttributesV2]); @@ -282,7 +282,7 @@ const ManagePasskeyDrawer: React.FC = ({ setDialogBoxAttributesV2({ title: t("delete_passkey"), - content: t("delete_passkey_confirmation"), + message: t("delete_passkey_confirmation"), proceed: { text: t("delete"), action: handleDelete, diff --git a/web/apps/photos/src/components/AuthenticateUserModal.tsx b/web/apps/photos/src/components/AuthenticateUserModal.tsx index 9c230cc220..0b6a83b7f9 100644 --- a/web/apps/photos/src/components/AuthenticateUserModal.tsx +++ b/web/apps/photos/src/components/AuthenticateUserModal.tsx @@ -126,7 +126,7 @@ const passwordChangedElsewhereDialogAttributes = ( onLogin: () => void, ): MiniDialogAttributes => ({ title: t("password_changed_elsewhere"), - content: t("password_changed_elsewhere_message"), + message: t("password_changed_elsewhere_message"), proceed: { text: t("login"), action: onLogin, diff --git a/web/apps/photos/src/components/DeleteAccountModal.tsx b/web/apps/photos/src/components/DeleteAccountModal.tsx index 72494f9455..8b75b2a630 100644 --- a/web/apps/photos/src/components/DeleteAccountModal.tsx +++ b/web/apps/photos/src/components/DeleteAccountModal.tsx @@ -43,7 +43,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { setDialogBoxAttributesV2({ title: t("error"), close: { variant: "critical" }, - content: t("generic_error_retry"), + message: t("generic_error_retry"), }); const initiateDelete = async ( @@ -86,7 +86,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { const confirmAccountDeletion = () => { setDialogBoxAttributesV2({ title: t("delete_account"), - content: , + message: , proceed: { text: t("delete"), action: solveChallengeAndDeleteAccount, @@ -101,7 +101,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { setDialogBoxAttributesV2({ title: t("delete_account"), - content: ( + message: ( }} diff --git a/web/apps/photos/src/components/Sidebar/index.tsx b/web/apps/photos/src/components/Sidebar/index.tsx index f1e2ba8b2b..0275a1f92a 100644 --- a/web/apps/photos/src/components/Sidebar/index.tsx +++ b/web/apps/photos/src/components/Sidebar/index.tsx @@ -681,7 +681,7 @@ const DebugSection: React.FC = () => { const confirmLogDownload = () => showMiniDialog({ title: t("DOWNLOAD_LOGS"), - content: , + message: , proceed: { text: t("download"), variant: "accent", diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index 5b68b6839b..9ecc2eb6b5 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -260,7 +260,7 @@ export default function App({ Component, pageProps }: AppProps) { setDialogBoxAttributesV2({ title: t("error"), icon: , - content: t("generic_error"), + message: t("generic_error"), close: { variant: "critical" }, }) ), diff --git a/web/packages/accounts/pages/recover.tsx b/web/packages/accounts/pages/recover.tsx index 531f37763f..c6e86cdafc 100644 --- a/web/packages/accounts/pages/recover.tsx +++ b/web/packages/accounts/pages/recover.tsx @@ -101,7 +101,7 @@ const Page: React.FC = ({ appContext }) => { setDialogBoxAttributesV2({ title: t("sorry"), close: {}, - content: t("NO_RECOVERY_KEY_MESSAGE"), + message: t("NO_RECOVERY_KEY_MESSAGE"), }); return ( diff --git a/web/packages/accounts/pages/two-factor/recover.tsx b/web/packages/accounts/pages/two-factor/recover.tsx index 820a0707e4..be2d2227fd 100644 --- a/web/packages/accounts/pages/two-factor/recover.tsx +++ b/web/packages/accounts/pages/two-factor/recover.tsx @@ -151,7 +151,7 @@ const Page: React.FC = ({ appContext, twoFactorType }) => { appContext.setDialogBoxAttributesV2({ title: t("contact_support"), close: dialogClose ?? {}, - content: ( + message: ( component. */ - content?: React.ReactNode; + message?: React.ReactNode; + /** + * If `true`, then clicks in the backdrop are ignored. The default behaviour + * is to close the dialog when the background is clicked. + */ + staticBackdrop?: boolean; + /** + * If `true`, then the dialog cannot be closed (e.g. with the ESC key, or + * clicking on the backdrop) except through one of the explicitly provided + * actions. + */ + nonClosable?: boolean; + /** + * Customize the primary action button offered by the dialog box. + * + * This is provided by boxes which serve as some sort of confirmation. For + * dialogs which are informational notifications, this is usually skipped, + * only the {@link close} action button is configured. + */ + proceed?: { + /** The string to use as the label for the primary action button. */ + text: string; + /** The color of the button. */ + variant?: ButtonProps["color"]; + /** + * The function to call when the user presses the primary action button. + * + * It is passed a {@link setLoading} function that can be used to show + * or hide loading indicator or the primary action button. + */ + action: + | (() => void | Promise) + | ((setLoading: (value: boolean) => void) => void | Promise); + }; /** * Customize the cancel (dismiss) action button offered by the dialog box. * - * Usually dialog boxes should have a cancel action, but this can be skipped - * to only show one of the other types of buttons. + * Usually all dialog boxes should have a cancel action. */ close?: { /** The string to use as the label for the cancel button. */ @@ -60,24 +90,7 @@ export interface MiniDialogAttributes { */ action?: () => void; }; - /** - * Customize the primary action button offered by the dialog box. - */ - proceed?: { - /** The string to use as the label for the primary action. */ - text: string; - /** - * The function to call when the user presses the primary action button. - * - * It is passed a {@link setLoading} function that can be used to show - * or hide loading indicator or the primary action button. - */ - action: - | (() => void | Promise) - | ((setLoading: (value: boolean) => void) => void | Promise); - variant?: ButtonProps["color"]; - disabled?: boolean; - }; + /** The direction in which the buttons are stacked. Default is "column". */ buttonDirection?: "row" | "column"; } @@ -145,11 +158,10 @@ export const AttributedMiniDialog: React.FC< {attributes.icon}
)} - - {attributes.content && ( + {attributes.message && ( - {attributes.content} + {attributes.message} )} {children} @@ -160,7 +172,7 @@ export const AttributedMiniDialog: React.FC< gap: "12px", }} direction={ - attributes.buttonDirection === "row" + attributes.buttonDirection == "row" ? "row-reverse" : "column" } @@ -168,7 +180,7 @@ export const AttributedMiniDialog: React.FC< {attributes.proceed && ( { await attributes.proceed?.action( @@ -177,14 +189,13 @@ export const AttributedMiniDialog: React.FC< onClose(); }} - disabled={attributes.proceed.disabled} > {attributes.proceed.text} )} {attributes.close && ( { attributes.close?.action && diff --git a/web/packages/new/photos/components/MLSettings.tsx b/web/packages/new/photos/components/MLSettings.tsx index cf55625bf3..3b1db3002b 100644 --- a/web/packages/new/photos/components/MLSettings.tsx +++ b/web/packages/new/photos/components/MLSettings.tsx @@ -292,7 +292,7 @@ const ManageML: React.FC = ({ const confirmDisableML = () => { setDialogBoxAttributesV2({ title: t("ml_search_disable"), - content: t("ml_search_disable_confirm"), + message: t("ml_search_disable_confirm"), close: { text: t("cancel") }, proceed: { variant: "critical", diff --git a/web/packages/new/photos/components/gallery/PeopleHeader.tsx b/web/packages/new/photos/components/gallery/PeopleHeader.tsx index debe3cf9f6..aa0b05922e 100644 --- a/web/packages/new/photos/components/gallery/PeopleHeader.tsx +++ b/web/packages/new/photos/components/gallery/PeopleHeader.tsx @@ -105,7 +105,7 @@ const CGroupPersonOptions: React.FC = ({ const handleDeletePerson = () => setDialogBoxAttributesV2({ title: pt("Reset person?"), - content: pt( + message: pt( "The name, face groupings and suggestions for this person will be reset", ), close: { text: t("cancel") }, diff --git a/web/packages/shared/components/LoginComponents.tsx b/web/packages/shared/components/LoginComponents.tsx index 4f0366a834..7ba8e7ae80 100644 --- a/web/packages/shared/components/LoginComponents.tsx +++ b/web/packages/shared/components/LoginComponents.tsx @@ -207,7 +207,7 @@ export const sessionExpiredDialogAttributes = ( onLogin: () => void, ): MiniDialogAttributes => ({ title: t("SESSION_EXPIRED"), - content: t("SESSION_EXPIRED_MESSAGE"), + message: t("SESSION_EXPIRED_MESSAGE"), nonClosable: true, proceed: { text: t("login"), @@ -222,5 +222,5 @@ export const sessionExpiredDialogAttributes = ( const genericErrorAttributes = (): MiniDialogAttributes => ({ title: t("error"), close: { variant: "critical" }, - content: t("generic_error_retry"), + message: t("generic_error_retry"), }); From a0ecc943d4e9cdab8fcb82b110830e9d195f54b5 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 12:22:02 +0530 Subject: [PATCH 157/438] Fix --- web/apps/auth/src/pages/_app.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/apps/auth/src/pages/_app.tsx b/web/apps/auth/src/pages/_app.tsx index b2cffcd165..f11505073f 100644 --- a/web/apps/auth/src/pages/_app.tsx +++ b/web/apps/auth/src/pages/_app.tsx @@ -4,7 +4,7 @@ import { clientPackageName, staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; import { type MiniDialogAttributes, - MiniDialog, + AttributedMiniDialog, } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; @@ -134,7 +134,7 @@ const App: React.FC = ({ Component, pageProps }) => { setDialogBoxAttributesV2({ title: t("error"), close: { variant: "critical" }, - content: t("generic_error_retry"), + message: t("generic_error_retry"), }); const logout = () => { @@ -167,7 +167,7 @@ const App: React.FC = ({ Component, pageProps }) => { - Date: Thu, 10 Oct 2024 12:39:50 +0530 Subject: [PATCH 158/438] wip: checkpoint --- web/packages/base/components/MiniDialog.tsx | 50 +++++++++++-------- .../shared/components/LoginComponents.tsx | 4 +- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index 369b150424..a946bc3eeb 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -52,44 +52,50 @@ export interface MiniDialogAttributes { */ nonClosable?: boolean; /** - * Customize the primary action button offered by the dialog box. + * Customize the primary action button shown in the dialog. * * This is provided by boxes which serve as some sort of confirmation. For * dialogs which are informational notifications, this is usually skipped, * only the {@link close} action button is configured. */ - proceed?: { - /** The string to use as the label for the primary action button. */ - text: string; - /** The color of the button. */ - variant?: ButtonProps["color"]; + continue?: { /** - * The function to call when the user presses the primary action button. + * The string to use as the label for the primary action button. + * + * Default is `t("ok")`. + */ + text?: string; + /** + * The color of the button. + * + * Default is "accent". + */ + color?: ButtonProps["color"]; + /** + * If `true`, the primary action button is auto focused when the dialog + * is opened, allowing the user to confirm just by pressing ENTER. + */ + autoFocus?: boolean; + /** + * The function to call when the user activates the button. + * + * Default is to close the dialog. * * It is passed a {@link setLoading} function that can be used to show * or hide loading indicator or the primary action button. */ - action: + action?: | (() => void | Promise) | ((setLoading: (value: boolean) => void) => void | Promise); }; /** - * Customize the cancel (dismiss) action button offered by the dialog box. + * The string to use as the label for the cancel button. * - * Usually all dialog boxes should have a cancel action. + * Default is `t("cancel")`. + * + * Set this to `false` to omit the cancel button altogether. */ - close?: { - /** The string to use as the label for the cancel button. */ - text?: string; - /** The color of the button. */ - variant?: ButtonProps["color"]; - /** - * The function to call when the user cancels. - * - * If provided, this callback is invoked before closing the dialog. - */ - action?: () => void; - }; + cancel?: string | false; /** The direction in which the buttons are stacked. Default is "column". */ buttonDirection?: "row" | "column"; } diff --git a/web/packages/shared/components/LoginComponents.tsx b/web/packages/shared/components/LoginComponents.tsx index 7ba8e7ae80..652900ab60 100644 --- a/web/packages/shared/components/LoginComponents.tsx +++ b/web/packages/shared/components/LoginComponents.tsx @@ -209,11 +209,11 @@ export const sessionExpiredDialogAttributes = ( title: t("SESSION_EXPIRED"), message: t("SESSION_EXPIRED_MESSAGE"), nonClosable: true, - proceed: { + continue: { text: t("login"), action: onLogin, - variant: "accent", }, + cancel: false, }); /** From 473e22c0c1d6ac86e90be1d0efe50eac9b38fd42 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 12:44:07 +0530 Subject: [PATCH 159/438] wip checkpoint --- web/packages/base/components/MiniDialog.tsx | 85 +++++++++------------ 1 file changed, 36 insertions(+), 49 deletions(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index a946bc3eeb..0744077582 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -4,7 +4,6 @@ /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { LoadingButton } from "@/base/components/mui/LoadingButton"; -import { dialogCloseHandler } from "@ente/shared/components/DialogBox/TitleWithCloseButton"; import type { ButtonProps } from "@mui/material"; import { Box, @@ -122,11 +121,10 @@ export const AttributedMiniDialog: React.FC< return <>; } - const handleClose = dialogCloseHandler({ - staticBackdrop: attributes.staticBackdrop, - nonClosable: attributes.nonClosable, - onClose: onClose, - }); + const handleClose = () => { + if (attributes.nonClosable) return; + onClose(); + }; const { PaperProps, ...rest } = props; @@ -171,49 +169,38 @@ export const AttributedMiniDialog: React.FC<
)} {children} - {(attributes.proceed || attributes.close) && ( - - {attributes.proceed && ( - { - await attributes.proceed?.action( - setLoading, - ); - - onClose(); - }} - > - {attributes.proceed.text} - - )} - {attributes.close && ( - { - attributes.close?.action && - attributes.close?.action(); - onClose(); - }} - > - {attributes.close?.text ?? t("ok")} - - )} - - )} + + {attributes.continue && ( + { + await attributes.continue?.action?.(setLoading); + onClose(); + }} + > + {attributes.continue?.text ?? t("ok")} + + )} + {attributes.cancel && ( + + {attributes.cancel ?? t("cancel")} + + )} + ); From 8b24225fbbfc9416de41a902affeaaf660cd2b43 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 13:07:34 +0530 Subject: [PATCH 160/438] wip checkpoint --- web/apps/accounts/src/pages/_app.tsx | 25 ++++++++++++------- .../photos/src/components/Sidebar/index.tsx | 6 +---- web/packages/accounts/types/context.ts | 17 ++++++++++--- web/packages/new/photos/types/context.ts | 11 +------- 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/web/apps/accounts/src/pages/_app.tsx b/web/apps/accounts/src/pages/_app.tsx index 02d27bd390..32cdeff553 100644 --- a/web/apps/accounts/src/pages/_app.tsx +++ b/web/apps/accounts/src/pages/_app.tsx @@ -16,7 +16,7 @@ import { CssBaseline } from "@mui/material"; import { ThemeProvider } from "@mui/material/styles"; import { t } from "i18next"; import type { AppProps } from "next/app"; -import React, { useEffect, useState } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { AppContext } from "../types/context"; import "styles/global.css"; @@ -24,10 +24,23 @@ import "styles/global.css"; const App: React.FC = ({ Component, pageProps }) => { const [isI18nReady, setIsI18nReady] = useState(false); const [showNavbar, setShowNavbar] = useState(false); - const [dialogBoxAttributeV2, setDialogBoxAttributesV2] = useState< + + // Mini Dialog scaffolding -- + + const [miniDialogAttributes, setMiniDialogAttributes] = useState< MiniDialogAttributes | undefined >(); - const [dialogBoxV2View, setDialogBoxV2View] = useState(false); + + const [openMiniDialog, setOpenMiniDialog] = useState(false); + + const showMiniDialog = useCallback((attributes: MiniDialogAttributes) => { + setMiniDialogAttributes(attributes); + setOpenMiniDialog(true); + }, []); + + const closeMiniDialog = useCallback(() => setOpenMiniDialog(false), []); + + // -- useEffect(() => { disableDiskLogs(); @@ -36,12 +49,6 @@ const App: React.FC = ({ Component, pageProps }) => { return () => logUnhandledErrorsAndRejections(false); }, []); - useEffect(() => { - setDialogBoxV2View(true); - }, [dialogBoxAttributeV2]); - - const closeDialogBoxV2 = () => setDialogBoxV2View(false); - const appContext = { showNavBar: setShowNavbar, setDialogBoxAttributesV2, diff --git a/web/apps/photos/src/components/Sidebar/index.tsx b/web/apps/photos/src/components/Sidebar/index.tsx index 0275a1f92a..6f54c88582 100644 --- a/web/apps/photos/src/components/Sidebar/index.tsx +++ b/web/apps/photos/src/components/Sidebar/index.tsx @@ -682,14 +682,10 @@ const DebugSection: React.FC = () => { showMiniDialog({ title: t("DOWNLOAD_LOGS"), message: , - proceed: { + continue: { text: t("download"), - variant: "accent", action: downloadLogs, }, - close: { - text: t("cancel"), - }, }); const downloadLogs = () => { diff --git a/web/packages/accounts/types/context.ts b/web/packages/accounts/types/context.ts index ae9fd7b9b6..d625db096c 100644 --- a/web/packages/accounts/types/context.ts +++ b/web/packages/accounts/types/context.ts @@ -5,9 +5,20 @@ import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; * defer to the pages provided by the accounts package. */ export interface AccountsContextT { - /** Perform the (possibly app specific) logout sequence. */ + /** + * Perform the (possibly app specific) logout sequence. + */ logout: () => void; - /** Show or hide the app's navigation bar. */ + /** + * Show or hide the app's navigation bar. + */ showNavBar: (show: boolean) => void; - setDialogBoxAttributesV2: (attrs: MiniDialogAttributes) => void; + /** + * Show a "mini dialog" with the given attributes. + * + * Mini dialogs (see {@link AttributedMiniDialog}) are meant for simple + * confirmation or notications. Their appearance and functionality can be + * customized by providing appropriate {@link MiniDialogAttributes}. + */ + showMiniDialog: (attributes: MiniDialogAttributes) => void; } diff --git a/web/packages/new/photos/types/context.ts b/web/packages/new/photos/types/context.ts index 4c11a9bb01..993bab29e5 100644 --- a/web/packages/new/photos/types/context.ts +++ b/web/packages/new/photos/types/context.ts @@ -4,7 +4,6 @@ import type { SetDialogBoxAttributes } from "@ente/shared/components/DialogBox/t import { THEME_COLOR } from "@ente/shared/themes/constants"; import { createContext, useContext } from "react"; import type { SetNotificationAttributes } from "./notification"; -import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; /** * The type of the React context available to all pages in the photos app. @@ -18,18 +17,10 @@ export type AppContextT = AccountsContextT & { * Hide the global activity indicator. */ finishLoading: () => void; - /** - * Show a "mini dialog" with the given attributes. - * - * Mini dialogs (see {@link AttributedMiniDialog}) are meant for simple - * confirmation or notication dialogs. Their appearance and functionality - * can be customized by providing relevant {@link MiniDialogAttributes}. - */ - showMiniDialog: (attributes: MiniDialogAttributes) => void; + onGenericError: (error: unknown) => void; somethingWentWrong: () => void; setDialogMessage: SetDialogBoxAttributes; setNotificationAttributes: SetNotificationAttributes; - onGenericError: (error: unknown) => void; closeMessageDialog: () => void; mapEnabled: boolean; updateMapEnabled: (enabled: boolean) => Promise; From 88c10db52d7cc2d6f89c5abd4b74707261f5733f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 14:18:34 +0530 Subject: [PATCH 161/438] Create helper hook --- web/apps/accounts/src/pages/_app.tsx | 43 ++++++------------- web/apps/accounts/src/types/context.ts | 8 +--- web/packages/base/components/MiniDialog.tsx | 20 --------- .../base/components/hooks/use-mini-dialog.ts | 31 +++++++++++++ 4 files changed, 45 insertions(+), 57 deletions(-) create mode 100644 web/packages/base/components/hooks/use-mini-dialog.ts diff --git a/web/apps/accounts/src/pages/_app.tsx b/web/apps/accounts/src/pages/_app.tsx index 32cdeff553..87a1008602 100644 --- a/web/apps/accounts/src/pages/_app.tsx +++ b/web/apps/accounts/src/pages/_app.tsx @@ -1,9 +1,7 @@ import { staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; -import { - type MiniDialogAttributes, - AttributedMiniDialog, -} from "@/base/components/MiniDialog"; +import { useAttributedMiniDialog } from "@/base/components/hooks/use-mini-dialog"; +import { AttributedMiniDialog } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; import { setupI18n } from "@/base/i18n"; @@ -16,7 +14,7 @@ import { CssBaseline } from "@mui/material"; import { ThemeProvider } from "@mui/material/styles"; import { t } from "i18next"; import type { AppProps } from "next/app"; -import React, { useCallback, useEffect, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import { AppContext } from "../types/context"; import "styles/global.css"; @@ -24,23 +22,7 @@ import "styles/global.css"; const App: React.FC = ({ Component, pageProps }) => { const [isI18nReady, setIsI18nReady] = useState(false); const [showNavbar, setShowNavbar] = useState(false); - - // Mini Dialog scaffolding -- - - const [miniDialogAttributes, setMiniDialogAttributes] = useState< - MiniDialogAttributes | undefined - >(); - - const [openMiniDialog, setOpenMiniDialog] = useState(false); - - const showMiniDialog = useCallback((attributes: MiniDialogAttributes) => { - setMiniDialogAttributes(attributes); - setOpenMiniDialog(true); - }, []); - - const closeMiniDialog = useCallback(() => setOpenMiniDialog(false), []); - - // -- + const { showMiniDialog, miniDialogProps } = useAttributedMiniDialog(); useEffect(() => { disableDiskLogs(); @@ -49,10 +31,13 @@ const App: React.FC = ({ Component, pageProps }) => { return () => logUnhandledErrorsAndRejections(false); }, []); - const appContext = { - showNavBar: setShowNavbar, - setDialogBoxAttributesV2, - }; + const appContext = useMemo( + () => ({ + showNavBar: setShowNavbar, + showMiniDialog, + }), + [showMiniDialog], + ); const title = isI18nReady ? t("title_accounts") : staticAppTitle; @@ -62,11 +47,7 @@ const App: React.FC = ({ Component, pageProps }) => { - + {!isI18nReady && ( diff --git a/web/apps/accounts/src/types/context.ts b/web/apps/accounts/src/types/context.ts index e095490524..dece58358d 100644 --- a/web/apps/accounts/src/types/context.ts +++ b/web/apps/accounts/src/types/context.ts @@ -1,15 +1,11 @@ -import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; +import type { AccountsContextT } from "@/accounts/types/context"; import { ensure } from "@/utils/ensure"; import { createContext, useContext } from "react"; /** * The type of the context for pages in the accounts app. */ -interface AppContextT { - /** Show or hide the app's navigation bar. */ - showNavBar: (show: boolean) => void; - setDialogBoxAttributesV2: (attrs: MiniDialogAttributes) => void; -} +type AppContextT = Omit; /** * The React {@link Context} available to all nodes in the React tree. diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index 0744077582..dcf0a53239 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -206,26 +206,6 @@ export const AttributedMiniDialog: React.FC< ); }; -// TODO: Sketch of a possible approach to using this. Haven't throught this -// through, just noting down the outline inspired by an API I saw. -// /** -// * A React hook for simplifying use of MiniDialog within the photos app context. -// * -// * It relies on the presence of the {@link setDialogBoxAttributesV2} function -// * provided by the Photos app's {@link AppContext}. -// */ -// export const useConfirm = (attr) => { -// const {setDialogBoxAttributesV2} = useAppContext(); -// return () => { -// new Promise((resolve) => { -// setDialogBoxAttributesV2( -// proceed: { -// action: attr.action.then(resolve) -// } -// ) -// } -// } - type TitledMiniDialogProps = Omit & { onClose: () => void; /** diff --git a/web/packages/base/components/hooks/use-mini-dialog.ts b/web/packages/base/components/hooks/use-mini-dialog.ts new file mode 100644 index 0000000000..8ac74536a0 --- /dev/null +++ b/web/packages/base/components/hooks/use-mini-dialog.ts @@ -0,0 +1,31 @@ +import { useCallback, useState } from "react"; +import type { MiniDialogAttributes } from "../MiniDialog"; + +/** + * A React hook for simplifying the provisioning of a {@link showMiniDialog} + * function to inject in app contexts, and the other props that are needed for + * to pass on to the {@link AttributedMiniDialog}. + */ +export const useAttributedMiniDialog = () => { + const [miniDialogAttributes, setMiniDialogAttributes] = useState< + MiniDialogAttributes | undefined + >(); + + const [openMiniDialog, setOpenMiniDialog] = useState(false); + + const showMiniDialog = useCallback((attributes: MiniDialogAttributes) => { + setMiniDialogAttributes(attributes); + setOpenMiniDialog(true); + }, []); + + const onCloseMiniDialog = useCallback(() => setOpenMiniDialog(false), []); + + return { + showMiniDialog, + miniDialogProps: { + open: openMiniDialog, + onClose: onCloseMiniDialog, + attributes: miniDialogAttributes, + }, + }; +}; From 68e7a38463a08ae0ea1680515066c786642b1ec6 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 14:37:06 +0530 Subject: [PATCH 162/438] Another helper --- web/apps/accounts/src/pages/_app.tsx | 2 +- .../accounts/src/pages/passkeys/index.tsx | 8 +++--- .../use-mini-dialog.tsx} | 28 +++++++++++++++++++ web/packages/build-config/eslintrc-react.js | 5 ++++ 4 files changed, 38 insertions(+), 5 deletions(-) rename web/packages/base/components/{hooks/use-mini-dialog.ts => utils/use-mini-dialog.tsx} (55%) diff --git a/web/apps/accounts/src/pages/_app.tsx b/web/apps/accounts/src/pages/_app.tsx index 87a1008602..36bbcd39ab 100644 --- a/web/apps/accounts/src/pages/_app.tsx +++ b/web/apps/accounts/src/pages/_app.tsx @@ -1,9 +1,9 @@ import { staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; -import { useAttributedMiniDialog } from "@/base/components/hooks/use-mini-dialog"; import { AttributedMiniDialog } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; +import { useAttributedMiniDialog } from "@/base/hooks/use-mini-dialog"; import { setupI18n } from "@/base/i18n"; import { disableDiskLogs } from "@/base/log"; import { logUnhandledErrorsAndRejections } from "@/base/log-web"; diff --git a/web/apps/accounts/src/pages/passkeys/index.tsx b/web/apps/accounts/src/pages/passkeys/index.tsx index d365af0b6d..c909602910 100644 --- a/web/apps/accounts/src/pages/passkeys/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/index.tsx @@ -34,7 +34,7 @@ import { import { useAppContext } from "../../types/context"; const Page: React.FC = () => { - const { showNavBar, setDialogBoxAttributesV2 } = useAppContext(); + const { showNavBar, showMiniDialog } = useAppContext(); const [token, setToken] = useState(); const [passkeys, setPasskeys] = useState([]); @@ -44,12 +44,12 @@ const Page: React.FC = () => { >(); const showPasskeyFetchFailedErrorDialog = useCallback(() => { - setDialogBoxAttributesV2({ + showMiniDialog({ title: t("error"), message: t("passkey_fetch_failed"), - close: {}, + cancel: false, }); - }, [setDialogBoxAttributesV2]); + }, [showMiniDialog]); useEffect(() => { showNavBar(true); diff --git a/web/packages/base/components/hooks/use-mini-dialog.ts b/web/packages/base/components/utils/use-mini-dialog.tsx similarity index 55% rename from web/packages/base/components/hooks/use-mini-dialog.ts rename to web/packages/base/components/utils/use-mini-dialog.tsx index 8ac74536a0..cad7a557f2 100644 --- a/web/packages/base/components/hooks/use-mini-dialog.ts +++ b/web/packages/base/components/utils/use-mini-dialog.tsx @@ -1,3 +1,5 @@ +import ErrorOutline from "@mui/icons-material/ErrorOutline"; +import { t } from "i18next"; import { useCallback, useState } from "react"; import type { MiniDialogAttributes } from "../MiniDialog"; @@ -29,3 +31,29 @@ export const useAttributedMiniDialog = () => { }, }; }; + +/** + * A convenience function to construct {@link MiniDialogAttributes} for showing + * error dialogs. + * + * It takes one or two arguments. + * + * - If both are provided, then the first one is taken as the title and the + * second one as the message. + * + * - Otherwise it sets a default title and use the only argument as the message. + */ +export const errorAttributes = ( + messageOrTitle: string, + optionalMessage?: string, +): MiniDialogAttributes => { + const title = optionalMessage ? messageOrTitle : t("error"); + const message = optionalMessage ? optionalMessage : messageOrTitle; + + return { + title, + icon: , + message, + continue: { color: "critical" }, + }; +}; diff --git a/web/packages/build-config/eslintrc-react.js b/web/packages/build-config/eslintrc-react.js index 571d37e622..098403b08b 100644 --- a/web/packages/build-config/eslintrc-react.js +++ b/web/packages/build-config/eslintrc-react.js @@ -13,9 +13,14 @@ module.exports = { "react/jsx-no-target-blank": ["warn", { allowReferrer: true }], /* Otherwise we need to do unnecessary boilerplating when using memo. */ "react/display-name": "off", + /* Apparently Fast refresh only works if a file only exports components, + and this rule warns about that. Constants are okay though (otherwise + we'll need to create unnecessary helper files). */ "react-refresh/only-export-components": [ "warn", { allowConstantExport: true }, ], + /* Next.js supports the JSX transform introduced in React 17 */ + "react/react-in-jsx-scope": "off", }, }; From 79eb912a420d2619481f9cfcf27b0d0b9661184d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 14:41:30 +0530 Subject: [PATCH 163/438] Fin apps/accounts --- web/apps/accounts/src/pages/_app.tsx | 2 +- .../accounts/src/pages/passkeys/index.tsx | 19 ++++++++----------- .../{use-mini-dialog.tsx => mini-dialog.tsx} | 2 +- 3 files changed, 10 insertions(+), 13 deletions(-) rename web/packages/base/components/utils/{use-mini-dialog.tsx => mini-dialog.tsx} (98%) diff --git a/web/apps/accounts/src/pages/_app.tsx b/web/apps/accounts/src/pages/_app.tsx index 36bbcd39ab..49e9739ea1 100644 --- a/web/apps/accounts/src/pages/_app.tsx +++ b/web/apps/accounts/src/pages/_app.tsx @@ -3,7 +3,7 @@ import { CustomHead } from "@/base/components/Head"; import { AttributedMiniDialog } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; -import { useAttributedMiniDialog } from "@/base/hooks/use-mini-dialog"; +import { useAttributedMiniDialog } from "@/base/components/utils/mini-dialog"; import { setupI18n } from "@/base/i18n"; import { disableDiskLogs } from "@/base/log"; import { logUnhandledErrorsAndRejections } from "@/base/log-web"; diff --git a/web/apps/accounts/src/pages/passkeys/index.tsx b/web/apps/accounts/src/pages/passkeys/index.tsx index c909602910..3b6f6af2d2 100644 --- a/web/apps/accounts/src/pages/passkeys/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/index.tsx @@ -1,6 +1,7 @@ import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemDivider, MenuItemGroup } from "@/base/components/Menu"; import { Titlebar } from "@/base/components/Titlebar"; +import { mdErrorAttributes } from "@/base/components/utils/mini-dialog"; import log from "@/base/log"; import { ensure } from "@/utils/ensure"; import { CenteredFlex } from "@ente/shared/components/Container"; @@ -44,11 +45,7 @@ const Page: React.FC = () => { >(); const showPasskeyFetchFailedErrorDialog = useCallback(() => { - showMiniDialog({ - title: t("error"), - message: t("passkey_fetch_failed"), - cancel: false, - }); + showMiniDialog(mdErrorAttributes(t("passkey_fetch_failed"))); }, [showMiniDialog]); useEffect(() => { @@ -263,11 +260,12 @@ const ManagePasskeyDrawer: React.FC = ({ passkey, onUpdateOrDeletePasskey, }) => { - const { setDialogBoxAttributesV2 } = useAppContext(); + const { showMiniDialog } = useAppContext(); const [showRenameDialog, setShowRenameDialog] = useState(false); const showDeleteConfirmationDialog = useCallback(() => { + /* mark: uses-loading */ const handleDelete = async (setLoading: (value: boolean) => void) => { setLoading(true); try { @@ -280,17 +278,16 @@ const ManagePasskeyDrawer: React.FC = ({ } }; - setDialogBoxAttributesV2({ + showMiniDialog({ title: t("delete_passkey"), message: t("delete_passkey_confirmation"), - proceed: { + continue: { text: t("delete"), + color: "critical", action: handleDelete, - variant: "critical", }, - close: { text: t("cancel") }, }); - }, [token, passkey, onUpdateOrDeletePasskey, setDialogBoxAttributesV2]); + }, [showMiniDialog, token, passkey, onUpdateOrDeletePasskey]); return ( <> diff --git a/web/packages/base/components/utils/use-mini-dialog.tsx b/web/packages/base/components/utils/mini-dialog.tsx similarity index 98% rename from web/packages/base/components/utils/use-mini-dialog.tsx rename to web/packages/base/components/utils/mini-dialog.tsx index cad7a557f2..0b81aea53b 100644 --- a/web/packages/base/components/utils/use-mini-dialog.tsx +++ b/web/packages/base/components/utils/mini-dialog.tsx @@ -43,7 +43,7 @@ export const useAttributedMiniDialog = () => { * * - Otherwise it sets a default title and use the only argument as the message. */ -export const errorAttributes = ( +export const mdErrorAttributes = ( messageOrTitle: string, optionalMessage?: string, ): MiniDialogAttributes => { From 03e5e16bc3307e53ad33975784a11827d38af574 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 15:00:28 +0530 Subject: [PATCH 164/438] Move --- .../components/LoginComponents.tsx | 8 ++++---- web/packages/accounts/pages/credentials.tsx | 12 ++++++------ web/packages/accounts/pages/verify.tsx | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) rename web/packages/{shared => accounts}/components/LoginComponents.tsx (96%) diff --git a/web/packages/shared/components/LoginComponents.tsx b/web/packages/accounts/components/LoginComponents.tsx similarity index 96% rename from web/packages/shared/components/LoginComponents.tsx rename to web/packages/accounts/components/LoginComponents.tsx index 652900ab60..a1b5158bda 100644 --- a/web/packages/shared/components/LoginComponents.tsx +++ b/web/packages/accounts/components/LoginComponents.tsx @@ -7,14 +7,14 @@ import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import log from "@/base/log"; import { customAPIHost } from "@/base/origins"; +import { VerticallyCentered } from "@ente/shared/components/Container"; +import FormPaper from "@ente/shared/components/Form/FormPaper"; +import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer"; +import LinkButton from "@ente/shared/components/LinkButton"; import { CircularProgress, Stack, Typography, styled } from "@mui/material"; import { t } from "i18next"; import { useRouter } from "next/router"; import React, { useEffect, useState } from "react"; -import { VerticallyCentered } from "./Container"; -import FormPaper from "./Form/FormPaper"; -import FormPaperFooter from "./Form/FormPaper/Footer"; -import LinkButton from "./LinkButton"; export const PasswordHeader: React.FC = ({ children, diff --git a/web/packages/accounts/pages/credentials.tsx b/web/packages/accounts/pages/credentials.tsx index 5ffb93b73b..ca8245258f 100644 --- a/web/packages/accounts/pages/credentials.tsx +++ b/web/packages/accounts/pages/credentials.tsx @@ -7,12 +7,6 @@ import { ensure } from "@/utils/ensure"; import { VerticallyCentered } from "@ente/shared/components/Container"; import FormPaper from "@ente/shared/components/Form/FormPaper"; import LinkButton from "@ente/shared/components/LinkButton"; -import { - LoginFlowFormFooter, - PasswordHeader, - VerifyingPasskey, - sessionExpiredDialogAttributes, -} from "@ente/shared/components/LoginComponents"; import VerifyMasterPasswordForm, { type VerifyMasterPasswordFormProps, } from "@ente/shared/components/VerifyMasterPasswordForm"; @@ -46,6 +40,12 @@ import { t } from "i18next"; import { useRouter } from "next/router"; import { useCallback, useEffect, useState } from "react"; import { getSRPAttributes } from "../api/srp"; +import { + LoginFlowFormFooter, + PasswordHeader, + VerifyingPasskey, + sessionExpiredDialogAttributes, +} from "../components/LoginComponents"; import { PAGES } from "../constants/pages"; import { openPasskeyVerificationURL, diff --git a/web/packages/accounts/pages/verify.tsx b/web/packages/accounts/pages/verify.tsx index 860459d3c9..c3b334cdd7 100644 --- a/web/packages/accounts/pages/verify.tsx +++ b/web/packages/accounts/pages/verify.tsx @@ -6,10 +6,6 @@ import { VerticallyCentered } from "@ente/shared/components/Container"; import FormPaper from "@ente/shared/components/Form/FormPaper"; import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title"; import LinkButton from "@ente/shared/components/LinkButton"; -import { - LoginFlowFormFooter, - VerifyingPasskey, -} from "@ente/shared/components/LoginComponents"; import SingleInputForm, { type SingleInputFormProps, } from "@ente/shared/components/SingleInputForm"; @@ -35,6 +31,10 @@ import { useEffect, useState } from "react"; import { Trans } from "react-i18next"; import { getSRPAttributes } from "../api/srp"; import { putAttributes, sendOtt, verifyOtt } from "../api/user"; +import { + LoginFlowFormFooter, + VerifyingPasskey, +} from "../components/LoginComponents"; import { PAGES } from "../constants/pages"; import { openPasskeyVerificationURL, From 6b64e20a7ea5405e88853342ad2ec6b3ae1c3d58 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 15:22:21 +0530 Subject: [PATCH 165/438] Move --- .../accounts/src/pages/passkeys/index.tsx | 4 ++-- .../accounts/components/LoginComponents.tsx | 19 +++++-------------- .../base/components/utils/mini-dialog.tsx | 5 ++++- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/web/apps/accounts/src/pages/passkeys/index.tsx b/web/apps/accounts/src/pages/passkeys/index.tsx index 3b6f6af2d2..fb9f591ad5 100644 --- a/web/apps/accounts/src/pages/passkeys/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/index.tsx @@ -1,7 +1,7 @@ import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemDivider, MenuItemGroup } from "@/base/components/Menu"; import { Titlebar } from "@/base/components/Titlebar"; -import { mdErrorAttributes } from "@/base/components/utils/mini-dialog"; +import { errorDialogAttributes } from "@/base/components/utils/mini-dialog"; import log from "@/base/log"; import { ensure } from "@/utils/ensure"; import { CenteredFlex } from "@ente/shared/components/Container"; @@ -45,7 +45,7 @@ const Page: React.FC = () => { >(); const showPasskeyFetchFailedErrorDialog = useCallback(() => { - showMiniDialog(mdErrorAttributes(t("passkey_fetch_failed"))); + showMiniDialog(errorDialogAttributes(t("passkey_fetch_failed"))); }, [showMiniDialog]); useEffect(() => { diff --git a/web/packages/accounts/components/LoginComponents.tsx b/web/packages/accounts/components/LoginComponents.tsx index a1b5158bda..b7bdb675c3 100644 --- a/web/packages/accounts/components/LoginComponents.tsx +++ b/web/packages/accounts/components/LoginComponents.tsx @@ -5,6 +5,7 @@ import { } from "@/accounts/services/passkey"; import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; +import { genericErrorDialogAttributes } from "@/base/components/utils/mini-dialog"; import log from "@/base/log"; import { customAPIHost } from "@/base/origins"; import { VerticallyCentered } from "@ente/shared/components/Container"; @@ -108,7 +109,7 @@ export const VerifyingPasskey: React.FC = ({ e instanceof Error && e.message == passkeySessionExpiredErrorMessage ? sessionExpiredDialogAttributes(logout) - : genericErrorAttributes(), + : genericErrorDialogAttributes(), ); setVerificationStatus("waiting"); } @@ -194,11 +195,10 @@ const ButtonStack = styled("div")` `; /** - * {@link DialogBoxAttributesV2} for showing the error when the user's session - * has expired. + * {@link MiniDialogAttributes} for showing asking the user to login again when + * their session has expired. * - * It asks them to login again. There is one button, which allows them to - * logout. + * There is one button, which allows them to logout. * * @param onLogin Called when the user presses the "Login" button on the error * dialog. @@ -215,12 +215,3 @@ export const sessionExpiredDialogAttributes = ( }, cancel: false, }); - -/** - * {@link DialogBoxAttributesV2} for showing a generic error. - */ -const genericErrorAttributes = (): MiniDialogAttributes => ({ - title: t("error"), - close: { variant: "critical" }, - message: t("generic_error_retry"), -}); diff --git a/web/packages/base/components/utils/mini-dialog.tsx b/web/packages/base/components/utils/mini-dialog.tsx index 0b81aea53b..088e8511f2 100644 --- a/web/packages/base/components/utils/mini-dialog.tsx +++ b/web/packages/base/components/utils/mini-dialog.tsx @@ -43,7 +43,7 @@ export const useAttributedMiniDialog = () => { * * - Otherwise it sets a default title and use the only argument as the message. */ -export const mdErrorAttributes = ( +export const errorDialogAttributes = ( messageOrTitle: string, optionalMessage?: string, ): MiniDialogAttributes => { @@ -57,3 +57,6 @@ export const mdErrorAttributes = ( continue: { color: "critical" }, }; }; + +export const genericErrorDialogAttributes = () => + errorDialogAttributes(t("generic_error")); From d6a39ae45262364e5979ba63d09a20b5f334c374 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 15:27:31 +0530 Subject: [PATCH 166/438] wip checkpoint --- web/apps/auth/src/pages/_app.tsx | 37 +++++---------- web/apps/auth/src/pages/auth.tsx | 6 +-- .../src/components/AuthenticateUserModal.tsx | 11 ++--- .../src/components/DeleteAccountModal.tsx | 31 +++++-------- .../components/PhotoViewer/FileInfo/index.tsx | 45 +++++++++++++++---- web/apps/photos/src/utils/ui/index.tsx | 40 +---------------- .../accounts/components/LoginComponents.tsx | 6 +-- web/packages/accounts/pages/credentials.tsx | 8 ++-- web/packages/accounts/pages/verify.tsx | 4 +- 9 files changed, 75 insertions(+), 113 deletions(-) diff --git a/web/apps/auth/src/pages/_app.tsx b/web/apps/auth/src/pages/_app.tsx index f11505073f..e18b0684ff 100644 --- a/web/apps/auth/src/pages/_app.tsx +++ b/web/apps/auth/src/pages/_app.tsx @@ -2,12 +2,13 @@ import { accountLogout } from "@/accounts/services/logout"; import type { AccountsContextT } from "@/accounts/types/context"; import { clientPackageName, staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; -import { - type MiniDialogAttributes, - AttributedMiniDialog, -} from "@/base/components/MiniDialog"; +import { AttributedMiniDialog } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; +import { + genericErrorDialogAttributes, + useAttributedMiniDialog, +} from "@/base/components/utils/mini-dialog"; import { setupI18n } from "@/base/i18n"; import { logStartupBanner, @@ -39,6 +40,7 @@ import React, { useState, } from "react"; import LoadingBar, { type LoadingBarRef } from "react-top-loading-bar"; + import "../../public/css/global.css"; /** @@ -68,10 +70,8 @@ const App: React.FC = ({ Component, pageProps }) => { const [showNavbar, setShowNavBar] = useState(false); const isLoadingBarRunning = useRef(false); const loadingBar = useRef(null); - const [dialogBoxAttributeV2, setDialogBoxAttributesV2] = useState< - MiniDialogAttributes | undefined - >(); - const [dialogBoxV2View, setDialogBoxV2View] = useState(false); + + const { showMiniDialog, miniDialogProps } = useAttributedMiniDialog(); const [themeColor, setThemeColor] = useLocalState( LS_KEYS.THEME, THEME_COLOR.DARK, @@ -111,16 +111,13 @@ const App: React.FC = ({ Component, pageProps }) => { }; }, []); - useEffect(() => { - setDialogBoxV2View(true); - }, [dialogBoxAttributeV2]); - const showNavBar = (show: boolean) => setShowNavBar(show); const startLoading = () => { !isLoadingBarRunning.current && loadingBar.current?.continuousStart(); isLoadingBarRunning.current = true; }; + const finishLoading = () => { setTimeout(() => { isLoadingBarRunning.current && loadingBar.current?.complete(); @@ -128,14 +125,8 @@ const App: React.FC = ({ Component, pageProps }) => { }, 100); }; - const closeDialogBoxV2 = () => setDialogBoxV2View(false); - const somethingWentWrong = () => - setDialogBoxAttributesV2({ - title: t("error"), - close: { variant: "critical" }, - message: t("generic_error_retry"), - }); + showMiniDialog(genericErrorDialogAttributes()); const logout = () => { void accountLogout().then(() => router.push("/")); @@ -144,7 +135,7 @@ const App: React.FC = ({ Component, pageProps }) => { const appContext = { logout, showNavBar, - setDialogBoxAttributesV2, + showMiniDialog, startLoading, finishLoading, themeColor, @@ -167,11 +158,7 @@ const App: React.FC = ({ Component, pageProps }) => { - + {(loading || !isI18nReady) && ( diff --git a/web/apps/auth/src/pages/auth.tsx b/web/apps/auth/src/pages/auth.tsx index 917808bd83..6fb996cf3f 100644 --- a/web/apps/auth/src/pages/auth.tsx +++ b/web/apps/auth/src/pages/auth.tsx @@ -1,3 +1,4 @@ +import { sessionExpiredDialogAttributes } from "@/accounts/components/LoginComponents"; import { stashRedirect } from "@/accounts/services/redirect"; import { EnteLogo } from "@/base/components/EnteLogo"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; @@ -7,7 +8,6 @@ import { HorizontalFlex, VerticallyCentered, } from "@ente/shared/components/Container"; -import { sessionExpiredDialogAttributes } from "@ente/shared/components/LoginComponents"; import OverflowMenu from "@ente/shared/components/OverflowMenu/menu"; import { OverflowMenuOption } from "@ente/shared/components/OverflowMenu/option"; import { AUTH_PAGES as PAGES } from "@ente/shared/constants/pages"; @@ -23,7 +23,7 @@ import { getAuthCodes } from "services/remote"; import { AppContext } from "./_app"; const Page: React.FC = () => { - const { logout, showNavBar, setDialogBoxAttributesV2 } = ensure( + const { logout, showNavBar, showMiniDialog } = ensure( useContext(AppContext), ); const router = useRouter(); @@ -32,7 +32,7 @@ const Page: React.FC = () => { const [searchTerm, setSearchTerm] = useState(""); const showSessionExpiredDialog = () => - setDialogBoxAttributesV2(sessionExpiredDialogAttributes(logout)); + showMiniDialog(sessionExpiredDialogAttributes(logout)); useEffect(() => { const fetchCodes = async () => { diff --git a/web/apps/photos/src/components/AuthenticateUserModal.tsx b/web/apps/photos/src/components/AuthenticateUserModal.tsx index 0b6a83b7f9..6f17a61bc7 100644 --- a/web/apps/photos/src/components/AuthenticateUserModal.tsx +++ b/web/apps/photos/src/components/AuthenticateUserModal.tsx @@ -24,8 +24,7 @@ export default function AuthenticateUserModal({ onClose, onAuthenticate, }: Iprops) { - const { setDialogMessage, setDialogBoxAttributesV2, logout } = - useContext(AppContext); + const { setDialogMessage, showMiniDialog, logout } = useContext(AppContext); const [user, setUser] = useState(); const [keyAttributes, setKeyAttributes] = useState(); @@ -46,7 +45,7 @@ export default function AuthenticateUserModal({ const session = await checkSessionValidity(); if (session.status != "valid") { onClose(); - setDialogBoxAttributesV2( + showMiniDialog( passwordChangedElsewhereDialogAttributes(logout), ); } @@ -55,7 +54,7 @@ export default function AuthenticateUserModal({ // potentially transient issues. log.warn("Ignoring error when determining session validity", e); } - }, [setDialogBoxAttributesV2, logout]); + }, [showMiniDialog, logout]); useEffect(() => { const main = async () => { @@ -127,10 +126,8 @@ const passwordChangedElsewhereDialogAttributes = ( ): MiniDialogAttributes => ({ title: t("password_changed_elsewhere"), message: t("password_changed_elsewhere_message"), - proceed: { + continue: { text: t("login"), action: onLogin, - variant: "accent", }, - close: { text: t("cancel") }, }); diff --git a/web/apps/photos/src/components/DeleteAccountModal.tsx b/web/apps/photos/src/components/DeleteAccountModal.tsx index 8b75b2a630..82cd039c44 100644 --- a/web/apps/photos/src/components/DeleteAccountModal.tsx +++ b/web/apps/photos/src/components/DeleteAccountModal.tsx @@ -1,7 +1,6 @@ import { TitledMiniDialog } from "@/base/components/MiniDialog"; import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { LoadingButton } from "@/base/components/mui/LoadingButton"; -import log from "@/base/log"; import { AppContext } from "@/new/photos/types/context"; import { initiateEmail } from "@/new/photos/utils/web"; import { Link, Stack, useMediaQuery } from "@mui/material"; @@ -28,7 +27,7 @@ interface FormValues { } const DeleteAccountModal = ({ open, onClose }: Iprops) => { - const { setDialogBoxAttributesV2, logout } = useContext(AppContext); + const { showMiniDialog, onGenericError, logout } = useContext(AppContext); const { authenticateUser } = useContext(GalleryContext); const [loading, setLoading] = useState(false); @@ -39,13 +38,6 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { const isMobile = useMediaQuery("(max-width: 428px)"); - const somethingWentWrong = () => - setDialogBoxAttributesV2({ - title: t("error"), - close: { variant: "critical" }, - message: t("generic_error_retry"), - }); - const initiateDelete = async ( { reason, feedback }: FormValues, { setFieldError }: FormikHelpers, @@ -76,30 +68,28 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { askToMailForDeletion(); } } catch (e) { - log.error("Error while initiating account deletion", e); - somethingWentWrong(); + onGenericError(e); } finally { setLoading(false); } }; const confirmAccountDeletion = () => { - setDialogBoxAttributesV2({ + showMiniDialog({ title: t("delete_account"), message: , - proceed: { + continue: { text: t("delete"), + color: "critical", action: solveChallengeAndDeleteAccount, - variant: "critical", }, - close: { text: t("cancel") }, }); }; const askToMailForDeletion = () => { const emailID = "account-deletion@ente.io"; - setDialogBoxAttributesV2({ + showMiniDialog({ title: t("delete_account"), message: ( { values={{ emailID }} /> ), - proceed: { + continue: { text: t("delete"), + color: "critical", action: () => initiateEmail(emailID), - variant: "critical", }, - close: { text: t("cancel") }, }); }; + /* mark: uses-loading */ const solveChallengeAndDeleteAccount = async ( setLoading: (value: boolean) => void, ) => { @@ -129,8 +119,7 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { await deleteAccount(decryptedChallenge, reason, feedback); logout(); } catch (e) { - log.error("solveChallengeAndDeleteAccount failed", e); - somethingWentWrong(); + onGenericError(e); } finally { setLoading(false); } diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx index f558b2e480..9c39ae3f87 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx @@ -1,4 +1,5 @@ import { EnteDrawer } from "@/base/components/EnteDrawer"; +import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { Titlebar } from "@/base/components/Titlebar"; import { EllipsizedTypography } from "@/base/components/Typography"; @@ -53,12 +54,9 @@ import LinkButton from "components/pages/gallery/LinkButton"; import { t } from "i18next"; import { GalleryContext } from "pages/gallery"; import React, { useContext, useEffect, useMemo, useState } from "react"; +import { Trans } from "react-i18next"; import { changeFileName, updateExistingFilePubMetadata } from "utils/file"; import { PublicCollectionGalleryContext } from "utils/publicCollectionGallery"; -import { - getMapDisableConfirmationDialog, - getMapEnableConfirmationDialog, -} from "utils/ui"; import { FileNameEditDialog } from "./FileNameEditDialog"; import InfoItem from "./InfoItem"; import MapBox from "./MapBox"; @@ -101,7 +99,7 @@ export const FileInfo: React.FC = ({ closePhotoViewer, onSelectPerson, }) => { - const { mapEnabled, updateMapEnabled, setDialogBoxAttributesV2 } = + const { mapEnabled, updateMapEnabled, showMiniDialog } = useContext(AppContext); const galleryContext = useContext(GalleryContext); const publicCollectionGalleryContext = useContext( @@ -151,13 +149,13 @@ export const FileInfo: React.FC = ({ }; const openEnableMapConfirmationDialog = () => - setDialogBoxAttributesV2( - getMapEnableConfirmationDialog(() => updateMapEnabled(true)), + showMiniDialog( + confirmEnableMapsDialogAttributes(() => updateMapEnabled(true)), ); const openDisableMapConfirmationDialog = () => - setDialogBoxAttributesV2( - getMapDisableConfirmationDialog(() => updateMapEnabled(false)), + showMiniDialog( + confirmDisableMapsDialogAttributes(() => updateMapEnabled(false)), ); const handleSelectFace = (annotatedFaceID: AnnotatedFaceID) => { @@ -379,6 +377,35 @@ const parseExifInfo = ( return info; }; +const confirmEnableMapsDialogAttributes = ( + onConfirm: () => void, +): MiniDialogAttributes => ({ + title: t("ENABLE_MAPS"), + message: ( + + ), + }} + /> + ), + continue: { text: t("enable"), action: onConfirm }, +}); + +const confirmDisableMapsDialogAttributes = ( + onConfirm: () => void, +): MiniDialogAttributes => ({ + title: t("DISABLE_MAPS"), + message: , + continue: { text: t("disable"), action: onConfirm }, +}); + const FileInfoSidebar = styled((props: DialogProps) => ( ))({ diff --git a/web/apps/photos/src/utils/ui/index.tsx b/web/apps/photos/src/utils/ui/index.tsx index ecd25edb64..4d259f2310 100644 --- a/web/apps/photos/src/utils/ui/index.tsx +++ b/web/apps/photos/src/utils/ui/index.tsx @@ -1,3 +1,4 @@ +import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; import { ensureElectron } from "@/base/electron"; import { AppUpdate } from "@/base/types/ipc"; import { openURL } from "@/new/photos/utils/web"; @@ -136,45 +137,6 @@ export const getSessionExpiredMessage = ( }, }); -export const getMapEnableConfirmationDialog = ( - enableMapHelper, -): DialogBoxAttributes => ({ - title: t("ENABLE_MAPS"), - content: ( - - ), - }} - /> - ), - proceed: { - action: enableMapHelper, - text: t("enable"), - variant: "accent", - }, - close: { text: t("cancel") }, -}); - -export const getMapDisableConfirmationDialog = ( - disableMapHelper, -): DialogBoxAttributes => ({ - title: t("DISABLE_MAPS"), - content: , - proceed: { - action: disableMapHelper, - text: t("disable"), - variant: "accent", - }, - close: { text: t("cancel") }, -}); - export const getEditorCloseConfirmationMessage = ( doClose: () => void, ): DialogBoxAttributes => ({ diff --git a/web/packages/accounts/components/LoginComponents.tsx b/web/packages/accounts/components/LoginComponents.tsx index b7bdb675c3..cece699417 100644 --- a/web/packages/accounts/components/LoginComponents.tsx +++ b/web/packages/accounts/components/LoginComponents.tsx @@ -75,7 +75,7 @@ interface VerifyingPasskeyProps { onRetry: () => void; /** Perform the (possibly app specific) logout sequence. */ logout: () => void; - setDialogBoxAttributesV2: (attrs: MiniDialogAttributes) => void; + showMiniDialog: (attrs: MiniDialogAttributes) => void; } export const VerifyingPasskey: React.FC = ({ @@ -83,7 +83,7 @@ export const VerifyingPasskey: React.FC = ({ email, onRetry, logout, - setDialogBoxAttributesV2, + showMiniDialog, }) => { type VerificationStatus = "waiting" | "checking" | "pending"; const [verificationStatus, setVerificationStatus] = @@ -105,7 +105,7 @@ export const VerifyingPasskey: React.FC = ({ else router.push(await saveCredentialsAndNavigateTo(response)); } catch (e) { log.error("Passkey verification status check failed", e); - setDialogBoxAttributesV2( + showMiniDialog( e instanceof Error && e.message == passkeySessionExpiredErrorMessage ? sessionExpiredDialogAttributes(logout) diff --git a/web/packages/accounts/pages/credentials.tsx b/web/packages/accounts/pages/credentials.tsx index ca8245258f..5287a7fbcf 100644 --- a/web/packages/accounts/pages/credentials.tsx +++ b/web/packages/accounts/pages/credentials.tsx @@ -66,7 +66,7 @@ import type { PageProps } from "../types/page"; import type { SRPAttributes } from "../types/srp"; const Page: React.FC = ({ appContext }) => { - const { logout, showNavBar, setDialogBoxAttributesV2 } = appContext; + const { logout, showNavBar, showMiniDialog } = appContext; const [srpAttributes, setSrpAttributes] = useState(); const [keyAttributes, setKeyAttributes] = useState(); @@ -82,7 +82,7 @@ const Page: React.FC = ({ appContext }) => { const validateSession = useCallback(async () => { const showSessionExpiredDialog = () => - setDialogBoxAttributesV2(sessionExpiredDialogAttributes(logout)); + showMiniDialog(sessionExpiredDialogAttributes(logout)); try { const session = await checkSessionValidity(); @@ -114,7 +114,7 @@ const Page: React.FC = ({ appContext }) => { // potentially transient issues. log.warn("Ignoring error when determining session validity", e); } - }, [setDialogBoxAttributesV2, logout]); + }, [showMiniDialog, logout]); useEffect(() => { const main = async () => { @@ -354,7 +354,7 @@ const Page: React.FC = ({ appContext }) => { onRetry={() => openPasskeyVerificationURL(passkeyVerificationData) } - {...{ logout, setDialogBoxAttributesV2 }} + {...{ logout, showMiniDialog }} /> ); } diff --git a/web/packages/accounts/pages/verify.tsx b/web/packages/accounts/pages/verify.tsx index c3b334cdd7..f11e77f2f8 100644 --- a/web/packages/accounts/pages/verify.tsx +++ b/web/packages/accounts/pages/verify.tsx @@ -46,7 +46,7 @@ import type { PageProps } from "../types/page"; import type { SRPAttributes, SRPSetupAttributes } from "../types/srp"; const Page: React.FC = ({ appContext }) => { - const { logout, showNavBar, setDialogBoxAttributesV2 } = appContext; + const { logout, showNavBar, showMiniDialog } = appContext; const [email, setEmail] = useState(""); const [resend, setResend] = useState(0); @@ -202,7 +202,7 @@ const Page: React.FC = ({ appContext }) => { onRetry={() => openPasskeyVerificationURL(passkeyVerificationData) } - {...{ logout, setDialogBoxAttributesV2 }} + {...{ logout, showMiniDialog }} /> ); } From f9209e212d0cba3d60f08eee51ead68eaaf66418 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 15:44:55 +0530 Subject: [PATCH 167/438] wip checkpoint --- .../PhotoViewer/ImageEditorOverlay/index.tsx | 20 ++++++--- web/apps/photos/src/pages/_app.tsx | 43 +++++-------------- web/apps/photos/src/utils/ui/index.tsx | 15 ------- web/packages/accounts/pages/recover.tsx | 7 +-- .../accounts/pages/two-factor/recover.tsx | 11 +++-- web/packages/base/components/MiniDialog.tsx | 5 +++ 6 files changed, 42 insertions(+), 59 deletions(-) diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx index 02cd636e09..5cdfe0b8a7 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx @@ -4,6 +4,7 @@ import { MenuItemGroup, MenuSectionTitle, } from "@/base/components/Menu"; +import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; import { nameAndExtension } from "@/base/file"; import log from "@/base/log"; import { photosDialogZIndex } from "@/new/photos/components/z-index"; @@ -39,7 +40,6 @@ import type { Dispatch, MutableRefObject, SetStateAction } from "react"; import { createContext, useContext, useEffect, useRef, useState } from "react"; import { getLocalCollections } from "services/collectionService"; import uploadManager from "services/upload/uploadManager"; -import { getEditorCloseConfirmationMessage } from "utils/ui"; import ColoursMenu from "./ColoursMenu"; import CropMenu, { cropRegionOfCanvas, getCropRegionArgs } from "./CropMenu"; import FreehandCropRegion from "./FreehandCropRegion"; @@ -84,7 +84,7 @@ export interface CropBoxProps { } const ImageEditorOverlay = (props: IProps) => { - const appContext = useContext(AppContext); + const { showMiniDialog } = useContext(AppContext); const canvasRef = useRef(null); const originalSizeCanvasRef = useRef(null); @@ -442,9 +442,7 @@ const ImageEditorOverlay = (props: IProps) => { const handleCloseWithConfirmation = () => { if (transformationPerformed || coloursAdjusted) { - appContext.setDialogBoxAttributesV2( - getEditorCloseConfirmationMessage(handleClose), - ); + showMiniDialog(confirmEditorCloseDialogAttributes(handleClose)); } else { handleClose(); } @@ -733,6 +731,18 @@ const ImageEditorOverlay = (props: IProps) => { export default ImageEditorOverlay; +const confirmEditorCloseDialogAttributes = ( + onConfirm: () => void, +): MiniDialogAttributes => ({ + title: t("CONFIRM_EDITOR_CLOSE_MESSAGE"), + message: t("CONFIRM_EDITOR_CLOSE_DESCRIPTION"), + continue: { + text: t("close"), + color: "critical", + action: onConfirm, + }, +}); + /** * Create a new {@link File} with the contents of the given canvas. * diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index 9ecc2eb6b5..3fec77edc3 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -1,9 +1,12 @@ import { clientPackageName, staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; -import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; import { AttributedMiniDialog } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; import { AppNavbar } from "@/base/components/Navbar"; +import { + genericErrorDialogAttributes, + useAttributedMiniDialog, +} from "@/base/components/utils/mini-dialog"; import { setupI18n } from "@/base/i18n"; import log from "@/base/log"; import { @@ -36,7 +39,6 @@ import { getTheme } from "@ente/shared/themes"; import { THEME_COLOR } from "@ente/shared/themes/constants"; import type { User } from "@ente/shared/user/types"; import ArrowForward from "@mui/icons-material/ArrowForward"; -import ErrorOutline from "@mui/icons-material/ErrorOutline"; import { CssBaseline } from "@mui/material"; import { ThemeProvider } from "@mui/material/styles"; import Notification from "components/Notification"; @@ -72,17 +74,15 @@ export default function App({ Component, pageProps }: AppProps) { const isLoadingBarRunning = useRef(false); const loadingBar = useRef(null); const [dialogMessage, setDialogMessage] = useState(); - const [dialogBoxAttributeV2, setDialogBoxAttributesV2] = useState< - MiniDialogAttributes | undefined - >(); const [messageDialogView, setMessageDialogView] = useState(false); - const [dialogBoxV2View, setDialogBoxV2View] = useState(false); const [watchFolderView, setWatchFolderView] = useState(false); const [watchFolderFiles, setWatchFolderFiles] = useState(null); const [notificationView, setNotificationView] = useState(false); const closeNotification = () => setNotificationView(false); const [notificationAttributes, setNotificationAttributes] = useState(null); + + const { showMiniDialog, miniDialogProps } = useAttributedMiniDialog(); const [themeColor, setThemeColor] = useLocalState( LS_KEYS.THEME, THEME_COLOR.DARK, @@ -201,10 +201,6 @@ export default function App({ Component, pageProps }: AppProps) { setMessageDialogView(true); }, [dialogMessage]); - useEffect(() => { - setDialogBoxV2View(true); - }, [dialogBoxAttributeV2]); - useEffect(() => { setNotificationView(true); }, [notificationAttributes]); @@ -236,12 +232,6 @@ export default function App({ Component, pageProps }: AppProps) { () => setMessageDialogView(false), [], ); - const closeDialogBoxV2 = () => setDialogBoxV2View(false); - - const showMiniDialog = useCallback((attributes: MiniDialogAttributes) => { - setDialogBoxAttributesV2(attributes); - setDialogBoxV2View(true); - }, []); // Use `onGenericError` instead. const somethingWentWrong = useCallback( @@ -254,18 +244,10 @@ export default function App({ Component, pageProps }: AppProps) { [], ); - const onGenericError = useCallback( - (e: unknown) => ( - log.error("Error", e), - setDialogBoxAttributesV2({ - title: t("error"), - icon: , - message: t("generic_error"), - close: { variant: "critical" }, - }) - ), - [], - ); + const onGenericError = useCallback((e: unknown) => { + log.error("Error", e); + showMiniDialog(genericErrorDialogAttributes()); + }, []); const logout = useCallback(() => { void photosLogout().then(() => router.push("/")); @@ -287,7 +269,6 @@ export default function App({ Component, pageProps }: AppProps) { showMiniDialog, somethingWentWrong, onGenericError, - setDialogBoxAttributesV2, mapEnabled, updateMapEnabled, // <- changes on each render isCFProxyDisabled, @@ -318,9 +299,7 @@ export default function App({ Component, pageProps }: AppProps) { /> void, -): DialogBoxAttributes => ({ - title: t("CONFIRM_EDITOR_CLOSE_MESSAGE"), - content: t("CONFIRM_EDITOR_CLOSE_DESCRIPTION"), - proceed: { - action: doClose, - text: t("close"), - variant: "critical", - }, - close: { text: t("cancel") }, -}); diff --git a/web/packages/accounts/pages/recover.tsx b/web/packages/accounts/pages/recover.tsx index c6e86cdafc..c4ad1ba20f 100644 --- a/web/packages/accounts/pages/recover.tsx +++ b/web/packages/accounts/pages/recover.tsx @@ -29,7 +29,7 @@ const bip39 = require("bip39"); bip39.setDefaultWordlist("english"); const Page: React.FC = ({ appContext }) => { - const { showNavBar, setDialogBoxAttributesV2 } = appContext; + const { showNavBar, showMiniDialog } = appContext; const [keyAttributes, setKeyAttributes] = useState< KeyAttributes | undefined @@ -98,10 +98,11 @@ const Page: React.FC = ({ appContext }) => { }; const showNoRecoveryKeyMessage = () => - setDialogBoxAttributesV2({ + showMiniDialog({ title: t("sorry"), - close: {}, message: t("NO_RECOVERY_KEY_MESSAGE"), + continue: { color: "secondary" }, + cancel: false, }); return ( diff --git a/web/packages/accounts/pages/two-factor/recover.tsx b/web/packages/accounts/pages/two-factor/recover.tsx index be2d2227fd..0aa1406b6f 100644 --- a/web/packages/accounts/pages/two-factor/recover.tsx +++ b/web/packages/accounts/pages/two-factor/recover.tsx @@ -42,7 +42,7 @@ export interface RecoverPageProps { } const Page: React.FC = ({ appContext, twoFactorType }) => { - const { logout } = appContext; + const { showMiniDialog, logout } = appContext; const [encryptedTwoFactorSecret, setEncryptedTwoFactorSecret] = useState | null>(null); @@ -72,6 +72,7 @@ const Page: React.FC = ({ appContext, twoFactorType }) => { if (!resp.encryptedSecret) { showContactSupportDialog({ text: t("GO_BACK"), + autoClose: true, action: router.back, }); } else { @@ -91,6 +92,7 @@ const Page: React.FC = ({ appContext, twoFactorType }) => { setDoesHaveEncryptedRecoveryKey(false); showContactSupportDialog({ text: t("GO_BACK"), + autoClose: true, action: router.back, }); } @@ -146,11 +148,10 @@ const Page: React.FC = ({ appContext, twoFactorType }) => { }; const showContactSupportDialog = ( - dialogClose?: MiniDialogAttributes["close"], + dialogContinue?: MiniDialogAttributes["continue"], ) => { - appContext.setDialogBoxAttributesV2({ + showMiniDialog({ title: t("contact_support"), - close: dialogClose ?? {}, message: ( = ({ appContext, twoFactorType }) => { values={{ emailID: "support@ente.io" }} /> ), + continue: { color: "secondary", ...(dialogContinue ?? {}) }, + cancel: false, }); }; diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index dcf0a53239..037d887845 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -75,6 +75,11 @@ export interface MiniDialogAttributes { * is opened, allowing the user to confirm just by pressing ENTER. */ autoFocus?: boolean; + /** + * If `true`, close the dialog after {@link action} completes. + * TODO: Test/Impl/Is this needed? + */ + autoClose?: boolean; /** * The function to call when the user activates the button. * From 288d66dfa74fcd9c64d56128f9292ce815cbfe4a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 15:59:27 +0530 Subject: [PATCH 168/438] Finish re --- web/packages/base/components/MiniDialog.tsx | 12 +++----- .../new/photos/components/MLSettings.tsx | 29 ++++++------------- .../components/gallery/PeopleHeader.tsx | 9 +++--- 3 files changed, 17 insertions(+), 33 deletions(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index 037d887845..820be8e061 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -1,7 +1,3 @@ -// TODO: -/* eslint-disable @typescript-eslint/prefer-optional-chain */ -/* eslint-disable @typescript-eslint/no-unnecessary-condition */ -/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { LoadingButton } from "@/base/components/mui/LoadingButton"; import type { ButtonProps } from "@mui/material"; @@ -147,7 +143,7 @@ export const AttributedMiniDialog: React.FC< }} {...rest} > - {(attributes.icon || attributes.title) && ( + {(attributes.icon ?? attributes.title) && ( { await attributes.continue?.action?.(setLoading); onClose(); }} > - {attributes.continue?.text ?? t("ok")} + {attributes.continue.text ?? t("ok")} )} {attributes.cancel && ( diff --git a/web/packages/new/photos/components/MLSettings.tsx b/web/packages/new/photos/components/MLSettings.tsx index 3b1db3002b..15480eddf4 100644 --- a/web/packages/new/photos/components/MLSettings.tsx +++ b/web/packages/new/photos/components/MLSettings.tsx @@ -27,7 +27,7 @@ import { import { t } from "i18next"; import React, { useEffect, useState, useSyncExternalStore } from "react"; import { Trans } from "react-i18next"; -import { useAppContext, type AppContextT } from "../types/context"; +import { useAppContext } from "../types/context"; import { openURL } from "../utils/web"; import { useWrapAsyncOperation } from "./use-wrap-async"; @@ -36,8 +36,6 @@ export const MLSettings: React.FC = ({ onClose, onRootClose, }) => { - const { setDialogBoxAttributesV2 } = useAppContext(); - const mlStatus = useSyncExternalStore(mlStatusSubscribe, mlStatusSnapshot); const [openFaceConsent, setOpenFaceConsent] = useState(false); @@ -68,10 +66,7 @@ export const MLSettings: React.FC = ({ component = ; } else { component = ( - + ); } @@ -252,15 +247,11 @@ interface ManageMLProps { mlStatus: Exclude; /** Called when the user wants to disable ML. */ onDisableML: () => void; - /** Subset of appContext. */ - setDialogBoxAttributesV2: AppContextT["setDialogBoxAttributesV2"]; } -const ManageML: React.FC = ({ - mlStatus, - onDisableML, - setDialogBoxAttributesV2, -}) => { +const ManageML: React.FC = ({ mlStatus, onDisableML }) => { + const { showMiniDialog } = useAppContext(); + const { phase, nSyncedFiles, nTotalFiles } = mlStatus; let status: string; @@ -289,19 +280,17 @@ const ManageML: React.FC = ({ ? `${Math.round((100 * nSyncedFiles) / nTotalFiles)}%` : `${nSyncedFiles} / ${nTotalFiles}`; - const confirmDisableML = () => { - setDialogBoxAttributesV2({ + const confirmDisableML = () => + showMiniDialog({ title: t("ml_search_disable"), message: t("ml_search_disable_confirm"), - close: { text: t("cancel") }, - proceed: { - variant: "critical", + continue: { text: t("disable"), + color: "critical", action: onDisableML, }, buttonDirection: "row", }); - }; return ( diff --git a/web/packages/new/photos/components/gallery/PeopleHeader.tsx b/web/packages/new/photos/components/gallery/PeopleHeader.tsx index aa0b05922e..2b59b96967 100644 --- a/web/packages/new/photos/components/gallery/PeopleHeader.tsx +++ b/web/packages/new/photos/components/gallery/PeopleHeader.tsx @@ -92,7 +92,7 @@ const CGroupPersonOptions: React.FC = ({ cgroup, onSelectPerson, }) => { - const { setDialogBoxAttributesV2 } = useAppContext(); + const { showMiniDialog } = useAppContext(); const [openAddNameInput, setOpenAddNameInput] = useState(false); @@ -103,17 +103,16 @@ const CGroupPersonOptions: React.FC = ({ ); const handleDeletePerson = () => - setDialogBoxAttributesV2({ + showMiniDialog({ title: pt("Reset person?"), message: pt( "The name, face groupings and suggestions for this person will be reset", ), - close: { text: t("cancel") }, - proceed: { + continue: { text: t("reset"), + color: "primary", action: deletePerson, }, - buttonDirection: "row", }); const deletePerson = useWrapAsyncOperation(async () => { From dde2b8894aba7dbb0daa9f2dc41b49735f31c68a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 16:04:59 +0530 Subject: [PATCH 169/438] Test 1 --- web/packages/base/components/MiniDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index 820be8e061..0efada4f47 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -192,7 +192,7 @@ export const AttributedMiniDialog: React.FC< {attributes.continue.text ?? t("ok")} )} - {attributes.cancel && ( + {attributes.cancel !== false && ( Date: Thu, 10 Oct 2024 16:27:00 +0530 Subject: [PATCH 170/438] Tune semantics --- web/packages/base/components/MiniDialog.tsx | 27 +++++++++++---------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index 0efada4f47..91d8e78736 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -71,22 +71,17 @@ export interface MiniDialogAttributes { * is opened, allowing the user to confirm just by pressing ENTER. */ autoFocus?: boolean; - /** - * If `true`, close the dialog after {@link action} completes. - * TODO: Test/Impl/Is this needed? - */ - autoClose?: boolean; /** * The function to call when the user activates the button. * - * Default is to close the dialog. + * If this function returns a promise, then an activity indicator will + * be shown on the button until the promise settles. * - * It is passed a {@link setLoading} function that can be used to show - * or hide loading indicator or the primary action button. + * If this function is not provided, or if the function completes / + * fullfills, then then the dialog is automatically closed. Otherwise + * (that is, if the provided function throws), the dialog remains open. */ - action?: - | (() => void | Promise) - | ((setLoading: (value: boolean) => void) => void | Promise); + action?: () => void | Promise; }; /** * The string to use as the label for the cancel button. @@ -185,8 +180,14 @@ export const AttributedMiniDialog: React.FC< color={attributes.continue.color ?? "accent"} autoFocus={attributes.continue.autoFocus} onClick={async () => { - await attributes.continue?.action?.(setLoading); - onClose(); + setLoading(true); + try { + await attributes.continue?.action?.(); + setLoading(false); + onClose(); + } catch { + setLoading(false); + } }} > {attributes.continue.text ?? t("ok")} From ed17206f51dbcf4079317e7d243c36b21edb9d3c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 16:37:08 +0530 Subject: [PATCH 171/438] Fix warnings --- web/packages/base/components/MiniDialog.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index 91d8e78736..6179773b82 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -127,7 +127,6 @@ export const AttributedMiniDialog: React.FC< return ( {(attributes.icon ?? attributes.title) && ( From e822d327e46a03048e21b661e1b456c663931177 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 16:41:05 +0530 Subject: [PATCH 172/438] All cases --- web/packages/base/components/MiniDialog.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index 6179773b82..510ab6082f 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -80,6 +80,16 @@ export interface MiniDialogAttributes { * If this function is not provided, or if the function completes / * fullfills, then then the dialog is automatically closed. Otherwise * (that is, if the provided function throws), the dialog remains open. + * + * That's quite a mouthful, here's a flowchart: + * + * - Not provided: Close + * - Provided sync: + * - Success: Close + * - Failure: Remain open + * - Provided async: + * - Success: Close + * - Failure: Remain open */ action?: () => void | Promise; }; From 24dc72eee31da2cdff7ad08be0aae9e421973374 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 16:13:34 +0530 Subject: [PATCH 173/438] Loose ends --- web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx | 2 +- web/apps/photos/src/pages/_app.tsx | 1 + web/packages/base/components/utils/mini-dialog.tsx | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx index 9c39ae3f87..9f3c87ca7b 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx @@ -403,7 +403,7 @@ const confirmDisableMapsDialogAttributes = ( ): MiniDialogAttributes => ({ title: t("DISABLE_MAPS"), message: , - continue: { text: t("disable"), action: onConfirm }, + continue: { text: t("disable"), color: "critical", action: onConfirm }, }); const FileInfoSidebar = styled((props: DialogProps) => ( diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index 3fec77edc3..17ff25cc40 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -213,6 +213,7 @@ export default function App({ Component, pageProps }: AppProps) { setLocalMapEnabled(enabled); setMapEnabled(enabled); } catch (e) { + // TODO: Handle the error here. log.error("Error while updating mapEnabled", e); } }; diff --git a/web/packages/base/components/utils/mini-dialog.tsx b/web/packages/base/components/utils/mini-dialog.tsx index 088e8511f2..5118e52a62 100644 --- a/web/packages/base/components/utils/mini-dialog.tsx +++ b/web/packages/base/components/utils/mini-dialog.tsx @@ -55,6 +55,7 @@ export const errorDialogAttributes = ( icon: , message, continue: { color: "critical" }, + cancel: false, }; }; From 5e639e972978fe6ac60d766aed29a2be5a419ed8 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 17:03:29 +0530 Subject: [PATCH 174/438] Provision an error handler --- web/packages/base/components/MiniDialog.tsx | 41 ++++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index 510ab6082f..ce88463ab9 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -12,6 +12,7 @@ import { } from "@mui/material"; import { t } from "i18next"; import React, { useState } from "react"; +import log from "../log"; /** * Customize the contents of an {@link AttributedMiniDialog}. @@ -70,7 +71,7 @@ export interface MiniDialogAttributes { * If `true`, the primary action button is auto focused when the dialog * is opened, allowing the user to confirm just by pressing ENTER. */ - autoFocus?: boolean; + autoFocus?: ButtonProps["autoFocus"]; /** * The function to call when the user activates the button. * @@ -78,18 +79,20 @@ export interface MiniDialogAttributes { * be shown on the button until the promise settles. * * If this function is not provided, or if the function completes / - * fullfills, then then the dialog is automatically closed. Otherwise - * (that is, if the provided function throws), the dialog remains open. + * fullfills, then then the dialog is automatically closed. + * + * Otherwise (that is, if the provided function throws), the dialog + * remains open, showing a generic error. * * That's quite a mouthful, here's a flowchart: * * - Not provided: Close * - Provided sync: * - Success: Close - * - Failure: Remain open + * - Failure: Remain open, showing generic error * - Provided async: * - Success: Close - * - Failure: Remain open + * - Failure: Remain open, showing generic error */ action?: () => void | Promise; }; @@ -121,15 +124,20 @@ type MiniDialogProps = Omit & { export const AttributedMiniDialog: React.FC< React.PropsWithChildren > = ({ open, onClose, attributes, children, ...props }) => { - const [loading, setLoading] = useState(false); + const [phase, setPhase] = useState<"loading" | "failed" | undefined>(); if (!attributes) { return <>; } + const resetPhaseAndClose = () => { + setPhase(undefined); + onClose(); + }; + const handleClose = () => { if (attributes.nonClosable) return; - onClose(); + resetPhaseAndClose(); }; const { PaperProps, ...rest } = props; @@ -188,20 +196,25 @@ export const AttributedMiniDialog: React.FC< : "column" } > + {phase == "failed" && ( + + {t("generic_error")} + + )} {attributes.continue && ( { - setLoading(true); + setPhase("loading"); try { await attributes.continue?.action?.(); - setLoading(false); - onClose(); - } catch { - setLoading(false); + resetPhaseAndClose(); + } catch (e) { + log.error("Error", e); + setPhase("failed"); } }} > @@ -212,7 +225,7 @@ export const AttributedMiniDialog: React.FC< {attributes.cancel ?? t("cancel")} From 4d3b89048c0fead6f9cee25cfd46cd2d0ea8df59 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 17:06:22 +0530 Subject: [PATCH 175/438] Fix error about nesting p in div --- web/packages/base/components/MiniDialog.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index ce88463ab9..ff124a035e 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -183,7 +183,12 @@ export const AttributedMiniDialog: React.FC< )} {attributes.message && ( - + {attributes.message} )} From de74acedab9f10e0a3dd60888a878e6687fff23a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 17:11:25 +0530 Subject: [PATCH 176/438] Use inbuilt error handler --- .../accounts/src/pages/passkeys/index.tsx | 40 ++++++++----------- web/apps/photos/src/pages/_app.tsx | 11 ++--- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/web/apps/accounts/src/pages/passkeys/index.tsx b/web/apps/accounts/src/pages/passkeys/index.tsx index fb9f591ad5..88bf77b80b 100644 --- a/web/apps/accounts/src/pages/passkeys/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/index.tsx @@ -264,30 +264,22 @@ const ManagePasskeyDrawer: React.FC = ({ const [showRenameDialog, setShowRenameDialog] = useState(false); - const showDeleteConfirmationDialog = useCallback(() => { - /* mark: uses-loading */ - const handleDelete = async (setLoading: (value: boolean) => void) => { - setLoading(true); - try { - await deletePasskey(ensure(token), ensure(passkey).id); - onUpdateOrDeletePasskey(); - } catch (e) { - log.error("Failed to delete passkey", e); - } finally { - setLoading(false); - } - }; - - showMiniDialog({ - title: t("delete_passkey"), - message: t("delete_passkey_confirmation"), - continue: { - text: t("delete"), - color: "critical", - action: handleDelete, - }, - }); - }, [showMiniDialog, token, passkey, onUpdateOrDeletePasskey]); + const showDeleteConfirmationDialog = useCallback( + () => + showMiniDialog({ + title: t("delete_passkey"), + message: t("delete_passkey_confirmation"), + continue: { + text: t("delete"), + color: "critical", + action: async () => { + await deletePasskey(ensure(token), ensure(passkey).id); + onUpdateOrDeletePasskey(); + }, + }, + }), + [showMiniDialog, token, passkey, onUpdateOrDeletePasskey], + ); return ( <> diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index 17ff25cc40..0c7b0f61c0 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -208,14 +208,9 @@ export default function App({ Component, pageProps }: AppProps) { const showNavBar = (show: boolean) => setShowNavBar(show); const updateMapEnabled = async (enabled: boolean) => { - try { - await updateMapEnabledStatus(enabled); - setLocalMapEnabled(enabled); - setMapEnabled(enabled); - } catch (e) { - // TODO: Handle the error here. - log.error("Error while updating mapEnabled", e); - } + await updateMapEnabledStatus(enabled); + setLocalMapEnabled(enabled); + setMapEnabled(enabled); }; const startLoading = () => { From 78962b261179877d9677858e096d3551c04376d9 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 17:16:56 +0530 Subject: [PATCH 177/438] Touchups --- .../src/components/AuthenticateUserModal.tsx | 1 + .../src/components/DeleteAccountModal.tsx | 24 ++++++------------- .../accounts/pages/two-factor/recover.tsx | 2 -- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/web/apps/photos/src/components/AuthenticateUserModal.tsx b/web/apps/photos/src/components/AuthenticateUserModal.tsx index 6f17a61bc7..1fe92900e9 100644 --- a/web/apps/photos/src/components/AuthenticateUserModal.tsx +++ b/web/apps/photos/src/components/AuthenticateUserModal.tsx @@ -130,4 +130,5 @@ const passwordChangedElsewhereDialogAttributes = ( text: t("login"), action: onLogin, }, + cancel: false, }); diff --git a/web/apps/photos/src/components/DeleteAccountModal.tsx b/web/apps/photos/src/components/DeleteAccountModal.tsx index 82cd039c44..795d96bfb3 100644 --- a/web/apps/photos/src/components/DeleteAccountModal.tsx +++ b/web/apps/photos/src/components/DeleteAccountModal.tsx @@ -106,23 +106,13 @@ const DeleteAccountModal = ({ open, onClose }: Iprops) => { }); }; - /* mark: uses-loading */ - const solveChallengeAndDeleteAccount = async ( - setLoading: (value: boolean) => void, - ) => { - try { - setLoading(true); - const decryptedChallenge = await decryptDeleteAccountChallenge( - deleteAccountChallenge.current, - ); - const { reason, feedback } = reasonAndFeedbackRef.current; - await deleteAccount(decryptedChallenge, reason, feedback); - logout(); - } catch (e) { - onGenericError(e); - } finally { - setLoading(false); - } + const solveChallengeAndDeleteAccount = async () => { + const decryptedChallenge = await decryptDeleteAccountChallenge( + deleteAccountChallenge.current, + ); + const { reason, feedback } = reasonAndFeedbackRef.current; + await deleteAccount(decryptedChallenge, reason, feedback); + logout(); }; return ( diff --git a/web/packages/accounts/pages/two-factor/recover.tsx b/web/packages/accounts/pages/two-factor/recover.tsx index 0aa1406b6f..8fdfd4dbb8 100644 --- a/web/packages/accounts/pages/two-factor/recover.tsx +++ b/web/packages/accounts/pages/two-factor/recover.tsx @@ -72,7 +72,6 @@ const Page: React.FC = ({ appContext, twoFactorType }) => { if (!resp.encryptedSecret) { showContactSupportDialog({ text: t("GO_BACK"), - autoClose: true, action: router.back, }); } else { @@ -92,7 +91,6 @@ const Page: React.FC = ({ appContext, twoFactorType }) => { setDoesHaveEncryptedRecoveryKey(false); showContactSupportDialog({ text: t("GO_BACK"), - autoClose: true, action: router.back, }); } From 710b7e93dc5ed4e10d1ffdab1cd95a88d2d177d2 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 17:25:58 +0530 Subject: [PATCH 178/438] Ok is a better title, the go back is a bit confusing --- web/packages/accounts/pages/two-factor/recover.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/web/packages/accounts/pages/two-factor/recover.tsx b/web/packages/accounts/pages/two-factor/recover.tsx index 8fdfd4dbb8..d090160d11 100644 --- a/web/packages/accounts/pages/two-factor/recover.tsx +++ b/web/packages/accounts/pages/two-factor/recover.tsx @@ -70,10 +70,7 @@ const Page: React.FC = ({ appContext, twoFactorType }) => { const resp = await recoverTwoFactor(sid, twoFactorType); setDoesHaveEncryptedRecoveryKey(!!resp.encryptedSecret); if (!resp.encryptedSecret) { - showContactSupportDialog({ - text: t("GO_BACK"), - action: router.back, - }); + showContactSupportDialog({ action: router.back }); } else { setEncryptedTwoFactorSecret({ encryptedData: resp.encryptedSecret, @@ -89,10 +86,7 @@ const Page: React.FC = ({ appContext, twoFactorType }) => { } else { log.error("two factor recovery page setup failed", e); setDoesHaveEncryptedRecoveryKey(false); - showContactSupportDialog({ - text: t("GO_BACK"), - action: router.back, - }); + showContactSupportDialog({ action: router.back }); } } }; From 1cdc7aa59405e08aeb8e1639c8064f350168db00 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Thu, 10 Oct 2024 18:45:05 +0530 Subject: [PATCH 179/438] [mob][photos] Decode heic using flutter compress --- mobile/lib/utils/image_ml_util.dart | 44 +++++++++++++++-------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/mobile/lib/utils/image_ml_util.dart b/mobile/lib/utils/image_ml_util.dart index 6e24ac9d5a..a6d047a842 100644 --- a/mobile/lib/utils/image_ml_util.dart +++ b/mobile/lib/utils/image_ml_util.dart @@ -5,7 +5,7 @@ import "dart:typed_data" show Float32List, Uint8List; import "dart:ui"; import 'package:flutter/painting.dart' as paint show decodeImageFromList; -import "package:heif_converter/heif_converter.dart"; +import "package:flutter_image_compress/flutter_image_compress.dart"; import "package:logging/logging.dart"; import 'package:ml_linalg/linalg.dart'; import "package:photos/models/ml/face/box.dart"; @@ -40,27 +40,29 @@ Future<(Image, Uint8List)> decodeImageFromPath(String imagePath) async { return (image, rawRgbaBytes); } catch (e, s) { final format = imagePath.split('.').last; - if (Platform.isAndroid) { - _logger.info('Cannot decode $format, converting to JPG on Android'); - final String? jpgPath = - await HeifConverter.convert(imagePath, format: 'jpg'); - if (jpgPath != null) { - _logger.info('Conversion successful, decoding JPG'); - final imageData = await File(jpgPath).readAsBytes(); - final image = await decodeImageFromData(imageData); - final rawRgbaBytes = await _getRawRgbaBytes(image); - return (image, rawRgbaBytes); - } - _logger.info('Unable to convert $format to JPG'); + _logger.info( + 'Cannot decode $format on ${Platform.isAndroid ? "Android" : "iOS"}, converting to jpeg', + ); + try { + final Uint8List? convertedData = + await FlutterImageCompress.compressWithFile( + imagePath, + format: CompressFormat.jpeg, + ); + final image = await decodeImageFromData(convertedData!); + final rawRgbaBytes = await _getRawRgbaBytes(image); + _logger.info('Conversion successful, jpeg decoded'); + return (image, rawRgbaBytes); + } catch (e) { + _logger.severe( + 'Error decoding image of format $format on ${Platform.isAndroid ? "Android" : "iOS"}', + e, + s, + ); + throw Exception( + 'InvalidImageFormatException: Error decoding image of format $format', + ); } - _logger.severe( - 'Error decoding image of format $format (Android: ${Platform.isAndroid})', - e, - s, - ); - throw Exception( - 'InvalidImageFormatException: Error decoding image of format $format', - ); } } From a7c31b65a2f1566b250cfcf63152bc277caed8c6 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:26:03 +0530 Subject: [PATCH 180/438] Rename --- web/packages/accounts/pages/recover.tsx | 2 +- web/packages/base/locales/ar-SA/translation.json | 2 +- web/packages/base/locales/bg-BG/translation.json | 2 +- web/packages/base/locales/ca-ES/translation.json | 2 +- web/packages/base/locales/da-DK/translation.json | 2 +- web/packages/base/locales/de-DE/translation.json | 2 +- web/packages/base/locales/el-GR/translation.json | 2 +- web/packages/base/locales/en-US/translation.json | 2 +- web/packages/base/locales/es-ES/translation.json | 2 +- web/packages/base/locales/et-EE/translation.json | 2 +- web/packages/base/locales/fa-IR/translation.json | 2 +- web/packages/base/locales/fi-FI/translation.json | 2 +- web/packages/base/locales/fr-FR/translation.json | 2 +- web/packages/base/locales/gu-IN/translation.json | 2 +- web/packages/base/locales/hi-IN/translation.json | 2 +- web/packages/base/locales/id-ID/translation.json | 2 +- web/packages/base/locales/is-IS/translation.json | 2 +- web/packages/base/locales/it-IT/translation.json | 2 +- web/packages/base/locales/ja-JP/translation.json | 2 +- web/packages/base/locales/km-KH/translation.json | 2 +- web/packages/base/locales/ko-KR/translation.json | 2 +- web/packages/base/locales/lt-LT/translation.json | 2 +- web/packages/base/locales/nl-NL/translation.json | 2 +- web/packages/base/locales/pl-PL/translation.json | 2 +- web/packages/base/locales/pt-BR/translation.json | 2 +- web/packages/base/locales/pt-PT/translation.json | 2 +- web/packages/base/locales/ru-RU/translation.json | 2 +- web/packages/base/locales/sl-SI/translation.json | 2 +- web/packages/base/locales/sv-SE/translation.json | 2 +- web/packages/base/locales/ta-IN/translation.json | 2 +- web/packages/base/locales/te-IN/translation.json | 2 +- web/packages/base/locales/th-TH/translation.json | 2 +- web/packages/base/locales/ti-ER/translation.json | 2 +- web/packages/base/locales/tr-TR/translation.json | 2 +- web/packages/base/locales/uk-UA/translation.json | 2 +- web/packages/base/locales/zh-CN/translation.json | 2 +- 36 files changed, 36 insertions(+), 36 deletions(-) diff --git a/web/packages/accounts/pages/recover.tsx b/web/packages/accounts/pages/recover.tsx index c4ad1ba20f..c08a5d97df 100644 --- a/web/packages/accounts/pages/recover.tsx +++ b/web/packages/accounts/pages/recover.tsx @@ -100,7 +100,7 @@ const Page: React.FC = ({ appContext }) => { const showNoRecoveryKeyMessage = () => showMiniDialog({ title: t("sorry"), - message: t("NO_RECOVERY_KEY_MESSAGE"), + message: t("no_recovery_key_message"), continue: { color: "secondary" }, cancel: false, }); diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index 2ed8265e65..111d4d1d9b 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "ما من مفتاح استعادة؟", "INCORRECT_RECOVERY_KEY": "مفتاح استعادة غير صحيح", "sorry": "عذرا", - "NO_RECOVERY_KEY_MESSAGE": "بسبب طبيعة نظام التشفير التام بين الطرفين، لا يمكن فك تشفير بياناتك دون كلمة المرور أو مفتاح الاسترداد الخاص بك", + "no_recovery_key_message": "بسبب طبيعة نظام التشفير التام بين الطرفين، لا يمكن فك تشفير بياناتك دون كلمة المرور أو مفتاح الاسترداد الخاص بك", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "الاتصال بالدعم", "request_feature": "طلب ميزة", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index f0175de147..22d42dcfd5 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index 3a47835b5f..98c7cfd623 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index 914d263e0a..6ddd5b522f 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -122,7 +122,7 @@ "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_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", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index db0db2bb87..58aaf5acb5 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "Χωρίς κλειδί ανάκτησης;", "INCORRECT_RECOVERY_KEY": "Εσφαλμένο κλειδί ανάκτησης", "sorry": "Συγνώμη", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Παρακαλώ αφήστε ένα μήνυμα ηλ. ταχυδρομείου στο {{emailID}} από την καταχωρημένη διεύθυνση σας", "contact_support": "Επικοινωνήστε με την υποστήριξη", "request_feature": "Αίτηση Λειτουργίας", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 4aa56a1f95..953d8edded 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -122,7 +122,7 @@ "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_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", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index fe76b3bd61..46ce63bcca 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -122,7 +122,7 @@ "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_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", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index 303a9f3221..9d17aff1a6 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index 222aaaa481..151c4e4628 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 28391bf8ab..2d7bf22d3d 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -122,7 +122,7 @@ "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_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", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index 08b5d92bc5..b3e0e86ea6 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "Tidak punya kunci pemulihan?", "INCORRECT_RECOVERY_KEY": "Kunci pemulihan salah", "sorry": "Maaf", - "NO_RECOVERY_KEY_MESSAGE": "Karena sifat protokol enkripsi ujung ke ujung kami, data kamu tidak dapat didekripsi tanpa sandi atau kunci pemulihan kamu", + "no_recovery_key_message": "Karena sifat protokol enkripsi ujung ke ujung kami, data kamu tidak dapat didekripsi tanpa sandi atau kunci pemulihan kamu", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Silakan kirimkan email ke {{emailID}} dari alamat email terdaftar kamu", "contact_support": "Hubungi dukungan", "request_feature": "Minta Fitur", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index 05c333ecf1..c6f3a31532 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "Enginn endurheimtunarlykill?", "INCORRECT_RECOVERY_KEY": "", "sorry": "Fyrirgefðu", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index faca1ce884..0beac40f76 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -122,7 +122,7 @@ "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_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à", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index fb3e83ca2d..598ce7f880 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 96d1af3fb4..d50d2a4404 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 4c961d954e..68a7008d40 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "Neturite atkūrimo rakto?", "INCORRECT_RECOVERY_KEY": "Neteisingas atkūrimo raktas.", "sorry": "Atsiprašome", - "NO_RECOVERY_KEY_MESSAGE": "Dėl mūsų visapusio šifravimo protokolo pobūdžio jūsų duomenų negalima iššifruoti be slaptažodžio arba atkūrimo rakto", + "no_recovery_key_message": "Dėl mūsų visapusio šifravimo protokolo pobūdžio jūsų duomenų negalima iššifruoti be slaptažodžio arba atkūrimo rakto", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Iš savo registruoto el. pašto adreso parašykite el. laišką adresu {{{emailID}}", "contact_support": "Susisiekti su palaikymo komanda", "request_feature": "Prašyti funkcijos", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 0a608ac71d..06e51b4c14 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -122,7 +122,7 @@ "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_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", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 497971a7ae..86be1a5a8f 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "Brak klucza odzyskiwania?", "INCORRECT_RECOVERY_KEY": "Nieprawidłowy klucz odzyskiwania", "sorry": "Przepraszamy", - "NO_RECOVERY_KEY_MESSAGE": "Ze względu na charakter naszego protokołu szyfrowania end-to-end, Twoje dane nie mogą być odszyfrowane bez hasła lub klucza odzyskiwania", + "no_recovery_key_message": "Ze względu na charakter naszego protokołu szyfrowania end-to-end, Twoje dane nie mogą być odszyfrowane bez hasła lub klucza odzyskiwania", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Wyślij wiadomość e-mail na {{emailID}} z zarejestrowanego adresu e-mail", "contact_support": "Skontaktuj się z pomocą techniczną", "request_feature": "Zaproponuj Funkcję", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index ad373d915c..a17eeb6bf4 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -122,7 +122,7 @@ "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_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 recurso", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 11b82444a1..2a110fbfd5 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 177cd0be71..5e17671343 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "Нет ключа восстановления?", "INCORRECT_RECOVERY_KEY": "Неправильный ключ восстановления", "sorry": "Извините", - "NO_RECOVERY_KEY_MESSAGE": "Из-за природы нашего сквозного протокола шифрования ваши данные не могут быть расшифрованы без вашего пароля или ключа восстановления", + "no_recovery_key_message": "Из-за природы нашего сквозного протокола шифрования ваши данные не могут быть расшифрованы без вашего пароля или ключа восстановления", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Пожалуйста, отправьте электронное письмо на адрес {{emailID}} с вашего зарегистрированного адреса электронной почты", "contact_support": "Связаться с поддержкой", "request_feature": "Запросить функцию", diff --git a/web/packages/base/locales/sl-SI/translation.json b/web/packages/base/locales/sl-SI/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/sl-SI/translation.json +++ b/web/packages/base/locales/sl-SI/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index 452dbc336f..2b3e3d465c 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "Ingen återställningsnyckel?", "INCORRECT_RECOVERY_KEY": "Felaktig återställningsnyckel", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index d90d67b874..efbbed4fee 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "Kurtarma anahtarı yok mu?", "INCORRECT_RECOVERY_KEY": "Kurtarma anahtarı yanlış", "sorry": "Üzgünüz", - "NO_RECOVERY_KEY_MESSAGE": "Uçtan uca şifreleme protokolümüzün doğası gereği, verilerin parolan veya kurtarma anahtarın olmadan çözülemez", + "no_recovery_key_message": "Uçtan uca şifreleme protokolümüzün doğası gereği, verilerin parolan veya kurtarma anahtarın olmadan çözülemez", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Lütfen kaydolduğun e-posta adresinden {{emailID}} adresine bir e-posta bırak", "contact_support": "Destek ile iletişime geç", "request_feature": "Özellik İste", diff --git a/web/packages/base/locales/uk-UA/translation.json b/web/packages/base/locales/uk-UA/translation.json index ac2e6f1147..603a6a1953 100644 --- a/web/packages/base/locales/uk-UA/translation.json +++ b/web/packages/base/locales/uk-UA/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "", "INCORRECT_RECOVERY_KEY": "", "sorry": "", - "NO_RECOVERY_KEY_MESSAGE": "", + "no_recovery_key_message": "", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", "contact_support": "", "request_feature": "", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index 968fdb95c5..97a1ab3146 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -122,7 +122,7 @@ "NO_RECOVERY_KEY": "没有恢复密钥?", "INCORRECT_RECOVERY_KEY": "不正确的恢复密钥", "sorry": "抱歉", - "NO_RECOVERY_KEY_MESSAGE": "由于我们端到端加密协议的性质,如果没有您的密码或恢复密钥,您的数据将无法解密", + "no_recovery_key_message": "由于我们端到端加密协议的性质,如果没有您的密码或恢复密钥,您的数据将无法解密", "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "请用您注册Ente账户的电子邮箱发一封邮件给 {{emailID}}", "contact_support": "联系支持", "request_feature": "功能建议", From 86add71393899fd00359fc6b5846e1aadc4b4e7c Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:31:17 +0530 Subject: [PATCH 181/438] Rename --- web/packages/accounts/pages/two-factor/recover.tsx | 2 +- web/packages/base/locales/ar-SA/translation.json | 2 +- web/packages/base/locales/bg-BG/translation.json | 2 +- web/packages/base/locales/ca-ES/translation.json | 2 +- web/packages/base/locales/da-DK/translation.json | 2 +- web/packages/base/locales/de-DE/translation.json | 2 +- web/packages/base/locales/el-GR/translation.json | 2 +- web/packages/base/locales/en-US/translation.json | 2 +- web/packages/base/locales/es-ES/translation.json | 2 +- web/packages/base/locales/et-EE/translation.json | 2 +- web/packages/base/locales/fa-IR/translation.json | 2 +- web/packages/base/locales/fi-FI/translation.json | 2 +- web/packages/base/locales/fr-FR/translation.json | 2 +- web/packages/base/locales/gu-IN/translation.json | 2 +- web/packages/base/locales/hi-IN/translation.json | 2 +- web/packages/base/locales/id-ID/translation.json | 2 +- web/packages/base/locales/is-IS/translation.json | 2 +- web/packages/base/locales/it-IT/translation.json | 2 +- web/packages/base/locales/ja-JP/translation.json | 2 +- web/packages/base/locales/km-KH/translation.json | 2 +- web/packages/base/locales/ko-KR/translation.json | 2 +- web/packages/base/locales/lt-LT/translation.json | 2 +- web/packages/base/locales/nl-NL/translation.json | 2 +- web/packages/base/locales/pl-PL/translation.json | 2 +- web/packages/base/locales/pt-BR/translation.json | 2 +- web/packages/base/locales/pt-PT/translation.json | 2 +- web/packages/base/locales/ru-RU/translation.json | 2 +- web/packages/base/locales/sl-SI/translation.json | 2 +- web/packages/base/locales/sv-SE/translation.json | 2 +- web/packages/base/locales/ta-IN/translation.json | 2 +- web/packages/base/locales/te-IN/translation.json | 2 +- web/packages/base/locales/th-TH/translation.json | 2 +- web/packages/base/locales/ti-ER/translation.json | 2 +- web/packages/base/locales/tr-TR/translation.json | 2 +- web/packages/base/locales/uk-UA/translation.json | 2 +- web/packages/base/locales/zh-CN/translation.json | 2 +- 36 files changed, 36 insertions(+), 36 deletions(-) diff --git a/web/packages/accounts/pages/two-factor/recover.tsx b/web/packages/accounts/pages/two-factor/recover.tsx index d090160d11..61c5b512cd 100644 --- a/web/packages/accounts/pages/two-factor/recover.tsx +++ b/web/packages/accounts/pages/two-factor/recover.tsx @@ -146,7 +146,7 @@ const Page: React.FC = ({ appContext, twoFactorType }) => { title: t("contact_support"), message: ( , }} diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index 111d4d1d9b..b1178befb9 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "مفتاح استعادة غير صحيح", "sorry": "عذرا", "no_recovery_key_message": "بسبب طبيعة نظام التشفير التام بين الطرفين، لا يمكن فك تشفير بياناتك دون كلمة المرور أو مفتاح الاسترداد الخاص بك", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "الاتصال بالدعم", "request_feature": "طلب ميزة", "support": "الدعم", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index 22d42dcfd5..c5f3838267 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index 98c7cfd623..b4d7c44382 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index 6ddd5b522f..16abc5873d 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -123,7 +123,7 @@ "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", + "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", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index 58aaf5acb5..e8daa3c315 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "Εσφαλμένο κλειδί ανάκτησης", "sorry": "Συγνώμη", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Παρακαλώ αφήστε ένα μήνυμα ηλ. ταχυδρομείου στο {{emailID}} από την καταχωρημένη διεύθυνση σας", + "no_two_factor_recovery_key_message": "Παρακαλώ αφήστε ένα μήνυμα ηλ. ταχυδρομείου στο {{emailID}} από την καταχωρημένη διεύθυνση σας", "contact_support": "Επικοινωνήστε με την υποστήριξη", "request_feature": "Αίτηση Λειτουργίας", "support": "Υποστήριξη", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 953d8edded..66b76cefd9 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -123,7 +123,7 @@ "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", + "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", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index 46ce63bcca..2a13e6d291 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -123,7 +123,7 @@ "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", + "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", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index 9d17aff1a6..a961ac5866 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index 151c4e4628..d628604774 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 2d7bf22d3d..dfbd1e992d 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -123,7 +123,7 @@ "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", + "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", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index b3e0e86ea6..6b029eb361 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "Kunci pemulihan salah", "sorry": "Maaf", "no_recovery_key_message": "Karena sifat protokol enkripsi ujung ke ujung kami, data kamu tidak dapat didekripsi tanpa sandi atau kunci pemulihan kamu", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Silakan kirimkan email ke {{emailID}} dari alamat email terdaftar kamu", + "no_two_factor_recovery_key_message": "Silakan kirimkan email ke {{emailID}} dari alamat email terdaftar kamu", "contact_support": "Hubungi dukungan", "request_feature": "Minta Fitur", "support": "Dukungan", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index c6f3a31532..e29c0ba6cc 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "Fyrirgefðu", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index 0beac40f76..dc1e7ec7eb 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -123,7 +123,7 @@ "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", + "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", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index 598ce7f880..6d49a2ad62 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index d50d2a4404..7fa4b0bb4d 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 68a7008d40..049ef69c33 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "Neteisingas atkūrimo raktas.", "sorry": "Atsiprašome", "no_recovery_key_message": "Dėl mūsų visapusio šifravimo protokolo pobūdžio jūsų duomenų negalima iššifruoti be slaptažodžio arba atkūrimo rakto", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Iš savo registruoto el. pašto adreso parašykite el. laišką adresu {{{emailID}}", + "no_two_factor_recovery_key_message": "Iš savo registruoto el. pašto adreso parašykite el. laišką adresu {{{emailID}}", "contact_support": "Susisiekti su palaikymo komanda", "request_feature": "Prašyti funkcijos", "support": "Palaikymas", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 06e51b4c14..5270f42c06 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -123,7 +123,7 @@ "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", + "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", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 86be1a5a8f..ef0f0c12ba 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "Nieprawidłowy klucz odzyskiwania", "sorry": "Przepraszamy", "no_recovery_key_message": "Ze względu na charakter naszego protokołu szyfrowania end-to-end, Twoje dane nie mogą być odszyfrowane bez hasła lub klucza odzyskiwania", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Wyślij wiadomość e-mail na {{emailID}} z zarejestrowanego adresu e-mail", + "no_two_factor_recovery_key_message": "Wyślij wiadomość e-mail na {{emailID}} z zarejestrowanego adresu e-mail", "contact_support": "Skontaktuj się z pomocą techniczną", "request_feature": "Zaproponuj Funkcję", "support": "Wsparcie Techniczne", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index a17eeb6bf4..127496c6eb 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -123,7 +123,7 @@ "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", + "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 recurso", "support": "Suporte", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 2a110fbfd5..6c33a41166 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 5e17671343..63392ce9ad 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "Неправильный ключ восстановления", "sorry": "Извините", "no_recovery_key_message": "Из-за природы нашего сквозного протокола шифрования ваши данные не могут быть расшифрованы без вашего пароля или ключа восстановления", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Пожалуйста, отправьте электронное письмо на адрес {{emailID}} с вашего зарегистрированного адреса электронной почты", + "no_two_factor_recovery_key_message": "Пожалуйста, отправьте электронное письмо на адрес {{emailID}} с вашего зарегистрированного адреса электронной почты", "contact_support": "Связаться с поддержкой", "request_feature": "Запросить функцию", "support": "Поддержка", diff --git a/web/packages/base/locales/sl-SI/translation.json b/web/packages/base/locales/sl-SI/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/sl-SI/translation.json +++ b/web/packages/base/locales/sl-SI/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index 2b3e3d465c..379d543ad6 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "Felaktig återställningsnyckel", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "Support", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index efbbed4fee..2b5da1bcf4 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "Kurtarma anahtarı yanlış", "sorry": "Üzgünüz", "no_recovery_key_message": "Uçtan uca şifreleme protokolümüzün doğası gereği, verilerin parolan veya kurtarma anahtarın olmadan çözülemez", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "Lütfen kaydolduğun e-posta adresinden {{emailID}} adresine bir e-posta bırak", + "no_two_factor_recovery_key_message": "Lütfen kaydolduğun e-posta adresinden {{emailID}} adresine bir e-posta bırak", "contact_support": "Destek ile iletişime geç", "request_feature": "Özellik İste", "support": "Destek", diff --git a/web/packages/base/locales/uk-UA/translation.json b/web/packages/base/locales/uk-UA/translation.json index 603a6a1953..66d022fffe 100644 --- a/web/packages/base/locales/uk-UA/translation.json +++ b/web/packages/base/locales/uk-UA/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "", "sorry": "", "no_recovery_key_message": "", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "", + "no_two_factor_recovery_key_message": "", "contact_support": "", "request_feature": "", "support": "", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index 97a1ab3146..6b22980c32 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -123,7 +123,7 @@ "INCORRECT_RECOVERY_KEY": "不正确的恢复密钥", "sorry": "抱歉", "no_recovery_key_message": "由于我们端到端加密协议的性质,如果没有您的密码或恢复密钥,您的数据将无法解密", - "NO_TWO_FACTOR_RECOVERY_KEY_MESSAGE": "请用您注册Ente账户的电子邮箱发一封邮件给 {{emailID}}", + "no_two_factor_recovery_key_message": "请用您注册Ente账户的电子邮箱发一封邮件给 {{emailID}}", "contact_support": "联系支持", "request_feature": "功能建议", "support": "支持", From d1bcd12599b67bfe72a1b4021113a1d7f8d2d795 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:38:21 +0530 Subject: [PATCH 182/438] Rename --- .../src/components/PhotoViewer/FileInfo/MapBox.tsx | 2 +- .../src/components/PhotoViewer/FileInfo/index.tsx | 10 +++++----- .../photos/src/components/Sidebar/MapSetting.tsx | 8 ++++---- web/packages/base/locales/ar-SA/translation.json | 12 ++++++------ web/packages/base/locales/bg-BG/translation.json | 12 ++++++------ web/packages/base/locales/ca-ES/translation.json | 12 ++++++------ web/packages/base/locales/da-DK/translation.json | 12 ++++++------ web/packages/base/locales/de-DE/translation.json | 12 ++++++------ web/packages/base/locales/el-GR/translation.json | 12 ++++++------ web/packages/base/locales/en-US/translation.json | 12 ++++++------ web/packages/base/locales/es-ES/translation.json | 12 ++++++------ web/packages/base/locales/et-EE/translation.json | 12 ++++++------ web/packages/base/locales/fa-IR/translation.json | 12 ++++++------ web/packages/base/locales/fi-FI/translation.json | 12 ++++++------ web/packages/base/locales/fr-FR/translation.json | 12 ++++++------ web/packages/base/locales/gu-IN/translation.json | 12 ++++++------ web/packages/base/locales/hi-IN/translation.json | 12 ++++++------ web/packages/base/locales/id-ID/translation.json | 12 ++++++------ web/packages/base/locales/is-IS/translation.json | 12 ++++++------ web/packages/base/locales/it-IT/translation.json | 12 ++++++------ web/packages/base/locales/ja-JP/translation.json | 12 ++++++------ web/packages/base/locales/km-KH/translation.json | 12 ++++++------ web/packages/base/locales/ko-KR/translation.json | 12 ++++++------ web/packages/base/locales/lt-LT/translation.json | 12 ++++++------ web/packages/base/locales/nl-NL/translation.json | 12 ++++++------ web/packages/base/locales/pl-PL/translation.json | 12 ++++++------ web/packages/base/locales/pt-BR/translation.json | 12 ++++++------ web/packages/base/locales/pt-PT/translation.json | 12 ++++++------ web/packages/base/locales/ru-RU/translation.json | 12 ++++++------ web/packages/base/locales/sl-SI/translation.json | 12 ++++++------ web/packages/base/locales/sv-SE/translation.json | 12 ++++++------ web/packages/base/locales/ta-IN/translation.json | 12 ++++++------ web/packages/base/locales/te-IN/translation.json | 12 ++++++------ web/packages/base/locales/th-TH/translation.json | 12 ++++++------ web/packages/base/locales/ti-ER/translation.json | 12 ++++++------ web/packages/base/locales/tr-TR/translation.json | 12 ++++++------ web/packages/base/locales/uk-UA/translation.json | 12 ++++++------ web/packages/base/locales/zh-CN/translation.json | 12 ++++++------ 38 files changed, 220 insertions(+), 220 deletions(-) diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/MapBox.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/MapBox.tsx index 0fcd6975ae..7e8656f104 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/MapBox.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/MapBox.tsx @@ -71,7 +71,7 @@ const MapBox: React.FC = ({ {" "} - {t("ENABLE_MAP")} + {t("enable_map")} ); diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx index 9f3c87ca7b..d92e2da420 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx @@ -229,7 +229,7 @@ export const FileInfo: React.FC = ({ fontWeight: "bold", }} > - {t("DISABLE_MAP")} + {t("disable_map")} ) } @@ -380,10 +380,10 @@ const parseExifInfo = ( const confirmEnableMapsDialogAttributes = ( onConfirm: () => void, ): MiniDialogAttributes => ({ - title: t("ENABLE_MAPS"), + title: t("enable_maps_confirm"), message: ( void, ): MiniDialogAttributes => ({ - title: t("DISABLE_MAPS"), - message: , + title: t("disable_maps_confirm"), + message: , continue: { text: t("disable"), color: "critical", action: onConfirm }, }); diff --git a/web/apps/photos/src/components/Sidebar/MapSetting.tsx b/web/apps/photos/src/components/Sidebar/MapSetting.tsx index c7206eabe4..99314acead 100644 --- a/web/apps/photos/src/components/Sidebar/MapSetting.tsx +++ b/web/apps/photos/src/components/Sidebar/MapSetting.tsx @@ -166,7 +166,7 @@ function EnableMap({ onClose, enableMap, onRootClose }) { @@ -174,7 +174,7 @@ function EnableMap({ onClose, enableMap, onRootClose }) { {" "} - + diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index b1178befb9..17ee3a4064 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "عرض على OpenStreetMap", "MAP": "خريطة", "MAP_SETTINGS": "إعدادات الخريطة", - "ENABLE_MAPS": "تمكين الخرائط ؟", - "ENABLE_MAP": "تمكين الخريطة", - "DISABLE_MAPS": "تعطيل الخرائط؟", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "تعطيل الخريطة", + "enable_maps_confirm": "تمكين الخرائط ؟", + "enable_map": "تمكين الخريطة", + "disable_maps_confirm": "تعطيل الخرائط؟", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "تعطيل الخريطة", "DETAILS": "تفاصيل", "view_exif": "عرض جميع بيانات Exif", "no_exif": "لا توجد بيانات Exif", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index c5f3838267..9073210a61 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index b4d7c44382..90c108e56a 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index 16abc5873d..58b5440797 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -239,12 +239,12 @@ "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", + "enable_maps_confirm": "Karten aktivieren?", + "enable_map": "Karte aktivieren", + "disable_maps_confirm": "Karten deaktivieren?", + "enable_maps_confirm_message": "

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

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", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index e8daa3c315..2650ced555 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Προβολή στο OpenStreetMap", "MAP": "Χάρτης", "MAP_SETTINGS": "Ρυθμίσεις Χάρτη", - "ENABLE_MAPS": "Ενεργοποίηση Χαρτών;", - "ENABLE_MAP": "Ενεργοποίηση χάρτη", - "DISABLE_MAPS": "Απενεργοποίηση Χαρτών;", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "Απενεργοποίηση χάρτη", + "enable_maps_confirm": "Ενεργοποίηση Χαρτών;", + "enable_map": "Ενεργοποίηση χάρτη", + "disable_maps_confirm": "Απενεργοποίηση Χαρτών;", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "Απενεργοποίηση χάρτη", "DETAILS": "Λεπτομέρειες", "view_exif": "Προβολή όλων των δεδομένων Exif", "no_exif": "Χωρίς δεδομένα Exif", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 66b76cefd9..6df99f777b 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -239,12 +239,12 @@ "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", + "enable_maps_confirm": "Enable Maps?", + "enable_map": "Enable map", + "disable_maps_confirm": "Disable Maps?", + "enable_maps_confirm_message": "

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

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", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index 2a13e6d291..5007f98b8f 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Ver en OpenStreetMap", "MAP": "Mapa", "MAP_SETTINGS": "", - "ENABLE_MAPS": "¿Activar Mapas?", - "ENABLE_MAP": "Activar mapa", - "DISABLE_MAPS": "¿Desactivar Mapas?", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "Desactivar mapa", + "enable_maps_confirm": "¿Activar Mapas?", + "enable_map": "Activar mapa", + "disable_maps_confirm": "¿Desactivar Mapas?", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "Desactivar mapa", "DETAILS": "Detalles", "view_exif": "Ver todos los datos de Exif", "no_exif": "No hay datos Exif", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index a961ac5866..556c37f346 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index d628604774..ee84a09946 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index dfbd1e992d..173761ebb3 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -239,12 +239,12 @@ "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", + "enable_maps_confirm": "Activer la carte?", + "enable_map": "Activer la carte", + "disable_maps_confirm": "Désactiver la carte?", + "enable_maps_confirm_message": "

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

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", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index 6b029eb361..c8ec75ab47 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Lihat di OpenStreetMap", "MAP": "Peta", "MAP_SETTINGS": "Pengaturan Peta", - "ENABLE_MAPS": "Aktifkan Peta?", - "ENABLE_MAP": "Aktifkan peta", - "DISABLE_MAPS": "Nonaktifkan Peta?", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "Nonaktifkan peta", + "enable_maps_confirm": "Aktifkan Peta?", + "enable_map": "Aktifkan peta", + "disable_maps_confirm": "Nonaktifkan Peta?", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "Nonaktifkan peta", "DETAILS": "Rincian", "view_exif": "Lihat seluruh data Exif", "no_exif": "Tidak ada data Exif", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index e29c0ba6cc..2fe7e22050 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index dc1e7ec7eb..8fc8cb8a07 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -239,12 +239,12 @@ "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": "

Questa opzione mostrerà le tue foto sulla mappa del mondo.

La mappa è ospitata da OpenStreetMap, la posizione esatta delle tue foto non saranno mai condivise.

Puoi disabilitare questa funzione in qualsiasi momento dalle Impostazioni.

", - "DISABLE_MAP_DESCRIPTION": "

Questo opzione disabiliterà la visualizzazione delle tue foto sulla mappa del mondo.

Puoi abilitare questa funzione in qualsiasi momento dalle impostazioni.

", - "DISABLE_MAP": "Disattivare Mappa", + "enable_maps_confirm": "Attivare Mappa?", + "enable_map": "Attivare mappa", + "disable_maps_confirm": "Disattivare Mappa?", + "enable_maps_confirm_message": "

Questa opzione mostrerà le tue foto sulla mappa del mondo.

La mappa è ospitata da OpenStreetMap, la posizione esatta delle tue foto non saranno mai condivise.

Puoi disabilitare questa funzione in qualsiasi momento dalle Impostazioni.

", + "disable_maps_confirm_message": "

Questo opzione disabiliterà la visualizzazione delle tue foto sulla mappa del mondo.

Puoi abilitare questa funzione in qualsiasi momento dalle impostazioni.

", + "disable_map": "Disattivare Mappa", "DETAILS": "Dettagli", "view_exif": "Mostra tutti i dati EXIF", "no_exif": "Nessun dato EXIF", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index 6d49a2ad62..a5b8e1e533 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 7fa4b0bb4d..97c30213c0 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 049ef69c33..a4d3343536 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Peržiūrėti žemėlapyje „OpenStreetMap“", "MAP": "Žemėlapis", "MAP_SETTINGS": "Žemėlapio nustatymai", - "ENABLE_MAPS": "Įjungti žemėlapius?", - "ENABLE_MAP": "Įjungti žemėlapį", - "DISABLE_MAPS": "Išjungti žemėlapius?", - "ENABLE_MAP_DESCRIPTION": "

Tai parodys jūsų nuotraukas pasaulio žemėlapyje.

Žemėlapį talpina „OpenStreetMap“, o tiksliomis nuotraukų vietomis niekada nebendrinama.

Šią funkciją bet kada galite išjungti iš nustatymų.

", - "DISABLE_MAP_DESCRIPTION": "

Tai išjungs jūsų nuotraukų rodymą pasaulio žemėlapyje.

Šią funkciją bet kada galite įjungti iš nustatymų.

", - "DISABLE_MAP": "Išjungti žemėlapį", + "enable_maps_confirm": "Įjungti žemėlapius?", + "enable_map": "Įjungti žemėlapį", + "disable_maps_confirm": "Išjungti žemėlapius?", + "enable_maps_confirm_message": "

Tai parodys jūsų nuotraukas pasaulio žemėlapyje.

Žemėlapį talpina „OpenStreetMap“, o tiksliomis nuotraukų vietomis niekada nebendrinama.

Šią funkciją bet kada galite išjungti iš nustatymų.

", + "disable_maps_confirm_message": "

Tai išjungs jūsų nuotraukų rodymą pasaulio žemėlapyje.

Šią funkciją bet kada galite įjungti iš nustatymų.

", + "disable_map": "Išjungti žemėlapį", "DETAILS": "Išsami informacija", "view_exif": "Peržiūrėti visus Exif duomenis", "no_exif": "Nėra Exif duomenų", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 5270f42c06..1bc02bb389 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -239,12 +239,12 @@ "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", + "enable_maps_confirm": "Kaarten inschakelen?", + "enable_map": "Kaarten inschakelen", + "disable_maps_confirm": "Kaarten uitzetten?", + "enable_maps_confirm_message": "

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

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", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index ef0f0c12ba..06bb9d312e 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Pokaż na OpenStreetMap", "MAP": "Mapa", "MAP_SETTINGS": "Ustawienia Mapy", - "ENABLE_MAPS": "Włączyć Mapy?", - "ENABLE_MAP": "Włącz mapę", - "DISABLE_MAPS": "Wyłączyć Mapy?", - "ENABLE_MAP_DESCRIPTION": "

To pokaże Twoje zdjęcia na mapie świata.

Mapa jest hostowana przez OpenStreetMap, a dokładne lokalizacje Twoich zdjęć nigdy nie są udostępniane.

Możesz wyłączyć tę funkcję w dowolnym momencie w Ustawieniach.

", - "DISABLE_MAP_DESCRIPTION": "

To wyłączy wyświetlanie zdjęć na mapie świata.

Możesz włączyć tę funkcję w dowolnym momencie w Ustawieniach.

", - "DISABLE_MAP": "Wyłącz mapę", + "enable_maps_confirm": "Włączyć Mapy?", + "enable_map": "Włącz mapę", + "disable_maps_confirm": "Wyłączyć Mapy?", + "enable_maps_confirm_message": "

To pokaże Twoje zdjęcia na mapie świata.

Mapa jest hostowana przez OpenStreetMap, a dokładne lokalizacje Twoich zdjęć nigdy nie są udostępniane.

Możesz wyłączyć tę funkcję w dowolnym momencie w Ustawieniach.

", + "disable_maps_confirm_message": "

To wyłączy wyświetlanie zdjęć na mapie świata.

Możesz włączyć tę funkcję w dowolnym momencie w Ustawieniach.

", + "disable_map": "Wyłącz mapę", "DETAILS": "Szczegóły", "view_exif": "Wyświetl wszystkie dane Exif", "no_exif": "Brak danych Exif", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index 127496c6eb..a4fe8db739 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Ver no OpenStreetMap", "MAP": "Mapa", "MAP_SETTINGS": "Configurações 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", + "enable_maps_confirm": "Habilitar mapa?", + "enable_map": "Habilitar mapa", + "disable_maps_confirm": "Desativar Mapas?", + "enable_maps_confirm_message": "

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

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", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 6c33a41166..587c907891 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 63392ce9ad..554fcb7ce2 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Просмотр на OpenStreetMap", "MAP": "Карта", "MAP_SETTINGS": "Настройки карты", - "ENABLE_MAPS": "Включить карты?", - "ENABLE_MAP": "Включить отображение", - "DISABLE_MAPS": "Отключить карты?", - "ENABLE_MAP_DESCRIPTION": "

Это отобразит ваши фотографии на карте мира.

Карта размещена на OpenStreetMap, и точные местоположения ваших фотографий никогда не публикуются.

Вы можете отключить эту функцию в любое время в настройках.

", - "DISABLE_MAP_DESCRIPTION": "

Это приведет к отключению отображения ваших фотографий на карте мира.

Вы можете включить эту функцию в любое время в настройках.

", - "DISABLE_MAP": "Отключить карту", + "enable_maps_confirm": "Включить карты?", + "enable_map": "Включить отображение", + "disable_maps_confirm": "Отключить карты?", + "enable_maps_confirm_message": "

Это отобразит ваши фотографии на карте мира.

Карта размещена на OpenStreetMap, и точные местоположения ваших фотографий никогда не публикуются.

Вы можете отключить эту функцию в любое время в настройках.

", + "disable_maps_confirm_message": "

Это приведет к отключению отображения ваших фотографий на карте мира.

Вы можете включить эту функцию в любое время в настройках.

", + "disable_map": "Отключить карту", "DETAILS": "Подробности", "view_exif": "Просмотр всех данных Exif", "no_exif": "Нет данных Exif", diff --git a/web/packages/base/locales/sl-SI/translation.json b/web/packages/base/locales/sl-SI/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/sl-SI/translation.json +++ b/web/packages/base/locales/sl-SI/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index 379d543ad6..b26bf6b4b5 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "Karta", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "Visa all Exif-data", "no_exif": "Ingen Exif-data", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index 2b5da1bcf4..6dc9d98c12 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/uk-UA/translation.json b/web/packages/base/locales/uk-UA/translation.json index 66d022fffe..a663bec974 100644 --- a/web/packages/base/locales/uk-UA/translation.json +++ b/web/packages/base/locales/uk-UA/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "ENABLE_MAPS": "", - "ENABLE_MAP": "", - "DISABLE_MAPS": "", - "ENABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP_DESCRIPTION": "", - "DISABLE_MAP": "", + "enable_maps_confirm": "", + "enable_map": "", + "disable_maps_confirm": "", + "enable_maps_confirm_message": "", + "disable_maps_confirm_message": "", + "disable_map": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index 6b22980c32..ea4fabda42 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "在 OpenStreetMap 上查看", "MAP": "地图", "MAP_SETTINGS": "地图设置", - "ENABLE_MAPS": "要启用地图吗?", - "ENABLE_MAP": "启用地图", - "DISABLE_MAPS": "要禁用地图吗?", - "ENABLE_MAP_DESCRIPTION": "

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

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

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

", - "DISABLE_MAP_DESCRIPTION": "

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

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

", - "DISABLE_MAP": "禁用地图", + "enable_maps_confirm": "要启用地图吗?", + "enable_map": "启用地图", + "disable_maps_confirm": "要禁用地图吗?", + "enable_maps_confirm_message": "

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

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

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

", + "disable_maps_confirm_message": "

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

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

", + "disable_map": "禁用地图", "DETAILS": "详情", "view_exif": "查看所有 Exif 数据", "no_exif": "无 Exif 数据", From 29477ab4a099e5f1dbaa0ea27126ca6e20a52944 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:40:27 +0530 Subject: [PATCH 183/438] Move --- web/packages/base/locales/ar-SA/translation.json | 6 +++--- web/packages/base/locales/bg-BG/translation.json | 6 +++--- web/packages/base/locales/ca-ES/translation.json | 6 +++--- web/packages/base/locales/da-DK/translation.json | 6 +++--- web/packages/base/locales/de-DE/translation.json | 6 +++--- web/packages/base/locales/el-GR/translation.json | 6 +++--- web/packages/base/locales/en-US/translation.json | 6 +++--- web/packages/base/locales/es-ES/translation.json | 6 +++--- web/packages/base/locales/et-EE/translation.json | 6 +++--- web/packages/base/locales/fa-IR/translation.json | 6 +++--- web/packages/base/locales/fi-FI/translation.json | 6 +++--- web/packages/base/locales/fr-FR/translation.json | 6 +++--- web/packages/base/locales/gu-IN/translation.json | 6 +++--- web/packages/base/locales/hi-IN/translation.json | 6 +++--- web/packages/base/locales/id-ID/translation.json | 6 +++--- web/packages/base/locales/is-IS/translation.json | 6 +++--- web/packages/base/locales/it-IT/translation.json | 6 +++--- web/packages/base/locales/ja-JP/translation.json | 6 +++--- web/packages/base/locales/km-KH/translation.json | 6 +++--- web/packages/base/locales/ko-KR/translation.json | 6 +++--- web/packages/base/locales/lt-LT/translation.json | 6 +++--- web/packages/base/locales/nl-NL/translation.json | 6 +++--- web/packages/base/locales/pl-PL/translation.json | 6 +++--- web/packages/base/locales/pt-BR/translation.json | 6 +++--- web/packages/base/locales/pt-PT/translation.json | 6 +++--- web/packages/base/locales/ru-RU/translation.json | 6 +++--- web/packages/base/locales/sl-SI/translation.json | 6 +++--- web/packages/base/locales/sv-SE/translation.json | 6 +++--- web/packages/base/locales/ta-IN/translation.json | 6 +++--- web/packages/base/locales/te-IN/translation.json | 6 +++--- web/packages/base/locales/th-TH/translation.json | 6 +++--- web/packages/base/locales/ti-ER/translation.json | 6 +++--- web/packages/base/locales/tr-TR/translation.json | 6 +++--- web/packages/base/locales/uk-UA/translation.json | 6 +++--- web/packages/base/locales/zh-CN/translation.json | 6 +++--- 35 files changed, 105 insertions(+), 105 deletions(-) diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index 17ee3a4064..100b4abd5b 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "عرض على OpenStreetMap", "MAP": "خريطة", "MAP_SETTINGS": "إعدادات الخريطة", - "enable_maps_confirm": "تمكين الخرائط ؟", "enable_map": "تمكين الخريطة", - "disable_maps_confirm": "تعطيل الخرائط؟", + "enable_maps_confirm": "تمكين الخرائط ؟", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "تعطيل الخريطة", + "disable_maps_confirm": "تعطيل الخرائط؟", + "disable_maps_confirm_message": "", "DETAILS": "تفاصيل", "view_exif": "عرض جميع بيانات Exif", "no_exif": "لا توجد بيانات Exif", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index 9073210a61..5438cbbd0c 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index 90c108e56a..5fb87a9742 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index 58b5440797..f481caa686 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "In OpenStreetMap öffnen", "MAP": "Karte", "MAP_SETTINGS": "Karten\nEinstellungen", - "enable_maps_confirm": "Karten aktivieren?", "enable_map": "Karte aktivieren", - "disable_maps_confirm": "Karten deaktivieren?", + "enable_maps_confirm": "Karten aktivieren?", "enable_maps_confirm_message": "

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

Dies wird die Anzeige deiner Fotos auf einer Weltkarte deaktivieren.

Du kannst diese Funktion jederzeit in den Einstellungen aktivieren.

", "disable_map": "Karte deaktivieren", + "disable_maps_confirm": "Karten deaktivieren?", + "disable_maps_confirm_message": "

Dies wird die Anzeige deiner Fotos auf einer Weltkarte deaktivieren.

Du kannst diese Funktion jederzeit in den Einstellungen aktivieren.

", "DETAILS": "Details", "view_exif": "Alle Exif-Daten anzeigen", "no_exif": "Keine Exif-Daten", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index 2650ced555..2ab0bdc6a2 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Προβολή στο OpenStreetMap", "MAP": "Χάρτης", "MAP_SETTINGS": "Ρυθμίσεις Χάρτη", - "enable_maps_confirm": "Ενεργοποίηση Χαρτών;", "enable_map": "Ενεργοποίηση χάρτη", - "disable_maps_confirm": "Απενεργοποίηση Χαρτών;", + "enable_maps_confirm": "Ενεργοποίηση Χαρτών;", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "Απενεργοποίηση χάρτη", + "disable_maps_confirm": "Απενεργοποίηση Χαρτών;", + "disable_maps_confirm_message": "", "DETAILS": "Λεπτομέρειες", "view_exif": "Προβολή όλων των δεδομένων Exif", "no_exif": "Χωρίς δεδομένα Exif", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 6df99f777b..b9ab78786b 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "View on OpenStreetMap", "MAP": "Map", "MAP_SETTINGS": "Map Settings", - "enable_maps_confirm": "Enable Maps?", "enable_map": "Enable map", - "disable_maps_confirm": "Disable Maps?", + "enable_maps_confirm": "Enable Maps?", "enable_maps_confirm_message": "

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

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

You can enable this feature anytime from Settings.

", "disable_map": "Disable map", + "disable_maps_confirm": "Disable Maps?", + "disable_maps_confirm_message": "

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

You can enable this feature anytime from Settings.

", "DETAILS": "Details", "view_exif": "View all Exif data", "no_exif": "No Exif data", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index 5007f98b8f..8716d58e1e 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Ver en OpenStreetMap", "MAP": "Mapa", "MAP_SETTINGS": "", - "enable_maps_confirm": "¿Activar Mapas?", "enable_map": "Activar mapa", - "disable_maps_confirm": "¿Desactivar Mapas?", + "enable_maps_confirm": "¿Activar Mapas?", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "Desactivar mapa", + "disable_maps_confirm": "¿Desactivar Mapas?", + "disable_maps_confirm_message": "", "DETAILS": "Detalles", "view_exif": "Ver todos los datos de Exif", "no_exif": "No hay datos Exif", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index 556c37f346..c7c6281996 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index ee84a09946..f56059bbe1 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 173761ebb3..35da86b87e 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Visualiser sur OpenStreetMap", "MAP": "Carte", "MAP_SETTINGS": "Paramètres de la carte", - "enable_maps_confirm": "Activer la carte?", "enable_map": "Activer la carte", - "disable_maps_confirm": "Désactiver la carte?", + "enable_maps_confirm": "Activer la carte?", "enable_maps_confirm_message": "

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

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", + "disable_maps_confirm": "Désactiver la carte?", + "disable_maps_confirm_message": "

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.

", "DETAILS": "Détails", "view_exif": "Visualiser toutes les données Exif", "no_exif": "Aucune donnée Exif", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index c8ec75ab47..625e7a1527 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Lihat di OpenStreetMap", "MAP": "Peta", "MAP_SETTINGS": "Pengaturan Peta", - "enable_maps_confirm": "Aktifkan Peta?", "enable_map": "Aktifkan peta", - "disable_maps_confirm": "Nonaktifkan Peta?", + "enable_maps_confirm": "Aktifkan Peta?", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "Nonaktifkan peta", + "disable_maps_confirm": "Nonaktifkan Peta?", + "disable_maps_confirm_message": "", "DETAILS": "Rincian", "view_exif": "Lihat seluruh data Exif", "no_exif": "Tidak ada data Exif", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index 2fe7e22050..f98289cd81 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index 8fc8cb8a07..54a6a8db65 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Guarda su OpenStreetMap", "MAP": "Mappa", "MAP_SETTINGS": "Impostazioni Mappa", - "enable_maps_confirm": "Attivare Mappa?", "enable_map": "Attivare mappa", - "disable_maps_confirm": "Disattivare Mappa?", + "enable_maps_confirm": "Attivare Mappa?", "enable_maps_confirm_message": "

Questa opzione mostrerà le tue foto sulla mappa del mondo.

La mappa è ospitata da OpenStreetMap, la posizione esatta delle tue foto non saranno mai condivise.

Puoi disabilitare questa funzione in qualsiasi momento dalle Impostazioni.

", - "disable_maps_confirm_message": "

Questo opzione disabiliterà la visualizzazione delle tue foto sulla mappa del mondo.

Puoi abilitare questa funzione in qualsiasi momento dalle impostazioni.

", "disable_map": "Disattivare Mappa", + "disable_maps_confirm": "Disattivare Mappa?", + "disable_maps_confirm_message": "

Questo opzione disabiliterà la visualizzazione delle tue foto sulla mappa del mondo.

Puoi abilitare questa funzione in qualsiasi momento dalle impostazioni.

", "DETAILS": "Dettagli", "view_exif": "Mostra tutti i dati EXIF", "no_exif": "Nessun dato EXIF", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index a5b8e1e533..9ccf0cbdec 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 97c30213c0..485d0217e5 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index a4d3343536..ff6fb29904 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Peržiūrėti žemėlapyje „OpenStreetMap“", "MAP": "Žemėlapis", "MAP_SETTINGS": "Žemėlapio nustatymai", - "enable_maps_confirm": "Įjungti žemėlapius?", "enable_map": "Įjungti žemėlapį", - "disable_maps_confirm": "Išjungti žemėlapius?", + "enable_maps_confirm": "Įjungti žemėlapius?", "enable_maps_confirm_message": "

Tai parodys jūsų nuotraukas pasaulio žemėlapyje.

Žemėlapį talpina „OpenStreetMap“, o tiksliomis nuotraukų vietomis niekada nebendrinama.

Šią funkciją bet kada galite išjungti iš nustatymų.

", - "disable_maps_confirm_message": "

Tai išjungs jūsų nuotraukų rodymą pasaulio žemėlapyje.

Šią funkciją bet kada galite įjungti iš nustatymų.

", "disable_map": "Išjungti žemėlapį", + "disable_maps_confirm": "Išjungti žemėlapius?", + "disable_maps_confirm_message": "

Tai išjungs jūsų nuotraukų rodymą pasaulio žemėlapyje.

Šią funkciją bet kada galite įjungti iš nustatymų.

", "DETAILS": "Išsami informacija", "view_exif": "Peržiūrėti visus Exif duomenis", "no_exif": "Nėra Exif duomenų", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 1bc02bb389..2545ccd882 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Bekijk op OpenStreetMap", "MAP": "Kaart", "MAP_SETTINGS": "Kaart instellingen", - "enable_maps_confirm": "Kaarten inschakelen?", "enable_map": "Kaarten inschakelen", - "disable_maps_confirm": "Kaarten uitzetten?", + "enable_maps_confirm": "Kaarten inschakelen?", "enable_maps_confirm_message": "

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

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", + "disable_maps_confirm": "Kaarten uitzetten?", + "disable_maps_confirm_message": "

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

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

", "DETAILS": "Details", "view_exif": "Bekijk alle Exif gegevens", "no_exif": "Geen Exif gegevens", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 06bb9d312e..c457f64f54 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Pokaż na OpenStreetMap", "MAP": "Mapa", "MAP_SETTINGS": "Ustawienia Mapy", - "enable_maps_confirm": "Włączyć Mapy?", "enable_map": "Włącz mapę", - "disable_maps_confirm": "Wyłączyć Mapy?", + "enable_maps_confirm": "Włączyć Mapy?", "enable_maps_confirm_message": "

To pokaże Twoje zdjęcia na mapie świata.

Mapa jest hostowana przez OpenStreetMap, a dokładne lokalizacje Twoich zdjęć nigdy nie są udostępniane.

Możesz wyłączyć tę funkcję w dowolnym momencie w Ustawieniach.

", - "disable_maps_confirm_message": "

To wyłączy wyświetlanie zdjęć na mapie świata.

Możesz włączyć tę funkcję w dowolnym momencie w Ustawieniach.

", "disable_map": "Wyłącz mapę", + "disable_maps_confirm": "Wyłączyć Mapy?", + "disable_maps_confirm_message": "

To wyłączy wyświetlanie zdjęć na mapie świata.

Możesz włączyć tę funkcję w dowolnym momencie w Ustawieniach.

", "DETAILS": "Szczegóły", "view_exif": "Wyświetl wszystkie dane Exif", "no_exif": "Brak danych Exif", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index a4fe8db739..977016d4db 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Ver no OpenStreetMap", "MAP": "Mapa", "MAP_SETTINGS": "Configurações do Mapa", - "enable_maps_confirm": "Habilitar mapa?", "enable_map": "Habilitar mapa", - "disable_maps_confirm": "Desativar Mapas?", + "enable_maps_confirm": "Habilitar mapa?", "enable_maps_confirm_message": "

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

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", + "disable_maps_confirm": "Desativar Mapas?", + "disable_maps_confirm_message": "

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

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

", "DETAILS": "Detalhes", "view_exif": "Ver todos os dados Exif", "no_exif": "Sem dados Exif", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 587c907891..b1aa951e77 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 554fcb7ce2..0f5cc02312 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "Просмотр на OpenStreetMap", "MAP": "Карта", "MAP_SETTINGS": "Настройки карты", - "enable_maps_confirm": "Включить карты?", "enable_map": "Включить отображение", - "disable_maps_confirm": "Отключить карты?", + "enable_maps_confirm": "Включить карты?", "enable_maps_confirm_message": "

Это отобразит ваши фотографии на карте мира.

Карта размещена на OpenStreetMap, и точные местоположения ваших фотографий никогда не публикуются.

Вы можете отключить эту функцию в любое время в настройках.

", - "disable_maps_confirm_message": "

Это приведет к отключению отображения ваших фотографий на карте мира.

Вы можете включить эту функцию в любое время в настройках.

", "disable_map": "Отключить карту", + "disable_maps_confirm": "Отключить карты?", + "disable_maps_confirm_message": "

Это приведет к отключению отображения ваших фотографий на карте мира.

Вы можете включить эту функцию в любое время в настройках.

", "DETAILS": "Подробности", "view_exif": "Просмотр всех данных Exif", "no_exif": "Нет данных Exif", diff --git a/web/packages/base/locales/sl-SI/translation.json b/web/packages/base/locales/sl-SI/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/sl-SI/translation.json +++ b/web/packages/base/locales/sl-SI/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index b26bf6b4b5..0bca949fcc 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "Karta", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "Visa all Exif-data", "no_exif": "Ingen Exif-data", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index 6dc9d98c12..33781a94f6 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/uk-UA/translation.json b/web/packages/base/locales/uk-UA/translation.json index a663bec974..f485cf6bf3 100644 --- a/web/packages/base/locales/uk-UA/translation.json +++ b/web/packages/base/locales/uk-UA/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "", "MAP": "", "MAP_SETTINGS": "", - "enable_maps_confirm": "", "enable_map": "", - "disable_maps_confirm": "", + "enable_maps_confirm": "", "enable_maps_confirm_message": "", - "disable_maps_confirm_message": "", "disable_map": "", + "disable_maps_confirm": "", + "disable_maps_confirm_message": "", "DETAILS": "", "view_exif": "", "no_exif": "", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index ea4fabda42..a55ff97386 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -239,12 +239,12 @@ "SHOW_ON_MAP": "在 OpenStreetMap 上查看", "MAP": "地图", "MAP_SETTINGS": "地图设置", - "enable_maps_confirm": "要启用地图吗?", "enable_map": "启用地图", - "disable_maps_confirm": "要禁用地图吗?", + "enable_maps_confirm": "要启用地图吗?", "enable_maps_confirm_message": "

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

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

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

", - "disable_maps_confirm_message": "

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

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

", "disable_map": "禁用地图", + "disable_maps_confirm": "要禁用地图吗?", + "disable_maps_confirm_message": "

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

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

", "DETAILS": "详情", "view_exif": "查看所有 Exif 数据", "no_exif": "无 Exif 数据", From c48fbb328bd0da28a8f61490f6bc79c9df6efe30 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:41:29 +0530 Subject: [PATCH 184/438] Rename --- web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx | 2 +- web/packages/base/locales/ar-SA/translation.json | 2 +- web/packages/base/locales/bg-BG/translation.json | 2 +- web/packages/base/locales/ca-ES/translation.json | 2 +- web/packages/base/locales/da-DK/translation.json | 2 +- web/packages/base/locales/de-DE/translation.json | 2 +- web/packages/base/locales/el-GR/translation.json | 2 +- web/packages/base/locales/en-US/translation.json | 2 +- web/packages/base/locales/es-ES/translation.json | 2 +- web/packages/base/locales/et-EE/translation.json | 2 +- web/packages/base/locales/fa-IR/translation.json | 2 +- web/packages/base/locales/fi-FI/translation.json | 2 +- web/packages/base/locales/fr-FR/translation.json | 2 +- web/packages/base/locales/gu-IN/translation.json | 2 +- web/packages/base/locales/hi-IN/translation.json | 2 +- web/packages/base/locales/id-ID/translation.json | 2 +- web/packages/base/locales/is-IS/translation.json | 2 +- web/packages/base/locales/it-IT/translation.json | 2 +- web/packages/base/locales/ja-JP/translation.json | 2 +- web/packages/base/locales/km-KH/translation.json | 2 +- web/packages/base/locales/ko-KR/translation.json | 2 +- web/packages/base/locales/lt-LT/translation.json | 2 +- web/packages/base/locales/nl-NL/translation.json | 2 +- web/packages/base/locales/pl-PL/translation.json | 2 +- web/packages/base/locales/pt-BR/translation.json | 2 +- web/packages/base/locales/pt-PT/translation.json | 2 +- web/packages/base/locales/ru-RU/translation.json | 2 +- web/packages/base/locales/sl-SI/translation.json | 2 +- web/packages/base/locales/sv-SE/translation.json | 2 +- web/packages/base/locales/ta-IN/translation.json | 2 +- web/packages/base/locales/te-IN/translation.json | 2 +- web/packages/base/locales/th-TH/translation.json | 2 +- web/packages/base/locales/ti-ER/translation.json | 2 +- web/packages/base/locales/tr-TR/translation.json | 2 +- web/packages/base/locales/uk-UA/translation.json | 2 +- web/packages/base/locales/zh-CN/translation.json | 2 +- 36 files changed, 36 insertions(+), 36 deletions(-) diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx index d92e2da420..2f20e168aa 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx @@ -216,7 +216,7 @@ export const FileInfo: React.FC = ({ rel="noopener" sx={{ fontWeight: "bold" }} > - {t("SHOW_ON_MAP")} + {t("view_on_map")} ) : ( Date: Thu, 10 Oct 2024 20:43:45 +0530 Subject: [PATCH 185/438] Rename --- web/apps/photos/src/components/Sidebar/MapSetting.tsx | 4 ++-- web/apps/photos/src/components/Sidebar/Preferences.tsx | 2 +- web/packages/base/locales/ar-SA/translation.json | 4 ++-- web/packages/base/locales/bg-BG/translation.json | 4 ++-- web/packages/base/locales/ca-ES/translation.json | 4 ++-- web/packages/base/locales/da-DK/translation.json | 4 ++-- web/packages/base/locales/de-DE/translation.json | 4 ++-- web/packages/base/locales/el-GR/translation.json | 4 ++-- web/packages/base/locales/en-US/translation.json | 4 ++-- web/packages/base/locales/es-ES/translation.json | 4 ++-- web/packages/base/locales/et-EE/translation.json | 4 ++-- web/packages/base/locales/fa-IR/translation.json | 4 ++-- web/packages/base/locales/fi-FI/translation.json | 4 ++-- web/packages/base/locales/fr-FR/translation.json | 4 ++-- web/packages/base/locales/gu-IN/translation.json | 4 ++-- web/packages/base/locales/hi-IN/translation.json | 4 ++-- web/packages/base/locales/id-ID/translation.json | 4 ++-- web/packages/base/locales/is-IS/translation.json | 4 ++-- web/packages/base/locales/it-IT/translation.json | 4 ++-- web/packages/base/locales/ja-JP/translation.json | 4 ++-- web/packages/base/locales/km-KH/translation.json | 4 ++-- web/packages/base/locales/ko-KR/translation.json | 4 ++-- web/packages/base/locales/lt-LT/translation.json | 4 ++-- web/packages/base/locales/nl-NL/translation.json | 4 ++-- web/packages/base/locales/pl-PL/translation.json | 4 ++-- web/packages/base/locales/pt-BR/translation.json | 4 ++-- web/packages/base/locales/pt-PT/translation.json | 4 ++-- web/packages/base/locales/ru-RU/translation.json | 4 ++-- web/packages/base/locales/sl-SI/translation.json | 4 ++-- web/packages/base/locales/sv-SE/translation.json | 4 ++-- web/packages/base/locales/ta-IN/translation.json | 4 ++-- web/packages/base/locales/te-IN/translation.json | 4 ++-- web/packages/base/locales/th-TH/translation.json | 4 ++-- web/packages/base/locales/ti-ER/translation.json | 4 ++-- web/packages/base/locales/tr-TR/translation.json | 4 ++-- web/packages/base/locales/uk-UA/translation.json | 4 ++-- web/packages/base/locales/zh-CN/translation.json | 4 ++-- 37 files changed, 73 insertions(+), 73 deletions(-) diff --git a/web/apps/photos/src/components/Sidebar/MapSetting.tsx b/web/apps/photos/src/components/Sidebar/MapSetting.tsx index 99314acead..e8106a1d58 100644 --- a/web/apps/photos/src/components/Sidebar/MapSetting.tsx +++ b/web/apps/photos/src/components/Sidebar/MapSetting.tsx @@ -65,7 +65,7 @@ export const MapSettings: React.FC = ({ @@ -77,7 +77,7 @@ export const MapSettings: React.FC = ({ onClick={openModifyMapEnabled} variant="toggle" checked={mapEnabled} - label={t("MAP_SETTINGS")} + label={t("map_settings")} />
diff --git a/web/apps/photos/src/components/Sidebar/Preferences.tsx b/web/apps/photos/src/components/Sidebar/Preferences.tsx index f88f52bb05..135e817227 100644 --- a/web/apps/photos/src/components/Sidebar/Preferences.tsx +++ b/web/apps/photos/src/components/Sidebar/Preferences.tsx @@ -69,7 +69,7 @@ export const Preferences: React.FC = ({ } - label={t("MAP")} + label={t("map")} /> 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.

", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index 68efecb58a..256ec9ec21 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Προσθήκη περιγραφής", "location": "Τοποθεσία", "view_on_map": "Προβολή στο OpenStreetMap", - "MAP": "Χάρτης", - "MAP_SETTINGS": "Ρυθμίσεις Χάρτη", + "map": "Χάρτης", + "map_settings": "Ρυθμίσεις Χάρτη", "enable_map": "Ενεργοποίηση χάρτη", "enable_maps_confirm": "Ενεργοποίηση Χαρτών;", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 008f4642a9..3e81650091 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Add a description", "location": "Location", "view_on_map": "View on OpenStreetMap", - "MAP": "Map", - "MAP_SETTINGS": "Map Settings", + "map": "Map", + "map_settings": "Map Settings", "enable_map": "Enable map", "enable_maps_confirm": "Enable Maps?", "enable_maps_confirm_message": "

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.

", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index cd0ef34542..6e81720869 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Añadir una descripción", "location": "Localización", "view_on_map": "Ver en OpenStreetMap", - "MAP": "Mapa", - "MAP_SETTINGS": "", + "map": "Mapa", + "map_settings": "", "enable_map": "Activar mapa", "enable_maps_confirm": "¿Activar Mapas?", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index 82054fba5e..c1f1ab43e7 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index 04011207f5..476809a8ff 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 041cb55230..eff3b12aa1 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Ajouter une description", "location": "Emplacement", "view_on_map": "Visualiser sur OpenStreetMap", - "MAP": "Carte", - "MAP_SETTINGS": "Paramètres de la carte", + "map": "Carte", + "map_settings": "Paramètres de la carte", "enable_map": "Activer la carte", "enable_maps_confirm": "Activer la carte?", "enable_maps_confirm_message": "

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.

", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index 8927df6f0c..6a616208c1 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Tambah keterangan", "location": "", "view_on_map": "Lihat di OpenStreetMap", - "MAP": "Peta", - "MAP_SETTINGS": "Pengaturan Peta", + "map": "Peta", + "map_settings": "Pengaturan Peta", "enable_map": "Aktifkan peta", "enable_maps_confirm": "Aktifkan Peta?", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index 8aa283ba89..4089decb62 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index 1e2aa17344..a73d705f5e 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Aggiungi una descrizione", "location": "Posizione", "view_on_map": "Guarda su OpenStreetMap", - "MAP": "Mappa", - "MAP_SETTINGS": "Impostazioni Mappa", + "map": "Mappa", + "map_settings": "Impostazioni Mappa", "enable_map": "Attivare mappa", "enable_maps_confirm": "Attivare Mappa?", "enable_maps_confirm_message": "

Questa opzione mostrerà le tue foto sulla mappa del mondo.

La mappa è ospitata da OpenStreetMap, la posizione esatta delle tue foto non saranno mai condivise.

Puoi disabilitare questa funzione in qualsiasi momento dalle Impostazioni.

", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index 4d2bf6b664..2d7d0d9bdc 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index bccf23a063..4ec9d199a1 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 652e071708..1b69520e2f 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Pridėti aprašymą", "location": "Vietovė", "view_on_map": "Peržiūrėti žemėlapyje „OpenStreetMap“", - "MAP": "Žemėlapis", - "MAP_SETTINGS": "Žemėlapio nustatymai", + "map": "Žemėlapis", + "map_settings": "Žemėlapio nustatymai", "enable_map": "Įjungti žemėlapį", "enable_maps_confirm": "Įjungti žemėlapius?", "enable_maps_confirm_message": "

Tai parodys jūsų nuotraukas pasaulio žemėlapyje.

Žemėlapį talpina „OpenStreetMap“, o tiksliomis nuotraukų vietomis niekada nebendrinama.

Šią funkciją bet kada galite išjungti iš nustatymų.

", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 874335619b..5f03abbc76 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Voeg een beschrijving toe", "location": "Locatie", "view_on_map": "Bekijk op OpenStreetMap", - "MAP": "Kaart", - "MAP_SETTINGS": "Kaart instellingen", + "map": "Kaart", + "map_settings": "Kaart instellingen", "enable_map": "Kaarten inschakelen", "enable_maps_confirm": "Kaarten inschakelen?", "enable_maps_confirm_message": "

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.

", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 22a2583ec5..492376cfbe 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Dodaj opis", "location": "Lokalizacja", "view_on_map": "Pokaż na OpenStreetMap", - "MAP": "Mapa", - "MAP_SETTINGS": "Ustawienia Mapy", + "map": "Mapa", + "map_settings": "Ustawienia Mapy", "enable_map": "Włącz mapę", "enable_maps_confirm": "Włączyć Mapy?", "enable_maps_confirm_message": "

To pokaże Twoje zdjęcia na mapie świata.

Mapa jest hostowana przez OpenStreetMap, a dokładne lokalizacje Twoich zdjęć nigdy nie są udostępniane.

Możesz wyłączyć tę funkcję w dowolnym momencie w Ustawieniach.

", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index 136dbbfb5a..c60c744753 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Adicionar uma descrição", "location": "Local", "view_on_map": "Ver no OpenStreetMap", - "MAP": "Mapa", - "MAP_SETTINGS": "Configurações do Mapa", + "map": "Mapa", + "map_settings": "Configurações do Mapa", "enable_map": "Habilitar mapa", "enable_maps_confirm": "Habilitar mapa?", "enable_maps_confirm_message": "

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.

", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 03b8c02410..b1b98a0a22 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 3359caae88..57150c0488 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Добавьте описание", "location": "Местоположение", "view_on_map": "Просмотр на OpenStreetMap", - "MAP": "Карта", - "MAP_SETTINGS": "Настройки карты", + "map": "Карта", + "map_settings": "Настройки карты", "enable_map": "Включить отображение", "enable_maps_confirm": "Включить карты?", "enable_maps_confirm_message": "

Это отобразит ваши фотографии на карте мира.

Карта размещена на OpenStreetMap, и точные местоположения ваших фотографий никогда не публикуются.

Вы можете отключить эту функцию в любое время в настройках.

", diff --git a/web/packages/base/locales/sl-SI/translation.json b/web/packages/base/locales/sl-SI/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/sl-SI/translation.json +++ b/web/packages/base/locales/sl-SI/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index 24907c7f18..4e03994ceb 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "Lägg till en beskrivning", "location": "", "view_on_map": "", - "MAP": "Karta", - "MAP_SETTINGS": "", + "map": "Karta", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index 8831e69e65..80a2f93dc9 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/uk-UA/translation.json b/web/packages/base/locales/uk-UA/translation.json index 8574fb981c..2826dd17b0 100644 --- a/web/packages/base/locales/uk-UA/translation.json +++ b/web/packages/base/locales/uk-UA/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "", "location": "", "view_on_map": "", - "MAP": "", - "MAP_SETTINGS": "", + "map": "", + "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index c724e67f9c..48cb2f5ad2 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -237,8 +237,8 @@ "CAPTION_PLACEHOLDER": "添加说明", "location": "地理位置", "view_on_map": "在 OpenStreetMap 上查看", - "MAP": "地图", - "MAP_SETTINGS": "地图设置", + "map": "地图", + "map_settings": "地图设置", "enable_map": "启用地图", "enable_maps_confirm": "要启用地图吗?", "enable_maps_confirm_message": "

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

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

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

", From 96e541acb497e5c581d256aa0eadfae3a58978db Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:47:16 +0530 Subject: [PATCH 186/438] Fix --- web/packages/base/locales/de-DE/translation.json | 2 +- web/packages/base/locales/en-US/translation.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index 5c50ef9a64..cf8c5a5e71 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -238,7 +238,7 @@ "location": "Standort", "view_on_map": "In OpenStreetMap öffnen", "map": "Karte", - "map_settings": "Karten\nEinstellungen", + "map_settings": "Karten Einstellungen", "enable_map": "Karte aktivieren", "enable_maps_confirm": "Karten aktivieren?", "enable_maps_confirm_message": "

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.

", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 3e81650091..24485e0c88 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -238,7 +238,7 @@ "location": "Location", "view_on_map": "View on OpenStreetMap", "map": "Map", - "map_settings": "Map Settings", + "map_settings": "Map settings", "enable_map": "Enable map", "enable_maps_confirm": "Enable Maps?", "enable_maps_confirm_message": "

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.

", From 16f54342aeeffdd06ec4d291c59428af3f54055f Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:49:38 +0530 Subject: [PATCH 187/438] Rename --- web/apps/photos/src/components/Sidebar/index.tsx | 4 ++-- web/packages/base/locales/ar-SA/translation.json | 4 ++-- web/packages/base/locales/bg-BG/translation.json | 4 ++-- web/packages/base/locales/ca-ES/translation.json | 4 ++-- web/packages/base/locales/da-DK/translation.json | 4 ++-- web/packages/base/locales/de-DE/translation.json | 4 ++-- web/packages/base/locales/el-GR/translation.json | 4 ++-- web/packages/base/locales/en-US/translation.json | 4 ++-- web/packages/base/locales/es-ES/translation.json | 4 ++-- web/packages/base/locales/et-EE/translation.json | 4 ++-- web/packages/base/locales/fa-IR/translation.json | 4 ++-- web/packages/base/locales/fi-FI/translation.json | 4 ++-- web/packages/base/locales/fr-FR/translation.json | 4 ++-- web/packages/base/locales/gu-IN/translation.json | 4 ++-- web/packages/base/locales/hi-IN/translation.json | 4 ++-- web/packages/base/locales/id-ID/translation.json | 4 ++-- web/packages/base/locales/is-IS/translation.json | 4 ++-- web/packages/base/locales/it-IT/translation.json | 4 ++-- web/packages/base/locales/ja-JP/translation.json | 4 ++-- web/packages/base/locales/km-KH/translation.json | 4 ++-- web/packages/base/locales/ko-KR/translation.json | 4 ++-- web/packages/base/locales/lt-LT/translation.json | 4 ++-- web/packages/base/locales/nl-NL/translation.json | 4 ++-- web/packages/base/locales/pl-PL/translation.json | 4 ++-- web/packages/base/locales/pt-BR/translation.json | 4 ++-- web/packages/base/locales/pt-PT/translation.json | 4 ++-- web/packages/base/locales/ru-RU/translation.json | 4 ++-- web/packages/base/locales/sl-SI/translation.json | 4 ++-- web/packages/base/locales/sv-SE/translation.json | 4 ++-- web/packages/base/locales/ta-IN/translation.json | 4 ++-- web/packages/base/locales/te-IN/translation.json | 4 ++-- web/packages/base/locales/th-TH/translation.json | 4 ++-- web/packages/base/locales/ti-ER/translation.json | 4 ++-- web/packages/base/locales/tr-TR/translation.json | 4 ++-- web/packages/base/locales/uk-UA/translation.json | 4 ++-- web/packages/base/locales/zh-CN/translation.json | 4 ++-- 36 files changed, 72 insertions(+), 72 deletions(-) diff --git a/web/apps/photos/src/components/Sidebar/index.tsx b/web/apps/photos/src/components/Sidebar/index.tsx index 6f54c88582..21d61e2c84 100644 --- a/web/apps/photos/src/components/Sidebar/index.tsx +++ b/web/apps/photos/src/components/Sidebar/index.tsx @@ -680,8 +680,8 @@ const DebugSection: React.FC = () => { const confirmLogDownload = () => showMiniDialog({ - title: t("DOWNLOAD_LOGS"), - message: , + title: t("download_logs"), + message: , continue: { text: t("download"), action: downloadLogs, diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index f9f1781125..21ee2f2e45 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index 4b6822741c..926a030303 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index 8ed9047651..2393d30916 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index cf8c5a5e71..dbbf2cc584 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Ordner ändern", "FAMILY_PLAN": "Familientarif", "debug_logs": "Debug-Logs", - "DOWNLOAD_LOGS": "Logs herunterladen", - "DOWNLOAD_LOGS_MESSAGE": "

Hier kannst du Debug-Logs herunterladen, die du uns zur Fehleranalyse zusenden kannst.

Beachte bitte, dass die Logs Dateinamen enthalten, um Probleme mit bestimmten Dateien nachvollziehen zu können.

", + "download_logs": "Logs herunterladen", + "download_logs_message": "

Hier kannst du Debug-Logs herunterladen, die du uns zur Fehleranalyse zusenden kannst.

Beachte bitte, dass die Logs Dateinamen enthalten, um Probleme mit bestimmten Dateien nachvollziehen zu können.

", "WEAK_DEVICE": "Dein Browser ist nicht leistungsstark genug, um deine Bilder zu verschlüsseln. Versuche, dich an einem Computer bei Ente anzumelden, oder lade dir die Ente-App für dein Gerät (Handy oder Desktop) herunter.", "drag_and_drop_hint": "Oder ziehe Dateien per Drag-and-Drop in das Ente-Fenster", "AUTHENTICATE": "Authentifizieren", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index 256ec9ec21..4ebc3670b2 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 24485e0c88..6bff64df75 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Change Folder", "FAMILY_PLAN": "Family plan", "debug_logs": "Debug logs", - "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.

", + "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.

", "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", "AUTHENTICATE": "Authenticate", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index 6e81720869..5c4e5de667 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Cambiar carpeta", "FAMILY_PLAN": "Plan familiar", "debug_logs": "Logs de depuración", - "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.

", + "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.

", "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", "AUTHENTICATE": "Autenticado", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index c1f1ab43e7..689f162b3d 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index 476809a8ff..7a99182d79 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index eff3b12aa1..f4be638fb9 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Modifier le dossier", "FAMILY_PLAN": "Plan famille", "debug_logs": "Journaux de débugs", - "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 .

", + "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 .

", "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", "AUTHENTICATE": "Authentification", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index 6a616208c1..7b7e9dc530 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Ubah Folder", "FAMILY_PLAN": "Paket keluarga", "debug_logs": "Log debug", - "DOWNLOAD_LOGS": "Unduh log", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "Unduh log", + "download_logs_message": "", "WEAK_DEVICE": "Browser yang saat ini kamu gunakan tidak cukup kuat untuk mengenkripsi fotomu. Silakan coba gunakan Ente di komputer lain, atau unduh app seluler/desktop Ente.", "drag_and_drop_hint": "Atau seret ke jendela Ente", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index 4089decb62..d3c25e9f1e 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index a73d705f5e..f6c6526ef4 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Cambia Cartella", "FAMILY_PLAN": "Piano famiglia", "debug_logs": "Log di debug", - "DOWNLOAD_LOGS": "Scarica i log", - "DOWNLOAD_LOGS_MESSAGE": "

Questo scaricherà il log di debug che puoi inviare via email a noi per aiutare a capire il tuo problema.

Nota che i nomi dei file saranno inclusi per aiutare a tenere traccia dei problemi con i file specifici.

", + "download_logs": "Scarica i log", + "download_logs_message": "

Questo scaricherà il log di debug che puoi inviare via email a noi per aiutare a capire il tuo problema.

Nota che i nomi dei file saranno inclusi per aiutare a tenere traccia dei problemi con i file specifici.

", "WEAK_DEVICE": "Il browser web che stai usando non è abbastanza potente per crittografare le foto. Prova ad accedere a Ente sul tuo computer o scarica l'app mobile/desktop Ente.", "drag_and_drop_hint": "Oppure trascina nella finestra di Ente", "AUTHENTICATE": "Autenticati", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index 2d7d0d9bdc..62a3af13f3 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 4ec9d199a1..04380b53c6 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 1b69520e2f..f1f9d2e4a3 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "Nustatyti tapatybę", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 5f03abbc76..23df18005b 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Map wijzigen", "FAMILY_PLAN": "Familie abonnement", "debug_logs": "Logboeken voor foutmeldingen", - "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.

", + "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.

", "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", "AUTHENTICATE": "Verifiëren", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 492376cfbe..b1194ee975 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Zmień Folder", "FAMILY_PLAN": "Plan rodzinny", "debug_logs": "Logi debugowania", - "DOWNLOAD_LOGS": "Pobierz logi", - "DOWNLOAD_LOGS_MESSAGE": "

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

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

", + "download_logs": "Pobierz logi", + "download_logs_message": "

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

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

", "WEAK_DEVICE": "Przeglądarka, której używasz nie jest wystarczająco silna, aby zaszyfrować Twoje zdjęcia. Prosimy zalogować się do Ente na Twoim komputerze lub pobierz aplikacje mobilną/komputerową Ente.", "drag_and_drop_hint": "Lub przeciągnij i upuść do okna Ente", "AUTHENTICATE": "Uwierzytelnij się", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index c60c744753..fce890ce8f 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Alterar pasta", "FAMILY_PLAN": "Plano familiar", "debug_logs": "Logs de depuração", - "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.

", + "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.

", "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", "AUTHENTICATE": "Autenticar", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index b1b98a0a22..84c80ae963 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 57150c0488..6dacea58b6 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Изменить папку", "FAMILY_PLAN": "Семейный план", "debug_logs": "Журналы отладки", - "DOWNLOAD_LOGS": "Загрузка журналов", - "DOWNLOAD_LOGS_MESSAGE": "

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

Пожалуйста, обратите внимание, что будут указаны имена файлов, которые помогут отслеживать проблемы с конкретными файлами.

", + "download_logs": "Загрузка журналов", + "download_logs_message": "

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

Пожалуйста, обратите внимание, что будут указаны имена файлов, которые помогут отслеживать проблемы с конкретными файлами.

", "WEAK_DEVICE": "Используемый вами веб-браузер недостаточно мощный, чтобы зашифровать ваши фотографии. Пожалуйста, попробуйте войти в Ente на своем компьютере или загрузить мобильное/настольное приложение Ente.", "drag_and_drop_hint": "Или перетащите в основное окно", "AUTHENTICATE": "Проверка подлинности", diff --git a/web/packages/base/locales/sl-SI/translation.json b/web/packages/base/locales/sl-SI/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/sl-SI/translation.json +++ b/web/packages/base/locales/sl-SI/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index 4e03994ceb..83010703d7 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "Ändra mapp", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "Ladda ner loggar", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "Ladda ner loggar", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index 80a2f93dc9..05f822e944 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/uk-UA/translation.json b/web/packages/base/locales/uk-UA/translation.json index 2826dd17b0..0f59a194f4 100644 --- a/web/packages/base/locales/uk-UA/translation.json +++ b/web/packages/base/locales/uk-UA/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "", "FAMILY_PLAN": "", "debug_logs": "", - "DOWNLOAD_LOGS": "", - "DOWNLOAD_LOGS_MESSAGE": "", + "download_logs": "", + "download_logs_message": "", "WEAK_DEVICE": "", "drag_and_drop_hint": "", "AUTHENTICATE": "", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index 48cb2f5ad2..cd2638dbae 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -452,8 +452,8 @@ "CHANGE_FOLDER": "更改文件夹", "FAMILY_PLAN": "家庭计划", "debug_logs": "调试日志", - "DOWNLOAD_LOGS": "下载日志", - "DOWNLOAD_LOGS_MESSAGE": "

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

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

", + "download_logs": "下载日志", + "download_logs_message": "

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

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

", "WEAK_DEVICE": "您使用的网络浏览器功能不够强大,无法加密您的照片。 请尝试在电脑上登录Ente,或下载Ente移动/桌面应用程序。", "drag_and_drop_hint": "或者拖动并拖动到 Ente 窗口", "AUTHENTICATE": "身份认证", From c23fc791347ca6629bc6f74d9efd137d4072a746 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:53:03 +0530 Subject: [PATCH 188/438] Trim --- .../base/locales/de-DE/translation.json | 12 ++++++------ .../base/locales/en-US/translation.json | 12 ++++++------ .../base/locales/es-ES/translation.json | 4 ++-- .../base/locales/fr-FR/translation.json | 14 +++++++------- .../base/locales/id-ID/translation.json | 2 +- .../base/locales/it-IT/translation.json | 12 ++++++------ .../base/locales/lt-LT/translation.json | 4 ++-- .../base/locales/nl-NL/translation.json | 14 +++++++------- .../base/locales/pl-PL/translation.json | 14 +++++++------- .../base/locales/pt-BR/translation.json | 12 ++++++------ .../base/locales/ru-RU/translation.json | 18 +++++++++--------- .../base/locales/zh-CN/translation.json | 12 ++++++------ 12 files changed, 65 insertions(+), 65 deletions(-) diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index dbbf2cc584..d2b07ce5aa 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -241,10 +241,10 @@ "map_settings": "Karten Einstellungen", "enable_map": "Karte aktivieren", "enable_maps_confirm": "Karten aktivieren?", - "enable_maps_confirm_message": "

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.

", + "enable_maps_confirm_message": "

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": "Karte deaktivieren", "disable_maps_confirm": "Karten deaktivieren?", - "disable_maps_confirm_message": "

Dies wird die Anzeige deiner Fotos auf einer Weltkarte deaktivieren.

Du kannst diese Funktion jederzeit in den Einstellungen aktivieren.

", + "disable_maps_confirm_message": "

Dies wird die Anzeige deiner Fotos auf einer Weltkarte deaktivieren.

Du kannst diese Funktion jederzeit in den Einstellungen aktivieren.

", "DETAILS": "Details", "view_exif": "Alle Exif-Daten anzeigen", "no_exif": "Keine Exif-Daten", @@ -368,7 +368,7 @@ "participants_count_one": "1 Teilnehmer", "participants_count": "{{count, number}} Teilnehmer", "ADD_VIEWERS": "Betrachter hinzufügen", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} wird nicht in der Lage sein, weitere Fotos zum Album

hinzuzufügen. {{selectedEmail}} wird weiterhin die eigenen Fotos aus dem Album entfernen können

", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} wird nicht in der Lage sein, weitere Fotos zum Album

hinzuzufügen. {{selectedEmail}} wird weiterhin die eigenen Fotos aus dem Album entfernen können

", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} wird Fotos zum Album hinzufügen können", "CONVERT_TO_VIEWER": "Ja, zu \"Beobachter\" ändern", "CONVERT_TO_COLLABORATOR": "Ja, in Kollaborateur umwandeln", @@ -384,7 +384,7 @@ "ADD_MORE": "Mehr hinzufügen", "VIEWERS": "Zuschauer", "OR_ADD_EXISTING": "Oder eine Vorherige auswählen", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} wird vom Album entfernt

Alle Bilder von {{selectedEmail}} werden ebenfalls aus dem Album entfernt

", + "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} wird vom Album entfernt

Alle Bilder von {{selectedEmail}} werden ebenfalls aus dem Album entfernt

", "NOT_FOUND": "404 - Nicht gefunden", "LINK_EXPIRED": "Link ist abgelaufen", "LINK_EXPIRED_MESSAGE": "Dieser Link ist abgelaufen oder wurde deaktiviert!", @@ -453,7 +453,7 @@ "FAMILY_PLAN": "Familientarif", "debug_logs": "Debug-Logs", "download_logs": "Logs herunterladen", - "download_logs_message": "

Hier kannst du Debug-Logs herunterladen, die du uns zur Fehleranalyse zusenden kannst.

Beachte bitte, dass die Logs Dateinamen enthalten, um Probleme mit bestimmten Dateien nachvollziehen zu können.

", + "download_logs_message": "

Hier kannst du Debug-Logs herunterladen, die du uns zur Fehleranalyse zusenden kannst.

Beachte bitte, dass die Logs Dateinamen enthalten, um Probleme mit bestimmten Dateien nachvollziehen zu können.

", "WEAK_DEVICE": "Dein Browser ist nicht leistungsstark genug, um deine Bilder zu verschlüsseln. Versuche, dich an einem Computer bei Ente anzumelden, oder lade dir die Ente-App für dein Gerät (Handy oder Desktop) herunter.", "drag_and_drop_hint": "Oder ziehe Dateien per Drag-and-Drop in das Ente-Fenster", "AUTHENTICATE": "Authentifizieren", @@ -498,7 +498,7 @@ "language": "Sprache", "advanced": "Erweitert", "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Ungültiges Exportverzeichnis", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

Das von dir gewählte Exportverzeichnis existiert nicht.

Bitte wähle einen gültigen Ordner.

", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

Das von dir gewählte Exportverzeichnis existiert nicht.

Bitte wähle einen gültigen Ordner.

", "SUBSCRIPTION_VERIFICATION_ERROR": "Verifizierung des Abonnements fehlgeschlagen", "storage_unit": { "b": "B", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index 6bff64df75..e8ecba5436 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -241,10 +241,10 @@ "map_settings": "Map settings", "enable_map": "Enable map", "enable_maps_confirm": "Enable Maps?", - "enable_maps_confirm_message": "

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.

", + "enable_maps_confirm_message": "

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": "Disable map", "disable_maps_confirm": "Disable Maps?", - "disable_maps_confirm_message": "

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

You can enable this feature anytime from Settings.

", + "disable_maps_confirm_message": "

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

You can enable this feature anytime from Settings.

", "DETAILS": "Details", "view_exif": "View all Exif data", "no_exif": "No Exif data", @@ -368,7 +368,7 @@ "participants_count_one": "1 participant", "participants_count": "{{count, number}} participants", "ADD_VIEWERS": "Add viewers", - "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_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", @@ -384,7 +384,7 @@ "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

", + "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!", @@ -453,7 +453,7 @@ "FAMILY_PLAN": "Family plan", "debug_logs": "Debug logs", "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.

", + "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.

", "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", "AUTHENTICATE": "Authenticate", @@ -498,7 +498,7 @@ "language": "Language", "advanced": "Advanced", "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.

", + "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", "storage_unit": { "b": "B", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index 5c4e5de667..a7e99e2912 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -453,7 +453,7 @@ "FAMILY_PLAN": "Plan familiar", "debug_logs": "Logs de depuración", "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.

", + "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.

", "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", "AUTHENTICATE": "Autenticado", @@ -498,7 +498,7 @@ "language": "Idioma", "advanced": "Avanzado", "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.

", + "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_unit": { "b": "B", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index f4be638fb9..2f1237a547 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -131,7 +131,7 @@ "logout": "Déconnexion", "logout_message": "Voulez-vous vraiment vous déconnecter?", "delete_account": "Supprimer le compte", - "delete_account_manually_message": "

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

Votre demande sera traitée dans les 72 heures.

", + "delete_account_manually_message": "

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

Votre demande sera traitée dans les 72 heures.

", "CHANGE_EMAIL": "Modifier l'e-mail", "ok": "Ok", "success": "Parfait", @@ -241,10 +241,10 @@ "map_settings": "Paramètres de la carte", "enable_map": "Activer la carte", "enable_maps_confirm": "Activer la carte?", - "enable_maps_confirm_message": "

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.

", + "enable_maps_confirm_message": "

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": "Désactiver la carte", "disable_maps_confirm": "Désactiver la carte?", - "disable_maps_confirm_message": "

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

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.

", "DETAILS": "Détails", "view_exif": "Visualiser toutes les données Exif", "no_exif": "Aucune donnée Exif", @@ -368,7 +368,7 @@ "participants_count_one": "1 participant", "participants_count": "{{count, number}} participants", "ADD_VIEWERS": "Ajouter un observateur", - "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_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", @@ -384,7 +384,7 @@ "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

", + "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é!", @@ -487,7 +487,7 @@ "ml_search_disable_confirm": "Voulez-vous désactiver l'apprentissage automatique sur tous vos appareils ?", "ml_consent": "Activer l'apprentissage automatique", "ml_consent_title": "Activer l'apprentissage automatique ?", - "ml_consent_description": "

Si vous activez l'apprentissage automatique, Ente extraira de vos photos et de celles partagées avec vous des informations comme la géométrie des visages.

Cela se fera sur votre appareil, et toutes les données biométriques générées seront chiffrées de bout-en-bout.

Veuillez cliquer ici pour accéder à notre politique de confidentialité, vous y trouverez plus de détails concernant cette fonction

", + "ml_consent_description": "

Si vous activez l'apprentissage automatique, Ente extraira de vos photos et de celles partagées avec vous des informations comme la géométrie des visages.

Cela se fera sur votre appareil, et toutes les données biométriques générées seront chiffrées de bout-en-bout.

Veuillez cliquer ici pour accéder à notre politique de confidentialité, vous y trouverez plus de détails concernant cette fonction

", "ml_consent_confirmation": "Je comprends, et souhaite activer l'apprentissage automatique", "labs": "Labo", "YOURS": "Le vôtre", @@ -498,7 +498,7 @@ "language": "Langue", "advanced": "Avancé", "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

", + "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_unit": { "b": "o", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index 7b7e9dc530..d498696426 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -384,7 +384,7 @@ "ADD_MORE": "", "VIEWERS": "", "OR_ADD_EXISTING": "", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} akan dikeluarkan dari album ini

Semua foto yang ia tambahkan juga akan dihapus dari album ini

", + "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} akan dikeluarkan dari album ini

Semua foto yang ia tambahkan juga akan dihapus dari album ini

", "NOT_FOUND": "404 - tidak ditemukan", "LINK_EXPIRED": "Link telah kedaluwarsa", "LINK_EXPIRED_MESSAGE": "Link ini telah kedaluwarsa atau sudah dinonaktifkan!", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index f6c6526ef4..0446e31269 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -241,10 +241,10 @@ "map_settings": "Impostazioni Mappa", "enable_map": "Attivare mappa", "enable_maps_confirm": "Attivare Mappa?", - "enable_maps_confirm_message": "

Questa opzione mostrerà le tue foto sulla mappa del mondo.

La mappa è ospitata da OpenStreetMap, la posizione esatta delle tue foto non saranno mai condivise.

Puoi disabilitare questa funzione in qualsiasi momento dalle Impostazioni.

", + "enable_maps_confirm_message": "

Questa opzione mostrerà le tue foto sulla mappa del mondo.

La mappa è ospitata da OpenStreetMap, la posizione esatta delle tue foto non saranno mai condivise.

Puoi disabilitare questa funzione in qualsiasi momento dalle Impostazioni.

", "disable_map": "Disattivare Mappa", "disable_maps_confirm": "Disattivare Mappa?", - "disable_maps_confirm_message": "

Questo opzione disabiliterà la visualizzazione delle tue foto sulla mappa del mondo.

Puoi abilitare questa funzione in qualsiasi momento dalle impostazioni.

", + "disable_maps_confirm_message": "

Questo opzione disabiliterà la visualizzazione delle tue foto sulla mappa del mondo.

Puoi abilitare questa funzione in qualsiasi momento dalle impostazioni.

", "DETAILS": "Dettagli", "view_exif": "Mostra tutti i dati EXIF", "no_exif": "Nessun dato EXIF", @@ -368,7 +368,7 @@ "participants_count_one": "1 partecipante", "participants_count": "{{count, number}} partecipanti", "ADD_VIEWERS": "Aggiungi visualizzatori", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} non sarà in grado di aggiungere altre foto all'album

Essi saranno comunque in grado di rimuovere le foto aggiunte da loro

", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} non sarà in grado di aggiungere altre foto all'album

Essi saranno comunque in grado di rimuovere le foto aggiunte da loro

", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} potrà aggiungere foto all'album", "CONVERT_TO_VIEWER": "Sì, converti in visualizzatore", "CONVERT_TO_COLLABORATOR": "Sì, converti in collaboratore", @@ -384,7 +384,7 @@ "ADD_MORE": "Aggiungi altri", "VIEWERS": "Visualizzatori", "OR_ADD_EXISTING": "Oppure scegline uno esistente", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} sarà rimosso dall'album

Tutte le foto da essi aggiunte verranno rimosse dall'album

", + "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} sarà rimosso dall'album

Tutte le foto da essi aggiunte verranno rimosse dall'album

", "NOT_FOUND": "404 - non trovato", "LINK_EXPIRED": "Link scaduto", "LINK_EXPIRED_MESSAGE": "Questo link è scaduto o è stato disabilitato!", @@ -453,7 +453,7 @@ "FAMILY_PLAN": "Piano famiglia", "debug_logs": "Log di debug", "download_logs": "Scarica i log", - "download_logs_message": "

Questo scaricherà il log di debug che puoi inviare via email a noi per aiutare a capire il tuo problema.

Nota che i nomi dei file saranno inclusi per aiutare a tenere traccia dei problemi con i file specifici.

", + "download_logs_message": "

Questo scaricherà il log di debug che puoi inviare via email a noi per aiutare a capire il tuo problema.

Nota che i nomi dei file saranno inclusi per aiutare a tenere traccia dei problemi con i file specifici.

", "WEAK_DEVICE": "Il browser web che stai usando non è abbastanza potente per crittografare le foto. Prova ad accedere a Ente sul tuo computer o scarica l'app mobile/desktop Ente.", "drag_and_drop_hint": "Oppure trascina nella finestra di Ente", "AUTHENTICATE": "Autenticati", @@ -498,7 +498,7 @@ "language": "Lingua", "advanced": "Avanzate", "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Directory di esportazione non valida", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

La directory di esportazione selezionata non esiste.

Si prega di selezionare una directory valida.

", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

La directory di esportazione selezionata non esiste.

Si prega di selezionare una directory valida.

", "SUBSCRIPTION_VERIFICATION_ERROR": "Verifica dell'abbonamento non riuscita", "storage_unit": { "b": "B", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index f1f9d2e4a3..761e490423 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -241,10 +241,10 @@ "map_settings": "Žemėlapio nustatymai", "enable_map": "Įjungti žemėlapį", "enable_maps_confirm": "Įjungti žemėlapius?", - "enable_maps_confirm_message": "

Tai parodys jūsų nuotraukas pasaulio žemėlapyje.

Žemėlapį talpina „OpenStreetMap“, o tiksliomis nuotraukų vietomis niekada nebendrinama.

Šią funkciją bet kada galite išjungti iš nustatymų.

", + "enable_maps_confirm_message": "

Tai parodys jūsų nuotraukas pasaulio žemėlapyje.

Žemėlapį talpina „OpenStreetMap“, o tiksliomis nuotraukų vietomis niekada nebendrinama.

Šią funkciją bet kada galite išjungti iš nustatymų.

", "disable_map": "Išjungti žemėlapį", "disable_maps_confirm": "Išjungti žemėlapius?", - "disable_maps_confirm_message": "

Tai išjungs jūsų nuotraukų rodymą pasaulio žemėlapyje.

Šią funkciją bet kada galite įjungti iš nustatymų.

", + "disable_maps_confirm_message": "

Tai išjungs jūsų nuotraukų rodymą pasaulio žemėlapyje.

Šią funkciją bet kada galite įjungti iš nustatymų.

", "DETAILS": "Išsami informacija", "view_exif": "Peržiūrėti visus Exif duomenis", "no_exif": "Nėra Exif duomenų", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 23df18005b..3d430b7740 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -241,10 +241,10 @@ "map_settings": "Kaart instellingen", "enable_map": "Kaarten inschakelen", "enable_maps_confirm": "Kaarten inschakelen?", - "enable_maps_confirm_message": "

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.

", + "enable_maps_confirm_message": "

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": "Kaarten uitzetten", "disable_maps_confirm": "Kaarten uitzetten?", - "disable_maps_confirm_message": "

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

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

", + "disable_maps_confirm_message": "

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

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

", "DETAILS": "Details", "view_exif": "Bekijk alle Exif gegevens", "no_exif": "Geen Exif gegevens", @@ -368,7 +368,7 @@ "participants_count_one": "1 deelnemer", "participants_count": "{{count, number}} deelnemers", "ADD_VIEWERS": "Voeg kijkers toe", - "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_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", @@ -384,7 +384,7 @@ "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

", + "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!", @@ -453,7 +453,7 @@ "FAMILY_PLAN": "Familie abonnement", "debug_logs": "Logboeken voor foutmeldingen", "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.

", + "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.

", "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", "AUTHENTICATE": "Verifiëren", @@ -498,7 +498,7 @@ "language": "Taal", "advanced": "Geavanceerd", "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.

", + "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_unit": { "b": "B", @@ -544,7 +544,7 @@ "delete_account_feedback_placeholder": "Feedback", "delete_account_confirm_checkbox_label": "Ja, ik wil permanent mijn account inclusief alle gegevens verwijderen", "delete_account_confirm": "Account verwijderen bevestigen", - "delete_account_confirm_message": "

Dit account is gekoppeld aan andere Ente apps, als je die gebruikt.

Je geüploade gegevens worden in alle Ente apps gepland voor verwijdering, en je account wordt permanent verwijderd voor alle Ente diensten.

", + "delete_account_confirm_message": "

Dit account is gekoppeld aan andere Ente apps, als je die gebruikt.

Je geüploade gegevens worden in alle Ente apps gepland voor verwijdering, en je account wordt permanent verwijderd voor alle Ente diensten.

", "feedback_required": "Help ons alsjeblieft met deze informatie", "feedback_required_found_another_service": "Wat doet de andere dienst beter?", "RECOVER_TWO_FACTOR": "Herstel tweestaps", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index b1194ee975..c275fa56f1 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -241,10 +241,10 @@ "map_settings": "Ustawienia Mapy", "enable_map": "Włącz mapę", "enable_maps_confirm": "Włączyć Mapy?", - "enable_maps_confirm_message": "

To pokaże Twoje zdjęcia na mapie świata.

Mapa jest hostowana przez OpenStreetMap, a dokładne lokalizacje Twoich zdjęć nigdy nie są udostępniane.

Możesz wyłączyć tę funkcję w dowolnym momencie w Ustawieniach.

", + "enable_maps_confirm_message": "

To pokaże Twoje zdjęcia na mapie świata.

Mapa jest hostowana przez OpenStreetMap, a dokładne lokalizacje Twoich zdjęć nigdy nie są udostępniane.

Możesz wyłączyć tę funkcję w dowolnym momencie w Ustawieniach.

", "disable_map": "Wyłącz mapę", "disable_maps_confirm": "Wyłączyć Mapy?", - "disable_maps_confirm_message": "

To wyłączy wyświetlanie zdjęć na mapie świata.

Możesz włączyć tę funkcję w dowolnym momencie w Ustawieniach.

", + "disable_maps_confirm_message": "

To wyłączy wyświetlanie zdjęć na mapie świata.

Możesz włączyć tę funkcję w dowolnym momencie w Ustawieniach.

", "DETAILS": "Szczegóły", "view_exif": "Wyświetl wszystkie dane Exif", "no_exif": "Brak danych Exif", @@ -368,7 +368,7 @@ "participants_count_one": "1 uczestnik", "participants_count": "{{count, number}} uczestników", "ADD_VIEWERS": "Dodaj widzów", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} nie będzie mógł dodać więcej zdjęć do tego albumu.

Nadal będą mogli usuwać istniejące zdjęcia, które dodali

", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} nie będzie mógł dodać więcej zdjęć do tego albumu.

Nadal będą mogli usuwać istniejące zdjęcia, które dodali

", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} będzie mógł dodawać zdjęcia do albumu", "CONVERT_TO_VIEWER": "Tak, konwertuj na widza", "CONVERT_TO_COLLABORATOR": "Tak, konwertuj na współuczestnika", @@ -384,7 +384,7 @@ "ADD_MORE": "Dodaj więcej", "VIEWERS": "Widzowie", "OR_ADD_EXISTING": "Lub wybierz istniejący", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} zostanie usunięty z albumu

Wszelkie dodane przez nich zdjęcia zostaną usunięte z albumu

", + "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} zostanie usunięty z albumu

Wszelkie dodane przez nich zdjęcia zostaną usunięte z albumu

", "NOT_FOUND": "404 - nie znaleziono", "LINK_EXPIRED": "Link wygasł", "LINK_EXPIRED_MESSAGE": "Ten link wygasł lub został wyłączony!", @@ -453,7 +453,7 @@ "FAMILY_PLAN": "Plan rodzinny", "debug_logs": "Logi debugowania", "download_logs": "Pobierz logi", - "download_logs_message": "

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

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

", + "download_logs_message": "

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

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

", "WEAK_DEVICE": "Przeglądarka, której używasz nie jest wystarczająco silna, aby zaszyfrować Twoje zdjęcia. Prosimy zalogować się do Ente na Twoim komputerze lub pobierz aplikacje mobilną/komputerową Ente.", "drag_and_drop_hint": "Lub przeciągnij i upuść do okna Ente", "AUTHENTICATE": "Uwierzytelnij się", @@ -498,7 +498,7 @@ "language": "Język", "advanced": "Zaawansowane", "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Nieprawidłowy katalog eksportu", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

Wybrany katalog eksportu nie istnieje.

Proszę wybrać prawidłowy katalog.

", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

Wybrany katalog eksportu nie istnieje.

Proszę wybrać prawidłowy katalog.

", "SUBSCRIPTION_VERIFICATION_ERROR": "Weryfikacja subskrypcji nie powiodła się", "storage_unit": { "b": "B", @@ -544,7 +544,7 @@ "delete_account_feedback_placeholder": "Opinia", "delete_account_confirm_checkbox_label": "Tak, chcę trwale usunąć konto i wszystkie dane z nim powiązane", "delete_account_confirm": "Potwierdź Usunięcie Konta", - "delete_account_confirm_message": "

To konto jest połączone z innymi aplikacjami Ente, jeśli ich używasz.

Twoje przesłane dane, we wszystkich aplikacjach Ente, zostaną zaplanowane do usunięcia, a Twoje konto zostanie usunięte na zawsze.

", + "delete_account_confirm_message": "

To konto jest połączone z innymi aplikacjami Ente, jeśli ich używasz.

Twoje przesłane dane, we wszystkich aplikacjach Ente, zostaną zaplanowane do usunięcia, a Twoje konto zostanie usunięte na zawsze.

", "feedback_required": "Pomóż nam z tą informacją", "feedback_required_found_another_service": "Co lepiej robi ta inna usługa?", "RECOVER_TWO_FACTOR": "Odzyskaj uwierzytelnianie dwustopniowe", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index fce890ce8f..8ec40e94d9 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -241,10 +241,10 @@ "map_settings": "Configurações do Mapa", "enable_map": "Habilitar mapa", "enable_maps_confirm": "Habilitar mapa?", - "enable_maps_confirm_message": "

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.

", + "enable_maps_confirm_message": "

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": "Desabilitar mapa", "disable_maps_confirm": "Desativar Mapas?", - "disable_maps_confirm_message": "

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

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

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

", "DETAILS": "Detalhes", "view_exif": "Ver todos os dados Exif", "no_exif": "Sem dados Exif", @@ -384,7 +384,7 @@ "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

", + "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!", @@ -453,7 +453,7 @@ "FAMILY_PLAN": "Plano familiar", "debug_logs": "Logs de depuração", "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.

", + "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.

", "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", "AUTHENTICATE": "Autenticar", @@ -487,7 +487,7 @@ "ml_search_disable_confirm": "Você deseja desativar o aprendizado de máquina em todos os seus dispositivos?", "ml_consent": "Habilitar aprendizado de máquina", "ml_consent_title": "Habilitar aprendizado de máquina?", - "ml_consent_description": "

Se você habilitar o reconhecimento facial, o aplicativo extrairá a geometria do rosto de suas fotos, inclusive aquelas compartilhadas com você.

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

", + "ml_consent_description": "

Se você habilitar o reconhecimento facial, o aplicativo extrairá a geometria do rosto de suas fotos, inclusive aquelas compartilhadas com você.

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

", "ml_consent_confirmation": "Eu entendo, e desejo habilitar o aprendizado de máquina", "labs": "Laboratórios", "YOURS": "seu", @@ -498,7 +498,7 @@ "language": "Idioma", "advanced": "Avançado", "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.

", + "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_unit": { "b": "B", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 6dacea58b6..32cf888022 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -131,7 +131,7 @@ "logout": "Выйти", "logout_message": "Вы уверены, что хотите выйти?", "delete_account": "Удалить аккаунт", - "delete_account_manually_message": "

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

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

", + "delete_account_manually_message": "

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

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

", "CHANGE_EMAIL": "Изменить адрес электронной почты", "ok": "ОК", "success": "Успешно", @@ -182,7 +182,7 @@ "UPDATE_SUBSCRIPTION_MESSAGE": "Хотите сменить текущий план?", "UPDATE_SUBSCRIPTION": "Изменить план", "CANCEL_SUBSCRIPTION": "Отменить подписку", - "CANCEL_SUBSCRIPTION_MESSAGE": "

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

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

", + "CANCEL_SUBSCRIPTION_MESSAGE": "

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

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

", "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

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

", "SUBSCRIPTION_CANCEL_FAILED": "Не удалось отменить подписку", "SUBSCRIPTION_CANCEL_SUCCESS": "Подписка успешно отменена", @@ -241,10 +241,10 @@ "map_settings": "Настройки карты", "enable_map": "Включить отображение", "enable_maps_confirm": "Включить карты?", - "enable_maps_confirm_message": "

Это отобразит ваши фотографии на карте мира.

Карта размещена на OpenStreetMap, и точные местоположения ваших фотографий никогда не публикуются.

Вы можете отключить эту функцию в любое время в настройках.

", + "enable_maps_confirm_message": "

Это отобразит ваши фотографии на карте мира.

Карта размещена на OpenStreetMap, и точные местоположения ваших фотографий никогда не публикуются.

Вы можете отключить эту функцию в любое время в настройках.

", "disable_map": "Отключить карту", "disable_maps_confirm": "Отключить карты?", - "disable_maps_confirm_message": "

Это приведет к отключению отображения ваших фотографий на карте мира.

Вы можете включить эту функцию в любое время в настройках.

", + "disable_maps_confirm_message": "

Это приведет к отключению отображения ваших фотографий на карте мира.

Вы можете включить эту функцию в любое время в настройках.

", "DETAILS": "Подробности", "view_exif": "Просмотр всех данных Exif", "no_exif": "Нет данных Exif", @@ -368,7 +368,7 @@ "participants_count_one": "1 участник", "participants_count": "{{count, number}} участники", "ADD_VIEWERS": "Добавить зрителей", - "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} они не смогут добавить больше фотографий в альбом

Они по-прежнему смогут удалять добавленные ими фотографии

", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} они не смогут добавить больше фотографий в альбом

Они по-прежнему смогут удалять добавленные ими фотографии

", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} сможете добавлять фотографии в альбом", "CONVERT_TO_VIEWER": "Да, преобразовать в программу просмотра", "CONVERT_TO_COLLABORATOR": "Да, преобразовать в соавтора", @@ -384,7 +384,7 @@ "ADD_MORE": "Добавить еще", "VIEWERS": "Зрителей", "OR_ADD_EXISTING": "Или выберите уже существующий вариант", - "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} будут удалены из альбома

Все добавленные ими фотографии также будут удалены из альбома

", + "REMOVE_PARTICIPANT_MESSAGE": "

{{selectedEmail}} будут удалены из альбома

Все добавленные ими фотографии также будут удалены из альбома

", "NOT_FOUND": "404 - не найден", "LINK_EXPIRED": "Срок действия ссылки истек", "LINK_EXPIRED_MESSAGE": "Срок действия этой ссылки либо истек, либо она была отключена!", @@ -398,7 +398,7 @@ "LINK_EXPIRY": "Истечение срока действия ссылки", "NEVER": "Никогда", "DISABLE_FILE_DOWNLOAD": "Отключить загрузку", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Вы уверены, что хотите отключить кнопку загрузки файлов?

Зрители по-прежнему могут делать скриншоты или сохранять копии ваших фотографий с помощью внешних инструментов.

", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Вы уверены, что хотите отключить кнопку загрузки файлов?

Зрители по-прежнему могут делать скриншоты или сохранять копии ваших фотографий с помощью внешних инструментов.

", "SHARED_USING": "Совместное использование ", "SHARING_REFERRAL_CODE": "Используйте код {{referralCode}} чтобы получить 10 ГБ бесплатно", "LIVE": "Жить", @@ -453,7 +453,7 @@ "FAMILY_PLAN": "Семейный план", "debug_logs": "Журналы отладки", "download_logs": "Загрузка журналов", - "download_logs_message": "

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

Пожалуйста, обратите внимание, что будут указаны имена файлов, которые помогут отслеживать проблемы с конкретными файлами.

", + "download_logs_message": "

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

Пожалуйста, обратите внимание, что будут указаны имена файлов, которые помогут отслеживать проблемы с конкретными файлами.

", "WEAK_DEVICE": "Используемый вами веб-браузер недостаточно мощный, чтобы зашифровать ваши фотографии. Пожалуйста, попробуйте войти в Ente на своем компьютере или загрузить мобильное/настольное приложение Ente.", "drag_and_drop_hint": "Или перетащите в основное окно", "AUTHENTICATE": "Проверка подлинности", @@ -498,7 +498,7 @@ "language": "Язык", "advanced": "Передовой", "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Недопустимый каталог экспорта", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

Выбранный вами каталог экспорта не существует.

Пожалуйста, выберите правильный каталог.

", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

Выбранный вами каталог экспорта не существует.

Пожалуйста, выберите правильный каталог.

", "SUBSCRIPTION_VERIFICATION_ERROR": "Не удалось подтвердить подписку", "storage_unit": { "b": "B", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index cd2638dbae..ce0da29c47 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -241,10 +241,10 @@ "map_settings": "地图设置", "enable_map": "启用地图", "enable_maps_confirm": "要启用地图吗?", - "enable_maps_confirm_message": "

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

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

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

", + "enable_maps_confirm_message": "

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

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

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

", "disable_map": "禁用地图", "disable_maps_confirm": "要禁用地图吗?", - "disable_maps_confirm_message": "

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

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

", + "disable_maps_confirm_message": "

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

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

", "DETAILS": "详情", "view_exif": "查看所有 Exif 数据", "no_exif": "无 Exif 数据", @@ -368,7 +368,7 @@ "participants_count_one": "1 名参与者", "participants_count": "{{count, number}} 名参与者", "ADD_VIEWERS": "添加查看者", - "CHANGE_PERMISSIONS_TO_VIEWER": "

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

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

", + "CHANGE_PERMISSIONS_TO_VIEWER": "

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

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

", "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} 将能够将照片添加到相册", "CONVERT_TO_VIEWER": "是的,转换为查看者", "CONVERT_TO_COLLABORATOR": "是,转换为协作者", @@ -384,7 +384,7 @@ "ADD_MORE": "添加更多", "VIEWERS": "查看者", "OR_ADD_EXISTING": "或选择一个现有的", - "REMOVE_PARTICIPANT_MESSAGE": "

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

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

", + "REMOVE_PARTICIPANT_MESSAGE": "

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

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

", "NOT_FOUND": "404 - 未找到", "LINK_EXPIRED": "链接已过期", "LINK_EXPIRED_MESSAGE": "此链接已过期或已被禁用!", @@ -453,7 +453,7 @@ "FAMILY_PLAN": "家庭计划", "debug_logs": "调试日志", "download_logs": "下载日志", - "download_logs_message": "

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

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

", + "download_logs_message": "

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

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

", "WEAK_DEVICE": "您使用的网络浏览器功能不够强大,无法加密您的照片。 请尝试在电脑上登录Ente,或下载Ente移动/桌面应用程序。", "drag_and_drop_hint": "或者拖动并拖动到 Ente 窗口", "AUTHENTICATE": "身份认证", @@ -498,7 +498,7 @@ "language": "语言", "advanced": "高级设置", "EXPORT_DIRECTORY_DOES_NOT_EXIST": "无效的导出目录", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

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

请选择一个有效的目录。

", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

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

请选择一个有效的目录。

", "SUBSCRIPTION_VERIFICATION_ERROR": "订阅验证失败", "storage_unit": { "b": "B", From 1c1ad93875bf14a172ca769a7b84bc787d3f424e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:54:41 +0530 Subject: [PATCH 189/438] Rename --- .../src/components/PhotoViewer/ImageEditorOverlay/index.tsx | 4 ++-- web/packages/base/locales/ar-SA/translation.json | 4 ++-- web/packages/base/locales/bg-BG/translation.json | 4 ++-- web/packages/base/locales/ca-ES/translation.json | 4 ++-- web/packages/base/locales/da-DK/translation.json | 4 ++-- web/packages/base/locales/de-DE/translation.json | 4 ++-- web/packages/base/locales/el-GR/translation.json | 4 ++-- web/packages/base/locales/en-US/translation.json | 4 ++-- web/packages/base/locales/es-ES/translation.json | 4 ++-- web/packages/base/locales/et-EE/translation.json | 4 ++-- web/packages/base/locales/fa-IR/translation.json | 4 ++-- web/packages/base/locales/fi-FI/translation.json | 4 ++-- web/packages/base/locales/fr-FR/translation.json | 4 ++-- web/packages/base/locales/gu-IN/translation.json | 4 ++-- web/packages/base/locales/hi-IN/translation.json | 4 ++-- web/packages/base/locales/id-ID/translation.json | 4 ++-- web/packages/base/locales/is-IS/translation.json | 4 ++-- web/packages/base/locales/it-IT/translation.json | 4 ++-- web/packages/base/locales/ja-JP/translation.json | 4 ++-- web/packages/base/locales/km-KH/translation.json | 4 ++-- web/packages/base/locales/ko-KR/translation.json | 4 ++-- web/packages/base/locales/lt-LT/translation.json | 4 ++-- web/packages/base/locales/nl-NL/translation.json | 4 ++-- web/packages/base/locales/pl-PL/translation.json | 4 ++-- web/packages/base/locales/pt-BR/translation.json | 4 ++-- web/packages/base/locales/pt-PT/translation.json | 4 ++-- web/packages/base/locales/ru-RU/translation.json | 4 ++-- web/packages/base/locales/sl-SI/translation.json | 4 ++-- web/packages/base/locales/sv-SE/translation.json | 4 ++-- web/packages/base/locales/ta-IN/translation.json | 4 ++-- web/packages/base/locales/te-IN/translation.json | 4 ++-- web/packages/base/locales/th-TH/translation.json | 4 ++-- web/packages/base/locales/ti-ER/translation.json | 4 ++-- web/packages/base/locales/tr-TR/translation.json | 4 ++-- web/packages/base/locales/uk-UA/translation.json | 4 ++-- web/packages/base/locales/zh-CN/translation.json | 4 ++-- 36 files changed, 72 insertions(+), 72 deletions(-) diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx index 5cdfe0b8a7..e3e3c41d7c 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx @@ -734,8 +734,8 @@ export default ImageEditorOverlay; const confirmEditorCloseDialogAttributes = ( onConfirm: () => void, ): MiniDialogAttributes => ({ - title: t("CONFIRM_EDITOR_CLOSE_MESSAGE"), - message: t("CONFIRM_EDITOR_CLOSE_DESCRIPTION"), + title: t("confirm_editor_close"), + message: t("confirm_editor_close_message"), continue: { text: t("close"), color: "critical", diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index 21ee2f2e45..59fa13c900 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index 926a030303..17d3545591 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index 2393d30916..5956cbe172 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index d2b07ce5aa..9101e1054d 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -574,8 +574,8 @@ "crop": "Zuschneiden" }, "CONVERT": "Konvertieren", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Editor wirklich schließen?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Lade dein bearbeitetes Bild herunter oder speichere es in Ente, um die Änderungen nicht zu verlieren.", + "confirm_editor_close": "Editor wirklich schließen?", + "confirm_editor_close_message": "Lade dein bearbeitetes Bild herunter oder speichere es in Ente, um die Änderungen nicht zu verlieren.", "BRIGHTNESS": "Helligkeit", "CONTRAST": "Kontrast", "SATURATION": "Sättigung", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index 4ebc3670b2..a1f95be25a 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -574,8 +574,8 @@ "crop": "Περικοπή" }, "CONVERT": "Μετατροπή", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "Φωτεινότητα", "CONTRAST": "Αντίθεση", "SATURATION": "Κορεσμός", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index e8ecba5436..fe07dec252 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -574,8 +574,8 @@ "crop": "Crop" }, "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.", + "confirm_editor_close": "Are you sure you want to close the editor?", + "confirm_editor_close_message": "Download your edited image or save a copy to Ente to persist your changes.", "BRIGHTNESS": "Brightness", "CONTRAST": "Contrast", "SATURATION": "Saturation", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index a7e99e2912..549058da5f 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "Brillo", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index 689f162b3d..feaa13e8a8 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index 7a99182d79..e85a223bee 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 2f1237a547..3b08b0b5f4 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -574,8 +574,8 @@ "crop": "Rogner" }, "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.", + "confirm_editor_close": "Êtes-vous sûr de vouloir fermer l'éditeur ?", + "confirm_editor_close_message": "Téléchargez votre image modifiée ou enregistrez une copie sur Ente pour maintenir vos modifications.", "BRIGHTNESS": "Luminosité", "CONTRAST": "Contraste", "SATURATION": "Saturation", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index d498696426..72cfb37f71 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -574,8 +574,8 @@ "crop": "Potong" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Apakah kamu yakin ingin menutup editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "Apakah kamu yakin ingin menutup editor?", + "confirm_editor_close_message": "", "BRIGHTNESS": "Kecerahan", "CONTRAST": "Kontras", "SATURATION": "", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index d3c25e9f1e..996e87fd21 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index 0446e31269..c6b0d31a79 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -574,8 +574,8 @@ "crop": "Ritaglia" }, "CONVERT": "Converti", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Sei sicuro di voler chiudere l'editor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Scarica la tua immagine modificata oppure salvane una copia su Ente per preservare le modifiche.", + "confirm_editor_close": "Sei sicuro di voler chiudere l'editor?", + "confirm_editor_close_message": "Scarica la tua immagine modificata oppure salvane una copia su Ente per preservare le modifiche.", "BRIGHTNESS": "Luminosità", "CONTRAST": "Contrasto", "SATURATION": "Saturazione", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index 62a3af13f3..66b12f8cc6 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 04380b53c6..7a6a7c665d 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 761e490423..0b8a8662eb 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -574,8 +574,8 @@ "crop": "Apkirpti" }, "CONVERT": "Konvertuoti", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 3d430b7740..2d3029ec06 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -574,8 +574,8 @@ "crop": "Bijsnijden" }, "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.", + "confirm_editor_close": "Weet u zeker dat u de editor wilt afsluiten?", + "confirm_editor_close_message": "Download uw bewerkte afbeelding of sla een kopie op in Ente om uw wijzigingen te behouden.", "BRIGHTNESS": "Helderheid", "CONTRAST": "Contrast", "SATURATION": "Saturatie", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index c275fa56f1..96b2bb6803 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -574,8 +574,8 @@ "crop": "Przytnij" }, "CONVERT": "Konwertuj", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Czy na pewno chcesz zamknąć edytor?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Pobierz edytowany obraz lub zapisz kopię do Ente, aby utrzymać zmiany.", + "confirm_editor_close": "Czy na pewno chcesz zamknąć edytor?", + "confirm_editor_close_message": "Pobierz edytowany obraz lub zapisz kopię do Ente, aby utrzymać zmiany.", "BRIGHTNESS": "Jasność", "CONTRAST": "Kontrast", "SATURATION": "Nasycenie", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index 8ec40e94d9..1312175694 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -574,8 +574,8 @@ "crop": "Recortar" }, "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.", + "confirm_editor_close": "Tem certeza de que deseja fechar o editor?", + "confirm_editor_close_message": "Baixe sua imagem editada ou salve uma cópia para o ente para persistir nas alterações.", "BRIGHTNESS": "Brilho", "CONTRAST": "Contraste", "SATURATION": "Saturação", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 84c80ae963..8b75b06078 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 32cf888022..64ffbc94e2 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -574,8 +574,8 @@ "crop": "Обрезать" }, "CONVERT": "Преобразовать", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "Вы уверены, что хотите закрыть редактор?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "Загрузите отредактированное изображение или сохраните копию в ente, чтобы сохранить внесенные изменения.", + "confirm_editor_close": "Вы уверены, что хотите закрыть редактор?", + "confirm_editor_close_message": "Загрузите отредактированное изображение или сохраните копию в ente, чтобы сохранить внесенные изменения.", "BRIGHTNESS": "Яркость", "CONTRAST": "Контраст", "SATURATION": "Насыщенность", diff --git a/web/packages/base/locales/sl-SI/translation.json b/web/packages/base/locales/sl-SI/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/sl-SI/translation.json +++ b/web/packages/base/locales/sl-SI/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index 83010703d7..fc8ad36f93 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "Ljusstyrka", "CONTRAST": "Kontrast", "SATURATION": "", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index 05f822e944..ecaecfdb73 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/uk-UA/translation.json b/web/packages/base/locales/uk-UA/translation.json index 0f59a194f4..d11a4e533b 100644 --- a/web/packages/base/locales/uk-UA/translation.json +++ b/web/packages/base/locales/uk-UA/translation.json @@ -574,8 +574,8 @@ "crop": "" }, "CONVERT": "", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "", + "confirm_editor_close": "", + "confirm_editor_close_message": "", "BRIGHTNESS": "", "CONTRAST": "", "SATURATION": "", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index ce0da29c47..7de3e841ff 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -574,8 +574,8 @@ "crop": "裁剪" }, "CONVERT": "转换", - "CONFIRM_EDITOR_CLOSE_MESSAGE": "您确定要关闭编辑器吗?", - "CONFIRM_EDITOR_CLOSE_DESCRIPTION": "下载已编辑的图片或将副本保存到 Ente 以保留您的更改。", + "confirm_editor_close": "您确定要关闭编辑器吗?", + "confirm_editor_close_message": "下载已编辑的图片或将副本保存到 Ente 以保留您的更改。", "BRIGHTNESS": "亮度", "CONTRAST": "对比度", "SATURATION": "饱和度", From 62ecfc34c26fdc0c0f7b4b7af6ec278d75c40e57 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 10 Oct 2024 20:56:13 +0530 Subject: [PATCH 190/438] Rename and move --- web/apps/photos/src/utils/ui/index.tsx | 4 ++-- web/packages/accounts/components/LoginComponents.tsx | 4 ++-- web/packages/base/locales/ar-SA/translation.json | 4 ++-- web/packages/base/locales/bg-BG/translation.json | 4 ++-- web/packages/base/locales/ca-ES/translation.json | 4 ++-- web/packages/base/locales/da-DK/translation.json | 4 ++-- web/packages/base/locales/de-DE/translation.json | 4 ++-- web/packages/base/locales/el-GR/translation.json | 4 ++-- web/packages/base/locales/en-US/translation.json | 4 ++-- web/packages/base/locales/es-ES/translation.json | 4 ++-- web/packages/base/locales/et-EE/translation.json | 4 ++-- web/packages/base/locales/fa-IR/translation.json | 4 ++-- web/packages/base/locales/fi-FI/translation.json | 4 ++-- web/packages/base/locales/fr-FR/translation.json | 4 ++-- web/packages/base/locales/gu-IN/translation.json | 4 ++-- web/packages/base/locales/hi-IN/translation.json | 4 ++-- web/packages/base/locales/id-ID/translation.json | 4 ++-- web/packages/base/locales/is-IS/translation.json | 4 ++-- web/packages/base/locales/it-IT/translation.json | 4 ++-- web/packages/base/locales/ja-JP/translation.json | 4 ++-- web/packages/base/locales/km-KH/translation.json | 4 ++-- web/packages/base/locales/ko-KR/translation.json | 4 ++-- web/packages/base/locales/lt-LT/translation.json | 4 ++-- web/packages/base/locales/nl-NL/translation.json | 4 ++-- web/packages/base/locales/pl-PL/translation.json | 4 ++-- web/packages/base/locales/pt-BR/translation.json | 4 ++-- web/packages/base/locales/pt-PT/translation.json | 4 ++-- web/packages/base/locales/ru-RU/translation.json | 4 ++-- web/packages/base/locales/sl-SI/translation.json | 4 ++-- web/packages/base/locales/sv-SE/translation.json | 4 ++-- web/packages/base/locales/ta-IN/translation.json | 4 ++-- web/packages/base/locales/te-IN/translation.json | 4 ++-- web/packages/base/locales/th-TH/translation.json | 4 ++-- web/packages/base/locales/ti-ER/translation.json | 4 ++-- web/packages/base/locales/tr-TR/translation.json | 4 ++-- web/packages/base/locales/uk-UA/translation.json | 4 ++-- web/packages/base/locales/zh-CN/translation.json | 4 ++-- 37 files changed, 74 insertions(+), 74 deletions(-) diff --git a/web/apps/photos/src/utils/ui/index.tsx b/web/apps/photos/src/utils/ui/index.tsx index 3bfab469f9..77d1879571 100644 --- a/web/apps/photos/src/utils/ui/index.tsx +++ b/web/apps/photos/src/utils/ui/index.tsx @@ -124,8 +124,8 @@ export const getSubscriptionPurchaseSuccessMessage = ( export const getSessionExpiredMessage = ( action: () => void, ): DialogBoxAttributes => ({ - title: t("SESSION_EXPIRED"), - content: t("SESSION_EXPIRED_MESSAGE"), + title: t("session_expired"), + content: t("session_expired_message"), nonClosable: true, proceed: { diff --git a/web/packages/accounts/components/LoginComponents.tsx b/web/packages/accounts/components/LoginComponents.tsx index cece699417..dcb4eb5829 100644 --- a/web/packages/accounts/components/LoginComponents.tsx +++ b/web/packages/accounts/components/LoginComponents.tsx @@ -206,8 +206,8 @@ const ButtonStack = styled("div")` export const sessionExpiredDialogAttributes = ( onLogin: () => void, ): MiniDialogAttributes => ({ - title: t("SESSION_EXPIRED"), - message: t("SESSION_EXPIRED_MESSAGE"), + title: t("session_expired"), + message: t("session_expired_message"), nonClosable: true, continue: { text: t("login"), diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index 59fa13c900..713c906341 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "هل ترغب في تحميلهم إلى", "upload_to_single_album": "ألبوم واحد", "upload_to_album_per_folder": "ألبومات منفصلة", - "SESSION_EXPIRED_MESSAGE": "لقد انتهت صلاحية جلستك، يرجى تسجيل الدخول مرة أخرى للمتابعة", - "SESSION_EXPIRED": "انتهت صلاحية الجلسة", + "session_expired": "انتهت صلاحية الجلسة", + "session_expired_message": "لقد انتهت صلاحية جلستك، يرجى تسجيل الدخول مرة أخرى للمتابعة", "PASSWORD_GENERATION_FAILED": "لم يتمكن متصفحك من إنشاء مفتاح قوي يفي بمعايير تشفير Ente، يرجى المحاولة باستخدام تطبيق الهاتف المحمول أو متصفح آخر", "CHANGE_PASSWORD": "تغيير كلمة المرور", "password_changed_elsewhere": "تم تغيير كلمة المرور في مكان آخر", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index 17d3545591..7b455f5227 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index 5956cbe172..3133978879 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index 9101e1054d..c2f0eb476a 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Möchtest du sie hochladen in", "upload_to_single_album": "Ein einzelnes Album", "upload_to_album_per_folder": "Getrennte Alben", - "SESSION_EXPIRED_MESSAGE": "Ihre Sitzung ist abgelaufen. Bitte loggen Sie sich erneut ein, um fortzufahren", - "SESSION_EXPIRED": "Sitzung abgelaufen", + "session_expired": "Sitzung abgelaufen", + "session_expired_message": "Ihre Sitzung ist abgelaufen. Bitte loggen Sie sich erneut ein, um fortzufahren", "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", "password_changed_elsewhere": "Passwort anderswo geändert", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index a1f95be25a..fa3f3dbcb1 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Θα θέλατε να τα ανεβάσετε στο", "upload_to_single_album": "Ένα ενιαίο άλμπουμ", "upload_to_album_per_folder": "Ξεχωριστά άλμπουμ", - "SESSION_EXPIRED_MESSAGE": "Η συνεδρία σας έληξε, παρακαλούμε συνδεθείτε ξανά για να συνεχίσετε", - "SESSION_EXPIRED": "Η συνεδρία έληξε", + "session_expired": "Η συνεδρία έληξε", + "session_expired_message": "Η συνεδρία σας έληξε, παρακαλούμε συνδεθείτε ξανά για να συνεχίσετε", "PASSWORD_GENERATION_FAILED": "Ο περιηγητής σας δεν μπόρεσε να δημιουργήσει ένα ισχυρό κλειδί που να πληροί τα πρότυπα κρυπτογράφησης του Ente, παρακαλώ δοκιμάστε χρησιμοποιώντας την εφαρμογή ή άλλον περιηγητή", "CHANGE_PASSWORD": "Αλλαγή κωδικού πρόσβασής", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index fe07dec252..cafab48265 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Would you like to upload them into", "upload_to_single_album": "A single album", "upload_to_album_per_folder": "Separate albums", - "SESSION_EXPIRED_MESSAGE": "Your session has expired, please login again to continue", - "SESSION_EXPIRED": "Session expired", + "session_expired": "Session expired", + "session_expired_message": "Your session has expired, please login again to continue", "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", "password_changed_elsewhere": "Password changed elsewhere", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index 549058da5f..c929d61253 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Quieres subirlos a", "upload_to_single_album": "Un solo álbum", "upload_to_album_per_folder": "Separar álbumes", - "SESSION_EXPIRED_MESSAGE": "Tu sesión ha caducado. Inicia sesión de nuevo para continuar", - "SESSION_EXPIRED": "Sesión caducado", + "session_expired": "Sesión caducado", + "session_expired_message": "Tu sesión ha caducado. Inicia sesión de nuevo para continuar", "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", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index feaa13e8a8..85d68e94d1 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index e85a223bee..7b7b133c61 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 3b08b0b5f4..77dba1d9de 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Voulez-vous les charger dans", "upload_to_single_album": "Un seul album", "upload_to_album_per_folder": "Albums séparés", - "SESSION_EXPIRED_MESSAGE": "Votre session a expiré, veuillez vous reconnecter pour poursuivre", - "SESSION_EXPIRED": "Session expiré", + "session_expired": "Session expiré", + "session_expired_message": "Votre session a expiré, veuillez vous reconnecter pour poursuivre", "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", "password_changed_elsewhere": "Mot de passe modifié ailleurs", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index 72cfb37f71..82a39e51b3 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Apakah kamu ingin mengunggahnya ke", "upload_to_single_album": "Satu album", "upload_to_album_per_folder": "Album terpisah", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "Browser kamu tidak dapat menghasilkan kunci yang kuat, yang memenuhi standar enkripsi Ente. Silakan coba menggunakan app seluler atau browser lain", "CHANGE_PASSWORD": "Ubah sandi", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index 996e87fd21..7d37cd09ef 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index c6b0d31a79..ce34e0dcc1 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Vuoi caricarli in", "upload_to_single_album": "Un album singolo", "upload_to_album_per_folder": "Album separati", - "SESSION_EXPIRED_MESSAGE": "La sessione è scaduta. Per continuare, esegui nuovamente l'accesso", - "SESSION_EXPIRED": "Sessione scaduta", + "session_expired": "Sessione scaduta", + "session_expired_message": "La sessione è scaduta. Per continuare, esegui nuovamente l'accesso", "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", "password_changed_elsewhere": "Password cambiata altrove", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index 66b12f8cc6..ca404b0f70 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 7a6a7c665d..97e8a3e8b3 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "그것들을 업로드 하겠습니까", "upload_to_single_album": "싱글 앨범", "upload_to_album_per_folder": "앨범들 분리", - "SESSION_EXPIRED_MESSAGE": "세션이 만료되었습니다. 계속하려면 다시 로그인하세요", - "SESSION_EXPIRED": "세션 만료", + "session_expired": "세션 만료", + "session_expired_message": "세션이 만료되었습니다. 계속하려면 다시 로그인하세요", "PASSWORD_GENERATION_FAILED": "당신의 브라우저는 Ente의 암호화 표준을 충족하는 강력한 키를 생성할 수 없습니다. 모바일 앱이나 다른 브라우저를 사용하세요.", "CHANGE_PASSWORD": "암호 변경하기", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 0b8a8662eb..93bbfad2c2 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Ar norėtumėte juos įkelti į", "upload_to_single_album": "Vieną albumą", "upload_to_album_per_folder": "Atskirus albumus", - "SESSION_EXPIRED_MESSAGE": "Jūsų seansas baigėsi. Prisijunkite iš naujo, kad tęstumėte.", - "SESSION_EXPIRED": "Seansas baigėsi", + "session_expired": "Seansas baigėsi", + "session_expired_message": "Jūsų seansas baigėsi. Prisijunkite iš naujo, kad tęstumėte.", "PASSWORD_GENERATION_FAILED": "Jūsų naršyklė negalėjo sugeneruoti stipraus rakto, kuris atitiktų „Ente“ šifravimo standartus. Bandykite naudoti mobiliąją programą arba kitą naršyklę.", "CHANGE_PASSWORD": "Keisti slaptažodį", "password_changed_elsewhere": "Slaptažodis pakeistas kitur", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index 2d3029ec06..b8218e7e0c 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Wilt u deze uploaden naar", "upload_to_single_album": "Één enkel album", "upload_to_album_per_folder": "Aparte albums maken", - "SESSION_EXPIRED_MESSAGE": "Uw sessie is verlopen. Meld u opnieuw aan om verder te gaan", - "SESSION_EXPIRED": "Sessie verlopen", + "session_expired": "Sessie verlopen", + "session_expired_message": "Uw sessie is verlopen. Meld u opnieuw aan om verder te gaan", "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", "password_changed_elsewhere": "Wachtwoord elders gewijzigd", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 96b2bb6803..72436f3736 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Czy chcesz przesłać je do", "upload_to_single_album": "Pojedynczy album", "upload_to_album_per_folder": "Oddziel albumy", - "SESSION_EXPIRED_MESSAGE": "Twoja sesja wygasła, prosimy zalogować się ponownie, aby kontynuować", - "SESSION_EXPIRED": "Sesja wygasła", + "session_expired": "Sesja wygasła", + "session_expired_message": "Twoja sesja wygasła, prosimy zalogować się ponownie, aby kontynuować", "PASSWORD_GENERATION_FAILED": "Twoja przeglądarka nie była w stanie wygenerować silnego klucza, który spełnia standardy szyfrowania Ente, spróbuj użyć aplikacji mobilnej lub innej przeglądarki", "CHANGE_PASSWORD": "Zmień hasło", "password_changed_elsewhere": "Hasło zostało zmienione gdzie indziej", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index 1312175694..960cfd6249 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Gostaria de enviá-los para", "upload_to_single_album": "Um único álbum", "upload_to_album_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", + "session_expired": "Sessão expirada", + "session_expired_message": "A sua sessão expirou. Por favor inicie sessão novamente para continuar", "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", "password_changed_elsewhere": "Senha alterada em outro lugar", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 8b75b06078..528cb005e6 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index 64ffbc94e2..9dc8fbd272 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Вы хотите загрузить их в", "upload_to_single_album": "Один альбом", "upload_to_album_per_folder": "Отдельные альбомы", - "SESSION_EXPIRED_MESSAGE": "Истёк срок действия вашей сессии. Для продолжения, пожалуйста, войдите снова", - "SESSION_EXPIRED": "Время сессии истекло", + "session_expired": "Время сессии истекло", + "session_expired_message": "Истёк срок действия вашей сессии. Для продолжения, пожалуйста, войдите снова", "PASSWORD_GENERATION_FAILED": "Вашему браузеру не удалось сгенерировать надежный ключ, соответствующий стандартам шифрования ente, пожалуйста, попробуйте использовать мобильное приложение или другой браузер", "CHANGE_PASSWORD": "Изменить пароль", "password_changed_elsewhere": "Пароль изменен в другом месте", diff --git a/web/packages/base/locales/sl-SI/translation.json b/web/packages/base/locales/sl-SI/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/sl-SI/translation.json +++ b/web/packages/base/locales/sl-SI/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index fc8ad36f93..2d419f1ef5 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "Din session har upphört, logga in igen för att fortsätta", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "Din session har upphört, logga in igen för att fortsätta", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "Ändra lösenord", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index ecaecfdb73..e56d905b8f 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "Bunları yüklemek ister misin?", "upload_to_single_album": "Tek bir albüm", "upload_to_album_per_folder": "Ayrı ayrı albümler", - "SESSION_EXPIRED_MESSAGE": "Oturum sona erdi, devam etmek için lütfen tekrar giriş yap", - "SESSION_EXPIRED": "Oturum süresi doldu", + "session_expired": "Oturum süresi doldu", + "session_expired_message": "Oturum sona erdi, devam etmek için lütfen tekrar giriş yap", "PASSWORD_GENERATION_FAILED": "Tarayıcın Ente'nin şifreleme standartlarını karşılayan güçlü bir anahtar üretemedi, lütfen mobil uygulamayı veya başka bir tarayıcıyı kullanmayı dene", "CHANGE_PASSWORD": "Parolayı değiştir", "password_changed_elsewhere": "Parola başka bir yerde değiştirildi", diff --git a/web/packages/base/locales/uk-UA/translation.json b/web/packages/base/locales/uk-UA/translation.json index d11a4e533b..d96e1a79f2 100644 --- a/web/packages/base/locales/uk-UA/translation.json +++ b/web/packages/base/locales/uk-UA/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "", "upload_to_single_album": "", "upload_to_album_per_folder": "", - "SESSION_EXPIRED_MESSAGE": "", - "SESSION_EXPIRED": "", + "session_expired": "", + "session_expired_message": "", "PASSWORD_GENERATION_FAILED": "", "CHANGE_PASSWORD": "", "password_changed_elsewhere": "", diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index 7de3e841ff..7690f75760 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -102,8 +102,8 @@ "upload_to_choice": "你想要上传他们到", "upload_to_single_album": "单个相册", "upload_to_album_per_folder": "独立相册", - "SESSION_EXPIRED_MESSAGE": "您的会话已过期,请重新登录以继续", - "SESSION_EXPIRED": "会话已过期", + "session_expired": "会话已过期", + "session_expired_message": "您的会话已过期,请重新登录以继续", "PASSWORD_GENERATION_FAILED": "您的浏览器无法生成一个符合Ente加密标准的强密钥,请尝试使用移动应用程序或其他浏览器", "CHANGE_PASSWORD": "修改密码", "password_changed_elsewhere": "密码已在别处更改", From b9dd0bc3b781ee5e8df86ef441a392625c93406d Mon Sep 17 00:00:00 2001 From: Laurens Priem Date: Fri, 11 Oct 2024 10:02:11 +0530 Subject: [PATCH 191/438] ONNX changes (#3654) ## Description - Quantized the CLIP text encoder - Moved preprocessing and postprocessing of face detection inside the model - Optimised the ONNX models more wherever possible - Created a place in infra for ML version control of sorts ## Tests Have tested the changes on mobile, but not on desktop. Please carefully review the changes on desktop, especially regarding the face detection post-processing, more specifically the image (re-)size correction. --- desktop/src/main/services/ml-worker.ts | 20 +- infra/ml/.gitignore | 22 + infra/ml/.python-version | 1 + infra/ml/CLIP/mobileclip_onnx.ipynb | 1288 +++++++++++++++ infra/ml/README.md | 19 + infra/ml/YOLOv5Face/pytorch_weights/.gitkeep | 0 infra/ml/YOLOv5Face/yoloface_onnx.ipynb | 999 ++++++++++++ infra/ml/data/man.jpeg | Bin 0 -> 4120 bytes infra/ml/data/people.jpeg | Bin 0 -> 9012 bytes infra/ml/data/singapore.jpg | Bin 0 -> 613520 bytes infra/ml/pyproject.toml | 34 + infra/ml/uv.lock | 1427 +++++++++++++++++ .../face_ml/face_detection/detection.dart | 16 +- .../face_detection_postprocessing.dart | 138 -- .../face_detection_service.dart | 192 ++- .../services/machine_learning/ml_model.dart | 1 + .../clip/clip_image_encoder.dart | 4 +- .../clip/clip_text_encoder.dart | 4 +- .../ml/machine_learning_settings_page.dart | 6 +- mobile/lib/utils/image_ml_util.dart | 210 +-- .../.gradle/8.5/checksums/checksums.lock | Bin 0 -> 17 bytes .../dependencies-accessors.lock | Bin 0 -> 17 bytes .../8.5/dependencies-accessors/gc.properties | 0 .../8.5/executionHistory/executionHistory.bin | Bin 0 -> 19773 bytes .../executionHistory/executionHistory.lock | Bin 0 -> 17 bytes .../.gradle/8.5/fileChanges/last-build.bin | Bin 0 -> 1 bytes .../.gradle/8.5/fileHashes/fileHashes.bin | Bin 0 -> 18797 bytes .../.gradle/8.5/fileHashes/fileHashes.lock | Bin 0 -> 17 bytes .../android/.gradle/8.5/gc.properties | 0 .../buildOutputCleanup.lock | Bin 0 -> 17 bytes .../buildOutputCleanup/cache.properties | 2 + .../buildOutputCleanup/outputFiles.bin | Bin 0 -> 18803 bytes .../android/.gradle/config.properties | 2 + .../android/.gradle/file-system.probe | Bin 0 -> 8 bytes .../android/.gradle/vcs-1/gc.properties | 0 .../android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43462 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + mobile/plugins/onnx_dart/android/gradlew | 249 +++ mobile/plugins/onnx_dart/android/gradlew.bat | 92 ++ .../onnx_dart/android/local.properties | 11 +- .../ente/photos/onnx_dart/OnnxDartPlugin.kt | 34 +- web/apps/photos/package.json | 1 - web/docs/dependencies.md | 9 - web/packages/base/types/ipc.ts | 5 +- web/packages/new/photos/services/ml/clip.ts | 6 +- web/packages/new/photos/services/ml/face.ts | 205 +-- web/packages/new/photos/services/ml/image.ts | 47 - web/yarn.lock | 5 - 48 files changed, 4393 insertions(+), 663 deletions(-) create mode 100644 infra/ml/.gitignore create mode 100644 infra/ml/.python-version create mode 100644 infra/ml/CLIP/mobileclip_onnx.ipynb create mode 100644 infra/ml/README.md create mode 100644 infra/ml/YOLOv5Face/pytorch_weights/.gitkeep create mode 100644 infra/ml/YOLOv5Face/yoloface_onnx.ipynb create mode 100644 infra/ml/data/man.jpeg create mode 100644 infra/ml/data/people.jpeg create mode 100644 infra/ml/data/singapore.jpg create mode 100644 infra/ml/pyproject.toml create mode 100644 infra/ml/uv.lock delete mode 100644 mobile/lib/services/machine_learning/face_ml/face_detection/face_detection_postprocessing.dart create mode 100644 mobile/plugins/onnx_dart/android/.gradle/8.5/checksums/checksums.lock create mode 100644 mobile/plugins/onnx_dart/android/.gradle/8.5/dependencies-accessors/dependencies-accessors.lock create mode 100644 mobile/plugins/onnx_dart/android/.gradle/8.5/dependencies-accessors/gc.properties create mode 100644 mobile/plugins/onnx_dart/android/.gradle/8.5/executionHistory/executionHistory.bin create mode 100644 mobile/plugins/onnx_dart/android/.gradle/8.5/executionHistory/executionHistory.lock create mode 100644 mobile/plugins/onnx_dart/android/.gradle/8.5/fileChanges/last-build.bin create mode 100644 mobile/plugins/onnx_dart/android/.gradle/8.5/fileHashes/fileHashes.bin create mode 100644 mobile/plugins/onnx_dart/android/.gradle/8.5/fileHashes/fileHashes.lock create mode 100644 mobile/plugins/onnx_dart/android/.gradle/8.5/gc.properties create mode 100644 mobile/plugins/onnx_dart/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock create mode 100644 mobile/plugins/onnx_dart/android/.gradle/buildOutputCleanup/cache.properties create mode 100644 mobile/plugins/onnx_dart/android/.gradle/buildOutputCleanup/outputFiles.bin create mode 100644 mobile/plugins/onnx_dart/android/.gradle/config.properties create mode 100644 mobile/plugins/onnx_dart/android/.gradle/file-system.probe create mode 100644 mobile/plugins/onnx_dart/android/.gradle/vcs-1/gc.properties create mode 100644 mobile/plugins/onnx_dart/android/gradle/wrapper/gradle-wrapper.jar create mode 100644 mobile/plugins/onnx_dart/android/gradle/wrapper/gradle-wrapper.properties create mode 100755 mobile/plugins/onnx_dart/android/gradlew create mode 100644 mobile/plugins/onnx_dart/android/gradlew.bat diff --git a/desktop/src/main/services/ml-worker.ts b/desktop/src/main/services/ml-worker.ts index fcbd73576c..33b6c729ae 100644 --- a/desktop/src/main/services/ml-worker.ts +++ b/desktop/src/main/services/ml-worker.ts @@ -202,8 +202,8 @@ const createInferenceSession = async (modelPath: string) => { }; const cachedCLIPImageSession = makeCachedInferenceSession( - "mobileclip_s2_image_opset18_rgba_sim.onnx", - 143093992 /* 143 MB */, + "mobileclip_s2_image_opset18_rgba_opt.onnx", + 143099752 /* 143 MB */, ); /** @@ -228,8 +228,8 @@ export const computeCLIPImageEmbedding = async ( }; const cachedCLIPTextSession = makeCachedInferenceSession( - "mobileclip_s2_text_int32.onnx", - 253895600 /* 253 MB */, + "mobileclip_s2_text_opset18_quant.onnx", + 67144712 /* 67 MB */, ); let _tokenizer: Tokenizer | undefined; @@ -273,17 +273,21 @@ export const computeCLIPTextEmbeddingIfAvailable = async (text: string) => { }; const cachedFaceDetectionSession = makeCachedInferenceSession( - "yolov5s_face_640_640_dynamic.onnx", - 30762872 /* 29 MB */, + "yolov5s_face_opset18_rgba_opt.onnx", + 28952612 /* 29 MB */, ); /** * Face detection with the YOLO model and ONNX runtime. */ -export const detectFaces = async (input: Float32Array) => { +export const detectFaces = async ( + input: Uint8ClampedArray, + inputShape: number[], +) => { const session = await cachedFaceDetectionSession(); + const inputArray = new Uint8Array(input.buffer); const feeds = { - input: new ort.Tensor("float32", input, [1, 3, 640, 640]), + input: new ort.Tensor("uint8", inputArray, inputShape), }; const t = Date.now(); const results = await session.run(feeds); diff --git a/infra/ml/.gitignore b/infra/ml/.gitignore new file mode 100644 index 0000000000..4887c07499 --- /dev/null +++ b/infra/ml/.gitignore @@ -0,0 +1,22 @@ +# Python-generated files +__pycache__/ +*.py[oc] +build/ +dist/ +wheels/ +*.egg-info + +# Virtual environments +.venv + +# Models +*/onnx_models/ +*.pt +*.onnx +*.tflite + +# Imported repos +CLIP/mobileclip_repo/ + +# Data +data/flickr8k_captions.txt \ No newline at end of file diff --git a/infra/ml/.python-version b/infra/ml/.python-version new file mode 100644 index 0000000000..e4fba21835 --- /dev/null +++ b/infra/ml/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/infra/ml/CLIP/mobileclip_onnx.ipynb b/infra/ml/CLIP/mobileclip_onnx.ipynb new file mode 100644 index 0000000000..9a39daaaa8 --- /dev/null +++ b/infra/ml/CLIP/mobileclip_onnx.ipynb @@ -0,0 +1,1288 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Prepping MobileCLIP model for use in Ente\n", + "\n", + "[Paper](https://arxiv.org/pdf/2311.17049.pdf) | [Github](https://github.com/apple/ml-mobileclip)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setting up Pytorch weights and source code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# !mkdir mobileclip_repo\n", + "# %cd mobileclip_repo\n", + "# !git clone https://github.com/apple/ml-mobileclip.git\n", + "# %cd ml-mobileclip" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%cd mobileclip_repo/ml-mobileclip/" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# !source get_pretrained_models.sh # Files will be downloaded to `checkpoints` directory.\n", + "# %cd ../.." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!uv pip install clip-benchmark>=1.4.0 datasets>=2.8.0 open-clip-torch>=2.20.0 timm>=0.9.5" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torch.onnx\n", + "import torchvision\n", + "import torch.nn as nn\n", + "from PIL import Image\n", + "import mobileclip\n", + "import numpy as np\n", + "from numpy.linalg import norm\n", + "import onnx\n", + "import onnxruntime as ort\n", + "print(ort.__version__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model, _, preprocess = mobileclip.create_model_and_transforms('mobileclip_s2', pretrained='checkpoints/mobileclip_s2.pt')\n", + "og_model = model\n", + "model.eval()\n", + "og_model.eval()\n", + "tokenizer = mobileclip.get_tokenizer('mobileclip_s2')\n", + "\n", + "image = preprocess(Image.open(\"docs/fig_accuracy_latency.png\").convert('RGB')).unsqueeze(0)\n", + "text = tokenizer([\"Hello World!\", \"a diagram\", \"a dog\", \"a cat\"])\n", + "\n", + "with torch.no_grad(), torch.cuda.amp.autocast():\n", + " image_features = model.encode_image(image)\n", + " text_features = model.encode_text(text)\n", + " image_features /= image_features.norm(dim=-1, keepdim=True)\n", + " text_features /= text_features.norm(dim=-1, keepdim=True)\n", + "\n", + " text_probs = (100.0 * image_features @ text_features.T).softmax(dim=-1)\n", + "\n", + "print(\"Label probs:\", text_probs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%cd ../.." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# !rm -rf mobileclip_repo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "tokenizer([\"This is a tokenized string\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "text_input = tokenizer([\"Hello World! This is a super duper long piece of text of at least 77 tokens, purely to make sure that indeed this is a good input without any zeros that the exporter might somehow confuse with a boolean. Apparently we're still not at 77 tokens, so I just keep on monkey typing this story in the hope that someday I have a fully tokenized string of text that is longer than the required 77 tokens. Thank you for coming to my TED talk.\"])\n", + "text_emb = model.encode_text(text_input)[0].detach().numpy()\n", + "text_emb /= norm(text_emb)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "preprocess" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from PIL import Image" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image_singapore = Image.open(\"../data/singapore.jpg\").convert('RGBA')\n", + "image_input = preprocess(image_singapore).unsqueeze(0)\n", + "print(image_input.detach().numpy().shape)\n", + "print(1*3*256*256)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image_emb = model(image_input[:,:3,:,:])[0][0].detach().numpy()\n", + "print(image_emb.shape)\n", + "print(norm(image_emb))\n", + "image_emb[0:5]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image_singapore_onnx = np.array(image_singapore)\n", + "print(image_singapore_onnx.shape)\n", + "print(image_singapore_onnx.dtype)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Export to ONNX" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "onnx_opset = 18 # use opset 18 for Resize to antialias" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Image model" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "class EncodeImageWrapper(nn.Module):\n", + " def __init__(self, original_model):\n", + " super(EncodeImageWrapper, self).__init__()\n", + " self.original_model = original_model\n", + "\n", + " def forward(self, input):\n", + " return self.original_model.encode_image(input)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "image_model_wrapper = EncodeImageWrapper(model)\n", + "image_model_wrapper.eval()\n", + "image_model_wrapper.original_model.eval()\n", + "clip_image_onnx_export_path = \"onnx_models/mobileclip_s2_image_float32.onnx\"\n", + "torch.onnx.export(image_model_wrapper, image, clip_image_onnx_export_path, opset_version=onnx_opset, do_constant_folding=True, input_names=[\"input\"], output_names=[\"output\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "mobileclip_image_onnx = onnx.load(clip_image_onnx_export_path)\n", + "onnx.checker.check_model(mobileclip_image_onnx)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Text model" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "class EncodeTextWrapper(nn.Module):\n", + " def __init__(self, original_model):\n", + " super(EncodeTextWrapper, self).__init__()\n", + " self.original_model = original_model\n", + "\n", + " def forward(self, input):\n", + " return self.original_model.encode_text(input)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "text_model_wrapper = EncodeTextWrapper(model)\n", + "text_model_wrapper.eval()\n", + "text_model_wrapper.original_model.eval()\n", + "clip_text_onnx_export_path = \"onnx_models/mobileclip_s2_text_int64.onnx\"\n", + "torch.onnx.export(text_model_wrapper, text_input, clip_text_onnx_export_path, opset_version=onnx_opset, do_constant_folding=True, input_names=['input'], output_names=['output'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Altering ONNX models" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Image model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Change input name to `og_input` so we can reserve `input` for altered model that includes preprocessing" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "og_input = onnx.helper.make_tensor_value_info(\n", + " name=\"og_input\",\n", + " elem_type=onnx.TensorProto.FLOAT,\n", + " shape=[1, 3, 256, 256], \n", + ")\n", + "\n", + "# Update the input names in the rest of the model\n", + "for node in mobileclip_image_onnx.graph.node:\n", + " for i, input_name in enumerate(node.input):\n", + " if input_name == \"input\":\n", + " node.input[i] = \"og_input\"\n", + "\n", + "graph = onnx.helper.make_graph(\n", + " nodes=mobileclip_image_onnx.graph.node,\n", + " name=mobileclip_image_onnx.graph.name,\n", + " inputs=[og_input],\n", + " outputs=mobileclip_image_onnx.graph.output,\n", + " initializer=mobileclip_image_onnx.graph.initializer,\n", + ")\n", + "mobileclip_image_onnx = onnx.helper.make_model(graph, opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)])\n", + "onnx.save_model(mobileclip_image_onnx, clip_image_onnx_export_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add preprocessing to the model" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "from onnxruntime_extensions.tools.pre_post_processing import PrePostProcessor, create_named_value, Resize, ImageBytesToFloat, Unsqueeze, CenterCrop, Debug, ChannelsLastToChannelsFirst" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "inputs = [create_named_value(\"input_to_process\", onnx.TensorProto.UINT8, [\"H\", \"W\", \"C\"])]\n", + "\n", + "pipeline = PrePostProcessor(inputs, onnx_opset)\n", + "\n", + "pipeline.add_pre_processing(\n", + " [\n", + " Resize(256), \n", + " CenterCrop(256, 256), # Crop to 256x256. NOTE: Currently only HWC input is handled.\n", + " ChannelsLastToChannelsFirst(), # Convert to CHW\n", + " # Debug(),\n", + " ImageBytesToFloat(), # Convert to float in range 0..1 by dividing uint8 values by 255\n", + " # Debug(),\n", + " Unsqueeze([0]), # add batch, CHW --> 1CHW\n", + " # Debug(),\n", + " ]\n", + ")\n", + "\n", + "clip_image_with_preprocessing = pipeline.run(mobileclip_image_onnx)\n", + "\n", + "onnx.checker.check_model(clip_image_with_preprocessing)\n", + "clip_image_onnx_rgb_path = f\"onnx_models/mobileclip_s2_image_opset{onnx_opset}_rgb.onnx\"\n", + "new_model_path = clip_image_onnx_rgb_path\n", + "onnx.save_model(clip_image_with_preprocessing, new_model_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add a slice node so that the model can take raw RGBA data as input (as well as standard RGB)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "onnx_model = clip_image_with_preprocessing\n", + "\n", + "# Create a new input with flexible channel dimension\n", + "new_input = onnx.helper.make_tensor_value_info(\n", + " name=\"input\",\n", + " elem_type=onnx.TensorProto.UINT8,\n", + " shape=[\"H\", \"W\", \"C\"], \n", + ")\n", + "\n", + "# Create constant tensors for starts, ends, and axes\n", + "starts_tensor = onnx.helper.make_tensor(\n", + " name=\"starts\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[1],\n", + " vals=np.array([0], dtype=np.int64)\n", + ")\n", + "ends_tensor = onnx.helper.make_tensor(\n", + " name=\"ends\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[1],\n", + " vals=np.array([3], dtype=np.int64)\n", + ")\n", + "axes_tensor = onnx.helper.make_tensor(\n", + " name=\"axes\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[1],\n", + " vals=np.array([2], dtype=np.int64)\n", + ")\n", + "new_initializers = [starts_tensor, ends_tensor, axes_tensor] + list(onnx_model.graph.initializer)\n", + "slice_node = onnx.helper.make_node(\n", + " \"Slice\",\n", + " inputs=[\"input\", \"starts\", \"ends\", \"axes\"],\n", + " outputs=[\"sliced_input\"],\n", + " name=\"slice_rgba_input_node\"\n", + ")\n", + "\n", + "\n", + "# Add the new input and Slice node to the graph\n", + "graph = onnx.helper.make_graph(\n", + " [slice_node] + list(onnx_model.graph.node), # Prepend Slice node to existing nodes\n", + " onnx_model.graph.name,\n", + " [new_input],\n", + " list(onnx_model.graph.output),\n", + " initializer=new_initializers,\n", + " value_info=onnx_model.graph.value_info,\n", + ")\n", + "\n", + "# Create the new model\n", + "mobileclip_image_onnx_rgba = onnx.helper.make_model(\n", + " graph,\n", + " opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)]\n", + ")\n", + "\n", + "\n", + "# Update the input names in the rest of the model\n", + "for node in mobileclip_image_onnx_rgba.graph.node:\n", + " for i, input_name in enumerate(node.input):\n", + " if input_name == \"input_to_process\":\n", + " node.input[i] = \"sliced_input\"\n", + "\n", + "# Save the new model\n", + "onnx.checker.check_model(mobileclip_image_onnx_rgba)\n", + "clip_image_onnx_rgba_path = f\"onnx_models/mobileclip_s2_image_opset{onnx_opset}_rgba.onnx\"\n", + "onnx.save(mobileclip_image_onnx_rgba, clip_image_onnx_rgba_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Optimize the model" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "clip_image_sim_path = f\"onnx_models/mobileclip_s2_image_opset{onnx_opset}_rgba_sim.onnx\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!onnxsim {clip_image_onnx_rgba_path} {clip_image_sim_path}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Optimize the graph" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "image_opt_sess_options = ort.SessionOptions()\n", + "\n", + "image_opt_sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL\n", + "image_opt_sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_BASIC\n", + "\n", + "clip_image_opt_path = f\"onnx_models/mobileclip_s2_image_opset{onnx_opset}_rgba_opt.onnx\"\n", + "image_opt_sess_options.optimized_model_filepath = clip_image_opt_path\n", + "\n", + "opt_image_session = ort.InferenceSession(clip_image_sim_path, image_opt_sess_options)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add metadata to the model" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "clip_image_opt = onnx.load(clip_image_opt_path)\n", + "clip_image_opt.producer_name = \"EnteMobileCLIPImageEncoder\"\n", + "clip_image_opt.doc_string = \"MobileCLIP S2 Image Encoder with built-in preprocessing. Accepts both RGB and RGBA raw bytes input (uint8) in HWC format.\"\n", + "clip_image_opt.graph.doc_string = \"\"\n", + "clip_image_opt.graph.name = \"SliceRGB+Resize+CenterCrop+ToFloat+Unsqueeze+MobileCLIP_S2_ImageEncoder\"\n", + "onnx.save(clip_image_opt, clip_image_opt_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test the model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ort_session = ort.InferenceSession(clip_image_opt_path)\n", + "onnx_emb = ort_session.run(None, {\"input\": image_singapore_onnx})[0][0]\n", + "onnx_emb /= norm(onnx_emb)\n", + "np.dot(image_emb, onnx_emb)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "!rm {clip_image_onnx_export_path}\n", + "!rm {clip_image_onnx_rgb_path}\n", + "!rm {clip_image_onnx_rgba_path}\n", + "!rm {clip_image_sim_path}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Text model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Make sure the model can use int32 as input" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "mobileclip_text_onxx = onnx.load(clip_text_onnx_export_path)\n", + "\n", + "for tensor in mobileclip_text_onxx.graph.input:\n", + " if tensor.name == \"input\":\n", + " tensor.type.tensor_type.elem_type = onnx.TensorProto.INT32\n", + " break\n", + "\n", + "# Save the modified model\n", + "clip_text_onnx_int32_path = \"onnx_models/mobileclip_s2_text_int32.onnx\"\n", + "onnx.save(mobileclip_text_onxx, clip_text_onnx_int32_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Simplify](https://github.com/daquexian/onnx-simplifier) the model" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "clip_text_sim_path = f\"onnx_models/mobileclip_s2_text_opset{onnx_opset}_int32_sim.onnx\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!onnxsim {clip_text_onnx_int32_path} {clip_text_sim_path}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Apply basic offline [graph optimizations](https://onnxruntime.ai/docs/performance/model-optimizations/graph-optimizations.html). Only do the basic optimizations offline, the extended and layout optimizations should be done online depending on execution provider and hardware." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "text_opt_sess_options = ort.SessionOptions()\n", + "\n", + "text_opt_sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL\n", + "text_opt_sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_BASIC\n", + "\n", + "clip_text_opt_path = f\"onnx_models/mobileclip_s2_text_opset{onnx_opset}_int32_opt.onnx\"\n", + "text_opt_sess_options.optimized_model_filepath = clip_text_opt_path\n", + "\n", + "opt_text_session = ort.InferenceSession(clip_text_sim_path, text_opt_sess_options)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add metadata to the model" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "clip_text_opt = onnx.load(clip_text_opt_path)\n", + "clip_text_opt.producer_name = \"EnteMobileCLIPTextEncoder\"\n", + "clip_text_opt.doc_string = \"MobileCLIP S2 Text Encoder. Accepts an integer array (int32) of length 77. Longer arrays will be truncated.\"\n", + "clip_text_opt.graph.doc_string = \"\"\n", + "clip_text_opt.graph.name = \"MobileCLIP_S2_TextEncoder\"\n", + "onnx.save(clip_text_opt, clip_text_opt_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test the model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mobileclip_text_ort_sess = ort.InferenceSession(clip_text_opt_path)\n", + "text_onnx_emb = mobileclip_text_ort_sess.run([\"output\"], {\"input\": text_input.numpy().astype(\"int32\")})[0][0]\n", + "text_onnx_emb /= norm(text_onnx_emb)\n", + "np.dot(text_emb, text_onnx_emb)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [], + "source": [ + "!rm {clip_text_onnx_export_path}\n", + "!rm {clip_text_onnx_int32_path}\n", + "!rm {clip_text_sim_path}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Quantize text model\n", + "\n", + "https://onnxruntime.ai/docs/performance/model-optimizations/quantization.html" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Quantization pre-processing (not to confuse with normal pre-processing)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [], + "source": [ + "from onnxruntime.quantization import quant_pre_process" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "clip_text_quantized_preprocessed_path = \"onnx_models/mobileclip_s2_text_quant_preprocessed.onnx\"\n", + "quant_pre_process(clip_text_opt_path, clip_text_quantized_preprocessed_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dynamic quantization" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "from onnxruntime.quantization import quantize_dynamic, quantize_static, QuantType" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "node_names = []\n", + "matmul_nodes_names = []\n", + "for node in clip_text_opt.graph.node:\n", + " node_names.append(node.name)\n", + " if node.op_type == \"MatMul\" and node.name != \"/text_encoder/transformer.0/pre_norm_ffn/pre_norm_ffn.4/MatMul\":\n", + " matmul_nodes_names.append(node.name)\n", + "len(node_names)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [], + "source": [ + "clip_text_quantized_dynamic_path = f\"onnx_models/mobileclip_s2_text_opset{onnx_opset}_quant.onnx\"\n", + "quantize_dynamic(clip_text_quantized_preprocessed_path, clip_text_quantized_dynamic_path, nodes_to_exclude=node_names[28])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mobileclip_text_quant_dyn_ort_sess = ort.InferenceSession(clip_text_quantized_dynamic_path)\n", + "text_onnx_quant_dyn_emb = mobileclip_text_quant_dyn_ort_sess.run([\"output\"], {\"input\": text_input.numpy().astype(\"int32\")})[0][0]\n", + "text_onnx_quant_dyn_emb /= norm(text_onnx_quant_dyn_emb)\n", + "np.dot(text_onnx_quant_dyn_emb, text_onnx_emb)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Quantization Debugging (uncomment if you want to try it)" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "# exclude_amount = 1\n", + "\n", + "\n", + "# for i in range(25, 30, exclude_amount):\n", + "# begin = i\n", + "# end = min(i+exclude_amount, len(node_names))\n", + " \n", + "# clip_text_quantized_dynamic_debug_path = f\"onnx_models/mobileclip_s2_text_opset{onnx_opset}_int8dyn_opt_debug.onnx\"\n", + "# quantize_dynamic(clip_text_quantized_preprocessed_path, clip_text_quantized_dynamic_debug_path, nodes_to_exclude=node_names[begin:end])\n", + "# mobileclip_text_quant_dyn_ort_sess_debug = ort.InferenceSession(clip_text_quantized_dynamic_debug_path)\n", + "# text_onnx_quant_dyn_emb_debug = mobileclip_text_quant_dyn_ort_sess_debug.run([\"output\"], {\"input\": text_input.numpy().astype(\"int32\")})[0][0]\n", + "# text_onnx_quant_dyn_emb_debug /= norm(text_onnx_quant_dyn_emb_debug)\n", + "# sim_debug = np.dot(text_onnx_quant_dyn_emb_debug, text_onnx_emb)\n", + "# print(f\"Skipping nodes from {begin} to {end} resulted in a similarity of {sim_debug:.4f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "node_names[28:29]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test on a dataset of image captions. Before continuing, download the dataset from [Kaggle](https://www.kaggle.com/datasets/aladdinpersson/flickr8kimagescaptions/data) and put it in the `../data` folder" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "import csv\n", + "from tqdm import tqdm\n", + "import time\n", + "import copy\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "captions = []\n", + "\n", + "with open('../data/flickr8k_captions.txt', 'r', encoding='utf-8') as file:\n", + " csv_reader = csv.reader(file)\n", + " next(csv_reader)\n", + " for row in csv_reader:\n", + " captions.append(row[1])\n", + "\n", + "print(len(captions))\n", + "print(captions[:5])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test accuracy of quantized model quickly (uncomment code below)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "test_size = 600\n", + "similarities = np.zeros(test_size)\n", + "mobileclip_text_quant_dyn_ort_sess = ort.InferenceSession(clip_text_quantized_dynamic_path)\n", + "\n", + "for i, caption in tqdm(enumerate(captions[:test_size])):\n", + " text_input_test = tokenizer([caption])\n", + " text_emb_test = model.encode_text(text_input_test)[0].detach().numpy()\n", + " text_emb_test /= norm(text_emb_test)\n", + " text_onnx_test_emb = mobileclip_text_quant_dyn_ort_sess.run([\"output\"], {\"input\": text_input_test.numpy().astype(\"int32\")})[0][0]\n", + " text_onnx_test_emb /= norm(text_onnx_test_emb)\n", + " similarities[i] = np.dot(text_onnx_test_emb, text_emb_test)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(f\"Mean similarity: {similarities.mean()}\")\n", + "print(f\"Standard deviation: {similarities.std()}\")\n", + "print(f\"Minimum similarity: {similarities.min()}\")\n", + "print(f\"Maximum similarity: {similarities.max()}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test accuracy of quantized model extensively (uncomment code below)" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [], + "source": [ + "# captions_extensive = copy.deepcopy(captions)\n", + "\n", + "# for i in range(10000):\n", + "# captions_extensive[i] = captions_extensive[i] + \" \" + captions_extensive[i + 10000] + \" \" + captions_extensive[i + 20000] + \" \" + captions_extensive[i + 30000]\n", + "# captions_extensive[i + 10000] = captions_extensive[i + 10000] + \" \" + captions_extensive[i + 20000] + \" \" + captions_extensive[i + 30000]\n", + "# captions_extensive[i + 20000] = captions_extensive[i + 20000] + \" \" + captions_extensive[i + 30000]\n", + "# captions_extensive = captions_extensive[:40000]\n", + "\n", + "# test_size = len(captions_extensive)\n", + "# similarities_extensive = np.zeros(test_size)\n", + "# mobileclip_text_quant_dyn_ort_sess = ort.InferenceSession(clip_text_quantized_dynamic_path)\n", + "\n", + "# for i, caption in tqdm(enumerate(captions_extensive[:test_size])):\n", + "# text_input_test = tokenizer([caption])\n", + "# text_emb_test = model.encode_text(text_input_test)[0].detach().numpy()\n", + "# text_emb_test /= norm(text_emb_test)\n", + "# text_onnx_test_emb = mobileclip_text_quant_dyn_ort_sess.run([\"output\"], {\"input\": text_input_test.numpy().astype(\"int32\")})[0][0]\n", + "# text_onnx_test_emb /= norm(text_onnx_test_emb)\n", + "# similarities_extensive[i] = np.dot(text_onnx_test_emb, text_emb_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [], + "source": [ + "# print(f\"Mean similarity: {similarities_extensive.mean()}\")\n", + "# print(f\"Standard deviation: {similarities_extensive.std()}\")\n", + "# print(f\"Minimum similarity: {similarities_extensive.min()}\")\n", + "# print(f\"Maximum similarity: {similarities_extensive.max()}\")\n", + "# print(f\"Percentage of similarities above 0.99: {np.sum(similarities_extensive > 0.99) / len(similarities_extensive) * 100:.2f}%\")\n", + "# print(f\"Percentage of similarities above 0.995: {np.sum(similarities_extensive > 0.995) / len(similarities_extensive) * 100:.2f}%\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Investigating the MatMul excluded from quantization to improve performance (uncomment code below)" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [], + "source": [ + "# quant_model = onnx.load(clip_text_opt_path)\n", + "# node_name = node_names[28] # /text_encoder/transformer.0/pre_norm_ffn/pre_norm_ffn.4/MatMul\n", + "# # use_node_name = matmul_nodes_names[8]\n", + "# use_node_name = node_name\n", + "\n", + "# # Find the MatMul node\n", + "# special_matmul_node = None\n", + "# for node in quant_model.graph.node:\n", + "# if node.op_type == 'MatMul' and node.name == use_node_name:\n", + "# special_matmul_node = node\n", + "# print(f\"MatMul node found: {special_matmul_node.name}\")\n", + "# break\n", + "\n", + "# if special_matmul_node is None:\n", + "# raise ValueError(f\"MatMul node with name '{use_node_name}' not found in the model.\")\n", + "\n", + "# # Get the weight tensor\n", + "# weight_name = special_matmul_node.input[1]\n", + "# special_weight_tensor = None\n", + "# for init in quant_model.graph.initializer:\n", + "# if init.name == weight_name:\n", + "# special_weight_tensor = init\n", + "# break\n", + "\n", + "# if special_weight_tensor is None:\n", + "# raise ValueError(f\"Weight tensor for MatMul node '{use_node_name}' not found.\")\n", + "\n", + "# special_weight_array = onnx.numpy_helper.to_array(special_weight_tensor)\n", + "\n", + "# mean = np.mean(special_weight_array)\n", + "# std = np.std(special_weight_array)\n", + "# min_val = np.min(special_weight_array)\n", + "# max_val = np.max(special_weight_array)\n", + "\n", + "# print(f\"Statistical Analysis for MatMul node '{use_node_name}':\")\n", + "# print(f\"Mean: {mean}\")\n", + "# print(f\"Standard Deviation: {std}\")\n", + "# print(f\"Minimum: {min_val}\")\n", + "# print(f\"Maximum: {max_val}\")\n", + "# print(f\"Dynamic Range: {max_val - min_val}\")\n", + "\n", + "# plt.figure(figsize=(10, 6))\n", + "# plt.hist(special_weight_array.flatten(), bins=50, edgecolor='black')\n", + "# plt.title(f\"Histogram of Weights for MatMul node '{use_node_name}'\")\n", + "# plt.xlabel(\"Weight Value\")\n", + "# plt.ylabel(\"Frequency\")\n", + "# plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test speed of quantized model" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [], + "source": [ + "# time_test_size = 1000\n", + "# mobileclip_text_quant_dyn_ort_sess = ort.InferenceSession(clip_text_quantized_dynamic_path)\n", + "# times_unquantized = np.zeros(time_test_size)\n", + "# times_quantized = np.zeros(time_test_size)\n", + "\n", + "# # Time of unquantized model\n", + "# print(\"Timing unquantized model...\")\n", + "# for i, caption in tqdm(enumerate(captions[:time_test_size])):\n", + "# text_input_test = tokenizer([caption])\n", + "# start = time.time()\n", + "# _ = model.encode_text(text_input_test)\n", + "# end = time.time()\n", + "# times_unquantized[i] = end - start\n", + "\n", + "# # Time of quantized model\n", + "# print(\"Timing quantized model...\")\n", + "# for i, caption in tqdm(enumerate(captions[:time_test_size])):\n", + "# text_input_test = tokenizer([caption]).numpy().astype(\"int32\")\n", + "# start = time.time()\n", + "# _ = mobileclip_text_quant_dyn_ort_sess.run([\"output\"], {\"input\": text_input_test})\n", + "# end = time.time()\n", + "# times_quantized[i] = end - start\n", + "\n", + "# original_mean = times_unquantized.mean()\n", + "# original_std = times_unquantized.std()\n", + "# quantized_mean = times_quantized.mean()\n", + "# quantized_std = times_quantized.std()\n", + "\n", + "# print(f\"Original model: {original_mean:.6f} ± {original_std:.6f} seconds\")\n", + "# print(f\"Quantized model: {quantized_mean:.6f} ± {quantized_std:.6f} seconds\")\n", + "# print(f\"Speedup: {original_mean / quantized_mean:.2f}x\")" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [], + "source": [ + "!rm {clip_text_quantized_preprocessed_path}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Quantizing image model\n", + "\n", + "Eventually got it to roughly 0.996 similarity with the original model, at a reduction of 54MB, from 143 to 89MB. Also not bad, but since it's less of a reduction and the resulting embeddings will be stored permanently we decided not to use it. Uncomment code below to restart investigation if wanted." + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "# image_node_names = []\n", + "# image_matmul_nodes_names = []\n", + "# image_conv_nodes_names = []\n", + "# for node in clip_image_opt.graph.node:\n", + "# image_node_names.append(node.name)\n", + "# if node.op_type == \"MatMul\":\n", + "# image_matmul_nodes_names.append(node.name)\n", + "# if node.op_type == \"Conv\":\n", + "# image_conv_nodes_names.append(node.name)\n", + "# print(len(image_node_names))\n", + "# print(len(image_matmul_nodes_names))\n", + "# print(len(image_conv_nodes_names))" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [], + "source": [ + "# clip_image_quantized_dynamic_path = f\"onnx_models/mobileclip_s2_image_opset{onnx_opset}_int8_opt.onnx\"\n", + "# exclude = list(set(image_node_names[:100] + image_conv_nodes_names))\n", + "# quantize_dynamic(clip_image_opt_path, clip_image_quantized_dynamic_path, weight_type=QuantType.QUInt8, nodes_to_exclude=exclude)\n", + "\n", + "# mobileclip_image_quant_dyn_ort_sess = ort.InferenceSession(clip_image_quantized_dynamic_path)\n", + "# image_onnx_quant_dyn_emb = mobileclip_image_quant_dyn_ort_sess.run([\"output\"], {\"input\": image_singapore_onnx})[0][0]\n", + "# image_onnx_quant_dyn_emb /= norm(image_onnx_quant_dyn_emb)\n", + "# np.dot(image_onnx_quant_dyn_emb, image_emb)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Debug quantizations" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [], + "source": [ + "# exclude_amount = 50\n", + "# exclude_for_sure = image_node_names[:100] + image_node_names[225:260] + image_node_names[280:300] + image_node_names[430:480] + image_node_names[510:560] + image_node_names[650:]\n", + "\n", + "# image_test_quant = Image.open(\"../data/singapore.jpg\").convert('RGB')\n", + "# image_test_quant_onnx = np.array(image_test_quant)\n", + "\n", + "# clip_image_opt_sess = ort.InferenceSession(clip_image_opt_path)\n", + "# onnx_emb_quant_test = clip_image_opt_sess.run(None, {\"input\": image_test_quant_onnx})[0][0]\n", + "# onnx_emb_quant_test /= norm(onnx_emb_quant_test)\n", + "\n", + "\n", + "# for i in range(550, 600, exclude_amount):\n", + "# begin = i\n", + "# end = min(i+exclude_amount, len(image_node_names))\n", + "# exclude = list(set(exclude_for_sure + image_node_names[begin:end]))\n", + " \n", + "# clip_image_quantized_dynamic_debug_path = f\"onnx_models/mobileclip_s2_image_opset{onnx_opset}_int8dyn_opt_debug.onnx\"\n", + "# quantize_dynamic(clip_image_opt_path, clip_image_quantized_dynamic_debug_path, weight_type=QuantType.QUInt8, nodes_to_exclude=exclude)\n", + "# mobileclip_image_quant_dyn_ort_sess_debug = ort.InferenceSession(clip_image_quantized_dynamic_debug_path)\n", + "# image_onnx_quant_dyn_emb_debug = mobileclip_image_quant_dyn_ort_sess_debug.run([\"output\"], {\"input\": image_test_quant_onnx})[0][0]\n", + "# image_onnx_quant_dyn_emb_debug /= norm(image_onnx_quant_dyn_emb_debug)\n", + "# sim_debug = np.dot(image_onnx_quant_dyn_emb_debug, onnx_emb_quant_test)\n", + "# print(f\"Skipping nodes from {begin} to {end} resulted in a similarity of {sim_debug:.4f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Float16 conversion for Image model\n", + "\n", + "https://onnxruntime.ai/docs/performance/model-optimizations/float16.html" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [], + "source": [ + "from onnxconverter_common import convert_float_to_float16" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [], + "source": [ + "check_nodes_names = []\n", + "skip_nodes_names = []\n", + "try_image_model = onnx.load(clip_image_opt_path)\n", + "for node in try_image_model.graph.node:\n", + " check_nodes_names.append(node.name)\n", + "preprocess_nodes = check_nodes_names[:25]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "clip_image_fp16 = convert_float_to_float16(try_image_model, keep_io_types=True, disable_shape_infer=True, node_block_list=preprocess_nodes)\n", + "clip_image_fp16_path = f\"onnx_models/mobileclip_s2_image_opset{onnx_opset}_fp16.onnx\"\n", + "onnx.save(clip_image_fp16, clip_image_fp16_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image_onnx_input = np.array(Image.open(\"../data/singapore.jpg\").convert('RGB'))\n", + "try_sess_options = ort.SessionOptions()\n", + "try_sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_EXTENDED\n", + "# try_sess_options.inter_op_num_threads = 0\n", + "# try_sess_options.intra_op_num_threads = 0\n", + "# try_sess_options.execution_mode = ort.ExecutionMode.ORT_PARALLEL\n", + "# try_sess_options.enable_profiling = True\n", + "# try_sess_options.log_severity_level = 0 # Verbose\n", + "clip_image_fp16_sess = ort.InferenceSession(clip_image_fp16_path, try_sess_options)\n", + "clip_image_sess = ort.InferenceSession(clip_image_opt_path, try_sess_options)\n", + "image_onnx_fp16_emb = clip_image_fp16_sess.run([\"output\"], {\"input\": image_onnx_input})[0][0]\n", + "image_onnx_fp16_emb /= norm(image_onnx_fp16_emb)\n", + "image_onnx_emb = clip_image_sess.run([\"output\"], {\"input\": image_onnx_input})[0][0]\n", + "image_onnx_emb /= norm(image_onnx_emb)\n", + "print(np.dot(image_onnx_fp16_emb, image_onnx_emb))\n", + "print(image_onnx_emb[0:5])\n", + "print(image_onnx_fp16_emb[0:5])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Test speed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "time_test_size = 100\n", + "\n", + "begin_time_fp16 = time.time()\n", + "for i in tqdm(range(time_test_size)):\n", + " _ = clip_image_fp16_sess.run([\"output\"], {\"input\": image_onnx_input})\n", + "end_time_fp16 = time.time()\n", + "time_fp16 = end_time_fp16 - begin_time_fp16\n", + "\n", + "begin_time_opt = time.time()\n", + "for i in tqdm(range(time_test_size)):\n", + " _ = clip_image_sess.run([\"output\"], {\"input\": image_onnx_input})\n", + "end_time_opt = time.time()\n", + "time_opt = end_time_opt - begin_time_opt\n", + "\n", + "\n", + "\n", + "print(f\"Optimized model: {time_opt:.6f} seconds, so {time_opt / time_test_size:.6f} seconds per inference\")\n", + "print(f\"FP16 model: {time_fp16:.6f} seconds, so {time_fp16 / time_test_size:.6f} seconds per inference\")\n", + "print(f\"Speed difference FP16: {time_opt / time_fp16:.2f}x\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ente_clip", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/infra/ml/README.md b/infra/ml/README.md new file mode 100644 index 0000000000..ffc468ba2f --- /dev/null +++ b/infra/ml/README.md @@ -0,0 +1,19 @@ +# Ente ML playground + +This is a central place to keep track of any (Python) code used for prepping our ML models. The purpose of storing it here is to have some kind of version control over the alterations made to the models. + +Most of the code is in [Jupyter Notebooks](https://jupyter.org/), which facilitates quick interation and good documentation. + +## Running any notebook + +In case you're using VSCode, make sure you've installed the [Jupyter](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter) extension. + +1. [Install uv](https://docs.astral.sh/uv/getting-started/installation/) +2. Run `uv sync` +3. Run `uv venv` +4. In any notebook, make sure to select the virtual environment kernel from `.venv/bin/python` in the top (right corner on VSCode) + +## Notebooks and git + +Please make sure to always clear output data inside a notebook before committing changes to git. +Jupyter notebooks are known to not always work nicely with Git versioning control when there is output in them. diff --git a/infra/ml/YOLOv5Face/pytorch_weights/.gitkeep b/infra/ml/YOLOv5Face/pytorch_weights/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/infra/ml/YOLOv5Face/yoloface_onnx.ipynb b/infra/ml/YOLOv5Face/yoloface_onnx.ipynb new file mode 100644 index 0000000000..b7b157be5f --- /dev/null +++ b/infra/ml/YOLOv5Face/yoloface_onnx.ipynb @@ -0,0 +1,999 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Prepping YOLOv5Face model for use in Ente\n", + "\n", + "[Paper](https://arxiv.org/abs/2105.12931) | [Github](https://github.com/deepcam-cn/yolov5-face)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setting up Pytorch weights and source code" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Please manually put the Pytorch .pt weights in the `pytorch_weights` directory. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "model_weights_path = \"pytorch_weights/yolov5s_face.pt\"\n", + "models_path = \"onnx_models/\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!mkdir yoloface_repo\n", + "%cd yoloface_repo\n", + "!git clone https://github.com/deepcam-cn/yolov5-face.git\n", + "%cd ..\n", + "!cp -r yoloface_repo/yolov5-face/models/ models/\n", + "!cp -r yoloface_repo/yolov5-face/utils/ utils/\n", + "!rm -rf yoloface_repo" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Libraries\n", + "import torch\n", + "import torch.nn as nn\n", + "from PIL import Image\n", + "import json\n", + "import numpy as np\n", + "import onnx\n", + "import onnxruntime as ort\n", + "print(ort.__version__)\n", + "\n", + "# Source code\n", + "from models.common import Conv, ShuffleV2Block\n", + "from models.experimental import attempt_load\n", + "from utils.activations import Hardswish, SiLU\n", + "from utils.general import set_logging, check_img_size" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Export to ONNX" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "onnx_opset = 18\n", + "img_size = [640, 640]\n", + "batch_size = 1\n", + "dynamic_shapes = False\n", + "\n", + "# Load PyTorch model\n", + "model = attempt_load(\n", + " model_weights_path, map_location=torch.device(\"cpu\")\n", + ") # load FP32 model\n", + "delattr(model.model[-1], \"anchor_grid\")\n", + "model.model[-1].anchor_grid = [\n", + " torch.zeros(1)\n", + "] * 3 # nl=3 number of detection layers\n", + "model.model[-1].export_cat = True\n", + "model.eval()\n", + "labels = model.names\n", + "\n", + "# Checks\n", + "gs = int(max(model.stride)) # grid size (max stride)\n", + "img_size = [\n", + " check_img_size(x, gs) for x in img_size\n", + "] # verify img_size are gs-multiples\n", + "\n", + "# Test input\n", + "img = torch.zeros(batch_size, 3, *img_size)\n", + "\n", + "# Update model\n", + "for k, m in model.named_modules():\n", + " m._non_persistent_buffers_set = set() # pytorch 1.6.0 compatibility\n", + " if isinstance(m, Conv): # assign export-friendly activations\n", + " if isinstance(m.act, nn.Hardswish):\n", + " m.act = Hardswish()\n", + " elif isinstance(m.act, nn.SiLU):\n", + " m.act = SiLU()\n", + " if isinstance(m, ShuffleV2Block): # shufflenet block nn.SiLU\n", + " for i in range(len(m.branch1)):\n", + " if isinstance(m.branch1[i], nn.SiLU):\n", + " m.branch1[i] = SiLU()\n", + " for i in range(len(m.branch2)):\n", + " if isinstance(m.branch2[i], nn.SiLU):\n", + " m.branch2[i] = SiLU()\n", + "y = model(img) # dry run\n", + "\n", + "# ONNX export\n", + "print(\"\\nStarting ONNX export with onnx %s...\" % onnx.__version__)\n", + "onnx_model_export_path = models_path + model_weights_path.replace(\".pt\", \".onnx\").split('/')[-1]\n", + "model.fuse() \n", + "input_names = [\"input\"]\n", + "output_names = [\"output\"]\n", + "torch.onnx.export(\n", + " model,\n", + " img,\n", + " onnx_model_export_path,\n", + " verbose=False,\n", + " opset_version=onnx_opset,\n", + " input_names=input_names,\n", + " output_names=output_names,\n", + " dynamic_axes=(\n", + " {\"input\": {0: \"batch\"}, \"output\": {0: \"batch\"}} if dynamic_shapes else None\n", + " ),\n", + ")\n", + "\n", + "# Checks\n", + "onnx_model = onnx.load(onnx_model_export_path) # load onnx model\n", + "onnx.checker.check_model(onnx_model) # check onnx model\n", + "\n", + "# onnx infer\n", + "providers = [\"CPUExecutionProvider\"]\n", + "session = ort.InferenceSession(onnx_model_export_path, providers=providers)\n", + "im = img.cpu().numpy().astype(np.float32) # torch to numpy\n", + "y_onnx = session.run(\n", + " [session.get_outputs()[0].name], {session.get_inputs()[0].name: im}\n", + ")[0]\n", + "print(\"pred's shape is \", y_onnx.shape)\n", + "print(\"max(|torch_pred - onnx_pred|) =\", abs(y.cpu().numpy() - y_onnx).max())" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "!rm -rf models/\n", + "!rm -rf utils/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Altering ONNX model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add preprocessing inside model" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "from onnxruntime_extensions.tools.pre_post_processing import PrePostProcessor, create_named_value, Resize, ImageBytesToFloat, Unsqueeze, Debug, LetterBox, ChannelsLastToChannelsFirst" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "inputs = [create_named_value(\"input_to_preprocess\", onnx.TensorProto.UINT8, [\"H\", \"W\", \"C\"])]\n", + "\n", + "pipeline = PrePostProcessor(inputs, onnx_opset)\n", + "\n", + "pipeline.add_pre_processing(\n", + " [\n", + " Resize(640, layout= \"HWC\", policy=\"not_larger\"), # Resize to 640, maintaining aspect ratio and letting largest dimension not exceed 640 (so smaller dimension will be <= 640)\n", + " # Debug(),\n", + " LetterBox((640, 640), layout=\"HWC\", fill_value=114), # Add padding to make the image actually always 640x640,\n", + " ChannelsLastToChannelsFirst(), # Convert to CHW\n", + " # Debug(),\n", + " ImageBytesToFloat(), # Convert to float in range 0..1 by dividing uint8 values by 255\n", + " # Debug(),\n", + " Unsqueeze([0]), # add batch, CHW --> 1CHW\n", + " # Debug(),\n", + " ]\n", + ")\n", + "\n", + "# pipeline.add_post_processing()\n", + "onnx_model_prepro = pipeline.run(onnx_model)\n", + "onnx.checker.check_model(onnx_model_prepro)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To debug and visually inspect the preprocessing, please uncomment the `Debug()` statements in above block and run it again, and then uncomment and run the code in the block below:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# onnx.save(onnx_model_prepro, \"yolov5s_face_prepro.onnx\")\n", + "\n", + "# image_singapore = Image.open(\"../data/singapore.jpg\").convert('RGB')\n", + "# image_singapore_onnx = np.array(image_singapore)\n", + "# print(image_singapore_onnx.shape)\n", + "# print(type(image_singapore_onnx))\n", + "# print(image_singapore_onnx.dtype)\n", + "\n", + "# ort_session = ort.InferenceSession(\"yolov5s_face_prepro.onnx\")\n", + "# test = ort_session.run(None, {\"input_to_preprocess\": image_singapore_onnx})\n", + "\n", + "# preprocessed = test[4]\n", + "# print(preprocessed.shape)\n", + "# print(type(preprocessed))\n", + "\n", + "# # import matplotlib#.pyplot as plt\n", + "# from IPython.display import display\n", + "# # matplotlib.use('TkAgg')\n", + "\n", + "# displayable_array = preprocessed.reshape(3, 640, 640).transpose((1, 2, 0))\n", + "# # Display the image\n", + "# # matplotlib.pyplot.imshow(displayable_array)\n", + "# # matplotlib.pyplot.axis('off') \n", + "# # matplotlib.pyplot.show()\n", + "# display(Image.fromarray((displayable_array * 255).astype(np.uint8)))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add slice operator for use of RGBA input" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a new input with flexible channel dimension\n", + "new_input = onnx.helper.make_tensor_value_info(\n", + " name=\"input\",\n", + " elem_type=onnx.TensorProto.UINT8,\n", + " shape=[\"H\", \"W\", \"C\"], \n", + ")\n", + "\n", + "# Create constant tensors for starts, ends, and axes and use them to create a Slice node\n", + "starts_tensor = onnx.helper.make_tensor(\n", + " name=\"starts\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[1],\n", + " vals=np.array([0], dtype=np.int64)\n", + ")\n", + "ends_tensor = onnx.helper.make_tensor(\n", + " name=\"ends\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[1],\n", + " vals=np.array([3], dtype=np.int64)\n", + ")\n", + "axes_tensor = onnx.helper.make_tensor(\n", + " name=\"axes\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[1],\n", + " vals=np.array([2], dtype=np.int64)\n", + ")\n", + "slice_node = onnx.helper.make_node(\n", + " \"Slice\",\n", + " inputs=[\"input\", \"starts\", \"ends\", \"axes\"],\n", + " outputs=[\"sliced_input\"],\n", + " name=\"slice_rgba_input_node\",\n", + ")\n", + "# Combine initializers\n", + "initializers = [starts_tensor, ends_tensor, axes_tensor] + list(onnx_model_prepro.graph.initializer)\n", + "\n", + "# Get the name of the original input\n", + "original_input_name = onnx_model_prepro.graph.input[0].name\n", + "\n", + "# Make new graph by adding the new input and Slice node to the old graph\n", + "graph = onnx.helper.make_graph(\n", + " [slice_node] + list(onnx_model_prepro.graph.node), # Prepend Slice node to existing nodes\n", + " onnx_model_prepro.graph.name,\n", + " [new_input] + list(onnx_model_prepro.graph.input)[1:], # Replace first input, keep others\n", + " list(onnx_model_prepro.graph.output),\n", + " initializer=initializers,\n", + " value_info=onnx_model_prepro.graph.value_info,\n", + ")\n", + "\n", + "# Create the new model\n", + "onnx_model_rgba = onnx.helper.make_model(\n", + " graph,\n", + " opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)]\n", + ")\n", + "\n", + "# Update the input names in the rest of the model\n", + "for node in onnx_model_rgba.graph.node:\n", + " for i, input_name in enumerate(node.input):\n", + " if input_name == original_input_name:\n", + " node.input[i] = \"sliced_input\"\n", + "\n", + "# Save the new model\n", + "onnx.checker.check_model(onnx_model_rgba)\n", + "onnx_model_rgba_path = onnx_model_export_path[:-5] + \"_rgba.onnx\"\n", + "onnx.save(onnx_model_rgba, onnx_model_rgba_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "# image = Image.open(\"../data/man.jpeg\").convert('RGBA')\n", + "# image_onnx = np.array(image)\n", + "# print(image_onnx.shape)\n", + "# print(type(image_onnx))\n", + "# print(image_onnx.dtype)\n", + "\n", + "# ort_session = ort.InferenceSession(\"yolov5s_face_rgba.onnx\")\n", + "# test = ort_session.run(None, {\"input\": image_onnx})\n", + "# print(test[0].shape)\n", + "# scores_output = test[0][:,:,4]\n", + "# print(f\"Highest score: {scores_output.max()}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add post-processing inside the model" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's first rename the output of the model so we can name the post-processed output as `output`.\n", + "Then we have to split `[1, 25200, 16]` into `[1, 25200, 4]`, `[1, 25200, 1]`, `[1, 25200, 11]` (i.e. `[1, detections, bbox]`, `[1, detections, score]`, `[1, detections, landmarks]`) named `boxes`, `scores`, `masks`." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "# Add a Split operator at the end so that it be used with the SelectBestBoundingBoxesByNMS operator\n", + "num_det = 25200\n", + "graph = onnx_model_rgba.graph\n", + "\n", + "# Let's first rename the output of the model so we can name the post-processed output as `output`\n", + "for node in onnx_model_rgba.graph.node:\n", + " for i, output_name in enumerate(node.output):\n", + " if output_name == \"output\":\n", + " node.output[i] = \"og_output\"\n", + "og_output = onnx.helper.make_tensor_value_info(\n", + " name=\"og_output\",\n", + " elem_type=onnx.TensorProto.FLOAT,\n", + " shape=[1, num_det, 16], \n", + ")\n", + "\n", + "# Create the split node\n", + "boxes_output = onnx.helper.make_tensor_value_info(\n", + " name=\"boxes_unsqueezed\",\n", + " elem_type=onnx.TensorProto.FLOAT,\n", + " shape=[1, num_det, 4], \n", + ")\n", + "scores_output = onnx.helper.make_tensor_value_info(\n", + " name=\"scores_unsqueezed\",\n", + " elem_type=onnx.TensorProto.FLOAT,\n", + " shape=[1, num_det, 1], \n", + ")\n", + "masks_output = onnx.helper.make_tensor_value_info(\n", + " name=\"masks_unsqueezed\",\n", + " elem_type=onnx.TensorProto.FLOAT,\n", + " shape=[1, num_det, 11], \n", + ")\n", + "splits_tensor = onnx.helper.make_tensor(\n", + " name=\"splits\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[3],\n", + " vals=np.array([4, 1, 11], dtype=np.int64)\n", + ")\n", + "split_node = onnx.helper.make_node(\n", + " \"Split\",\n", + " inputs=[\"og_output\", \"splits\"],\n", + " outputs=[\"boxes_unsqueezed\", \"scores_unsqueezed\", \"masks_unsqueezed\"],\n", + " name=\"split_og_output\",\n", + " axis=2,\n", + ")\n", + "\n", + "# Combine initializers\n", + "initializers = list(graph.initializer) + [splits_tensor]\n", + "\n", + "# Make new graph by adding the new outputs and Split node to the old graph\n", + "graph = onnx.helper.make_graph(\n", + " list(graph.node) + [split_node], # Append split node to existing nodes\n", + " graph.name,\n", + " list(graph.input), \n", + " [boxes_output, scores_output, masks_output],\n", + " initializer=initializers,\n", + " value_info=graph.value_info,\n", + ")\n", + "\n", + "# Create the new model\n", + "onnx_model_split = onnx.helper.make_model(\n", + " graph,\n", + " opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)]\n", + ")\n", + "\n", + "# Save the new model\n", + "onnx.checker.check_model(onnx_model_split)\n", + "onnx_model_split_path = onnx_model_export_path[:-5] + \"_split.onnx\"\n", + "onnx.save(onnx_model_split, onnx_model_split_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can run NMS on these splitted outputs using `NonMaxSuppression` operator" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "num_det = 25200\n", + "graph = onnx_model_split.graph\n", + "nodes = list(graph.node)\n", + "outputs = list(graph.output)\n", + "initializers = list(graph.initializer)\n", + "original_output = graph.output[0]\n", + "\n", + "# Create the Transpose node for the scores (since NMS requires the scores to be in the middle dimension for some reason)\n", + "transpose_node_score = onnx.helper.make_node(\n", + " \"Transpose\",\n", + " inputs=[\"scores_unsqueezed\"],\n", + " outputs=[\"scores_transposed\"],\n", + " name=\"transpose_scores\",\n", + " perm=[0, 2, 1],\n", + ")\n", + "nodes.append(transpose_node_score)\n", + "\n", + "# Create the NMS node\n", + "nms_indices = onnx.helper.make_tensor_value_info(\"nms_indices\", onnx.TensorProto.INT64, shape=[\"detections\", 3])\n", + "max_output = onnx.helper.make_tensor(\"max_output\",onnx.TensorProto.INT64, [1], np.array([100], dtype=np.int64))\n", + "iou_threshold = onnx.helper.make_tensor(\"iou_threshold\",onnx.TensorProto.FLOAT, [1], np.array([0.4], dtype=np.float32))\n", + "score_threshold = onnx.helper.make_tensor(\"score_threshold\",onnx.TensorProto.FLOAT, [1], np.array([0.6], dtype=np.float32))\n", + "initializers = initializers + [max_output, iou_threshold, score_threshold]\n", + "nms_node = onnx.helper.make_node(\n", + " \"NonMaxSuppression\",\n", + " inputs=[\"boxes_unsqueezed\", \"scores_transposed\", \"max_output\", \"iou_threshold\", \"score_threshold\"],\n", + " outputs=[\"nms_indices\"],\n", + " name=\"perform_nms\",\n", + " center_point_box=1,\n", + ")\n", + "nodes.append(nms_node)\n", + "outputs.append(nms_indices)\n", + "\n", + "# Make new graph by adding the new outputs and Split node to the old graph\n", + "graph = onnx.helper.make_graph(\n", + " nodes,\n", + " graph.name,\n", + " list(graph.input), \n", + " outputs,\n", + " initializer=initializers,\n", + " value_info=graph.value_info,\n", + ")\n", + "\n", + "# Create the new model\n", + "onnx_model_nms = onnx.helper.make_model(\n", + " graph,\n", + " opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)]\n", + ")\n", + "\n", + "# Save the new model\n", + "onnx.checker.check_model(onnx_model_nms)\n", + "onnx_model_nms_path = onnx_model_export_path[:-5] + \"_nms.onnx\"\n", + "onnx.save(onnx_model_nms, onnx_model_nms_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "# image = Image.open(\"../data/man.jpeg\").convert('RGBA')\n", + "# image_onnx = np.array(image)\n", + "\n", + "# ort_session = ort.InferenceSession(\"yolov5s_face_nms.onnx\")\n", + "# test = ort_session.run(None, {\"input\": image_onnx})\n", + "# print(test[3].shape)\n", + "# print(test[3])\n", + "# print(test[1][0, 24129, 0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we need to add some Squeeze, Slice and Gather nodes so handle the NMS given indices properly. The goal is that the final output is a very simple array of shape `(detections, 16)` of only the relevant detections." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "num_det = 25200\n", + "graph = onnx_model_nms.graph\n", + "nodes = list(graph.node)\n", + "outputs = list(graph.output)\n", + "initializers = list(graph.initializer)\n", + "original_output = graph.output[0]\n", + "\n", + "# Create Slide node to slice the NMS indices from (detections, 3) to (detections, 1) by taking the third column\n", + "sliced_indices = onnx.helper.make_tensor_value_info(\"sliced_indices\", onnx.TensorProto.INT64, shape=[\"detections\", 1])\n", + "outputs.append(sliced_indices)\n", + "starts_slice_tensor = onnx.helper.make_tensor(\n", + " name=\"starts_slice_tensor\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[1],\n", + " vals=np.array([2], dtype=np.int64)\n", + ")\n", + "ends_slice_tensor = onnx.helper.make_tensor(\n", + " name=\"ends_slice_tensor\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[1],\n", + " vals=np.array([3], dtype=np.int64)\n", + ")\n", + "axes_slice_tensor = onnx.helper.make_tensor(\n", + " name=\"axes_slice_tensor\",\n", + " data_type=onnx.TensorProto.INT64,\n", + " dims=[1],\n", + " vals=np.array([1], dtype=np.int64)\n", + ")\n", + "initializers = initializers + [starts_slice_tensor, ends_slice_tensor, axes_slice_tensor]\n", + "slice_node = onnx.helper.make_node(\n", + " \"Slice\",\n", + " inputs=[\"nms_indices\", \"starts_slice_tensor\", \"ends_slice_tensor\", \"axes_slice_tensor\"],\n", + " outputs=[\"sliced_indices\"],\n", + " name=\"slice_nms_indices\",\n", + ")\n", + "nodes.append(slice_node)\n", + "\n", + "# Create Squeeze node to squeeze the sliced indices\n", + "squeezed_indices = onnx.helper.make_tensor_value_info(\"squeezed_indices\", onnx.TensorProto.INT64, shape=[\"detections\"])\n", + "outputs.append(squeezed_indices)\n", + "squeeze_slice_tensor = onnx.helper.make_tensor(\"squeeze_slice_axis\",onnx.TensorProto.INT64, [1], np.array([1], dtype=np.int64))\n", + "initializers.append(squeeze_slice_tensor)\n", + "squeeze_slice_node = onnx.helper.make_node(\n", + " \"Squeeze\",\n", + " inputs=[\"sliced_indices\", \"squeeze_slice_axis\"],\n", + " outputs=[\"squeezed_indices\"],\n", + " name=\"squeeze_sliced_indices\",\n", + ")\n", + "nodes.append(squeeze_slice_node)\n", + "\n", + "# Create Squeeze node to squeeze the original output\n", + "squeezed_output = onnx.helper.make_tensor_value_info(\"squeezed_output\", onnx.TensorProto.FLOAT, shape=[25200, 16])\n", + "outputs.append(squeezed_output)\n", + "squeeze_tensor = onnx.helper.make_tensor(\"squeeze_axis\",onnx.TensorProto.INT64, [1], np.array([0], dtype=np.int64))\n", + "initializers.append(squeeze_tensor)\n", + "squeeze_node = onnx.helper.make_node(\n", + " \"Squeeze\",\n", + " inputs=[\"og_output\", \"squeeze_axis\"],\n", + " outputs=[\"squeezed_output\"],\n", + " name=\"squeeze_output\",\n", + ")\n", + "nodes.append(squeeze_node)\n", + "\n", + "\n", + "# Create Gather node to gather the relevant NMS indices from the original output\n", + "postpro_output = onnx.helper.make_tensor_value_info(\"output\", onnx.TensorProto.FLOAT, shape=[\"detections\", 16])\n", + "outputs.append(postpro_output)\n", + "gather_node = onnx.helper.make_node(\n", + " \"Gather\",\n", + " inputs=[\"squeezed_output\", \"squeezed_indices\"],\n", + " outputs=[\"output\"],\n", + " name=\"gather_output\",\n", + ")\n", + "nodes.append(gather_node)\n", + "\n", + "\n", + "# Make the new graph\n", + "graph = onnx.helper.make_graph(\n", + " nodes,\n", + " graph.name,\n", + " list(graph.input), \n", + " [postpro_output],\n", + " initializer=initializers,\n", + " value_info=graph.value_info,\n", + ")\n", + "\n", + "# Create the new model\n", + "onnx_model_prepostpro = onnx.helper.make_model(\n", + " graph,\n", + " opset_imports=[onnx.helper.make_opsetid(\"\", onnx_opset)]\n", + ")\n", + "\n", + "# Save the new model\n", + "onnx.checker.check_model(onnx_model_prepostpro)\n", + "onnx_model_prepostpro_path = onnx_model_export_path[:-5] + \"_prepostpro.onnx\"\n", + "onnx.save(onnx_model_prepostpro, onnx_model_prepostpro_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "# image = Image.open(\"../data/people.jpeg\").convert('RGBA')\n", + "# image_onnx = np.array(image)\n", + "\n", + "# ort_session = ort.InferenceSession(\"yolov5s_face_prepostpro.onnx\")\n", + "# test = ort_session.run(None, {\"input\": image_onnx})\n", + "# test[0].shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Optimize model" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "# define path og model and sim model\n", + "onnx_model_sim_path = onnx_model_export_path[:-5] + f\"_opset{onnx_opset}_rgba_sim.onnx\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Simplify the model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!onnxsim {onnx_model_prepostpro_path} {onnx_model_sim_path}" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "# !onnxsim yolov5s_face_prepostpro.onnx yolov5s_face_opset18_rgba_sim.onnx" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Optimize the graph" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "opt_sess_options = ort.SessionOptions()\n", + "\n", + "opt_sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL\n", + "opt_sess_options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_BASIC\n", + "\n", + "onnx_model_opt_path = onnx_model_export_path[:-5] + f\"_opset{onnx_opset}_rgba_opt.onnx\"\n", + "opt_sess_options.optimized_model_filepath = onnx_model_opt_path\n", + "\n", + "opt_session = ort.InferenceSession(onnx_model_sim_path, opt_sess_options)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add metadata to model\n", + "\n", + "https://onnx.ai/onnx/intro/python.html#opset-and-metadata" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "new_yolo_face_model = onnx.load(onnx_model_opt_path)\n", + "new_yolo_face_model.producer_name = \"EnteYOLOv5Face\"\n", + "new_yolo_face_model.doc_string = \"YOLOv5 Face detector with built-in pre- and post-processing. Accepts both RGB and RGBA raw bytes input (uint8) in HWC format. Outputs the relevant detections in the format (detections, 16) where the first 4 values are the bounding box coordinates, the fifth is the confidence score, and the rest are the landmarks.\"\n", + "new_yolo_face_model.graph.doc_string = \"\"\n", + "new_yolo_face_model.graph.name = \"SliceRGB+Resize+LetterBox+ToFloat+Unsqueeze+YOLOv5Face+NMS+Slice+Gather\"\n", + "onnx.save(new_yolo_face_model, onnx_model_opt_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "!rm {onnx_model_export_path}\n", + "!rm {onnx_model_rgba_path}\n", + "!rm {onnx_model_split_path}\n", + "!rm {onnx_model_nms_path}\n", + "!rm {onnx_model_prepostpro_path}\n", + "!rm {onnx_model_sim_path}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Tune some settings" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "# from tqdm import tqdm\n", + "# import time" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "# image = Image.open(\"../data/people.jpeg\").convert('RGBA')\n", + "# image_onnx = np.array(image)\n", + "# time_test_size = 500\n", + "\n", + "# sess_options1 = ort.SessionOptions()\n", + "# sess_options1.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_EXTENDED\n", + "# # sess_options.enable_profiling = True\n", + "# # sess_options.log_severity_level = 0 # Verbose\n", + "# sess_options1.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL\n", + "# ort_session1 = ort.InferenceSession(onnx_model_opt_path, sess_options1)\n", + "\n", + "# begin_time_1 = time.time()\n", + "# for i in tqdm(range(time_test_size)):\n", + "# _ = ort_session1.run(None, {\"input\": image_onnx})\n", + "# end_time_1 = time.time()\n", + "# time_1 = end_time_1 - begin_time_1\n", + "\n", + "\n", + "# sess_options2 = ort.SessionOptions()\n", + "# sess_options2.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_EXTENDED\n", + "# # sess_options.enable_profiling = True\n", + "# # sess_options.log_severity_level = 0 # Verbose\n", + "# sess_options2.inter_op_num_threads = 4\n", + "# # sess_options2.intra_op_num_threads = 4\n", + "# sess_options2.execution_mode = ort.ExecutionMode.ORT_PARALLEL\n", + "# ort_session2 = ort.InferenceSession(onnx_model_opt_path, sess_options2, providers=[\"CPUExecutionProvider\"])\n", + "\n", + "# begin_time_2 = time.time()\n", + "# for i in tqdm(range(time_test_size)):\n", + "# _ = ort_session2.run(None, {\"input\": image_onnx})\n", + "# end_time_2 = time.time()\n", + "# time_2 = end_time_2 - begin_time_2\n", + "\n", + "# print(f\"Time for first execution: {time_1}\")\n", + "# print(f\"Time for second execution: {time_2}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So lessons:\n", + "1. Use sequential execution\n", + "2. Use extended optimizations\n", + "3. Number of inter op doesn't have significant impact\n", + "4. Number of intra op doesn't have significant impact" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One final test:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image = Image.open(\"../data/man.jpeg\").convert('RGBA')\n", + "imageWidth, imageHeight = image.size\n", + "inputWidth, inputHeight = 640, 640\n", + "print(imageWidth, imageHeight)\n", + "image_onnx = np.array(image)\n", + "\n", + "sess_options1 = ort.SessionOptions()\n", + "sess_options1.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_EXTENDED\n", + "# sess_options.enable_profiling = True\n", + "# sess_options.log_severity_level = 0 # Verbose\n", + "# sess_options1.execution_mode = ort.ExecutionMode.ORT_SEQUENTIAL\n", + "ort_session = ort.InferenceSession(onnx_model_opt_path)\n", + "raw_detection = ort_session.run(None, {\"input\": image_onnx})[0][0]\n", + "print(raw_detection.shape)\n", + "raw_detection" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [], + "source": [ + "from PIL import Image, ImageDraw\n", + "from IPython.display import display\n", + "\n", + "def display_face_detection(image_path, face_box, landmarks):\n", + " # Open the image\n", + " img = Image.open(image_path)\n", + " \n", + " # Create a draw object\n", + " draw = ImageDraw.Draw(img)\n", + " \n", + " # Draw the bounding box\n", + " draw.rectangle(face_box, outline=\"red\", width=2)\n", + " \n", + " # Draw the landmark points\n", + " for point in landmarks:\n", + " x, y = point\n", + " radius = 3\n", + " draw.ellipse([x-radius, y-radius, x+radius, y+radius], fill=\"blue\")\n", + " \n", + " # Display the image\n", + " display(img)" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [], + "source": [ + "def correct_detection_and_display(image_path, raw_detection, imageWidth, imageHeight, inputWidth, inputHeight):\n", + "\n", + " # Create the raw relative bounding box and landmarks\n", + " box = [0, 0, 0, 0]\n", + " box[0] = (raw_detection[0] - raw_detection[2] / 2) / inputWidth\n", + " box[1] = (raw_detection[1] - raw_detection[3] / 2) / inputHeight\n", + " box[2] = (raw_detection[0] + raw_detection[2] / 2) / inputWidth\n", + " box[3] = (raw_detection[1] + raw_detection[3] / 2) / inputHeight\n", + " landmarks = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]\n", + " i = 0\n", + " for x, y in zip(raw_detection[5:15:2], raw_detection[6:15:2]):\n", + " landmarks[i] = (x / inputWidth, y / inputHeight)\n", + " i += 1\n", + "\n", + " # Correct the bounding box and landmarks for letterboxing during preprocessing\n", + " scale = min(inputWidth / imageWidth, inputHeight / imageHeight)\n", + " scaledWidth = round(imageWidth * scale)\n", + " scaledHeight = round(imageHeight * scale)\n", + " print(f\"scaledWidth: {scaledWidth}, scaledHeight: {scaledHeight}\")\n", + "\n", + " halveDiffX = (inputWidth - scaledWidth) / 2\n", + " halveDiffY = (inputHeight - scaledHeight) / 2\n", + " print(f\"halveDiffX: {halveDiffX}, halveDiffY: {halveDiffY}\")\n", + " scaleX = inputHeight / scaledWidth\n", + " scaleY = inputHeight / scaledHeight\n", + " translateX = - halveDiffX / inputWidth\n", + " translateY = - halveDiffY / inputHeight\n", + " print(f\"scaleX: {scaleX}, scaleY: {scaleY}\")\n", + " print(f\"translateX: {translateX}, translateY: {translateY}\")\n", + "\n", + " box[0] = (box[0] + translateX) * scaleX\n", + " box[1] = (box[1] + translateY) * scaleY\n", + " box[2] = (box[2] + translateX) * scaleX\n", + " box[3] = (box[3] + translateY) * scaleY\n", + "\n", + " for i in range(5):\n", + " landmarks[i] = ((landmarks[i][0] + translateX) * scaleX, (landmarks[i][1] + translateY) * scaleY)\n", + "\n", + " # Convert the bounding box and landmarks to absolute values\n", + " box = [box[0] * imageWidth, box[1] * imageHeight, box[2] * imageWidth, box[3] * imageHeight]\n", + " landmarks = [(x * imageWidth, y * imageHeight) for x, y in landmarks]\n", + "\n", + " print(\"Bounding box:\", box)\n", + " print(\"Landmarks:\", landmarks)\n", + "\n", + " display_face_detection(image_path, box, landmarks)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "image_path = \"../data/man.jpeg\"\n", + "# face_box = (50, 10, 100, 100) # (left, top, right, bottom)\n", + "# landmarks = [\n", + "# (30, 30), # Left eye\n", + "# (80, 30), # Right eye\n", + "# (55, 50), # Nose\n", + "# (35, 80), # Left mouth corner\n", + "# (75, 80) # Right mouth corner\n", + "# ]\n", + "\n", + "correct_detection_and_display(image_path, raw_detection, imageWidth, imageHeight, inputWidth, inputHeight)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ente_clip", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/infra/ml/data/man.jpeg b/infra/ml/data/man.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..da6df890d9484940c1ad09835cb86ce64acc6e9c GIT binary patch literal 4120 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 literal 0 HcmV?d00001 diff --git a/infra/ml/data/singapore.jpg b/infra/ml/data/singapore.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f0ac5d83e7ef572c7663dc66e6cf82decb367d40 GIT binary patch literal 613520 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
a=Dzc| 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

  • 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%0AJUqnVX~dTg6uX4z`C@(`M9sQ|C_C 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%0DEA{-3G_9Fs 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