diff --git a/.github/workflows/auth-release.yml b/.github/workflows/auth-release.yml index 4bb31e85e1..65361fb064 100644 --- a/.github/workflows/auth-release.yml +++ b/.github/workflows/auth-release.yml @@ -90,13 +90,14 @@ jobs: - name: Install dependencies for desktop build run: | sudo apt-get update -y - sudo apt-get install -y libsecret-1-dev libsodium-dev libwebkit2gtk-4.0-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config libsqlite3-dev locate appindicator3-0.1 libappindicator3-dev libffi-dev libtiff5 + sudo apt-get install -y libsecret-1-dev libsodium-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config libsqlite3-dev locate appindicator3-0.1 libappindicator3-dev libffi-dev libtiff5 sudo updatedb --localpaths='/usr/lib/x86_64-linux-gnu' - name: Build desktop app run: | flutter config --enable-linux-desktop - dart pub global activate flutter_distributor + # dart pub global activate flutter_distributor + dart pub global activate --source git https://github.com/prateekmedia/flutter_distributor --git-ref develop --git-path packages/flutter_distributor flutter_distributor package --platform=linux --targets=deb --skip-clean mv dist/**/*-*-linux.deb artifacts/ente-${{ github.ref_name }}-x86_64.deb env: @@ -104,7 +105,7 @@ jobs: - name: Generate checksums and push to artifacts run: | - sha256sum artifacts/ente-* > artifacts/sha256sum-apk-deb + sha256sum artifacts/ente-* > artifacts/sha256sum-apk-deb - name: Create a draft GitHub release uses: ncipollo/release-action@v1 @@ -125,65 +126,65 @@ jobs: track: internal build-fedora-etc: - runs-on: ubuntu-latest + runs-on: ubuntu-latest - defaults: - run: - working-directory: auth + defaults: + run: + working-directory: auth - steps: - - name: Checkout code and submodules - uses: actions/checkout@v4 - with: - submodules: recursive + steps: + - name: Checkout code and submodules + uses: actions/checkout@v4 + with: + submodules: recursive - - name: Install Flutter ${{ env.FLUTTER_VERSION }} - uses: subosito/flutter-action@v2 - with: - channel: "stable" - flutter-version: ${{ env.FLUTTER_VERSION }} - cache: true + - name: Install Flutter ${{ env.FLUTTER_VERSION }} + uses: subosito/flutter-action@v2 + with: + channel: "stable" + flutter-version: ${{ env.FLUTTER_VERSION }} + cache: true - - name: Create artifacts directory - run: mkdir artifacts + - name: Create artifacts directory + run: mkdir artifacts - - name: Install dependencies for desktop build - run: | - sudo apt-get update -y - sudo apt-get install -y libsecret-1-dev libsodium-dev libwebkit2gtk-4.0-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config rpm patchelf libsqlite3-dev locate libayatana-appindicator3-dev libffi-dev libtiff5 xz-utils libarchive-tools - sudo updatedb --localpaths='/usr/lib/x86_64-linux-gnu' + - name: Install dependencies for desktop build + run: | + sudo apt-get update -y + sudo apt-get install -y libsecret-1-dev libsodium-dev libfuse2 ninja-build libgtk-3-dev dpkg-dev pkg-config rpm patchelf libsqlite3-dev locate libayatana-appindicator3-dev libffi-dev libtiff5 xz-utils libarchive-tools + sudo updatedb --localpaths='/usr/lib/x86_64-linux-gnu' - - name: Install appimagetool - run: | - wget -O appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" - chmod +x appimagetool - mv appimagetool /usr/local/bin/ + - name: Install appimagetool + run: | + wget -O appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" + chmod +x appimagetool + mv appimagetool /usr/local/bin/ - - name: Build desktop app - run: | - flutter config --enable-linux-desktop - # dart pub global activate flutter_distributor - dart pub global activate --source git https://github.com/prateekmedia/flutter_distributor --git-ref pacman --git-path packages/flutter_distributor - # Run below command if it is a beta or nightly - if [[ ${{ github.ref }} =~ beta|nightly ]]; then - flutter_distributor package --platform=linux --targets=pacman --skip-clean - mv dist/**/*-*-linux.pacman artifacts/ente-${{ github.ref_name }}-x86_64.pacman - fi - flutter_distributor package --platform=linux --targets=rpm --skip-clean - mv dist/**/*-*-linux.rpm artifacts/ente-${{ github.ref_name }}-x86_64.rpm - flutter_distributor package --platform=linux --targets=appimage --skip-clean - mv dist/**/*-*-linux.AppImage artifacts/ente-${{ github.ref_name }}-x86_64.AppImage + - name: Build desktop app + run: | + flutter config --enable-linux-desktop + # dart pub global activate flutter_distributor + dart pub global activate --source git https://github.com/prateekmedia/flutter_distributor --git-ref develop --git-path packages/flutter_distributor + # Run below command if it is a beta or nightly + if [[ ${{ github.ref }} =~ beta|nightly ]]; then + flutter_distributor package --platform=linux --targets=pacman --skip-clean + mv dist/**/*-*-linux.pacman artifacts/ente-${{ github.ref_name }}-x86_64.pacman + fi + flutter_distributor package --platform=linux --targets=rpm --skip-clean + mv dist/**/*-*-linux.rpm artifacts/ente-${{ github.ref_name }}-x86_64.rpm + flutter_distributor package --platform=linux --targets=appimage --skip-clean + mv dist/**/*-*-linux.AppImage artifacts/ente-${{ github.ref_name }}-x86_64.AppImage - - name: Generate checksums - run: sha256sum artifacts/ente-* >> artifacts/sha256sum-rpm-appimage + - name: Generate checksums + run: sha256sum artifacts/ente-* >> artifacts/sha256sum-rpm-appimage - - name: Create a draft GitHub release - uses: ncipollo/release-action@v1 - with: - artifacts: "auth/artifacts/*" - draft: true - allowUpdates: true - updateOnlyUnreleased: true + - name: Create a draft GitHub release + uses: ncipollo/release-action@v1 + with: + artifacts: "auth/artifacts/*" + draft: true + allowUpdates: true + updateOnlyUnreleased: true build-windows: runs-on: windows-latest @@ -211,10 +212,11 @@ jobs: - name: Build Windows installer run: | flutter config --enable-windows-desktop - dart pub global activate flutter_distributor + # dart pub global activate flutter_distributor + dart pub global activate --source git https://github.com/prateekmedia/flutter_distributor --git-ref develop --git-path packages/flutter_distributor make innoinstall flutter_distributor package --platform=windows --targets=exe --skip-clean - mv dist/**/ente_auth-*-windows-setup.exe artifacts/ente-${{ github.ref_name }}-installer.exe + mv dist/**/*-windows-setup.exe artifacts/ente-${{ github.ref_name }}-installer.exe - name: Retain Windows EXE and DLLs run: cp -r build/windows/x64/runner/Release ente-${{ github.ref_name }}-windows @@ -307,7 +309,7 @@ jobs: flutter config --enable-macos-desktop dart pub global activate flutter_distributor flutter_distributor package --platform=macos --targets=dmg --skip-clean - mv dist/**/ente_auth-*-macos.dmg artifacts/ente-${{ github.ref_name }}.dmg + mv dist/**/*-macos.dmg artifacts/ente-${{ github.ref_name }}.dmg - name: Code sign DMG run: | diff --git a/auth/assets/custom-icons/_data/custom-icons.json b/auth/assets/custom-icons/_data/custom-icons.json index d1cacf8271..dfcffe31bb 100644 --- a/auth/assets/custom-icons/_data/custom-icons.json +++ b/auth/assets/custom-icons/_data/custom-icons.json @@ -20,6 +20,9 @@ "title": "airtm", "hex": "000000" }, + { + "title": "Aiven" + }, { "title": "aliyun", "altNames": [ @@ -29,13 +32,22 @@ { "title": "Amazon" }, + { + "title": "Amazon Web Services" + }, { "title": "Anycoin Direct", "slug": "anycoindirect" }, + { + "title": "Appwrite" + }, { "title": "AscendEX" }, + { + "title": "Aternos" + }, { "title": "BaiduCloud", "altNames": [ @@ -73,6 +85,10 @@ "币安" ] }, + { + "title": "Binance TR", + "slug": "binance_tr" + }, { "title": "BinanceUS", "slug": "binance_us", @@ -113,11 +129,13 @@ "title": "Bitwarden" }, { - "title": "Bloom Host", - "slug": "bloom_host", - "altNames": [ - "Bloom Host Billing" - ] + "title": "Black Desert" + }, + { + "title": "Blackbaud" + }, + { + "title": "Blizzard" }, { "title": "Blockchain", @@ -128,17 +146,30 @@ ] }, { - "title": "BorgBase", + "title": "Bloom Host", + "slug": "bloom_host", "altNames": [ - "borg" + "Bloom Host Billing" ] }, + { + "title": "Bohemia" + }, { "title": "Booking", "altNames": [ "Booking.com" ] }, + { + "title": "BorgBase", + "altNames": [ + "borg" + ] + }, + { + "title": "Box" + }, { "title": "Brave Creators", "slug": "brave_creators", @@ -148,6 +179,9 @@ "Brave Browser" ] }, + { + "title": "Broadcom" + }, { "title": "Bybit" }, @@ -157,6 +191,15 @@ { "title": "Capacities" }, + { + "title": "Capcom" + }, + { + "title": "Carta", + "altNames": [ + "Carta.com" + ] + }, { "title": "CERN" }, @@ -168,12 +211,21 @@ "slug": "cih", "hex": "D14633" }, + { + "title": "Cloud66" + }, { "title": "CloudAMQP" }, + { + "title": "ClouDNS" + }, { "title": "Cloudflare" }, + { + "title": "Cloudhq" + }, { "title": "Coinbase" }, @@ -198,6 +250,9 @@ "Crypto com" ] }, + { + "title": "CSFloat" + }, { "title": "DCS", "altNames": [ @@ -210,6 +265,16 @@ { "title": "deriv" }, + { + "title": "DigiFinex", + "altNames": [ + "Digi Finex", + "Digifinex.com" + ] + }, + { + "title": "Digital Ocean" + }, { "title": "DirectAdmin" }, @@ -222,10 +287,16 @@ { "title": "Doppler" }, + { + "title": "Dropbox" + }, { "title": "dus.net", "slug": "dusnet" }, + { + "title": "EA" + }, { "title": "eBay" }, @@ -240,23 +311,53 @@ ] }, { - "title": "ente", - "hex": "1DB954" + "title": "Elastic Cloud" + }, + { + "title": "Eneba" + }, + { + "title": "Engine Yard" }, { "title": "enom" }, + { + "title": "ente", + "hex": "1DB954" + }, { "title": "Epic Games", "slug": "epic_games", "hex": "000000" }, + { + "title": "Equinix Metal" + }, + { + "title": "Erai-raws" + }, { "title": "Esketit" }, + { + "title": "ESL Gaming" + }, { "title": "Estateguru" }, + { + "title": "Eve Online" + }, + { + "title": "Evernote" + }, + { + "title": "Faceit" + }, + { + "title": "Fanatical" + }, { "title": "Filen" }, @@ -264,6 +365,9 @@ "title": "Firefox", "slug": "mozilla" }, + { + "title": "Fly.io" + }, { "title": "ForUsAll" }, @@ -282,6 +386,12 @@ { "title": "Google" }, + { + "title": "Google Cloud Platform" + }, + { + "title": "Google Drive" + }, { "title": "Gosuslugi", "slug": "Gosuslugi", @@ -296,31 +406,55 @@ "Government Gateway" ] }, + { + "title": "Gree" + }, { "title": "Guideline" }, + { + "title": "Guildwars2" + }, { "title": "Gusto" }, { "title": "Habbo" }, + { + "title": "HashiCorp Cloud Platform" + }, { "title": "Healthchecks.io", "slug": "healthchecks" }, + { + "title": "Heroku" + }, + { + "title": "Hetzner" + }, { "title": "Hivelocity" }, { "title": "HTX" }, + { + "title": "Huawei Cloud" + }, { "title": "HuggingFace", "altNames": [ "Hugging Face" ] }, + { + "title": "Humble Bundle" + }, + { + "title": "IBM Cloud" + }, { "title": "IceDrive" }, @@ -328,18 +462,25 @@ "title": "ID.me", "slug": "IDme" }, + { + "title": "Idrive" + }, { "title": "Infomaniak" }, + { + "title": "Impact.com", + "slug": "impact" + }, { "title": "ING" }, { - "title": "Instant Gaming", - "slug": "instant_gaming" + "title": "Instagram" }, { - "title": "Instagram" + "title": "Instant Gaming", + "slug": "instant_gaming" }, { "title": "INWX" @@ -362,14 +503,40 @@ "坚果云" ] }, + { + "title": "Jottacloud" + }, + { + "title": "Joyent" + }, { "title": "Kagi" }, + { + "title": "KeyCDN" + }, { "title": "Kick" }, + { + "title": "Kinguin" + }, { "title": "Kite" + }, + { + "title": "KnownHost", + "altNames": [ + "Known Host", + "KnownHost.com" + ] + }, + { + "title": "Ko-fi", + "altNames": [ + "Ko fi", + "Kofi" + ] }, { "title": "Koofr" @@ -391,15 +558,27 @@ "title": "La Poste", "slug": "laposte" }, + { + "title": "Laravel Forge" + }, { "title": "Lark", "altNames": [ "飞书" ] }, + { + "title": "Leaseweb" + }, { "title": "Letterboxd" }, + { + "title": "Lichess" + }, + { + "title": "Linode" + }, { "title": "Linux.Do", "slug": "LINUX_DO", @@ -421,6 +600,9 @@ "title": "Login.gov", "slug": "login_gov" }, + { + "title": "MacStadium" + }, { "title": "Marketplace.tf", "slug": "marketplacedottf" @@ -447,9 +629,15 @@ { "title": "Microsoft" }, + { + "title": "Microsoft Azure" + }, { "title": "Migros" }, + { + "title": "Minecraft" + }, { "title": "Mintos" }, @@ -460,6 +648,9 @@ "MistralAI" ] }, + { + "title": "Modrinth" + }, { "title": "Mozilla" }, @@ -491,6 +682,12 @@ "FritzBox 7583" ] }, + { + "title": "Myprimobox" + }, + { + "title": "N-able" + }, { "title": "Name.com", "slug": "name_com" @@ -503,7 +700,7 @@ ] }, { - "title": "NextDNS" + "title": "Netlify" }, { "title": "Newton", @@ -511,6 +708,15 @@ "Newton Crypto" ] }, + { + "title": "Nexon" + }, + { + "title": "NextDNS" + }, + { + "title": "Nexusmods" + }, { "title": "ngrok", "hex": "858585" @@ -524,6 +730,9 @@ { "title": "Njalla" }, + { + "title": "Nordlocker" + }, { "title": "Notesnook" }, @@ -536,9 +745,25 @@ { "title": "NVIDIA" }, + { + "title": "Obsidian" + }, { "title": "Odido" }, + { + "title": "okx", + "hex": "000000", + "altNames": [ + "欧易" + ] + }, + { + "title": "Onedrive" + }, + { + "title": "Onehub" + }, { "title": "OpenObserve", "slug": "open_observe", @@ -548,11 +773,7 @@ ] }, { - "title": "okx", - "hex": "000000", - "altNames": [ - "欧易" - ] + "title": "Oracle Cloud Infrastructure" }, { "title": "Parsec" @@ -568,16 +789,31 @@ { "title": "pCloud" }, + { + "title": "PebbleHost", + "altNames": [ + "Pebble Host" + ] + }, { "title": "Peerberry" }, { "title": "Pingvin Share" }, + { + "title": "PlayerAuctions" + }, + { + "title": "Playstation" + }, { "title": "Plutus", "hex": "DEC685" }, + { + "title": "Poli Systems" + }, { "title": "Poloniex" }, @@ -601,6 +837,15 @@ { "title": "Proxmox" }, + { + "title": "PSN Profiles" + }, + { + "title": "Put.io" + }, + { + "title": "Puter" + }, { "title": "qiniuyun", "altNames": [ @@ -608,6 +853,18 @@ "qiniu" ] }, + { + "title": "QNAP" + }, + { + "title": "Railway" + }, + { + "title": "Rapidgator" + }, + { + "title": "Razer" + }, { "title": "Real-Debrid", "slug": "real_debrid" @@ -625,15 +882,27 @@ ] }, { - "title": "Render" + "title": "Restorecord" + }, + { + "title": "Restream", + "altNames": [ + "restream.io" + ] }, { "title": "Revolt", "hex": "858585" }, + { + "title": "Rewind" + }, { "title": "RippleMatch" }, + { + "title": "Roblox" + }, { "title": "Rockstar Games", "slug": "rockstar_games" @@ -649,15 +918,33 @@ { "title": "Samsung" }, + { + "title": "ScaleGrid" + }, + { + "title": "Scaleway" + }, + { + "title": "Scalr" + }, { "title": "Sendgrid" }, + { + "title": "Serverspace" + }, { "title": "service-bw" }, + { + "title": "Shadow" + }, { "title": "Shakepay" }, + { + "title": "Side Quest" + }, { "title": "SimpleLogin" }, @@ -692,6 +979,9 @@ { "title": "Snapchat" }, + { + "title": "Square Enix" + }, { "title": "Standard Notes", "slug": "standardnotes" @@ -699,6 +989,12 @@ { "title": "Surfshark" }, + { + "title": "Sync" + }, + { + "title": "Synology" + }, { "title": "Synology DSM", "slug": "synology_dsm" @@ -714,12 +1010,7 @@ "title": "TCPShield" }, { - "title": "tencent cloud", - "slug": "tencent_cloud", - "altNames": [ - "腾讯云", - "tencentcloud" - ] + "title": "Teamviewer" }, { "title": "Techlore", @@ -728,6 +1019,9 @@ "Techlore Forums" ] }, + { + "title": "Technic" + }, { "title": "Teleport", "altNames": [ @@ -736,11 +1030,23 @@ ] }, { - "title": "Termius", - "hex": "858585" + "title": "tencent cloud", + "slug": "tencent_cloud", + "altNames": [ + "腾讯云", + "tencentcloud" + ] }, { - "title": "Titan" + "title": "Terabit", + "altNames": [ + "Terabit Hosting", + "terabit.io" + ] + }, + { + "title": "Termius", + "hex": "858585" }, { "title": "tianyiyun", @@ -748,6 +1054,12 @@ "天翼云" ] }, + { + "title": "Tilaa" + }, + { + "title": "Titan" + }, { "title": "TorGuard" }, @@ -762,6 +1074,15 @@ }, { "title": "Tresorit" + }, + { + "title": "TRowePrice", + "altNames": [ + "T Rowe Price", + "TRowe Price", + "T Rowe Price Group", + "T Rowe Price Group, Inc" + ] }, { "title": "Tweakers" @@ -777,6 +1098,15 @@ "Twitch tv" ] }, + { + "title": "Ubiquiti", + "slug": "ubiquiti", + "altNames": [ + "Unifi SSO", + "Unifi", + "Ubiquiti SSO" + ] + }, { "title": "Ubisoft" }, @@ -788,6 +1118,9 @@ "title": "Unity", "hex": "858585" }, + { + "title": "Updraftplus" + }, { "title": "Uphold" }, @@ -804,7 +1137,19 @@ ] }, { - "title": "WARGAMING.NET" + "title": "WARGAMING.NET", + "altNames": [ + "Wargaming" + ] + }, + { + "title": "VRChat" + }, + { + "title": "Vultr" + }, + { + "title": "Warner Bros Games" }, { "title": "Wealthfront" @@ -812,6 +1157,9 @@ { "title": "Wealthsimple" }, + { + "title": "Wetransfer" + }, { "title": "WHMCS" }, @@ -831,6 +1179,9 @@ { "title": "WYZE" }, + { + "title": "Xbox" + }, { "title": "yahoo" }, diff --git a/auth/assets/custom-icons/icons/Aiven.svg b/auth/assets/custom-icons/icons/Aiven.svg new file mode 100644 index 0000000000..a04e49afe1 --- /dev/null +++ b/auth/assets/custom-icons/icons/Aiven.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Amazon Web Services.svg b/auth/assets/custom-icons/icons/Amazon Web Services.svg new file mode 100644 index 0000000000..03c912db39 --- /dev/null +++ b/auth/assets/custom-icons/icons/Amazon Web Services.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Appwrite.svg b/auth/assets/custom-icons/icons/Appwrite.svg new file mode 100644 index 0000000000..98bffa5011 --- /dev/null +++ b/auth/assets/custom-icons/icons/Appwrite.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Aternos.svg b/auth/assets/custom-icons/icons/Aternos.svg new file mode 100644 index 0000000000..9e0decb1cd --- /dev/null +++ b/auth/assets/custom-icons/icons/Aternos.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/auth/assets/custom-icons/icons/Black Desert.svg b/auth/assets/custom-icons/icons/Black Desert.svg new file mode 100644 index 0000000000..a0659e8278 --- /dev/null +++ b/auth/assets/custom-icons/icons/Black Desert.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Blackbaud.svg b/auth/assets/custom-icons/icons/Blackbaud.svg new file mode 100644 index 0000000000..67d3dd8557 --- /dev/null +++ b/auth/assets/custom-icons/icons/Blackbaud.svg @@ -0,0 +1,43 @@ + + + + diff --git a/auth/assets/custom-icons/icons/Blizzard.svg b/auth/assets/custom-icons/icons/Blizzard.svg new file mode 100644 index 0000000000..cc454d6776 --- /dev/null +++ b/auth/assets/custom-icons/icons/Blizzard.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Bohemia.svg b/auth/assets/custom-icons/icons/Bohemia.svg new file mode 100644 index 0000000000..f9047dfdf3 --- /dev/null +++ b/auth/assets/custom-icons/icons/Bohemia.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Box.svg b/auth/assets/custom-icons/icons/Box.svg new file mode 100644 index 0000000000..acfaaa1866 --- /dev/null +++ b/auth/assets/custom-icons/icons/Box.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Broadcom.svg b/auth/assets/custom-icons/icons/Broadcom.svg new file mode 100644 index 0000000000..b957092c0b --- /dev/null +++ b/auth/assets/custom-icons/icons/Broadcom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Capcom.svg b/auth/assets/custom-icons/icons/Capcom.svg new file mode 100644 index 0000000000..df1117281d --- /dev/null +++ b/auth/assets/custom-icons/icons/Capcom.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Cloud66.svg b/auth/assets/custom-icons/icons/Cloud66.svg new file mode 100644 index 0000000000..b006121811 --- /dev/null +++ b/auth/assets/custom-icons/icons/Cloud66.svg @@ -0,0 +1,44 @@ + + + + diff --git a/auth/assets/custom-icons/icons/Cloudhq.svg b/auth/assets/custom-icons/icons/Cloudhq.svg new file mode 100644 index 0000000000..0a4ea4d8e6 --- /dev/null +++ b/auth/assets/custom-icons/icons/Cloudhq.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Digital Ocean.svg b/auth/assets/custom-icons/icons/Digital Ocean.svg new file mode 100644 index 0000000000..4f4fc25ac7 --- /dev/null +++ b/auth/assets/custom-icons/icons/Digital Ocean.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Dropbox.svg b/auth/assets/custom-icons/icons/Dropbox.svg new file mode 100644 index 0000000000..80fb667116 --- /dev/null +++ b/auth/assets/custom-icons/icons/Dropbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/EA.svg b/auth/assets/custom-icons/icons/EA.svg new file mode 100644 index 0000000000..9eb88938d9 --- /dev/null +++ b/auth/assets/custom-icons/icons/EA.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/auth/assets/custom-icons/icons/ESL Gaming.svg b/auth/assets/custom-icons/icons/ESL Gaming.svg new file mode 100644 index 0000000000..e5fbc5f9f5 --- /dev/null +++ b/auth/assets/custom-icons/icons/ESL Gaming.svg @@ -0,0 +1 @@ +ESLGaming icon diff --git a/auth/assets/custom-icons/icons/Elastic Cloud.svg b/auth/assets/custom-icons/icons/Elastic Cloud.svg new file mode 100644 index 0000000000..8994145a3b --- /dev/null +++ b/auth/assets/custom-icons/icons/Elastic Cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Eneba.svg b/auth/assets/custom-icons/icons/Eneba.svg new file mode 100644 index 0000000000..109a2558cf --- /dev/null +++ b/auth/assets/custom-icons/icons/Eneba.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Engine Yard.svg b/auth/assets/custom-icons/icons/Engine Yard.svg new file mode 100644 index 0000000000..ba3c3ff4f8 --- /dev/null +++ b/auth/assets/custom-icons/icons/Engine Yard.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Equinix Metal.svg b/auth/assets/custom-icons/icons/Equinix Metal.svg new file mode 100644 index 0000000000..2674b8efae --- /dev/null +++ b/auth/assets/custom-icons/icons/Equinix Metal.svg @@ -0,0 +1,43 @@ + + + + diff --git a/auth/assets/custom-icons/icons/Erai-raws.svg b/auth/assets/custom-icons/icons/Erai-raws.svg new file mode 100644 index 0000000000..44b1536b68 --- /dev/null +++ b/auth/assets/custom-icons/icons/Erai-raws.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Eve Online.svg b/auth/assets/custom-icons/icons/Eve Online.svg new file mode 100644 index 0000000000..ec5306dafd --- /dev/null +++ b/auth/assets/custom-icons/icons/Eve Online.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Evernote.svg b/auth/assets/custom-icons/icons/Evernote.svg new file mode 100644 index 0000000000..f7bc7f4ed4 --- /dev/null +++ b/auth/assets/custom-icons/icons/Evernote.svg @@ -0,0 +1 @@ +Evernote-colorCreated with Sketch. diff --git a/auth/assets/custom-icons/icons/Faceit.svg b/auth/assets/custom-icons/icons/Faceit.svg new file mode 100644 index 0000000000..316ef2c91a --- /dev/null +++ b/auth/assets/custom-icons/icons/Faceit.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/auth/assets/custom-icons/icons/Fanatical.svg b/auth/assets/custom-icons/icons/Fanatical.svg new file mode 100644 index 0000000000..cfcff35bb8 --- /dev/null +++ b/auth/assets/custom-icons/icons/Fanatical.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Fly.io.svg b/auth/assets/custom-icons/icons/Fly.io.svg new file mode 100644 index 0000000000..4fb92ab2de --- /dev/null +++ b/auth/assets/custom-icons/icons/Fly.io.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Google Cloud Platform.svg b/auth/assets/custom-icons/icons/Google Cloud Platform.svg new file mode 100644 index 0000000000..2516a83b37 --- /dev/null +++ b/auth/assets/custom-icons/icons/Google Cloud Platform.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Google Drive.svg b/auth/assets/custom-icons/icons/Google Drive.svg new file mode 100644 index 0000000000..2748e3ef6f --- /dev/null +++ b/auth/assets/custom-icons/icons/Google Drive.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/auth/assets/custom-icons/icons/Gree.svg b/auth/assets/custom-icons/icons/Gree.svg new file mode 100644 index 0000000000..106bfe16ca --- /dev/null +++ b/auth/assets/custom-icons/icons/Gree.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Guildwars2.svg b/auth/assets/custom-icons/icons/Guildwars2.svg new file mode 100644 index 0000000000..810f10d8b8 --- /dev/null +++ b/auth/assets/custom-icons/icons/Guildwars2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/HashiCorp Cloud Platform.svg b/auth/assets/custom-icons/icons/HashiCorp Cloud Platform.svg new file mode 100644 index 0000000000..2de83aa625 --- /dev/null +++ b/auth/assets/custom-icons/icons/HashiCorp Cloud Platform.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Heroku.svg b/auth/assets/custom-icons/icons/Heroku.svg new file mode 100644 index 0000000000..485e4879a7 --- /dev/null +++ b/auth/assets/custom-icons/icons/Heroku.svg @@ -0,0 +1,6 @@ + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Hetzner.svg b/auth/assets/custom-icons/icons/Hetzner.svg new file mode 100644 index 0000000000..3729640e36 --- /dev/null +++ b/auth/assets/custom-icons/icons/Hetzner.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Huawei Cloud.svg b/auth/assets/custom-icons/icons/Huawei Cloud.svg new file mode 100644 index 0000000000..b3007b4b71 --- /dev/null +++ b/auth/assets/custom-icons/icons/Huawei Cloud.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Humble Bundle.svg b/auth/assets/custom-icons/icons/Humble Bundle.svg new file mode 100644 index 0000000000..110dc2d2da --- /dev/null +++ b/auth/assets/custom-icons/icons/Humble Bundle.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/auth/assets/custom-icons/icons/IBM Cloud.svg b/auth/assets/custom-icons/icons/IBM Cloud.svg new file mode 100644 index 0000000000..15d748d49e --- /dev/null +++ b/auth/assets/custom-icons/icons/IBM Cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Idrive.svg b/auth/assets/custom-icons/icons/Idrive.svg new file mode 100644 index 0000000000..ed72acffe0 --- /dev/null +++ b/auth/assets/custom-icons/icons/Idrive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Jottacloud.svg b/auth/assets/custom-icons/icons/Jottacloud.svg new file mode 100644 index 0000000000..cacad44c46 --- /dev/null +++ b/auth/assets/custom-icons/icons/Jottacloud.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Joyent.svg b/auth/assets/custom-icons/icons/Joyent.svg new file mode 100644 index 0000000000..c27260a6a3 --- /dev/null +++ b/auth/assets/custom-icons/icons/Joyent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/KeyCDN.svg b/auth/assets/custom-icons/icons/KeyCDN.svg new file mode 100644 index 0000000000..e15d348834 --- /dev/null +++ b/auth/assets/custom-icons/icons/KeyCDN.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Kinguin.svg b/auth/assets/custom-icons/icons/Kinguin.svg new file mode 100644 index 0000000000..94ec1f5178 --- /dev/null +++ b/auth/assets/custom-icons/icons/Kinguin.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Ko-fi.svg b/auth/assets/custom-icons/icons/Ko-fi.svg new file mode 100644 index 0000000000..6a9ebf0e65 --- /dev/null +++ b/auth/assets/custom-icons/icons/Ko-fi.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/auth/assets/custom-icons/icons/Laravel Forge.svg b/auth/assets/custom-icons/icons/Laravel Forge.svg new file mode 100644 index 0000000000..00a2e3b2ab --- /dev/null +++ b/auth/assets/custom-icons/icons/Laravel Forge.svg @@ -0,0 +1,43 @@ + + + + diff --git a/auth/assets/custom-icons/icons/Leaseweb.svg b/auth/assets/custom-icons/icons/Leaseweb.svg new file mode 100644 index 0000000000..302a040787 --- /dev/null +++ b/auth/assets/custom-icons/icons/Leaseweb.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Lichess.svg b/auth/assets/custom-icons/icons/Lichess.svg new file mode 100644 index 0000000000..1597ea06a3 --- /dev/null +++ b/auth/assets/custom-icons/icons/Lichess.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Linode.svg b/auth/assets/custom-icons/icons/Linode.svg new file mode 100644 index 0000000000..bacf830273 --- /dev/null +++ b/auth/assets/custom-icons/icons/Linode.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/MacStadium.svg b/auth/assets/custom-icons/icons/MacStadium.svg new file mode 100644 index 0000000000..02cf61ad00 --- /dev/null +++ b/auth/assets/custom-icons/icons/MacStadium.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Microsoft Azure.svg b/auth/assets/custom-icons/icons/Microsoft Azure.svg new file mode 100644 index 0000000000..43928680b9 --- /dev/null +++ b/auth/assets/custom-icons/icons/Microsoft Azure.svg @@ -0,0 +1,29 @@ + + + + + + + Miscellaneous + + + microsoft-azure + + + Microsoft Azure + + + image/svg+xml + + + Amido Limited + + + Richard Slater + + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Minecraft.svg b/auth/assets/custom-icons/icons/Minecraft.svg new file mode 100644 index 0000000000..8435ae985d --- /dev/null +++ b/auth/assets/custom-icons/icons/Minecraft.svg @@ -0,0 +1 @@ +image/svg+xml diff --git a/auth/assets/custom-icons/icons/Modrinth.svg b/auth/assets/custom-icons/icons/Modrinth.svg new file mode 100644 index 0000000000..fabdf608ad --- /dev/null +++ b/auth/assets/custom-icons/icons/Modrinth.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Myprimobox.svg b/auth/assets/custom-icons/icons/Myprimobox.svg new file mode 100644 index 0000000000..2b0df1e198 --- /dev/null +++ b/auth/assets/custom-icons/icons/Myprimobox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/N-able.svg b/auth/assets/custom-icons/icons/N-able.svg new file mode 100644 index 0000000000..162b8b5698 --- /dev/null +++ b/auth/assets/custom-icons/icons/N-able.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Netlify.svg b/auth/assets/custom-icons/icons/Netlify.svg new file mode 100644 index 0000000000..a619161231 --- /dev/null +++ b/auth/assets/custom-icons/icons/Netlify.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Nexon.svg b/auth/assets/custom-icons/icons/Nexon.svg new file mode 100644 index 0000000000..623ea66c27 --- /dev/null +++ b/auth/assets/custom-icons/icons/Nexon.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Nexusmods.svg b/auth/assets/custom-icons/icons/Nexusmods.svg new file mode 100644 index 0000000000..cbf5a43432 --- /dev/null +++ b/auth/assets/custom-icons/icons/Nexusmods.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Nordlocker.svg b/auth/assets/custom-icons/icons/Nordlocker.svg new file mode 100644 index 0000000000..8878e3fcda --- /dev/null +++ b/auth/assets/custom-icons/icons/Nordlocker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Obsidian.svg b/auth/assets/custom-icons/icons/Obsidian.svg new file mode 100644 index 0000000000..273588fb73 --- /dev/null +++ b/auth/assets/custom-icons/icons/Obsidian.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Onedrive.svg b/auth/assets/custom-icons/icons/Onedrive.svg new file mode 100644 index 0000000000..3c820c4f94 --- /dev/null +++ b/auth/assets/custom-icons/icons/Onedrive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Onehub.svg b/auth/assets/custom-icons/icons/Onehub.svg new file mode 100644 index 0000000000..922cd3d9a0 --- /dev/null +++ b/auth/assets/custom-icons/icons/Onehub.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Oracle Cloud Infrastructure.svg b/auth/assets/custom-icons/icons/Oracle Cloud Infrastructure.svg new file mode 100644 index 0000000000..7b0e1a3ea5 --- /dev/null +++ b/auth/assets/custom-icons/icons/Oracle Cloud Infrastructure.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/PSN Profiles.svg b/auth/assets/custom-icons/icons/PSN Profiles.svg new file mode 100644 index 0000000000..1d2453ee72 --- /dev/null +++ b/auth/assets/custom-icons/icons/PSN Profiles.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/PebbleHost.svg b/auth/assets/custom-icons/icons/PebbleHost.svg new file mode 100644 index 0000000000..2e67ae8c70 --- /dev/null +++ b/auth/assets/custom-icons/icons/PebbleHost.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/auth/assets/custom-icons/icons/PlayerAuctions.svg b/auth/assets/custom-icons/icons/PlayerAuctions.svg new file mode 100644 index 0000000000..396a44e8da --- /dev/null +++ b/auth/assets/custom-icons/icons/PlayerAuctions.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Playstation.svg b/auth/assets/custom-icons/icons/Playstation.svg new file mode 100644 index 0000000000..34dda9068d --- /dev/null +++ b/auth/assets/custom-icons/icons/Playstation.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Poli Systems.svg b/auth/assets/custom-icons/icons/Poli Systems.svg new file mode 100644 index 0000000000..e6104e33d5 --- /dev/null +++ b/auth/assets/custom-icons/icons/Poli Systems.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Put.io.svg b/auth/assets/custom-icons/icons/Put.io.svg new file mode 100644 index 0000000000..116608fd18 --- /dev/null +++ b/auth/assets/custom-icons/icons/Put.io.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Puter.svg b/auth/assets/custom-icons/icons/Puter.svg new file mode 100644 index 0000000000..79b76d19d1 --- /dev/null +++ b/auth/assets/custom-icons/icons/Puter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/QNAP.svg b/auth/assets/custom-icons/icons/QNAP.svg new file mode 100644 index 0000000000..daf51717e2 --- /dev/null +++ b/auth/assets/custom-icons/icons/QNAP.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Railway.svg b/auth/assets/custom-icons/icons/Railway.svg new file mode 100644 index 0000000000..619ce5071f --- /dev/null +++ b/auth/assets/custom-icons/icons/Railway.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Rapidgator.svg b/auth/assets/custom-icons/icons/Rapidgator.svg new file mode 100644 index 0000000000..03cd6183ff --- /dev/null +++ b/auth/assets/custom-icons/icons/Rapidgator.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Razer.svg b/auth/assets/custom-icons/icons/Razer.svg new file mode 100644 index 0000000000..3b8d6fc440 --- /dev/null +++ b/auth/assets/custom-icons/icons/Razer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Restorecord.svg b/auth/assets/custom-icons/icons/Restorecord.svg new file mode 100644 index 0000000000..1d1894e95b --- /dev/null +++ b/auth/assets/custom-icons/icons/Restorecord.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Restream.svg b/auth/assets/custom-icons/icons/Restream.svg new file mode 100644 index 0000000000..d87244ee31 --- /dev/null +++ b/auth/assets/custom-icons/icons/Restream.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/auth/assets/custom-icons/icons/Rewind.svg b/auth/assets/custom-icons/icons/Rewind.svg new file mode 100644 index 0000000000..ede9b155fc --- /dev/null +++ b/auth/assets/custom-icons/icons/Rewind.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Roblox.svg b/auth/assets/custom-icons/icons/Roblox.svg new file mode 100644 index 0000000000..1a7a75c16e --- /dev/null +++ b/auth/assets/custom-icons/icons/Roblox.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/ScaleGrid.svg b/auth/assets/custom-icons/icons/ScaleGrid.svg new file mode 100644 index 0000000000..b8a4bf1a26 --- /dev/null +++ b/auth/assets/custom-icons/icons/ScaleGrid.svg @@ -0,0 +1,43 @@ + + + + diff --git a/auth/assets/custom-icons/icons/Scaleway.svg b/auth/assets/custom-icons/icons/Scaleway.svg new file mode 100644 index 0000000000..de67221b54 --- /dev/null +++ b/auth/assets/custom-icons/icons/Scaleway.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Scalr.svg b/auth/assets/custom-icons/icons/Scalr.svg new file mode 100644 index 0000000000..c35d1d61e4 --- /dev/null +++ b/auth/assets/custom-icons/icons/Scalr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Serverspace.svg b/auth/assets/custom-icons/icons/Serverspace.svg new file mode 100644 index 0000000000..d8bafd2bf1 --- /dev/null +++ b/auth/assets/custom-icons/icons/Serverspace.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Shadow.svg b/auth/assets/custom-icons/icons/Shadow.svg new file mode 100644 index 0000000000..a116c4149f --- /dev/null +++ b/auth/assets/custom-icons/icons/Shadow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Side Quest.svg b/auth/assets/custom-icons/icons/Side Quest.svg new file mode 100644 index 0000000000..aaf0eaa2a0 --- /dev/null +++ b/auth/assets/custom-icons/icons/Side Quest.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Square Enix.svg b/auth/assets/custom-icons/icons/Square Enix.svg new file mode 100644 index 0000000000..087fb52d58 --- /dev/null +++ b/auth/assets/custom-icons/icons/Square Enix.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Sync.svg b/auth/assets/custom-icons/icons/Sync.svg new file mode 100644 index 0000000000..155232a651 --- /dev/null +++ b/auth/assets/custom-icons/icons/Sync.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Synology.svg b/auth/assets/custom-icons/icons/Synology.svg new file mode 100644 index 0000000000..a37b86aceb --- /dev/null +++ b/auth/assets/custom-icons/icons/Synology.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/TeamViewer.svg b/auth/assets/custom-icons/icons/TeamViewer.svg new file mode 100644 index 0000000000..7afa42596a --- /dev/null +++ b/auth/assets/custom-icons/icons/TeamViewer.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Technic.svg b/auth/assets/custom-icons/icons/Technic.svg new file mode 100644 index 0000000000..53b1cafb17 --- /dev/null +++ b/auth/assets/custom-icons/icons/Technic.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Terabit.svg b/auth/assets/custom-icons/icons/Terabit.svg new file mode 100644 index 0000000000..ed83219e19 --- /dev/null +++ b/auth/assets/custom-icons/icons/Terabit.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/auth/assets/custom-icons/icons/Tilaa.svg b/auth/assets/custom-icons/icons/Tilaa.svg new file mode 100644 index 0000000000..c20371be4c --- /dev/null +++ b/auth/assets/custom-icons/icons/Tilaa.svg @@ -0,0 +1,43 @@ + + + + diff --git a/auth/assets/custom-icons/icons/Updraftplus.svg b/auth/assets/custom-icons/icons/Updraftplus.svg new file mode 100644 index 0000000000..afc9bb32b8 --- /dev/null +++ b/auth/assets/custom-icons/icons/Updraftplus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/VRChat.svg b/auth/assets/custom-icons/icons/VRChat.svg new file mode 100644 index 0000000000..d317e9a0b2 --- /dev/null +++ b/auth/assets/custom-icons/icons/VRChat.svg @@ -0,0 +1 @@ + diff --git a/auth/assets/custom-icons/icons/Vultr.svg b/auth/assets/custom-icons/icons/Vultr.svg new file mode 100644 index 0000000000..c6e47b0856 --- /dev/null +++ b/auth/assets/custom-icons/icons/Vultr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Warner Bros Games.svg b/auth/assets/custom-icons/icons/Warner Bros Games.svg new file mode 100644 index 0000000000..b10a089caf --- /dev/null +++ b/auth/assets/custom-icons/icons/Warner Bros Games.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Wetransfer.svg b/auth/assets/custom-icons/icons/Wetransfer.svg new file mode 100644 index 0000000000..dfa63e15a7 --- /dev/null +++ b/auth/assets/custom-icons/icons/Wetransfer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/Xbox.svg b/auth/assets/custom-icons/icons/Xbox.svg new file mode 100644 index 0000000000..249c685d74 --- /dev/null +++ b/auth/assets/custom-icons/icons/Xbox.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/auth/assets/custom-icons/icons/binance_tr.svg b/auth/assets/custom-icons/icons/binance_tr.svg new file mode 100644 index 0000000000..c3885f78a6 --- /dev/null +++ b/auth/assets/custom-icons/icons/binance_tr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/carta.svg b/auth/assets/custom-icons/icons/carta.svg new file mode 100644 index 0000000000..6041b36f13 --- /dev/null +++ b/auth/assets/custom-icons/icons/carta.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/cloudns.svg b/auth/assets/custom-icons/icons/cloudns.svg new file mode 100644 index 0000000000..9096df8c3c --- /dev/null +++ b/auth/assets/custom-icons/icons/cloudns.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/csfloat.svg b/auth/assets/custom-icons/icons/csfloat.svg new file mode 100644 index 0000000000..b2b54ba304 --- /dev/null +++ b/auth/assets/custom-icons/icons/csfloat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/digifinex.svg b/auth/assets/custom-icons/icons/digifinex.svg new file mode 100644 index 0000000000..111b5ca533 --- /dev/null +++ b/auth/assets/custom-icons/icons/digifinex.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/knownhost.svg b/auth/assets/custom-icons/icons/knownhost.svg new file mode 100644 index 0000000000..13d73cff04 --- /dev/null +++ b/auth/assets/custom-icons/icons/knownhost.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/auth/assets/custom-icons/icons/render.svg b/auth/assets/custom-icons/icons/render.svg index 68cdd931f5..cfb5a52e5c 100644 --- a/auth/assets/custom-icons/icons/render.svg +++ b/auth/assets/custom-icons/icons/render.svg @@ -1,6 +1,5 @@ - - - - - + + + + diff --git a/auth/assets/custom-icons/icons/troweprice.svg b/auth/assets/custom-icons/icons/troweprice.svg new file mode 100644 index 0000000000..1542e457b8 --- /dev/null +++ b/auth/assets/custom-icons/icons/troweprice.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/auth/assets/custom-icons/icons/ubiquiti.svg b/auth/assets/custom-icons/icons/ubiquiti.svg new file mode 100644 index 0000000000..9c7a802402 --- /dev/null +++ b/auth/assets/custom-icons/icons/ubiquiti.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/auth/assets/simple-icons b/auth/assets/simple-icons index bffc992b7d..8a3731352a 160000 --- a/auth/assets/simple-icons +++ b/auth/assets/simple-icons @@ -1 +1 @@ -Subproject commit bffc992b7d1365ee44b1683f8397e9f7a44d0c2c +Subproject commit 8a3731352af133a02223a6c7b1f37c4abb096af0 diff --git a/auth/flutter b/auth/flutter index 2663184aa7..5874a72aa4 160000 --- a/auth/flutter +++ b/auth/flutter @@ -1 +1 @@ -Subproject commit 2663184aa79047d0a33a14a3b607954f8fdd8730 +Subproject commit 5874a72aa4c779a02553007c47dacbefba2374dc diff --git a/auth/lib/core/configuration.dart b/auth/lib/core/configuration.dart index 950ebd60b6..c032d79689 100644 --- a/auth/lib/core/configuration.dart +++ b/auth/lib/core/configuration.dart @@ -13,11 +13,11 @@ import 'package:ente_auth/models/key_attributes.dart'; import 'package:ente_auth/models/key_gen_result.dart'; import 'package:ente_auth/models/private_key_attributes.dart'; import 'package:ente_auth/store/authenticator_db.dart'; +import 'package:ente_auth/utils/directory_utils.dart'; import 'package:ente_auth/utils/lock_screen_settings.dart'; import 'package:ente_crypto_dart/ente_crypto_dart.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:logging/logging.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; import 'package:tuple/tuple.dart'; @@ -56,7 +56,6 @@ class Configuration { static final _logger = Logger("Configuration"); String? _cachedToken; - late String _documentsDirectory; late SharedPreferences _preferences; String? _key; String? _secretKey; @@ -75,8 +74,7 @@ class Configuration { _preferences = await SharedPreferences.getInstance(); sqfliteFfiInit(); _secureStorage = const FlutterSecureStorage(); - _documentsDirectory = (await getApplicationDocumentsDirectory()).path; - _tempDirectory = "$_documentsDirectory/temp/"; + _tempDirectory = (await DirectoryUtils.getDirectoryForInit()).path; final tempDirectory = io.Directory(_tempDirectory); try { final currentTime = DateTime.now().microsecondsSinceEpoch; diff --git a/auth/lib/l10n/arb/app_lt.arb b/auth/lib/l10n/arb/app_lt.arb index 6b569cf0eb..c74c01139d 100644 --- a/auth/lib/l10n/arb/app_lt.arb +++ b/auth/lib/l10n/arb/app_lt.arb @@ -8,17 +8,17 @@ }, "onBoardingBody": "Saugiai kurkite atsargines 2FA kodų kopijas", "onBoardingGetStarted": "Pradėti", - "setupFirstAccount": "Nustatyti pirmąją paskyrą", + "setupFirstAccount": "Nustatykite savo pirmąją paskyrą", "importScanQrCode": "Skenuoti QR kodą", "qrCode": "QR kodas", - "importEnterSetupKey": "Įveskite sąrankos raktą", - "importAccountPageTitle": "Įveskite paskyros duomenis", + "importEnterSetupKey": "Įvesti sąrankos raktą", + "importAccountPageTitle": "Įvesti paskyros duomenis", "secretCanNotBeEmpty": "Paslaptis negali būti tuščia.", "bothIssuerAndAccountCanNotBeEmpty": "Tiek išdavėjas ir paskyra negali būti tušti.", "incorrectDetails": "Neteisingi duomenys", "pleaseVerifyDetails": "Patikrinkite duomenis ir bandykite dar kartą.", "codeIssuerHint": "Išdavėjas", - "codeSecretKeyHint": "Slaptas raktas", + "codeSecretKeyHint": "Slaptasis raktas", "secret": "Paslaptis", "all": "Viskas", "notes": "Pastabos", @@ -50,7 +50,7 @@ "deleteCodeMessage": "Ar tikrai norite ištrinti šį kodą? Šis veiksmas negrįžtamas.", "trashCode": "Ištuštinti kodą?", "trashCodeMessage": "Ar tikrai norite ištuštinti {account} kodą?", - "trash": "Šiukšlinė", + "trash": "Ištuštinti", "viewLogsAction": "Peržiūrėti žurnalus", "sendLogsDescription": "Tai nusiųs žurnalo įrašus, kurie padės mums išspręsti jūsų problemą. Nors imamės atsargumo priemonių, kad slaptos informacijos nebūtų įrašoma, raginame jus peržiūrėti šiuos žurnalus prieš bendrinant juos.", "preparingLogsTitle": "Ruošiami žurnalai...", @@ -66,7 +66,7 @@ "copyEmailAction": "Kopijuoti el. paštą", "exportLogsAction": "Eksportuoti žurnalus", "reportABug": "Pranešti apie riktą", - "crashAndErrorReporting": "Strigčių ir klaidų pranešimas", + "crashAndErrorReporting": "Pranešti apie strigčius ir klaidas", "reportBug": "Pranešti apie riktą", "emailUsMessage": "Siųskite el. laišką mums adresu {email}", "@emailUsMessage": { @@ -77,18 +77,18 @@ } }, "contactSupport": "Susisiekti su palaikymo komanda", - "rateUsOnStore": "Vertinti mus parduotuvėje {storeName}", + "rateUsOnStore": "Vertinti mus parduotuvėje „{storeName}“", "blog": "Tinklaraštis", "merchandise": "Atributika", "verifyPassword": "Patvirtinkite slaptažodį", "pleaseWait": "Palaukite...", "generatingEncryptionKeysTitle": "Generuojami šifravimo raktai...", "recreatePassword": "Iš naujo sukurti slaptažodį", - "recreatePasswordMessage": "Dabartinis įrenginys nėra pakankamai galingas, kad patvirtintų jūsų slaptažodį, todėl turime jį vieną kartą regeneruoti taip, kad jis veiktų visuose įrenginiuose. \n\nPrisijunkite naudojant atkūrimo raktą ir regeneruokite slaptažodį (jei norite, galite vėl naudoti tą patį).", + "recreatePasswordMessage": "Dabartinis įrenginys nėra pakankamai galingas, kad patvirtintų jūsų slaptažodį, todėl turime jį vieną kartą iš naujo sugeneruoti taip, kad jis veiktų visuose įrenginiuose. \n\nPrisijunkite naudodami atkūrimo raktą ir sugeneruokite iš naujo slaptažodį (jei norite, galite vėl naudoti tą patį).", "useRecoveryKey": "Naudoti atkūrimo raktą", "incorrectPasswordTitle": "Neteisingas slaptažodis.", "welcomeBack": "Sveiki sugrįžę!", - "madeWithLoveAtPrefix": "sukurta su ❤️ ", + "madeWithLoveAtPrefix": "sukurta su ❤️ vietoje ", "supportDevs": "Prenumeruokite „ente“, kad palaikytumėte mus", "supportDiscount": "Naudokite kupono kodą „AUTH“, kad gautumėte 10 % nuolaida pirmiesiems metams", "changeEmail": "Keisti el. paštą", @@ -100,14 +100,14 @@ "passwordForDecryptingExport": "Slaptažodis eksportui iššifruoti", "passwordEmptyError": "Slaptažodis negali būti tuščias.", "importFromApp": "Importuoti kodus iš „{appName}“", - "importGoogleAuthGuide": "Eksportuokite paskyras iš „Google Authenticator“ į QR kodą naudojant parinktį Perkelti paskyras. Tada naudojant kitą įrenginį nuskenuokite QR kodą.\n\nPatarimas: QR kodą galite nufotografuoti naudojant nešiojamojo kompiuterio internetinę vaizdo kamerą.", + "importGoogleAuthGuide": "Eksportuokite paskyras iš „Google Authenticator“ į QR kodą naudodami parinktį Perkelti paskyras. Tada naudojant kitą įrenginį nuskenuokite QR kodą.\n\nPatarimas: QR kodą galite nufotografuoti naudojant nešiojamojo kompiuterio internetinę vaizdo kamerą.", "importSelectJsonFile": "Pasirinkti JSON failą", "importSelectAppExport": "Pasirinkti „{appName}“ eksporto failą", "importEnteEncGuide": "Pasirinkite užšifruotą JSON failą, eksportuotą iš „Ente“", "importRaivoGuide": "Naudokite „Raivo“ nustatymuose esančią parinktį „Export OTPs to Zip archive“ (eksportuoti OTP į ZIP archyvą).\n\nIšskleiskite ZIP failą ir importuokite JSON failą.", - "importBitwardenGuide": "Naudokite „Bitwarden“ įrankiuose esančią parinktį „Eksportuoti saugyklą“ ir importuokite nešifruotą JSON failą.", - "importAegisGuide": "Naudokite „Aegis“ nustatymuose esančią parinktį „Eksportuoti slėptuvę“.\n\nJei jūsų saugykla yra užšifruota, turėsite įvesti saugyklos slaptažodį, kad iššifruotumėte saugyklą.", - "import2FasGuide": "Naudokite 2FAS parinktį „Settings->2FAS Backup->Export to file“.\n\nJei atsarginė kopija užšifruota, turėsite įvesti slaptažodį, kad iššifruotumėte atsarginę kopiją.", + "importBitwardenGuide": "Naudokite „Bitwarden“ įrankiuose esančią parinktį Eksportuoti saugyklą ir importuokite nešifruotą JSON failą.", + "importAegisGuide": "Naudokite „Aegis“ nustatymuose esančią parinktį Eksportuoti slėptuvę.\n\nJei jūsų saugykla užšifruota, turėsite įvesti saugyklos slaptažodį, kad iššifruotumėte saugyklą.", + "import2FasGuide": "Naudokite programoje 2FAS esančią parinktį „Settings->2FAS Backup->Export to file“.\n\nJei atsarginė kopija užšifruota, turėsite įvesti slaptažodį, kad iššifruotumėte atsarginę kopiją.", "importLastpassGuide": "Naudokite „Lastpass Authenticator“ nustatymuose esančią parinktį „Transfer accounts“ (perkelti paskyras) ir paspauskite „Export accounts to file“ (eksportuoti paskyras į failą). Importuokite atsisiųstą JSON failą.", "exportCodes": "Eksportuoti kodus", "importLabel": "Importuoti", @@ -122,7 +122,7 @@ "authToChangeYourEmail": "Nustatykite tapatybę, kad pakeistumėte savo el. paštą", "authToChangeYourPassword": "Nustatykite tapatybę, kad pakeistumėte slaptažodį", "authToViewSecrets": "Nustatykite tapatybę, kad peržiūrėtumėte savo paslaptis", - "authToInitiateSignIn": "Nustatykite tapatybę, kad pradėtumėte prisijungti prie atsarginės kopijos.", + "authToInitiateSignIn": "Nustatykite tapatybę, kad pradėtumėte prisijungti norint kurti atsargines kopijas.", "ok": "Gerai", "cancel": "Atšaukti", "yes": "Taip", @@ -134,7 +134,7 @@ "copied": "Nukopijuota", "pleaseTryAgain": "Bandykite dar kartą.", "existingUser": "Esamas naudotojas", - "newUser": "Naujas platformoje „Ente“", + "newUser": "Naujas sistemoje „Ente“", "delete": "Ištrinti", "enterYourPasswordHint": "Įveskite savo slaptažodį", "forgotPassword": "Pamiršau slaptažodį", @@ -148,7 +148,7 @@ "hintForMobile": "Ilgai paspauskite kodą, kad jį redaguotumėte arba pašalintumėte.", "hintForDesktop": "Dešiniuoju pelės mygtuku spustelėkite kodą, kad jį redaguotumėte arba pašalintumėte.", "scan": "Skenuoti", - "scanACode": "Skenuoti kodą", + "scanACode": "Skenuokite kodą", "verify": "Patvirtinti", "verifyEmail": "Patvirtinti el. paštą", "enterCodeHint": "Įveskite 6 skaitmenų kodą\niš autentifikatoriaus programos", @@ -170,17 +170,19 @@ "invalidQRCode": "Netinkamas QR kodas.", "noRecoveryKeyTitle": "Neturite atkūrimo rakto?", "enterEmailHint": "Įveskite savo el. pašto adresą", - "invalidEmailTitle": "Netinkamas el. pašto adresas.", + "invalidEmailTitle": "Netinkamas el. pašto adresas", "invalidEmailMessage": "Įveskite tinkamą el. pašto adresą.", "deleteAccount": "Ištrinti paskyrą", "deleteAccountQuery": "Apgailestausime, kad išeinate. Ar susiduriate su kažkokiomis problemomis?", "yesSendFeedbackAction": "Taip, siųsti atsiliepimą", "noDeleteAccountAction": "Ne, ištrinti paskyrą", + "initiateAccountDeleteTitle": "Nustatykite tapatybę, kad pradėtumėte paskyros ištrynimą", "sendEmail": "Siųsti el. laišką", "createNewAccount": "Kurti naują paskyrą", "weakStrength": "Silpna", "strongStrength": "Stipri", "moderateStrength": "Vidutinė", + "confirmPassword": "Patvirtinkite slaptažodį", "close": "Uždaryti", "oopsSomethingWentWrong": "Ups, kažkas nutiko ne taip.", "selectLanguage": "Pasirinkite kalbą", @@ -190,20 +192,93 @@ "lockscreen": "Ekrano užraktas", "authToChangeLockscreenSetting": "Nustatykite tapatybę, kad pakeistumėte užrakinto ekrano nustatymą", "deviceLockEnablePreSteps": "Kad įjungtumėte įrenginio užraktą, sistemos nustatymuose nustatykite įrenginio prieigos kodą arba ekrano užraktą.", + "viewActiveSessions": "Peržiūrėti aktyvius seansus", + "authToViewYourActiveSessions": "Nustatykite tapatybę, kad peržiūrėtumėte savo aktyvius seansus", + "searchHint": "Ieškokite...", + "search": "Paieška", + "sorryUnableToGenCode": "Atsiprašome, nepavyksta sugeneruoti {issuerName} kodo.", + "noResult": "Nėra rezultatų", + "addCode": "Pridėti kodą", + "scanAQrCode": "Skenuoti QR kodą", + "enterDetailsManually": "Įvesti duomenis rankiniu būdu", + "edit": "Redaguoti", + "share": "Bendrinti", + "shareCodes": "Bendrinti kodus", + "shareCodesDuration": "Pasirinkite trukmę, kuriai norite bendrinti kodus.", + "restore": "Atkurti", + "copiedToClipboard": "Nukopijuota į iškarpinę", + "copiedNextToClipboard": "Nukopijuotas sekantis kodas į iškarpinę", + "error": "Klaida", + "recoveryKeyCopiedToClipboard": "Nukopijuotas atkūrimo raktas į iškarpinę", + "recoveryKeyOnForgotPassword": "Jei pamiršote slaptažodį, vienintelis būdas atkurti duomenis – naudoti šį raktą.", + "recoveryKeySaveDescription": "Šio rakto nesaugome, todėl išsaugokite šį 24 žodžių raktą saugioje vietoje.", + "doThisLater": "Daryti tai vėliau", + "saveKey": "Išsaugoti raktą", + "save": "Išsaugoti", + "send": "Siųsti", + "saveOrSendDescription": "Ar norite tai išsaugoti saugykloje (pagal numatytuosius nustatymus – atsisiuntimų aplanke), ar siųsti į kitas programas?", + "saveOnlyDescription": "Ar norite tai išsaugoti savo saugykloje (pagal numatytuosius nustatymus – atsisiuntimų aplanke)?", + "back": "Atgal", + "createAccount": "Kurti paskyrą", + "passwordStrength": "Slaptažodžio stiprumas: {passwordStrengthValue}", + "@passwordStrength": { + "description": "Text to indicate the password strength", + "placeholders": { + "passwordStrengthValue": { + "description": "The strength of the password as a string", + "type": "String", + "example": "Weak or Moderate or Strong" + } + }, + "message": "Password Strength: {passwordStrengthText}" + }, + "password": "Slaptažodis", + "signUpTerms": "Sutinku su paslaugų sąlygomis ir privatumo politika", + "privacyPolicyTitle": "Privatumo politika", + "termsOfServicesTitle": "Sąlygos", + "encryption": "Šifravimas", + "setPasswordTitle": "Nustatyti slaptažodį", + "changePasswordTitle": "Keisti slaptažodį", + "resetPasswordTitle": "Nustatyti slaptažodį iš naujo", + "encryptionKeys": "Šifravimo raktai", + "passwordWarning": "Šio slaptažodžio nesaugome, todėl jei jį pamiršite, negalėsime iššifruoti jūsų duomenų", + "enterPasswordToEncrypt": "Įveskite slaptažodį, kurį galime naudoti jūsų duomenims užšifruoti", + "enterNewPasswordToEncrypt": "Įveskite naują slaptažodį, kurį galime naudoti jūsų duomenims užšifruoti", + "passwordChangedSuccessfully": "Slaptažodis sėkmingai pakeistas", + "generatingEncryptionKeys": "Generuojami šifravimo raktai...", "continueLabel": "Tęsti", + "insecureDevice": "Nesaugus įrenginys", + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Atsiprašome, šiame įrenginyje nepavyko sugeneruoti saugių raktų.\n\nRegistruokitės iš kito įrenginio.", + "howItWorks": "Kaip tai veikia", + "ackPasswordLostWarning": "Suprantu, kad jei prarasiu slaptažodį, galiu prarasti savo duomenis, kadangi duomenys yra visapusiškai užšifruota.", "loginTerms": "Spustelėjus Prisijungti sutinku su paslaugų sąlygomis ir privatumo politika", "logInLabel": "Prisijungti", "logout": "Atsijungti", "areYouSureYouWantToLogout": "Ar tikrai norite atsijungti?", "yesLogout": "Taip, atsijungti", "exit": "Išeiti", + "verifyingRecoveryKey": "Patvirtinima atkūrimo raktą...", + "recoveryKeyVerified": "Patvirtintas atkūrimo raktas", + "recoveryKeySuccessBody": "Puiku! Jūsų atkūrimo raktas tinkamas. Dėkojame už patvirtinimą.\n\nNepamirškite sukurti saugią atkūrimo rakto atsarginę kopiją.", + "invalidRecoveryKey": "Įvestas atkūrimo raktas yra netinkamas. Įsitikinkite, kad jame yra 24 žodžiai, ir patikrinkite kiekvieno iš jų rašybą.\n\nJei įvedėte senesnį atkūrimo kodą, įsitikinkite, kad jis yra 64 simbolių ilgio, ir patikrinkite kiekvieną iš jų.", + "recreatePasswordTitle": "Iš naujo sukurti slaptažodį", + "recreatePasswordBody": "Dabartinis įrenginys nėra pakankamai galingas, kad patvirtintų jūsų slaptažodį, bet mes galime iš naujo sugeneruoti taip, kad jis veiktų su visais įrenginiais.\n\nPrisijunkite naudodami atkūrimo raktą ir sugeneruokite iš naujo slaptažodį (jei norite, galite vėl naudoti tą patį).", + "invalidKey": "Netinkamas raktas.", + "tryAgain": "Bandyti dar kartą", + "viewRecoveryKey": "Peržiūrėti atkūrimo raktą", + "confirmRecoveryKey": "Patvirtinkite atkūrimo raktą", + "recoveryKeyVerifyReason": "Atkūrimo raktas – vienintelis būdas atkurti nuotraukas, jei pamiršote slaptažodį. Atkūrimo raktą galite rasti Nustatymose > Paskyra.\n\nĮveskite savo atkūrimo raktą čia, kad patvirtintumėte, ar teisingai jį išsaugojote.", + "confirmYourRecoveryKey": "Patvirtinkite savo atkūrimo raktą", "confirm": "Patvirtinti", "emailYourLogs": "Atsiųskite žurnalus el. laišku", + "pleaseSendTheLogsTo": "Siųskite žurnalus adresu\n{toEmail}", "copyEmailAddress": "Kopijuoti el. pašto adresą", "exportLogs": "Eksportuoti žurnalus", "enterYourRecoveryKey": "Įveskite atkūrimo raktą", "tempErrorContactSupportIfPersists": "Atrodo, kad kažkas nutiko ne taip. Bandykite dar kartą po kurio laiko. Jei klaida tęsiasi, susisiekite su mūsų palaikymo komanda.", "networkHostLookUpErr": "Nepavyksta prisijungti prie „Ente“. Patikrinkite tinklo nustatymus ir susisiekite su palaikymo komanda, jei klaida tęsiasi.", + "networkConnectionRefusedErr": "Nepavyksta prisijungti prie „Ente“. Bandykite dar kartą po kurio laiko. Jei klaida tęsiasi, susisiekite su palaikymo komanda.", + "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": "Atrodo, kad kažkas nutiko ne taip. Bandykite dar kartą po kurio laiko. Jei klaida tęsiasi, susisiekite su mūsų palaikymo komanda.", "about": "Apie", "weAreOpenSource": "Esame atviro kodo!", "privacy": "Privatumas", @@ -224,7 +299,7 @@ }, "authToExportCodes": "Nustatykite tapatybę, kad eksportuotumėte savo kodus", "importSuccessTitle": "Valio!", - "importSuccessDesc": "Importavote {count} kodų!", + "importSuccessDesc": "Importavote {count} kodų.", "@importSuccessDesc": { "placeholders": { "count": { @@ -241,7 +316,7 @@ "checkInboxAndSpamFolder": "Patikrinkite savo gautieją (ir šlamštą), kad užbaigtumėte patvirtinimą", "tapToEnterCode": "Palieskite, kad įvestumėte kodą", "resendEmail": "Iš naujo siųsti el. laišką", - "weHaveSendEmailTo": "Išsiuntėme laišką į {email}", + "weHaveSendEmailTo": "Išsiuntėme laišką adresu {email}", "@weHaveSendEmailTo": { "description": "Text to indicate that we have sent a mail to the user", "placeholders": { @@ -256,10 +331,117 @@ "somethingWentWrongPleaseTryAgain": "Kažkas nutiko ne taip. Bandykite dar kartą.", "thisWillLogYouOutOfThisDevice": "Tai jus atjungs nuo šio įrenginio.", "thisWillLogYouOutOfTheFollowingDevice": "Tai jus atjungs nuo toliau nurodyto įrenginio:", + "terminateSession": "Baigti seansą?", + "terminate": "Baigti", + "thisDevice": "Šis įrenginys", + "toResetVerifyEmail": "Kad iš naujo nustatytumėte slaptažodį, pirmiausia patvirtinkite savo el. paštą.", + "thisEmailIsAlreadyInUse": "Šis el. paštas jau naudojamas.", + "verificationFailedPleaseTryAgain": "Patvirtinimas nepavyko. Bandykite dar kartą.", + "yourVerificationCodeHasExpired": "Jūsų patvirtinimo kodo laikas nebegaliojantis.", + "incorrectCode": "Neteisingas kodas", + "sorryTheCodeYouveEnteredIsIncorrect": "Atsiprašome, įvestas kodas yra neteisingas.", + "emailChangedTo": "El. paštas pakeistas į {newEmail}", + "authenticationFailedPleaseTryAgain": "Tapatybės nustatymas nepavyko. Bandykite dar kartą.", + "authenticationSuccessful": "Tapatybės nustatymas sėkmingas!", + "twofactorAuthenticationSuccessfullyReset": "Dvigubas tapatybės nustatymas sėkmingai iš naujo nustatytas.", + "incorrectRecoveryKey": "Neteisingas atkūrimo raktas", + "theRecoveryKeyYouEnteredIsIncorrect": "Įvestas atkūrimo raktas yra neteisingas.", + "enterPassword": "Įveskite slaptažodį", + "selectExportFormat": "Pasirinkite eksporto formatą", + "exportDialogDesc": "Užšifruoti eksportai bus apsaugoti jūsų pasirinktu slaptažodžiu.", + "encrypted": "Užšifruota", + "plainText": "Paprastasis tekstas", + "passwordToEncryptExport": "Slaptažodis eksportui užšifruoti", + "export": "Eksportuoti", + "useOffline": "Naudoti be atsarginių kopijų", + "signInToBackup": "Prisijunkite, kad sukurtumėte atsargines kodų kopijas", + "singIn": "Prisijungti", + "sigInBackupReminder": "Eksportuokite kodus, kad turėtumėte atsarginę kopiją, kurią galėsite atkurti.", + "offlineModeWarning": "Pasirinkote tęsti be atsarginių kopijų. Kad įsitikintumėte, jog jūsų kodai yra saugūs, pasidarykite atsargines kopijas rankiniu būdu.", + "showLargeIcons": "Rodyti dideles piktogramas", + "compactMode": "Kompaktinis režimas", + "shouldHideCode": "Slėpti kodus", + "doubleTapToViewHiddenCode": "Galite dukart paliesti elementą, kad peržiūrėtumėte kodą", + "focusOnSearchBar": "Fokusuoti paiešką paleidžiant programą", + "confirmUpdatingkey": "Ar tikrai norite atnaujinti slaptąjį raktą?", + "minimizeAppOnCopy": "Sumažinti programą kopijuojant", + "editCodeAuthMessage": "Nustatykite tapatybę, kad redaguotumėte kodą", + "deleteCodeAuthMessage": "Nustatykite tapatybę, kad ištrintumėte kodą", + "showQRAuthMessage": "Nustatykite tapatybę, kad būtų rodomas QR kodas", + "confirmAccountDeleteTitle": "Patvirtinkite paskyros ištrynimą", + "confirmAccountDeleteMessage": "Ši paskyra susieta su kitomis „Ente“ programomis, jei jas naudojate.\n\nJūsų įkelti duomenys per visas „Ente“ programas bus planuojama ištrinti, o jūsų paskyra bus ištrinta negrįžtamai.", + "androidBiometricHint": "Patvirtinkite tapatybę", + "@androidBiometricHint": { + "description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters." + }, + "androidBiometricNotRecognized": "Neatpažinta. Bandykite dar kartą.", + "@androidBiometricNotRecognized": { + "description": "Message to let the user know that authentication was failed. It is used on Android side. Maximum 60 characters." + }, + "androidBiometricSuccess": "Sėkmė", + "@androidBiometricSuccess": { + "description": "Message to let the user know that authentication was successful. It is used on Android side. Maximum 60 characters." + }, + "androidCancelButton": "Atšaukti", + "@androidCancelButton": { + "description": "Message showed on a button that the user can click to leave the current dialog. It is used on Android side. Maximum 30 characters." + }, + "androidSignInTitle": "Privalomas tapatybės nustatymas", + "@androidSignInTitle": { + "description": "Message showed as a title in a dialog which indicates the user that they need to scan biometric to continue. It is used on Android side. Maximum 60 characters." + }, + "androidBiometricRequiredTitle": "Privaloma biometrija", + "@androidBiometricRequiredTitle": { + "description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters." + }, + "androidDeviceCredentialsRequiredTitle": "Privalomi įrenginio kredencialai", + "@androidDeviceCredentialsRequiredTitle": { + "description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters." + }, + "androidDeviceCredentialsSetupDescription": "Privalomi įrenginio kredencialai", + "@androidDeviceCredentialsSetupDescription": { + "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." + }, + "goToSettings": "Eiti į nustatymus", + "@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": "Biometrinis tapatybės nustatymas jūsų įrenginyje nenustatytas. Eikite į Nustatymai > Saugumas ir pridėkite biometrinį tapatybės nustatymą.", + "@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": "Biometrinis tapatybės nustatymas išjungtas. Kad jį įjungtumėte, užrakinkite ir atrakinkite ekraną.", + "@iOSLockOut": { + "description": "Message advising the user to re-enable biometrics on their device. It shows in a dialog on iOS side." + }, + "iOSGoToSettingsDescription": "Biometrinis tapatybės nustatymas jūsų įrenginyje nenustatytas. Telefone įjunkite „Touch ID“ arba „Face ID“.", + "@iOSGoToSettingsDescription": { + "description": "Message advising the user to go to the settings and configure Biometrics for their device. It shows in a dialog on iOS side." + }, + "iOSOkButton": "Gerai", + "@iOSOkButton": { + "description": "Message showed on a button that the user can click to leave the current dialog. It is used on iOS side. Maximum 30 characters." + }, + "noInternetConnection": "Nėra interneto ryšio", + "pleaseCheckYourInternetConnectionAndTryAgain": "Patikrinkite savo interneto ryšį ir bandykite dar kartą.", + "signOutFromOtherDevices": "Atsijungti iš kitų įrenginių", + "signOutOtherBody": "Jei manote, kad kas nors gali žinoti jūsų slaptažodį, galite priverstinai atsijungti iš visų kitų įrenginių, naudojančių jūsų paskyrą.", + "signOutOtherDevices": "Atsijungti kitus įrenginius", + "doNotSignOut": "Neatsijungti", + "hearUsWhereTitle": "Kaip išgirdote apie „Ente“? (nebūtina)", + "hearUsExplanation": "Mes nesekame programų diegimų. Mums padėtų, jei pasakytumėte, kur mus radote.", + "recoveryKeySaved": "Atkūrimo raktas išsaugotas atsisiuntimų aplanke.", + "waitingForBrowserRequest": "Laukiama naršyklės užklausos...", + "waitingForVerification": "Laukiama patvirtinimo...", + "passkey": "Slaptaraktas", + "passKeyPendingVerification": "Vis dar laukiama patvirtinimo", + "loginSessionExpired": "Seansas baigėsi", + "loginSessionExpiredDetails": "Jūsų seansas baigėsi. Prisijunkite iš naujo.", + "developerSettingsWarning": "Ar tikrai norite modifikuoti kūrėjo nustatymus?", "developerSettings": "Kūrėjo nustatymai", "serverEndpoint": "Serverio galutinis taškas", "invalidEndpoint": "Netinkamas galutinis taškas", - "invalidEndpointMessage": "Atsiprašome. Jūsų įvestas galutinis taškas yra netinkamas. Įveskite tinkamą galutinį tašką ir bandykite dar kartą.", + "invalidEndpointMessage": "Atsiprašome, įvestas galutinis taškas netinkamas. Įveskite tinkamą galutinį tašką ir bandykite dar kartą.", "endpointUpdatedMessage": "Galutinis taškas sėkmingai atnaujintas", "customEndpoint": "Prijungta prie {endpoint}", "pinText": "Prisegti", @@ -268,6 +450,14 @@ "unpinnedCodeMessage": "{code} buvo atsegtas", "tags": "Žymės", "createNewTag": "Kurti naują žymę", + "tag": "Žymė", + "create": "Kurti", + "editTag": "Redaguoti žymę", + "deleteTagTitle": "Ištrinti žymę?", + "deleteTagMessage": "Ar tikrai norite ištrinti šią žymę? Šis veiksmas negrįžtamas.", + "somethingWentWrongParsingCode": "Mums nepavyko išanalizuoti {x} kodų.", + "updateNotAvailable": "Nėra naujinimų", + "viewRawCodes": "Peržiūrėti neapdorotus kodus", "rawCodes": "Neapdoroti kodai", "rawCodeData": "Neapdoroti kodo duomenys", "appLock": "Programos užraktas", @@ -277,8 +467,22 @@ "immediately": "Iš karto", "reEnterPassword": "Įveskite slaptažodį iš naujo", "reEnterPin": "Įveskite PIN iš naujo", - "next": "Sekantis", + "next": "Toliau", "tooManyIncorrectAttempts": "Per daug neteisingų bandymų.", "tapToUnlock": "Palieskite, kad atrakintumėte", + "setNewPassword": "Nustatykite naują slaptažodį", + "deviceLock": "Įrenginio užraktas", + "hideContent": "Slėpti turinį", + "hideContentDescriptionAndroid": "Paslepia programų turinį programų perjungiklyje ir išjungia ekrano kopijas", + "hideContentDescriptioniOS": "Paslepia programos turinį programos perjungiklyje", + "autoLockFeatureDescription": "Laikas, po kurio programa užrakinama perkėlus ją į foną", + "appLockDescription": "Pasirinkite tarp numatytojo įrenginio užrakinimo ekrano ir pasirinktinio užrakinimo ekrano su PIN kodu arba slaptažodžiu.", + "pinLock": "PIN užraktas", + "enterPin": "Įveskite PIN", + "setNewPin": "Nustatykite naują PIN", + "importFailureDescNew": "Nepavyko išanalizuoti pasirinkto failo.", + "appLockNotEnabled": "Programos užraktas neįjungtas", + "appLockNotEnabledDescription": "Įjunkite programos užraktą iš Saugumas > Programos užraktas", + "authToViewPasskey": "Nustatykite tapatybę, kad peržiūrėtumėte slaptaraktą", "appLockOfflineModeWarning": "Pasirinkote tęsti be atsarginių kopijų. Jei pamiršite programos užraktą, jums bus užrakinta prieiga prie duomenų." } \ 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 6237009b1e..ecb41a894a 100644 --- a/auth/lib/l10n/arb/app_pt.arb +++ b/auth/lib/l10n/arb/app_pt.arb @@ -116,7 +116,7 @@ "selectFile": "Selecionar arquivo", "emailVerificationToggle": "Verificação por e-mail", "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", + "authToChangeEmailVerificationSetting": "Autentique-se para alterar a verificação de e-mail", "authenticateGeneric": "Autentique", "authToViewYourRecoveryKey": "Autentique para ver sua chave de recuperação", "authToChangeYourEmail": "Autentique para alterar o seu e-mail", diff --git a/auth/lib/main.dart b/auth/lib/main.dart index f812960a9a..b88104c188 100644 --- a/auth/lib/main.dart +++ b/auth/lib/main.dart @@ -22,6 +22,7 @@ import 'package:ente_auth/store/code_store.dart'; import 'package:ente_auth/ui/tools/app_lock.dart'; import 'package:ente_auth/ui/tools/lock_screen.dart'; import 'package:ente_auth/ui/utils/icon_utils.dart'; +import 'package:ente_auth/utils/directory_utils.dart'; import 'package:ente_auth/utils/lock_screen_settings.dart'; import 'package:ente_auth/utils/platform_util.dart'; import 'package:ente_auth/utils/window_protocol_handler.dart'; @@ -72,6 +73,7 @@ void main() async { size: WindowListenerService.instance.getWindowSize(), ); await windowManager.waitUntilReadyToShow(windowOptions, () async { + await DirectoryUtils.migrateNamingChanges(); await windowManager.show(); await windowManager.focus(); initSystemTray().ignore(); diff --git a/auth/lib/store/authenticator_db.dart b/auth/lib/store/authenticator_db.dart index deb57bc814..cc47745d59 100644 --- a/auth/lib/store/authenticator_db.dart +++ b/auth/lib/store/authenticator_db.dart @@ -37,8 +37,9 @@ class AuthenticatorDB { ), ); } - final Directory documentsDirectory = - await getApplicationDocumentsDirectory(); + final Directory documentsDirectory = Platform.isMacOS + ? await getApplicationSupportDirectory() + : await getApplicationDocumentsDirectory(); final String path = join(documentsDirectory.path, _databaseName); debugPrint(path); return await openDatabase( diff --git a/auth/lib/store/offline_authenticator_db.dart b/auth/lib/store/offline_authenticator_db.dart index d1af51fff3..3d280825bc 100644 --- a/auth/lib/store/offline_authenticator_db.dart +++ b/auth/lib/store/offline_authenticator_db.dart @@ -37,8 +37,9 @@ class OfflineAuthenticatorDB { ), ); } - final Directory documentsDirectory = - await getApplicationDocumentsDirectory(); + final Directory documentsDirectory = Platform.isMacOS + ? await getApplicationSupportDirectory() + : await getApplicationDocumentsDirectory(); final String path = join(documentsDirectory.path, _databaseName); debugPrint(path); return await openDatabase( diff --git a/auth/lib/utils/directory_utils.dart b/auth/lib/utils/directory_utils.dart index b9da6e6130..0cef244c67 100644 --- a/auth/lib/utils/directory_utils.dart +++ b/auth/lib/utils/directory_utils.dart @@ -1,12 +1,137 @@ +import 'dart:io'; + +import 'package:io/io.dart'; +import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:xdg_directories/xdg_directories.dart'; class DirectoryUtils { - static Future getDatabasePath(String databaseName) async => p.joinAll( - [ + static final logger = Logger('DirectoryUtils'); + + static Future getDatabasePath(String databaseName) async { + String? directoryPath; + + directoryPath ??= (await getApplicationSupportDirectory()).path; + + return p.joinAll( + [ + directoryPath, + ".$databaseName", + ], + ); + } + + static Future getDirectoryForInit() async { + Directory? directory; + if (Platform.isLinux) { + try { + return cacheHome; + } catch (e) { + logger.warning("Failed to get cacheHome: $e"); + } + } + + directory ??= await getApplicationDocumentsDirectory(); + + return Directory(p.join(directory.path, "enteauthinit")); + } + + static Future getTempsDir() async { + return await getTemporaryDirectory(); + } + + static String migratedNamingChanges = "migrated_naming_changes.b5"; + static migrateNamingChanges() async { + try { + final sharedPrefs = await SharedPreferences.getInstance(); + if (sharedPrefs.containsKey(migratedNamingChanges)) { + return; + } + var databaseFile = File( + p.join( (await getApplicationDocumentsDirectory()).path, "ente", - ".$databaseName", - ], + ".ente.authenticator.db", + ), ); + var offlineDatabaseFile = File( + p.join( + (await getApplicationDocumentsDirectory()).path, + "ente", + ".ente.offline_authenticator.db", + ), + ); + Directory oldDataDir; + Directory newDataDir; + + Directory? tempDir; + if (Platform.isLinux) { + oldDataDir = Directory( + p.join(dataHome.path, "ente_auth"), + ); + tempDir = Directory( + p.join(dataHome.path, "enteauth"), + ); + } else if (Platform.isWindows) { + oldDataDir = Directory( + p.join( + (await getApplicationDocumentsDirectory()).path, + "ente", + ), + ); + tempDir = Directory( + p.join( + (await getApplicationDocumentsDirectory()).path, + "enteauth", + ), + ); + } else { + oldDataDir = await getApplicationDocumentsDirectory(); + databaseFile = File( + p.join( + (await getApplicationDocumentsDirectory()).path, + "ente.authenticator.db", + ), + ); + offlineDatabaseFile = File( + p.join( + (await getApplicationDocumentsDirectory()).path, + "ente.offline_authenticator.db", + ), + ); + } + + if (tempDir?.existsSync() ?? false) { + oldDataDir = tempDir!; + } + newDataDir = await getApplicationSupportDirectory(); + await newDataDir.create(recursive: true); + + final prefix = Platform.isMacOS ? "" : "."; + File newDatabaseFile = + File(p.join(newDataDir.path, "${prefix}ente.authenticator.db")); + if (await databaseFile.exists() && !await newDatabaseFile.exists()) { + await databaseFile.copy(newDatabaseFile.path); + } + + File newOfflineDatabaseFile = File( + p.join(newDataDir.path, "${prefix}ente.offline_authenticator.db"), + ); + if (await offlineDatabaseFile.exists() && + !await newOfflineDatabaseFile.exists()) { + await offlineDatabaseFile.copy(newOfflineDatabaseFile.path); + } + + if (Platform.isLinux && await oldDataDir.exists()) { + await copyPath(oldDataDir.path, newDataDir.path); + } + + sharedPrefs.setBool(migratedNamingChanges, true).ignore(); + } catch (e, st) { + logger.warning("Migrating Database failed!", e, st); + rethrow; + } + } } diff --git a/auth/lib/utils/email_util.dart b/auth/lib/utils/email_util.dart index 73291a1ed5..3c35769574 100644 --- a/auth/lib/utils/email_util.dart +++ b/auth/lib/utils/email_util.dart @@ -10,6 +10,7 @@ import 'package:ente_auth/ui/components/dialog_widget.dart'; import 'package:ente_auth/ui/components/models/button_type.dart'; import 'package:ente_auth/ui/tools/debug/log_file_viewer.dart'; import 'package:ente_auth/utils/dialog_util.dart'; +import 'package:ente_auth/utils/directory_utils.dart'; import 'package:ente_auth/utils/platform_util.dart'; import 'package:ente_auth/utils/share_utils.dart'; import 'package:ente_auth/utils/toast_util.dart'; @@ -146,7 +147,7 @@ Future getZippedLogsFile(BuildContext context) async { await dialog.show(); final logsPath = (await getApplicationSupportDirectory()).path; final logsDirectory = Directory("$logsPath/logs"); - final tempPath = (await getTemporaryDirectory()).path; + final tempPath = (await DirectoryUtils.getTempsDir()).path; final zipFilePath = "$tempPath/logs-${Configuration.instance.getUserID() ?? 0}.zip"; final encoder = ZipFileEncoder(); diff --git a/auth/lib/utils/platform_util.dart b/auth/lib/utils/platform_util.dart index 5e02702579..87fed6f97e 100644 --- a/auth/lib/utils/platform_util.dart +++ b/auth/lib/utils/platform_util.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:desktop_webview_window/desktop_webview_window.dart'; import 'package:ente_auth/ui/common/web_page.dart'; import 'package:file_saver/file_saver.dart'; import 'package:flutter/cupertino.dart'; @@ -31,17 +30,7 @@ class PlatformUtil { static openWebView(BuildContext context, String title, String url) async { if (PlatformUtil.isDesktop()) { - if (!await WebviewWindow.isWebviewAvailable()) { - await launchUrlString(url); - return; - } - - final webview = await WebviewWindow.create( - configuration: CreateConfiguration( - title: title, - ), - ); - webview.launch(url); + await launchUrlString(url); return; } await Navigator.of(context).push( diff --git a/auth/linux/CMakeLists.txt b/auth/linux/CMakeLists.txt index 2c0f9c6882..b36a97b845 100644 --- a/auth/linux/CMakeLists.txt +++ b/auth/linux/CMakeLists.txt @@ -4,7 +4,7 @@ project(runner LANGUAGES CXX) # The name of the executable created for the application. Change this to change # the on-disk name of your application. -set(BINARY_NAME "ente_auth") +set(BINARY_NAME "enteauth") # The unique GTK application identifier for this application. See: # https://wiki.gnome.org/HowDoI/ChooseApplicationID set(APPLICATION_ID "io.ente.auth") diff --git a/auth/linux/flutter/generated_plugin_registrant.cc b/auth/linux/flutter/generated_plugin_registrant.cc index 7b1c79935e..2fdf0b385a 100644 --- a/auth/linux/flutter/generated_plugin_registrant.cc +++ b/auth/linux/flutter/generated_plugin_registrant.cc @@ -6,7 +6,6 @@ #include "generated_plugin_registrant.h" -#include #include #include #include @@ -20,9 +19,6 @@ #include void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) desktop_webview_window_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopWebviewWindowPlugin"); - desktop_webview_window_plugin_register_with_registrar(desktop_webview_window_registrar); g_autoptr(FlPluginRegistrar) file_saver_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSaverPlugin"); file_saver_plugin_register_with_registrar(file_saver_registrar); diff --git a/auth/linux/flutter/generated_plugins.cmake b/auth/linux/flutter/generated_plugins.cmake index 45674067d7..7ad28f0761 100644 --- a/auth/linux/flutter/generated_plugins.cmake +++ b/auth/linux/flutter/generated_plugins.cmake @@ -3,7 +3,6 @@ # list(APPEND FLUTTER_PLUGIN_LIST - desktop_webview_window file_saver flutter_local_authentication flutter_secure_storage_linux diff --git a/auth/linux/packaging/appimage/make_config.yaml b/auth/linux/packaging/appimage/make_config.yaml index a41658fd17..8e88af9120 100644 --- a/auth/linux/packaging/appimage/make_config.yaml +++ b/auth/linux/packaging/appimage/make_config.yaml @@ -1,7 +1,8 @@ -display_name: Auth +display_name: Ente Auth +package_name: enteauth license: GPLv3 -metainfo: linux/packaging/ente_auth.appdata.xml +metainfo: linux/packaging/enteauth.appdata.xml icon: assets/icons/auth-icon.png @@ -25,10 +26,6 @@ startup_notify: false # # include: # - libcurl.so.4 -include: - - libffi.so.8 - - libtiff.so.5 - - libjpeg.so.8 supported_mime_type: - - x-scheme-handler/enteauth \ No newline at end of file + - x-scheme-handler/enteauth diff --git a/auth/linux/packaging/deb/make_config.yaml b/auth/linux/packaging/deb/make_config.yaml index 3ec44bae56..78022df17e 100644 --- a/auth/linux/packaging/deb/make_config.yaml +++ b/auth/linux/packaging/deb/make_config.yaml @@ -1,5 +1,7 @@ -display_name: Auth -package_name: auth +display_name: Ente Auth +package_name: enteauth +include_build_number: false + maintainer: name: Ente.io Developers email: auth@ente.io @@ -10,10 +12,9 @@ license: GPLv3 icon: assets/icons/auth-icon.png installed_size: 36000 -metainfo: linux/packaging/ente_auth.appdata.xml +metainfo: linux/packaging/enteauth.appdata.xml dependencies: - - libwebkit2gtk-4.0-37 - libsqlite3-0 - libsodium23 - libsecret-1-0 @@ -25,7 +26,7 @@ keywords: - Authentication - 2FA -generic_name: Ente Authentication +generic_name: Ente Authenticator categories: - Utility diff --git a/auth/linux/packaging/ente_auth.appdata.xml b/auth/linux/packaging/enteauth.appdata.xml similarity index 74% rename from auth/linux/packaging/ente_auth.appdata.xml rename to auth/linux/packaging/enteauth.appdata.xml index 5ef4c647f4..0772f405b8 100644 --- a/auth/linux/packaging/ente_auth.appdata.xml +++ b/auth/linux/packaging/enteauth.appdata.xml @@ -1,16 +1,16 @@ - ente_auth + enteauth CC0-1.0 AGPL-3.0 Ente Auth - Open source 2FA authenticator, with end-to-end encrypted backups + FOSS, cross-platform 2FA app

Auth provides end-to-end encrypted cloud backups so you don't have to worry about losing your tokens. Our cryptography has been externally audited.

Auth has an app for every platform. Mobile, desktop and web. Your codes sync across all your devices, end-to-end encrypted.

Auth also comes with Offline mode, tags, icons, pins, import/export and more

- ente_auth.desktop + enteauth.desktop https://ente.io/auth @@ -18,14 +18,18 @@ - + - ente_auth.desktop + enteauth.desktop Ente.io Developers auth@ente.io + + #ffffff + #000000 + \ No newline at end of file diff --git a/auth/linux/packaging/pacman/make_config.yaml b/auth/linux/packaging/pacman/make_config.yaml index 7545d8c06e..5ee05e2016 100644 --- a/auth/linux/packaging/pacman/make_config.yaml +++ b/auth/linux/packaging/pacman/make_config.yaml @@ -1,5 +1,5 @@ -display_name: Auth -package_name: auth +display_name: Ente Auth +package_name: enteauth maintainer: name: Ente.io Developers email: auth@ente.io @@ -8,29 +8,18 @@ licenses: icon: assets/icons/auth-icon.png installed_size: 36000 -metainfo: linux/packaging/ente_auth.appdata.xml +metainfo: linux/packaging/enteauth.appdata.xml dependencies: - - c-ares - - ffmpeg - - gtk3 - - http-parser - - libevent - - libvpx - - libxslt - - libxss - - minizip - - nss - - re2 - - snappy - - libnotify + - sqlite + - libsecret - libappindicator-gtk3 keywords: - Authentication - 2FA -generic_name: Ente Authentication +generic_name: Ente Authenticator categories: - Utility @@ -47,12 +36,12 @@ postinstall_scripts: postupgrade_scripts: - post_install - + postremove_scripts: - gtk-update-icon-cache -q -t -f usr/share/icons/hicolor - update-desktop-database -q - if [ -e /usr/lib/libsodium.so.23 ]; then - - rm /usr/lib/libsodium.so.23 + - rm /usr/lib/libsodium.so.23 - fi -startup_notify: false \ No newline at end of file +startup_notify: false diff --git a/auth/linux/packaging/rpm/make_config.yaml b/auth/linux/packaging/rpm/make_config.yaml index 6f6c45153a..8bd55438d5 100644 --- a/auth/linux/packaging/rpm/make_config.yaml +++ b/auth/linux/packaging/rpm/make_config.yaml @@ -6,15 +6,15 @@ packager: Ente.io Developers packagerEmail: auth@ente.io license: GPLv3 url: https://github.com/ente-io/ente +package_name: enteauth +include_build_number: false display_name: Auth -metainfo: linux/packaging/ente_auth.appdata.xml +metainfo: linux/packaging/enteauth.appdata.xml requires: - libsqlite3x - - webkit2gtk4.0 - - libsodium - libsecret - libappindicator @@ -22,7 +22,7 @@ keywords: - Authentication - 2FA -generic_name: Ente Authentication +generic_name: Ente Authenticator categories: - Utility diff --git a/auth/macos/Flutter/GeneratedPluginRegistrant.swift b/auth/macos/Flutter/GeneratedPluginRegistrant.swift index 5e814a187f..5c6cfc0c6d 100644 --- a/auth/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/auth/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,7 +7,6 @@ import Foundation import app_links import connectivity_plus -import desktop_webview_window import device_info_plus import file_saver import flutter_inappwebview_macos @@ -31,7 +30,6 @@ import window_manager func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin")) ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) - DesktopWebviewWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWebviewWindowPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) diff --git a/auth/pubspec.lock b/auth/pubspec.lock index 36fb338398..08ebc6efbd 100644 --- a/auth/pubspec.lock +++ b/auth/pubspec.lock @@ -326,15 +326,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.10" - desktop_webview_window: - dependency: "direct main" - description: - path: "packages/desktop_webview_window" - ref: main - resolved-ref: "3e4247ba5b71049704395b70b5a827fb113b88ea" - url: "https://github.com/MixinNetwork/flutter-plugins" - source: git - version: "0.2.4" device_info_plus: dependency: "direct main" description: @@ -879,7 +870,7 @@ packages: source: hosted version: "0.19.0" io: - dependency: transitive + dependency: "direct main" description: name: io sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" @@ -1821,7 +1812,7 @@ packages: source: hosted version: "0.4.2" xdg_directories: - dependency: transitive + dependency: "direct main" description: name: xdg_directories sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" diff --git a/auth/pubspec.yaml b/auth/pubspec.yaml index 34baa0e1b9..f94b46875a 100644 --- a/auth/pubspec.yaml +++ b/auth/pubspec.yaml @@ -1,6 +1,6 @@ name: ente_auth description: ente two-factor authenticator -version: 4.0.2+402 +version: 4.1.0+410 publish_to: none environment: @@ -19,11 +19,6 @@ dependencies: confetti: ^0.8.0 connectivity_plus: ^6.0.5 convert: ^3.1.1 - desktop_webview_window: - git: - url: https://github.com/MixinNetwork/flutter-plugins - ref: main - path: packages/desktop_webview_window device_info_plus: ^9.1.1 dio: ^5.4.0 dotted_border: ^2.0.0+2 @@ -67,6 +62,7 @@ dependencies: gradient_borders: ^1.0.0 http: ^1.1.0 intl: ^0.19.0 + io: ^1.0.4 json_annotation: ^4.5.0 local_auth: ^2.3.0 local_auth_android: ^1.0.37 @@ -105,6 +101,7 @@ dependencies: uuid: ^4.2.2 win32: ^5.1.1 window_manager: ^0.4.2 + xdg_directories: ^1.0.4 dependency_overrides: flutter_secure_storage_linux: diff --git a/auth/windows/flutter/generated_plugin_registrant.cc b/auth/windows/flutter/generated_plugin_registrant.cc index d4872e8b9c..bfed849740 100644 --- a/auth/windows/flutter/generated_plugin_registrant.cc +++ b/auth/windows/flutter/generated_plugin_registrant.cc @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -27,8 +26,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("AppLinksPluginCApi")); ConnectivityPlusWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); - DesktopWebviewWindowPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); FileSaverPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSaverPlugin")); FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar( diff --git a/auth/windows/flutter/generated_plugins.cmake b/auth/windows/flutter/generated_plugins.cmake index 598cf85d96..cc78f72ebb 100644 --- a/auth/windows/flutter/generated_plugins.cmake +++ b/auth/windows/flutter/generated_plugins.cmake @@ -5,7 +5,6 @@ list(APPEND FLUTTER_PLUGIN_LIST app_links connectivity_plus - desktop_webview_window file_saver flutter_inappwebview_windows flutter_local_authentication diff --git a/auth/windows/packaging/exe/make_config.yaml b/auth/windows/packaging/exe/make_config.yaml index 378d2d4d8c..efd1736446 100644 --- a/auth/windows/packaging/exe/make_config.yaml +++ b/auth/windows/packaging/exe/make_config.yaml @@ -1,4 +1,5 @@ app_id: 9E5F0C93-96A3-4DA9-AE52-1AA6339851FC +package_name: enteauth publisher: ente.io publisher_url: https://github.com/ente-io/ente display_name: Ente Auth diff --git a/cli/config.yaml.example b/cli/config.yaml.example index e6c605095a..a709e080ed 100644 --- a/cli/config.yaml.example +++ b/cli/config.yaml.example @@ -1,7 +1,7 @@ # You can put this configuration file in the following locations: # - $HOME/.ente/config.yaml # - config.yaml in the current working directory -# - $ENTE_CLI_CONFIG_PATH/config.yaml +# - $ENTE_CLI_CONFIG_DIR/config.yaml endpoint: api: "http://localhost:8080" diff --git a/cli/docs/selfhost.md b/cli/docs/selfhost.md index d38f0325a5..b4e7a33d88 100644 --- a/cli/docs/selfhost.md +++ b/cli/docs/selfhost.md @@ -1,8 +1,10 @@ + + ## Self Hosting If you are self-hosting the server, you can still configure CLI to export data & perform basic admin actions. To do this, first configure the CLI to point to your server. -Define a config.yaml and put it either in the same directory as CLI binary or path defined in env variable `ENTE_CLI_CONFIG_PATH` +Define a config.yaml and put it either in the same directory as CLI binary or path defined in env variable `ENTE_CLI_CONFIG_DIR` ```yaml endpoint: diff --git a/cli/main.go b/cli/main.go index 0ea9b7c833..7b0312485e 100644 --- a/cli/main.go +++ b/cli/main.go @@ -18,29 +18,29 @@ import ( var AppVersion = "0.2.2" func main() { - cliDBPath, err := GetCLIConfigPath() + cliConfigDir, err := GetCLIConfigDir() if secrets.IsRunningInContainer() { - cliDBPath = constants.CliDataPath - _, err := internal.ValidateDirForWrite(cliDBPath) + cliConfigDir = constants.CliDataPath + _, err := internal.ValidateDirForWrite(cliConfigDir) if err != nil { - log.Fatalf("Please mount a volume to %s\n%v\n", cliDBPath, err) + log.Fatalf("Please mount a volume to %s\n%v\n", cliConfigDir, err) } } if err != nil { log.Fatalf("Could not create cli config path\n%v\n", err) } - initConfig(cliDBPath) - newCliPath := fmt.Sprintf("%s/ente-cli.db", cliDBPath) - if !strings.HasPrefix(cliDBPath, "/") { - oldCliPath := fmt.Sprintf("%sente-cli.db", cliDBPath) + initConfig(cliConfigDir) + newCliDBPath := filepath.Join(cliConfigDir, "ente-cli.db") + if !strings.HasPrefix(cliConfigDir, "/") { + oldCliPath := fmt.Sprintf("%sente-cli.db", cliConfigDir) if _, err := os.Stat(oldCliPath); err == nil { - log.Printf("migrating old cli db from %s to %s\n", oldCliPath, newCliPath) - if err := os.Rename(oldCliPath, newCliPath); err != nil { + log.Printf("migrating old cli db from %s to %s\n", oldCliPath, newCliDBPath) + if err := os.Rename(oldCliPath, newCliDBPath); err != nil { log.Fatalf("Could not rename old cli db\n%v\n", err) } } } - db, err := pkg.GetDB(newCliPath) + db, err := pkg.GetDB(newCliDBPath) if err != nil { if strings.Contains(err.Error(), "timeout") { @@ -85,11 +85,11 @@ func main() { cmd.Execute(&ctrl, AppVersion) } -func initConfig(cliConfigPath string) { - viper.SetConfigName("config") // name of config file (without extension) - viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name - viper.AddConfigPath(cliConfigPath + "/") // path to look for the config file in - viper.AddConfigPath(".") // optionally look for config in the working directory +func initConfig(cliConfigDir string) { + viper.SetConfigName("config") // name of config file (without extension) + viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name + viper.AddConfigPath(cliConfigDir + "/") // path to look for the config file in + viper.AddConfigPath(".") // optionally look for config in the working directory viper.SetDefault("endpoint.api", constants.EnteApiUrl) viper.SetDefault("endpoint.accounts", constants.EnteAccountUrl) @@ -102,11 +102,19 @@ func initConfig(cliConfigPath string) { } } -// GetCLIConfigPath returns the path to the .ente-cli folder and creates it if it doesn't exist. -func GetCLIConfigPath() (string, error) { - if os.Getenv("ENTE_CLI_CONFIG_PATH") != "" { - return os.Getenv("ENTE_CLI_CONFIG_PATH"), nil +// GetCLIConfigDir returns the path to the .ente-cli folder and creates it if it doesn't exist. +func GetCLIConfigDir() (string, error) { + var configDir = os.Getenv("ENTE_CLI_CONFIG_DIR") + if configDir == "" { + // for backward compatibility, check for ENTE_CLI_CONFIG_PATH + configDir = os.Getenv("ENTE_CLI_CONFIG_PATH") } + if configDir != "" { + // remove trailing slash (for all OS) + configDir = strings.TrimSuffix(configDir, string(filepath.Separator)) + return configDir, nil + } + // Get the user's home directory homeDir, err := os.UserHomeDir() if err != nil { diff --git a/desktop/.github/workflows/desktop-release.yml b/desktop/.github/workflows/desktop-release.yml index fbaac39546..610b9343d4 100644 --- a/desktop/.github/workflows/desktop-release.yml +++ b/desktop/.github/workflows/desktop-release.yml @@ -88,7 +88,7 @@ jobs: if: startsWith(matrix.os, 'ubuntu') # See: # https://github.com/electron-userland/electron-builder/issues/4181 - run: sudo apt-get install libarchive-tools + run: sudo apt-get update && sudo apt-get install libarchive-tools - name: Build uses: ente-io/action-electron-builder@eff78a1d33bdab4c54ede0e5cdc71e0c2cf803e2 diff --git a/desktop/CHANGELOG.md b/desktop/CHANGELOG.md index 11a4314f95..e544b644b1 100644 --- a/desktop/CHANGELOG.md +++ b/desktop/CHANGELOG.md @@ -1,11 +1,17 @@ # CHANGELOG -## v1.7.6 (Unreleased) +## v1.7.7 (Unreleased) -- Parse description from metadata JSON. -- Support Italian and Lithuanian translations. +- Retain JPEG originals even on date modifications. - . +## v1.7.6 + +- Face merging and suggestions (beta). +- Parse description from metadata JSON. +- Support Italian, Ukrainian and Lithuanian translations. +- Fix an out of memory crash on uploading large libraries. + ## v1.7.5 - Face grouping (beta). diff --git a/desktop/package.json b/desktop/package.json index 683d74a2db..675262d52c 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -1,6 +1,6 @@ { "name": "ente", - "version": "1.7.6-beta", + "version": "1.7.7-beta", "private": true, "description": "Desktop client for Ente Photos", "repository": "github:ente-io/photos-desktop", @@ -48,7 +48,7 @@ "ajv": "^8.17.1", "concurrently": "^8.2.2", "cross-env": "^7.0.3", - "electron": "^30.4.0", + "electron": "^33.0.2", "electron-builder": "^25.0.5", "eslint": "^9", "prettier": "^3.3.3", diff --git a/desktop/yarn.lock b/desktop/yarn.lock index 2d3b6f6a00..ec40989c38 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -1282,10 +1282,10 @@ electron-updater@^6.3.4: semver "^7.6.3" tiny-typed-emitter "^2.1.0" -electron@^30.4.0: - version "30.4.0" - resolved "https://registry.yarnpkg.com/electron/-/electron-30.4.0.tgz#66641a644059147f0e597e49999599e23dcdbfe3" - integrity sha512-ric3KLPQ9anXYjtTDkj5NbEcXZqRUwqxrxTviIjLdMdHqd5O+hkSHEzXgbSJUOt+7uw+zZuybn9+IM9y7iEpqg== +electron@^33.0.2: + version "33.0.2" + resolved "https://registry.yarnpkg.com/electron/-/electron-33.0.2.tgz#db31b105bf0edd7c8600dfb70c2dfc214e3789f1" + integrity sha512-C2WksfP0COsMHbYXSJG68j6S3TjuGDrw/YT42B526yXalIlNQZ2GeAYKryg6AEMkIp3p8TUfDRD0+HyiyCt/nw== dependencies: "@electron/get" "^2.0.0" "@types/node" "^20.9.0" diff --git a/docs/docs/.vitepress/sidebar.ts b/docs/docs/.vitepress/sidebar.ts index 9078bce2e7..2cf669976f 100644 --- a/docs/docs/.vitepress/sidebar.ts +++ b/docs/docs/.vitepress/sidebar.ts @@ -227,10 +227,11 @@ export const sidebar = [ collapsed: true, items: [ { text: "Getting started", link: "/self-hosting/" }, + { text: "System requirements", link: "/self-hosting/guides/system-requirements", }, { text: "Guides", items: [ - { text: "Introduction", link: "/self-hosting/guides/" }, + { text: "Introduction", link: "/self-hosting/guides/" }, { text: "Connect to custom server", link: "/self-hosting/guides/custom-server/", @@ -248,10 +249,6 @@ export const sidebar = [ text: "Mobile build", link: "/self-hosting/guides/mobile-build", }, - { - text: "System requirements", - link: "/self-hosting/guides/system-requirements", - }, { text: "Configuring S3", link: "/self-hosting/guides/configuring-s3", @@ -264,6 +261,10 @@ export const sidebar = [ text: "DB migration", link: "/self-hosting/guides/db-migration", }, + { + text: "Hosting Ente without Docker", + link: "/self-hosting/guides/standalone-ente", + }, ], }, { @@ -295,6 +296,10 @@ export const sidebar = [ text: "Yarn", link: "/self-hosting/troubleshooting/yarn", }, + { + text: "Ente CLI Secrets", + link: "/self-hosting/troubleshooting/keyring", + }, ], }, ], diff --git a/docs/docs/photos/faq/machine-learning.md b/docs/docs/photos/faq/machine-learning.md index 919ec748a5..53bf5ca558 100644 --- a/docs/docs/photos/faq/machine-learning.md +++ b/docs/docs/photos/faq/machine-learning.md @@ -24,8 +24,10 @@ De-merging a certain grouping can be done by going to the person, pressing ### Desktop -Note that while desktop supports naming a person, it currently does not yet -support merging persons. This will be added soon. +Similarly, on desktop you can use the "Add a name" button to merge people by +selecting an existing person, and use the "Review suggestions" sheet to de-merge +previously merged persons (click the top right history icon on the suggestion +sheet to see the previous merges, and if necessary, undo them). ## How do I change the cover for a recognized person? @@ -56,7 +58,10 @@ person**. This will take you to the grouping of this person. Here you can press ### Desktop -This is currently not yet supported on desktop, but will be added soon. +Similarly, on desktop, you use the "Ignore" option from the top right menu to +ignore a particular face group (If you already give them a name, "Reset person" +first). And to undo this action, open that person (via the file info of a photo +containing that person), and select "Show person". ## How well does the app handle photos of babies? @@ -70,4 +75,4 @@ If you find a mixed grouping of several different babies, you can use the option will make the model re-evaluate the grouping with stricter settings, hopefully separating the different babies in different new groupings. -Please note this functionality is currently only available on mobile. +Please note this functionality is currently only available on mobile. diff --git a/docs/docs/photos/faq/photo-dates.md b/docs/docs/photos/faq/photo-dates.md index 10710caa80..1918093dc7 100644 --- a/docs/docs/photos/faq/photo-dates.md +++ b/docs/docs/photos/faq/photo-dates.md @@ -64,12 +64,14 @@ videos that you imported. The modifications (e.g. date changes) you make within Ente will be written into a separate metadata JSON file during export so as to not modify the original. -> There is one exception to this. For JPEG files, the Exif DateTimeOriginal is -> changed during export from web or desktop apps. This was done on a customer -> request, but in hindsight this has been an incorrect move. We are going to -> deprecate this behavior, and will instead provide separate tools (or -> functionality within the app itself) for customers who intentionally wish to -> modify their originals to reflect the associated metadata JSON. +> [!WARNING] +> +> There used to be one exception to this - for JPEG files, the Exif +> DateTimeOriginal was changed during export from web or desktop apps. This was +> done on a customer request, but in hindsight this was an incorrect change. +> +> We have deprecated this behaviour, and the desktop version 1.7.6 is going to +> be the last version with this exception. As an example: suppose you have `flower.png`. When you export your library, you will end up with: @@ -81,13 +83,36 @@ 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 +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. +Here is a sample of how the JSON would look: + +```json +{ + "description": "This will be imported as the caption", + "creationTime": { + "timestamp": "1613532136", + "formatted": "17 Feb 2021, 03:22:16 UTC" + }, + "modificationTime": { + "timestamp": "1640225957", + "formatted": "23 Dec 2021, 02:19:17 UTC" + }, + "geoData": { + "latitude": 12.004170700000001, + "longitude": 79.8013945 + } +} +``` + +`photoTakenTime` will be considered as an alias for `creationTime`, and +`geoDataExif` will be considered as a fallback for `geoData`. + ### File creation time. The photo's data will be preserved verbatim, however when it is written out to diff --git a/docs/docs/photos/features/albums.md b/docs/docs/photos/features/albums.md index 2163efde38..bc010f4150 100644 --- a/docs/docs/photos/features/albums.md +++ b/docs/docs/photos/features/albums.md @@ -48,6 +48,10 @@ albums**. result in the creation of a new album – empty folders (or folders that only contain other folders) will be ignored. +- In separate album mode, only the leafmost folder name is considered. For + example, both `A/B/C/D/x.png` and `1/2/3/D/y.png` will get uploaded into the + same Ente album named "D". + > [!NOTE] > > Ente albums cannot be nested currently. That is, in the **separate album** diff --git a/docs/docs/self-hosting/guides/standalone-ente.md b/docs/docs/self-hosting/guides/standalone-ente.md new file mode 100644 index 0000000000..e5c219f316 --- /dev/null +++ b/docs/docs/self-hosting/guides/standalone-ente.md @@ -0,0 +1,104 @@ +--- +title: Installing Ente Standalone (without Docker) +description: Installing and setting up Ente standalone without docker. +--- + +# Installing and Deploying Ente Standalone (without Docker) + +## Running Museum (Ente's server) without Docker + +First, start by installing all the dependencies to get your machine ready for development. + +```sh +# For MacOS +brew tap homebrew/core +brew update +brew install go + +# For Ubuntu based distros +sudo apt update && sudo apt upgrade +sudo apt install golang-go +``` + +Alternatively, you can also download the latest binaries from ['All Release'](https://go.dev/dl/) page from the official website. + +```sh +brew install postgres@15 +# Link the postgres keg +brew link postgresql@15 + +brew install libsodium + +# For Ubuntu based distros +sudo apt install postgresql +sudo apt install libsodium23 libsodium-dev +``` + +The package `libsodium23` might be installed already in some cases. + +Installing pkg-config + +```sh +brew install pkg-config + +# For Ubuntu based distros +sudo apt install pkg-config +``` + +## Starting Postgres + +### With pg_ctl + +```sh +pg_ctl -D /usr/local/var/postgres -l logfile start +``` + +Dependeing on the Operating System type the path for postgres binary or configuration file might be different, please check if the command keeps failing for you. + +Ideally, if you are on a Linux system with systemd as the init. You can also start postgres as a systemd service. After Installation execute the following commands: + +```sh +sudo systemctl enable postgresql +sudo systemctl daemon-reload && sudo systemctl start postgresql +``` + +### Create user + +```sh +createuser -s postgres +``` + +## Start Museum + +Start by cloning ente to your system. + +```sh +git clone https://github.com/ente-io/ente +``` + +```sh +export ENTE_DB_USER=postgres +cd ente/server +go run cmd/museum/main.go +``` + +You can also add the export line to your shell's RC file, to avoid exporting the environment variable every time. + +For live reloads, install [air](https://github.com/air-verse/air#installation). Then you can just call air after declaring the required environment variables. For example, + +```sh +ENTE_DB_USER=postgres +air +``` + +## Museum as a background service + +Please check the below links if you want to run Museum as a service, both of them are battle tested. + +1. [How to run museum as a systemd service](https://gist.github.com/mngshm/a0edb097c91d1dc45aeed755af310323) +2. [Museum.service](https://github.com/ente-io/ente/blob/23e678889189157ecc389c258267685934b83631/server/scripts/deploy/museum.service#L4) + +Once you are done with setting and running Museum, all you are left to do is run the web app and reverse_proxy it with a webserver. You can check the following resources for Deploying your web app. + +1. [Hosting the Web App](https://help.ente.io/self-hosting/guides/web-app). +2. [Running Ente Web app as a systemd Service](https://gist.github.com/mngshm/72e32bd483c2129621ed0d74412492fd) diff --git a/docs/docs/self-hosting/troubleshooting/keyring.md b/docs/docs/self-hosting/troubleshooting/keyring.md new file mode 100644 index 0000000000..066c2574d1 --- /dev/null +++ b/docs/docs/self-hosting/troubleshooting/keyring.md @@ -0,0 +1,32 @@ +--- +title: Ente CLI Secrets +description: A quick hotfix for keyring errors while running Ente CLI. +--- + +# Ente CLI Secrets + +Ente CLI makes use of keyring for storing sensitive information +like your passwords. And running the cli straight out of the +box might give you some errors related to keyrings in some case. + +Follow the below steps to run Ente CLI and also avoid keyrings errors. + +- Create a secrets.txt file and save your user password inside it. + +```sh +# export the secrets path + +export ENTE_CLI_SECRETS_PATH=./ + +./ente-cli +``` + +And you are good to go. + +- You can also add the above line to your shell's rc file, to not +having to export it manually every time. + +## Ref + +- [Ente CLI Secrets Path](https://www.reddit.com/r/selfhosted/comments/1gc09il/comment/lu2hox2/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button) +- [Keyrings](https://man7.org/linux/man-pages/man7/keyrings.7.html) diff --git a/infra/docs/remote-desktop.md b/infra/docs/remote-desktop.md new file mode 100644 index 0000000000..ae2ccec7d5 --- /dev/null +++ b/infra/docs/remote-desktop.md @@ -0,0 +1,32 @@ +## Setting up a remote desktop + +This is handy, e.g., when creating test environments with large disks, where we +still need a graphical session to run the desktop app. + +Create a normal Ubuntu instance (tweak the exact commands if using a different +distro). + +Install + +- **Xfce4** - The desktop environment +- **xorg** - An X server +- **xrdp** - A remote desktop protocol (RDP) server. + +```sh +sudo apt install xfce4 xorg xrdp +``` + +Configure xrdp to use Xfce + +```sh +echo xfce4-session > ~/.xsession +``` + +Start the xrdp service, and also enable it so that it starts on boot + +```sh +sudo systemctl enable xrdp +sudo systemctl start xrdp +``` + +On macOS, install a RDP client, e.g. [Microsoft Remote Desktop](https://apps.apple.com/us/app/microsoft-remote-desktop/id1295203466). diff --git a/infra/workers/data-puller/package.json b/infra/workers/data-puller/package.json new file mode 100644 index 0000000000..183b2b6bf1 --- /dev/null +++ b/infra/workers/data-puller/package.json @@ -0,0 +1,5 @@ +{ + "name": "data-puller", + "version": "0.0.0", + "private": true +} diff --git a/infra/workers/data-puller/src/index.ts b/infra/workers/data-puller/src/index.ts new file mode 100644 index 0000000000..38cdad000d --- /dev/null +++ b/infra/workers/data-puller/src/index.ts @@ -0,0 +1,30 @@ +/** + * Proxy requests for downloading files from object storage. + * + * Used by museum when replicating. + */ + +export default { + async fetch(request: Request) { + switch (request.method) { + case "GET": + return handleGET(request); + default: + console.log(`Unsupported HTTP method ${request.method}`); + return new Response(null, { status: 405 }); + } + }, +} satisfies ExportedHandler; + +const handleGET = async (request: Request) => { + const url = new URL(request.url); + + // Random bots keep trying to pentest causing noise in the logs. If the + // request doesn't have a src, we can just safely ignore it. + const src = url.searchParams.get("src"); + if (!src) return new Response(null, { status: 400 }); + + const source = atob(src); + + return fetch(source); +}; diff --git a/infra/workers/data-puller/tsconfig.json b/infra/workers/data-puller/tsconfig.json new file mode 100644 index 0000000000..a65b752070 --- /dev/null +++ b/infra/workers/data-puller/tsconfig.json @@ -0,0 +1 @@ +{ "extends": "../tsconfig.base.json", "include": ["src"] } diff --git a/infra/workers/data-puller/wrangler.toml b/infra/workers/data-puller/wrangler.toml new file mode 100644 index 0000000000..7c254ec480 --- /dev/null +++ b/infra/workers/data-puller/wrangler.toml @@ -0,0 +1,5 @@ +name = "data-puller" +main = "src/index.ts" +compatibility_date = "2024-06-14" + +tail_consumers = [{ service = "tail" }] diff --git a/mobile/fastlane/metadata/android/lt/full_description.txt b/mobile/fastlane/metadata/android/lt/full_description.txt new file mode 100644 index 0000000000..09b1f11399 --- /dev/null +++ b/mobile/fastlane/metadata/android/lt/full_description.txt @@ -0,0 +1,36 @@ +„ente“ – tai paprasta programa, skirta kurti atsargines kopijas ir bendrinti nuotraukas bei vaizdo įrašus. + +Jei ieškojote privatumą užtikrinančios alternatyvos „Google“ nuotraukoms, atsidūrėte tinkamoje vietoje. Su „ente“ jie saugomi visapusiu šifravimu (e2ee). Tai reiškia, kad tik jūs galite juos peržiūrėti. + +Turime atvirojo kodo „Android“, „iOS“, interneto ir darbalaukio programų, o jūsų nuotraukos bus sklandžiai sinchronizuojamos tarp visų įrenginių visapusiu šifravimo būdu (e2ee). + +„ente“ taip pat leidžia lengvai bendrinti albumus su artimaisiais, net jei jie nesinaudoja „ente“. Galite bendrinti viešai matomas nuorodas, kad jie galėtų peržiūrėti jūsų albumą ir bendradarbiauti pridėdami į jį nuotraukų, net ir neturėdami paskyros ar programos. + +Jūsų užšifruoti duomenys replikuojami į 3 skirtingas vietas, įskaitant slėptuvę nuo kritulių Paryžiuje. Mes rimtai žiūrime į palikimą ir pasirūpiname, kad jūsų prisiminimai išliktų gyvi. + +Esame čia tam, kad sukurtume saugiausią nuotraukų programą, prisijunkite prie mūsų kelionės! + +FUNKCIJOS +– Originalios kokybės atsarginės kopijos, nes kiekvienas taškelis yra svarbus +– Šeimos planai, kad galėtumėte dalytis saugykla su šeima +– Bendradarbiavimo albumai, kad po kelionės galėtumėte sujungti nuotraukas +– Bendrinami aplankai, jei norite, kad partneris galėtų mėgautis jūsų „fotoaparato“ paspaudimais +– Albumo nuorodos, kurias galima apsaugoti slaptažodžiu +– Galimybė atlaisvinti vietą, pašalinant saugiai atsargines kopijas sukūrusius failus +– Žmonių palaikymas, nes esate to verti +– Aprašymai, kad galėtumėte žymėti savo prisiminimus ir lengvai juos surasti +– Vaizdų rengyklė, kad būtų galima pridėti baigiamuosius akcentus +– Mėgkite, slėpkite ir išgyvenkite savo prisiminimus, juk jie brangūs +– Vienu spustelėjimu importuokite iš „Google“, „Apple“, kietojo disko ir kitų +– Tamsi tema, nes jūsų nuotraukos joje atrodo gerai +– 2FA, 3FA, biometrinis tapatybės nustatymas +– ir DAR daugiau! + +LEIDIMAI +„ente“ prašo tam tikrų leidimų, kad galėtų atlikti nuotraukų saugyklos paslaugų teikėjo funkcijas, kurias galima peržiūrėti čia: https://github.com/ente-io/ente/blob/f-droid/mobile/android/permissions.md + +KAINODARA +Nesiūlome amžinai nemokamų planų, nes mums svarbu, kad išliktume tvarūs ir atlaikytume laiko išbandymą. Vietoj to siūlome nebrangius planus, kuriais galite laisvai dalytis su savo šeima. Daugiau informacijos galima rasti svetainėje ente.io. + +PALAIKYMAS +Didžiuojamės galėdami pasiūlyti žmogiškąją pagalbą. Jei esate mūsų mokamas klientas, galite susisiekti adresu team@ente.io ir tikėtis mūsų komandos atsakymo per 24 valandas. diff --git a/mobile/fastlane/metadata/android/lt/short_description.txt b/mobile/fastlane/metadata/android/lt/short_description.txt new file mode 100644 index 0000000000..5162c6b919 --- /dev/null +++ b/mobile/fastlane/metadata/android/lt/short_description.txt @@ -0,0 +1 @@ +„ente“ – tai visapusiškai užšifruota nuotraukų saugyklos programa \ No newline at end of file diff --git a/mobile/fastlane/metadata/android/lt/title.txt b/mobile/fastlane/metadata/android/lt/title.txt new file mode 100644 index 0000000000..047931d593 --- /dev/null +++ b/mobile/fastlane/metadata/android/lt/title.txt @@ -0,0 +1 @@ +„ente“: užšifruota nuotraukų saugykla \ No newline at end of file diff --git a/mobile/fastlane/metadata/ios/lt/description.txt b/mobile/fastlane/metadata/ios/lt/description.txt new file mode 100644 index 0000000000..73464e32c3 --- /dev/null +++ b/mobile/fastlane/metadata/ios/lt/description.txt @@ -0,0 +1,33 @@ +„Ente“ – tai paprasta programa, skirta automatiškai kurti atsargines kopijas ir tvarkyti nuotraukas bei vaizdo įrašus. + +Jei ieškojote privatumą užtikrinančios alternatyvos savo prisiminimams išsaugoti, atsidūrėte tinkamoje vietoje. Su „Ente“ jie saugomi visapusiu šifravimu (e2ee). Tai reiškia, kad tik jūs galite juos peržiūrėti. + +Turime programų visoms platformoms, o jūsų nuotraukos bus sklandžiai sinchronizuojamos tarp visų jūsų įrenginių visapusiu šifravimo būdu (e2ee). + +„Ente“ taip pat leidžia lengvai bendrinti albumus su artimaisiais. Galite bendrinti juos tiesiogiai su kitais „Ente“ naudotojais visapusiškai užšifruotus arba su viešai matomomis nuorodomis. + +Jūsų užšifruoti duomenys saugomi įvairiose vietose, įskaitant Paryžiuje esančią slėptuvę nuo kritulių. Mes rimtai žiūrime į palikimą ir pasirūpiname, kad jūsų prisiminimai išliktų gyvi. + +Esame čia tam, kad sukurtume saugiausią nuotraukų programą, prisijunkite prie mūsų kelionės! + +FUNKCIJOS +– Originalios kokybės atsarginės kopijos, nes kiekvienas taškelis yra svarbus +– Šeimos planai, kad galėtumėte dalytis saugykla su šeima +– Bendrinami aplankai, jei norite, kad partneris galėtų mėgautis jūsų „fotoaparato“ paspaudimais +– Albumo nuorodos, kurias galima apsaugoti slaptažodžiu ir nustatyti jų galiojimo laiką +– Galimybė atlaisvinti vietą, pašalinant saugiai atsargines kopijas sukūrusius failus +– Vaizdų rengyklė, kad būtų galima pridėti baigiamuosius akcentus +– Mėgkite, slėpkite ir išgyvenkite savo prisiminimus, juk jie brangūs +– Vienu spustelėjimu importuokite iš visų pagrindinių saugyklų teikėjų +– Tamsi tema, nes jūsų nuotraukos joje atrodo gerai +– 2FA, 3FA, biometrinis tapatybės nustatymas +– ir DAR daugiau! + +KAINODARA +Nesiūlome amžinai nemokamų planų, nes mums svarbu, kad išliktume tvarūs ir atlaikytume laiko išbandymą. Vietoj to siūlome nebrangius planus, kuriais galite laisvai dalytis su savo šeima. Daugiau informacijos galima rasti svetainėje ente.io. + +PALAIKYMAS +Didžiuojamės galėdami pasiūlyti žmogiškąją pagalbą. Jei esate mūsų mokamas klientas, galite susisiekti adresu team@ente.io ir tikėtis mūsų komandos atsakymo per 24 valandas. + +SĄLYGOS +https://ente.io/terms diff --git a/mobile/fastlane/metadata/playstore/lt/full_description.txt b/mobile/fastlane/metadata/playstore/lt/full_description.txt new file mode 100644 index 0000000000..ecf818aaa5 --- /dev/null +++ b/mobile/fastlane/metadata/playstore/lt/full_description.txt @@ -0,0 +1,30 @@ +„Ente“ – tai paprasta programa, skirta automatiškai kurti atsargines kopijas ir tvarkyti nuotraukas bei vaizdo įrašus. + +Jei ieškojote privatumą užtikrinančios alternatyvos savo prisiminimams išsaugoti, atsidūrėte tinkamoje vietoje. Su „Ente“ jie saugomi visapusiu šifravimu (e2ee). Tai reiškia, kad tik jūs galite juos peržiūrėti. + +Turime „Android“, „iOS“, interneto ir darbalaukio programų, o jūsų nuotraukos bus sklandžiai sinchronizuojamos tarp visų jūsų įrenginių visapusiu šifravimo būdu (e2ee). + +„Ente“ taip pat leidžia lengvai bendrinti albumus su artimaisiais. Galite bendrinti juos tiesiogiai su kitais „Ente“ naudotojais visapusiškai užšifruotus arba su viešai matomomis nuorodomis. + +Jūsų užšifruoti duomenys saugomi įvairiose vietose, įskaitant Paryžiuje esančią slėptuvę nuo kritulių. Mes rimtai žiūrime į palikimą ir pasirūpiname, kad jūsų prisiminimai išliktų gyvi. + +Esame čia tam, kad sukurtume saugiausią nuotraukų programą, prisijunkite prie mūsų kelionės! + +✨ FUNKCIJOS +– Originalios kokybės atsarginės kopijos, nes kiekvienas taškelis yra svarbus +– Šeimos planai, kad galėtumėte dalytis saugykla su šeima +– Bendrinami aplankai, jei norite, kad partneris galėtų mėgautis jūsų „fotoaparato“ paspaudimais +– Albumo nuorodos, kurias galima apsaugoti slaptažodžiu ir nustatyti jų galiojimo laiką +– Galimybė atlaisvinti vietą, pašalinant saugiai atsargines kopijas sukūrusius failus +– Vaizdų rengyklė, kad būtų galima pridėti baigiamuosius akcentus +– Mėgkite, slėpkite ir išgyvenkite savo prisiminimus, juk jie brangūs +– Vienu spustelėjimu importuokite iš visų pagrindinių saugyklų teikėjų +– Tamsi tema, nes jūsų nuotraukos joje atrodo gerai +– 2FA, 3FA, biometrinis tapatybės nustatymas +– ir DAR daugiau! + +💲 KAINODARA +Nesiūlome amžinai nemokamų planų, nes mums svarbu, kad išliktume tvarūs ir atlaikytume laiko išbandymą. Vietoj to siūlome nebrangius planus, kuriais galite laisvai dalytis su savo šeima. Daugiau informacijos galima rasti svetainėje ente.io. + +🙋 PALAIKYMAS +Didžiuojamės galėdami pasiūlyti žmogiškąją pagalbą. Jei esate mūsų mokamas klientas, galite susisiekti adresu team@ente.io ir tikėtis mūsų komandos atsakymo per 24 valandas. \ No newline at end of file diff --git a/mobile/lib/core/constants.dart b/mobile/lib/core/constants.dart index 9060f2329a..9f9a6ac15c 100644 --- a/mobile/lib/core/constants.dart +++ b/mobile/lib/core/constants.dart @@ -107,3 +107,6 @@ const uploadTempFilePrefix = "upload_file_"; final tempDirCleanUpInterval = kDebugMode ? const Duration(seconds: 30).inMicroseconds : const Duration(hours: 6).inMicroseconds; + +const kFilterChipHeight = 32.0; +const kMaxAppbarFilters = 14; diff --git a/mobile/lib/db/files_db.dart b/mobile/lib/db/files_db.dart index ebcc40bc8e..8f336a6394 100644 --- a/mobile/lib/db/files_db.dart +++ b/mobile/lib/db/files_db.dart @@ -1492,7 +1492,7 @@ class FilesDB { return rows.isNotEmpty; } - Future> getFilesFromIDs(List ids) async { + Future> getFileIDToFileFromIDs(List ids) async { final result = {}; if (ids.isEmpty) { return result; @@ -1513,6 +1513,34 @@ class FilesDB { return result; } + Future> getFilesFromIDs( + List ids, { + bool asc = false, + bool dedupeByUploadId = false, + Set collectionsToIgnore = const {}, + }) async { + final order = (asc ? 'ASC' : 'DESC'); + if (ids.isEmpty) { + return []; + } + + final inParam = ids.map((id) => "'$id'").join(','); + final db = await instance.sqliteAsyncDB; + final results = await db.getAll( + 'SELECT * FROM $filesTable WHERE $columnUploadedFileID IN ($inParam) ORDER BY $columnCreationTime $order', + ); + final files = convertToFiles(results); + final result = await applyDBFilters( + files, + DBFilterOptions( + ignoredCollectionIDs: collectionsToIgnore, + dedupeUploadID: dedupeByUploadId, + ), + ); + + return result; + } + Future> getFilesFromGeneratedIDs(List ids) async { final result = {}; if (ids.isEmpty) { @@ -1578,6 +1606,26 @@ class FilesDB { return collectionIDsOfFile; } + ///Each collectionIDs in list aren't necessarily unique + Future> getAllCollectionIDsOfFiles( + List uploadedFileIDs, + ) async { + final db = await instance.sqliteAsyncDB; + final inParam = uploadedFileIDs.join(','); + + final results = await db.getAll( + ''' + SELECT $columnCollectionID FROM $filesTable + WHERE $columnUploadedFileID IN ($inParam) AND $columnCollectionID != -1 + ''', + ); + final collectionIDsOfFiles = []; + for (var result in results) { + collectionIDsOfFiles.add(result['collection_id'] as int); + } + return collectionIDsOfFiles; + } + List convertToFilesForIsolate(Map args) { final List files = []; for (final result in args["result"]) { diff --git a/mobile/lib/db/ml/clip_db.dart b/mobile/lib/db/ml/clip_db.dart index 3ac64477ec..555f9684d4 100644 --- a/mobile/lib/db/ml/clip_db.dart +++ b/mobile/lib/db/ml/clip_db.dart @@ -11,14 +11,6 @@ import "package:photos/models/ml/ml_versions.dart"; import "package:photos/models/ml/vector.dart"; extension ClipDB on MLDataDB { - static const databaseName = "ente.embeddings.db"; - - Future> getAllClipEmbeddings() async { - final db = await MLDataDB.instance.asyncDB; - final results = await db.getAll('SELECT * FROM $clipTable'); - return _convertToEmbeddings(results); - } - Future> getAllClipVectors() async { Logger("ClipDB").info("reading all embeddings from DB"); final db = await MLDataDB.instance.asyncDB; @@ -82,16 +74,6 @@ extension ClipDB on MLDataDB { Bus.instance.fire(EmbeddingUpdatedEvent()); } - List _convertToEmbeddings(List> results) { - final List embeddings = []; - for (final result in results) { - final embedding = _getEmbeddingFromRow(result); - if (embedding.isEmpty) continue; - embeddings.add(embedding); - } - return embeddings; - } - List _convertToVectors(List> results) { final List embeddings = []; for (final result in results) { @@ -102,14 +84,6 @@ extension ClipDB on MLDataDB { return embeddings; } - ClipEmbedding _getEmbeddingFromRow(Map row) { - final fileID = row[fileIDColumn] as int; - final bytes = row[embeddingColumn] as Uint8List; - final version = row[mlVersionColumn] as int; - final list = Float32List.view(bytes.buffer); - return ClipEmbedding(fileID: fileID, embedding: list, version: version); - } - EmbeddingVector _getVectorFromRow(Map row) { final fileID = row[fileIDColumn] as int; final bytes = row[embeddingColumn] as Uint8List; diff --git a/mobile/lib/db/ml/db.dart b/mobile/lib/db/ml/db.dart index 89c4860506..6ed5b85e3c 100644 --- a/mobile/lib/db/ml/db.dart +++ b/mobile/lib/db/ml/db.dart @@ -46,6 +46,7 @@ class MLDataDB { createNotPersonFeedbackTable, fcClusterIDIndex, createClipEmbeddingsTable, + createFileDataTable, ]; // only have a single app-wide reference to the database @@ -228,6 +229,15 @@ class MLDataDB { return maps.map((e) => e[clusterIDColumn] as String).toSet(); } + Future> getPersonsClusterIDs(List personID) async { + final db = await instance.asyncDB; + final inParam = personID.map((e) => "'$e'").join(','); + final List> maps = await db.getAll( + 'SELECT $clusterIDColumn FROM $clusterPersonTable WHERE $personIdColumn IN ($inParam)', + ); + return maps.map((e) => e[clusterIDColumn] as String).toSet(); + } + Future clearTable() async { final db = await instance.asyncDB; @@ -237,6 +247,7 @@ class MLDataDB { await db.execute(deleteClusterSummaryTable); await db.execute(deleteNotPersonFeedbackTable); await db.execute(deleteClipEmbeddingsTable); + await db.execute(deleteFileDataTable); } Future> getFaceEmbeddingsForCluster( @@ -983,4 +994,63 @@ class MLDataDB { _logger.severe('Error dropping feedback tables', e); } } + + Future> getFileIDsOfPersonID(String personID) async { + final db = await instance.asyncDB; + final result = await db.getAll( + ''' + SELECT DISTINCT $facesTable.$fileIDColumn + FROM $clusterPersonTable + JOIN $faceClustersTable ON $clusterPersonTable.$clusterIDColumn = $faceClustersTable.$clusterIDColumn + JOIN $facesTable ON $faceClustersTable.$faceIDColumn = $facesTable.$faceIDColumn + WHERE $clusterPersonTable.$personIdColumn = ? + ''', + [personID], + ); + + return [for (final row in result) row[fileIDColumn]]; + } + + Future> getFileIDsOfClusterID(String clusterID) async { + final db = await instance.asyncDB; + final result = await db.getAll( + ''' + SELECT DISTINCT $facesTable.$fileIDColumn + FROM $faceClustersTable + JOIN $facesTable ON $faceClustersTable.$faceIDColumn = $facesTable.$faceIDColumn + WHERE $faceClustersTable.$clusterIDColumn = ? + ''', + [clusterID], + ); + + return [for (final row in result) row[fileIDColumn]]; + } + + Future> getAllFileIDsOfFaceIDsNotInAnyCluster() async { + final db = await instance.asyncDB; + final result = await db.getAll( + ''' + SELECT DISTINCT file_id + FROM faces + LEFT JOIN face_clusters ON faces.face_id = face_clusters.face_id + WHERE face_clusters.face_id IS NULL; + ''', + ); + return {for (final row in result) row[fileIDColumn]}; + } + + Future> getAllFilesAssociatedWithAllClusters({ + List? exceptClusters, + }) async { + final notInParam = exceptClusters?.map((e) => "'$e'").join(',') ?? ''; + final db = await instance.asyncDB; + final result = await db.getAll(''' + SELECT DISTINCT $facesTable.$fileIDColumn + FROM $facesTable + JOIN $faceClustersTable on $faceClustersTable.$faceIDColumn = $facesTable.$faceIDColumn + WHERE $faceClustersTable.$clusterIDColumn NOT IN ($notInParam); + '''); + + return {for (final row in result) row[fileIDColumn]}; + } } diff --git a/mobile/lib/db/ml/db_fields.dart b/mobile/lib/db/ml/db_fields.dart index 7a3a9d7631..06f30ae9fd 100644 --- a/mobile/lib/db/ml/db_fields.dart +++ b/mobile/lib/db/ml/db_fields.dart @@ -106,3 +106,19 @@ CREATE TABLE IF NOT EXISTS $clipTable ( '''; const deleteClipEmbeddingsTable = 'DELETE FROM $clipTable'; + +const fileDataTable = 'filedata'; +const createFileDataTable = ''' +CREATE TABLE IF NOT EXISTS $fileDataTable ( + $fileIDColumn INTEGER NOT NULL, + user_id INTEGER NOT NULL, + type TEXT NOT NULL, + size INTEGER NOT NULL, + obj_id TEXT, + obj_nonce TEXT, + updated_at INTEGER NOT NULL, + PRIMARY KEY ($fileIDColumn, type) + ); +'''; + +const deleteFileDataTable = 'DELETE FROM $fileDataTable'; diff --git a/mobile/lib/db/ml/filedata.dart b/mobile/lib/db/ml/filedata.dart new file mode 100644 index 0000000000..477aca8b40 --- /dev/null +++ b/mobile/lib/db/ml/filedata.dart @@ -0,0 +1,34 @@ +import "package:photos/db/ml/db.dart"; +import "package:photos/db/ml/db_fields.dart"; +import "package:photos/services/filedata/model/file_data.dart"; + +extension FileDataTable on MLDataDB { + Future putFDStatus(List fdStatusList) async { + if (fdStatusList.isEmpty) return; + final db = await MLDataDB.instance.asyncDB; + final inputs = >[]; + for (var status in fdStatusList) { + inputs.add( + [ + status.fileID, + status.userID, + status.type, + status.size, + status.objectID, + status.objectNonce, + status.updatedAt, + ], + ); + } + await db.executeBatch( + 'INSERT OR REPLACE INTO $fileDataTable ($fileIDColumn, user_id, type, size, obj_id, obj_nonce, updated_at ) values(?, ?, ?, ?, ?, ?, ?)', + inputs, + ); + } + + Future> getFileIDsWithFDData() async { + final db = await MLDataDB.instance.asyncDB; + final res = await db.execute('SELECT $fileIDColumn FROM $fileDataTable'); + return res.map((e) => e[fileIDColumn] as int).toSet(); + } +} diff --git a/mobile/lib/generated/intl/messages_ar.dart b/mobile/lib/generated/intl/messages_ar.dart index 1ce7ba622c..e1e0d5181e 100644 --- a/mobile/lib/generated/intl/messages_ar.dart +++ b/mobile/lib/generated/intl/messages_ar.dart @@ -26,6 +26,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("مرحبًا مجددًا!"), "ackPasswordLostWarning": MessageLookupByLibrary.simpleMessage( "أُدركُ أنّني فقدتُ كلمة مروري، فقد أفقد بياناتي لأن بياناتي مشفرة تشفيرًا تامًّا من النهاية إلى النهاية."), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "cancel": MessageLookupByLibrary.simpleMessage("إلغاء"), "decrypting": MessageLookupByLibrary.simpleMessage("فك التشفير..."), "email": MessageLookupByLibrary.simpleMessage("البريد الإلكتروني"), @@ -45,9 +50,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("ما من مفتاح استرداد؟"), "noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage( "لا يمكن فك تشفير بياناتك دون كلمة المرور أو مفتاح الاسترداد بسبب طبيعة بروتوكول التشفير الخاص بنا من النهاية إلى النهاية"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "recoverButton": MessageLookupByLibrary.simpleMessage("استرداد"), "recoverySuccessful": MessageLookupByLibrary.simpleMessage("نجح الاسترداد!"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "sorry": MessageLookupByLibrary.simpleMessage("المعذرة"), "terminate": MessageLookupByLibrary.simpleMessage("إنهاء"), "terminateSession": @@ -62,6 +69,8 @@ class MessageLookup extends MessageLookupByLibrary { "لإعادة تعيين كلمة المرور، يرجى التحقق من بريدك الإلكتروني أولاً."), "verify": MessageLookupByLibrary.simpleMessage("التحقّق"), "verifyEmail": - MessageLookupByLibrary.simpleMessage("التحقق من البريد الإلكتروني") + MessageLookupByLibrary.simpleMessage("التحقق من البريد الإلكتروني"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") }; } diff --git a/mobile/lib/generated/intl/messages_be.dart b/mobile/lib/generated/intl/messages_be.dart index aa8eee6a3a..efd5ebae4b 100644 --- a/mobile/lib/generated/intl/messages_be.dart +++ b/mobile/lib/generated/intl/messages_be.dart @@ -23,32 +23,62 @@ class MessageLookup extends MessageLookupByLibrary { static String m0(passwordStrengthValue) => "Надзейнасць пароля: ${passwordStrengthValue}"; - static String m1(email) => + static String m1(storageAmountInGB) => "${storageAmountInGB} Гб"; + + static String m2(email) => "Ліст адпраўлены на электронную пошту ${email}"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { + "about": MessageLookupByLibrary.simpleMessage("Пра праграму"), "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("З вяртаннем!"), + "ackPasswordLostWarning": MessageLookupByLibrary.simpleMessage( + "Я ўсведамляю, што калі я страчу свой пароль, то я магу згубіць свае даныя, бо мае даныя абаронены скразным шыфраваннем."), "activeSessions": MessageLookupByLibrary.simpleMessage("Актыўныя сеансы"), + "addMore": MessageLookupByLibrary.simpleMessage("Дадаць яшчэ"), + "after1Day": MessageLookupByLibrary.simpleMessage("Праз 1 дзень"), + "after1Hour": MessageLookupByLibrary.simpleMessage("Праз 1 гадзіну"), + "after1Month": MessageLookupByLibrary.simpleMessage("Праз 1 месяц"), + "after1Week": MessageLookupByLibrary.simpleMessage("Праз 1 тыдзень"), + "after1Year": MessageLookupByLibrary.simpleMessage("Праз 1 год"), + "albumOwner": MessageLookupByLibrary.simpleMessage("Уладальнік"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "apply": MessageLookupByLibrary.simpleMessage("Ужыць"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Якая асноўная прычына выдалення вашага ўліковага запісу?"), + "backup": MessageLookupByLibrary.simpleMessage("Рэзервовая копія"), "cancel": MessageLookupByLibrary.simpleMessage("Скасаваць"), + "change": MessageLookupByLibrary.simpleMessage("Змяніць"), + "changeEmail": MessageLookupByLibrary.simpleMessage( + "Змяніць адрас электроннай пошты"), "changePasswordTitle": MessageLookupByLibrary.simpleMessage("Змяніць пароль"), "checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage( "Праверце свае ўваходныя лісты (і спам) для завяршэння праверкі"), + "codeAppliedPageTitle": + MessageLookupByLibrary.simpleMessage("Код ужыты"), + "confirm": MessageLookupByLibrary.simpleMessage("Пацвердзіць"), "confirmAccountDeletion": MessageLookupByLibrary.simpleMessage( "Пацвердзіць выдаленне ўліковага запісу"), "confirmDeletePrompt": MessageLookupByLibrary.simpleMessage( "Так. Я хачу незваротна выдаліць гэты ўліковы запіс і яго даныя ва ўсіх праграмах."), "confirmPassword": MessageLookupByLibrary.simpleMessage("Пацвердзіць пароль"), + "contactSupport": MessageLookupByLibrary.simpleMessage( + "Звярніцеся ў службу падтрымкі"), + "continueLabel": MessageLookupByLibrary.simpleMessage("Працягнуць"), + "copyLink": MessageLookupByLibrary.simpleMessage("Скапіяваць спасылку"), "createAccount": MessageLookupByLibrary.simpleMessage("Стварыць уліковы запіс"), "createNewAccount": MessageLookupByLibrary.simpleMessage("Стварыць новы ўліковы запіс"), + "darkTheme": MessageLookupByLibrary.simpleMessage("Цёмная"), "decrypting": MessageLookupByLibrary.simpleMessage("Расшыфроўка..."), "deleteAccount": MessageLookupByLibrary.simpleMessage("Выдаліць уліковы запіс"), @@ -56,8 +86,12 @@ class MessageLookup extends MessageLookupByLibrary { "Нам шкада, што вы выдаляеце свой уліковы запіс. Абагуліце з намі водгук, каб дапамагчы нам палепшыць сэрвіс."), "deleteAccountPermanentlyButton": MessageLookupByLibrary.simpleMessage( "Незваротна выдаліць уліковы запіс"), + "deleteAlbum": MessageLookupByLibrary.simpleMessage("Выдаліць альбом"), "deleteEmailRequest": MessageLookupByLibrary.simpleMessage( "Адпраўце ліст на account-deletion@ente.io з вашага зарэгістраванага адраса электроннай пошты."), + "deleteFromEnte": + MessageLookupByLibrary.simpleMessage("Выдаліць з Ente"), + "deletePhotos": MessageLookupByLibrary.simpleMessage("Выдаліць фота"), "deleteReason1": MessageLookupByLibrary.simpleMessage( "У вас адсутнічае важная функцыя, якая мне неабходна"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -68,11 +102,25 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Прычына адсутнічае ў спісе"), "deleteRequestSLAText": MessageLookupByLibrary.simpleMessage( "Ваш запыт будзе апрацаваны цягам 72 гадзін."), + "details": MessageLookupByLibrary.simpleMessage("Падрабязнасці"), + "discover_food": MessageLookupByLibrary.simpleMessage("Ежа"), + "discover_notes": MessageLookupByLibrary.simpleMessage("Нататкі"), + "discover_pets": MessageLookupByLibrary.simpleMessage("Хатнія жывёлы"), + "discover_receipts": MessageLookupByLibrary.simpleMessage("Чэкі"), + "discover_screenshots": + MessageLookupByLibrary.simpleMessage("Скрыншоты"), + "discover_selfies": MessageLookupByLibrary.simpleMessage("Сэлфi"), + "discover_wallpapers": MessageLookupByLibrary.simpleMessage("Шпалеры"), + "doThisLater": + MessageLookupByLibrary.simpleMessage("Зрабіць гэта пазней"), + "done": MessageLookupByLibrary.simpleMessage("Гатова"), "email": MessageLookupByLibrary.simpleMessage("Электронная пошта"), + "encryption": MessageLookupByLibrary.simpleMessage("Шыфраванне"), "encryptionKeys": MessageLookupByLibrary.simpleMessage("Ключы шыфравання"), "entePhotosPerm": MessageLookupByLibrary.simpleMessage( "Праграме неабходны доступ для захавання вашых фатаграфій"), + "enterCode": MessageLookupByLibrary.simpleMessage("Увядзіце код"), "enterNewPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( "Увядзіце новы пароль, каб мы маглі выкарыстаць яго для расшыфроўкі вашых даных"), "enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( @@ -81,25 +129,57 @@ class MessageLookup extends MessageLookupByLibrary { "Увядзіце сапраўдны адрас электронная пошты."), "enterYourEmailAddress": MessageLookupByLibrary.simpleMessage( "Увядзіце свой адрас электроннай пошты"), + "enterYourPassword": + MessageLookupByLibrary.simpleMessage("Увядзіце свой пароль"), "enterYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Увядзіце свой ключ аднаўлення"), + "familyPlans": + MessageLookupByLibrary.simpleMessage("Сямейныя тарыфныя планы"), + "faqs": MessageLookupByLibrary.simpleMessage("Частыя пытанні"), "feedback": MessageLookupByLibrary.simpleMessage("Водгук"), "forgotPassword": MessageLookupByLibrary.simpleMessage("Забыліся пароль"), + "freeTrial": + MessageLookupByLibrary.simpleMessage("Бясплатная пробная версія"), + "general": MessageLookupByLibrary.simpleMessage("Асноўныя"), + "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( + "Генерацыя ключоў шыфравання..."), + "howItWorks": MessageLookupByLibrary.simpleMessage("Як гэта працуе"), + "ignoreUpdate": MessageLookupByLibrary.simpleMessage("Iгнараваць"), + "incorrectPasswordTitle": + MessageLookupByLibrary.simpleMessage("Няправільны пароль"), "incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage( "Вы ўвялі памылковы ключ аднаўлення"), "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage("Няправільны ключ аднаўлення"), + "insecureDevice": + MessageLookupByLibrary.simpleMessage("Небяспечная прылада"), + "installManually": + MessageLookupByLibrary.simpleMessage("Усталяваць уручную"), "invalidEmailAddress": MessageLookupByLibrary.simpleMessage( "Памылковы адрас электроннай пошты"), "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage( "Калі ласка, дапамажыце нам з гэтай інфармацыяй"), + "lightTheme": MessageLookupByLibrary.simpleMessage("Светлая"), + "lockscreen": MessageLookupByLibrary.simpleMessage("Экран блакіроўкі"), + "logInLabel": MessageLookupByLibrary.simpleMessage("Увайсці"), + "loginTerms": MessageLookupByLibrary.simpleMessage( + "Націскаючы ўвайсці, я пагаджаюся з умовамі абслугоўвання і палітыкай прыватнасці"), + "logout": MessageLookupByLibrary.simpleMessage("Выйсці"), + "magicSearch": MessageLookupByLibrary.simpleMessage("Магічны пошук"), + "manage": MessageLookupByLibrary.simpleMessage("Кіраванне"), + "manageParticipants": MessageLookupByLibrary.simpleMessage("Кіраванне"), "moderateStrength": MessageLookupByLibrary.simpleMessage("Умераны"), + "never": MessageLookupByLibrary.simpleMessage("Ніколі"), + "noDuplicates": + MessageLookupByLibrary.simpleMessage("✨ Няма дублікатаў"), "noRecoveryKey": MessageLookupByLibrary.simpleMessage("Няма ключа аднаўлення?"), "noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage( "Вашы даныя не могуць быць расшыфраваны без пароля або ключа аднаўлення па прычыне архітэктуры наша пратакола скразнога шыфравання"), + "notifications": MessageLookupByLibrary.simpleMessage("Апавяшчэнні"), "ok": MessageLookupByLibrary.simpleMessage("Добра"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Вой"), "password": MessageLookupByLibrary.simpleMessage("Пароль"), "passwordChangedSuccessfully": @@ -107,28 +187,77 @@ class MessageLookup extends MessageLookupByLibrary { "passwordStrength": m0, "passwordWarning": MessageLookupByLibrary.simpleMessage( "Мы не захоўваем гэты пароль і мы не зможам расшыфраваць вашы даныя, калі вы забудзеце яго"), + "photoSmallCase": MessageLookupByLibrary.simpleMessage("фота"), + "pleaseTryAgain": + MessageLookupByLibrary.simpleMessage("Паспрабуйце яшчэ раз"), + "pleaseWait": MessageLookupByLibrary.simpleMessage("Пачакайце..."), + "privacyPolicyTitle": + MessageLookupByLibrary.simpleMessage("Палітыка прыватнасці"), + "rateUs": MessageLookupByLibrary.simpleMessage("Ацаніце нас"), + "recover": MessageLookupByLibrary.simpleMessage("Аднавіць"), + "recoverAccount": + MessageLookupByLibrary.simpleMessage("Аднавіць уліковы запіс"), "recoverButton": MessageLookupByLibrary.simpleMessage("Аднавіць"), + "recoveryKey": MessageLookupByLibrary.simpleMessage("Ключ аднаўлення"), + "recoveryKeyCopiedToClipboard": MessageLookupByLibrary.simpleMessage( + "Ключ аднаўлення скапіяваны ў буфер абмену"), + "recoveryKeyOnForgotPassword": MessageLookupByLibrary.simpleMessage( + "Адзіным спосабам аднавіць вашы даныя з\'яўляецца гэты ключ, калі вы забылі свой пароль."), + "recoveryKeySaveDescription": MessageLookupByLibrary.simpleMessage( + "Захавайце гэты ключ, які складаецца з 24 слоў, у наедзеным месцы. Ён не захоўваецца на нашым серверы."), "recoverySuccessful": MessageLookupByLibrary.simpleMessage("Паспяховае аднаўленне!"), + "recreatePasswordBody": MessageLookupByLibrary.simpleMessage( + "У бягучай прылады недастаткова вылічальнай здольнасці для праверкі вашага паролю, але мы можам регенерыраваць яго, бо гэта працуе з усімі прыладамі.\n\nУвайдзіце, выкарыстоўваючы свой ключа аднаўлення і регенерыруйце свой пароль (калі хочаце, то можаце выбраць папярэдні пароль)."), + "recreatePasswordTitle": + MessageLookupByLibrary.simpleMessage("Стварыць пароль паўторна"), + "remove": MessageLookupByLibrary.simpleMessage("Выдаліць"), + "removeDuplicates": + MessageLookupByLibrary.simpleMessage("Выдаліць дублікаты"), + "removeParticipant": + MessageLookupByLibrary.simpleMessage("Выдаліць удзельніка"), + "removeWithQuestionMark": + MessageLookupByLibrary.simpleMessage("Выдаліць?"), "resendEmail": MessageLookupByLibrary.simpleMessage("Адправіць ліст яшчэ раз"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Скінуць пароль"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "retry": MessageLookupByLibrary.simpleMessage("Паўтарыць"), + "saveKey": MessageLookupByLibrary.simpleMessage("Захаваць ключ"), + "scanCode": MessageLookupByLibrary.simpleMessage("Сканіраваць код"), + "security": MessageLookupByLibrary.simpleMessage("Бяспека"), + "selectAll": MessageLookupByLibrary.simpleMessage("Абраць усё"), "selectReason": MessageLookupByLibrary.simpleMessage("Выберыце прычыну"), "sendEmail": MessageLookupByLibrary.simpleMessage("Адправіць ліст"), + "sendLink": MessageLookupByLibrary.simpleMessage("Адправіць спасылку"), "setPasswordTitle": MessageLookupByLibrary.simpleMessage("Задаць пароль"), + "setupComplete": + MessageLookupByLibrary.simpleMessage("Наладжванне завершана"), + "signUpTerms": MessageLookupByLibrary.simpleMessage( + "Я пагаджаюся з умовамі абслугоўвання і палітыкай прыватнасці"), + "skip": MessageLookupByLibrary.simpleMessage("Прапусціць"), "somethingWentWrongPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Нешта пайшло не так. Паспрабуйце яшчэ раз"), "sorry": MessageLookupByLibrary.simpleMessage("Прабачце"), + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": + MessageLookupByLibrary.simpleMessage( + "Немагчыма згенерыраваць ключы бяспекі на гэтай прыладзе.\n\nЗарэгіструйцеся з іншай прылады."), + "status": MessageLookupByLibrary.simpleMessage("Стан"), + "storageInGB": m1, "strongStrength": MessageLookupByLibrary.simpleMessage("Надзейны"), + "support": MessageLookupByLibrary.simpleMessage("Падтрымка"), + "systemTheme": MessageLookupByLibrary.simpleMessage("Сістэма"), "tapToEnterCode": MessageLookupByLibrary.simpleMessage("Націсніце, каб увесці код"), "terminate": MessageLookupByLibrary.simpleMessage("Перарваць"), "terminateSession": MessageLookupByLibrary.simpleMessage("Перарваць сеанс?"), + "termsOfServicesTitle": MessageLookupByLibrary.simpleMessage("Умовы"), + "theme": MessageLookupByLibrary.simpleMessage("Тема"), "thisDevice": MessageLookupByLibrary.simpleMessage("Гэта прылада"), "thisWillLogYouOutOfTheFollowingDevice": MessageLookupByLibrary.simpleMessage( @@ -137,11 +266,33 @@ class MessageLookup extends MessageLookupByLibrary { "Гэта дзеянне завяршыць сеанс на вашай прыладзе!"), "toResetVerifyEmail": MessageLookupByLibrary.simpleMessage( "Праверце электронную пошту, каб скінуць свой пароль."), + "trash": MessageLookupByLibrary.simpleMessage("Сметніца"), + "twofactorAuthenticationPageTitle": + MessageLookupByLibrary.simpleMessage( + "Двухфактарная аўтэнтыфікацыя"), + "uncategorized": MessageLookupByLibrary.simpleMessage("Без катэгорыі"), + "update": MessageLookupByLibrary.simpleMessage("Абнавіць"), + "updateAvailable": + MessageLookupByLibrary.simpleMessage("Даступна абнаўленне"), + "useRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Выкарыстоўваць ключ аднаўлення"), "verify": MessageLookupByLibrary.simpleMessage("Праверыць"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Праверыць электронную пошту"), - "weHaveSendEmailTo": m1, + "verifyPassword": + MessageLookupByLibrary.simpleMessage("Праверыць пароль"), + "videoSmallCase": MessageLookupByLibrary.simpleMessage("відэа"), + "viewLargeFiles": MessageLookupByLibrary.simpleMessage("Вялікія файлы"), + "viewer": MessageLookupByLibrary.simpleMessage("Праглядальнік"), + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Ненадзейны"), + "welcomeBack": MessageLookupByLibrary.simpleMessage("З вяртаннем!"), + "yesDelete": MessageLookupByLibrary.simpleMessage("Так, выдаліць"), + "yesLogout": MessageLookupByLibrary.simpleMessage("Так, выйсці"), + "yesRemove": MessageLookupByLibrary.simpleMessage("Так, выдаліць"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), + "you": MessageLookupByLibrary.simpleMessage("Вы"), "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage( "Ваш уліковы запіс быў выдалены") }; diff --git a/mobile/lib/generated/intl/messages_bg.dart b/mobile/lib/generated/intl/messages_bg.dart index e887127f40..45fc6483aa 100644 --- a/mobile/lib/generated/intl/messages_bg.dart +++ b/mobile/lib/generated/intl/messages_bg.dart @@ -21,5 +21,15 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'bg'; final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => {}; + static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") + }; } diff --git a/mobile/lib/generated/intl/messages_ca.dart b/mobile/lib/generated/intl/messages_ca.dart index 84dea987b0..1288bb1ada 100644 --- a/mobile/lib/generated/intl/messages_ca.dart +++ b/mobile/lib/generated/intl/messages_ca.dart @@ -21,5 +21,15 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ca'; final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => {}; + static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") + }; } diff --git a/mobile/lib/generated/intl/messages_cs.dart b/mobile/lib/generated/intl/messages_cs.dart index 226e365e9c..4fe746b06d 100644 --- a/mobile/lib/generated/intl/messages_cs.dart +++ b/mobile/lib/generated/intl/messages_cs.dart @@ -22,10 +22,19 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Jaký je váš hlavní důvod, proč mažete svůj účet?"), "checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage( "Zkontrolujte prosím svou doručenou poštu (a spam) pro dokončení ověření"), - "incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage("") + "incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage(""), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") }; } diff --git a/mobile/lib/generated/intl/messages_da.dart b/mobile/lib/generated/intl/messages_da.dart index 56893ea385..2199a784ab 100644 --- a/mobile/lib/generated/intl/messages_da.dart +++ b/mobile/lib/generated/intl/messages_da.dart @@ -20,12 +20,12 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'da'; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'ingen minder', one: '${formattedCount} minde', other: '${formattedCount} minder')}"; - static String m3(count) => "${count} valgt"; + static String m4(count) => "${count} valgt"; - static String m4(verificationID) => + static String m5(verificationID) => "Hey, kan du bekræfte, at dette er dit ente.io verifikation ID: ${verificationID}"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -36,6 +36,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Aktive sessioner"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Oplysninger om tilføjelser"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Hvad er hovedårsagen til, at du sletter din konto?"), "backedUpFolders": @@ -99,27 +104,29 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Langt tryk på en e-mail for at bekræfte slutningen af krypteringen."), "manage": MessageLookupByLibrary.simpleMessage("Administrér"), - "memoryCount": m2, + "memoryCount": m3, "mlIndexingDescription": MessageLookupByLibrary.simpleMessage( "Bemærk venligst, at maskinindlæring vil resultere i en højere båndbredde og batteriforbrug, indtil alle elementer er indekseret. Overvej at bruge desktop app til hurtigere indeksering, vil alle resultater blive synkroniseret automatisk."), "moments": MessageLookupByLibrary.simpleMessage("Øjeblikke"), "next": MessageLookupByLibrary.simpleMessage("Næste"), "ok": MessageLookupByLibrary.simpleMessage("Ok"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Ups"), "password": MessageLookupByLibrary.simpleMessage("Adgangskode"), "pleaseContactSupportAndWeWillBeHappyToHelp": MessageLookupByLibrary.simpleMessage( "Kontakt support@ente.io og vi vil være glade for at hjælpe!"), "renameFile": MessageLookupByLibrary.simpleMessage("Omdøb fil"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "scanThisBarcodeWithnyourAuthenticatorApp": MessageLookupByLibrary.simpleMessage( "Skan denne QR-kode med godkendelses-appen"), "searchHint1": MessageLookupByLibrary.simpleMessage("Hurtig, søgning på enheden"), "selectReason": MessageLookupByLibrary.simpleMessage("Vælg årsag"), - "selectedPhotos": m3, + "selectedPhotos": m4, "sendEmail": MessageLookupByLibrary.simpleMessage("Send email"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "somethingWentWrongPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Noget gik galt, prøv venligst igen"), @@ -134,6 +141,8 @@ class MessageLookup extends MessageLookupByLibrary { "verify": MessageLookupByLibrary.simpleMessage("Bekræft"), "viewAddOnButton": MessageLookupByLibrary.simpleMessage("Vis tilføjelser"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Din konto er blevet slettet") }; diff --git a/mobile/lib/generated/intl/messages_de.dart b/mobile/lib/generated/intl/messages_de.dart index a735c03d7a..3e80b76818 100644 --- a/mobile/lib/generated/intl/messages_de.dart +++ b/mobile/lib/generated/intl/messages_de.dart @@ -20,37 +20,37 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'de'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, one: 'Teilnehmer', other: 'Teilnehmer')} hinzufügen"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Element hinzufügen', other: 'Elemente hinzufügen')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Dein ${storageAmount} Add-on ist gültig bis ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, one: 'Betrachter', other: 'Betrachter')} hinzufügen"; - static String m9(emailOrName) => "Von ${emailOrName} hinzugefügt"; + static String m10(emailOrName) => "Von ${emailOrName} hinzugefügt"; - static String m10(albumName) => "Erfolgreich zu ${albumName} hinzugefügt"; + static String m11(albumName) => "Erfolgreich zu ${albumName} hinzugefügt"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Keine Teilnehmer', one: '1 Teilnehmer', other: '${count} Teilnehmer')}"; - static String m12(versionValue) => "Version: ${versionValue}"; + static String m13(versionValue) => "Version: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} frei"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Bitte kündige dein aktuelles Abo über ${paymentProvider} zuerst"; - static String m15(user) => + static String m16(user) => "Der Nutzer \"${user}\" wird keine weiteren Fotos zum Album hinzufügen können.\n\nJedoch kann er weiterhin vorhandene Bilder, welche durch ihn hinzugefügt worden sind, wieder entfernen"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Deine Familiengruppe hat bereits ${storageAmountInGb} GB erhalten', @@ -58,136 +58,136 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Du hast bereits ${storageAmountInGb} GB erhalten!', })}"; - static String m17(albumName) => + static String m18(albumName) => "Kollaborativer Link für ${albumName} erstellt"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Bitte kontaktiere ${familyAdminEmail} um dein Abo zu verwalten"; - static String m19(provider) => + static String m20(provider) => "Bitte kontaktiere uns über support@ente.io, um dein ${provider} Abo zu verwalten."; - static String m20(endpoint) => "Verbunden mit ${endpoint}"; + static String m21(endpoint) => "Verbunden mit ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Lösche ${count} Element', other: 'Lösche ${count} Elemente')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Lösche ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Der öffentliche Link zum Zugriff auf \"${albumName}\" wird entfernt."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Bitte sende eine E-Mail an ${supportEmail} von deiner registrierten E-Mail-Adresse"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Du hast ${Intl.plural(count, one: '${count} duplizierte Datei', other: '${count} dupliziere Dateien')} gelöscht und (${storageSaved}!) freigegeben"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} Dateien, ${formattedSize} jede"; - static String m27(newEmail) => "E-Mail-Adresse geändert zu ${newEmail}"; + static String m28(newEmail) => "E-Mail-Adresse geändert zu ${newEmail}"; - static String m28(email) => + static String m29(email) => "${email} hat kein Ente-Konto.\n\nSende eine Einladung, um Fotos zu teilen."; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "${Intl.plural(count, one: '1 Datei', other: '${formattedNumber} Dateien')} auf diesem Gerät wurde(n) sicher gespeichert"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "${Intl.plural(count, one: '1 Datei', other: '${formattedNumber} Dateien')} in diesem Album wurde(n) sicher gespeichert"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "${storageAmountInGB} GB jedes Mal, wenn sich jemand mit deinem Code für einen bezahlten Tarif anmeldet"; - static String m32(endDate) => "Kostenlose Demo verfügbar bis zum ${endDate}"; + static String m33(endDate) => "Kostenlose Demo verfügbar bis zum ${endDate}"; - static String m33(count) => + static String m34(count) => "Du kannst immernoch über Ente ${Intl.plural(count, one: 'darauf', other: 'auf sie')} zugreifen, solange du ein aktives Abo hast"; - static String m34(sizeInMBorGB) => "${sizeInMBorGB} freigeben"; + static String m35(sizeInMBorGB) => "${sizeInMBorGB} freigeben"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'Es kann vom Gerät gelöscht werden, um ${formattedSize} freizugeben', other: 'Sie können vom Gerät gelöscht werden, um ${formattedSize} freizugeben')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Verarbeite ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} Objekt', other: '${count} Objekte')}"; - static String m38(expiryTime) => "Link läuft am ${expiryTime} ab"; + static String m39(expiryTime) => "Link läuft am ${expiryTime} ab"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'keine Erinnerungsstücke', one: '${formattedCount} Erinnerung', other: '${formattedCount} Erinnerungsstücke')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Element verschieben', other: 'Elemente verschieben')}"; - static String m40(albumName) => "Erfolgreich zu ${albumName} hinzugefügt"; + static String m41(albumName) => "Erfolgreich zu ${albumName} hinzugefügt"; - static String m41(name) => "Nicht ${name}?"; + static String m42(name) => "Nicht ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Bitte wende Dich an ${familyAdminEmail}, um den Code zu ändern."; static String m0(passwordStrengthValue) => "Passwortstärke: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Bitte kontaktiere den Support von ${providerName}, falls etwas abgebucht wurde"; - static String m44(endDate) => + static String m45(endDate) => "Kostenlose Testversion gültig bis ${endDate}.\nDu kannst anschließend ein bezahltes Paket auswählen."; - static String m45(toEmail) => "Bitte sende uns eine E-Mail an ${toEmail}"; + static String m46(toEmail) => "Bitte sende uns eine E-Mail an ${toEmail}"; - static String m46(toEmail) => "Bitte sende die Protokolle an ${toEmail}"; + static String m47(toEmail) => "Bitte sende die Protokolle an ${toEmail}"; - static String m47(folderName) => "Verarbeite ${folderName}..."; + static String m48(folderName) => "Verarbeite ${folderName}..."; - static String m48(storeName) => "Bewerte uns auf ${storeName}"; + static String m49(storeName) => "Bewerte uns auf ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Ihr beide erhaltet ${storageInGB} GB* kostenlos"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} wird aus diesem geteilten Album entfernt\n\nAlle von ihnen hinzugefügte Fotos werden ebenfalls aus dem Album entfernt"; - static String m51(endDate) => "Erneuert am ${endDate}"; + static String m52(endDate) => "Erneuert am ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} Ergebnis gefunden', other: '${count} Ergebnisse gefunden')}"; - static String m3(count) => "${count} ausgewählt"; + static String m4(count) => "${count} ausgewählt"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "${count} ausgewählt (${yourCount} von Ihnen)"; - static String m54(verificationID) => + static String m55(verificationID) => "Hier ist meine Verifizierungs-ID: ${verificationID} für ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Hey, kannst du bestätigen, dass dies deine ente.io Verifizierungs-ID ist: ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Ente Weiterempfehlungs-Code: ${referralCode} \n\nEinlösen unter Einstellungen → Allgemein → Weiterempfehlungen, um ${referralStorageInGB} GB kostenlos zu erhalten, sobald Sie einen kostenpflichtigen Tarif abgeschlossen haben\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Teile mit bestimmten Personen', one: 'Teilen mit 1 Person', other: 'Teilen mit ${numberOfPeople} Personen')}"; - static String m57(emailIDs) => "Geteilt mit ${emailIDs}"; - - static String m58(fileType) => - "Dieses ${fileType} wird von deinem Gerät gelöscht."; + static String m58(emailIDs) => "Geteilt mit ${emailIDs}"; static String m59(fileType) => + "Dieses ${fileType} wird von deinem Gerät gelöscht."; + + static String m60(fileType) => "Diese Datei ist sowohl in Ente als auch auf deinem Gerät."; - static String m60(fileType) => "Diese Datei wird von Ente gelöscht."; + static String m61(fileType) => "Diese Datei wird von Ente gelöscht."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -215,7 +215,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Verifiziere ${email}"; - static String m1(email) => + static String m2(email) => "Wir haben eine E-Mail an ${email} gesendet"; static String m72(count) => @@ -244,10 +244,10 @@ class MessageLookup extends MessageLookupByLibrary { "Neue E-Mail-Adresse hinzufügen"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Bearbeiter hinzufügen"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Vom Gerät hinzufügen"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Ort hinzufügen"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Hinzufügen"), "addMore": MessageLookupByLibrary.simpleMessage("Mehr hinzufügen"), @@ -259,7 +259,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Neue Person hinzufügen"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Details der Add-ons"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Add-ons"), "addPhotos": MessageLookupByLibrary.simpleMessage("Fotos hinzufügen"), "addSelected": @@ -270,12 +270,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Zum versteckten Album hinzufügen"), "addViewer": MessageLookupByLibrary.simpleMessage("Album teilen"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Füge deine Foto jetzt hinzu"), "addedAs": MessageLookupByLibrary.simpleMessage("Hinzugefügt als"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage( "Wird zu Favoriten hinzugefügt..."), "advanced": MessageLookupByLibrary.simpleMessage("Erweitert"), @@ -286,7 +286,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Nach 1 Woche"), "after1Year": MessageLookupByLibrary.simpleMessage("Nach 1 Jahr"), "albumOwner": MessageLookupByLibrary.simpleMessage("Besitzer"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Albumtitel"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album aktualisiert"), @@ -294,6 +294,8 @@ class MessageLookup extends MessageLookupByLibrary { "allClear": MessageLookupByLibrary.simpleMessage("✨ Alles klar"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage( "Alle Erinnerungsstücke gesichert"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Erlaube Nutzern, mit diesem Link ebenfalls Fotos zu diesem geteilten Album hinzuzufügen."), "allowAddingPhotos": MessageLookupByLibrary.simpleMessage( @@ -327,7 +329,7 @@ class MessageLookup extends MessageLookupByLibrary { "appLock": MessageLookupByLibrary.simpleMessage("App-Sperre"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Wähle zwischen dem Standard-Sperrbildschirm deines Gerätes und einem eigenen Sperrbildschirm mit PIN oder Passwort."), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Anwenden"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Code nutzen"), @@ -351,6 +353,9 @@ class MessageLookup extends MessageLookupByLibrary { "Bist Du sicher, dass du dich abmelden möchtest?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Bist du sicher, dass du verlängern möchtest?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Dein Abonnement wurde gekündigt. Möchtest du uns den Grund mitteilen?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -404,7 +409,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "Automatisches Verbinden funktioniert nur mit Geräten, die Chromecast unterstützen."), "available": MessageLookupByLibrary.simpleMessage("Verfügbar"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Gesicherte Ordner"), "backup": MessageLookupByLibrary.simpleMessage("Backup"), @@ -434,10 +439,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Du kannst nur Dateien entfernen, die dir gehören"), "cancel": MessageLookupByLibrary.simpleMessage("Abbrechen"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Abonnement kündigen"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Konnte geteilte Dateien nicht löschen"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -471,7 +476,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Freien Speicher einlösen"), "claimMore": MessageLookupByLibrary.simpleMessage("Mehr einlösen!"), "claimed": MessageLookupByLibrary.simpleMessage("Eingelöst"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Unkategorisiert leeren"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -500,7 +505,7 @@ class MessageLookup extends MessageLookupByLibrary { "Erstelle einen Link, mit dem andere Fotos in dem geteilten Album sehen und selbst welche hinzufügen können - ohne dass sie die ein Ente-Konto oder die App benötigen. Ideal um gemeinsam Fotos von Events zu sammeln."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Gemeinschaftlicher Link"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Bearbeiter"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -515,6 +520,7 @@ class MessageLookup extends MessageLookupByLibrary { "collectPhotosDescription": MessageLookupByLibrary.simpleMessage( "Erstelle einen Link, mit dem deine Freunde Fotos in Originalqualität hochladen können."), "color": MessageLookupByLibrary.simpleMessage("Farbe"), + "configuration": MessageLookupByLibrary.simpleMessage("Konfiguration"), "confirm": MessageLookupByLibrary.simpleMessage("Bestätigen"), "confirm2FADisable": MessageLookupByLibrary.simpleMessage( "Bist du sicher, dass du die Zwei-Faktor-Authentifizierung (2FA) deaktivieren willst?"), @@ -532,10 +538,10 @@ class MessageLookup extends MessageLookupByLibrary { "Bestätige deinen Wiederherstellungsschlüssel"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Mit Gerät verbinden"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Support kontaktieren"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Kontakte"), "contents": MessageLookupByLibrary.simpleMessage("Inhalte"), "continueLabel": MessageLookupByLibrary.simpleMessage("Weiter"), @@ -581,7 +587,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("Aktuell genutzt werden "), "custom": MessageLookupByLibrary.simpleMessage("Benutzerdefiniert"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Dunkel"), "dayToday": MessageLookupByLibrary.simpleMessage("Heute"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Gestern"), @@ -617,11 +623,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Vom Gerät löschen"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Von Ente löschen"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Standort löschen"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Fotos löschen"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Es fehlt eine zentrale Funktion, die ich benötige"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -660,7 +666,7 @@ class MessageLookup extends MessageLookupByLibrary { "Zuschauer können weiterhin Screenshots oder mit anderen externen Programmen Kopien der Bilder machen."), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Bitte beachten Sie:"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Zweiten Faktor (2FA) deaktivieren"), "disablingTwofactorAuthentication": @@ -703,9 +709,9 @@ class MessageLookup extends MessageLookupByLibrary { "Herunterladen fehlgeschlagen"), "downloading": MessageLookupByLibrary.simpleMessage("Wird heruntergeladen..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Bearbeiten"), "editLocation": MessageLookupByLibrary.simpleMessage("Standort bearbeiten"), @@ -718,8 +724,8 @@ class MessageLookup extends MessageLookupByLibrary { "Edits to location will only be seen within Ente"), "eligible": MessageLookupByLibrary.simpleMessage("zulässig"), "email": MessageLookupByLibrary.simpleMessage("E-Mail"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("E-Mail-Verifizierung"), "emailYourLogs": MessageLookupByLibrary.simpleMessage( @@ -833,8 +839,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Dateitypen"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Dateitypen und -namen"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Dateien gelöscht"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage( @@ -850,27 +856,27 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Gesichter gefunden"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage( "Kostenlos hinzugefügter Speicherplatz"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage( "Freier Speicherplatz nutzbar"), "freeTrial": MessageLookupByLibrary.simpleMessage("Kostenlose Testphase"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Gerätespeicher freiräumen"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Spare Speicherplatz auf deinem Gerät, indem du Dateien löschst, die bereits gesichert wurden."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Speicherplatz freigeben"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Bis zu 1000 Erinnerungsstücke angezeigt in der Galerie"), "general": MessageLookupByLibrary.simpleMessage("Allgemein"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Generierung von Verschlüsselungscodes..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Zu den Einstellungen"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), @@ -950,7 +956,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Etwas ist schiefgelaufen. Bitte versuche es später noch einmal. Sollte der Fehler weiter bestehen, kontaktiere unser Supportteam."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Elemente zeigen die Anzahl der Tage bis zum dauerhaften Löschen an"), @@ -979,7 +985,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("Geräte-Limit"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Aktiviert"), "linkExpired": MessageLookupByLibrary.simpleMessage("Abgelaufen"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Ablaufdatum des Links"), "linkHasExpired": @@ -1015,6 +1021,8 @@ class MessageLookup extends MessageLookupByLibrary { "loadingYourPhotos": MessageLookupByLibrary.simpleMessage("Lade deine Fotos..."), "localGallery": MessageLookupByLibrary.simpleMessage("Lokale Galerie"), + "localIndexing": + MessageLookupByLibrary.simpleMessage("Lokale Indizierung"), "localSyncErrorMessage": MessageLookupByLibrary.simpleMessage( "Es sieht so aus, als ob etwas schiefgelaufen ist, da die lokale Foto-Synchronisierung länger dauert als erwartet. Bitte kontaktiere unser Support-Team"), "location": MessageLookupByLibrary.simpleMessage("Standort"), @@ -1064,7 +1072,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Karten"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage( "Mit vorhandenem zusammenführen"), @@ -1091,12 +1099,12 @@ class MessageLookup extends MessageLookupByLibrary { "moreDetails": MessageLookupByLibrary.simpleMessage("Weitere Details"), "mostRecent": MessageLookupByLibrary.simpleMessage("Neuste"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Nach Relevanz"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Zum Album verschieben"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Zu verstecktem Album verschieben"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage( "In den Papierkorb verschoben"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -1146,7 +1154,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Keine Ergebnisse gefunden"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage("Keine Systemsperre gefunden"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage("Noch nichts mit Dir geteilt"), "nothingToSeeHere": MessageLookupByLibrary.simpleMessage( @@ -1157,7 +1165,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("Auf dem Gerät"), "onEnte": MessageLookupByLibrary.simpleMessage( "Auf ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Hoppla"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Hoppla, die Änderungen konnten nicht gespeichert werden"), @@ -1197,7 +1206,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Zahlung fehlgeschlagen"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Leider ist deine Zahlung fehlgeschlagen. Wende dich an unseren Support und wir helfen dir weiter!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Ausstehende Elemente"), "pendingSync": @@ -1227,7 +1236,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinLock": MessageLookupByLibrary.simpleMessage("PIN-Sperre"), "playOnTv": MessageLookupByLibrary.simpleMessage( "Album auf dem Fernseher wiedergeben"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore Abo"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1239,14 +1248,14 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Bitte wenden Sie sich an den Support, falls das Problem weiterhin besteht"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Bitte erteile die nötigen Berechtigungen"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Bitte logge dich erneut ein"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Bitte wähle die zu entfernenden schnellen Links"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Bitte versuche es erneut"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1273,7 +1282,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Private Sicherungen"), "privateSharing": MessageLookupByLibrary.simpleMessage("Privates Teilen"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Öffentlicher Link erstellt"), "publicLinkEnabled": @@ -1283,7 +1292,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Ticket erstellen"), "rateTheApp": MessageLookupByLibrary.simpleMessage("App bewerten"), "rateUs": MessageLookupByLibrary.simpleMessage("Bewerte uns"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Wiederherstellen"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Konto wiederherstellen"), @@ -1320,7 +1329,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Gib diesen Code an deine Freunde"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Sie schließen ein bezahltes Abo ab"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Weiterempfehlungen"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Einlösungen sind derzeit pausiert"), @@ -1348,7 +1357,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Link entfernen"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Teilnehmer entfernen"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("Personenetikett entfernen"), "removePublicLink": @@ -1366,7 +1375,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Datei umbenennen"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Abonnement erneuern"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Fehler melden"), "reportBug": MessageLookupByLibrary.simpleMessage("Fehler melden"), "resendEmail": @@ -1375,6 +1384,7 @@ class MessageLookup extends MessageLookupByLibrary { "Ignorierte Dateien zurücksetzen"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Passwort zurücksetzen"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("Standardwerte zurücksetzen"), "restore": MessageLookupByLibrary.simpleMessage("Wiederherstellen"), @@ -1438,7 +1448,7 @@ class MessageLookup extends MessageLookupByLibrary { "Gruppiere Fotos, die innerhalb des Radius eines bestimmten Fotos aufgenommen wurden"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Laden Sie Personen ein, damit Sie geteilte Fotos hier einsehen können"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Sicherheit"), "selectALocation": MessageLookupByLibrary.simpleMessage("Standort auswählen"), @@ -1465,8 +1475,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Ausgewählte Elemente werden aus allen Alben gelöscht und in den Papierkorb verschoben."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Absenden"), "sendEmail": MessageLookupByLibrary.simpleMessage("E-Mail senden"), "sendInvite": MessageLookupByLibrary.simpleMessage("Einladung senden"), @@ -1494,16 +1504,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Teile jetzt ein Album"), "shareLink": MessageLookupByLibrary.simpleMessage("Link teilen"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Teile mit ausgewählten Personen"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Hol dir Ente, damit wir ganz einfach Fotos und Videos in Originalqualität teilen können\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Mit Nicht-Ente-Benutzern teilen"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Teile dein erstes Album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1514,7 +1524,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Neue geteilte Fotos"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Erhalte Benachrichtigungen, wenn jemand ein Foto zu einem gemeinsam genutzten Album hinzufügt, dem du angehörst"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Mit mir geteilt"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Mit dir geteilt"), @@ -1530,11 +1540,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Andere Geräte abmelden"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Ich stimme den Nutzungsbedingungen und der Datenschutzerklärung zu"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Es wird aus allen Alben gelöscht."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Überspringen"), "social": MessageLookupByLibrary.simpleMessage("Social Media"), "someItemsAreInBothEnteAndYourDevice": @@ -1581,7 +1591,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Speicherplatz"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Familie"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Sie"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Speichergrenze überschritten"), "storageUsageInfo": m62, @@ -1785,7 +1795,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Wir unterstützen keine Bearbeitung von Fotos und Alben, die du noch nicht besitzt"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Schwach"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Willkommen zurück!"), @@ -1802,6 +1812,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("Ja, ausloggen"), "yesRemove": MessageLookupByLibrary.simpleMessage("Ja, entfernen"), "yesRenew": MessageLookupByLibrary.simpleMessage("Ja, erneuern"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Du"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("Du bist im Familien-Tarif!"), diff --git a/mobile/lib/generated/intl/messages_el.dart b/mobile/lib/generated/intl/messages_el.dart index 79c0433b27..8862a1cc3d 100644 --- a/mobile/lib/generated/intl/messages_el.dart +++ b/mobile/lib/generated/intl/messages_el.dart @@ -22,7 +22,16 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "enterYourEmailAddress": MessageLookupByLibrary.simpleMessage( - "Εισάγετε την διεύθυνση ηλ. ταχυδρομείου σας") + "Εισάγετε την διεύθυνση ηλ. ταχυδρομείου σας"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") }; } diff --git a/mobile/lib/generated/intl/messages_en.dart b/mobile/lib/generated/intl/messages_en.dart index 4aedaae0d1..bae5b76a84 100644 --- a/mobile/lib/generated/intl/messages_en.dart +++ b/mobile/lib/generated/intl/messages_en.dart @@ -20,172 +20,172 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'en'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Add collaborator', one: 'Add collaborator', other: 'Add collaborators')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Add item', other: 'Add items')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Your ${storageAmount} add-on is valid till ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, zero: 'Add viewer', one: 'Add viewer', other: 'Add viewers')}"; - static String m9(emailOrName) => "Added by ${emailOrName}"; + static String m10(emailOrName) => "Added by ${emailOrName}"; - static String m10(albumName) => "Added successfully to ${albumName}"; + static String m11(albumName) => "Added successfully to ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'No Participants', one: '1 Participant', other: '${count} Participants')}"; - static String m12(versionValue) => "Version: ${versionValue}"; + static String m13(versionValue) => "Version: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} free"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Please cancel your existing subscription from ${paymentProvider} first"; - static String m15(user) => + static String m16(user) => "${user} will not be able to add more photos to this album\n\nThey will still be able to remove existing photos added by them"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Your family has claimed ${storageAmountInGb} GB so far', 'false': 'You have claimed ${storageAmountInGb} GB so far', 'other': 'You have claimed ${storageAmountInGb} GB so far!', })}"; - static String m17(albumName) => "Collaborative link created for ${albumName}"; + static String m18(albumName) => "Collaborative link created for ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Please contact ${familyAdminEmail} to manage your subscription"; - static String m19(provider) => + static String m20(provider) => "Please contact us at support@ente.io to manage your ${provider} subscription."; - static String m20(endpoint) => "Connected to ${endpoint}"; + static String m21(endpoint) => "Connected to ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Delete ${count} item', other: 'Delete ${count} items')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Deleting ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "This will remove the public link for accessing \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Please drop an email to ${supportEmail} from your registered email address"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "You have cleaned up ${Intl.plural(count, one: '${count} duplicate file', other: '${count} duplicate files')}, saving (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} files, ${formattedSize} each"; - static String m27(newEmail) => "Email changed to ${newEmail}"; + static String m28(newEmail) => "Email changed to ${newEmail}"; - static String m28(email) => + static String m29(email) => "${email} does not have an Ente account.\n\nSend them an invite to share photos."; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "${Intl.plural(count, one: '1 file', other: '${formattedNumber} files')} on this device have been backed up safely"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "${Intl.plural(count, one: '1 file', other: '${formattedNumber} files')} in this album has been backed up safely"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "${storageAmountInGB} GB each time someone signs up for a paid plan and applies your code"; - static String m32(endDate) => "Free trial valid till ${endDate}"; + static String m33(endDate) => "Free trial valid till ${endDate}"; - static String m33(count) => + static String m34(count) => "You can still access ${Intl.plural(count, one: 'it', other: 'them')} on Ente as long as you have an active subscription"; - static String m34(sizeInMBorGB) => "Free up ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "Free up ${sizeInMBorGB}"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'It can be deleted from the device to free up ${formattedSize}', other: 'They can be deleted from the device to free up ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Processing ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} item', other: '${count} items')}"; - static String m38(expiryTime) => "Link will expire on ${expiryTime}"; + static String m39(expiryTime) => "Link will expire on ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'no memories', one: '${formattedCount} memory', other: '${formattedCount} memories')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Move item', other: 'Move items')}"; - static String m40(albumName) => "Moved successfully to ${albumName}"; + static String m41(albumName) => "Moved successfully to ${albumName}"; - static String m41(name) => "Not ${name}?"; + static String m42(name) => "Not ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Please contact ${familyAdminEmail} to change your code."; static String m0(passwordStrengthValue) => "Password strength: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Please talk to ${providerName} support if you were charged"; - static String m44(endDate) => + static String m45(endDate) => "Free trial valid till ${endDate}.\nYou can choose a paid plan afterwards."; - static String m45(toEmail) => "Please email us at ${toEmail}"; + static String m46(toEmail) => "Please email us at ${toEmail}"; - static String m46(toEmail) => "Please send the logs to \n${toEmail}"; + static String m47(toEmail) => "Please send the logs to \n${toEmail}"; - static String m47(folderName) => "Processing ${folderName}..."; + static String m48(folderName) => "Processing ${folderName}..."; - static String m48(storeName) => "Rate us on ${storeName}"; + static String m49(storeName) => "Rate us on ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Both of you get ${storageInGB} GB* free"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} will be removed from this shared album\n\nAny photos added by them will also be removed from the album"; - static String m51(endDate) => "Subscription renews on ${endDate}"; + static String m52(endDate) => "Subscription renews on ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} result found', other: '${count} results found')}"; - static String m3(count) => "${count} selected"; + static String m4(count) => "${count} selected"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "${count} selected (${yourCount} yours)"; - static String m54(verificationID) => + static String m55(verificationID) => "Here\'s my verification ID: ${verificationID} for ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Hey, can you confirm that this is your ente.io verification ID: ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Ente referral code: ${referralCode} \n\nApply it in Settings → General → Referrals to get ${referralStorageInGB} GB free after you signup for a paid plan\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Share with specific people', one: 'Shared with 1 person', other: 'Shared with ${numberOfPeople} people')}"; - static String m57(emailIDs) => "Shared with ${emailIDs}"; - - static String m58(fileType) => - "This ${fileType} will be deleted from your device."; + static String m58(emailIDs) => "Shared with ${emailIDs}"; static String m59(fileType) => + "This ${fileType} will be deleted from your device."; + + static String m60(fileType) => "This ${fileType} is in both Ente and your device."; - static String m60(fileType) => "This ${fileType} will be deleted from Ente."; + static String m61(fileType) => "This ${fileType} will be deleted from Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -214,7 +214,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Verify ${email}"; - static String m1(email) => "We have sent a mail to ${email}"; + static String m2(email) => "We have sent a mail to ${email}"; static String m72(count) => "${Intl.plural(count, one: '${count} year ago', other: '${count} years ago')}"; @@ -239,10 +239,10 @@ class MessageLookup extends MessageLookupByLibrary { "addANewEmail": MessageLookupByLibrary.simpleMessage("Add a new email"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Add collaborator"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Add from device"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Add location"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Add"), "addMore": MessageLookupByLibrary.simpleMessage("Add more"), @@ -253,7 +253,7 @@ class MessageLookup extends MessageLookupByLibrary { "addNewPerson": MessageLookupByLibrary.simpleMessage("Add new person"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Details of add-ons"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Add-ons"), "addPhotos": MessageLookupByLibrary.simpleMessage("Add photos"), "addSelected": MessageLookupByLibrary.simpleMessage("Add selected"), @@ -262,12 +262,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Add to hidden album"), "addViewer": MessageLookupByLibrary.simpleMessage("Add viewer"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Add your photos now"), "addedAs": MessageLookupByLibrary.simpleMessage("Added as"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Adding to favorites..."), "advanced": MessageLookupByLibrary.simpleMessage("Advanced"), @@ -278,13 +278,15 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("After 1 week"), "after1Year": MessageLookupByLibrary.simpleMessage("After 1 year"), "albumOwner": MessageLookupByLibrary.simpleMessage("Owner"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Album title"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album updated"), "albums": MessageLookupByLibrary.simpleMessage("Albums"), "allClear": MessageLookupByLibrary.simpleMessage("✨ All clear"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("All memories preserved"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Allow people with the link to also add photos to the shared album."), "allowAddingPhotos": @@ -315,7 +317,7 @@ class MessageLookup extends MessageLookupByLibrary { "appLock": MessageLookupByLibrary.simpleMessage("App lock"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Choose between your device\'s default lock screen and a custom lock screen with a PIN or password."), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Apply"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Apply code"), @@ -338,6 +340,9 @@ class MessageLookup extends MessageLookupByLibrary { "Are you sure you want to logout?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Are you sure you want to renew?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Your subscription was cancelled. Would you like to share the reason?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -390,7 +395,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "Auto pair works only with devices that support Chromecast."), "available": MessageLookupByLibrary.simpleMessage("Available"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Backed up folders"), "backup": MessageLookupByLibrary.simpleMessage("Backup"), @@ -417,10 +422,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Can only remove files owned by you"), "cancel": MessageLookupByLibrary.simpleMessage("Cancel"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Cancel subscription"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage("Cannot delete shared files"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -452,7 +457,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Claim free storage"), "claimMore": MessageLookupByLibrary.simpleMessage("Claim more!"), "claimed": MessageLookupByLibrary.simpleMessage("Claimed"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Clean Uncategorized"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -481,7 +486,7 @@ class MessageLookup extends MessageLookupByLibrary { "Create a link to allow people to add and view photos in your shared album without needing an Ente app or account. Great for collecting event photos."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Collaborative link"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Collaborator"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -496,6 +501,7 @@ class MessageLookup extends MessageLookupByLibrary { "collectPhotosDescription": MessageLookupByLibrary.simpleMessage( "Create a link where your friends can upload photos in original quality."), "color": MessageLookupByLibrary.simpleMessage("Color"), + "configuration": MessageLookupByLibrary.simpleMessage("Configuration"), "confirm": MessageLookupByLibrary.simpleMessage("Confirm"), "confirm2FADisable": MessageLookupByLibrary.simpleMessage( "Are you sure you want to disable two-factor authentication?"), @@ -513,10 +519,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Confirm your recovery key"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Connect to device"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Contact support"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "contents": MessageLookupByLibrary.simpleMessage("Contents"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continue"), @@ -560,7 +566,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("Current usage is "), "custom": MessageLookupByLibrary.simpleMessage("Custom"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Dark"), "dayToday": MessageLookupByLibrary.simpleMessage("Today"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Yesterday"), @@ -595,11 +601,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Delete from device"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Delete from Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Delete location"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Delete photos"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "It’s missing a key feature that I need"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -639,7 +645,7 @@ class MessageLookup extends MessageLookupByLibrary { "Viewers can still take screenshots or save a copy of your photos using external tools"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Please note"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage("Disable two-factor"), "disablingTwofactorAuthentication": @@ -680,9 +686,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Download failed"), "downloading": MessageLookupByLibrary.simpleMessage("Downloading..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Edit"), "editLocation": MessageLookupByLibrary.simpleMessage("Edit location"), "editLocationTagTitle": @@ -693,8 +699,8 @@ class MessageLookup extends MessageLookupByLibrary { "Edits to location will only be seen within Ente"), "eligible": MessageLookupByLibrary.simpleMessage("eligible"), "email": MessageLookupByLibrary.simpleMessage("Email"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Email verification"), "emailYourLogs": @@ -804,8 +810,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("File types"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("File types and names"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Files deleted"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage("Files saved to gallery"), @@ -819,25 +825,25 @@ class MessageLookup extends MessageLookupByLibrary { "foundFaces": MessageLookupByLibrary.simpleMessage("Found faces"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Free storage claimed"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Free storage usable"), "freeTrial": MessageLookupByLibrary.simpleMessage("Free trial"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Free up device space"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Save space on your device by clearing files that have been already backed up."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Free up space"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Up to 1000 memories shown in gallery"), "general": MessageLookupByLibrary.simpleMessage("General"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Generating encryption keys..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Go to settings"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), "grantFullAccessPrompt": MessageLookupByLibrary.simpleMessage( @@ -911,7 +917,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "It looks like something went wrong. Please retry after some time. If the error persists, please contact our support team."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Items show the number of days remaining before permanent deletion"), @@ -937,7 +943,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("Device limit"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Enabled"), "linkExpired": MessageLookupByLibrary.simpleMessage("Expired"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Link expiry"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("Link has expired"), @@ -972,6 +978,7 @@ class MessageLookup extends MessageLookupByLibrary { "loadingYourPhotos": MessageLookupByLibrary.simpleMessage("Loading your photos..."), "localGallery": MessageLookupByLibrary.simpleMessage("Local gallery"), + "localIndexing": MessageLookupByLibrary.simpleMessage("Local indexing"), "localSyncErrorMessage": MessageLookupByLibrary.simpleMessage( "Looks like something went wrong since local photos sync is taking more time than expected. Please reach out to our support team"), "location": MessageLookupByLibrary.simpleMessage("Location"), @@ -1020,7 +1027,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Maps"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("Merge with existing"), @@ -1047,11 +1054,11 @@ class MessageLookup extends MessageLookupByLibrary { "moreDetails": MessageLookupByLibrary.simpleMessage("More details"), "mostRecent": MessageLookupByLibrary.simpleMessage("Most recent"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Most relevant"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Move to album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Move to hidden album"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Moved to trash"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage("Moving files to album..."), @@ -1099,7 +1106,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("No results found"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage("No system lock found"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage("Nothing shared with you yet"), "nothingToSeeHere": @@ -1109,7 +1116,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("On device"), "onEnte": MessageLookupByLibrary.simpleMessage( "On ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Oops"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage("Oops, could not save edits"), @@ -1147,7 +1155,7 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("Payment failed"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Unfortunately your payment failed. Please contact support and we\'ll help you out!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Pending items"), "pendingSync": MessageLookupByLibrary.simpleMessage("Pending sync"), "people": MessageLookupByLibrary.simpleMessage("People"), @@ -1174,7 +1182,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinAlbum": MessageLookupByLibrary.simpleMessage("Pin album"), "pinLock": MessageLookupByLibrary.simpleMessage("PIN lock"), "playOnTv": MessageLookupByLibrary.simpleMessage("Play album on TV"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore subscription"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1186,14 +1194,14 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Please contact support if the problem persists"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Please grant permissions"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Please login again"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Please select quick links to remove"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Please try again"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1219,7 +1227,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Private backups"), "privateSharing": MessageLookupByLibrary.simpleMessage("Private sharing"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Public link created"), "publicLinkEnabled": @@ -1229,7 +1237,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Raise ticket"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Rate the app"), "rateUs": MessageLookupByLibrary.simpleMessage("Rate us"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Recover"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recover account"), @@ -1263,7 +1271,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Give this code to your friends"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. They sign up for a paid plan"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Referrals"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Referrals are currently paused"), @@ -1289,7 +1297,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Remove link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Remove participant"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("Remove person label"), "removePublicLink": @@ -1307,7 +1315,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Rename file"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renew subscription"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Report a bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Report bug"), "resendEmail": MessageLookupByLibrary.simpleMessage("Resend email"), @@ -1315,6 +1323,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Reset ignored files"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Reset password"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("Reset to default"), "restore": MessageLookupByLibrary.simpleMessage("Restore"), @@ -1375,7 +1384,7 @@ class MessageLookup extends MessageLookupByLibrary { "Group photos that are taken within some radius of a photo"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invite people, and you\'ll see all photos shared by them here"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Security"), "selectALocation": MessageLookupByLibrary.simpleMessage("Select a location"), @@ -1402,8 +1411,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Selected items will be deleted from all albums and moved to trash."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Send"), "sendEmail": MessageLookupByLibrary.simpleMessage("Send email"), "sendInvite": MessageLookupByLibrary.simpleMessage("Send invite"), @@ -1430,16 +1439,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Share an album now"), "shareLink": MessageLookupByLibrary.simpleMessage("Share link"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Share only with the people you want"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Download Ente so we can easily share original quality photos and videos\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage("Share with non-Ente users"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Share your first album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1450,7 +1459,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("New shared photos"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Receive notifications when someone adds a photo to a shared album that you\'re a part of"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Shared with me"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Shared with you"), @@ -1465,11 +1474,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Sign out other devices"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "I agree to the terms of service and privacy policy"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "It will be deleted from all albums."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Skip"), "social": MessageLookupByLibrary.simpleMessage("Social"), "someItemsAreInBothEnteAndYourDevice": @@ -1512,7 +1521,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Storage"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Family"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("You"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Storage limit exceeded"), "storageUsageInfo": m62, @@ -1704,7 +1713,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "We don\'t support editing photos and albums that you don\'t own yet"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Weak"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Welcome back!"), "whatsNew": MessageLookupByLibrary.simpleMessage("What\'s new"), @@ -1720,6 +1729,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("Yes, logout"), "yesRemove": MessageLookupByLibrary.simpleMessage("Yes, remove"), "yesRenew": MessageLookupByLibrary.simpleMessage("Yes, Renew"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("You"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("You are on a family plan!"), diff --git a/mobile/lib/generated/intl/messages_es.dart b/mobile/lib/generated/intl/messages_es.dart index d934f42450..f70e940b86 100644 --- a/mobile/lib/generated/intl/messages_es.dart +++ b/mobile/lib/generated/intl/messages_es.dart @@ -20,37 +20,37 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'es'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Añadir colaborador', one: 'Añadir colaborador', other: 'Añadir colaboradores')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Agregar elemento', other: 'Agregar elementos')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Tu ${storageAmount} adicional es válido hasta ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, zero: 'Añadir espectador', one: 'Añadir espectador', other: 'Añadir espectadores')}"; - static String m9(emailOrName) => "Añadido por ${emailOrName}"; + static String m10(emailOrName) => "Añadido por ${emailOrName}"; - static String m10(albumName) => "Añadido exitosamente a ${albumName}"; + static String m11(albumName) => "Añadido exitosamente a ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'No hay Participantes', one: '1 Participante', other: '${count} Participantes')}"; - static String m12(versionValue) => "Versión: ${versionValue}"; + static String m13(versionValue) => "Versión: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} gratis"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Por favor, cancela primero tu suscripción existente de ${paymentProvider}"; - static String m15(user) => + static String m16(user) => "${user} no podrá añadir más fotos a este álbum\n\nTodavía podrán eliminar las fotos ya añadidas por ellos"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Tu familia ha reclamado ${storageAmountInGb} GB hasta el momento', @@ -60,137 +60,137 @@ class MessageLookup extends MessageLookupByLibrary { '¡Tú has reclamado ${storageAmountInGb} GB hasta el momento!', })}"; - static String m17(albumName) => + static String m18(albumName) => "Enlace colaborativo creado para ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Por favor contacta con ${familyAdminEmail} para administrar tu suscripción"; - static String m19(provider) => + static String m20(provider) => "Por favor, contáctanos en support@ente.io para gestionar tu suscripción a ${provider}."; - static String m20(endpoint) => "Conectado a ${endpoint}"; + static String m21(endpoint) => "Conectado a ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Elimina ${count} elemento', other: 'Elimina ${count} elementos')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Borrando ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Esto eliminará el enlace público para acceder a \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Por favor, envía un correo electrónico a ${supportEmail} desde tu dirección de correo electrónico registrada"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "¡Has limpiado ${Intl.plural(count, one: '${count} archivo duplicado', other: '${count} archivos duplicados')}, ahorrando (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} archivos, ${formattedSize} cada uno"; - static String m27(newEmail) => "Correo cambiado a ${newEmail}"; + static String m28(newEmail) => "Correo cambiado a ${newEmail}"; - static String m28(email) => + static String m29(email) => "${email} no tiene una cuente en Ente.\n\nEnvíale una invitación para compartir fotos."; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "${Intl.plural(count, one: '1 archivo', other: '${formattedNumber} archivos')} en este dispositivo han sido respaldados de forma segura"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "${Intl.plural(count, one: '1 archivo', other: '${formattedNumber} archivos')} en este álbum ha sido respaldado de forma segura"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "${storageAmountInGB} GB cada vez que alguien se registra en un plan de pago y aplica tu código"; - static String m32(endDate) => "Prueba gratuita válida hasta ${endDate}"; + static String m33(endDate) => "Prueba gratuita válida hasta ${endDate}"; - static String m33(count) => + static String m34(count) => "Aún puedes acceder ${Intl.plural(count, one: 'a él', other: 'a ellos')} en Ente mientras tengas una suscripción activa"; - static String m34(sizeInMBorGB) => "Liberar ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "Liberar ${sizeInMBorGB}"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'Se puede eliminar del dispositivo para liberar ${formattedSize}', other: 'Se pueden eliminar del dispositivo para liberar ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Procesando ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} elemento', other: '${count} elementos')}"; - static String m38(expiryTime) => "El enlace caducará en ${expiryTime}"; + static String m39(expiryTime) => "El enlace caducará en ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'sin recuerdos', one: '${formattedCount} recuerdo', other: '${formattedCount} recuerdos')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Mover elemento', other: 'Mover elementos')}"; - static String m40(albumName) => "Movido exitosamente a ${albumName}"; + static String m41(albumName) => "Movido exitosamente a ${albumName}"; - static String m41(name) => "¿No es ${name}?"; + static String m42(name) => "¿No es ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Por favor, contacta a ${familyAdminEmail} para cambiar tu código."; static String m0(passwordStrengthValue) => "Seguridad de la contraseña: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Por favor, habla con el soporte de ${providerName} si se te cobró"; - static String m44(endDate) => + static String m45(endDate) => "Prueba gratuita válida hasta ${endDate}.\nPuedes elegir un plan de pago después."; - static String m45(toEmail) => + static String m46(toEmail) => "Por favor, envíanos un correo electrónico a ${toEmail}"; - static String m46(toEmail) => "Por favor, envía los registros a ${toEmail}"; + static String m47(toEmail) => "Por favor, envía los registros a ${toEmail}"; - static String m47(folderName) => "Procesando ${folderName}..."; + static String m48(folderName) => "Procesando ${folderName}..."; - static String m48(storeName) => "Califícanos en ${storeName}"; + static String m49(storeName) => "Califícanos en ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Ambos obtienen ${storageInGB} GB* gratis"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} será eliminado de este álbum compartido\n\nCualquier foto añadida por ellos también será eliminada del álbum"; - static String m51(endDate) => "La suscripción se renueva el ${endDate}"; + static String m52(endDate) => "La suscripción se renueva el ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} resultado encontrado', other: '${count} resultados encontrados')}"; - static String m3(count) => "${count} seleccionados"; + static String m4(count) => "${count} seleccionados"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "${count} seleccionados (${yourCount} tuyos)"; - static String m54(verificationID) => + static String m55(verificationID) => "Aquí está mi ID de verificación: ${verificationID} para ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Hola, ¿puedes confirmar que esta es tu ID de verificación ente.io: ${verificationID}?"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Código de referido de Ente: ${referralCode} \n\nAñádelo en Ajustes → General → Referidos para obtener ${referralStorageInGB} GB gratis tras comprar un plan de pago.\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Compartir con personas específicas', one: 'Compartido con 1 persona', other: 'Compartido con ${numberOfPeople} personas')}"; - static String m57(emailIDs) => "Compartido con ${emailIDs}"; - - static String m58(fileType) => - "Este ${fileType} se eliminará de tu dispositivo."; + static String m58(emailIDs) => "Compartido con ${emailIDs}"; static String m59(fileType) => + "Este ${fileType} se eliminará de tu dispositivo."; + + static String m60(fileType) => "Este ${fileType} está tanto en Ente como en tu dispositivo."; - static String m60(fileType) => "Este ${fileType} será eliminado de Ente."; + static String m61(fileType) => "Este ${fileType} será eliminado de Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -218,7 +218,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Verificar ${email}"; - static String m1(email) => + static String m2(email) => "Hemos enviado un correo a ${email}"; static String m72(count) => @@ -243,10 +243,10 @@ class MessageLookup extends MessageLookupByLibrary { "Agregar nuevo correo electrónico"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Agregar colaborador"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage( "Agregar desde el dispositivo"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Agregar ubicación"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Añadir"), @@ -254,7 +254,7 @@ class MessageLookup extends MessageLookupByLibrary { "addNew": MessageLookupByLibrary.simpleMessage("Añadir nuevo"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage( "Detalles de los complementos"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Complementos"), "addPhotos": MessageLookupByLibrary.simpleMessage("Agregar fotos"), "addSelected": @@ -264,12 +264,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Añadir al álbum oculto"), "addViewer": MessageLookupByLibrary.simpleMessage("Añadir espectador"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Añade tus fotos ahora"), "addedAs": MessageLookupByLibrary.simpleMessage("Agregado como"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Añadiendo a favoritos..."), "advanced": MessageLookupByLibrary.simpleMessage("Avanzado"), @@ -282,7 +282,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Después de una semana"), "after1Year": MessageLookupByLibrary.simpleMessage("Después de un año"), "albumOwner": MessageLookupByLibrary.simpleMessage("Propietario"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Título del álbum"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Álbum actualizado"), @@ -290,6 +290,8 @@ class MessageLookup extends MessageLookupByLibrary { "allClear": MessageLookupByLibrary.simpleMessage("✨ Todo limpio"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage( "Todos los recuerdos preservados"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Permitir a las personas con el enlace añadir fotos al álbum compartido."), "allowAddingPhotos": @@ -322,7 +324,7 @@ class MessageLookup extends MessageLookupByLibrary { "appLock": MessageLookupByLibrary.simpleMessage("Aplicación bloqueada"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Escoge entre la pantalla de bloqueo por defecto de tu dispositivo y una pantalla de bloqueo personalizada con un PIN o contraseña."), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("ID de Apple"), "apply": MessageLookupByLibrary.simpleMessage("Aplicar"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Usar código"), @@ -345,6 +347,9 @@ class MessageLookup extends MessageLookupByLibrary { "¿Estás seguro de que quieres cerrar la sesión?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "¿Estás seguro de que quieres renovar?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Tu suscripción ha sido cancelada. ¿Quieres compartir el motivo?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -398,7 +403,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "El emparejamiento automático funciona sólo con dispositivos compatibles con Chromecast."), "available": MessageLookupByLibrary.simpleMessage("Disponible"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Carpetas respaldadas"), "backup": MessageLookupByLibrary.simpleMessage("Copia de respaldo"), @@ -429,10 +434,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Sólo puede eliminar archivos de tu propiedad"), "cancel": MessageLookupByLibrary.simpleMessage("Cancelar"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Cancelar suscripción"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "No se pueden eliminar los archivos compartidos"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -465,7 +470,7 @@ class MessageLookup extends MessageLookupByLibrary { "Reclamar almacenamiento gratis"), "claimMore": MessageLookupByLibrary.simpleMessage("¡Reclama más!"), "claimed": MessageLookupByLibrary.simpleMessage("Reclamado"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Limpiar no categorizado"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -494,7 +499,7 @@ class MessageLookup extends MessageLookupByLibrary { "Crea un enlace para permitir que otros pueda añadir y ver fotos en tu álbum compartido sin necesitar la aplicación Ente o una cuenta. Genial para recolectar fotos de eventos."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Enlace colaborativo"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Colaborador"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -527,10 +532,10 @@ class MessageLookup extends MessageLookupByLibrary { "Confirma tu clave de recuperación"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Conectar a dispositivo"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Contactar con soporte"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Contactos"), "contents": MessageLookupByLibrary.simpleMessage("Contenidos"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuar"), @@ -575,7 +580,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("El uso actual es de "), "custom": MessageLookupByLibrary.simpleMessage("Personalizado"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Oscuro"), "dayToday": MessageLookupByLibrary.simpleMessage("Hoy"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Ayer"), @@ -611,12 +616,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Eliminar del dispositivo"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Eliminar de Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Borrar la ubicación"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Borrar las fotos"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Falta una característica clave que necesito"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -658,7 +663,7 @@ class MessageLookup extends MessageLookupByLibrary { "Los espectadores todavía pueden tomar capturas de pantalla o guardar una copia de tus fotos usando herramientas externas"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Por favor, ten en cuenta"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage("Deshabilitar dos factores"), "disablingTwofactorAuthentication": @@ -701,9 +706,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Descarga fallida"), "downloading": MessageLookupByLibrary.simpleMessage("Descargando..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Editar"), "editLocation": MessageLookupByLibrary.simpleMessage("Editar la ubicación"), @@ -716,8 +721,8 @@ class MessageLookup extends MessageLookupByLibrary { "Las ediciones a la ubicación sólo se verán dentro de Ente"), "eligible": MessageLookupByLibrary.simpleMessage("elegible"), "email": MessageLookupByLibrary.simpleMessage("Correo electrónico"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage( "Verificación por correo electrónico"), "emailYourLogs": MessageLookupByLibrary.simpleMessage( @@ -832,8 +837,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Tipos de archivos"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Tipos de archivo y nombres"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Archivos eliminados"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage( @@ -848,25 +853,25 @@ class MessageLookup extends MessageLookupByLibrary { "foundFaces": MessageLookupByLibrary.simpleMessage("Caras encontradas"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage( "Almacenamiento gratuito reclamado"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage( "Almacenamiento libre disponible"), "freeTrial": MessageLookupByLibrary.simpleMessage("Prueba gratuita"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Liberar espacio del dispositivo"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Ahorra espacio en tu dispositivo limpiando archivos que ya han sido respaldados."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Liberar espacio"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Hasta 1000 memorias mostradas en la galería"), "general": MessageLookupByLibrary.simpleMessage("General"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Generando claves de encriptación..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Ir a Ajustes"), "googlePlayId": MessageLookupByLibrary.simpleMessage("ID de Google Play"), @@ -944,7 +949,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Parece que algo salió mal. Por favor, vuelve a intentarlo después de algún tiempo. Si el error persiste, ponte en contacto con nuestro equipo de soporte."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Los artículos muestran el número de días restantes antes de ser borrados permanente"), @@ -974,7 +979,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Límite del dispositivo"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Habilitado"), "linkExpired": MessageLookupByLibrary.simpleMessage("Vencido"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Enlace vence"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("El enlace ha caducado"), @@ -1066,7 +1071,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Mapas"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Mercancías"), "mlConsent": MessageLookupByLibrary.simpleMessage( "Habilitar aprendizaje automático"), @@ -1091,11 +1096,11 @@ class MessageLookup extends MessageLookupByLibrary { "moreDetails": MessageLookupByLibrary.simpleMessage("Más detalles"), "mostRecent": MessageLookupByLibrary.simpleMessage("Más reciente"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Más relevante"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Mover al álbum"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Mover al álbum oculto"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Movido a la papelera"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -1144,7 +1149,7 @@ class MessageLookup extends MessageLookupByLibrary { "No se han encontrado resultados"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage( "Bloqueo de sistema no encontrado"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage( "Aún no hay nada compartido contigo"), "nothingToSeeHere": MessageLookupByLibrary.simpleMessage( @@ -1154,7 +1159,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("En el dispositivo"), "onEnte": MessageLookupByLibrary.simpleMessage( "En ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Ups"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Ups, no se pudieron guardar las ediciónes"), @@ -1195,7 +1201,7 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("Pago fallido"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Lamentablemente tu pago falló. Por favor, ¡contacta con el soporte técnico y te ayudaremos!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Elementos pendientes"), "pendingSync": @@ -1224,7 +1230,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinLock": MessageLookupByLibrary.simpleMessage("PIN Bloqueado"), "playOnTv": MessageLookupByLibrary.simpleMessage("Reproducir álbum en TV"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Suscripción en la PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1236,14 +1242,14 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Por favor, contacta a soporte técnico si el problema persiste"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Por favor, concede permiso"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( "Por favor, vuelve a iniciar sesión"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Por favor, selecciona enlaces rápidos para eliminar"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Por favor, inténtalo nuevamente"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1270,7 +1276,7 @@ class MessageLookup extends MessageLookupByLibrary { "Copias de seguridad privadas"), "privateSharing": MessageLookupByLibrary.simpleMessage("Compartir en privado"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Enlace público creado"), "publicLinkEnabled": @@ -1281,7 +1287,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Evalúa la aplicación"), "rateUs": MessageLookupByLibrary.simpleMessage("Califícanos"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Recuperar"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recuperar cuenta"), @@ -1316,7 +1322,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Dale este código a tus amigos"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Se inscriben a un plan pagado"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Referidos"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Las referencias están actualmente en pausa"), @@ -1343,7 +1349,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Eliminar enlace"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Quitar participante"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage( "Eliminar etiqueta de persona"), "removePublicLink": @@ -1361,7 +1367,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Renombrar archivo"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renovar suscripción"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Reportar un error"), "reportBug": MessageLookupByLibrary.simpleMessage("Reportar error"), "resendEmail": @@ -1370,6 +1376,7 @@ class MessageLookup extends MessageLookupByLibrary { "Restablecer archivos ignorados"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Restablecer contraseña"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage( "Restablecer valores predeterminados"), "restore": MessageLookupByLibrary.simpleMessage("Restaurar"), @@ -1434,7 +1441,7 @@ class MessageLookup extends MessageLookupByLibrary { "Agrupar las fotos que se tomaron cerca de la localización de una foto"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invita a gente y verás todas las fotos compartidas aquí"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Seguridad"), "selectALocation": MessageLookupByLibrary.simpleMessage("Seleccionar una ubicación"), @@ -1463,8 +1470,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Los archivos seleccionados serán eliminados de todos los álbumes y movidos a la papelera."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Enviar"), "sendEmail": MessageLookupByLibrary.simpleMessage("Enviar correo electrónico"), @@ -1496,16 +1503,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Compartir un álbum ahora"), "shareLink": MessageLookupByLibrary.simpleMessage("Compartir enlace"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Comparte sólo con la gente que quieres"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Descarga Ente para que podamos compartir fácilmente fotos y videos en calidad original.\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Compartir con usuarios fuera de Ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Comparte tu primer álbum"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1517,7 +1524,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nuevas fotos compartidas"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Recibir notificaciones cuando alguien agrega una foto a un álbum compartido contigo"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Compartido conmigo"), "sharedWithYou": @@ -1534,11 +1541,11 @@ class MessageLookup extends MessageLookupByLibrary { "Cerrar la sesión de otros dispositivos"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Estoy de acuerdo con los términos del servicio y la política de privacidad"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Se borrará de todos los álbumes."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Omitir"), "social": MessageLookupByLibrary.simpleMessage("Social"), "someItemsAreInBothEnteAndYourDevice": @@ -1584,7 +1591,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Almacenamiento"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Familia"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Usted"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Límite de datos excedido"), "storageUsageInfo": m62, @@ -1787,7 +1794,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "No admitimos la edición de fotos y álbumes que aún no son tuyos"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Poco segura"), "welcomeBack": MessageLookupByLibrary.simpleMessage("¡Bienvenido de nuevo!"), @@ -1804,6 +1811,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("Sí, cerrar sesión"), "yesRemove": MessageLookupByLibrary.simpleMessage("Sí, quitar"), "yesRenew": MessageLookupByLibrary.simpleMessage("Sí, renovar"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Tu"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("¡Estás en un plan familiar!"), diff --git a/mobile/lib/generated/intl/messages_et.dart b/mobile/lib/generated/intl/messages_et.dart index c1b8a2ba7e..2f130c9cde 100644 --- a/mobile/lib/generated/intl/messages_et.dart +++ b/mobile/lib/generated/intl/messages_et.dart @@ -21,5 +21,15 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'et'; final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => {}; + static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") + }; } diff --git a/mobile/lib/generated/intl/messages_fa.dart b/mobile/lib/generated/intl/messages_fa.dart index 91d69fe41a..3a0c0bf299 100644 --- a/mobile/lib/generated/intl/messages_fa.dart +++ b/mobile/lib/generated/intl/messages_fa.dart @@ -20,18 +20,18 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'fa'; - static String m12(versionValue) => "نسخه: ${versionValue}"; + static String m13(versionValue) => "نسخه: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} رایگان"; - static String m24(supportEmail) => + static String m25(supportEmail) => "لطفا یک ایمیل از آدرس ایمیلی که ثبت نام کردید به ${supportEmail} ارسال کنید"; static String m0(passwordStrengthValue) => "قدرت رمز عبور: ${passwordStrengthValue}"; - static String m48(storeName) => "به ما در ${storeName} امتیاز دهید"; + static String m49(storeName) => "به ما در ${storeName} امتیاز دهید"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -39,7 +39,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "تایید ${email}"; - static String m1(email) => + static String m2(email) => "ما یک ایمیل به ${email} ارسال کرده‌ایم"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -62,6 +62,8 @@ class MessageLookup extends MessageLookupByLibrary { "addedAs": MessageLookupByLibrary.simpleMessage("اضافه شده به عنوان"), "advanced": MessageLookupByLibrary.simpleMessage("پیشرفته"), "albumUpdated": MessageLookupByLibrary.simpleMessage("آلبوم به‌روز شد"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "به افراد که این پیوند را دارند، اجازه دهید عکس‌ها را به آلبوم اشتراک گذاری شده اضافه کنند."), "allowAddingPhotos": @@ -75,10 +77,13 @@ class MessageLookup extends MessageLookupByLibrary { "androidCancelButton": MessageLookupByLibrary.simpleMessage("لغو"), "androidIosWebDesktop": MessageLookupByLibrary.simpleMessage( "اندروید، آی‌اواس، وب، رایانه رومیزی"), - "appVersion": m12, + "appVersion": m13, "archive": MessageLookupByLibrary.simpleMessage("بایگانی"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "آیا برای خارج شدن مطمئن هستید؟"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "دلیل اصلی که حساب کاربری‌تان را حذف می‌کنید، چیست؟"), "atAFalloutShelter": @@ -86,7 +91,7 @@ class MessageLookup extends MessageLookupByLibrary { "authToViewYourActiveSessions": MessageLookupByLibrary.simpleMessage( "لطفاً برای مشاهده دستگاه‌های فعال خود احراز هویت کنید"), "available": MessageLookupByLibrary.simpleMessage("در دسترس"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("پوشه‌های پشتیبان گیری شده"), "backup": MessageLookupByLibrary.simpleMessage("پشتیبان گیری"), @@ -164,7 +169,7 @@ class MessageLookup extends MessageLookupByLibrary { "discord": MessageLookupByLibrary.simpleMessage("دیسکورد"), "doThisLater": MessageLookupByLibrary.simpleMessage("بعداً انجام شود"), "downloading": MessageLookupByLibrary.simpleMessage("در حال دانلود..."), - "dropSupportEmail": m24, + "dropSupportEmail": m25, "editLocationTagTitle": MessageLookupByLibrary.simpleMessage("ویرایش مکان"), "email": MessageLookupByLibrary.simpleMessage("ایمیل"), @@ -266,6 +271,7 @@ class MessageLookup extends MessageLookupByLibrary { "با توجه به ماهیت پروتکل رمزگذاری سرتاسر ما، اطلاعات شما بدون رمز عبور یا کلید بازیابی شما قابل رمزگشایی نیست"), "notifications": MessageLookupByLibrary.simpleMessage("آگاه‌سازی‌ها"), "ok": MessageLookupByLibrary.simpleMessage("تایید"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("اوه"), "password": MessageLookupByLibrary.simpleMessage("رمز عبور"), "passwordChangedSuccessfully": MessageLookupByLibrary.simpleMessage( @@ -290,7 +296,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("پشتیبان گیری خصوصی"), "privateSharing": MessageLookupByLibrary.simpleMessage("اشتراک گذاری خصوصی"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("بازیابی"), "recoverAccount": MessageLookupByLibrary.simpleMessage("بازیابی حساب کاربری"), @@ -316,6 +322,7 @@ class MessageLookup extends MessageLookupByLibrary { "resendEmail": MessageLookupByLibrary.simpleMessage("ارسال مجدد ایمیل"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("بازنشانی رمز عبور"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "retry": MessageLookupByLibrary.simpleMessage("سعی مجدد"), "reviewSuggestions": MessageLookupByLibrary.simpleMessage("مرور پیشنهادها"), @@ -420,7 +427,7 @@ class MessageLookup extends MessageLookupByLibrary { "viewer": MessageLookupByLibrary.simpleMessage("بیننده"), "weAreOpenSource": MessageLookupByLibrary.simpleMessage("ما متن‌باز هستیم!"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("ضعیف"), "welcomeBack": MessageLookupByLibrary.simpleMessage("خوش آمدید!"), "whatsNew": MessageLookupByLibrary.simpleMessage("تغییرات جدید"), @@ -428,6 +435,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesConvertToViewer": MessageLookupByLibrary.simpleMessage("بله، تبدیل به بیننده شود"), "yesLogout": MessageLookupByLibrary.simpleMessage("بله، خارج می‌شوم"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("شما"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage( "شما در یک برنامه خانوادگی هستید!"), diff --git a/mobile/lib/generated/intl/messages_fr.dart b/mobile/lib/generated/intl/messages_fr.dart index b8b52697dc..f1f26ff085 100644 --- a/mobile/lib/generated/intl/messages_fr.dart +++ b/mobile/lib/generated/intl/messages_fr.dart @@ -20,37 +20,37 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'fr'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Ajouter un coauteur', one: 'Ajouter un coauteur', other: 'Ajouter des coauteurs')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Ajoutez un objet', other: 'Ajoutez des objets')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Votre extension de ${storageAmount} est valable jusqu\'au ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, zero: 'Ajouter un lecteur', one: 'Ajouter un lecteur', other: 'Ajouter des lecteurs')}"; - static String m9(emailOrName) => "Ajouté par ${emailOrName}"; + static String m10(emailOrName) => "Ajouté par ${emailOrName}"; - static String m10(albumName) => "Ajouté avec succès à ${albumName}"; + static String m11(albumName) => "Ajouté avec succès à ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Aucun Participant', one: '1 Participant', other: '${count} Participants')}"; - static String m12(versionValue) => "Version : ${versionValue}"; + static String m13(versionValue) => "Version : ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} gratuit"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Veuillez d\'abord annuler votre abonnement existant de ${paymentProvider}"; - static String m15(user) => + static String m16(user) => "${user} ne pourra pas ajouter plus de photos à cet album\n\nIl pourra toujours supprimer les photos existantes ajoutées par eux"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Votre famille a demandé ${storageAmountInGb} GB jusqu\'à présent', @@ -60,135 +60,135 @@ class MessageLookup extends MessageLookupByLibrary { 'Vous avez réclamé ${storageAmountInGb} GB jusqu\'à présent!', })}"; - static String m17(albumName) => "Lien collaboratif créé pour ${albumName}"; + static String m18(albumName) => "Lien collaboratif créé pour ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Veuillez contacter ${familyAdminEmail} pour gérer votre abonnement"; - static String m19(provider) => + static String m20(provider) => "Veuillez nous contacter à support@ente.io pour gérer votre abonnement ${provider}."; - static String m20(endpoint) => "Connecté à ${endpoint}"; + static String m21(endpoint) => "Connecté à ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Supprimer le fichier', other: 'Supprimer ${count} fichiers')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Suppression de ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Cela supprimera le lien public pour accéder à \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Veuillez envoyer un e-mail à ${supportEmail} depuis votre adresse enregistrée"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Vous avez nettoyé ${Intl.plural(count, one: '${count} fichier dupliqué', other: '${count} fichiers dupliqués')}, sauvegarde (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} fichiers, ${formattedSize} chacun"; - static String m27(newEmail) => "L\'e-mail a été changé en ${newEmail}"; + static String m28(newEmail) => "L\'e-mail a été changé en ${newEmail}"; - static String m28(email) => + static String m29(email) => "${email} n\'a pas de compte Ente.\n\nEnvoyez une invitation pour partager des photos."; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "${Intl.plural(count, one: '1 fichier sur cet appareil a été sauvegardé en toute sécurité', other: '${formattedNumber} fichiers sur cet appareil ont été sauvegardés en toute sécurité')}"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "${Intl.plural(count, one: '1 fichier dans cet album a été sauvegardé en toute sécurité', other: '${formattedNumber} fichiers dans cet album ont été sauvegardés en toute sécurité')}"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "${storageAmountInGB} Go chaque fois que quelqu\'un s\'inscrit à une offre payante et applique votre code"; - static String m32(endDate) => "Essai gratuit valide jusqu’au ${endDate}"; + static String m33(endDate) => "Essai gratuit valide jusqu’au ${endDate}"; - static String m33(count) => + static String m34(count) => "Vous pouvez toujours ${Intl.plural(count, one: 'y', other: 'y')} accéder sur ente tant que vous avez un abonnement actif"; - static String m34(sizeInMBorGB) => "Libérer ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "Libérer ${sizeInMBorGB}"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'Peut être supprimé de l\'appareil pour libérer ${formattedSize}', other: 'Peuvent être supprimés de l\'appareil pour libérer ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Traitement en cours ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} objet', other: '${count} objets')}"; - static String m38(expiryTime) => "Le lien expirera le ${expiryTime}"; + static String m39(expiryTime) => "Le lien expirera le ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, one: '${formattedCount} mémoire', other: '${formattedCount} souvenirs')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Déplacez l\'objet', other: 'Déplacez des objets')}"; - static String m40(albumName) => "Déplacé avec succès vers ${albumName}"; + static String m41(albumName) => "Déplacé avec succès vers ${albumName}"; - static String m41(name) => "Pas ${name}?"; + static String m42(name) => "Pas ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Veuillez contacter ${familyAdminEmail} pour modifier votre code."; static String m0(passwordStrengthValue) => "Sécurité du mot de passe : ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Veuillez contacter le support ${providerName} si vous avez été facturé"; - static String m44(endDate) => + static String m45(endDate) => "Essai gratuit valable jusqu\'à ${endDate}.\nVous pouvez choisir un plan payant par la suite."; - static String m45(toEmail) => "Merci de nous envoyer un e-mail à ${toEmail}"; + static String m46(toEmail) => "Merci de nous envoyer un e-mail à ${toEmail}"; - static String m46(toEmail) => "Envoyez les logs à ${toEmail}"; + static String m47(toEmail) => "Envoyez les logs à ${toEmail}"; - static String m47(folderName) => "Traitement de ${folderName}..."; + static String m48(folderName) => "Traitement de ${folderName}..."; - static String m48(storeName) => "Notez-nous sur ${storeName}"; + static String m49(storeName) => "Notez-nous sur ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Vous recevez tous les deux ${storageInGB} GB* gratuits"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} sera retiré de cet album partagé\n\nToutes les photos ajoutées par eux seront également retirées de l\'album"; - static String m51(endDate) => "Renouvellement le ${endDate}"; + static String m52(endDate) => "Renouvellement le ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} résultat trouvé', other: '${count} résultats trouvés')}"; - static String m3(count) => "${count} sélectionné(s)"; + static String m4(count) => "${count} sélectionné(s)"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "${count} sélectionné(s) (${yourCount} à vous)"; - static String m54(verificationID) => + static String m55(verificationID) => "Voici mon ID de vérification : ${verificationID} pour ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Hé, pouvez-vous confirmer qu\'il s\'agit de votre ID de vérification ente.io : ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Code de parrainage Ente : ${referralCode} \n\nValidez le dans Paramètres → Général → Références pour obtenir ${referralStorageInGB} Go gratuitement après votre inscription à un plan payant\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Partagez avec des personnes spécifiques', one: 'Partagé avec 1 personne', other: 'Partagé avec ${numberOfPeople} des gens')}"; - static String m57(emailIDs) => "Partagé avec ${emailIDs}"; - - static String m58(fileType) => - "Elle ${fileType} sera supprimée de votre appareil."; + static String m58(emailIDs) => "Partagé avec ${emailIDs}"; static String m59(fileType) => + "Elle ${fileType} sera supprimée de votre appareil."; + + static String m60(fileType) => "Cette ${fileType} est à la fois sur ente et sur votre appareil."; - static String m60(fileType) => "Cette ${fileType} sera supprimée de l\'Ente."; + static String m61(fileType) => "Cette ${fileType} sera supprimée de l\'Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} Go"; + static String m1(storageAmountInGB) => "${storageAmountInGB} Go"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -216,7 +216,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Vérifier ${email}"; - static String m1(email) => + static String m2(email) => "Nous avons envoyé un e-mail à ${email}"; static String m72(count) => @@ -242,10 +242,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter un nouvel email"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Ajouter un collaborateur"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Ajouter depuis l\'appareil"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Ajouter la localisation"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Ajouter"), @@ -253,7 +253,7 @@ class MessageLookup extends MessageLookupByLibrary { "addNew": MessageLookupByLibrary.simpleMessage("Ajouter un nouveau"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage( "Détails des modules complémentaires"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Modules complémentaires"), "addPhotos": MessageLookupByLibrary.simpleMessage("Ajouter des photos"), @@ -266,12 +266,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter à un album masqué"), "addViewer": MessageLookupByLibrary.simpleMessage("Ajouter un observateur"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage( "Ajoutez vos photos maintenant"), "addedAs": MessageLookupByLibrary.simpleMessage("Ajouté comme"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Ajout aux favoris..."), "advanced": MessageLookupByLibrary.simpleMessage("Avancé"), @@ -282,7 +282,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Après 1 semaine"), "after1Year": MessageLookupByLibrary.simpleMessage("Après 1 an"), "albumOwner": MessageLookupByLibrary.simpleMessage("Propriétaire"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Titre de l\'album"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album mis à jour"), @@ -290,6 +290,8 @@ class MessageLookup extends MessageLookupByLibrary { "allClear": MessageLookupByLibrary.simpleMessage("✨ Tout est effacé"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage( "Tous les souvenirs conservés"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Autoriser les personnes avec le lien à ajouter des photos à l\'album partagé."), "allowAddingPhotos": MessageLookupByLibrary.simpleMessage( @@ -321,7 +323,7 @@ class MessageLookup extends MessageLookupByLibrary { "Verrouillage d\'applications"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Choisissez entre l\'écran de verrouillage par défaut de votre appareil et un écran de verrouillage personnalisé avec un code PIN ou un mot de passe."), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Appliquer"), "applyCodeTitle": @@ -347,6 +349,9 @@ class MessageLookup extends MessageLookupByLibrary { "Voulez-vous vraiment vous déconnecter ?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Êtes-vous sûr de vouloir renouveler ?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Votre abonnement a été annulé. Souhaitez-vous partager la raison ?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -401,7 +406,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "L\'appairage automatique ne fonctionne qu\'avec les appareils qui prennent en charge Chromecast."), "available": MessageLookupByLibrary.simpleMessage("Disponible"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Dossiers sauvegardés"), "backup": MessageLookupByLibrary.simpleMessage("Sauvegarde"), @@ -432,10 +437,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Vous ne pouvez supprimer que les fichiers que vous possédez"), "cancel": MessageLookupByLibrary.simpleMessage("Annuler"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Annuler l\'abonnement"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Les fichiers partagés ne peuvent pas être supprimés"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -469,7 +474,7 @@ class MessageLookup extends MessageLookupByLibrary { "Réclamer le stockage gratuit"), "claimMore": MessageLookupByLibrary.simpleMessage("Réclamez plus !"), "claimed": MessageLookupByLibrary.simpleMessage("Réclamée"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage( "Effacer les éléments non classés"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -500,7 +505,7 @@ class MessageLookup extends MessageLookupByLibrary { "Créez un lien pour permettre aux gens d\'ajouter et de voir des photos dans votre album partagé sans avoir besoin d\'une application ente ou d\'un compte. Idéal pour récupérer des photos d\'événement."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Lien collaboratif"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Collaborateur"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -533,10 +538,10 @@ class MessageLookup extends MessageLookupByLibrary { "Confirmer la clé de récupération"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Connexion à l\'appareil"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Contacter l\'assistance"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Contacts"), "contents": MessageLookupByLibrary.simpleMessage("Contenus"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuer"), @@ -582,7 +587,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage( "L\'utilisation actuelle est "), "custom": MessageLookupByLibrary.simpleMessage("Personnaliser"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Sombre"), "dayToday": MessageLookupByLibrary.simpleMessage("Aujourd\'hui"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Hier"), @@ -621,12 +626,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Supprimer de l\'appareil"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Supprimé de Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Supprimer la localisation"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Supprimer des photos"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Il manque une fonction clé dont j\'ai besoin"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -668,7 +673,7 @@ class MessageLookup extends MessageLookupByLibrary { "Les observateurs peuvent toujours prendre des captures d\'écran ou enregistrer une copie de vos photos en utilisant des outils externes"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Veuillez remarquer"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Désactiver la double-authentification"), "disablingTwofactorAuthentication": @@ -712,9 +717,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Échec du téléchargement"), "downloading": MessageLookupByLibrary.simpleMessage("Téléchargement en cours..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Éditer"), "editLocation": MessageLookupByLibrary.simpleMessage("Modifier l’emplacement"), @@ -727,8 +732,8 @@ class MessageLookup extends MessageLookupByLibrary { "Les modifications de l\'emplacement ne seront visibles que dans Ente"), "eligible": MessageLookupByLibrary.simpleMessage("éligible"), "email": MessageLookupByLibrary.simpleMessage("E-mail"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage( "Vérification de l\'adresse e-mail"), "emailYourLogs": @@ -838,8 +843,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Types de fichiers"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Types et noms de fichiers"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Fichiers supprimés"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage( @@ -854,26 +859,26 @@ class MessageLookup extends MessageLookupByLibrary { "foundFaces": MessageLookupByLibrary.simpleMessage("Visages trouvés"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Stockage gratuit réclamé"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Stockage gratuit utilisable"), "freeTrial": MessageLookupByLibrary.simpleMessage("Essai gratuit"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Libérer de l\'espace sur l\'appareil"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Économisez de l\'espace sur votre appareil en effaçant les fichiers qui ont déjà été sauvegardés."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Libérer de l\'espace"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Jusqu\'à 1000 souvenirs affichés dans la galerie"), "general": MessageLookupByLibrary.simpleMessage("Général"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Génération des clés de chiffrement..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Allez aux réglages"), "googlePlayId": @@ -955,7 +960,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Il semble qu\'une erreur s\'est produite. Veuillez réessayer après un certain temps. Si l\'erreur persiste, veuillez contacter notre équipe d\'assistance."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Les éléments montrent le nombre de jours restants avant la suppression définitive"), @@ -986,7 +991,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Limite d\'appareil"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Activé"), "linkExpired": MessageLookupByLibrary.simpleMessage("Expiré"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Expiration du lien"), "linkHasExpired": @@ -1075,7 +1080,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Cartes"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Marchandise"), "mlConsent": MessageLookupByLibrary.simpleMessage( "Activer l\'apprentissage automatique"), @@ -1101,12 +1106,12 @@ class MessageLookup extends MessageLookupByLibrary { "mostRecent": MessageLookupByLibrary.simpleMessage("Les plus récents"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Les plus pertinents"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Déplacer vers l\'album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Déplacer vers un album masqué"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Déplacé dans la corbeille"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -1155,7 +1160,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Aucun résultat trouvé"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage("Aucun verrou système trouvé"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage( "Rien n\'a encore été partagé avec vous"), "nothingToSeeHere": MessageLookupByLibrary.simpleMessage( @@ -1165,7 +1170,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("Sur l\'appareil"), "onEnte": MessageLookupByLibrary.simpleMessage( "Sur ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Oups"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Oups, impossible d\'enregistrer les modifications"), @@ -1208,7 +1214,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Échec du paiement"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Malheureusement votre paiement a échoué. Veuillez contacter le support et nous vous aiderons !"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Éléments en attente"), "pendingSync": @@ -1238,7 +1244,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Verrouillage du code PIN"), "playOnTv": MessageLookupByLibrary.simpleMessage("Lire l\'album sur la TV"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Abonnement au PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1250,14 +1256,14 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Merci de contacter l\'assistance si cette erreur persiste"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Veuillez accorder la permission"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Veuillez vous reconnecter"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Veuillez sélectionner les liens rapides à supprimer"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Veuillez réessayer"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1283,7 +1289,7 @@ class MessageLookup extends MessageLookupByLibrary { "privateBackups": MessageLookupByLibrary.simpleMessage("Sauvegardes privées"), "privateSharing": MessageLookupByLibrary.simpleMessage("Partage privé"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Lien public créé"), "publicLinkEnabled": @@ -1294,7 +1300,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Évaluer l\'application"), "rateUs": MessageLookupByLibrary.simpleMessage("Évaluez-nous"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Récupérer"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Récupérer un compte"), @@ -1329,7 +1335,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Donnez ce code à vos amis"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Ils s\'inscrivent à une offre payante"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Parrainages"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Les recommandations sont actuellement en pause"), @@ -1357,7 +1363,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Supprimer le lien"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Supprimer le participant"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage( "Supprimer le libellé d\'une personne"), "removePublicLink": @@ -1377,7 +1383,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Renommer le fichier"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renouveler l’abonnement"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Signaler un bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Signaler un bug"), "resendEmail": @@ -1386,6 +1392,7 @@ class MessageLookup extends MessageLookupByLibrary { "Réinitialiser les fichiers ignorés"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage( "Réinitialiser le mot de passe"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage( "Réinitialiser aux valeurs par défaut"), "restore": MessageLookupByLibrary.simpleMessage("Restaurer"), @@ -1451,7 +1458,7 @@ class MessageLookup extends MessageLookupByLibrary { "Grouper les photos qui sont prises dans un certain angle d\'une photo"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invitez des gens, et vous verrez ici toutes les photos qu\'ils partagent"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Sécurité"), "selectALocation": MessageLookupByLibrary.simpleMessage("Sélectionnez un emplacement"), @@ -1480,8 +1487,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Les éléments sélectionnés seront supprimés de tous les albums et déplacés dans la corbeille."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Envoyer"), "sendEmail": MessageLookupByLibrary.simpleMessage("Envoyer un e-mail"), "sendInvite": @@ -1513,16 +1520,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage( "Partagez un album maintenant"), "shareLink": MessageLookupByLibrary.simpleMessage("Partager le lien"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Partager uniquement avec les personnes que vous voulez"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Téléchargez Ente pour que nous puissions facilement partager des photos et des vidéos de qualité originale\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Partager avec des utilisateurs non-Ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Partagez votre premier album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1533,7 +1540,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nouvelles photos partagées"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Recevoir des notifications quand quelqu\'un ajoute une photo à un album partagé dont vous faites partie"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Partagés avec moi"), "sharedWithYou": @@ -1551,11 +1558,11 @@ class MessageLookup extends MessageLookupByLibrary { "Déconnecter les autres appareils"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "J\'accepte les conditions d\'utilisation et la politique de confidentialité"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Elle sera supprimée de tous les albums."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Ignorer"), "social": MessageLookupByLibrary.simpleMessage("Réseaux Sociaux"), "someItemsAreInBothEnteAndYourDevice": @@ -1601,7 +1608,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Stockage"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Famille"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Vous"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Limite de stockage atteinte"), "storageUsageInfo": m62, @@ -1810,7 +1817,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Nous ne prenons pas en charge l\'édition des photos et des albums que vous ne possédez pas encore"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Securité Faible"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bienvenue !"), "whatsNew": MessageLookupByLibrary.simpleMessage("Nouveautés"), @@ -1827,6 +1834,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Oui, se déconnecter"), "yesRemove": MessageLookupByLibrary.simpleMessage("Oui, supprimer"), "yesRenew": MessageLookupByLibrary.simpleMessage("Oui, renouveler"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Vous"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage( "Vous êtes sur un plan familial !"), diff --git a/mobile/lib/generated/intl/messages_gu.dart b/mobile/lib/generated/intl/messages_gu.dart index 6c1d7e4d90..03e6eae36e 100644 --- a/mobile/lib/generated/intl/messages_gu.dart +++ b/mobile/lib/generated/intl/messages_gu.dart @@ -21,5 +21,15 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'gu'; final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => {}; + static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") + }; } diff --git a/mobile/lib/generated/intl/messages_he.dart b/mobile/lib/generated/intl/messages_he.dart index 4469d82016..2bb258a60b 100644 --- a/mobile/lib/generated/intl/messages_he.dart +++ b/mobile/lib/generated/intl/messages_he.dart @@ -20,96 +20,96 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'he'; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'הוסף פריט', two: 'הוסף פריטים', many: 'הוסף פריטים', other: 'הוסף פריטים')}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'אין משתתפים', one: '1 משתתף', two: '2 משתתפים', other: '${count} משתתפים')}"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "אנא בטל את המנוי הקיים מ-${paymentProvider} קודם"; - static String m15(user) => + static String m16(user) => "${user} לא יוכל להוסיף עוד תמונות לאלבום זה\n\nהם עדיין יכולו להסיר תמונות קיימות שנוספו על ידיהם"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'קיבלת ${storageAmountInGb} GB עד כה', 'false': 'קיבלת ${storageAmountInGb} GB עד כה', 'other': 'קיבלת ${storageAmountInGb} GB עד כה!', })}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "אנא צור קשר עם ${familyAdminEmail} על מנת לנהל את המנוי שלך"; - static String m19(provider) => + static String m20(provider) => "אנא צור איתנו קשר ב-support@ente.io על מנת לנהל את המנוי ${provider}."; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'מחק ${count} פריט', two: 'מחק ${count} פריטים', other: 'מחק ${count} פריטים')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "מוחק ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "זה יסיר את הלינק הפומבי שדרכו ניתן לגשת ל\"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "אנא תשלח דוא\"ל ל${supportEmail} מהכתובת דוא\"ל שנרשמת איתה"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} קבצים, כל אחד ${formattedSize}"; - static String m28(email) => + static String m29(email) => "לא נמצא חשבון ente ל-${email}.\n\nשלח להם הזמנה על מנת לשתף תמונות."; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "${storageAmountInGB} GB כל פעם שמישהו נרשם עבור תוכנית בתשלום ומחיל את הקוד שלך"; - static String m32(endDate) => "ניסיון חינם בתוקף עד ל-${endDate}"; + static String m33(endDate) => "ניסיון חינם בתוקף עד ל-${endDate}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} פריט', two: '${count} פריטים', many: '${count} פריטים', other: '${count} פריטים')}"; - static String m38(expiryTime) => "תוקף הקישור יפוג ב-${expiryTime}"; + static String m39(expiryTime) => "תוקף הקישור יפוג ב-${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, one: '${formattedCount} זכרון', two: '${formattedCount} זכרונות', many: '${formattedCount} זכרונות', other: '${formattedCount} זכרונות')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'הזז פריט', two: 'הזז פריטים', many: 'הזז פריטים', other: 'הזז פריטים')}"; static String m0(passwordStrengthValue) => "חוזק הסיסמא: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "אנא דבר עם התמיכה של ${providerName} אם אתה חוייבת"; - static String m48(storeName) => "דרג אותנו ב-${storeName}"; + static String m49(storeName) => "דרג אותנו ב-${storeName}"; - static String m49(storageInGB) => "3. שניכים מקבלים ${storageInGB} GB* בחינם"; + static String m50(storageInGB) => "3. שניכים מקבלים ${storageInGB} GB* בחינם"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} יוסר מהאלבום המשותף הזה\n\nגם תמונות שנוספו על ידיהם יוסרו מהאלבום"; - static String m3(count) => "${count} נבחרו"; + static String m4(count) => "${count} נבחרו"; - static String m53(count, yourCount) => "${count} נבחרו (${yourCount} שלך)"; + static String m54(count, yourCount) => "${count} נבחרו (${yourCount} שלך)"; - static String m54(verificationID) => + static String m55(verificationID) => "הנה מזהה האימות שלי: ${verificationID} עבור ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "היי, תוכל לוודא שזה מזהה האימות שלך של ente.io: ${verificationID}"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'שתף עם אנשים ספציפיים', one: 'שותף עם איש 1', two: 'שותף עם 2 אנשים', other: 'שותף עם ${numberOfPeople} אנשים')}"; - static String m57(emailIDs) => "הושתף ע\"י ${emailIDs}"; + static String m58(emailIDs) => "הושתף ע\"י ${emailIDs}"; - static String m58(fileType) => "${fileType} יימחק מהמכשיר שלך."; + static String m59(fileType) => "${fileType} יימחק מהמכשיר שלך."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m64(endDate) => "המנוי שלך יבוטל ב-${endDate}"; @@ -121,7 +121,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "אמת ${email}"; - static String m1(email) => "שלחנו דוא\"ל ל${email}"; + static String m2(email) => "שלחנו דוא\"ל ל${email}"; static String m72(count) => "${Intl.plural(count, one: 'לפני ${count} שנה', two: 'לפני ${count} שנים', many: 'לפני ${count} שנים', other: 'לפני ${count} שנים')}"; @@ -141,7 +141,7 @@ class MessageLookup extends MessageLookupByLibrary { "addANewEmail": MessageLookupByLibrary.simpleMessage("הוסף דוא\"ל חדש"), "addCollaborator": MessageLookupByLibrary.simpleMessage("הוסף משתף פעולה"), - "addItem": m6, + "addItem": m7, "addLocationButton": MessageLookupByLibrary.simpleMessage("הוסף"), "addMore": MessageLookupByLibrary.simpleMessage("הוסף עוד"), "addPhotos": MessageLookupByLibrary.simpleMessage("הוסף תמונות"), @@ -158,13 +158,15 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("אחרי שבוע 1"), "after1Year": MessageLookupByLibrary.simpleMessage("אחרי שנה 1"), "albumOwner": MessageLookupByLibrary.simpleMessage("בעלים"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("כותרת האלבום"), "albumUpdated": MessageLookupByLibrary.simpleMessage("האלבום עודכן"), "albums": MessageLookupByLibrary.simpleMessage("אלבומים"), "allClear": MessageLookupByLibrary.simpleMessage("✨ הכל נוקה"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("כל הזכרונות נשמרו"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "בנוסף אפשר לאנשים עם הלינק להוסיף תמונות לאלבום המשותף."), "allowAddingPhotos": @@ -197,6 +199,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("אתה בטוח שאתה רוצה להתנתק?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage("אתה בטוח שאתה רוצה לחדש?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "המנוי שלך בוטל. תרצה לשתף את הסיבה?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -244,9 +249,9 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "יכול להסיר רק קבצים שבבעלותך"), "cancel": MessageLookupByLibrary.simpleMessage("בטל"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("בטל מנוי"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "לא ניתן למחוק את הקבצים המשותפים"), "changeEmail": MessageLookupByLibrary.simpleMessage("שנה דוא\"ל"), @@ -262,7 +267,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("תבע מקום אחסון בחינם"), "claimMore": MessageLookupByLibrary.simpleMessage("תבע עוד!"), "claimed": MessageLookupByLibrary.simpleMessage("נתבע"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "click": MessageLookupByLibrary.simpleMessage("• לחץ"), "close": MessageLookupByLibrary.simpleMessage("סגור"), "clubByCaptureTime": @@ -302,10 +307,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("אמת את מפתח השחזור"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage("אמת את מפתח השחזור"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("צור קשר עם התמיכה"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "continueLabel": MessageLookupByLibrary.simpleMessage("המשך"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage("המשך עם ניסיון חינמי"), @@ -363,9 +368,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("למחוק אלבומים ריקים?"), "deleteFromBoth": MessageLookupByLibrary.simpleMessage("מחק משניהם"), "deleteFromDevice": MessageLookupByLibrary.simpleMessage("מחק מהמכשיר"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deletePhotos": MessageLookupByLibrary.simpleMessage("מחק תמונות"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage("חסר מאפיין מרכזי שאני צריך"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -390,7 +395,7 @@ class MessageLookup extends MessageLookupByLibrary { "צופים יכולים עדיין לקחת צילומי מסך או לשמור עותק של התמונות שלך בעזרת כלים חיצוניים"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("שים לב"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage("השבת דו-גורמי"), "discord": MessageLookupByLibrary.simpleMessage("Discord"), @@ -401,12 +406,12 @@ class MessageLookup extends MessageLookupByLibrary { "download": MessageLookupByLibrary.simpleMessage("הורד"), "downloadFailed": MessageLookupByLibrary.simpleMessage("ההורדה נכשלה"), "downloading": MessageLookupByLibrary.simpleMessage("מוריד..."), - "dropSupportEmail": m24, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("ערוך"), "eligible": MessageLookupByLibrary.simpleMessage("זכאי"), "email": MessageLookupByLibrary.simpleMessage("דוא\"ל"), - "emailNoEnteAccount": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("אימות מייל"), "empty": MessageLookupByLibrary.simpleMessage("ריק"), @@ -475,11 +480,11 @@ class MessageLookup extends MessageLookupByLibrary { "forgotPassword": MessageLookupByLibrary.simpleMessage("שכחתי סיסמה"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("מקום אחסון בחינם נתבע"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("מקום אחסון שמיש"), "freeTrial": MessageLookupByLibrary.simpleMessage("ניסיון חינמי"), - "freeTrialValidTill": m32, + "freeTrialValidTill": m33, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("פנה אחסון במכשיר"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("פנה מקום"), @@ -517,7 +522,7 @@ class MessageLookup extends MessageLookupByLibrary { "invite": MessageLookupByLibrary.simpleMessage("הזמן"), "inviteYourFriends": MessageLookupByLibrary.simpleMessage("הזמן את חברייך"), - "itemCount": m37, + "itemCount": m38, "itemsWillBeRemovedFromAlbum": MessageLookupByLibrary.simpleMessage( "הפריטים שנבחרו יוסרו מהאלבום הזה"), "keepPhotos": MessageLookupByLibrary.simpleMessage("השאר תמונות"), @@ -539,7 +544,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("מגבלת כמות מכשירים"), "linkEnabled": MessageLookupByLibrary.simpleMessage("מאופשר"), "linkExpired": MessageLookupByLibrary.simpleMessage("פג תוקף"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("תאריך תפוגה ללינק"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("הקישור פג תוקף"), @@ -567,13 +572,13 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("מפות"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("סחורה"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("פלאפון, דפדפן, שולחן עבודה"), "moderateStrength": MessageLookupByLibrary.simpleMessage("מתונה"), "monthly": MessageLookupByLibrary.simpleMessage("חודשי"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("הזז לאלבום"), "movedToTrash": MessageLookupByLibrary.simpleMessage("הועבר לאשפה"), "movingFilesToAlbum": @@ -600,6 +605,7 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("על המכשיר"), "onEnte": MessageLookupByLibrary.simpleMessage("באנטע"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("אופס"), "oopsSomethingWentWrong": MessageLookupByLibrary.simpleMessage("אופס, משהו השתבש"), @@ -617,7 +623,7 @@ class MessageLookup extends MessageLookupByLibrary { "אנחנו לא שומרים את הסיסמא הזו, לכן אם אתה שוכח אותה, אנחנו לא יכולים לפענח את המידע שלך"), "paymentDetails": MessageLookupByLibrary.simpleMessage("פרטי תשלום"), "paymentFailed": MessageLookupByLibrary.simpleMessage("התשלום נכשל"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "peopleUsingYourCode": MessageLookupByLibrary.simpleMessage("אנשים משתמשים בקוד שלך"), "permanentlyDelete": @@ -659,7 +665,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("צור ticket"), "rateTheApp": MessageLookupByLibrary.simpleMessage("דרג את האפליקציה"), "rateUs": MessageLookupByLibrary.simpleMessage("דרג אותנו"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("שחזר"), "recoverAccount": MessageLookupByLibrary.simpleMessage("שחזר חשבון"), "recoverButton": MessageLookupByLibrary.simpleMessage("שחזר"), @@ -685,7 +691,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. תמסור את הקוד הזה לחברייך"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. הם נרשמים עבור תוכנית בתשלום"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("הפניות"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage("הפניות כרגע מושהות"), @@ -701,7 +707,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("הסר מהאלבום?"), "removeLink": MessageLookupByLibrary.simpleMessage("הסרת קישור"), "removeParticipant": MessageLookupByLibrary.simpleMessage("הסר משתתף"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePublicLink": MessageLookupByLibrary.simpleMessage("הסר לינק ציבורי"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -717,6 +723,7 @@ class MessageLookup extends MessageLookupByLibrary { "resendEmail": MessageLookupByLibrary.simpleMessage("שלח דוא\"ל מחדש"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("איפוס סיסמה"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "restore": MessageLookupByLibrary.simpleMessage("שחזר"), "restoreToAlbum": MessageLookupByLibrary.simpleMessage("שחזר לאלבום"), "restoringFiles": @@ -752,8 +759,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedFoldersWillBeEncryptedAndBackedUp": MessageLookupByLibrary.simpleMessage( "התיקיות שנבחרו יוצפנו ויגובו"), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("שלח"), "sendEmail": MessageLookupByLibrary.simpleMessage("שלח דוא\"ל"), "sendInvite": MessageLookupByLibrary.simpleMessage("שלח הזמנה"), @@ -772,15 +779,15 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("שתף אלבום עכשיו"), "shareLink": MessageLookupByLibrary.simpleMessage("שתף קישור"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage("שתף רק אם אנשים שאתה בוחר"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "הורד את ente על מנת שנוכל לשתף תמונות וסרטונים באיכות המקור באופן קל\n\nhttps://ente.io"), "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "שתף עם משתמשים שהם לא של ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("שתף את האלבום הראשון שלך"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -791,13 +798,13 @@ class MessageLookup extends MessageLookupByLibrary { "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "קבל התראות כשמישהו מוסיף תמונה לאלבום משותף שאתה חלק ממנו"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("שותף איתי"), "sharing": MessageLookupByLibrary.simpleMessage("משתף..."), "showMemories": MessageLookupByLibrary.simpleMessage("הצג זכרונות"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "אני מסכים לתנאי שירות ולמדיניות הפרטיות"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage("זה יימחק מכל האלבומים."), "skip": MessageLookupByLibrary.simpleMessage("דלג"), @@ -826,7 +833,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("אחסון"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("משפחה"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("אתה"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("גבול מקום האחסון נחרג"), "strongStrength": MessageLookupByLibrary.simpleMessage("חזקה"), @@ -919,7 +926,7 @@ class MessageLookup extends MessageLookupByLibrary { "אנא בקר ב-web.ente.io על מנת לנהל את המנוי שלך"), "weAreOpenSource": MessageLookupByLibrary.simpleMessage("הקוד שלנו פתוח!"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("חלשה"), "welcomeBack": MessageLookupByLibrary.simpleMessage("ברוך שובך!"), "yearly": MessageLookupByLibrary.simpleMessage("שנתי"), @@ -932,6 +939,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("כן, התנתק"), "yesRemove": MessageLookupByLibrary.simpleMessage("כן, הסר"), "yesRenew": MessageLookupByLibrary.simpleMessage("כן, חדש"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("אתה"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("אתה על תוכנית משפחתית!"), diff --git a/mobile/lib/generated/intl/messages_hi.dart b/mobile/lib/generated/intl/messages_hi.dart index ff4756d8d4..3f3eaed6fb 100644 --- a/mobile/lib/generated/intl/messages_hi.dart +++ b/mobile/lib/generated/intl/messages_hi.dart @@ -25,6 +25,11 @@ class MessageLookup extends MessageLookupByLibrary { "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("आपका पुनः स्वागत है"), "activeSessions": MessageLookupByLibrary.simpleMessage("एक्टिव सेशन"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "आपका अकाउंट हटाने का मुख्य कारण क्या है?"), "cancel": MessageLookupByLibrary.simpleMessage("रद्द करें"), @@ -80,11 +85,13 @@ class MessageLookup extends MessageLookupByLibrary { "noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage( "हमारे एंड-टू-एंड एन्क्रिप्शन प्रोटोकॉल की प्रकृति के कारण, आपके डेटा को आपके पासवर्ड या रिकवरी कुंजी के बिना डिक्रिप्ट नहीं किया जा सकता है"), "ok": MessageLookupByLibrary.simpleMessage("ठीक है"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("ओह!"), "password": MessageLookupByLibrary.simpleMessage("पासवर्ड"), "recoverButton": MessageLookupByLibrary.simpleMessage("पुनः प्राप्त"), "recoverySuccessful": MessageLookupByLibrary.simpleMessage("रिकवरी सफल हुई!"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "selectReason": MessageLookupByLibrary.simpleMessage("कारण चुनें"), "sendEmail": MessageLookupByLibrary.simpleMessage("ईमेल भेजें"), "somethingWentWrongPleaseTryAgain": @@ -105,6 +112,8 @@ class MessageLookup extends MessageLookupByLibrary { "verify": MessageLookupByLibrary.simpleMessage("सत्यापित करें"), "verifyEmail": MessageLookupByLibrary.simpleMessage("ईमेल सत्यापित करें"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage( "आपका अकाउंट डिलीट कर दिया गया है") }; diff --git a/mobile/lib/generated/intl/messages_id.dart b/mobile/lib/generated/intl/messages_id.dart index 46889d9f3a..a0b515b185 100644 --- a/mobile/lib/generated/intl/messages_id.dart +++ b/mobile/lib/generated/intl/messages_id.dart @@ -20,33 +20,33 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'id'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, other: 'Tambahkan kolaborator')}"; - static String m6(count) => "${Intl.plural(count, other: 'Tambahkan item')}"; + static String m7(count) => "${Intl.plural(count, other: 'Tambahkan item')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Add-on ${storageAmount} kamu berlaku sampai ${endDate}"; - static String m9(emailOrName) => "Ditambahkan oleh ${emailOrName}"; + static String m10(emailOrName) => "Ditambahkan oleh ${emailOrName}"; - static String m10(albumName) => "Berhasil ditambahkan ke ${albumName}"; + static String m11(albumName) => "Berhasil ditambahkan ke ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: '0 Peserta', one: '1 Peserta', other: '${count} Peserta')}"; - static String m12(versionValue) => "Versi: ${versionValue}"; + static String m13(versionValue) => "Versi: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} tersedia"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Harap batalkan langganan kamu di ${paymentProvider} terlebih dahulu"; - static String m15(user) => + static String m16(user) => "${user} tidak akan dapat menambahkan foto lagi ke album ini\n\nIa masih dapat menghapus foto yang ditambahkan olehnya sendiri"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Keluargamu saat ini telah memperoleh ${storageAmountInGb} GB', @@ -54,126 +54,126 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Kamu saat ini telah memperoleh ${storageAmountInGb} GB!', })}"; - static String m17(albumName) => "Link kolaborasi terbuat untuk ${albumName}"; + static String m18(albumName) => "Link kolaborasi terbuat untuk ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Silakan hubungi ${familyAdminEmail} untuk mengatur langgananmu"; - static String m19(provider) => + static String m20(provider) => "Silakan hubungi kami di support@ente.io untuk mengatur langganan ${provider} kamu."; - static String m20(endpoint) => "Terhubung ke ${endpoint}"; + static String m21(endpoint) => "Terhubung ke ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Hapus ${count} item', other: 'Hapus ${count} item')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Menghapus ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Ini akan menghapus link publik yang digunakan untuk mengakses \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Silakan kirimkan email ke ${supportEmail} dari alamat email terdaftar kamu"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Kamu telah menghapus ${Intl.plural(count, other: '${count} file duplikat')} dan membersihkan (${storageSaved}!)"; - static String m27(newEmail) => "Email diubah menjadi ${newEmail}"; + static String m28(newEmail) => "Email diubah menjadi ${newEmail}"; - static String m28(email) => + static String m29(email) => "${email} tidak punya akun Ente.\n\nUndang dia untuk berbagi foto."; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "${Intl.plural(count, other: '${formattedNumber} file')} di perangkat ini telah berhasil dicadangkan"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "${Intl.plural(count, other: '${formattedNumber} file')} dalam album ini telah berhasil dicadangkan"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "${storageAmountInGB} GB setiap kali orang mendaftar dengan paket berbayar lalu menerapkan kode milikmu"; - static String m32(endDate) => "Percobaan gratis berlaku hingga ${endDate}"; + static String m33(endDate) => "Percobaan gratis berlaku hingga ${endDate}"; - static String m33(count) => + static String m34(count) => "Kamu masih bisa mengakses ${Intl.plural(count, other: 'filenya')} di Ente selama kamu masih berlangganan"; - static String m34(sizeInMBorGB) => "Bersihkan ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "Bersihkan ${sizeInMBorGB}"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, other: 'File tersebut bisa dihapus dari perangkat ini untuk membersihkan ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Memproses ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => "${Intl.plural(count, other: '${count} item')}"; + static String m38(count) => "${Intl.plural(count, other: '${count} item')}"; - static String m38(expiryTime) => "Link akan kedaluwarsa pada ${expiryTime}"; + static String m39(expiryTime) => "Link akan kedaluwarsa pada ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'tiada kenangan', one: '${formattedCount} kenangan', other: '${formattedCount} kenangan')}"; - static String m39(count) => "${Intl.plural(count, other: 'Pindahkan item')}"; + static String m40(count) => "${Intl.plural(count, other: 'Pindahkan item')}"; - static String m40(albumName) => "Berhasil dipindahkan ke ${albumName}"; + static String m41(albumName) => "Berhasil dipindahkan ke ${albumName}"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Harap hubungi ${familyAdminEmail} untuk mengubah kode kamu."; static String m0(passwordStrengthValue) => "Keamanan sandi: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Harap hubungi dukungan ${providerName} jika kamu dikenai biaya"; - static String m44(endDate) => + static String m45(endDate) => "Percobaan gratis berlaku hingga ${endDate}.\nKamu dapat memilih paket berbayar setelahnya."; - static String m45(toEmail) => "Silakan kirimi kami email di ${toEmail}"; + static String m46(toEmail) => "Silakan kirimi kami email di ${toEmail}"; - static String m46(toEmail) => "Silakan kirim log-nya ke \n${toEmail}"; + static String m47(toEmail) => "Silakan kirim log-nya ke \n${toEmail}"; - static String m48(storeName) => "Beri nilai di ${storeName}"; + static String m49(storeName) => "Beri nilai di ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Kalian berdua mendapat ${storageInGB} GB* gratis"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} akan dikeluarkan dari album berbagi ini\n\nSemua foto yang ia tambahkan juga akan dihapus dari album ini"; - static String m51(endDate) => "Langganan akan diperpanjang pada ${endDate}"; + static String m52(endDate) => "Langganan akan diperpanjang pada ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, other: '${count} hasil ditemukan')}"; - static String m3(count) => "${count} terpilih"; + static String m4(count) => "${count} terpilih"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "${count} dipilih (${yourCount} milikmu)"; - static String m54(verificationID) => + static String m55(verificationID) => "Ini ID Verifikasi saya di ente.io: ${verificationID}."; - static String m4(verificationID) => + static String m5(verificationID) => "Halo, bisakah kamu pastikan bahwa ini adalah ID Verifikasi ente.io milikmu: ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Kode rujukan Ente: ${referralCode} \n\nTerapkan pada Pengaturan → Umum → Rujukan untuk mendapatkan ${referralStorageInGB} GB gratis setelah kamu mendaftar paket berbayar\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Bagikan dengan orang tertentu', one: 'Berbagi dengan 1 orang', other: 'Berbagi dengan ${numberOfPeople} orang')}"; - static String m57(emailIDs) => "Dibagikan dengan ${emailIDs}"; - - static String m58(fileType) => - "${fileType} ini akan dihapus dari perangkat ini."; + static String m58(emailIDs) => "Dibagikan dengan ${emailIDs}"; static String m59(fileType) => + "${fileType} ini akan dihapus dari perangkat ini."; + + static String m60(fileType) => "${fileType} ini tersimpan di Ente dan juga di perangkat ini."; - static String m60(fileType) => "${fileType} ini akan dihapus dari Ente."; + static String m61(fileType) => "${fileType} ini akan dihapus dari Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -197,7 +197,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Verifikasi ${email}"; - static String m1(email) => + static String m2(email) => "Kami telah mengirimkan email ke ${email}"; static String m72(count) => @@ -222,14 +222,14 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Tambah email baru"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Tambah kolaborator"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Tambahkan dari perangkat"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Tambah tempat"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Tambah"), "addMore": MessageLookupByLibrary.simpleMessage("Tambah lagi"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addPhotos": MessageLookupByLibrary.simpleMessage("Tambah foto"), "addSelected": MessageLookupByLibrary.simpleMessage("Tambahkan yang dipilih"), @@ -239,8 +239,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Tambah ke album tersembunyi"), "addViewer": MessageLookupByLibrary.simpleMessage("Tambahkan pemirsa"), "addedAs": MessageLookupByLibrary.simpleMessage("Ditambahkan sebagai"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Menambahkan ke favorit..."), "advanced": MessageLookupByLibrary.simpleMessage("Lanjutan"), @@ -251,7 +251,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Setelah 1 minggu"), "after1Year": MessageLookupByLibrary.simpleMessage("Setelah 1 tahun"), "albumOwner": MessageLookupByLibrary.simpleMessage("Pemilik"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Judul album"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album diperbarui"), @@ -259,6 +259,8 @@ class MessageLookup extends MessageLookupByLibrary { "allClear": MessageLookupByLibrary.simpleMessage("✨ Sudah bersih"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("Semua kenangan terpelihara"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Izinkan orang yang memiliki link untuk menambahkan foto ke album berbagi ini."), "allowAddingPhotos": @@ -282,7 +284,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Android, iOS, Web, Desktop"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("Autentikasi diperlukan"), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("ID Apple"), "apply": MessageLookupByLibrary.simpleMessage("Terapkan"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Terapkan kode"), @@ -305,6 +307,9 @@ class MessageLookup extends MessageLookupByLibrary { "Apakah kamu yakin ingin keluar akun?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Apakah kamu yakin ingin memperpanjang?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Langganan kamu telah dibatalkan. Apakah kamu ingin membagikan alasannya?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -348,7 +353,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "Taut otomatis hanya tersedia di perangkat yang mendukung Chromecast."), "available": MessageLookupByLibrary.simpleMessage("Tersedia"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Folder yang dicadangkan"), "backup": MessageLookupByLibrary.simpleMessage("Pencadangan"), @@ -371,10 +376,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Hanya dapat menghapus berkas yang dimiliki oleh mu"), "cancel": MessageLookupByLibrary.simpleMessage("Batal"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Batalkan langganan"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Tidak dapat menghapus file berbagi"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -404,7 +409,7 @@ class MessageLookup extends MessageLookupByLibrary { "claimMore": MessageLookupByLibrary.simpleMessage("Peroleh lebih banyak!"), "claimed": MessageLookupByLibrary.simpleMessage("Diperoleh"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "clearIndexes": MessageLookupByLibrary.simpleMessage("Hapus indeks"), "click": MessageLookupByLibrary.simpleMessage("• Click"), "close": MessageLookupByLibrary.simpleMessage("Tutup"), @@ -420,7 +425,7 @@ class MessageLookup extends MessageLookupByLibrary { "Buat link untuk memungkinkan orang lain menambahkan dan melihat foto yang ada pada album bersama kamu tanpa memerlukan app atau akun Ente. Ideal untuk mengumpulkan foto pada suatu acara."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Link kolaborasi"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Kolaborator"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -446,10 +451,10 @@ class MessageLookup extends MessageLookupByLibrary { "Konfirmasi kunci pemulihan kamu"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Hubungkan ke perangkat"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Hubungi dukungan"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Kontak"), "continueLabel": MessageLookupByLibrary.simpleMessage("Lanjut"), "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( @@ -490,7 +495,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("Pemakaian saat ini sebesar "), "custom": MessageLookupByLibrary.simpleMessage("Kustom"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Gelap"), "dayToday": MessageLookupByLibrary.simpleMessage("Hari Ini"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Kemarin"), @@ -519,9 +524,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Hapus dari perangkat ini"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Hapus dari Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deletePhotos": MessageLookupByLibrary.simpleMessage("Hapus foto"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Fitur penting yang saya perlukan tidak ada"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -558,7 +563,7 @@ class MessageLookup extends MessageLookupByLibrary { "Orang yang melihat masih bisa mengambil tangkapan layar atau menyalin foto kamu menggunakan alat eksternal"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Perlu diketahui"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Nonaktifkan autentikasi dua langkah"), "disablingTwofactorAuthentication": @@ -593,8 +598,8 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Gagal mengunduh"), "downloading": MessageLookupByLibrary.simpleMessage("Mengunduh..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, "edit": MessageLookupByLibrary.simpleMessage("Edit"), "editLocation": MessageLookupByLibrary.simpleMessage("Edit lokasi"), "editLocationTagTitle": @@ -606,8 +611,8 @@ class MessageLookup extends MessageLookupByLibrary { "Perubahan lokasi hanya akan terlihat di Ente"), "eligible": MessageLookupByLibrary.simpleMessage("memenuhi syarat"), "email": MessageLookupByLibrary.simpleMessage("Email"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Verifikasi email"), "empty": MessageLookupByLibrary.simpleMessage("Kosongkan"), @@ -704,8 +709,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Jenis file"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Nama dan jenis file"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("File terhapus"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage("File tersimpan ke galeri"), @@ -719,23 +724,23 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Wajah yang ditemukan"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Kuota gratis diperoleh"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage( "Kuota gratis yang dapat digunakan"), "freeTrial": MessageLookupByLibrary.simpleMessage("Percobaan gratis"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Bersihkan penyimpanan perangkat"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Hemat ruang penyimpanan di perangkatmu dengan membersihkan file yang sudah tercadangkan."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Bersihkan ruang"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "general": MessageLookupByLibrary.simpleMessage("Umum"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Menghasilkan kunci enkripsi..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Buka pengaturan"), "googlePlayId": MessageLookupByLibrary.simpleMessage("ID Google Play"), "grantFullAccessPrompt": MessageLookupByLibrary.simpleMessage( @@ -795,7 +800,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Sepertinya terjadi kesalahan. Silakan coba lagi setelah beberapa saat. Jika kesalahan terus terjadi, silakan hubungi tim dukungan kami."), - "itemCount": m37, + "itemCount": m38, "itemsWillBeRemovedFromAlbum": MessageLookupByLibrary.simpleMessage( "Item yang dipilih akan dihapus dari album ini"), "joinDiscord": @@ -822,7 +827,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Batas perangkat"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Aktif"), "linkExpired": MessageLookupByLibrary.simpleMessage("Kedaluwarsa"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Waktu kedaluwarsa link"), "linkHasExpired": @@ -885,7 +890,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Peta"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), "mlConsent": MessageLookupByLibrary.simpleMessage("Aktifkan pemelajaran mesin"), @@ -904,10 +909,10 @@ class MessageLookup extends MessageLookupByLibrary { "moderateStrength": MessageLookupByLibrary.simpleMessage("Sedang"), "moments": MessageLookupByLibrary.simpleMessage("Momen"), "monthly": MessageLookupByLibrary.simpleMessage("Bulanan"), - "moveItem": m39, + "moveItem": m40, "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Pindahkan ke album tersembunyi"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Pindah ke sampah"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -958,7 +963,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("Di perangkat ini"), "onEnte": MessageLookupByLibrary.simpleMessage( "Di ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Aduh"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Aduh, tidak dapat menyimpan perubahan"), @@ -994,7 +1000,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Pembayaran gagal"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Sayangnya, pembayaranmu gagal. Silakan hubungi tim bantuan agar dapat kami bantu!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Item menunggu"), "pendingSync": MessageLookupByLibrary.simpleMessage("Sinkronisasi tertunda"), @@ -1017,7 +1023,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Foto yang telah kamu tambahkan akan dihapus dari album ini"), "playOnTv": MessageLookupByLibrary.simpleMessage("Putar album di TV"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Langganan PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1029,12 +1035,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Silakan hubungi tim bantuan jika masalah terus terjadi"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Harap berikan izin"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Silakan masuk akun lagi"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Silakan coba lagi"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1068,7 +1074,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Buat tiket dukungan"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Nilai app ini"), "rateUs": MessageLookupByLibrary.simpleMessage("Beri kami nilai"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Pulihkan"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Pulihkan akun"), "recoverButton": MessageLookupByLibrary.simpleMessage("Pulihkan"), @@ -1096,7 +1102,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Berikan kode ini ke teman kamu"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Ia perlu daftar ke paket berbayar"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Referensi"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage("Rujukan sedang dijeda"), @@ -1118,7 +1124,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Hapus link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Hapus peserta"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("Hapus label orang"), "removePublicLink": @@ -1134,13 +1140,14 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Ubah nama file"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Perpanjang langganan"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Laporkan bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Laporkan bug"), "resendEmail": MessageLookupByLibrary.simpleMessage("Kirim ulang email"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Atur ulang sandi"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "restore": MessageLookupByLibrary.simpleMessage("Pulihkan"), "restoringFiles": MessageLookupByLibrary.simpleMessage("Memulihkan file..."), @@ -1185,7 +1192,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Album, nama dan jenis file"), "searchHint5": MessageLookupByLibrary.simpleMessage( "Segera tiba: Penelusuran wajah & ajaib ✨"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Keamanan"), "selectALocation": MessageLookupByLibrary.simpleMessage("Pilih lokasi"), "selectALocationFirst": MessageLookupByLibrary.simpleMessage( @@ -1210,8 +1217,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Item terpilih akan dihapus dari semua album dan dipindahkan ke sampah."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Kirim"), "sendEmail": MessageLookupByLibrary.simpleMessage("Kirim email"), "sendInvite": MessageLookupByLibrary.simpleMessage("Kirim undangan"), @@ -1232,16 +1239,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Bagikan album sekarang"), "shareLink": MessageLookupByLibrary.simpleMessage("Bagikan link"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Bagikan hanya dengan orang yang kamu inginkan"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Unduh Ente agar kita bisa berbagi foto dan video kualitas asli dengan mudah\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Bagikan ke pengguna non-Ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Bagikan album pertamamu"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1254,7 +1261,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Foto terbagi baru"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Terima notifikasi apabila seseorang menambahkan foto ke album bersama yang kamu ikuti"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Dibagikan dengan saya"), "sharedWithYou": @@ -1269,11 +1276,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Keluar di perangkat lain"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Saya menyetujui ketentuan layanan dan kebijakan privasi Ente"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Ia akan dihapus dari semua album."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Lewati"), "social": MessageLookupByLibrary.simpleMessage("Sosial"), "someItemsAreInBothEnteAndYourDevice": @@ -1315,7 +1322,7 @@ class MessageLookup extends MessageLookupByLibrary { "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Keluarga"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Kamu"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Batas penyimpanan terlampaui"), "storageUsageInfo": m62, @@ -1479,7 +1486,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Menunggu WiFi..."), "weAreOpenSource": MessageLookupByLibrary.simpleMessage("Kode sumber kami terbuka!"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Lemah"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Selamat datang kembali!"), @@ -1496,6 +1503,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("Ya, keluar"), "yesRemove": MessageLookupByLibrary.simpleMessage("Ya, hapus"), "yesRenew": MessageLookupByLibrary.simpleMessage("Ya, Perpanjang"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Kamu"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage( "Kamu menggunakan paket keluarga!"), diff --git a/mobile/lib/generated/intl/messages_it.dart b/mobile/lib/generated/intl/messages_it.dart index 35c00e8826..1ad022dd95 100644 --- a/mobile/lib/generated/intl/messages_it.dart +++ b/mobile/lib/generated/intl/messages_it.dart @@ -20,37 +20,37 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'it'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Aggiungi collaboratore', one: 'Aggiungi collaboratore', other: 'Aggiungi collaboratori')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Aggiungi elemento', other: 'Aggiungi elementi')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Il tuo spazio aggiuntivo di ${storageAmount} è valido fino al ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, zero: 'Aggiungi visualizzatore', one: 'Aggiungi visualizzatore', other: 'Aggiungi visualizzatori')}"; - static String m9(emailOrName) => "Aggiunto da ${emailOrName}"; + static String m10(emailOrName) => "Aggiunto da ${emailOrName}"; - static String m10(albumName) => "Aggiunto con successo su ${albumName}"; + static String m11(albumName) => "Aggiunto con successo su ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Nessun partecipante', one: '1 Partecipante', other: '${count} Partecipanti')}"; - static String m12(versionValue) => "Versione: ${versionValue}"; + static String m13(versionValue) => "Versione: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} liberi"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Annulla prima il tuo abbonamento esistente da ${paymentProvider}"; - static String m15(user) => + static String m16(user) => "${user} non sarà più in grado di aggiungere altre foto a questo album\n\nSarà ancora in grado di rimuovere le foto esistenti aggiunte da lui o lei"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Il tuo piano famiglia ha già richiesto ${storageAmountInGb} GB finora', @@ -58,135 +58,135 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Hai già richiesto ${storageAmountInGb} GB finora!', })}"; - static String m17(albumName) => "Link collaborativo creato per ${albumName}"; + static String m18(albumName) => "Link collaborativo creato per ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Contatta ${familyAdminEmail} per gestire il tuo abbonamento"; - static String m19(provider) => + static String m20(provider) => "Scrivi all\'indirizzo support@ente.io per gestire il tuo abbonamento ${provider}."; - static String m20(endpoint) => "Connesso a ${endpoint}"; + static String m21(endpoint) => "Connesso a ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Elimina ${count} elemento', other: 'Elimina ${count} elementi')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Eliminazione di ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Questo rimuoverà il link pubblico per accedere a \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Per favore invia un\'email a ${supportEmail} dall\'indirizzo email con cui ti sei registrato"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Hai ripulito ${Intl.plural(count, one: '${count} doppione', other: '${count} doppioni')}, salvando (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} file, ${formattedSize} l\'uno"; - static String m27(newEmail) => "Email cambiata in ${newEmail}"; + static String m28(newEmail) => "Email cambiata in ${newEmail}"; - static String m28(email) => + static String m29(email) => "${email} non ha un account Ente.\n\nInvia un invito per condividere foto."; - static String m29(count, formattedNumber) => - "${Intl.plural(count, one: '1 file', other: '${formattedNumber} file')} di quest\'album sono stati salvati in modo sicuro"; - static String m30(count, formattedNumber) => "${Intl.plural(count, one: '1 file', other: '${formattedNumber} file')} di quest\'album sono stati salvati in modo sicuro"; - static String m31(storageAmountInGB) => + static String m31(count, formattedNumber) => + "${Intl.plural(count, one: '1 file', other: '${formattedNumber} file')} di quest\'album sono stati salvati in modo sicuro"; + + static String m32(storageAmountInGB) => "${storageAmountInGB} GB ogni volta che qualcuno si iscrive a un piano a pagamento e applica il tuo codice"; - static String m32(endDate) => "La prova gratuita termina il ${endDate}"; + static String m33(endDate) => "La prova gratuita termina il ${endDate}"; - static String m33(count) => + static String m34(count) => "Puoi ancora accedere a ${Intl.plural(count, one: '', other: 'loro')} su ente finché hai un abbonamento attivo"; - static String m34(sizeInMBorGB) => "Libera ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "Libera ${sizeInMBorGB}"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'Può essere cancellata per liberare ${formattedSize}', other: 'Possono essere cancellati per liberare ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Elaborazione ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} elemento', other: '${count} elementi')}"; - static String m38(expiryTime) => "Il link scadrà il ${expiryTime}"; + static String m39(expiryTime) => "Il link scadrà il ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, one: '${formattedCount} ricordo', other: '${formattedCount} ricordi')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Sposta elemento', other: 'Sposta elementi')}"; - static String m40(albumName) => "Spostato con successo su ${albumName}"; + static String m41(albumName) => "Spostato con successo su ${albumName}"; - static String m41(name) => "Non è ${name}?"; + static String m42(name) => "Non è ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Per favore contatta ${familyAdminEmail} per cambiare il tuo codice."; static String m0(passwordStrengthValue) => "Sicurezza password: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Si prega di parlare con il supporto di ${providerName} se ti è stato addebitato qualcosa"; - static String m44(endDate) => + static String m45(endDate) => "Prova gratuita valida fino al ${endDate}.\nIn seguito potrai scegliere un piano a pagamento."; - static String m45(toEmail) => "Per favore invia un\'email a ${toEmail}"; + static String m46(toEmail) => "Per favore invia un\'email a ${toEmail}"; - static String m46(toEmail) => "Invia i log a \n${toEmail}"; + static String m47(toEmail) => "Invia i log a \n${toEmail}"; - static String m47(folderName) => "Elaborando ${folderName}..."; + static String m48(folderName) => "Elaborando ${folderName}..."; - static String m48(storeName) => "Valutaci su ${storeName}"; + static String m49(storeName) => "Valutaci su ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Ottenete entrambi ${storageInGB} GB* gratis"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} verrà rimosso da questo album condiviso\n\nQualsiasi foto aggiunta dall\'utente verrà rimossa dall\'album"; - static String m51(endDate) => "Si rinnova il ${endDate}"; + static String m52(endDate) => "Si rinnova il ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} risultato trovato', other: '${count} risultati trovati')}"; - static String m3(count) => "${count} selezionati"; + static String m4(count) => "${count} selezionati"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "${count} selezionato (${yourCount} tuoi)"; - static String m54(verificationID) => + static String m55(verificationID) => "Ecco il mio ID di verifica: ${verificationID} per ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Hey, puoi confermare che questo è il tuo ID di verifica: ${verificationID} su ente.io"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Codice invito Ente: ${referralCode} \n\nInseriscilo in Impostazioni → Generali → Inviti per ottenere ${referralStorageInGB} GB gratis dopo la sottoscrizione a un piano a pagamento\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Condividi con persone specifiche', one: 'Condividi con una persona', other: 'Condividi con ${numberOfPeople} persone')}"; - static String m57(emailIDs) => "Condiviso con ${emailIDs}"; - - static String m58(fileType) => - "Questo ${fileType} verrà eliminato dal tuo dispositivo."; + static String m58(emailIDs) => "Condiviso con ${emailIDs}"; static String m59(fileType) => + "Questo ${fileType} verrà eliminato dal tuo dispositivo."; + + static String m60(fileType) => "Questo ${fileType} è sia su Ente che sul tuo dispositivo."; - static String m60(fileType) => "Questo ${fileType} verrà eliminato da Ente."; + static String m61(fileType) => "Questo ${fileType} verrà eliminato da Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -214,7 +214,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Verifica ${email}"; - static String m1(email) => + static String m2(email) => "Abbiamo inviato una mail a ${email}"; static String m72(count) => @@ -240,17 +240,17 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Aggiungi una nuova email"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Aggiungi collaboratore"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Aggiungi dal dispositivo"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Aggiungi luogo"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Aggiungi"), "addMore": MessageLookupByLibrary.simpleMessage("Aggiungi altri"), "addNew": MessageLookupByLibrary.simpleMessage("Aggiungi nuovo"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage( "Dettagli dei componenti aggiuntivi"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Componenti aggiuntivi"), "addPhotos": MessageLookupByLibrary.simpleMessage("Aggiungi foto"), "addSelected": @@ -262,12 +262,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Aggiungi ad album nascosto"), "addViewer": MessageLookupByLibrary.simpleMessage("Aggiungi in sola lettura"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Aggiungi le tue foto ora"), "addedAs": MessageLookupByLibrary.simpleMessage("Aggiunto come"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Aggiunto ai preferiti..."), "advanced": MessageLookupByLibrary.simpleMessage("Avanzate"), @@ -279,7 +279,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Dopo una settimana"), "after1Year": MessageLookupByLibrary.simpleMessage("Dopo un anno"), "albumOwner": MessageLookupByLibrary.simpleMessage("Proprietario"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Titolo album"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album aggiornato"), @@ -287,6 +287,8 @@ class MessageLookup extends MessageLookupByLibrary { "allClear": MessageLookupByLibrary.simpleMessage("✨ Tutto pulito"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("Tutti i ricordi conservati"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Permetti anche alle persone con il link di aggiungere foto all\'album condiviso."), "allowAddingPhotos": MessageLookupByLibrary.simpleMessage( @@ -319,7 +321,7 @@ class MessageLookup extends MessageLookupByLibrary { "appLock": MessageLookupByLibrary.simpleMessage("Blocco app"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Scegli tra la schermata di blocco predefinita del dispositivo e una schermata di blocco personalizzata con PIN o password."), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Applica"), "applyCodeTitle": @@ -343,6 +345,9 @@ class MessageLookup extends MessageLookupByLibrary { "Sei sicuro di volerti disconnettere?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Sei sicuro di volere rinnovare?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Il tuo abbonamento è stato annullato. Vuoi condividere il motivo?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -396,7 +401,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "L\'associazione automatica funziona solo con i dispositivi che supportano Chromecast."), "available": MessageLookupByLibrary.simpleMessage("Disponibile"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Cartelle salvate"), "backup": MessageLookupByLibrary.simpleMessage("Backup"), @@ -424,10 +429,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Puoi rimuovere solo i file di tua proprietà"), "cancel": MessageLookupByLibrary.simpleMessage("Annulla"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Annulla abbonamento"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Impossibile eliminare i file condivisi"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -460,7 +465,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Richiedi spazio gratuito"), "claimMore": MessageLookupByLibrary.simpleMessage("Richiedine di più!"), "claimed": MessageLookupByLibrary.simpleMessage("Riscattato"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Pulisci Senza Categoria"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -489,7 +494,7 @@ class MessageLookup extends MessageLookupByLibrary { "Crea un link per consentire alle persone di aggiungere e visualizzare foto nel tuo album condiviso senza bisogno di un\'applicazione o di un account Ente. Ottimo per raccogliere foto di un evento."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Link collaborativo"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Collaboratore"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -522,10 +527,10 @@ class MessageLookup extends MessageLookupByLibrary { "Conferma la tua chiave di recupero"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Connetti al dispositivo"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Contatta il supporto"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Contatti"), "contents": MessageLookupByLibrary.simpleMessage("Contenuti"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continua"), @@ -570,7 +575,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage( "Spazio attualmente utilizzato "), "custom": MessageLookupByLibrary.simpleMessage("Personalizza"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Scuro"), "dayToday": MessageLookupByLibrary.simpleMessage("Oggi"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Ieri"), @@ -606,11 +611,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Elimina dal dispositivo"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Elimina da Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Elimina posizione"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Elimina foto"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Manca una caratteristica chiave di cui ho bisogno"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -652,7 +657,7 @@ class MessageLookup extends MessageLookupByLibrary { "I visualizzatori possono scattare screenshot o salvare una copia delle foto utilizzando strumenti esterni"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Nota bene"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Disabilita autenticazione a due fattori"), "disablingTwofactorAuthentication": @@ -695,9 +700,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Scaricamento fallito"), "downloading": MessageLookupByLibrary.simpleMessage("Scaricamento in corso..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Modifica"), "editLocation": MessageLookupByLibrary.simpleMessage("Modifica luogo"), "editLocationTagTitle": @@ -708,8 +713,8 @@ class MessageLookup extends MessageLookupByLibrary { "Le modifiche alla posizione saranno visibili solo all\'interno di Ente"), "eligible": MessageLookupByLibrary.simpleMessage("idoneo"), "email": MessageLookupByLibrary.simpleMessage("Email"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Verifica Email"), "emailYourLogs": MessageLookupByLibrary.simpleMessage( @@ -817,8 +822,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Tipi di file"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Tipi e nomi di file"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("File eliminati"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage("File salvati nella galleria"), @@ -832,25 +837,25 @@ class MessageLookup extends MessageLookupByLibrary { "foundFaces": MessageLookupByLibrary.simpleMessage("Volti trovati"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Spazio gratuito richiesto"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Spazio libero utilizzabile"), "freeTrial": MessageLookupByLibrary.simpleMessage("Prova gratuita"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Libera spazio"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Risparmia spazio sul tuo dispositivo cancellando i file che sono già stati salvati online."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Libera spazio"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Fino a 1000 ricordi mostrati nella galleria"), "general": MessageLookupByLibrary.simpleMessage("Generali"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Generazione delle chiavi di crittografia..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Vai alle impostazioni"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), @@ -929,7 +934,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Sembra che qualcosa sia andato storto. Riprova tra un po\'. Se l\'errore persiste, contatta il nostro team di supporto."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Gli elementi mostrano il numero di giorni rimanenti prima della cancellazione permanente"), @@ -960,7 +965,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Limite dei dispositivi"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Attivato"), "linkExpired": MessageLookupByLibrary.simpleMessage("Scaduto"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Scadenza del link"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("Il link è scaduto"), @@ -1049,7 +1054,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Mappe"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), "mlConsent": MessageLookupByLibrary.simpleMessage( "Abilita l\'apprendimento automatico"), @@ -1074,12 +1079,12 @@ class MessageLookup extends MessageLookupByLibrary { "moreDetails": MessageLookupByLibrary.simpleMessage("Più dettagli"), "mostRecent": MessageLookupByLibrary.simpleMessage("Più recenti"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Più rilevanti"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Sposta nell\'album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Sposta in album nascosto"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Spostato nel cestino"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -1130,7 +1135,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nessun risultato trovato"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage( "Nessun blocco di sistema trovato"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage( "Ancora nulla di condiviso con te"), "nothingToSeeHere": @@ -1140,7 +1145,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("Sul dispositivo"), "onEnte": MessageLookupByLibrary.simpleMessage( "Su ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Oops"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Ops, impossibile salvare le modifiche"), @@ -1182,7 +1188,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Pagamento non riuscito"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Purtroppo il tuo pagamento non è riuscito. Contatta l\'assistenza e ti aiuteremo!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Elementi in sospeso"), "pendingSync": @@ -1211,7 +1217,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinLock": MessageLookupByLibrary.simpleMessage("Blocco con PIN"), "playOnTv": MessageLookupByLibrary.simpleMessage("Riproduci album sulla TV"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Abbonamento su PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1223,14 +1229,14 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Riprova. Se il problema persiste, ti invitiamo a contattare l\'assistenza"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Concedi i permessi"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( "Effettua nuovamente l\'accesso"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Si prega di selezionare i link rapidi da rimuovere"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Riprova"), "pleaseVerifyTheCodeYouHaveEntered": MessageLookupByLibrary.simpleMessage( @@ -1254,7 +1260,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Backup privato"), "privateSharing": MessageLookupByLibrary.simpleMessage("Condivisioni private"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Link pubblico creato"), "publicLinkEnabled": @@ -1265,7 +1271,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Invia ticket"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Valuta l\'app"), "rateUs": MessageLookupByLibrary.simpleMessage("Lascia una recensione"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Recupera"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recupera account"), @@ -1301,7 +1307,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Condividi questo codice con i tuoi amici"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Si iscrivono per un piano a pagamento"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Invita un Amico"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "I referral code sono attualmente in pausa"), @@ -1327,7 +1333,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Elimina link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Rimuovi partecipante"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("Rimuovi etichetta persona"), "removePublicLink": @@ -1345,7 +1351,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Rinomina file"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Rinnova abbonamento"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Segnala un bug"), "reportBug": MessageLookupByLibrary.simpleMessage("Segnala un bug"), "resendEmail": MessageLookupByLibrary.simpleMessage("Rinvia email"), @@ -1353,6 +1359,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ripristina i file ignorati"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Reimposta password"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("Ripristina predefinita"), "restore": MessageLookupByLibrary.simpleMessage("Ripristina"), @@ -1415,7 +1422,7 @@ class MessageLookup extends MessageLookupByLibrary { "Raggruppa foto scattate entro un certo raggio da una foto"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invita persone e vedrai qui tutte le foto condivise da loro"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Sicurezza"), "selectALocation": MessageLookupByLibrary.simpleMessage("Seleziona un luogo"), @@ -1443,8 +1450,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Gli elementi selezionati verranno eliminati da tutti gli album e spostati nel cestino."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Invia"), "sendEmail": MessageLookupByLibrary.simpleMessage("Invia email"), "sendInvite": MessageLookupByLibrary.simpleMessage("Invita"), @@ -1474,16 +1481,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Condividi un album"), "shareLink": MessageLookupByLibrary.simpleMessage("Condividi link"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Condividi solo con le persone che vuoi"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Scarica Ente in modo da poter facilmente condividere foto e video in qualità originale\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Condividi con utenti che non hanno un account Ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Condividi il tuo primo album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1494,7 +1501,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nuove foto condivise"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Ricevi notifiche quando qualcuno aggiunge una foto a un album condiviso, di cui fai parte"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Condivisi con me"), "sharedWithYou": @@ -1511,11 +1518,11 @@ class MessageLookup extends MessageLookupByLibrary { "Esci dagli altri dispositivi"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Accetto i termini di servizio e la politica sulla privacy"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Verrà eliminato da tutti gli album."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Salta"), "social": MessageLookupByLibrary.simpleMessage("Social"), "someItemsAreInBothEnteAndYourDevice": @@ -1562,7 +1569,7 @@ class MessageLookup extends MessageLookupByLibrary { "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Famiglia"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Tu"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Limite d\'archiviazione superato"), "storageUsageInfo": m62, @@ -1770,7 +1777,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Non puoi modificare foto e album che non possiedi"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Debole"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bentornato/a!"), "whatsNew": MessageLookupByLibrary.simpleMessage("Novità"), @@ -1786,6 +1793,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("Sì, disconnetti"), "yesRemove": MessageLookupByLibrary.simpleMessage("Sì, rimuovi"), "yesRenew": MessageLookupByLibrary.simpleMessage("Sì, Rinnova"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Tu"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage( "Sei un utente con piano famiglia!"), diff --git a/mobile/lib/generated/intl/messages_ja.dart b/mobile/lib/generated/intl/messages_ja.dart index 066308e7b6..bc70150d10 100644 --- a/mobile/lib/generated/intl/messages_ja.dart +++ b/mobile/lib/generated/intl/messages_ja.dart @@ -20,164 +20,164 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ja'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, zero: '共同編集者を追加', one: '共同編集者を追加', other: '共同編集者を追加')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: '項目を追加', other: '項目を追加')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "あなたの ${storageAmount} アドオンは ${endDate} まで有効です"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, zero: 'ビューアーを追加', one: 'ビューアーを追加', other: 'ビューアーを追加')}"; - static String m9(emailOrName) => "${emailOrName} が追加"; + static String m10(emailOrName) => "${emailOrName} が追加"; - static String m10(albumName) => "${albumName} に追加しました"; + static String m11(albumName) => "${albumName} に追加しました"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: '参加者なし', one: '1 参加者', other: '${count} 参加者')}"; - static String m12(versionValue) => "バージョン: ${versionValue}"; + static String m13(versionValue) => "バージョン: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} 無料"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "まず${paymentProvider} から既存のサブスクリプションをキャンセルしてください"; - static String m15(user) => + static String m16(user) => "${user} は写真をアルバムに追加できなくなります\n\n※${user} が追加した写真は今後も${user} が削除できます"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': '家族は ${storageAmountInGb} GB 受け取っています', 'false': 'あなたは ${storageAmountInGb} GB 受け取っています', 'other': 'あなたは ${storageAmountInGb} GB受け取っています', })}"; - static String m17(albumName) => "${albumName} のコラボレーションリンクを生成しました"; + static String m18(albumName) => "${albumName} のコラボレーションリンクを生成しました"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "サブスクリプションを管理するには、 ${familyAdminEmail} に連絡してください"; - static String m19(provider) => + static String m20(provider) => "${provider} サブスクリプションを管理するには、support@ente.io までご連絡ください。"; - static String m20(endpoint) => "${endpoint} に接続しました"; + static String m21(endpoint) => "${endpoint} に接続しました"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: '${count} 個の項目を削除', other: '${count} 個の項目を削除')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "${currentlyDeleting} / ${totalCount} を削除中"; - static String m23(albumName) => "\"${albumName}\" にアクセスするための公開リンクが削除されます。"; + static String m24(albumName) => "\"${albumName}\" にアクセスするための公開リンクが削除されます。"; - static String m24(supportEmail) => + static String m25(supportEmail) => "あなたの登録したメールアドレスから${supportEmail} にメールを送ってください"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "お掃除しました ${Intl.plural(count, one: '${count} 個の重複ファイル', other: '${count} 個の重複ファイル')}, (${storageSaved}が開放されます!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} 個のファイル、それぞれ${formattedSize}"; - static String m27(newEmail) => "メールアドレスが ${newEmail} に変更されました"; + static String m28(newEmail) => "メールアドレスが ${newEmail} に変更されました"; - static String m28(email) => + static String m29(email) => "${email} はEnteアカウントを持っていません。\n\n写真を共有するために「招待」を送信してください。"; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "${Intl.plural(count, other: '${formattedNumber} 個のファイル')} が安全にバックアップされました"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "${Intl.plural(count, other: '${formattedNumber} ファイル')} が安全にバックアップされました"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "誰かが有料プランにサインアップしてコードを適用する度に ${storageAmountInGB} GB"; - static String m32(endDate) => "無料トライアルは${endDate} までです"; + static String m33(endDate) => "無料トライアルは${endDate} までです"; - static String m33(count) => + static String m34(count) => "あなたが有効なサブスクリプションを持っている限りEnte上の ${Intl.plural(count, other: 'それらに')} アクセスできます"; - static String m34(sizeInMBorGB) => "${sizeInMBorGB} を解放する"; + static String m35(sizeInMBorGB) => "${sizeInMBorGB} を解放する"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, other: 'デバイスから削除して${formattedSize} 解放することができます')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "${currentlyProcessing} / ${totalCount} を処理中"; - static String m37(count) => "${Intl.plural(count, other: '${count}個のアイテム')}"; + static String m38(count) => "${Intl.plural(count, other: '${count}個のアイテム')}"; - static String m38(expiryTime) => "リンクは ${expiryTime} に期限切れになります"; + static String m39(expiryTime) => "リンクは ${expiryTime} に期限切れになります"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: '思い出なし', one: '${formattedCount} 思い出', other: '${formattedCount} 思い出')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: '項目を移動', other: '項目を移動')}"; - static String m40(albumName) => "${albumName} に移動しました"; + static String m41(albumName) => "${albumName} に移動しました"; - static String m41(name) => "${name} ではありませんか?"; + static String m42(name) => "${name} ではありませんか?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "コードを変更するには、 ${familyAdminEmail} までご連絡ください。"; static String m0(passwordStrengthValue) => "パスワードの長さ: ${passwordStrengthValue}"; - static String m43(providerName) => "請求された場合は、 ${providerName} のサポートに連絡してください"; + static String m44(providerName) => "請求された場合は、 ${providerName} のサポートに連絡してください"; - static String m44(endDate) => + static String m45(endDate) => "${endDate} まで無料トライアルが有効です。\nその後、有料プランを選択することができます。"; - static String m45(toEmail) => "${toEmail} にメールでご連絡ください"; + static String m46(toEmail) => "${toEmail} にメールでご連絡ください"; - static String m46(toEmail) => "ログを以下のアドレスに送信してください \n${toEmail}"; + static String m47(toEmail) => "ログを以下のアドレスに送信してください \n${toEmail}"; - static String m47(folderName) => "${folderName} を処理中..."; + static String m48(folderName) => "${folderName} を処理中..."; - static String m48(storeName) => "${storeName} で評価"; + static String m49(storeName) => "${storeName} で評価"; - static String m49(storageInGB) => "3. お二人とも ${storageInGB} GB*を無料で手に入ります。"; + static String m50(storageInGB) => "3. お二人とも ${storageInGB} GB*を無料で手に入ります。"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} はこの共有アルバムから退出します\n\n${userEmail} が追加した写真もアルバムから削除されます"; - static String m51(endDate) => "サブスクリプションは ${endDate} に更新します"; + static String m52(endDate) => "サブスクリプションは ${endDate} に更新します"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} 個の結果', other: '${count} 個の結果')}"; - static String m3(count) => "${count} 個を選択"; + static String m4(count) => "${count} 個を選択"; - static String m53(count, yourCount) => "${count} 個選択中(${yourCount} あなた)"; + static String m54(count, yourCount) => "${count} 個選択中(${yourCount} あなた)"; - static String m54(verificationID) => "私の確認ID: ente.ioの ${verificationID}"; + static String m55(verificationID) => "私の確認ID: ente.ioの ${verificationID}"; - static String m4(verificationID) => + static String m5(verificationID) => "これがあなたのente.io確認用IDであることを確認できますか? ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "リフェラルコード: ${referralCode}\n\n設定→一般→リフェラルで使うことで${referralStorageInGB}が無料になります(あなたが有料プランに加入したあと)。\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: '誰かと共有しましょう', one: '1人と共有されています', other: '${numberOfPeople} 人と共有されています')}"; - static String m57(emailIDs) => "${emailIDs} と共有中"; + static String m58(emailIDs) => "${emailIDs} と共有中"; - static String m58(fileType) => "${fileType} はEnteから削除されます。"; + static String m59(fileType) => "${fileType} はEnteから削除されます。"; - static String m59(fileType) => "この ${fileType} はEnteとお使いのデバイスの両方にあります。"; + static String m60(fileType) => "この ${fileType} はEnteとお使いのデバイスの両方にあります。"; - static String m60(fileType) => "${fileType} はEnteから削除されます。"; + static String m61(fileType) => "${fileType} はEnteから削除されます。"; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -203,7 +203,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "${email} を確認"; - static String m1(email) => "${email}にメールを送りました"; + static String m2(email) => "${email}にメールを送りました"; static String m72(count) => "${Intl.plural(count, one: '${count} 年前', other: '${count} 年前')}"; @@ -223,15 +223,15 @@ class MessageLookup extends MessageLookupByLibrary { "addAName": MessageLookupByLibrary.simpleMessage("名前を追加"), "addANewEmail": MessageLookupByLibrary.simpleMessage("新しいEメールアドレスを追加"), "addCollaborator": MessageLookupByLibrary.simpleMessage("コラボレーターを追加"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("デバイスから追加"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("位置情報を追加"), "addLocationButton": MessageLookupByLibrary.simpleMessage("追加"), "addMore": MessageLookupByLibrary.simpleMessage("さらに追加"), "addNew": MessageLookupByLibrary.simpleMessage("新規追加"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("アドオンの詳細"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("アドオン"), "addPhotos": MessageLookupByLibrary.simpleMessage("写真を追加"), "addSelected": MessageLookupByLibrary.simpleMessage("選んだものをアルバムに追加"), @@ -239,11 +239,11 @@ class MessageLookup extends MessageLookupByLibrary { "addToEnte": MessageLookupByLibrary.simpleMessage("Enteに追加"), "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("非表示アルバムに追加"), "addViewer": MessageLookupByLibrary.simpleMessage("ビューアーを追加"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("写真を今すぐ追加する"), "addedAs": MessageLookupByLibrary.simpleMessage("追加:"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("お気に入りに追加しています..."), "advanced": MessageLookupByLibrary.simpleMessage("詳細"), @@ -254,13 +254,15 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("1週間後"), "after1Year": MessageLookupByLibrary.simpleMessage("1年後"), "albumOwner": MessageLookupByLibrary.simpleMessage("所有者"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("アルバムタイトル"), "albumUpdated": MessageLookupByLibrary.simpleMessage("アルバムが更新されました"), "albums": MessageLookupByLibrary.simpleMessage("アルバム"), "allClear": MessageLookupByLibrary.simpleMessage("✨ オールクリア"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("すべての思い出が保存されました"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "リンクを持つ人が共有アルバムに写真を追加できるようにします。"), "allowAddingPhotos": MessageLookupByLibrary.simpleMessage("写真の追加を許可"), @@ -286,7 +288,7 @@ class MessageLookup extends MessageLookupByLibrary { "appLock": MessageLookupByLibrary.simpleMessage("アプリのロック"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "デバイスのデフォルトのロック画面と、カスタムロック画面のどちらを利用しますか?"), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("適用"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("コードを適用"), @@ -307,6 +309,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("本当にログアウトしてよろしいですか?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage("更新してもよろしいですか?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "サブスクリプションはキャンセルされました。理由を教えていただけますか?"), "askDeleteReason": @@ -354,7 +359,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "自動ペアリングは Chromecast に対応しているデバイスでのみ動作します。"), "available": MessageLookupByLibrary.simpleMessage("ご利用可能"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("バックアップされたフォルダ"), "backup": MessageLookupByLibrary.simpleMessage("バックアップ"), @@ -377,10 +382,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage("あなたが所有しているファイルのみを削除できます"), "cancel": MessageLookupByLibrary.simpleMessage("キャンセル"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("サブスクリプションをキャンセル"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage("共有ファイルは削除できません"), "castIPMismatchBody": @@ -408,7 +413,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("無料のストレージを受け取る"), "claimMore": MessageLookupByLibrary.simpleMessage("もっと!"), "claimed": MessageLookupByLibrary.simpleMessage("受け取り済"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("未分類のクリーンアップ"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -433,7 +438,7 @@ class MessageLookup extends MessageLookupByLibrary { "collabLinkSectionDescription": MessageLookupByLibrary.simpleMessage( "Enteアプリやアカウントを持っていない人にも、共有アルバムに写真を追加したり表示したりできるリンクを作成します。"), "collaborativeLink": MessageLookupByLibrary.simpleMessage("共同作業リンク"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("コラボレーター"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -462,9 +467,9 @@ class MessageLookup extends MessageLookupByLibrary { "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage("リカバリーキーを確認"), "connectToDevice": MessageLookupByLibrary.simpleMessage("デバイスに接続"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("お問い合わせ"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("連絡先"), "contents": MessageLookupByLibrary.simpleMessage("内容"), "continueLabel": MessageLookupByLibrary.simpleMessage("つづける"), @@ -500,7 +505,7 @@ class MessageLookup extends MessageLookupByLibrary { "crop": MessageLookupByLibrary.simpleMessage("クロップ"), "currentUsageIs": MessageLookupByLibrary.simpleMessage("現在の使用状況 "), "custom": MessageLookupByLibrary.simpleMessage("カスタム"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("ダーク"), "dayToday": MessageLookupByLibrary.simpleMessage("今日"), "dayYesterday": MessageLookupByLibrary.simpleMessage("昨日"), @@ -529,10 +534,10 @@ class MessageLookup extends MessageLookupByLibrary { "deleteFromBoth": MessageLookupByLibrary.simpleMessage("両方から削除"), "deleteFromDevice": MessageLookupByLibrary.simpleMessage("デバイスから削除"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Enteから削除"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("位置情報を削除"), "deletePhotos": MessageLookupByLibrary.simpleMessage("写真を削除"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage("いちばん必要な機能がない"), "deleteReason2": MessageLookupByLibrary.simpleMessage("アプリや特定の機能が想定通りに動かない"), @@ -565,7 +570,7 @@ class MessageLookup extends MessageLookupByLibrary { "ビューアーはスクリーンショットを撮ったり、外部ツールを使用して写真のコピーを保存したりすることができます"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("ご注意ください"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage("2段階認証を無効にする"), "disablingTwofactorAuthentication": MessageLookupByLibrary.simpleMessage("2要素認証を無効にしています..."), @@ -600,9 +605,9 @@ class MessageLookup extends MessageLookupByLibrary { "download": MessageLookupByLibrary.simpleMessage("ダウンロード"), "downloadFailed": MessageLookupByLibrary.simpleMessage("ダウンロード失敗"), "downloading": MessageLookupByLibrary.simpleMessage("ダウンロード中…"), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("編集"), "editLocation": MessageLookupByLibrary.simpleMessage("位置情報を編集"), "editLocationTagTitle": MessageLookupByLibrary.simpleMessage("位置情報を編集"), @@ -611,8 +616,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("位置情報の編集はEnteでのみ表示されます"), "eligible": MessageLookupByLibrary.simpleMessage("対象となる"), "email": MessageLookupByLibrary.simpleMessage("Eメール"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("メール確認"), "emailYourLogs": MessageLookupByLibrary.simpleMessage("ログをメールで送信"), @@ -706,8 +711,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("ファイルをギャラリーに保存しました"), "fileTypes": MessageLookupByLibrary.simpleMessage("ファイルの種類"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("ファイルの種類と名前"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("削除されたファイル"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage("ギャラリーに保存されたファイル"), @@ -717,25 +722,25 @@ class MessageLookup extends MessageLookupByLibrary { "forgotPassword": MessageLookupByLibrary.simpleMessage("パスワードを忘れた"), "foundFaces": MessageLookupByLibrary.simpleMessage("見つかった顔"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("空き容量を受け取る"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("無料のストレージが利用可能です"), "freeTrial": MessageLookupByLibrary.simpleMessage("無料トライアル"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("デバイスの空き領域を解放する"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "すでにバックアップされているファイルを消去して、デバイスの容量を空けます。"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("スペースを解放する"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage("ギャラリーに表示されるメモリは最大1000個までです"), "general": MessageLookupByLibrary.simpleMessage("設定"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage("暗号化鍵を生成しています"), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("設定に移動"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), "grantFullAccessPrompt": MessageLookupByLibrary.simpleMessage( @@ -804,7 +809,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "問題が発生したようです。しばらくしてから再試行してください。エラーが解決しない場合は、サポートチームにお問い合わせください。"), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage("完全に削除されるまでの日数が項目に表示されます"), "itemsWillBeRemovedFromAlbum": @@ -829,7 +834,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("デバイスの制限"), "linkEnabled": MessageLookupByLibrary.simpleMessage("有効"), "linkExpired": MessageLookupByLibrary.simpleMessage("期限切れ"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("リンクの期限切れ"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("リンクは期限切れです"), "linkNeverExpires": MessageLookupByLibrary.simpleMessage("なし"), @@ -907,7 +912,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("地図"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("グッズ"), "mlConsent": MessageLookupByLibrary.simpleMessage("機械学習を有効にする"), "mlConsentConfirmation": @@ -929,10 +934,10 @@ class MessageLookup extends MessageLookupByLibrary { "moreDetails": MessageLookupByLibrary.simpleMessage("さらに詳細を表示"), "mostRecent": MessageLookupByLibrary.simpleMessage("新しい順"), "mostRelevant": MessageLookupByLibrary.simpleMessage("関連度順"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("アルバムに移動"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("隠しアルバムに移動"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("ごみ箱へ移動"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage("アルバムにファイルを移動中"), @@ -975,7 +980,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("一致する結果が見つかりませんでした"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage("システムロックが見つかりませんでした"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage("あなたに共有されたものはありません"), "nothingToSeeHere": @@ -985,7 +990,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("デバイス上"), "onEnte": MessageLookupByLibrary.simpleMessage( "Enteで保管"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Oops"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage("編集を保存できませんでした"), @@ -1020,7 +1026,7 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("支払いに失敗しました"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "残念ながらお支払いに失敗しました。サポートにお問い合わせください。お手伝いします!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("処理待ちの項目"), "pendingSync": MessageLookupByLibrary.simpleMessage("同期を保留中"), "people": MessageLookupByLibrary.simpleMessage("人物"), @@ -1041,7 +1047,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinAlbum": MessageLookupByLibrary.simpleMessage("アルバムをピンする"), "pinLock": MessageLookupByLibrary.simpleMessage("PINロック"), "playOnTv": MessageLookupByLibrary.simpleMessage("TVでアルバムを再生"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStoreサブスクリプション"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1051,13 +1057,13 @@ class MessageLookup extends MessageLookupByLibrary { "Support@ente.ioにお問い合わせください、お手伝いいたします。"), "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage("問題が解決しない場合はサポートにお問い合わせください"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("権限を付与してください"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("もう一度試してください"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage("削除するクイックリンクを選択してください"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("もう一度試してください"), "pleaseVerifyTheCodeYouHaveEntered": MessageLookupByLibrary.simpleMessage("入力したコードを確認してください"), @@ -1077,7 +1083,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("プライバシーポリシー"), "privateBackups": MessageLookupByLibrary.simpleMessage("プライベートバックアップ"), "privateSharing": MessageLookupByLibrary.simpleMessage("プライベート共有"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("公開リンクが作成されました"), "publicLinkEnabled": @@ -1087,7 +1093,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("サポートを受ける"), "rateTheApp": MessageLookupByLibrary.simpleMessage("アプリを評価"), "rateUs": MessageLookupByLibrary.simpleMessage("評価して下さい"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("復元"), "recoverAccount": MessageLookupByLibrary.simpleMessage("アカウントを復元"), "recoverButton": MessageLookupByLibrary.simpleMessage("復元"), @@ -1119,7 +1125,7 @@ class MessageLookup extends MessageLookupByLibrary { "referralStep1": MessageLookupByLibrary.simpleMessage("1. このコードを友達に贈りましょう"), "referralStep2": MessageLookupByLibrary.simpleMessage("2. 友達が有料プランに登録"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("リフェラル"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage("リフェラルは現在一時停止しています"), @@ -1142,7 +1148,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("お気に入りリストから外す"), "removeLink": MessageLookupByLibrary.simpleMessage("リンクを削除"), "removeParticipant": MessageLookupByLibrary.simpleMessage("参加者を削除"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("人名を削除"), "removePublicLink": MessageLookupByLibrary.simpleMessage("公開リンクを削除"), "removePublicLinks": MessageLookupByLibrary.simpleMessage("公開リンクを削除"), @@ -1157,7 +1163,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("ファイル名を変更"), "renewSubscription": MessageLookupByLibrary.simpleMessage("サブスクリプションの更新"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("バグを報告"), "reportBug": MessageLookupByLibrary.simpleMessage("バグを報告"), "resendEmail": MessageLookupByLibrary.simpleMessage("メールを再送信"), @@ -1165,6 +1171,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("アップロード時に無視されるファイルをリセット"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("パスワードをリセット"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("初期設定にリセット"), "restore": MessageLookupByLibrary.simpleMessage("復元"), "restoreToAlbum": MessageLookupByLibrary.simpleMessage("アルバムに戻す"), @@ -1214,7 +1221,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("当時の直近で撮影された写真をグループ化"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage("友達を招待すると、共有される写真はここから閲覧できます"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("セキュリティ"), "selectALocation": MessageLookupByLibrary.simpleMessage("場所を選択"), "selectALocationFirst": @@ -1236,8 +1243,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "選択したアイテムはすべてのアルバムから削除され、ゴミ箱に移動されます。"), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("送信"), "sendEmail": MessageLookupByLibrary.simpleMessage("メールを送信する"), "sendInvite": MessageLookupByLibrary.simpleMessage("招待を送る"), @@ -1259,16 +1266,16 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("アルバムを開いて右上のシェアボタンをタップ"), "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("アルバムを共有"), "shareLink": MessageLookupByLibrary.simpleMessage("リンクの共有"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage("選んだ人と共有します"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Enteをダウンロードして、写真や動画の共有を簡単に!\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage("Enteを使っていない人に共有"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("アルバムの共有をしてみましょう"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1279,7 +1286,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("新しい共有写真"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage("誰かが写真を共有アルバムに追加した時に通知を受け取る"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("あなたと共有されたアルバム"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("あなたと共有されています"), "sharing": MessageLookupByLibrary.simpleMessage("共有中..."), @@ -1293,11 +1300,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("他のデバイスからサインアウトする"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "利用規約プライバシーポリシーに同意します"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage("全てのアルバムから削除されます。"), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("スキップ"), "social": MessageLookupByLibrary.simpleMessage("SNS"), "someItemsAreInBothEnteAndYourDevice": @@ -1335,7 +1342,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("ストレージ"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("ファミリー"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("あなた"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("ストレージの上限を超えました"), "storageUsageInfo": m62, @@ -1506,7 +1513,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "あなたが所有していない写真やアルバムの編集はサポートされていません"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("弱いパスワード"), "welcomeBack": MessageLookupByLibrary.simpleMessage("おかえりなさい!"), "whatsNew": MessageLookupByLibrary.simpleMessage("最新情報"), @@ -1522,6 +1529,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("はい、ログアウトします"), "yesRemove": MessageLookupByLibrary.simpleMessage("削除"), "yesRenew": MessageLookupByLibrary.simpleMessage("はい、更新する"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("あなた"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("ファミリープランに入会しています!"), diff --git a/mobile/lib/generated/intl/messages_km.dart b/mobile/lib/generated/intl/messages_km.dart index 22d4231361..3bb3947035 100644 --- a/mobile/lib/generated/intl/messages_km.dart +++ b/mobile/lib/generated/intl/messages_km.dart @@ -21,5 +21,15 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'km'; final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => {}; + static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") + }; } diff --git a/mobile/lib/generated/intl/messages_ko.dart b/mobile/lib/generated/intl/messages_ko.dart index e378d62fd9..12f1188e8f 100644 --- a/mobile/lib/generated/intl/messages_ko.dart +++ b/mobile/lib/generated/intl/messages_ko.dart @@ -24,6 +24,11 @@ class MessageLookup extends MessageLookupByLibrary { static Map _notInlinedMessages(_) => { "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("다시 오신 것을 환영합니다!"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage("계정을 삭제하는 가장 큰 이유가 무엇인가요?"), "cancel": MessageLookupByLibrary.simpleMessage("닫기"), @@ -40,7 +45,11 @@ class MessageLookup extends MessageLookupByLibrary { "feedback": MessageLookupByLibrary.simpleMessage("피드백"), "invalidEmailAddress": MessageLookupByLibrary.simpleMessage("잘못된 이메일 주소"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "verify": MessageLookupByLibrary.simpleMessage("인증"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("계정이 삭제되었습니다.") }; diff --git a/mobile/lib/generated/intl/messages_lt.dart b/mobile/lib/generated/intl/messages_lt.dart index 5d36692d79..0bb2ad4423 100644 --- a/mobile/lib/generated/intl/messages_lt.dart +++ b/mobile/lib/generated/intl/messages_lt.dart @@ -20,59 +20,306 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'lt'; - static String m12(versionValue) => "Versija: ${versionValue}"; + static String m6(count) => + "${Intl.plural(count, one: 'Pridėti bendradarbį', few: 'Pridėti bendradarbius', many: 'Pridėti bendradarbio', other: 'Pridėti bendradarbių')}"; - static String m47(folderName) => "Apdorojama ${folderName}..."; + static String m9(count) => + "${Intl.plural(count, one: 'Pridėti žiūrėtoją', few: 'Pridėti žiūrėtojus', many: 'Pridėti žiūrėtojo', other: 'Pridėti žiūrėtojų')}"; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m13(versionValue) => "Versija: ${versionValue}"; + + static String m15(paymentProvider) => + "Pirmiausia atsisakykite esamos prenumeratos iš ${paymentProvider}"; + + static String m16(user) => + "${user} negalės pridėti daugiau nuotraukų į šį albumą\n\nJie vis tiek galės pašalinti esamas pridėtas nuotraukas"; + + static String m21(endpoint) => "Prijungta prie ${endpoint}"; + + static String m25(supportEmail) => + "Iš savo registruoto el. pašto adreso atsiųskite el. laišką adresu ${supportEmail}"; + + static String m27(count, formattedSize) => + "${count} failai (-ų), kiekvienas ${formattedSize}"; + + static String m29(email) => + "${email} neturi „Ente“ paskyros.\n\nSiųskite jiems kvietimą bendrinti nuotraukas."; + + static String m33(endDate) => + "Nemokamas bandomasis laikotarpis galioja iki ${endDate}"; + + static String m35(sizeInMBorGB) => "Atlaisvinti ${sizeInMBorGB}"; + + static String m40(count) => + "${Intl.plural(count, one: 'Perkelti elementą', few: 'Perkelti elementus', many: 'Perkelti elemento', other: 'Perkelti elementų')}"; + + static String m42(name) => "Ne ${name}?"; + + static String m0(passwordStrengthValue) => + "Slaptažodžio stiprumas: ${passwordStrengthValue}"; + + static String m44(providerName) => + "Kreipkitės į ${providerName} palaikymo komandą, jei jums buvo nuskaičiuota."; + + static String m48(folderName) => "Apdorojama ${folderName}..."; + + static String m49(storeName) => "Vertinti mus parduotuvėje „${storeName}“"; + + static String m51(userEmail) => + "${userEmail} bus pašalintas iš šio bendrinamo albumo\n\nVisos jų pridėtos nuotraukos taip pat bus pašalintos iš albumo"; + + static String m53(count) => + "${Intl.plural(count, one: 'Rastas ${count} rezultatas', few: 'Rasti ${count} rezultatai', many: 'Rasta ${count} rezultato', other: 'Rasta ${count} rezultatų')}"; + + static String m4(count) => "${count} pasirinkta"; + + static String m54(count, yourCount) => + "${count} pasirinkta (${yourCount} jūsų)"; + + static String m60(fileType) => + "Šis ${fileType} yra ir platformoje „Ente“ bei įrenginyje."; + + static String m61(fileType) => "Šis ${fileType} bus ištrintas iš „Ente“."; + + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; + + static String m63(id) => + "Jūsų ${id} jau susietas su kita „Ente“ paskyra.\nJei norite naudoti savo ${id} su šia paskyra, susisiekite su mūsų palaikymo komanda."; + + static String m65(completed, total) => + "${completed} / ${total} išsaugomi prisiminimai"; + + static String m70(endDate) => "Galioja iki ${endDate}"; + + static String m2(email) => "Išsiuntėme laišką adresu ${email}"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { + "about": MessageLookupByLibrary.simpleMessage("Apie"), + "account": MessageLookupByLibrary.simpleMessage("Paskyra"), "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("Sveiki sugrįžę!"), "ackPasswordLostWarning": MessageLookupByLibrary.simpleMessage( - "Suprantu, kad jei prarasiu slaptažodį, galiu prarasti savo duomenis, kadangi mano duomenys yra visapusiškai užšifruota."), + "Suprantu, kad jei prarasiu slaptažodį, galiu prarasti savo duomenis, kadangi mano duomenys yra visapusiškai užšifruoti."), "activeSessions": MessageLookupByLibrary.simpleMessage("Aktyvūs seansai"), "add": MessageLookupByLibrary.simpleMessage("Pridėti"), + "addAName": MessageLookupByLibrary.simpleMessage("Pridėti vardą"), + "addANewEmail": + MessageLookupByLibrary.simpleMessage("Pridėti naują el. paštą"), + "addCollaborator": + MessageLookupByLibrary.simpleMessage("Pridėti bendradarbį"), + "addCollaborators": m6, + "addLocation": MessageLookupByLibrary.simpleMessage("Pridėti vietovę"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Pridėti"), + "addMore": MessageLookupByLibrary.simpleMessage("Pridėti daugiau"), + "addName": MessageLookupByLibrary.simpleMessage("Pridėti vardą"), + "addNameOrMerge": + MessageLookupByLibrary.simpleMessage("Pridėti vardą arba sujungti"), + "addNew": MessageLookupByLibrary.simpleMessage("Pridėti naują"), "addNewPerson": MessageLookupByLibrary.simpleMessage("Pridėti naują asmenį"), + "addToAlbum": MessageLookupByLibrary.simpleMessage("Pridėti į albumą"), + "addToEnte": MessageLookupByLibrary.simpleMessage("Pridėti į „Ente“"), + "addViewer": MessageLookupByLibrary.simpleMessage("Pridėti žiūrėtoją"), + "addViewers": m9, + "advancedSettings": + MessageLookupByLibrary.simpleMessage("Išplėstiniai"), + "after1Day": MessageLookupByLibrary.simpleMessage("Po 1 dienos"), + "after1Hour": MessageLookupByLibrary.simpleMessage("Po 1 valandos"), + "after1Month": MessageLookupByLibrary.simpleMessage("Po 1 mėnesio"), + "after1Week": MessageLookupByLibrary.simpleMessage("Po 1 savaitės"), + "after1Year": MessageLookupByLibrary.simpleMessage("Po 1 metų"), + "albumUpdated": + MessageLookupByLibrary.simpleMessage("Atnaujintas albumas"), + "albums": MessageLookupByLibrary.simpleMessage("Albumai"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( + "Leiskite nuorodą turintiems asmenims taip pat pridėti nuotraukų į bendrinamą albumą."), + "allowAddingPhotos": + MessageLookupByLibrary.simpleMessage("Leisti pridėti nuotraukų"), + "allowDownloads": + MessageLookupByLibrary.simpleMessage("Leisti atsisiuntimus"), + "androidBiometricHint": + MessageLookupByLibrary.simpleMessage("Patvirtinkite tapatybę"), + "androidCancelButton": MessageLookupByLibrary.simpleMessage("Atšaukti"), + "androidIosWebDesktop": MessageLookupByLibrary.simpleMessage( + "„Android“, „iOS“, internete ir darbalaukyje"), + "androidSignInTitle": MessageLookupByLibrary.simpleMessage( + "Privalomas tapatybės nustatymas"), + "appLock": MessageLookupByLibrary.simpleMessage("Programos užraktas"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Pasirinkite tarp numatytojo įrenginio užrakinimo ekrano ir pasirinktinio užrakinimo ekrano su PIN kodu arba slaptažodžiu."), - "appVersion": m12, + "appVersion": m13, + "appleId": MessageLookupByLibrary.simpleMessage("„Apple ID“"), + "apply": MessageLookupByLibrary.simpleMessage("Taikyti"), + "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Taikyti kodą"), + "archiving": MessageLookupByLibrary.simpleMessage("Archyvuojama..."), + "areYouSureThatYouWantToLeaveTheFamily": + MessageLookupByLibrary.simpleMessage( + "Ar tikrai norite palikti šeimos planą?"), + "areYouSureYouWantToChangeYourPlan": + MessageLookupByLibrary.simpleMessage( + "Ar tikrai norite keisti planą?"), + "areYouSureYouWantToExit": + MessageLookupByLibrary.simpleMessage("Ar tikrai norite išeiti?"), + "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( + "Ar tikrai norite atsijungti?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Kokia yra pagrindinė priežastis, dėl kurios ištrinate savo paskyrą?"), + "authToChangeEmailVerificationSetting": + MessageLookupByLibrary.simpleMessage( + "Nustatykite tapatybę, kad pakeistumėte el. pašto patvirtinimą"), + "authToChangeYourEmail": MessageLookupByLibrary.simpleMessage( + "Nustatykite tapatybę, kad pakeistumėte savo el. paštą"), + "authToChangeYourPassword": MessageLookupByLibrary.simpleMessage( + "Nustatykite tapatybę, kad pakeistumėte slaptažodį"), + "authToInitiateAccountDeletion": MessageLookupByLibrary.simpleMessage( + "Nustatykite tapatybę, kad pradėtumėte paskyros ištrynimą"), "authToViewPasskey": MessageLookupByLibrary.simpleMessage( "Nustatykite tapatybę, kad peržiūrėtumėte savo slaptaraktą"), + "autoCastDialogBody": MessageLookupByLibrary.simpleMessage( + "Čia matysite pasiekiamus perdavimo įrenginius."), + "autoLock": + MessageLookupByLibrary.simpleMessage("Automatinis užraktas"), + "autoLockFeatureDescription": MessageLookupByLibrary.simpleMessage( + "Laikas, po kurio programa užrakinama perkėlus ją į foną"), + "autoLogoutMessage": MessageLookupByLibrary.simpleMessage( + "Dėl techninio trikdžio buvote atjungti. Atsiprašome už nepatogumus."), + "autoPair": + MessageLookupByLibrary.simpleMessage("Automatiškai susieti"), + "autoPairDesc": MessageLookupByLibrary.simpleMessage( + "Automatinis susiejimas veikia tik su įrenginiais, kurie palaiko „Chromecast“."), + "available": MessageLookupByLibrary.simpleMessage("Prieinama"), "blog": MessageLookupByLibrary.simpleMessage("Tinklaraštis"), + "cachedData": + MessageLookupByLibrary.simpleMessage("Podėliuoti duomenis"), + "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( + "Galima pašalinti tik jums priklausančius failus"), "cancel": MessageLookupByLibrary.simpleMessage("Atšaukti"), + "cancelOtherSubscription": m15, + "cancelSubscription": + MessageLookupByLibrary.simpleMessage("Atsisakyti prenumeratos"), + "cannotAddMorePhotosAfterBecomingViewer": m16, + "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( + "Įsitikinkite, kad esate tame pačiame tinkle kaip ir televizorius."), + "castIPMismatchTitle": + MessageLookupByLibrary.simpleMessage("Nepavyko perduoti albumo"), + "castInstruction": MessageLookupByLibrary.simpleMessage( + "Aplankykite cast.ente.io įrenginyje, kurį norite susieti.\n\nĮveskite toliau esantį kodą, kad paleistumėte albumą televizoriuje."), + "centerPoint": MessageLookupByLibrary.simpleMessage("Vidurio taškas"), + "change": MessageLookupByLibrary.simpleMessage("Keisti"), "changeEmail": MessageLookupByLibrary.simpleMessage("Keisti el. paštą"), + "changeLocationOfSelectedItems": MessageLookupByLibrary.simpleMessage( + "Keisti pasirinktų elementų vietovę?"), + "changePassword": + MessageLookupByLibrary.simpleMessage("Keisti slaptažodį"), + "changePasswordTitle": + MessageLookupByLibrary.simpleMessage("Keisti slaptažodį"), + "changePermissions": + MessageLookupByLibrary.simpleMessage("Keisti leidimus?"), + "checkForUpdates": MessageLookupByLibrary.simpleMessage( + "Tikrinti, ar yra atnaujinimų"), + "checkInboxAndSpamFolder": MessageLookupByLibrary.simpleMessage( + "Patikrinkite savo gautieją (ir šlamštą), kad užbaigtumėte patvirtinimą"), + "checkStatus": MessageLookupByLibrary.simpleMessage("Tikrinti būseną"), + "checking": MessageLookupByLibrary.simpleMessage("Tikrinama..."), + "cleanUncategorized": + MessageLookupByLibrary.simpleMessage("Valyti nekategorizuotą"), + "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( + "Pašalinkite iš nekategorizuotą visus failus, esančius kituose albumuose"), + "clearCaches": MessageLookupByLibrary.simpleMessage("Valyti podėlius"), + "close": MessageLookupByLibrary.simpleMessage("Uždaryti"), + "clusteringProgress": + MessageLookupByLibrary.simpleMessage("Sankaupos vykdymas"), + "codeAppliedPageTitle": + MessageLookupByLibrary.simpleMessage("Pritaikytas kodas"), + "codeChangeLimitReached": MessageLookupByLibrary.simpleMessage( + "Atsiprašome, pasiekėte kodo pakeitimų ribą."), + "codeCopiedToClipboard": MessageLookupByLibrary.simpleMessage( + "Nukopijuotas kodas į iškarpinę"), + "collabLinkSectionDescription": MessageLookupByLibrary.simpleMessage( + "Sukurkite nuorodą, kad asmenys galėtų pridėti ir peržiūrėti nuotraukas bendrinamame albume, nereikalaujant „Ente“ programos ar paskyros. Puikiai tinka renginių nuotraukoms rinkti."), + "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": + MessageLookupByLibrary.simpleMessage( + "Bendradarbiai gali pridėti nuotraukų ir vaizdo įrašų į bendrintą albumą."), "collect": MessageLookupByLibrary.simpleMessage("Rinkti"), + "collectPhotosDescription": MessageLookupByLibrary.simpleMessage( + "Sukurkite nuorodą, į kurią draugai gali įkelti originalios kokybės nuotraukas."), "color": MessageLookupByLibrary.simpleMessage("Spalva"), + "configuration": MessageLookupByLibrary.simpleMessage("Konfiguracija"), + "confirm": MessageLookupByLibrary.simpleMessage("Patvirtinti"), "confirmAccountDeletion": MessageLookupByLibrary.simpleMessage( - "Patvirtinti paskyros ištrynimą"), + "Patvirtinkite paskyros ištrynimą"), "confirmDeletePrompt": MessageLookupByLibrary.simpleMessage( "Taip, noriu negrįžtamai ištrinti šią paskyrą ir jos duomenis per visas programas."), "confirmPassword": - MessageLookupByLibrary.simpleMessage("Patvirtinti slaptažodį"), + MessageLookupByLibrary.simpleMessage("Patvirtinkite slaptažodį"), + "confirmPlanChange": MessageLookupByLibrary.simpleMessage( + "Patvirtinkite plano pakeitimą"), + "confirmRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Patvirtinkite atkūrimo raktą"), + "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Patvirtinkite savo atkūrimo raktą"), + "connectToDevice": + MessageLookupByLibrary.simpleMessage("Prijungti prie įrenginio"), "contactSupport": MessageLookupByLibrary.simpleMessage( "Susisiekti su palaikymo komanda"), + "contacts": MessageLookupByLibrary.simpleMessage("Kontaktai"), + "continueLabel": MessageLookupByLibrary.simpleMessage("Tęsti"), + "continueOnFreeTrial": MessageLookupByLibrary.simpleMessage( + "Tęsti nemokame bandomajame laikotarpyje"), + "copyLink": MessageLookupByLibrary.simpleMessage("Kopijuoti nuorodą"), + "copypasteThisCodentoYourAuthenticatorApp": + MessageLookupByLibrary.simpleMessage( + "Nukopijuokite ir įklijuokite šį kodą\nį autentifikatoriaus programą"), + "couldNotFreeUpSpace": MessageLookupByLibrary.simpleMessage( + "Nepavyko atlaisvinti vietos."), + "create": MessageLookupByLibrary.simpleMessage("Kurti"), "createAccount": MessageLookupByLibrary.simpleMessage("Kurti paskyrą"), + "createCollaborativeLink": MessageLookupByLibrary.simpleMessage( + "Kurti bendradarbiavimo nuorodą"), "createNewAccount": MessageLookupByLibrary.simpleMessage("Kurti naują paskyrą"), + "creatingLink": + MessageLookupByLibrary.simpleMessage("Kuriama nuoroda..."), + "crop": MessageLookupByLibrary.simpleMessage("Apkirpti"), + "currentUsageIs": + MessageLookupByLibrary.simpleMessage("Dabartinis naudojimas – "), + "custom": MessageLookupByLibrary.simpleMessage("Pasirinktinis"), + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Tamsi"), "dayToday": MessageLookupByLibrary.simpleMessage("Šiandien"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Vakar"), "decrypting": MessageLookupByLibrary.simpleMessage("Iššifruojama..."), + "deduplicateFiles": + MessageLookupByLibrary.simpleMessage("Atdubliuoti failus"), + "delete": MessageLookupByLibrary.simpleMessage("Ištrinti"), "deleteAccount": MessageLookupByLibrary.simpleMessage("Ištrinti paskyrą"), "deleteAccountFeedbackPrompt": MessageLookupByLibrary.simpleMessage( "Apgailestaujame, kad išeinate. Pasidalykite savo atsiliepimais, kad padėtumėte mums tobulėti."), "deleteAccountPermanentlyButton": MessageLookupByLibrary.simpleMessage( "Ištrinti paskyrą negrįžtamai"), + "deleteAlbum": MessageLookupByLibrary.simpleMessage("Ištrinti albumą"), + "deleteAlbumDialog": MessageLookupByLibrary.simpleMessage( + "Taip pat ištrinti šiame albume esančias nuotraukas (ir vaizdo įrašus) iš visų kitų albumų, kuriuose jos yra dalis?"), + "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( + "Ši paskyra susieta su kitomis „Ente“ programomis, jei jas naudojate. Jūsų įkelti duomenys per visas „Ente“ programas bus planuojama ištrinti, o jūsų paskyra bus ištrinta negrįžtamai."), "deleteEmailRequest": MessageLookupByLibrary.simpleMessage( "Iš savo registruoto el. pašto adreso siųskite el. laišką adresu account-deletion@ente.io."), + "deleteFromBoth": + MessageLookupByLibrary.simpleMessage("Ištrinti iš abiejų"), + "deleteFromDevice": + MessageLookupByLibrary.simpleMessage("Ištrinti iš įrenginio"), + "deleteFromEnte": + MessageLookupByLibrary.simpleMessage("Ištrinti iš „Ente“"), + "deleteLocation": + MessageLookupByLibrary.simpleMessage("Ištrinti vietovę"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Ištrinti nuotraukas"), "deleteReason1": MessageLookupByLibrary.simpleMessage( @@ -85,6 +332,20 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Mano priežastis nenurodyta"), "deleteRequestSLAText": MessageLookupByLibrary.simpleMessage( "Jūsų prašymas bus apdorotas per 72 valandas."), + "descriptions": MessageLookupByLibrary.simpleMessage("Aprašymai"), + "developerSettings": + MessageLookupByLibrary.simpleMessage("Kūrėjo nustatymai"), + "developerSettingsWarning": MessageLookupByLibrary.simpleMessage( + "Ar tikrai norite modifikuoti kūrėjo nustatymus?"), + "deviceCodeHint": MessageLookupByLibrary.simpleMessage("Įveskite kodą"), + "deviceLock": + MessageLookupByLibrary.simpleMessage("Įrenginio užraktas"), + "deviceNotFound": + MessageLookupByLibrary.simpleMessage("Įrenginys nerastas"), + "disableDownloadWarningBody": MessageLookupByLibrary.simpleMessage( + "Žiūrėtojai vis tiek gali daryti ekrano kopijas arba išsaugoti nuotraukų kopijas naudojant išorinius įrankius"), + "disableDownloadWarningTitle": + MessageLookupByLibrary.simpleMessage("Atkreipkite dėmesį"), "discord": MessageLookupByLibrary.simpleMessage("„Discord“"), "discover": MessageLookupByLibrary.simpleMessage("Atraskite"), "discover_babies": MessageLookupByLibrary.simpleMessage("Kūdikiai"), @@ -94,6 +355,7 @@ class MessageLookup extends MessageLookupByLibrary { "discover_greenery": MessageLookupByLibrary.simpleMessage("Žaluma"), "discover_hills": MessageLookupByLibrary.simpleMessage("Kalvos"), "discover_identity": MessageLookupByLibrary.simpleMessage("Tapatybė"), + "discover_memes": MessageLookupByLibrary.simpleMessage("Mėmai"), "discover_notes": MessageLookupByLibrary.simpleMessage("Užrašai"), "discover_pets": MessageLookupByLibrary.simpleMessage("Gyvūnai"), "discover_receipts": MessageLookupByLibrary.simpleMessage("Kvitai"), @@ -106,121 +368,646 @@ class MessageLookup extends MessageLookupByLibrary { "discover_wallpapers": MessageLookupByLibrary.simpleMessage("Ekrano fonai"), "distanceInKMUnit": MessageLookupByLibrary.simpleMessage("km"), + "doNotSignOut": MessageLookupByLibrary.simpleMessage("Neatsijungti"), + "doThisLater": + MessageLookupByLibrary.simpleMessage("Daryti tai vėliau"), + "download": MessageLookupByLibrary.simpleMessage("Atsisiųsti"), + "downloadFailed": + MessageLookupByLibrary.simpleMessage("Atsisiuntimas nepavyko."), + "dropSupportEmail": m25, + "duplicateItemsGroup": m27, + "edit": MessageLookupByLibrary.simpleMessage("Redaguoti"), + "editLocation": + MessageLookupByLibrary.simpleMessage("Redaguoti vietovę"), + "editLocationTagTitle": + MessageLookupByLibrary.simpleMessage("Redaguoti vietovę"), + "editsToLocationWillOnlyBeSeenWithinEnte": + MessageLookupByLibrary.simpleMessage( + "Vietovės pakeitimai bus matomi tik per „Ente“"), "email": MessageLookupByLibrary.simpleMessage("El. paštas"), + "emailNoEnteAccount": m29, + "emailVerificationToggle": + MessageLookupByLibrary.simpleMessage("El. pašto patvirtinimas"), + "empty": MessageLookupByLibrary.simpleMessage("Ištuštinti"), + "emptyTrash": + MessageLookupByLibrary.simpleMessage("Ištuštinti šiukšlinę?"), + "enable": MessageLookupByLibrary.simpleMessage("Įjungti"), + "enableMLIndexingDesc": MessageLookupByLibrary.simpleMessage( + "„Ente“ palaiko įrenginyje mašininį mokymąsi, skirtą veidų atpažinimui, magiškai paieškai ir kitoms išplėstinėms paieškos funkcijoms"), + "enableMapsDesc": MessageLookupByLibrary.simpleMessage( + "Tai parodys jūsų nuotraukas pasaulio žemėlapyje.\n\nŠį žemėlapį talpina „OpenStreetMap“, o tiksliomis nuotraukų vietovėmis niekada nebendrinama.\n\nŠią funkciją bet kada galite išjungti iš nustatymų."), + "enabled": MessageLookupByLibrary.simpleMessage("Įjungta"), "encryption": MessageLookupByLibrary.simpleMessage("Šifravimas"), + "encryptionKeys": + MessageLookupByLibrary.simpleMessage("Šifravimo raktai"), + "endpointUpdatedMessage": MessageLookupByLibrary.simpleMessage( + "Galutinis taškas sėkmingai atnaujintas"), "entePhotosPerm": MessageLookupByLibrary.simpleMessage( "„Ente“ reikia leidimo išsaugoti jūsų nuotraukas"), + "enteSubscriptionPitch": MessageLookupByLibrary.simpleMessage( + "„Ente“ išsaugo jūsų prisiminimus, todėl jie visada bus pasiekiami, net jei prarasite įrenginį."), + "enterCode": MessageLookupByLibrary.simpleMessage("Įvesti kodą"), + "enterEmail": + MessageLookupByLibrary.simpleMessage("Įveskite el. paštą"), + "enterNewPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( + "Įveskite naują slaptažodį, kurį galime naudoti jūsų duomenims šifruoti"), + "enterPassword": + MessageLookupByLibrary.simpleMessage("Įveskite slaptažodį"), + "enterPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( + "Įveskite slaptažodį, kurį galime naudoti jūsų duomenims šifruoti"), + "enterPersonName": + MessageLookupByLibrary.simpleMessage("Įveskite asmens vardą"), + "enterPin": MessageLookupByLibrary.simpleMessage("Įveskite PIN"), + "enterThe6digitCodeFromnyourAuthenticatorApp": + MessageLookupByLibrary.simpleMessage( + "Įveskite 6 skaitmenų kodą\niš autentifikatoriaus programos"), "enterValidEmail": MessageLookupByLibrary.simpleMessage( "Įveskite tinkamą el. pašto adresą."), "enterYourEmailAddress": MessageLookupByLibrary.simpleMessage( "Įveskite savo el. pašto adresą"), "enterYourPassword": MessageLookupByLibrary.simpleMessage("Įveskite savo slaptažodį"), + "enterYourRecoveryKey": + MessageLookupByLibrary.simpleMessage("Įveskite atkūrimo raktą"), + "error": MessageLookupByLibrary.simpleMessage("Klaida"), + "everywhere": MessageLookupByLibrary.simpleMessage("visur"), "exif": MessageLookupByLibrary.simpleMessage("EXIF"), + "existingUser": + MessageLookupByLibrary.simpleMessage("Esamas naudotojas"), + "exportYourData": + MessageLookupByLibrary.simpleMessage("Eksportuoti duomenis"), "extraPhotosFound": MessageLookupByLibrary.simpleMessage( "Rastos papildomos nuotraukos"), "extraPhotosFoundFor": MessageLookupByLibrary.simpleMessage( "Rastos papildomos nuotraukos, skirtos \$text"), + "faceRecognition": + MessageLookupByLibrary.simpleMessage("Veido atpažinimas"), + "faces": MessageLookupByLibrary.simpleMessage("Veidai"), + "failedToCancel": + MessageLookupByLibrary.simpleMessage("Nepavyko atsisakyti"), + "failedToVerifyPaymentStatus": MessageLookupByLibrary.simpleMessage( + "Nepavyko patvirtinti mokėjimo būsenos"), "faq": MessageLookupByLibrary.simpleMessage("DUK"), + "faqs": MessageLookupByLibrary.simpleMessage("DUK"), "feedback": MessageLookupByLibrary.simpleMessage("Atsiliepimai"), + "findPeopleByName": MessageLookupByLibrary.simpleMessage( + "Greitai suraskite žmones pagal vardą"), + "forgotPassword": + MessageLookupByLibrary.simpleMessage("Pamiršau slaptažodį"), + "foundFaces": MessageLookupByLibrary.simpleMessage("Rasti veidai"), + "freeTrial": MessageLookupByLibrary.simpleMessage( + "Nemokamas bandomasis laikotarpis"), + "freeTrialValidTill": m33, + "freeUpAmount": m35, + "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( + "Generuojami šifravimo raktai..."), + "goToSettings": + MessageLookupByLibrary.simpleMessage("Eiti į nustatymus"), + "googlePlayId": + MessageLookupByLibrary.simpleMessage("„Google Play“ ID"), + "guestView": MessageLookupByLibrary.simpleMessage("Svečio peržiūra"), + "guestViewEnablePreSteps": MessageLookupByLibrary.simpleMessage( + "Kad įjungtumėte svečio peržiūrą, sistemos nustatymuose nustatykite įrenginio prieigos kodą arba ekrano užraktą."), + "hidden": MessageLookupByLibrary.simpleMessage("Paslėpti"), + "hide": MessageLookupByLibrary.simpleMessage("Slėpti"), + "hideContent": MessageLookupByLibrary.simpleMessage("Slėpti turinį"), + "hideContentDescriptionAndroid": MessageLookupByLibrary.simpleMessage( + "Paslepia programų turinį programų perjungiklyje ir išjungia ekrano kopijas"), + "hideContentDescriptionIos": MessageLookupByLibrary.simpleMessage( + "Paslepia programos turinį programos perjungiklyje"), "howItWorks": MessageLookupByLibrary.simpleMessage("Kaip tai veikia"), + "iOSOkButton": MessageLookupByLibrary.simpleMessage("Gerai"), + "immediately": MessageLookupByLibrary.simpleMessage("Iš karto"), + "importing": MessageLookupByLibrary.simpleMessage("Importuojama...."), "incorrectPasswordTitle": - MessageLookupByLibrary.simpleMessage("Neteisingas slaptažodis."), + MessageLookupByLibrary.simpleMessage("Neteisingas slaptažodis"), + "incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage( + "Įvestas atkūrimo raktas yra neteisingas."), + "incorrectRecoveryKeyTitle": + MessageLookupByLibrary.simpleMessage("Neteisingas atkūrimo raktas"), + "indexedItems": + MessageLookupByLibrary.simpleMessage("Indeksuoti elementai"), + "indexingIsPaused": MessageLookupByLibrary.simpleMessage( + "Indeksavimas pristabdytas. Jis bus automatiškai tęsiamas, kai įrenginys yra paruoštas."), + "insecureDevice": + MessageLookupByLibrary.simpleMessage("Nesaugus įrenginys"), "invalidEmailAddress": MessageLookupByLibrary.simpleMessage( - "Netinkamas el. pašto adresas."), + "Netinkamas el. pašto adresas"), + "invalidEndpoint": + MessageLookupByLibrary.simpleMessage("Netinkamas galutinis taškas"), + "invalidEndpointMessage": MessageLookupByLibrary.simpleMessage( + "Atsiprašome, įvestas galutinis taškas netinkamas. Įveskite tinkamą galutinį tašką ir bandykite dar kartą."), + "invalidKey": + MessageLookupByLibrary.simpleMessage("Netinkamas raktas."), + "invalidRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Įvestas atkūrimo raktas yra netinkamas. Įsitikinkite, kad jame yra 24 žodžiai, ir patikrinkite kiekvieno iš jų rašybą.\n\nJei įvedėte senesnį atkūrimo kodą, įsitikinkite, kad jis yra 64 simbolių ilgio, ir patikrinkite kiekvieną iš jų."), "inviteToEnte": MessageLookupByLibrary.simpleMessage("Kviesti į „Ente“"), + "itemsWillBeRemovedFromAlbum": MessageLookupByLibrary.simpleMessage( + "Pasirinkti elementai bus pašalinti iš šio albumo"), + "joinDiscord": + MessageLookupByLibrary.simpleMessage("Jungtis prie „Discord“"), "keepPhotos": MessageLookupByLibrary.simpleMessage("Palikti nuotraukas"), "kiloMeterUnit": MessageLookupByLibrary.simpleMessage("km"), "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage( "Maloniai padėkite mums su šia informacija"), + "lastUpdated": + MessageLookupByLibrary.simpleMessage("Paskutinį kartą atnaujintą"), + "leave": MessageLookupByLibrary.simpleMessage("Palikti"), + "leaveAlbum": MessageLookupByLibrary.simpleMessage("Palikti albumą"), + "leaveFamily": MessageLookupByLibrary.simpleMessage("Palikti šeimą"), + "left": MessageLookupByLibrary.simpleMessage("Kairė"), "light": MessageLookupByLibrary.simpleMessage("Šviesi"), "lightTheme": MessageLookupByLibrary.simpleMessage("Šviesi"), + "linkDeviceLimit": + MessageLookupByLibrary.simpleMessage("Įrenginių riba"), + "linkEnabled": MessageLookupByLibrary.simpleMessage("Įjungta"), + "linkExpiry": + MessageLookupByLibrary.simpleMessage("Nuorodos galiojimo laikas"), + "linkNeverExpires": MessageLookupByLibrary.simpleMessage("Niekada"), + "loadingGallery": + MessageLookupByLibrary.simpleMessage("Įkeliama galerija..."), "loadingYourPhotos": MessageLookupByLibrary.simpleMessage("Įkeliamos nuotraukos..."), + "localGallery": + MessageLookupByLibrary.simpleMessage("Vietinė galerija"), + "localIndexing": + MessageLookupByLibrary.simpleMessage("Vietinis indeksavimas"), "localSyncErrorMessage": MessageLookupByLibrary.simpleMessage( "Atrodo, kad kažkas nutiko ne taip, nes vietinių nuotraukų sinchronizavimas trunka ilgiau nei tikėtasi. Susisiekite su mūsų palaikymo komanda."), + "location": MessageLookupByLibrary.simpleMessage("Vietovė"), + "locationName": + MessageLookupByLibrary.simpleMessage("Vietovės pavadinimas"), + "locationTagFeatureDescription": MessageLookupByLibrary.simpleMessage( + "Vietos žymė grupuoja visas nuotraukas, kurios buvo padarytos tam tikru spinduliu nuo nuotraukos"), + "locations": MessageLookupByLibrary.simpleMessage("Vietovės"), + "lockButtonLabel": MessageLookupByLibrary.simpleMessage("Užrakinti"), "logInLabel": MessageLookupByLibrary.simpleMessage("Prisijungti"), + "loginSessionExpired": + MessageLookupByLibrary.simpleMessage("Seansas baigėsi"), + "loginSessionExpiredDetails": MessageLookupByLibrary.simpleMessage( + "Jūsų seansas baigėsi. Prisijunkite iš naujo."), "loginTerms": MessageLookupByLibrary.simpleMessage( "Spustelėjus Prisijungti sutinku su paslaugų sąlygomis ir privatumo politika"), + "logout": MessageLookupByLibrary.simpleMessage("Atsijungti"), + "longPressAnEmailToVerifyEndToEndEncryption": + MessageLookupByLibrary.simpleMessage( + "Ilgai paspauskite el. paštą, kad patvirtintumėte visapusį šifravimą."), + "loopVideoOff": MessageLookupByLibrary.simpleMessage( + "Išjungtas vaizdo įrašo ciklas"), + "loopVideoOn": MessageLookupByLibrary.simpleMessage( + "Įjungtas vaizdo įrašo ciklas"), + "lostDevice": + MessageLookupByLibrary.simpleMessage("Prarastas įrenginys?"), "machineLearning": - MessageLookupByLibrary.simpleMessage("Kompiuterinis mokymasis"), + MessageLookupByLibrary.simpleMessage("Mašininis mokymasis"), "magicSearch": MessageLookupByLibrary.simpleMessage("Magiška paieška"), + "magicSearchHint": MessageLookupByLibrary.simpleMessage( + "Magiška paieška leidžia ieškoti nuotraukų pagal jų turinį, pvz., „gėlė“, „raudonas automobilis“, „tapatybės dokumentai“"), + "manageFamily": MessageLookupByLibrary.simpleMessage("Tvarkyti šeimą"), + "manageLink": MessageLookupByLibrary.simpleMessage("Tvarkyti nuorodą"), + "manageParticipants": MessageLookupByLibrary.simpleMessage("Tvarkyti"), + "manageSubscription": + MessageLookupByLibrary.simpleMessage("Tvarkyti prenumeratą"), + "manualPairDesc": MessageLookupByLibrary.simpleMessage( + "Susieti su PIN kodu veikia bet kuriame ekrane, kuriame norite peržiūrėti albumą."), + "map": MessageLookupByLibrary.simpleMessage("Žemėlapis"), "mastodon": MessageLookupByLibrary.simpleMessage("„Mastodon“"), "matrix": MessageLookupByLibrary.simpleMessage("„Matrix“"), "merchandise": MessageLookupByLibrary.simpleMessage("Atributika"), - "mostRecent": MessageLookupByLibrary.simpleMessage("Naujausia"), - "mostRelevant": MessageLookupByLibrary.simpleMessage("Aktualiausia"), + "mergeWithExisting": + MessageLookupByLibrary.simpleMessage("Sujungti su esamais"), + "mlConsent": + MessageLookupByLibrary.simpleMessage("Įjungti mašininį mokymąsi"), + "mlConsentConfirmation": MessageLookupByLibrary.simpleMessage( + "Suprantu ir noriu įjungti mašininį mokymąsi"), + "mlConsentDescription": MessageLookupByLibrary.simpleMessage( + "Jei įjungsite mašininį mokymąsi, „Ente“ išsitrauks tokią informaciją kaip veido geometrija iš failų, įskaitant tuos, kuriais su jumis bendrinama.\n\nTai bus daroma jūsų įrenginyje, o visa sugeneruota biometrinė informacija bus visapusiškai užšifruota."), + "mlConsentPrivacy": MessageLookupByLibrary.simpleMessage( + "Spustelėkite čia dėl išsamesnės informacijos apie šią funkciją mūsų privatumo politikoje"), + "mlConsentTitle": + MessageLookupByLibrary.simpleMessage("Įjungti mašininį mokymąsi?"), + "mobileWebDesktop": MessageLookupByLibrary.simpleMessage( + "Mobiliuosiuose, internete ir darbalaukyje"), + "moderateStrength": MessageLookupByLibrary.simpleMessage("Vidutinė"), + "monthly": MessageLookupByLibrary.simpleMessage("Mėnesinis"), + "moreDetails": MessageLookupByLibrary.simpleMessage( + "Daugiau išsamios informacijos"), + "mostRecent": MessageLookupByLibrary.simpleMessage("Naujausią"), + "mostRelevant": MessageLookupByLibrary.simpleMessage("Aktualiausią"), + "moveItem": m40, + "movedToTrash": + MessageLookupByLibrary.simpleMessage("Perkelta į šiukšlinę"), + "name": MessageLookupByLibrary.simpleMessage("Pavadinimą"), + "nameTheAlbum": + MessageLookupByLibrary.simpleMessage("Pavadinti albumą"), + "networkConnectionRefusedErr": MessageLookupByLibrary.simpleMessage( + "Nepavyksta prisijungti prie „Ente“. Bandykite dar kartą po kurio laiko. Jei klaida tęsiasi, susisiekite su palaikymo komanda."), + "networkHostLookUpErr": MessageLookupByLibrary.simpleMessage( + "Nepavyksta prisijungti prie „Ente“. Patikrinkite tinklo nustatymus ir susisiekite su palaikymo komanda, jei klaida tęsiasi."), + "never": MessageLookupByLibrary.simpleMessage("Niekada"), + "newAlbum": MessageLookupByLibrary.simpleMessage("Naujas albumas"), "newPerson": MessageLookupByLibrary.simpleMessage("Naujas asmuo"), + "newToEnte": + MessageLookupByLibrary.simpleMessage("Naujas platformoje „Ente“"), + "newest": MessageLookupByLibrary.simpleMessage("Naujausią"), + "next": MessageLookupByLibrary.simpleMessage("Toliau"), + "no": MessageLookupByLibrary.simpleMessage("Ne"), + "noDeviceFound": + MessageLookupByLibrary.simpleMessage("Įrenginys nerastas"), + "noDeviceLimit": MessageLookupByLibrary.simpleMessage("Jokio"), "noExifData": MessageLookupByLibrary.simpleMessage("Nėra EXIF duomenų"), + "noImagesWithLocation": + MessageLookupByLibrary.simpleMessage("Nėra vaizdų su vietove"), + "noInternetConnection": + MessageLookupByLibrary.simpleMessage("Nėra interneto ryšio"), + "noQuickLinksSelected": MessageLookupByLibrary.simpleMessage( + "Nėra pasirinktų sparčiųjų nuorodų"), + "noRecoveryKey": + MessageLookupByLibrary.simpleMessage("Neturite atkūrimo rakto?"), "noRecoveryKeyNoDecryption": MessageLookupByLibrary.simpleMessage( "Dėl mūsų visapusio šifravimo protokolo pobūdžio jūsų duomenų negalima iššifruoti be slaptažodžio arba atkūrimo rakto"), "noResults": MessageLookupByLibrary.simpleMessage("Rezultatų nėra"), + "noSystemLockFound": + MessageLookupByLibrary.simpleMessage("Nerastas sistemos užraktas"), + "notPersonLabel": m42, "ok": MessageLookupByLibrary.simpleMessage("Gerai"), + "onDevice": MessageLookupByLibrary.simpleMessage("Įrenginyje"), + "onEnte": MessageLookupByLibrary.simpleMessage( + "Saugykloje ente"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Ups"), + "optionalAsShortAsYouLike": MessageLookupByLibrary.simpleMessage( + "Nebūtina, trumpai, kaip jums patinka..."), + "orPickAnExistingOne": + MessageLookupByLibrary.simpleMessage("Arba pasirinkite esamą"), + "pair": MessageLookupByLibrary.simpleMessage("Susieti"), + "pairWithPin": MessageLookupByLibrary.simpleMessage("Susieti su PIN"), + "pairingComplete": + MessageLookupByLibrary.simpleMessage("Susiejimas baigtas"), + "panorama": MessageLookupByLibrary.simpleMessage("Panorama"), + "passKeyPendingVerification": MessageLookupByLibrary.simpleMessage( + "Vis dar laukiama patvirtinimo"), "passkey": MessageLookupByLibrary.simpleMessage("Slaptaraktas"), + "passkeyAuthTitle": + MessageLookupByLibrary.simpleMessage("Slaptarakto patvirtinimas"), "password": MessageLookupByLibrary.simpleMessage("Slaptažodis"), + "passwordChangedSuccessfully": MessageLookupByLibrary.simpleMessage( + "Slaptažodis sėkmingai pakeistas"), + "passwordLock": + MessageLookupByLibrary.simpleMessage("Slaptažodžio užraktas"), + "passwordStrength": m0, + "passwordStrengthInfo": MessageLookupByLibrary.simpleMessage( + "Slaptažodžio stiprumas apskaičiuojamas atsižvelgiant į slaptažodžio ilgį, naudotus simbolius ir į tai, ar slaptažodis patenka į 10 000 dažniausiai naudojamų slaptažodžių."), + "passwordWarning": MessageLookupByLibrary.simpleMessage( + "Šio slaptažodžio nesaugome, todėl jei jį pamiršite, negalėsime iššifruoti jūsų duomenų"), + "paymentDetails": + MessageLookupByLibrary.simpleMessage("Mokėjimo duomenys"), + "paymentFailed": + MessageLookupByLibrary.simpleMessage("Mokėjimas nepavyko"), + "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( + "Deja, jūsų mokėjimas nepavyko. Susisiekite su palaikymo komanda ir mes jums padėsime!"), + "paymentFailedTalkToProvider": m44, + "pendingItems": + MessageLookupByLibrary.simpleMessage("Laukiami elementai"), + "pendingSync": + MessageLookupByLibrary.simpleMessage("Laukiama sinchronizacija"), + "people": MessageLookupByLibrary.simpleMessage("Asmenys"), + "permanentlyDeleteFromDevice": MessageLookupByLibrary.simpleMessage( + "Ištrinti negrįžtamai iš įrenginio?"), "personName": MessageLookupByLibrary.simpleMessage("Asmens vardas"), "photoSmallCase": MessageLookupByLibrary.simpleMessage("nuotrauka"), + "photosAddedByYouWillBeRemovedFromTheAlbum": + MessageLookupByLibrary.simpleMessage( + "Jūsų pridėtos nuotraukos bus pašalintos iš albumo"), + "pinAlbum": MessageLookupByLibrary.simpleMessage("Prisegti albumą"), + "pinLock": MessageLookupByLibrary.simpleMessage("PIN užrakinimas"), + "playOnTv": MessageLookupByLibrary.simpleMessage( + "Paleisti albumą televizoriuje"), + "playstoreSubscription": + MessageLookupByLibrary.simpleMessage("„PlayStore“ prenumerata"), + "pleaseCheckYourInternetConnectionAndTryAgain": + MessageLookupByLibrary.simpleMessage( + "Patikrinkite savo interneto ryšį ir bandykite dar kartą."), + "pleaseLoginAgain": + MessageLookupByLibrary.simpleMessage("Prisijunkite iš naujo."), + "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( + "Pasirinkite sparčiąsias nuorodas, kad pašalintumėte"), + "pleaseTryAgain": + MessageLookupByLibrary.simpleMessage("Bandykite dar kartą."), + "pleaseVerifyTheCodeYouHaveEntered": + MessageLookupByLibrary.simpleMessage("Patvirtinkite įvestą kodą."), + "pleaseWait": MessageLookupByLibrary.simpleMessage("Palaukite..."), + "pressAndHoldToPlayVideo": MessageLookupByLibrary.simpleMessage( + "Paspauskite ir palaikykite, kad paleistumėte vaizdo įrašą"), + "privacy": MessageLookupByLibrary.simpleMessage("Privatumas"), "privacyPolicyTitle": MessageLookupByLibrary.simpleMessage("Privatumo politika"), - "processingImport": m47, + "processingImport": m48, + "raiseTicket": MessageLookupByLibrary.simpleMessage("Sukurti paraišką"), + "rateTheApp": MessageLookupByLibrary.simpleMessage("Vertinti programą"), + "rateUsOnStore": m49, + "recover": MessageLookupByLibrary.simpleMessage("Atkurti"), + "recoverAccount": + MessageLookupByLibrary.simpleMessage("Atkurti paskyrą"), "recoverButton": MessageLookupByLibrary.simpleMessage("Atkurti"), + "recoveryKey": MessageLookupByLibrary.simpleMessage("Atkūrimo raktas"), + "recoveryKeyCopiedToClipboard": MessageLookupByLibrary.simpleMessage( + "Nukopijuotas atkūrimo raktas į iškarpinę"), + "recoveryKeyOnForgotPassword": MessageLookupByLibrary.simpleMessage( + "Jei pamiršote slaptažodį, vienintelis būdas atkurti duomenis – naudoti šį raktą."), + "recoveryKeySaveDescription": MessageLookupByLibrary.simpleMessage( + "Šio rakto nesaugome, todėl išsaugokite šį 24 žodžių raktą saugioje vietoje."), + "recoveryKeySuccessBody": MessageLookupByLibrary.simpleMessage( + "Puiku! Jūsų atkūrimo raktas tinkamas. Dėkojame už patvirtinimą.\n\nNepamirškite sukurti saugią atkūrimo rakto atsarginę kopiją."), + "recoveryKeyVerified": MessageLookupByLibrary.simpleMessage( + "Patvirtintas atkūrimo raktas"), + "recoveryKeyVerifyReason": MessageLookupByLibrary.simpleMessage( + "Atkūrimo raktas – vienintelis būdas atkurti nuotraukas, jei pamiršote slaptažodį. Atkūrimo raktą galite rasti Nustatymose > Paskyra.\n\nĮveskite savo atkūrimo raktą čia, kad patvirtintumėte, ar teisingai jį išsaugojote."), "recoverySuccessful": MessageLookupByLibrary.simpleMessage("Atkūrimas sėkmingas."), + "recreatePasswordBody": MessageLookupByLibrary.simpleMessage( + "Dabartinis įrenginys nėra pakankamai galingas, kad patvirtintų jūsų slaptažodį, bet mes galime iš naujo sugeneruoti taip, kad jis veiktų su visais įrenginiais.\n\nPrisijunkite naudojant atkūrimo raktą ir sugeneruokite iš naujo slaptažodį (jei norite, galite vėl naudoti tą patį)."), + "recreatePasswordTitle": + MessageLookupByLibrary.simpleMessage("Iš naujo sukurti slaptažodį"), "reddit": MessageLookupByLibrary.simpleMessage("„Reddit“"), + "reenterPassword": MessageLookupByLibrary.simpleMessage( + "Įveskite slaptažodį iš naujo"), + "reenterPin": + MessageLookupByLibrary.simpleMessage("Įveskite PIN iš naujo"), + "remoteImages": + MessageLookupByLibrary.simpleMessage("Nuotoliniai vaizdai"), + "remoteThumbnails": + MessageLookupByLibrary.simpleMessage("Nuotolinės miniatiūros"), + "remoteVideos": + MessageLookupByLibrary.simpleMessage("Nuotoliniai vaizdo įrašai"), + "remove": MessageLookupByLibrary.simpleMessage("Šalinti"), + "removeDuplicates": + MessageLookupByLibrary.simpleMessage("Šalinti dublikatus"), + "removeFromAlbum": + MessageLookupByLibrary.simpleMessage("Šalinti iš albumo"), + "removeFromAlbumTitle": + MessageLookupByLibrary.simpleMessage("Pašalinti iš albumo?"), + "removeFromFavorite": + MessageLookupByLibrary.simpleMessage("Šalinti iš mėgstamų"), + "removeLink": MessageLookupByLibrary.simpleMessage("Šalinti nuorodą"), + "removeParticipant": + MessageLookupByLibrary.simpleMessage("Šalinti dalyvį"), + "removeParticipantBody": m51, + "removePersonLabel": + MessageLookupByLibrary.simpleMessage("Šalinti asmens žymą"), + "removePublicLink": + MessageLookupByLibrary.simpleMessage("Šalinti viešą nuorodą"), + "removePublicLinks": + MessageLookupByLibrary.simpleMessage("Šalinti viešąsias nuorodas"), + "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( + "Kai kuriuos elementus, kuriuos šalinate, pridėjo kiti asmenys, todėl prarasite prieigą prie jų"), + "removeWithQuestionMark": + MessageLookupByLibrary.simpleMessage("Šalinti?"), + "rename": MessageLookupByLibrary.simpleMessage("Pervadinti"), + "renameFile": MessageLookupByLibrary.simpleMessage("Pervadinti failą"), + "renewSubscription": + MessageLookupByLibrary.simpleMessage("Atnaujinti prenumeratą"), "reportABug": MessageLookupByLibrary.simpleMessage("Pranešti apie riktą"), "reportBug": MessageLookupByLibrary.simpleMessage("Pranešti apie riktą"), + "resendEmail": + MessageLookupByLibrary.simpleMessage("Iš naujo siųsti el. laišką"), + "resetPasswordTitle": MessageLookupByLibrary.simpleMessage( + "Nustatyti slaptažodį iš naujo"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "resetToDefault": MessageLookupByLibrary.simpleMessage( + "Atkurti numatytąsias reikšmes"), + "restoreToAlbum": + MessageLookupByLibrary.simpleMessage("Atkurti į albumą"), + "reviewDeduplicateItems": MessageLookupByLibrary.simpleMessage( + "Peržiūrėkite ir ištrinkite elementus, kurie, jūsų manymu, yra dublikatai."), + "reviewSuggestions": + MessageLookupByLibrary.simpleMessage("Peržiūrėti pasiūlymus"), + "right": MessageLookupByLibrary.simpleMessage("Dešinė"), + "rotate": MessageLookupByLibrary.simpleMessage("Sukti"), + "saveKey": MessageLookupByLibrary.simpleMessage("Išsaugoti raktą"), + "saveYourRecoveryKeyIfYouHaventAlready": + MessageLookupByLibrary.simpleMessage( + "Išsaugokite atkūrimo raktą, jei dar to nepadarėte"), + "savingEdits": + MessageLookupByLibrary.simpleMessage("Išsaugomi redagavimai..."), + "scanCode": MessageLookupByLibrary.simpleMessage("Skenuoti kodą"), + "scanThisBarcodeWithnyourAuthenticatorApp": + MessageLookupByLibrary.simpleMessage( + "Skenuokite šį QR kodą\nsu autentifikatoriaus programa"), + "search": MessageLookupByLibrary.simpleMessage("Ieškoti"), + "searchHint4": MessageLookupByLibrary.simpleMessage("Vietovė"), + "searchLocationEmptySection": MessageLookupByLibrary.simpleMessage( + "Grupės nuotraukos, kurios padarytos tam tikru spinduliu nuo nuotraukos"), + "searchResultCount": m53, + "selectALocation": + MessageLookupByLibrary.simpleMessage("Pasirinkite vietovę"), + "selectALocationFirst": MessageLookupByLibrary.simpleMessage( + "Pirmiausia pasirinkite vietovę"), + "selectLanguage": + MessageLookupByLibrary.simpleMessage("Pasirinkite kalbą"), "selectReason": - MessageLookupByLibrary.simpleMessage("Pasirinkti priežastį"), + MessageLookupByLibrary.simpleMessage("Pasirinkite priežastį"), + "selectYourPlan": + MessageLookupByLibrary.simpleMessage("Pasirinkite planą"), + "selectedFilesAreNotOnEnte": MessageLookupByLibrary.simpleMessage( + "Pasirinkti failai nėra platformoje „Ente“"), + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, + "send": MessageLookupByLibrary.simpleMessage("Siųsti"), "sendEmail": MessageLookupByLibrary.simpleMessage("Siųsti el. laišką"), + "sendLink": MessageLookupByLibrary.simpleMessage("Siųsti nuorodą"), + "serverEndpoint": + MessageLookupByLibrary.simpleMessage("Serverio galutinis taškas"), + "setAPassword": + MessageLookupByLibrary.simpleMessage("Nustatyti slaptažodį"), + "setAs": MessageLookupByLibrary.simpleMessage("Nustatyti kaip"), + "setCover": MessageLookupByLibrary.simpleMessage("Nustatyti viršelį"), + "setLabel": MessageLookupByLibrary.simpleMessage("Nustatyti"), + "setNewPassword": MessageLookupByLibrary.simpleMessage( + "Nustatykite naują slaptažodį"), + "setNewPin": + MessageLookupByLibrary.simpleMessage("Nustatykite naują PIN"), + "setPasswordTitle": + MessageLookupByLibrary.simpleMessage("Nustatyti slaptažodį"), + "setupComplete": MessageLookupByLibrary.simpleMessage("Sąranka baigta"), + "share": MessageLookupByLibrary.simpleMessage("Bendrinti"), + "shareAlbumHint": MessageLookupByLibrary.simpleMessage( + "Atidarykite albumą ir palieskite bendrinimo mygtuką viršuje dešinėje, kad bendrintumėte."), "showPerson": MessageLookupByLibrary.simpleMessage("Rodyti asmenį"), + "signOutOtherBody": MessageLookupByLibrary.simpleMessage( + "Jei manote, kad kas nors gali žinoti jūsų slaptažodį, galite priverstinai atsijungti iš visų kitų įrenginių, naudojančių jūsų paskyrą."), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Sutinku su paslaugų sąlygomis ir privatumo politika"), + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, + "skip": MessageLookupByLibrary.simpleMessage("Praleisti"), "social": MessageLookupByLibrary.simpleMessage("Socialinės"), "somethingWentWrongPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Kažkas nutiko ne taip. Bandykite dar kartą."), "sorry": MessageLookupByLibrary.simpleMessage("Atsiprašome"), + "sorryCouldNotRemoveFromFavorites": + MessageLookupByLibrary.simpleMessage( + "Atsiprašome, nepavyko pašalinti iš mėgstamų."), + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": + MessageLookupByLibrary.simpleMessage( + "Atsiprašome, šiame įrenginyje nepavyko sugeneruoti saugių raktų.\n\nRegistruokitės iš kito įrenginio."), "sort": MessageLookupByLibrary.simpleMessage("Rikiuoti"), + "sortAlbumsBy": MessageLookupByLibrary.simpleMessage("Rikiuoti pagal"), + "sortNewestFirst": + MessageLookupByLibrary.simpleMessage("Naujausią pirmiausiai"), + "sortOldestFirst": + MessageLookupByLibrary.simpleMessage("Seniausią pirmiausiai"), + "startBackup": MessageLookupByLibrary.simpleMessage( + "Pradėti kurti atsarginę kopiją"), + "status": MessageLookupByLibrary.simpleMessage("Būsena"), + "stopCastingBody": MessageLookupByLibrary.simpleMessage( + "Ar norite sustabdyti perdavimą?"), + "stopCastingTitle": + MessageLookupByLibrary.simpleMessage("Stabdyti perdavimą"), "storage": MessageLookupByLibrary.simpleMessage("Saugykla"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Jūs"), - "storageInGB": m61, + "storageInGB": m1, + "storageLimitExceeded": + MessageLookupByLibrary.simpleMessage("Viršyta saugyklos riba."), + "strongStrength": MessageLookupByLibrary.simpleMessage("Stipri"), + "subAlreadyLinkedErrMessage": m63, "subscribe": MessageLookupByLibrary.simpleMessage("Prenumeruoti"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( "Kad įjungtumėte bendrinimą, reikia aktyvios mokamos prenumeratos."), + "subscription": MessageLookupByLibrary.simpleMessage("Prenumerata"), "suggestFeatures": MessageLookupByLibrary.simpleMessage("Siūlyti funkcijas"), "support": MessageLookupByLibrary.simpleMessage("Palaikymas"), + "syncProgress": m65, + "syncStopped": MessageLookupByLibrary.simpleMessage( + "Sinchronizavimas sustabdytas"), + "syncing": MessageLookupByLibrary.simpleMessage("Sinchronizuojama..."), "systemTheme": MessageLookupByLibrary.simpleMessage("Sistemos"), + "tapToCopy": MessageLookupByLibrary.simpleMessage( + "palieskite, kad nukopijuotumėte"), + "tapToEnterCode": MessageLookupByLibrary.simpleMessage( + "Palieskite, kad įvestumėte kodą"), + "tapToUnlock": MessageLookupByLibrary.simpleMessage( + "Palieskite, kad atrakintumėte"), + "tempErrorContactSupportIfPersists": MessageLookupByLibrary.simpleMessage( + "Atrodo, kad kažkas nutiko ne taip. Bandykite dar kartą po kurio laiko. Jei klaida tęsiasi, susisiekite su mūsų palaikymo komanda."), + "terminate": MessageLookupByLibrary.simpleMessage("Baigti"), + "terminateSession": + MessageLookupByLibrary.simpleMessage("Baigti seansą?"), + "terms": MessageLookupByLibrary.simpleMessage("Sąlygos"), "termsOfServicesTitle": MessageLookupByLibrary.simpleMessage("Sąlygos"), + "thankYou": MessageLookupByLibrary.simpleMessage("Dėkojame"), "theme": MessageLookupByLibrary.simpleMessage("Tema"), + "thisCanBeUsedToRecoverYourAccountIfYou": + MessageLookupByLibrary.simpleMessage( + "Tai gali būti naudojama paskyrai atkurti, jei prarandate dvigubo tapatybės nustatymą"), "thisDevice": MessageLookupByLibrary.simpleMessage("Šis įrenginys"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( - "Šis vaizdas neturi EXIF duomenų"), + "Šis vaizdas neturi Exif duomenų"), "thisWillLogYouOutOfTheFollowingDevice": MessageLookupByLibrary.simpleMessage( "Tai jus atjungs nuo toliau nurodyto įrenginio:"), "thisWillLogYouOutOfThisDevice": MessageLookupByLibrary.simpleMessage( "Tai jus atjungs nuo šio įrenginio."), + "thisWillRemovePublicLinksOfAllSelectedQuickLinks": + MessageLookupByLibrary.simpleMessage( + "Tai pašalins visų pasirinktų sparčiųjų nuorodų viešąsias nuorodas."), "toEnableAppLockPleaseSetupDevicePasscodeOrScreen": MessageLookupByLibrary.simpleMessage( "Kad įjungtumėte programos užraktą, sistemos nustatymuose nustatykite įrenginio prieigos kodą arba ekrano užraktą."), + "toResetVerifyEmail": MessageLookupByLibrary.simpleMessage( + "Kad iš naujo nustatytumėte slaptažodį, pirmiausia patvirtinkite savo el. paštą."), + "todaysLogs": + MessageLookupByLibrary.simpleMessage("Šiandienos žurnalai"), + "tooManyIncorrectAttempts": MessageLookupByLibrary.simpleMessage( + "Per daug neteisingų bandymų."), + "total": MessageLookupByLibrary.simpleMessage("iš viso"), + "trim": MessageLookupByLibrary.simpleMessage("Trumpinti"), + "tryAgain": MessageLookupByLibrary.simpleMessage("Bandyti dar kartą"), "twitter": MessageLookupByLibrary.simpleMessage("„Twitter“"), - "upgrade": MessageLookupByLibrary.simpleMessage("Atnaujinti"), + "twoMonthsFreeOnYearlyPlans": MessageLookupByLibrary.simpleMessage( + "2 mėnesiai nemokamai metiniuose planuose"), + "twofactorAuthenticationPageTitle": + MessageLookupByLibrary.simpleMessage( + "Dvigubas tapatybės nustatymas"), + "twofactorSetup": MessageLookupByLibrary.simpleMessage( + "Dvigubo tapatybės nustatymo sąranka"), + "unavailableReferralCode": MessageLookupByLibrary.simpleMessage( + "Atsiprašome, šis kodas nepasiekiamas."), + "uncategorized": + MessageLookupByLibrary.simpleMessage("Nekategorizuoti"), + "unlock": MessageLookupByLibrary.simpleMessage("Atrakinti"), + "unpinAlbum": MessageLookupByLibrary.simpleMessage("Atsegti albumą"), + "upgrade": MessageLookupByLibrary.simpleMessage("Keisti planą"), + "useAsCover": + MessageLookupByLibrary.simpleMessage("Naudoti kaip viršelį"), + "useRecoveryKey": + MessageLookupByLibrary.simpleMessage("Naudoti atkūrimo raktą"), "usedSpace": MessageLookupByLibrary.simpleMessage("Naudojama vieta"), + "validTill": m70, + "verificationFailedPleaseTryAgain": + MessageLookupByLibrary.simpleMessage( + "Patvirtinimas nepavyko. Bandykite dar kartą."), "verify": MessageLookupByLibrary.simpleMessage("Patvirtinti"), "verifyEmail": MessageLookupByLibrary.simpleMessage("Patvirtinti el. paštą"), "verifyIDLabel": MessageLookupByLibrary.simpleMessage("Patvirtinti"), + "verifyPasskey": + MessageLookupByLibrary.simpleMessage("Patvirtinti slaptaraktą"), + "verifyPassword": + MessageLookupByLibrary.simpleMessage("Patvirtinkite slaptažodį"), + "verifying": MessageLookupByLibrary.simpleMessage("Patvirtinama..."), + "verifyingRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Patvirtinima atkūrimo raktą..."), + "videoInfo": + MessageLookupByLibrary.simpleMessage("Vaizdo įrašo informacija"), + "videoSmallCase": MessageLookupByLibrary.simpleMessage("vaizdo įrašas"), + "viewAddOnButton": + MessageLookupByLibrary.simpleMessage("Peržiūrėti priedus"), + "viewAll": MessageLookupByLibrary.simpleMessage("Peržiūrėti viską"), + "viewLogs": MessageLookupByLibrary.simpleMessage("Peržiūrėti žurnalus"), + "viewRecoveryKey": + MessageLookupByLibrary.simpleMessage("Peržiūrėti atkūrimo raktą"), + "visitWebToManage": MessageLookupByLibrary.simpleMessage( + "Aplankykite web.ente.io, kad tvarkytumėte savo prenumeratą"), + "waitingForVerification": + MessageLookupByLibrary.simpleMessage("Laukiama patvirtinimo..."), + "weAreOpenSource": + MessageLookupByLibrary.simpleMessage("Esame atviro kodo!"), + "weHaveSendEmailTo": m2, + "weakStrength": MessageLookupByLibrary.simpleMessage("Silpna"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Sveiki sugrįžę!"), + "whatsNew": MessageLookupByLibrary.simpleMessage("Kas naujo"), + "yearly": MessageLookupByLibrary.simpleMessage("Metinis"), + "yes": MessageLookupByLibrary.simpleMessage("Taip"), + "yesCancel": MessageLookupByLibrary.simpleMessage("Taip, atsisakyti"), + "yesConvertToViewer": + MessageLookupByLibrary.simpleMessage("Taip, keisti į žiūrėtoją"), + "yesDelete": MessageLookupByLibrary.simpleMessage("Taip, ištrinti"), + "yesLogout": MessageLookupByLibrary.simpleMessage("Taip, atsijungti"), + "yesRemove": MessageLookupByLibrary.simpleMessage("Taip, šalinti"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), + "youAreOnTheLatestVersion": + MessageLookupByLibrary.simpleMessage("Esate naujausioje versijoje"), + "youCannotDowngradeToThisPlan": MessageLookupByLibrary.simpleMessage( + "Negalite pakeisti į šį planą"), "yourAccountHasBeenDeleted": - MessageLookupByLibrary.simpleMessage("Jūsų paskyra buvo ištrinta"), + MessageLookupByLibrary.simpleMessage("Jūsų paskyra ištrinta"), "yourStorageDetailsCouldNotBeFetched": MessageLookupByLibrary.simpleMessage( - "Nepavyko gauti jūsų saugyklos duomenų.") + "Nepavyko gauti jūsų saugyklos duomenų."), + "yourSubscriptionHasExpired": + MessageLookupByLibrary.simpleMessage("Jūsų prenumerata baigėsi."), + "yourVerificationCodeHasExpired": MessageLookupByLibrary.simpleMessage( + "Jūsų patvirtinimo kodo laikas nebegaliojantis."), + "youveNoDuplicateFilesThatCanBeCleared": + MessageLookupByLibrary.simpleMessage( + "Neturite dubliuotų failų, kuriuos būtų galima išvalyti") }; } diff --git a/mobile/lib/generated/intl/messages_nl.dart b/mobile/lib/generated/intl/messages_nl.dart index e811656d20..cf8a9bcc70 100644 --- a/mobile/lib/generated/intl/messages_nl.dart +++ b/mobile/lib/generated/intl/messages_nl.dart @@ -20,37 +20,37 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'nl'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Voeg samenwerker toe', one: 'Voeg samenwerker toe', other: 'Voeg samenwerkers toe')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Bestand toevoegen', other: 'Bestanden toevoegen')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Jouw ${storageAmount} add-on is geldig tot ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, one: 'Voeg kijker toe', other: 'Voeg kijkers toe')}"; - static String m9(emailOrName) => "Toegevoegd door ${emailOrName}"; + static String m10(emailOrName) => "Toegevoegd door ${emailOrName}"; - static String m10(albumName) => "Succesvol toegevoegd aan ${albumName}"; + static String m11(albumName) => "Succesvol toegevoegd aan ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Geen deelnemers', one: '1 deelnemer', other: '${count} deelnemers')}"; - static String m12(versionValue) => "Versie: ${versionValue}"; + static String m13(versionValue) => "Versie: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} vrij"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Annuleer eerst uw bestaande abonnement bij ${paymentProvider}"; - static String m15(user) => + static String m16(user) => "${user} zal geen foto\'s meer kunnen toevoegen aan dit album\n\nDe gebruiker zal nog steeds bestaande foto\'s kunnen verwijderen die door hen zijn toegevoegd"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Jouw familie heeft ${storageAmountInGb} GB geclaimd tot nu toe', @@ -58,138 +58,138 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Je hebt ${storageAmountInGb} GB geclaimd tot nu toe!', })}"; - static String m17(albumName) => + static String m18(albumName) => "Gezamenlijke link aangemaakt voor ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Neem contact op met ${familyAdminEmail} om uw abonnement te beheren"; - static String m19(provider) => + static String m20(provider) => "Neem contact met ons op via support@ente.io om uw ${provider} abonnement te beheren."; - static String m20(endpoint) => "Verbonden met ${endpoint}"; + static String m21(endpoint) => "Verbonden met ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Verwijder ${count} bestand', other: 'Verwijder ${count} bestanden')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Verwijderen van ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Dit verwijdert de openbare link voor toegang tot \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Stuur een e-mail naar ${supportEmail} vanaf het door jou geregistreerde e-mailadres"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Je hebt ${Intl.plural(count, one: '${count} dubbel bestand', other: '${count} dubbele bestanden')} opgeruimd, totaal (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} bestanden, elk ${formattedSize}"; - static String m27(newEmail) => "E-mailadres gewijzigd naar ${newEmail}"; + static String m28(newEmail) => "E-mailadres gewijzigd naar ${newEmail}"; - static String m28(email) => + static String m29(email) => "${email} heeft geen Ente account.\n\nStuur ze een uitnodiging om foto\'s te delen."; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "${Intl.plural(count, one: '1 bestand', other: '${formattedNumber} bestanden')} in dit album zijn veilig geback-upt"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "${Intl.plural(count, one: '1 bestand', other: '${formattedNumber} bestanden')} in dit album is veilig geback-upt"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "${storageAmountInGB} GB telkens als iemand zich aanmeldt voor een betaald abonnement en je code toepast"; - static String m32(endDate) => "Gratis proefversie geldig tot ${endDate}"; + static String m33(endDate) => "Gratis proefversie geldig tot ${endDate}"; - static String m33(count) => + static String m34(count) => "Je hebt nog steeds toegang tot ${Intl.plural(count, one: 'het', other: 'ze')} op Ente zolang je een actief abonnement hebt"; - static String m34(sizeInMBorGB) => "Maak ${sizeInMBorGB} vrij"; + static String m35(sizeInMBorGB) => "Maak ${sizeInMBorGB} vrij"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'Het kan verwijderd worden van het apparaat om ${formattedSize} vrij te maken', other: 'Ze kunnen verwijderd worden van het apparaat om ${formattedSize} vrij te maken')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Verwerken van ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} item', other: '${count} items')}"; - static String m38(expiryTime) => "Link vervalt op ${expiryTime}"; + static String m39(expiryTime) => "Link vervalt op ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'geen herinneringen', one: '${formattedCount} herinnering', other: '${formattedCount} herinneringen')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Bestand verplaatsen', other: 'Bestanden verplaatsen')}"; - static String m40(albumName) => "Succesvol verplaatst naar ${albumName}"; + static String m41(albumName) => "Succesvol verplaatst naar ${albumName}"; - static String m41(name) => "Niet ${name}?"; + static String m42(name) => "Niet ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Neem contact op met ${familyAdminEmail} om uw code te wijzigen."; static String m0(passwordStrengthValue) => "Wachtwoord sterkte: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Praat met ${providerName} klantenservice als u in rekening bent gebracht"; - static String m44(endDate) => + static String m45(endDate) => "Gratis proefperiode geldig tot ${endDate}.\nU kunt naderhand een betaald abonnement kiezen."; - static String m45(toEmail) => "Stuur ons een e-mail op ${toEmail}"; + static String m46(toEmail) => "Stuur ons een e-mail op ${toEmail}"; - static String m46(toEmail) => + static String m47(toEmail) => "Verstuur de logboeken alstublieft naar ${toEmail}"; - static String m47(folderName) => "Verwerken van ${folderName}..."; + static String m48(folderName) => "Verwerken van ${folderName}..."; - static String m48(storeName) => "Beoordeel ons op ${storeName}"; + static String m49(storeName) => "Beoordeel ons op ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "Jullie krijgen allebei ${storageInGB} GB* gratis"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} zal worden verwijderd uit dit gedeelde album\n\nAlle door hen toegevoegde foto\'s worden ook uit het album verwijderd"; - static String m51(endDate) => "Wordt verlengd op ${endDate}"; + static String m52(endDate) => "Wordt verlengd op ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} resultaat gevonden', other: '${count} resultaten gevonden')}"; - static String m3(count) => "${count} geselecteerd"; + static String m4(count) => "${count} geselecteerd"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "${count} geselecteerd (${yourCount} van jou)"; - static String m54(verificationID) => + static String m55(verificationID) => "Hier is mijn verificatie-ID: ${verificationID} voor ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Hey, kunt u bevestigen dat dit uw ente.io verificatie-ID is: ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Ente verwijzingscode: ${referralCode} \n\nPas het toe bij Instellingen → Algemeen → Verwijzingen om ${referralStorageInGB} GB gratis te krijgen nadat je je hebt aangemeld voor een betaald abonnement\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Deel met specifieke mensen', one: 'Gedeeld met 1 persoon', other: 'Gedeeld met ${numberOfPeople} mensen')}"; - static String m57(emailIDs) => "Gedeeld met ${emailIDs}"; - - static String m58(fileType) => - "Deze ${fileType} zal worden verwijderd van jouw apparaat."; + static String m58(emailIDs) => "Gedeeld met ${emailIDs}"; static String m59(fileType) => - "Deze ${fileType} staat zowel in Ente als op jouw apparaat."; + "Deze ${fileType} zal worden verwijderd van jouw apparaat."; static String m60(fileType) => + "Deze ${fileType} staat zowel in Ente als op jouw apparaat."; + + static String m61(fileType) => "Deze ${fileType} zal worden verwijderd uit Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -217,7 +217,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Verifieer ${email}"; - static String m1(email) => + static String m2(email) => "We hebben een e-mail gestuurd naar ${email}"; static String m72(count) => @@ -243,10 +243,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nieuw e-mailadres toevoegen"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Samenwerker toevoegen"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Toevoegen vanaf apparaat"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Locatie toevoegen"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Toevoegen"), @@ -254,7 +254,7 @@ class MessageLookup extends MessageLookupByLibrary { "addNew": MessageLookupByLibrary.simpleMessage("Nieuwe toevoegen"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Details van add-ons"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Add-ons"), "addPhotos": MessageLookupByLibrary.simpleMessage("Foto\'s toevoegen"), "addSelected": @@ -265,12 +265,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Toevoegen aan verborgen album"), "addViewer": MessageLookupByLibrary.simpleMessage("Voeg kijker toe"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Voeg nu je foto\'s toe"), "addedAs": MessageLookupByLibrary.simpleMessage("Toegevoegd als"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Toevoegen aan favorieten..."), "advanced": MessageLookupByLibrary.simpleMessage("Geavanceerd"), @@ -281,7 +281,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Na 1 week"), "after1Year": MessageLookupByLibrary.simpleMessage("Na 1 jaar"), "albumOwner": MessageLookupByLibrary.simpleMessage("Eigenaar"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Albumtitel"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album bijgewerkt"), @@ -289,6 +289,8 @@ class MessageLookup extends MessageLookupByLibrary { "allClear": MessageLookupByLibrary.simpleMessage("✨ Alles in orde"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("Alle herinneringen bewaard"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Sta toe dat mensen met de link ook foto\'s kunnen toevoegen aan het gedeelde album."), "allowAddingPhotos": @@ -320,7 +322,7 @@ class MessageLookup extends MessageLookupByLibrary { "appLock": MessageLookupByLibrary.simpleMessage("App-vergrendeling"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Kies tussen het standaard vergrendelscherm van uw apparaat en een aangepast vergrendelscherm met een pincode of wachtwoord."), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Toepassen"), "applyCodeTitle": @@ -345,6 +347,9 @@ class MessageLookup extends MessageLookupByLibrary { "Weet je zeker dat je wilt uitloggen?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Weet u zeker dat u wilt verlengen?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Uw abonnement is opgezegd. Wilt u de reden delen?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -398,7 +403,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "Automatisch koppelen werkt alleen met apparaten die Chromecast ondersteunen."), "available": MessageLookupByLibrary.simpleMessage("Beschikbaar"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Back-up mappen"), "backup": MessageLookupByLibrary.simpleMessage("Back-up"), @@ -426,10 +431,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Kan alleen bestanden verwijderen die jouw eigendom zijn"), "cancel": MessageLookupByLibrary.simpleMessage("Annuleer"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Abonnement opzeggen"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Kan gedeelde bestanden niet verwijderen"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -462,7 +467,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Claim gratis opslag"), "claimMore": MessageLookupByLibrary.simpleMessage("Claim meer!"), "claimed": MessageLookupByLibrary.simpleMessage("Geclaimd"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Ongecategoriseerd opschonen"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -491,7 +496,7 @@ class MessageLookup extends MessageLookupByLibrary { "Maak een link waarmee mensen foto\'s in jouw gedeelde album kunnen toevoegen en bekijken zonder dat ze daarvoor een Ente app of account nodig hebben. Handig voor het verzamelen van foto\'s van evenementen."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Gezamenlijke link"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Samenwerker"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -524,10 +529,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Bevestig herstelsleutel"), "connectToDevice": MessageLookupByLibrary.simpleMessage( "Verbinding maken met apparaat"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Contacteer klantenservice"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Contacten"), "contents": MessageLookupByLibrary.simpleMessage("Inhoud"), "continueLabel": MessageLookupByLibrary.simpleMessage("Doorgaan"), @@ -572,7 +577,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("Huidig gebruik is "), "custom": MessageLookupByLibrary.simpleMessage("Aangepast"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Donker"), "dayToday": MessageLookupByLibrary.simpleMessage("Vandaag"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Gisteren"), @@ -608,12 +613,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Verwijder van apparaat"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Verwijder van Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Verwijder locatie"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Foto\'s verwijderen"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Ik mis een belangrijke functie"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -655,7 +660,7 @@ class MessageLookup extends MessageLookupByLibrary { "Kijkers kunnen nog steeds screenshots maken of een kopie van je foto\'s opslaan met behulp van externe tools"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Let op"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Tweestapsverificatie uitschakelen"), "disablingTwofactorAuthentication": @@ -697,9 +702,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Download mislukt"), "downloading": MessageLookupByLibrary.simpleMessage("Downloaden..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Bewerken"), "editLocation": MessageLookupByLibrary.simpleMessage("Locatie bewerken"), @@ -712,8 +717,8 @@ class MessageLookup extends MessageLookupByLibrary { "Bewerkte locatie wordt alleen gezien binnen Ente"), "eligible": MessageLookupByLibrary.simpleMessage("gerechtigd"), "email": MessageLookupByLibrary.simpleMessage("E-mail"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("E-mailverificatie"), "emailYourLogs": @@ -828,8 +833,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Bestandstype"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Bestandstypen en namen"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Bestanden verwijderd"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage( @@ -845,25 +850,25 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Gezichten gevonden"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Gratis opslag geclaimd"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Gratis opslag bruikbaar"), "freeTrial": MessageLookupByLibrary.simpleMessage("Gratis proefversie"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Apparaatruimte vrijmaken"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Bespaar ruimte op je apparaat door bestanden die al geback-upt zijn te wissen."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Ruimte vrijmaken"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Tot 1000 herinneringen getoond in de galerij"), "general": MessageLookupByLibrary.simpleMessage("Algemeen"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Encryptiesleutels genereren..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Ga naar instellingen"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), @@ -940,7 +945,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Het lijkt erop dat er iets fout is gegaan. Probeer het later opnieuw. Als de fout zich blijft voordoen, neem dan contact op met ons supportteam."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Bestanden tonen het aantal resterende dagen voordat ze permanent worden verwijderd"), @@ -968,7 +973,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Apparaat limiet"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Ingeschakeld"), "linkExpired": MessageLookupByLibrary.simpleMessage("Verlopen"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Vervaldatum"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("Link is vervallen"), @@ -1055,7 +1060,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Kaarten"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Merchandise"), "mlConsent": MessageLookupByLibrary.simpleMessage("Schakel machine learning in"), @@ -1080,12 +1085,12 @@ class MessageLookup extends MessageLookupByLibrary { "moreDetails": MessageLookupByLibrary.simpleMessage("Meer details"), "mostRecent": MessageLookupByLibrary.simpleMessage("Meest recent"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Meest relevant"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Verplaats naar album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Verplaatsen naar verborgen album"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Naar prullenbak verplaatst"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -1135,7 +1140,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Geen resultaten gevonden"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage( "Geen systeemvergrendeling gevonden"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage("Nog niets met je gedeeld"), "nothingToSeeHere": @@ -1145,7 +1150,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("Op het apparaat"), "onEnte": MessageLookupByLibrary.simpleMessage( "Op ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Oeps"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Oeps, kon bewerkingen niet opslaan"), @@ -1185,7 +1191,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Betaling mislukt"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Helaas is je betaling mislukt. Neem contact op met support zodat we je kunnen helpen!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Bestanden in behandeling"), "pendingSync": MessageLookupByLibrary.simpleMessage( @@ -1215,7 +1221,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinLock": MessageLookupByLibrary.simpleMessage("PIN vergrendeling"), "playOnTv": MessageLookupByLibrary.simpleMessage("Album afspelen op TV"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore abonnement"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1227,14 +1233,14 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Neem contact op met klantenservice als het probleem aanhoudt"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Geef alstublieft toestemming"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Log opnieuw in"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Selecteer snelle links om te verwijderen"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Probeer het nog eens"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1260,7 +1266,7 @@ class MessageLookup extends MessageLookupByLibrary { "privateBackups": MessageLookupByLibrary.simpleMessage("Privé back-ups"), "privateSharing": MessageLookupByLibrary.simpleMessage("Privé delen"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Publieke link aangemaakt"), "publicLinkEnabled": @@ -1270,7 +1276,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Meld probleem"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Beoordeel de app"), "rateUs": MessageLookupByLibrary.simpleMessage("Beoordeel ons"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Herstellen"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Account herstellen"), @@ -1305,7 +1311,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Geef deze code aan je vrienden"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Ze registreren voor een betaald plan"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Referenties"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Verwijzingen zijn momenteel gepauzeerd"), @@ -1333,7 +1339,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Verwijder link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Deelnemer verwijderen"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("Verwijder persoonslabel"), "removePublicLink": @@ -1353,7 +1359,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Bestandsnaam wijzigen"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Abonnement verlengen"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Een fout melden"), "reportBug": MessageLookupByLibrary.simpleMessage("Fout melden"), "resendEmail": @@ -1362,6 +1368,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Reset genegeerde bestanden"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Wachtwoord resetten"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage( "Standaardinstellingen herstellen"), "restore": MessageLookupByLibrary.simpleMessage("Herstellen"), @@ -1424,7 +1431,7 @@ class MessageLookup extends MessageLookupByLibrary { "Foto\'s groeperen die in een bepaalde straal van een foto worden genomen"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Nodig mensen uit, en je ziet alle foto\'s die door hen worden gedeeld hier"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Beveiliging"), "selectALocation": MessageLookupByLibrary.simpleMessage("Selecteer een locatie"), @@ -1451,8 +1458,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Geselecteerde bestanden worden verwijderd uit alle albums en verplaatst naar de prullenbak."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Verzenden"), "sendEmail": MessageLookupByLibrary.simpleMessage("E-mail versturen"), "sendInvite": @@ -1482,16 +1489,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Deel nu een album"), "shareLink": MessageLookupByLibrary.simpleMessage("Link delen"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Deel alleen met de mensen die u wilt"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Download Ente zodat we gemakkelijk foto\'s en video\'s in originele kwaliteit kunnen delen\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Delen met niet-Ente gebruikers"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Deel jouw eerste album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1502,7 +1509,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nieuwe gedeelde foto\'s"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Ontvang meldingen wanneer iemand een foto toevoegt aan een gedeeld album waar je deel van uitmaakt"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Gedeeld met mij"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Gedeeld met jou"), @@ -1518,11 +1525,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Log uit op andere apparaten"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Ik ga akkoord met de gebruiksvoorwaarden en privacybeleid"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Het wordt uit alle albums verwijderd."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Overslaan"), "social": MessageLookupByLibrary.simpleMessage("Sociale media"), "someItemsAreInBothEnteAndYourDevice": MessageLookupByLibrary.simpleMessage( @@ -1565,7 +1572,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Opslagruimte"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Familie"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Jij"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Opslaglimiet overschreden"), "storageUsageInfo": m62, @@ -1768,7 +1775,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "We ondersteunen het bewerken van foto\'s en albums waar je niet de eigenaar van bent nog niet"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Zwak"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Welkom terug!"), "whatsNew": MessageLookupByLibrary.simpleMessage("Nieuw"), @@ -1784,6 +1791,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("Ja, log uit"), "yesRemove": MessageLookupByLibrary.simpleMessage("Ja, verwijderen"), "yesRenew": MessageLookupByLibrary.simpleMessage("Ja, verlengen"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Jij"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage( "U bent onderdeel van een familie abonnement!"), diff --git a/mobile/lib/generated/intl/messages_no.dart b/mobile/lib/generated/intl/messages_no.dart index b9f49e3183..e220877935 100644 --- a/mobile/lib/generated/intl/messages_no.dart +++ b/mobile/lib/generated/intl/messages_no.dart @@ -20,53 +20,53 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'no'; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Ingen deltakere', one: '1 deltaker', other: '${count} deltakere')}"; - static String m15(user) => + static String m16(user) => "${user} vil ikke kunne legge til flere bilder til dette albumet\n\nDe vil fortsatt kunne fjerne eksisterende bilder lagt til av dem"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Slett ${count} element', other: 'Slett ${count} elementer')}"; - static String m23(albumName) => + static String m24(albumName) => "Dette fjerner den offentlige lenken for tilgang til \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Vennligst send en e-post til ${supportEmail} fra din registrerte e-postadresse"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} filer, ${formattedSize} hver"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} element', other: '${count} elementer')}"; - static String m38(expiryTime) => "Lenken utløper på ${expiryTime}"; + static String m39(expiryTime) => "Lenken utløper på ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'ingen minner', one: '${formattedCount} minne', other: '${formattedCount} minner')}"; static String m0(passwordStrengthValue) => "Passordstyrke: ${passwordStrengthValue}"; - static String m3(count) => "${count} valgt"; + static String m4(count) => "${count} valgt"; - static String m53(count, yourCount) => "${count} valgt (${yourCount} dine)"; + static String m54(count, yourCount) => "${count} valgt (${yourCount} dine)"; - static String m54(verificationID) => + static String m55(verificationID) => "Her er min verifiserings-ID: ${verificationID} for ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Hei, kan du bekrefte at dette er din ente.io verifiserings-ID: ${verificationID}"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Del med bestemte personer', one: 'Delt med 1 person', other: 'Delt med ${numberOfPeople} personer')}"; static String m67(email) => "Dette er ${email} sin verifiserings-ID"; static String m71(email) => "Verifiser ${email}"; - static String m1(email) => + static String m2(email) => "Vi har sendt en e-post til ${email}"; final messages = _notInlinedMessages(_notInlinedMessages); @@ -91,9 +91,11 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Etter 1 uke"), "after1Year": MessageLookupByLibrary.simpleMessage("Etter 1 år"), "albumOwner": MessageLookupByLibrary.simpleMessage("Eier"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumUpdated": MessageLookupByLibrary.simpleMessage("Album oppdatert"), "albums": MessageLookupByLibrary.simpleMessage("Album"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Tillat folk med lenken å også legge til bilder til det delte albumet."), "allowAddingPhotos": @@ -101,6 +103,9 @@ class MessageLookup extends MessageLookupByLibrary { "allowDownloads": MessageLookupByLibrary.simpleMessage("Tillat nedlastinger"), "apply": MessageLookupByLibrary.simpleMessage("Anvend"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Hva er hovedårsaken til at du sletter kontoen din?"), "authToViewYourHiddenFiles": MessageLookupByLibrary.simpleMessage( @@ -108,7 +113,7 @@ class MessageLookup extends MessageLookupByLibrary { "authToViewYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Vennligst autentiser deg for å se gjennopprettingsnøkkelen din"), "cancel": MessageLookupByLibrary.simpleMessage("Avbryt"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "changeEmail": MessageLookupByLibrary.simpleMessage("Endre e-postadresse"), "changePasswordTitle": @@ -164,7 +169,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Slett fra begge"), "deleteFromDevice": MessageLookupByLibrary.simpleMessage("Slett fra enhet"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deletePhotos": MessageLookupByLibrary.simpleMessage("Slett bilder"), "deleteReason1": MessageLookupByLibrary.simpleMessage( "Det mangler en hovedfunksjon jeg trenger"), @@ -180,12 +185,12 @@ class MessageLookup extends MessageLookupByLibrary { "Seere kan fremdeles ta skjermbilder eller lagre en kopi av bildene dine ved bruk av eksterne verktøy"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Vær oppmerksom på"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "doThisLater": MessageLookupByLibrary.simpleMessage("Gjør dette senere"), "done": MessageLookupByLibrary.simpleMessage("Ferdig"), - "dropSupportEmail": m24, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateItemsGroup": m27, "email": MessageLookupByLibrary.simpleMessage("E-post"), "encryption": MessageLookupByLibrary.simpleMessage("Kryptering"), "encryptionKeys": @@ -245,14 +250,14 @@ class MessageLookup extends MessageLookupByLibrary { "invalidKey": MessageLookupByLibrary.simpleMessage("Ugyldig nøkkel"), "invalidRecoveryKey": MessageLookupByLibrary.simpleMessage( "Gjenopprettingsnøkkelen du har skrevet inn er ikke gyldig. Kontroller at den inneholder 24 ord og kontroller stavemåten av hvert ord.\n\nHvis du har angitt en eldre gjenopprettingskode, må du kontrollere at den er 64 tegn lang, og kontrollere hvert av dem."), - "itemCount": m37, + "itemCount": m38, "keepPhotos": MessageLookupByLibrary.simpleMessage("Behold Bilder"), "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage( "Vær vennlig og hjelp oss med denne informasjonen"), "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("Enhetsgrense"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Aktivert"), "linkExpired": MessageLookupByLibrary.simpleMessage("Utløpt"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Lenkeutløp"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("Lenken har utløpt"), @@ -270,7 +275,7 @@ class MessageLookup extends MessageLookupByLibrary { "manageLink": MessageLookupByLibrary.simpleMessage("Administrer lenke"), "manageParticipants": MessageLookupByLibrary.simpleMessage("Administrer"), - "memoryCount": m2, + "memoryCount": m3, "moderateStrength": MessageLookupByLibrary.simpleMessage("Moderat"), "movedToTrash": MessageLookupByLibrary.simpleMessage("Flyttet til papirkurven"), @@ -283,6 +288,7 @@ class MessageLookup extends MessageLookupByLibrary { "Grunnet vår type ente-til-ende-krypteringsprotokoll kan ikke dine data dekrypteres uten passordet ditt eller gjenopprettingsnøkkelen din"), "notifications": MessageLookupByLibrary.simpleMessage("Varslinger"), "ok": MessageLookupByLibrary.simpleMessage("Ok"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Oisann"), "orPickAnExistingOne": MessageLookupByLibrary.simpleMessage("Eller velg en eksisterende"), @@ -340,6 +346,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Send e-posten på nytt"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Tilbakestill passord"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "saveKey": MessageLookupByLibrary.simpleMessage("Lagre nøkkel"), "saveYourRecoveryKeyIfYouHaventAlready": MessageLookupByLibrary.simpleMessage( @@ -356,8 +363,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedFoldersWillBeEncryptedAndBackedUp": MessageLookupByLibrary.simpleMessage( "Valgte mapper vil bli kryptert og sikkerhetskopiert"), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "sendEmail": MessageLookupByLibrary.simpleMessage("Send e-post"), "sendInvite": MessageLookupByLibrary.simpleMessage("Send invitasjon"), "sendLink": MessageLookupByLibrary.simpleMessage("Send lenke"), @@ -367,9 +374,9 @@ class MessageLookup extends MessageLookupByLibrary { "setupComplete": MessageLookupByLibrary.simpleMessage("Oppsett fullført"), "shareALink": MessageLookupByLibrary.simpleMessage("Del en lenke"), - "shareMyVerificationID": m54, - "shareTextConfirmOthersVerificationID": m4, - "shareWithPeopleSectionTitle": m56, + "shareMyVerificationID": m55, + "shareTextConfirmOthersVerificationID": m5, + "shareWithPeopleSectionTitle": m57, "sharedPhotoNotifications": MessageLookupByLibrary.simpleMessage("Nye delte bilder"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( @@ -443,13 +450,15 @@ class MessageLookup extends MessageLookupByLibrary { "viewRecoveryKey": MessageLookupByLibrary.simpleMessage("Vis gjenopprettingsnøkkel"), "viewer": MessageLookupByLibrary.simpleMessage("Seer"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Svakt"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Velkommen tilbake!"), "yesConvertToViewer": MessageLookupByLibrary.simpleMessage("Ja, konverter til seer"), "yesDelete": MessageLookupByLibrary.simpleMessage("Ja, slett"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Deg"), "youCannotShareWithYourself": MessageLookupByLibrary.simpleMessage( "Du kan ikke dele med deg selv"), diff --git a/mobile/lib/generated/intl/messages_pl.dart b/mobile/lib/generated/intl/messages_pl.dart index ee08478c41..94308a24c6 100644 --- a/mobile/lib/generated/intl/messages_pl.dart +++ b/mobile/lib/generated/intl/messages_pl.dart @@ -20,37 +20,37 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'pl'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, one: 'Dodaj współuczestnika', few: 'Dodaj współuczestników', many: 'Dodaj współuczestników', other: 'Dodaj współuczestników')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Dodaj element', few: 'Dodaj elementy', other: 'Dodaj elementów')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Twój dodatek ${storageAmount} jest ważny do ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, one: 'Dodaj widza', few: 'Dodaj widzów', many: 'Dodaj widzów', other: 'Dodaj widzów')}"; - static String m9(emailOrName) => "Dodane przez ${emailOrName}"; + static String m10(emailOrName) => "Dodane przez ${emailOrName}"; - static String m10(albumName) => "Pomyślnie dodano do ${albumName}"; + static String m11(albumName) => "Pomyślnie dodano do ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Brak Uczestników', one: '1 Uczestnik', other: '${count} Uczestników')}"; - static String m12(versionValue) => "Wersja: ${versionValue}"; + static String m13(versionValue) => "Wersja: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} za darmo"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Prosimy najpierw anulować istniejącą subskrypcję z ${paymentProvider}"; - static String m15(user) => + static String m16(user) => "${user} nie będzie mógł dodać więcej zdjęć do tego albumu\n\nJednak nadal będą mogli usunąć istniejące zdjęcia, które dodali"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Twoja rodzina odebrała ${storageAmountInGb} GB do tej pory', @@ -58,136 +58,136 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Odebrałeś ${storageAmountInGb} GB do tej pory!', })}"; - static String m17(albumName) => "Utworzono link współpracy dla ${albumName}"; + static String m18(albumName) => "Utworzono link współpracy dla ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Prosimy skontaktować się z ${familyAdminEmail}, by zarzadząć swoją subskrypcją"; - static String m19(provider) => + static String m20(provider) => "Skontaktuj się z nami pod adresem support@ente.io, aby zarządzać subskrypcją ${provider}."; - static String m20(endpoint) => "Połączono z ${endpoint}"; + static String m21(endpoint) => "Połączono z ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Usuń ${count} element', few: 'Usuń ${count} elementy', many: 'Usuń ${count} elementów', other: 'Usuń ${count} elementu')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Usuwanie ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Spowoduje to usunięcie publicznego linku dostępu do \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Wyślij wiadomość e-mail na ${supportEmail} z zarejestrowanego adresu e-mail"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Wyczyszczono ${Intl.plural(count, one: '${count} zdduplikowany plik', other: '${count} zdduplikowane pliki')}, oszczędzając (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} plików, każdy po ${formattedSize}"; - static String m27(newEmail) => "Adres e-mail został zmieniony na ${newEmail}"; + static String m28(newEmail) => "Adres e-mail został zmieniony na ${newEmail}"; - static String m28(email) => + static String m29(email) => "${email} nie posiada konta Ente.\n\nWyślij im zaproszenie do udostępniania zdjęć."; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "${Intl.plural(count, one: '1 plikowi', other: '${formattedNumber} plikom')} na tym urządzeniu została bezpiecznie utworzona kopia zapasowa"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "${Intl.plural(count, one: '1 plikowi', other: '${formattedNumber} plikom')} w tym albumie została bezpiecznie utworzona kopia zapasowa"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "${storageAmountInGB} GB za każdym razem, gdy ktoś zarejestruje się w płatnym planie i użyje twojego kodu"; - static String m32(endDate) => "Okres próbny ważny do ${endDate}"; + static String m33(endDate) => "Okres próbny ważny do ${endDate}"; - static String m33(count) => + static String m34(count) => "Nadal możesz mieć dostęp ${Intl.plural(count, one: 'do tego', other: 'do tych')} na Ente tak długo, jak masz aktywną subskrypcję"; - static String m34(sizeInMBorGB) => "Zwolnij ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "Zwolnij ${sizeInMBorGB}"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'Można to usunąć z urządzenia, aby zwolnić ${formattedSize}', other: 'Można je usunąć z urządzenia, aby zwolnić ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Przetwarzanie ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} element', few: '${count} elementy', many: '${count} elementów', other: '${count} elementu')}"; - static String m38(expiryTime) => "Link wygaśnie ${expiryTime}"; + static String m39(expiryTime) => "Link wygaśnie ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'brak wspomnień', one: '${formattedCount} wspomnienie', few: '${formattedCount} wspomnienia', other: '${formattedCount} wspomnień')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Przenieś element', few: 'Przenieś elementy', other: 'Przenieś elementów')}"; - static String m40(albumName) => "Pomyślnie przeniesiono do ${albumName}"; + static String m41(albumName) => "Pomyślnie przeniesiono do ${albumName}"; - static String m41(name) => "Nie ${name}?"; + static String m42(name) => "Nie ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Skontaktuj się z ${familyAdminEmail}, aby zmienić swój kod."; static String m0(passwordStrengthValue) => "Siła hasła: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Porozmawiaj ze wsparciem ${providerName} jeśli zostałeś obciążony"; - static String m44(endDate) => + static String m45(endDate) => "Bezpłatny okres próbny ważny do ${endDate}.\nNastępnie możesz wybrać płatny plan."; - static String m45(toEmail) => + static String m46(toEmail) => "Prosimy o kontakt mailowy pod adresem ${toEmail}"; - static String m46(toEmail) => "Prosimy wysłać logi do ${toEmail}"; + static String m47(toEmail) => "Prosimy wysłać logi do ${toEmail}"; - static String m47(folderName) => "Przetwarzanie ${folderName}..."; + static String m48(folderName) => "Przetwarzanie ${folderName}..."; - static String m48(storeName) => "Oceń nas na ${storeName}"; + static String m49(storeName) => "Oceń nas na ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Oboje otrzymujecie ${storageInGB} GB* za darmo"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} zostanie usunięty z tego udostępnionego albumu\n\nWszelkie dodane przez nich zdjęcia zostaną usunięte z albumu"; - static String m51(endDate) => "Subskrypcja odnowi się ${endDate}"; + static String m52(endDate) => "Subskrypcja odnowi się ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: 'Znaleziono ${count} wynik', few: 'Znaleziono ${count} wyniki', other: 'Znaleziono ${count} wyników')}"; - static String m3(count) => "Wybrano ${count}"; + static String m4(count) => "Wybrano ${count}"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "Wybrano ${count} (twoich ${yourCount})"; - static String m54(verificationID) => + static String m55(verificationID) => "Oto mój identyfikator weryfikacyjny: ${verificationID} dla ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Hej, czy możesz potwierdzić, że to jest Twój identyfikator weryfikacyjny ente.io: ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Kod polecający: ${referralCode} \n\nZastosuj go w: Ustawienia → Ogólne → Polecanie, aby otrzymać ${referralStorageInGB} GB za darmo po zarejestrowaniu się w płatnym planie\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Udostępnione określonym osobom', one: 'Udostępnione 1 osobie', other: 'Udostępnione ${numberOfPeople} osobom')}"; - static String m57(emailIDs) => "Udostępnione z ${emailIDs}"; - - static String m58(fileType) => - "Ten ${fileType} zostanie usunięty z Twojego urządzenia."; + static String m58(emailIDs) => "Udostępnione z ${emailIDs}"; static String m59(fileType) => + "Ten ${fileType} zostanie usunięty z Twojego urządzenia."; + + static String m60(fileType) => "Ten ${fileType} jest zarówno w Ente, jak i na twoim urządzeniu."; - static String m60(fileType) => "Ten ${fileType} zostanie usunięty z Ente."; + static String m61(fileType) => "Ten ${fileType} zostanie usunięty z Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -217,7 +217,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Zweryfikuj ${email}"; - static String m1(email) => + static String m2(email) => "Wysłaliśmy wiadomość na adres ${email}"; static String m72(count) => @@ -242,10 +242,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Dodaj nowy adres e-mail"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Dodaj współuczestnika"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Dodaj z urządzenia"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Dodaj lokalizację"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Dodaj"), @@ -258,7 +258,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Dodaj nową osobę"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Szczegóły dodatków"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Dodatki"), "addPhotos": MessageLookupByLibrary.simpleMessage("Dodaj zdjęcia"), "addSelected": MessageLookupByLibrary.simpleMessage("Dodaj zaznaczone"), @@ -267,12 +267,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Dodaj do ukrytego albumu"), "addViewer": MessageLookupByLibrary.simpleMessage("Dodaj widza"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Dodaj swoje zdjęcia teraz"), "addedAs": MessageLookupByLibrary.simpleMessage("Dodano jako"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Dodawanie do ulubionych..."), "advanced": MessageLookupByLibrary.simpleMessage("Zaawansowane"), @@ -284,7 +284,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Po 1 tygodniu"), "after1Year": MessageLookupByLibrary.simpleMessage("Po 1 roku"), "albumOwner": MessageLookupByLibrary.simpleMessage("Właściciel"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Tytuł albumu"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album został zaktualizowany"), @@ -293,6 +293,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("✨ Wszystko wyczyszczone"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage( "Wszystkie wspomnienia zachowane"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Pozwól osobom z linkiem na dodawania zdjęć do udostępnionego albumu."), "allowAddingPhotos": @@ -326,7 +328,7 @@ class MessageLookup extends MessageLookupByLibrary { "Blokada dostępu do aplikacji"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Wybierz między domyślnym ekranem blokady urządzenia a niestandardowym ekranem blokady z kodem PIN lub hasłem."), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Zastosuj"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Użyj kodu"), @@ -350,6 +352,9 @@ class MessageLookup extends MessageLookupByLibrary { "Czy na pewno chcesz się wylogować?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Czy na pewno chcesz odnowić?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Twoja subskrypcja została anulowana. Czy chcesz podzielić się powodem?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -403,7 +408,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "Automatyczne parowanie działa tylko z urządzeniami obsługującymi Chromecast."), "available": MessageLookupByLibrary.simpleMessage("Dostępne"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Foldery kopii zapasowej"), "backup": MessageLookupByLibrary.simpleMessage("Kopia zapasowa"), @@ -434,10 +439,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Można usuwać tylko pliki należące do Ciebie"), "cancel": MessageLookupByLibrary.simpleMessage("Anuluj"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Anuluj subskrypcję"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Nie można usunąć udostępnionych plików"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -469,7 +474,7 @@ class MessageLookup extends MessageLookupByLibrary { "Odbierz bezpłatną przestrzeń dyskową"), "claimMore": MessageLookupByLibrary.simpleMessage("Zdobądź więcej!"), "claimed": MessageLookupByLibrary.simpleMessage("Odebrano"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Wyczyść Nieskategoryzowane"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -499,7 +504,7 @@ class MessageLookup extends MessageLookupByLibrary { "Utwórz link, aby umożliwić innym dodawanie i przeglądanie zdjęć w udostępnionym albumie bez konieczności korzystania z aplikacji lub konta Ente. Świetne rozwiązanie do gromadzenia zdjęć ze wspólnych wydarzeń."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Link do współpracy"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Współuczestnik"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -514,6 +519,7 @@ class MessageLookup extends MessageLookupByLibrary { "collectPhotosDescription": MessageLookupByLibrary.simpleMessage( "Utwórz link, w którym Twoi znajomi mogą przesyłać zdjęcia w oryginalnej jakości."), "color": MessageLookupByLibrary.simpleMessage("Kolor"), + "configuration": MessageLookupByLibrary.simpleMessage("Konfiguracja"), "confirm": MessageLookupByLibrary.simpleMessage("Potwierdź"), "confirm2FADisable": MessageLookupByLibrary.simpleMessage( "Czy na pewno chcesz wyłączyć uwierzytelnianie dwustopniowe?"), @@ -531,10 +537,10 @@ class MessageLookup extends MessageLookupByLibrary { "Potwierdź klucz odzyskiwania"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Połącz z urządzeniem"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage( "Skontaktuj się z pomocą techniczną"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Kontakty"), "contents": MessageLookupByLibrary.simpleMessage("Zawartość"), "continueLabel": MessageLookupByLibrary.simpleMessage("Kontynuuj"), @@ -578,7 +584,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("Aktualne użycie to "), "custom": MessageLookupByLibrary.simpleMessage("Niestandardowy"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Ciemny"), "dayToday": MessageLookupByLibrary.simpleMessage("Dzisiaj"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Wczoraj"), @@ -611,11 +617,11 @@ class MessageLookup extends MessageLookupByLibrary { "deleteFromDevice": MessageLookupByLibrary.simpleMessage("Usuń z urządzenia"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Usuń z Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Usuń lokalizację"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Usuń zdjęcia"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Brakuje kluczowej funkcji, której potrzebuję"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -656,7 +662,7 @@ class MessageLookup extends MessageLookupByLibrary { "Widzowie mogą nadal robić zrzuty ekranu lub zapisywać kopie zdjęć za pomocą programów trzecich"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Uwaga"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Wyłącz uwierzytelnianie dwustopniowe"), "disablingTwofactorAuthentication": @@ -699,9 +705,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Pobieranie nie powiodło się"), "downloading": MessageLookupByLibrary.simpleMessage("Pobieranie..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Edytuj"), "editLocation": MessageLookupByLibrary.simpleMessage("Edytuj lokalizację"), @@ -713,8 +719,8 @@ class MessageLookup extends MessageLookupByLibrary { "Edycje lokalizacji będą widoczne tylko w Ente"), "eligible": MessageLookupByLibrary.simpleMessage("kwalifikujący się"), "email": MessageLookupByLibrary.simpleMessage("Adres e-mail"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Weryfikacja e-mail"), "emailYourLogs": @@ -829,8 +835,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Rodzaje plików"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Typy plików i nazwy"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Pliki usunięto"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage("Pliki zapisane do galerii"), @@ -844,26 +850,26 @@ class MessageLookup extends MessageLookupByLibrary { "foundFaces": MessageLookupByLibrary.simpleMessage("Znaleziono twarze"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage( "Bezpłatna pamięć, którą odebrano"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Darmowa pamięć użyteczna"), "freeTrial": MessageLookupByLibrary.simpleMessage("Darmowy okres próbny"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Zwolnij miejsce na urządzeniu"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Oszczędzaj miejsce na urządzeniu poprzez wyczyszczenie plików, które zostały już przesłane."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Zwolnij miejsce"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "W galerii wyświetlane jest do 1000 pamięci"), "general": MessageLookupByLibrary.simpleMessage("Ogólne"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Generowanie kluczy szyfrujących..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Przejdź do ustawień"), "googlePlayId": @@ -942,7 +948,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Wygląda na to, że coś poszło nie tak. Spróbuj ponownie po pewnym czasie. Jeśli błąd będzie się powtarzał, skontaktuj się z naszym zespołem pomocy technicznej."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Elementy pokazują liczbę dni pozostałych przed trwałym usunięciem"), @@ -971,7 +977,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Limit urządzeń"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Aktywny"), "linkExpired": MessageLookupByLibrary.simpleMessage("Wygasł"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Wygaśnięcie linku"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("Link wygasł"), "linkNeverExpires": MessageLookupByLibrary.simpleMessage("Nigdy"), @@ -1006,6 +1012,8 @@ class MessageLookup extends MessageLookupByLibrary { "loadingYourPhotos": MessageLookupByLibrary.simpleMessage("Wczytywanie Twoich zdjęć..."), "localGallery": MessageLookupByLibrary.simpleMessage("Galeria lokalna"), + "localIndexing": + MessageLookupByLibrary.simpleMessage("Indeksowanie lokalne"), "localSyncErrorMessage": MessageLookupByLibrary.simpleMessage( "Wygląda na to, że coś poszło nie tak, ponieważ lokalna synchronizacja zdjęć zajmuje więcej czasu, niż oczekiwano. Skontaktuj się z naszym zespołem pomocy technicznej"), "location": MessageLookupByLibrary.simpleMessage("Lokalizacja"), @@ -1060,7 +1068,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Mapy"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Sklep"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("Scal z istniejącym"), @@ -1089,12 +1097,12 @@ class MessageLookup extends MessageLookupByLibrary { "mostRecent": MessageLookupByLibrary.simpleMessage("Od najnowszych"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Najbardziej trafne"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Przenieś do albumu"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Przenieś do ukrytego albumu"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Przeniesiono do kosza"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -1144,7 +1152,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nie znaleziono wyników"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage( "Nie znaleziono blokady systemowej"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage( "Nic Ci jeszcze nie udostępniono"), "nothingToSeeHere": MessageLookupByLibrary.simpleMessage( @@ -1154,7 +1162,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("Na urządzeniu"), "onEnte": MessageLookupByLibrary.simpleMessage("W ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Ups"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Ups, nie udało się zapisać zmian"), @@ -1194,7 +1203,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Płatność się nie powiodła"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Niestety Twoja płatność nie powiodła się. Skontaktuj się z pomocą techniczną, a my Ci pomożemy!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Oczekujące elementy"), "pendingSync": @@ -1224,7 +1233,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinLock": MessageLookupByLibrary.simpleMessage("Blokada PIN"), "playOnTv": MessageLookupByLibrary.simpleMessage( "Odtwórz album na telewizorze"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Subskrypcja PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1236,14 +1245,14 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Skontaktuj się z pomocą techniczną, jeśli problem będzie się powtarzał"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Prosimy przyznać uprawnienia"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Zaloguj się ponownie"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Prosimy wybrać szybkie linki do usunięcia"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Spróbuj ponownie"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1269,7 +1278,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Prywatne kopie zapasowe"), "privateSharing": MessageLookupByLibrary.simpleMessage("Udostępnianie prywatne"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Utworzono publiczny link"), "publicLinkEnabled": @@ -1279,7 +1288,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("Zgłoś"), "rateTheApp": MessageLookupByLibrary.simpleMessage("Oceń aplikację"), "rateUs": MessageLookupByLibrary.simpleMessage("Oceń nas"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Odzyskaj"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Odzyskaj konto"), @@ -1315,7 +1324,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Przekaż ten kod swoim znajomym"), "referralStep2": MessageLookupByLibrary.simpleMessage("2. Wykupują płatny plan"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Polecenia"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Wysyłanie poleceń jest obecnie wstrzymane"), @@ -1341,7 +1350,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Usuń link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Usuń użytkownika"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("Usuń etykietę osoby"), "removePublicLink": @@ -1360,7 +1369,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Zmień nazwę pliku"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Odnów subskrypcję"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Zgłoś błąd"), "reportBug": MessageLookupByLibrary.simpleMessage("Zgłoś błąd"), "resendEmail": @@ -1369,6 +1378,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Zresetuj zignorowane pliki"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Zresetuj hasło"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("Przywróć domyślne"), "restore": MessageLookupByLibrary.simpleMessage("Przywróć"), @@ -1431,7 +1441,7 @@ class MessageLookup extends MessageLookupByLibrary { "Grupuj zdjęcia zrobione w promieniu zdjęcia"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Zaproś ludzi, a zobaczysz tutaj wszystkie udostępnione przez nich zdjęcia"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Bezpieczeństwo"), "selectALocation": MessageLookupByLibrary.simpleMessage("Wybierz lokalizację"), @@ -1457,8 +1467,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Wybrane elementy zostaną usunięte ze wszystkich albumów i przeniesione do kosza."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Wyślij"), "sendEmail": MessageLookupByLibrary.simpleMessage("Wyślij e-mail"), "sendInvite": @@ -1485,16 +1495,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Udostępnij teraz album"), "shareLink": MessageLookupByLibrary.simpleMessage("Udostępnij link"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Udostępnij tylko ludziom, którym chcesz"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Pobierz Ente, abyśmy mogli łatwo udostępniać zdjęcia i wideo w oryginalnej jakości\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Udostępnij użytkownikom bez konta Ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Udostępnij swój pierwszy album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1507,7 +1517,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nowe udostępnione zdjęcia"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Otrzymuj powiadomienia, gdy ktoś doda zdjęcie do udostępnionego albumu, którego jesteś częścią"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Udostępnione ze mną"), "sharedWithYou": @@ -1524,11 +1534,11 @@ class MessageLookup extends MessageLookupByLibrary { "Wyloguj z pozostałych urządzeń"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Akceptuję warunki korzystania z usługi i politykę prywatności"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "To zostanie usunięte ze wszystkich albumów."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Pomiń"), "social": MessageLookupByLibrary.simpleMessage("Społeczność"), "someItemsAreInBothEnteAndYourDevice": @@ -1574,7 +1584,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Pamięć"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Rodzina"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Ty"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Przekroczono limit pamięci"), "storageUsageInfo": m62, @@ -1777,7 +1787,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Nie wspieramy edycji zdjęć i albumów, których jeszcze nie posiadasz"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Słabe"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Witaj ponownie!"), "whatsNew": MessageLookupByLibrary.simpleMessage("Co nowego"), @@ -1793,6 +1803,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("Tak, wyloguj"), "yesRemove": MessageLookupByLibrary.simpleMessage("Tak, usuń"), "yesRenew": MessageLookupByLibrary.simpleMessage("Tak, Odnów"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Ty"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("Jesteś w planie rodzinnym!"), diff --git a/mobile/lib/generated/intl/messages_pt.dart b/mobile/lib/generated/intl/messages_pt.dart index 67d6d65f83..2d6e825032 100644 --- a/mobile/lib/generated/intl/messages_pt.dart +++ b/mobile/lib/generated/intl/messages_pt.dart @@ -20,173 +20,172 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'pt'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Adicionar colaborador', one: 'Adicionar colaborador', other: 'Adicionar colaboradores')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Adicionar item', other: 'Adicionar itens')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Seu complemento ${storageAmount} é válido até ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, zero: 'Adicionar visualizador', one: 'Adicionar visualizador', other: 'Adicionar Visualizadores')}"; - static String m9(emailOrName) => "Adicionado por ${emailOrName}"; + static String m10(emailOrName) => "Adicionado por ${emailOrName}"; - static String m10(albumName) => "Adicionado com sucesso a ${albumName}"; + static String m11(albumName) => "Adicionado com sucesso a ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Nenhum participante', one: '1 participante', other: '${count} participantes')}"; - static String m12(versionValue) => "Versão: ${versionValue}"; + static String m13(versionValue) => "Versão: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} livre"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Primeiramente cancele sua assinatura existente do ${paymentProvider}"; - static String m15(user) => + static String m16(user) => "${user} Não poderá adicionar mais fotos a este álbum\n\nEles ainda conseguirão remover fotos existentes adicionadas por eles"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Sua família reinvidicou ${storageAmountInGb} GB até então', 'false': 'Você reinvindicou ${storageAmountInGb} GB até então', 'other': 'Você reinvindicou ${storageAmountInGb} GB até então!', })}"; - static String m17(albumName) => "Link colaborativo criado para ${albumName}"; + static String m18(albumName) => "Link colaborativo criado para ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Entre em contato com ${familyAdminEmail} para gerenciar sua assinatura"; - static String m19(provider) => + static String m20(provider) => "Entre em contato conosco em support@ente.io para gerenciar sua assinatura ${provider}."; - static String m20(endpoint) => "Conectado a ${endpoint}"; + static String m21(endpoint) => "Conectado a ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Excluir ${count} item', other: 'Excluir ${count} itens')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Excluindo ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Isso removerá o link público para acessar \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Envie um e-mail para ${supportEmail} a partir do seu endereço de e-mail registrado"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Você limpou ${Intl.plural(count, one: '${count} arquivo duplicado', other: '${count} arquivos duplicados')}, salvando (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} arquivos, ${formattedSize} cada"; - static String m27(newEmail) => "E-mail alterado para ${newEmail}"; + static String m28(newEmail) => "E-mail alterado para ${newEmail}"; - static String m28(email) => + static String m29(email) => "${email} não tem uma conta Ente.\n\nEnvie-os um convite para compartilhar fotos."; - static String m29(count, formattedNumber) => - "${Intl.plural(count, one: '1 arquivo', other: '${formattedNumber} arquivos')} neste dispositivo teve um backup seguro"; - static String m30(count, formattedNumber) => - "${Intl.plural(count, one: '1 arquivo', other: '${formattedNumber} arquivos')} neste álbum teve um backup seguro"; + "${Intl.plural(count, one: '1 arquivo', other: '${formattedNumber} arquivos')} deste dispositivo foi copiado com segurança"; - static String m31(storageAmountInGB) => + static String m31(count, formattedNumber) => + "${Intl.plural(count, one: '1 arquivo', other: '${formattedNumber} arquivos')} deste álbum foi copiado com segurança"; + + static String m32(storageAmountInGB) => "${storageAmountInGB} GB cada vez que alguém se inscrever a um plano pago e aplicar seu código"; - static String m32(endDate) => "A avaliação grátis acaba em ${endDate}"; + static String m33(endDate) => "A avaliação grátis acaba em ${endDate}"; - static String m33(count) => - "Você ainda pode acessar ${Intl.plural(count, one: 'ele', other: 'eles')} no Ente contanto que você tenha uma assinatura ativa"; + static String m34(count) => + "Você ainda pode acessá-${Intl.plural(count, one: 'lo', other: 'los')} no Ente, contanto que você tenha uma assinatura ativa"; - static String m34(sizeInMBorGB) => "Liberar ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "Liberar ${sizeInMBorGB}"; - static String m35(count, formattedSize) => - "${Intl.plural(count, one: 'Pode ser excluído do dispositivo para liberar ${formattedSize}', other: 'Eles podem ser excluídos do dispositivo para liberar ${formattedSize}')}"; + static String m36(count, formattedSize) => + "${Intl.plural(count, one: 'Ele pode ser excluído do dispositivo para liberar ${formattedSize}', other: 'Eles podem ser excluídos do dispositivo para liberar ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Processando ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} item', other: '${count} itens')}"; - static String m38(expiryTime) => "O link expirará em ${expiryTime}"; + static String m39(expiryTime) => "O link expirará em ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'sem memórias', one: '${formattedCount} memória', other: '${formattedCount} memórias')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Mover item', other: 'Mover itens')}"; - static String m40(albumName) => "Movido com sucesso para ${albumName}"; + static String m41(albumName) => "Movido com sucesso para ${albumName}"; - static String m41(name) => "Não é ${name}?"; + static String m42(name) => "Não é ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Entre em contato com ${familyAdminEmail} para alterar o seu código."; static String m0(passwordStrengthValue) => "Força da senha: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Fale com o suporte ${providerName} se você foi cobrado"; - static String m44(endDate) => + static String m45(endDate) => "Avaliação grátis válida até ${endDate}.\nVocê pode alterar para um plano pago depois."; - static String m45(toEmail) => - "Por favor, envie-nos um e-mail para ${toEmail}"; + static String m46(toEmail) => "Envie-nos um e-mail para ${toEmail}"; - static String m46(toEmail) => "Por favor, envie os logs para \n${toEmail}"; + static String m47(toEmail) => "Envie os registros para \n${toEmail}"; - static String m47(folderName) => "Processando ${folderName}..."; + static String m48(folderName) => "Processando ${folderName}..."; - static String m48(storeName) => "Avalie-nos em ${storeName}"; + static String m49(storeName) => "Avalie-nos em ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Ambos os dois ganham ${storageInGB} GB* grátis"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} será removido deste álbum compartilhado\n\nQuaisquer fotos adicionadas por eles também serão removidas do álbum"; - static String m51(endDate) => "Renovação de assinatura em ${endDate}"; + static String m52(endDate) => "Renovação de assinatura em ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} resultado encontrado', other: '${count} resultado encontrado')}"; - static String m3(count) => "${count} selecionado(s)"; + static String m4(count) => "${count} selecionado(s)"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "${count} selecionado(s) (${yourCount} seus)"; - static String m54(verificationID) => + static String m55(verificationID) => "Aqui está meu ID de verificação para o ente.io: ${verificationID}"; - static String m4(verificationID) => + static String m5(verificationID) => "Ei, você pode confirmar se este ID de verificação do ente.io é seu?: ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Código de referência do Ente: ${referralCode} \n\nAplique-o em Configurações → Geral → Referências para obter ${referralStorageInGB} GB grátis após a sua inscrição num plano pago\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Compartilhe com pessoas específicas', one: 'Compartilhado com 1 pessoa', other: 'Compartilhado com ${numberOfPeople} pessoas')}"; - static String m57(emailIDs) => "Compartilhado com ${emailIDs}"; - - static String m58(fileType) => - "Este ${fileType} será excluído do dispositivo."; + static String m58(emailIDs) => "Compartilhado com ${emailIDs}"; static String m59(fileType) => + "Este ${fileType} será excluído do dispositivo."; + + static String m60(fileType) => "Este ${fileType} está no Ente e em seu dispositivo."; - static String m60(fileType) => "Este ${fileType} será excluído do Ente."; + static String m61(fileType) => "Este ${fileType} será excluído do Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -214,7 +213,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Verificar ${email}"; - static String m1(email) => "Nós enviamos um e-mail à ${email}"; + static String m2(email) => "Nós enviamos um e-mail à ${email}"; static String m72(count) => "${Intl.plural(count, one: '${count} ano atrás', other: '${count} anos atrás')}"; @@ -240,11 +239,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Adicionar um novo e-mail"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Adicionar colaborador"), - "addCollaborators": m5, - "addFromDevice": MessageLookupByLibrary.simpleMessage( - "Adicionar a partir do dispositivo"), - "addItem": m6, - "addLocation": MessageLookupByLibrary.simpleMessage("Adicionar local"), + "addCollaborators": m6, + "addFromDevice": + MessageLookupByLibrary.simpleMessage("Adicionar do dispositivo"), + "addItem": m7, + "addLocation": + MessageLookupByLibrary.simpleMessage("Adicionar localização"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Adicionar"), "addMore": MessageLookupByLibrary.simpleMessage("Adicionar mais"), "addName": MessageLookupByLibrary.simpleMessage("Adicionar pessoa"), @@ -255,7 +255,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Adicionar nova pessoa"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Detalhes dos complementos"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Complementos"), "addPhotos": MessageLookupByLibrary.simpleMessage("Adicionar fotos"), "addSelected": @@ -264,15 +264,15 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Adicionar ao álbum"), "addToEnte": MessageLookupByLibrary.simpleMessage("Adicionar ao Ente"), "addToHiddenAlbum": - MessageLookupByLibrary.simpleMessage("Adicionar a álbum oculto"), + MessageLookupByLibrary.simpleMessage("Adicionar ao álbum oculto"), "addViewer": MessageLookupByLibrary.simpleMessage("Adicionar visualizador"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Adicione suas fotos agora"), "addedAs": MessageLookupByLibrary.simpleMessage("Adicionado como"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage( "Adicionando aos favoritos..."), "advanced": MessageLookupByLibrary.simpleMessage("Avançado"), @@ -283,7 +283,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Após 1 semana"), "after1Year": MessageLookupByLibrary.simpleMessage("Após 1 ano"), "albumOwner": MessageLookupByLibrary.simpleMessage("Proprietário"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Título do álbum"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Álbum atualizado"), @@ -291,6 +291,8 @@ class MessageLookup extends MessageLookupByLibrary { "allClear": MessageLookupByLibrary.simpleMessage("✨ Tudo limpo"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage( "Todas as memórias preservadas"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Permitir que as pessoas com link também adicionem fotos ao álbum compartilhado."), "allowAddingPhotos": @@ -309,21 +311,19 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Sucesso"), "androidCancelButton": MessageLookupByLibrary.simpleMessage("Cancelar"), "androidDeviceCredentialsRequiredTitle": - MessageLookupByLibrary.simpleMessage( - "Credenciais do dispositivo necessárias"), + MessageLookupByLibrary.simpleMessage("Credenciais necessários"), "androidDeviceCredentialsSetupDescription": - MessageLookupByLibrary.simpleMessage( - "Credenciais do dispositivo necessárias"), + MessageLookupByLibrary.simpleMessage("Credenciais necessários"), "androidGoToSettingsDescription": MessageLookupByLibrary.simpleMessage( - "A autenticação biométrica não está configurada no seu dispositivo. Vá em \'Configurações > Segurança\' para adicionar autenticação biométrica."), - "androidIosWebDesktop": - MessageLookupByLibrary.simpleMessage("Android, iOS, Web, Desktop"), + "A autenticação biométrica não está definida no dispositivo. Vá em \'Opções > Segurança\' para adicionar a autenticação biométrica."), + "androidIosWebDesktop": MessageLookupByLibrary.simpleMessage( + "Android, iOS, Web, Computador"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("Autenticação necessária"), "appLock": MessageLookupByLibrary.simpleMessage("Bloqueio de app"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Escolha entre a tela de bloqueio padrão do seu dispositivo e uma tela de bloqueio personalizada com PIN ou senha."), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("ID da Apple"), "apply": MessageLookupByLibrary.simpleMessage("Aplicar"), "applyCodeTitle": @@ -335,7 +335,7 @@ class MessageLookup extends MessageLookupByLibrary { "archiving": MessageLookupByLibrary.simpleMessage("Arquivando..."), "areYouSureThatYouWantToLeaveTheFamily": MessageLookupByLibrary.simpleMessage( - "Tem certeza que deseja sair do plano familiar?"), + "Você tem certeza que queira sair do plano familiar?"), "areYouSureYouWantToCancel": MessageLookupByLibrary.simpleMessage("Deseja cancelar?"), "areYouSureYouWantToChangeYourPlan": @@ -346,6 +346,9 @@ class MessageLookup extends MessageLookupByLibrary { "Você tem certeza que quer encerrar sessão?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage("Deseja renovar?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Sua assinatura foi cancelada. Deseja compartilhar o motivo?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -375,16 +378,16 @@ class MessageLookup extends MessageLookupByLibrary { "authToViewYourHiddenFiles": MessageLookupByLibrary.simpleMessage( "Autentique-se para visualizar seus arquivos ocultos"), "authToViewYourMemories": MessageLookupByLibrary.simpleMessage( - "Por favor, autentique-se para ver suas memórias"), + "Autentique-se para ver suas memórias"), "authToViewYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Autentique para ver sua chave de recuperação"), "authenticating": MessageLookupByLibrary.simpleMessage("Autenticando..."), "authenticationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( - "Falha na autenticação. Por favor, tente novamente"), + "Falha na autenticação. Tente novamente"), "authenticationSuccessful": - MessageLookupByLibrary.simpleMessage("Autenticação bem-sucedida!"), + MessageLookupByLibrary.simpleMessage("Autenticado com sucesso!"), "autoCastDialogBody": MessageLookupByLibrary.simpleMessage( "Você verá dispositivos disponíveis para transmitir aqui."), "autoCastiOSPermission": MessageLookupByLibrary.simpleMessage( @@ -393,18 +396,18 @@ class MessageLookup extends MessageLookupByLibrary { "autoLockFeatureDescription": MessageLookupByLibrary.simpleMessage( "Tempo após o qual o app bloqueia depois de ser colocado em segundo plano"), "autoLogoutMessage": MessageLookupByLibrary.simpleMessage( - "Devido a erros técnicos, você foi desconectado. Pedimos desculpas pelo inconveniente."), + "Devido ao ocorrido de erros técnicos, você foi desconectado. Pedimos desculpas pela inconveniência."), "autoPair": MessageLookupByLibrary.simpleMessage("Pareamento automático"), "autoPairDesc": MessageLookupByLibrary.simpleMessage( "O pareamento automático funciona apenas com dispositivos que suportam o Chromecast."), "available": MessageLookupByLibrary.simpleMessage("Disponível"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage( "Pastas copiadas com segurança"), "backup": MessageLookupByLibrary.simpleMessage("Cópia de segurança"), - "backupFailed": - MessageLookupByLibrary.simpleMessage("Erro ao efetuar o backup"), + "backupFailed": MessageLookupByLibrary.simpleMessage( + "Falhou ao copiar com segurança"), "backupOverMobileData": MessageLookupByLibrary.simpleMessage( "Salvamento com segurança usando dados móveis"), "backupSettings": MessageLookupByLibrary.simpleMessage( @@ -418,7 +421,8 @@ class MessageLookup extends MessageLookupByLibrary { "blackFridaySale": MessageLookupByLibrary.simpleMessage("Promoção da Black Friday"), "blog": MessageLookupByLibrary.simpleMessage("Blog"), - "cachedData": MessageLookupByLibrary.simpleMessage("Dados em cache"), + "cachedData": + MessageLookupByLibrary.simpleMessage("Dados armazenados em cache"), "calculating": MessageLookupByLibrary.simpleMessage("Calculando..."), "canNotUploadToAlbumsOwnedByOthers": MessageLookupByLibrary.simpleMessage( @@ -429,10 +433,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Só pode remover arquivos de sua propriedade"), "cancel": MessageLookupByLibrary.simpleMessage("Cancelar"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Cancelar assinatura"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Não é possível excluir arquivos compartilhados"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -463,21 +467,21 @@ class MessageLookup extends MessageLookupByLibrary { "Reivindicar armazenamento grátis"), "claimMore": MessageLookupByLibrary.simpleMessage("Reivindique mais!"), "claimed": MessageLookupByLibrary.simpleMessage("Reivindicado"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Limpar Sem Categoria"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( "Remover todos os arquivos de Não Categorizados que estão presentes em outros álbuns"), "clearCaches": MessageLookupByLibrary.simpleMessage("Limpar cache"), "clearIndexes": MessageLookupByLibrary.simpleMessage("Limpar índices"), - "click": MessageLookupByLibrary.simpleMessage("Clique"), + "click": MessageLookupByLibrary.simpleMessage("• Clique"), "clickOnTheOverflowMenu": MessageLookupByLibrary.simpleMessage("• Clique no menu adicional"), "close": MessageLookupByLibrary.simpleMessage("Fechar"), "clubByCaptureTime": MessageLookupByLibrary.simpleMessage( "Agrupar por tempo de captura"), - "clubByFileName": MessageLookupByLibrary.simpleMessage( - "Agrupar pelo nome de arquivo"), + "clubByFileName": + MessageLookupByLibrary.simpleMessage("Agrupar por nome do arquivo"), "clusteringProgress": MessageLookupByLibrary.simpleMessage("Progresso de agrupamento"), "codeAppliedPageTitle": @@ -492,7 +496,7 @@ class MessageLookup extends MessageLookupByLibrary { "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."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Link colaborativo"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Colaborador"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -502,11 +506,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Colagem salva na galeria"), "collect": MessageLookupByLibrary.simpleMessage("Coletar"), "collectEventPhotos": - MessageLookupByLibrary.simpleMessage("Coletar fotos do evento"), + MessageLookupByLibrary.simpleMessage("Coletar fotos de evento"), "collectPhotos": MessageLookupByLibrary.simpleMessage("Coletar fotos"), "collectPhotosDescription": MessageLookupByLibrary.simpleMessage( "Crie um link onde seus amigos podem enviar fotos na qualidade original."), "color": MessageLookupByLibrary.simpleMessage("Cor"), + "configuration": MessageLookupByLibrary.simpleMessage("Configuração"), "confirm": MessageLookupByLibrary.simpleMessage("Confirmar"), "confirm2FADisable": MessageLookupByLibrary.simpleMessage( "Você tem certeza que queira desativar a autenticação de dois fatores?"), @@ -524,10 +529,10 @@ class MessageLookup extends MessageLookupByLibrary { "Confirme sua chave de recuperação"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Conectar ao dispositivo"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Contatar suporte"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Contatos"), "contents": MessageLookupByLibrary.simpleMessage("Conteúdos"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuar"), @@ -542,14 +547,14 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Copie e cole este código\npara o aplicativo autenticador"), "couldNotBackUpTryLater": MessageLookupByLibrary.simpleMessage( - "Não foi possível fazer o backup de seus dados.\nTentaremos novamente mais tarde."), + "Nós não podemos copiar com segurança seus dados.\nNós tentaremos novamente mais tarde."), "couldNotFreeUpSpace": MessageLookupByLibrary.simpleMessage( "Não foi possível liberar espaço"), "couldNotUpdateSubscription": MessageLookupByLibrary.simpleMessage( "Não foi possível atualizar a assinatura"), "count": MessageLookupByLibrary.simpleMessage("Contagem"), "crashReporting": - MessageLookupByLibrary.simpleMessage("Relatório de falhas"), + MessageLookupByLibrary.simpleMessage("Relatório de erros"), "create": MessageLookupByLibrary.simpleMessage("Criar"), "createAccount": MessageLookupByLibrary.simpleMessage("Criar conta"), "createAlbumActionHint": MessageLookupByLibrary.simpleMessage( @@ -570,7 +575,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("O uso atual é "), "custom": MessageLookupByLibrary.simpleMessage("Personalizado"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Escuro"), "dayToday": MessageLookupByLibrary.simpleMessage("Hoje"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Ontem"), @@ -590,10 +595,10 @@ class MessageLookup extends MessageLookupByLibrary { "deleteAlbumDialog": MessageLookupByLibrary.simpleMessage( "Também excluir as fotos (e vídeos) presentes neste álbum de todos os outros álbuns que eles fazem parte?"), "deleteAlbumsDialogBody": MessageLookupByLibrary.simpleMessage( - "Isto irá apagar todos os álbuns vazios. Isso é útil quando você deseja reduzir a bagunça na sua lista de álbuns."), - "deleteAll": MessageLookupByLibrary.simpleMessage("Excluir Tudo"), + "Isso excluirá todos os álbuns vazios. Isso é útil quando você quiser reduzir a desordem no seu álbum."), + "deleteAll": MessageLookupByLibrary.simpleMessage("Excluir tudo"), "deleteConfirmDialogBody": MessageLookupByLibrary.simpleMessage( - "Esta conta está vinculada a outros aplicativos Ente, se você usar algum. Seus dados enviados, em todos os aplicativos Ente, serão agendados para exclusão, e sua conta será excluída permanentemente."), + "Esta conta está vinculada aos outros aplicativos do Ente, se você usar algum. Seus dados baixados, entre todos os aplicativos do Ente, serão programados para exclusão, e sua conta será permanentemente excluída."), "deleteEmailRequest": MessageLookupByLibrary.simpleMessage( "Por favor, envie um e-mail à account-deletion@ente.io do seu endereço de e-mail registrado."), "deleteEmptyAlbums": @@ -606,10 +611,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Excluir do dispositivo"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Excluir do Ente"), - "deleteItemCount": m21, - "deleteLocation": MessageLookupByLibrary.simpleMessage("Excluir Local"), + "deleteItemCount": m22, + "deleteLocation": + MessageLookupByLibrary.simpleMessage("Excluir localização"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Excluir fotos"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Está faltando um recurso-chave que eu preciso"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -625,7 +631,8 @@ class MessageLookup extends MessageLookupByLibrary { "deleteSharedAlbumDialogBody": MessageLookupByLibrary.simpleMessage( "O álbum será apagado para todos\n\nVocê perderá o acesso a fotos compartilhadas neste álbum que pertencem aos outros"), "descriptions": MessageLookupByLibrary.simpleMessage("Descrições"), - "deselectAll": MessageLookupByLibrary.simpleMessage("Desmarcar todos"), + "deselectAll": + MessageLookupByLibrary.simpleMessage("Deselecionar tudo"), "designedToOutlive": MessageLookupByLibrary.simpleMessage("Feito para ter longevidade"), "details": MessageLookupByLibrary.simpleMessage("Detalhes"), @@ -636,7 +643,7 @@ class MessageLookup extends MessageLookupByLibrary { "deviceCodeHint": MessageLookupByLibrary.simpleMessage("Insira o código"), "deviceFilesAutoUploading": MessageLookupByLibrary.simpleMessage( - "Arquivos adicionados a este álbum do dispositivo serão automaticamente enviados para o Ente."), + "Arquivos adicionados ao álbum do dispositivo serão automaticamente enviados para o Ente."), "deviceLock": MessageLookupByLibrary.simpleMessage("Bloqueio do dispositivo"), "deviceLockExplanation": MessageLookupByLibrary.simpleMessage( @@ -650,7 +657,7 @@ class MessageLookup extends MessageLookupByLibrary { "Os visualizadores podem fazer capturas de tela ou salvar uma cópia de suas fotos usando ferramentas externas"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Por favor, saiba que"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Desativar autenticação de dois fatores"), "disablingTwofactorAuthentication": @@ -689,49 +696,49 @@ class MessageLookup extends MessageLookupByLibrary { "Você quer descartar as edições que você fez?"), "done": MessageLookupByLibrary.simpleMessage("Concluído"), "doubleYourStorage": - MessageLookupByLibrary.simpleMessage("Dobre seu armazenamento"), + MessageLookupByLibrary.simpleMessage("Duplique seu armazenamento"), "download": MessageLookupByLibrary.simpleMessage("Baixar"), "downloadFailed": - MessageLookupByLibrary.simpleMessage("Falha no download"), + MessageLookupByLibrary.simpleMessage("Falhou ao baixar"), "downloading": MessageLookupByLibrary.simpleMessage("Baixando..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Editar"), "editLocation": MessageLookupByLibrary.simpleMessage("Editar local"), "editLocationTagTitle": - MessageLookupByLibrary.simpleMessage("Editar local"), + MessageLookupByLibrary.simpleMessage("Editar localização"), "editsSaved": MessageLookupByLibrary.simpleMessage("Edições salvas"), "editsToLocationWillOnlyBeSeenWithinEnte": MessageLookupByLibrary.simpleMessage( "Edições para local só serão vistas dentro do Ente"), "eligible": MessageLookupByLibrary.simpleMessage("elegível"), "email": MessageLookupByLibrary.simpleMessage("E-mail"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Verificação por e-mail"), "emailYourLogs": - MessageLookupByLibrary.simpleMessage("Enviar logs por e-mail"), + MessageLookupByLibrary.simpleMessage("Enviar registros por e-mail"), "empty": MessageLookupByLibrary.simpleMessage("Esvaziar"), "emptyTrash": MessageLookupByLibrary.simpleMessage("Esvaziar a lixeira?"), - "enable": MessageLookupByLibrary.simpleMessage("Habilitar"), + "enable": MessageLookupByLibrary.simpleMessage("Ativar"), "enableMLIndexingDesc": MessageLookupByLibrary.simpleMessage( "Ente suporta aprendizado de máquina no dispositivo para reconhecimento facial, busca mágica e outros recursos avançados de busca"), - "enableMaps": MessageLookupByLibrary.simpleMessage("Habilitar Mapa"), + "enableMaps": MessageLookupByLibrary.simpleMessage("Ativar mapas"), "enableMapsDesc": MessageLookupByLibrary.simpleMessage( - "Isto mostrará suas fotos em um mapa do mundo.\n\nEste mapa é hospedado pelo OpenStreetMap, e os exatos locais de suas fotos nunca são compartilhados.\n\nVocê pode desativar esse recurso a qualquer momento nas Configurações."), - "enabled": MessageLookupByLibrary.simpleMessage("Habilitado"), - "encryptingBackup": - MessageLookupByLibrary.simpleMessage("Criptografando backup..."), + "Isso exibirá suas fotos em um mapa mundial.\n\nEste mapa é hospedado por Open Street Map, e as exatas localizações das fotos nunca serão compartilhadas.\n\nVocê pode desativar esta função a qualquer momento em Opções."), + "enabled": MessageLookupByLibrary.simpleMessage("Ativado"), + "encryptingBackup": MessageLookupByLibrary.simpleMessage( + "Criptografando cópia de segurança..."), "encryption": MessageLookupByLibrary.simpleMessage("Criptografia"), "encryptionKeys": MessageLookupByLibrary.simpleMessage("Chaves de criptografia"), "endpointUpdatedMessage": MessageLookupByLibrary.simpleMessage( "Endpoint atualizado com sucesso"), "endtoendEncryptedByDefault": MessageLookupByLibrary.simpleMessage( - "Criptografia de ponta a ponta por padrão"), + "Criptografado de ponta a ponta por padrão"), "enteCanEncryptAndPreserveFilesOnlyIfYouGrant": MessageLookupByLibrary.simpleMessage( "Ente pode criptografar e preservar arquivos apenas se você conceder acesso a eles"), @@ -742,13 +749,13 @@ class MessageLookup extends MessageLookupByLibrary { "enteSubscriptionShareWithFamily": MessageLookupByLibrary.simpleMessage( "Sua família também pode ser adicionada ao seu plano."), "enterAlbumName": - MessageLookupByLibrary.simpleMessage("Digite o nome do álbum"), + MessageLookupByLibrary.simpleMessage("Inserir nome do álbum"), "enterCode": MessageLookupByLibrary.simpleMessage("Insira o código"), "enterCodeDescription": MessageLookupByLibrary.simpleMessage( "Insira o código fornecido pelo seu amigo para reivindicar o armazenamento grátis para os dois"), "enterEmail": MessageLookupByLibrary.simpleMessage("Inserir e-mail"), "enterFileName": - MessageLookupByLibrary.simpleMessage("Digite o nome do arquivo"), + MessageLookupByLibrary.simpleMessage("Inserir nome do arquivo"), "enterNewPasswordToEncrypt": MessageLookupByLibrary.simpleMessage( "Insira uma senha nova para criptografar seus dados"), "enterPassword": MessageLookupByLibrary.simpleMessage("Inserir senha"), @@ -772,13 +779,14 @@ class MessageLookup extends MessageLookupByLibrary { "Insira sua chave de recuperação"), "error": MessageLookupByLibrary.simpleMessage("Erro"), "everywhere": - MessageLookupByLibrary.simpleMessage("em todos os lugares"), + MessageLookupByLibrary.simpleMessage("em todas as partes"), "exif": MessageLookupByLibrary.simpleMessage("EXIF"), "existingUser": MessageLookupByLibrary.simpleMessage("Usuário existente"), "expiredLinkInfo": MessageLookupByLibrary.simpleMessage( "O link expirou. Selecione um novo tempo de expiração ou desative a expiração do link."), - "exportLogs": MessageLookupByLibrary.simpleMessage("Exportar logs"), + "exportLogs": + MessageLookupByLibrary.simpleMessage("Exportar registros"), "exportYourData": MessageLookupByLibrary.simpleMessage("Exportar dados"), "extraPhotosFound": MessageLookupByLibrary.simpleMessage( @@ -792,10 +800,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Falhou ao aplicar código"), "failedToCancel": MessageLookupByLibrary.simpleMessage("Falhou ao cancelar"), - "failedToDownloadVideo": MessageLookupByLibrary.simpleMessage( - "Falha ao fazer download do vídeo"), + "failedToDownloadVideo": + MessageLookupByLibrary.simpleMessage("Falhou ao baixar vídeo"), "failedToFetchOriginalForEdit": MessageLookupByLibrary.simpleMessage( - "Falha ao obter original para edição"), + "Falhou ao obter original para edição"), "failedToFetchReferralDetails": MessageLookupByLibrary.simpleMessage( "Não foi possível buscar os detalhes de referência. Tente novamente mais tarde."), "failedToLoadAlbums": @@ -805,7 +813,7 @@ class MessageLookup extends MessageLookupByLibrary { "failedToVerifyPaymentStatus": MessageLookupByLibrary.simpleMessage( "Falhou ao verificar estado do pagamento"), "familyPlanOverview": MessageLookupByLibrary.simpleMessage( - "Adicione 5 membros da família ao seu plano existente sem pagar a mais.\n\nCada membro recebe seu próprio espaço privado, e nenhum membro pode ver os arquivos uns dos outros a menos que sejam compartilhados.\n\nPlanos de família estão disponíveis para os clientes que têm uma assinatura do Ente paga.\n\nAssine agora para começar!"), + "Adicione 5 familiares para seu plano existente sem pagar nenhum custo adicional.\n\nCada membro ganha seu espaço privado, significando que eles não podem ver os arquivos dos outros a menos que eles sejam compartilhados.\n\nOs planos familiares estão disponíveis para clientes que já tem uma assinatura paga do Ente.\n\nAssine agora para iniciar!"), "familyPlanPortalTitle": MessageLookupByLibrary.simpleMessage("Família"), "familyPlans": @@ -815,16 +823,16 @@ class MessageLookup extends MessageLookupByLibrary { "favorite": MessageLookupByLibrary.simpleMessage("Favorito"), "feedback": MessageLookupByLibrary.simpleMessage("Feedback"), "fileFailedToSaveToGallery": MessageLookupByLibrary.simpleMessage( - "Falha ao salvar o arquivo na galeria"), + "Falhou ao salvar arquivo na galeria"), "fileInfoAddDescHint": MessageLookupByLibrary.simpleMessage("Adicionar descrição..."), "fileSavedToGallery": - MessageLookupByLibrary.simpleMessage("Vídeo salvo na galeria"), + MessageLookupByLibrary.simpleMessage("Arquivo salvo na galeria"), "fileTypes": MessageLookupByLibrary.simpleMessage("Tipos de arquivo"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Tipos de arquivo e nomes"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Arquivos excluídos"), "filesSavedToGallery": @@ -840,42 +848,41 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Rostos encontrados"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage( "Armazenamento grátis reivindicado"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Armazenamento disponível"), "freeTrial": MessageLookupByLibrary.simpleMessage("Avaliação grátis"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Liberar espaço no dispositivo"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Economize espaço em seu dispositivo por limpar arquivos já salvos com segurança."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Liberar espaço"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( - "Até 1000 memórias mostradas na galeria"), + "Até 1.000 memórias exibidas na galeria"), "general": MessageLookupByLibrary.simpleMessage("Geral"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Gerando chaves de criptografia..."), - "genericProgress": m36, - "goToSettings": - MessageLookupByLibrary.simpleMessage("Ir para Configurações"), + "genericProgress": m37, + "goToSettings": MessageLookupByLibrary.simpleMessage("Ir às opções"), "googlePlayId": MessageLookupByLibrary.simpleMessage("ID do Google Play"), "grantFullAccessPrompt": MessageLookupByLibrary.simpleMessage( - "Por favor, permita o acesso a todas as fotos nas configurações do aplicativo"), + "Permita o acesso a todas as fotos nas opções do aplicativo"), "grantPermission": - MessageLookupByLibrary.simpleMessage("Conceder permissão"), + MessageLookupByLibrary.simpleMessage("Conceder permissões"), "groupNearbyPhotos": MessageLookupByLibrary.simpleMessage("Agrupar fotos próximas"), "guestView": MessageLookupByLibrary.simpleMessage("Visão de convidado"), "guestViewEnablePreSteps": MessageLookupByLibrary.simpleMessage( "Para ativar a visão de convidado, por favor ative um método de autenticação nas configurações do sistema do seu dispositivo."), "hearUsExplanation": MessageLookupByLibrary.simpleMessage( - "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!"), + "Não rastreamos instalações de aplicativo. Seria útil se você contasse onde nos encontrou!"), "hearUsWhereTitle": MessageLookupByLibrary.simpleMessage( - "Como você ouviu sobre o Ente? (opcional)"), + "Como você soube do Ente? (opcional)"), "help": MessageLookupByLibrary.simpleMessage("Ajuda"), "hidden": MessageLookupByLibrary.simpleMessage("Oculto"), "hide": MessageLookupByLibrary.simpleMessage("Ocultar"), @@ -886,18 +893,18 @@ class MessageLookup extends MessageLookupByLibrary { "Oculta o conteúdo do seletor de apps"), "hiding": MessageLookupByLibrary.simpleMessage("Ocultando..."), "hostedAtOsmFrance": - MessageLookupByLibrary.simpleMessage("Hospedado na OSM France"), + MessageLookupByLibrary.simpleMessage("Hospedado em OSM France"), "howItWorks": MessageLookupByLibrary.simpleMessage("Como funciona"), "howToViewShareeVerificationID": MessageLookupByLibrary.simpleMessage( "Peça-os para manterem pressionado no endereço de e-mail na tela de opções, e verifique-se os IDs de ambos os dispositivos correspondem."), "iOSGoToSettingsDescription": MessageLookupByLibrary.simpleMessage( - "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."), + "A autenticação biométrica não está definida no dispositivo. Ative o Touch ID ou Face ID no dispositivo."), "iOSLockOut": MessageLookupByLibrary.simpleMessage( - "A Autenticação Biométrica está desativada. Por favor, bloqueie e desbloqueie sua tela para ativá-la."), + "A autenticação biométrica está desativada. Bloqueie e desbloqueie sua tela para ativá-la."), "iOSOkButton": MessageLookupByLibrary.simpleMessage("OK"), "ignoreUpdate": MessageLookupByLibrary.simpleMessage("Ignorar"), "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( - "Alguns arquivos neste álbum são ignorados do envio porque eles tinham sido anteriormente excluídos do Ente."), + "Alguns arquivos neste álbum são ignorados do envio porque eles foram anteriormente excluídos do Ente."), "immediately": MessageLookupByLibrary.simpleMessage("Imediatamente"), "importing": MessageLookupByLibrary.simpleMessage("Importando...."), "incorrectCode": @@ -935,11 +942,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Convide seus amigos ao Ente"), "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( - "Parece que algo deu errado. Por favor, tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de suporte."), - "itemCount": m37, + "Parece que algo deu errado. Tente novamente mais tarde. Caso o erro persistir, por favor, entre em contato com nossa equipe."), + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( - "Os itens mostram o número de dias restantes antes da exclusão permanente"), + "Os itens exibem o número de dias restantes antes da exclusão permanente"), "itemsWillBeRemovedFromAlbum": MessageLookupByLibrary.simpleMessage( "Os itens selecionados serão removidos deste álbum"), "joinDiscord": @@ -953,7 +960,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Última atualização"), "leave": MessageLookupByLibrary.simpleMessage("Sair"), "leaveAlbum": MessageLookupByLibrary.simpleMessage("Sair do álbum"), - "leaveFamily": MessageLookupByLibrary.simpleMessage("Sair da família"), + "leaveFamily": + MessageLookupByLibrary.simpleMessage("Sair do plano familiar"), "leaveSharedAlbum": MessageLookupByLibrary.simpleMessage( "Sair do álbum compartilhado?"), "left": MessageLookupByLibrary.simpleMessage("Esquerda"), @@ -965,7 +973,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Limite do dispositivo"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Ativado"), "linkExpired": MessageLookupByLibrary.simpleMessage("Expirado"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Expiração do link"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("O link expirou"), @@ -973,9 +981,9 @@ class MessageLookup extends MessageLookupByLibrary { "livePhotos": MessageLookupByLibrary.simpleMessage("Fotos em movimento"), "loadMessage1": MessageLookupByLibrary.simpleMessage( - "Você pode compartilhar sua assinatura com sua família"), + "Você pode compartilhar sua assinatura com seus familiares"), "loadMessage2": MessageLookupByLibrary.simpleMessage( - "Nós preservamos mais de 30 milhões de memórias até agora"), + "Nós preservamos mais de 30 milhões de memórias até então"), "loadMessage3": MessageLookupByLibrary.simpleMessage( "Mantemos 3 cópias dos seus dados, uma em um abrigo subterrâneo"), "loadMessage4": MessageLookupByLibrary.simpleMessage( @@ -985,9 +993,9 @@ class MessageLookup extends MessageLookupByLibrary { "loadMessage6": MessageLookupByLibrary.simpleMessage( "Você pode compartilhar links para seus álbuns com seus entes queridos"), "loadMessage7": MessageLookupByLibrary.simpleMessage( - "Nossos aplicativos móveis são executados em segundo plano para criptografar e fazer backup de quaisquer novas fotos que você clique"), + "Nossos aplicativos móveis são executados em segundo plano para criptografar e copiar com segurança quaisquer fotos novas que você acessar"), "loadMessage8": MessageLookupByLibrary.simpleMessage( - "web.ente.io tem um envio mais rápido"), + "web.ente.io tem um enviador mais rápido"), "loadMessage9": MessageLookupByLibrary.simpleMessage( "Nós usamos Xchacha20Poly1305 para criptografar seus dados com segurança"), "loadingExifData": @@ -1001,12 +1009,15 @@ class MessageLookup extends MessageLookupByLibrary { "loadingYourPhotos": MessageLookupByLibrary.simpleMessage("Carregando suas fotos..."), "localGallery": MessageLookupByLibrary.simpleMessage("Galeria local"), + "localIndexing": + MessageLookupByLibrary.simpleMessage("Indexação local"), "localSyncErrorMessage": MessageLookupByLibrary.simpleMessage( "Parece que algo deu errado, já que as fotos locais estão sincronizando mais tempo do que o esperado. Por favor, entre em contato com a nossa equipe de suporte"), - "location": MessageLookupByLibrary.simpleMessage("Local"), - "locationName": MessageLookupByLibrary.simpleMessage("Nome do Local"), + "location": MessageLookupByLibrary.simpleMessage("Localização"), + "locationName": + MessageLookupByLibrary.simpleMessage("Nome da localização"), "locationTagFeatureDescription": MessageLookupByLibrary.simpleMessage( - "Uma tag em grupo de todas as fotos que foram tiradas dentro de algum raio de uma foto"), + "Uma etiqueta de localização agrupa todas as fotos fotografadas em algum raio de uma foto"), "locations": MessageLookupByLibrary.simpleMessage("Locais"), "lockButtonLabel": MessageLookupByLibrary.simpleMessage("Bloquear"), "lockscreen": MessageLookupByLibrary.simpleMessage("Tela de bloqueio"), @@ -1020,13 +1031,13 @@ class MessageLookup extends MessageLookupByLibrary { "Ao clicar em entrar, eu concordo com os termos de serviço e a política de privacidade"), "logout": MessageLookupByLibrary.simpleMessage("Encerrar sessão"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( - "Isso enviará através dos logs para nos ajudar a depurar o seu problema. Por favor, note que nomes de arquivos serão incluídos para ajudar a rastrear problemas com arquivos específicos."), + "Isso enviará através dos registros para ajudar-nos a resolver seu problema. Saiba que, nome de arquivos serão incluídos para ajudar a buscar problemas com arquivos específicos."), "longPressAnEmailToVerifyEndToEndEncryption": MessageLookupByLibrary.simpleMessage( "Pressione e segure um e-mail para verificar a criptografia de ponta a ponta."), "longpressOnAnItemToViewInFullscreen": MessageLookupByLibrary.simpleMessage( - "Pressione e segure em um item para exibir em tela cheia"), + "Mantenha pressionado em um item para visualizá-lo em tela cheia"), "loopVideoOff": MessageLookupByLibrary.simpleMessage("Repetir vídeo desligado"), "loopVideoOn": @@ -1053,7 +1064,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Mapas"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Produtos"), "mergeWithExisting": MessageLookupByLibrary.simpleMessage("Juntar com o existente"), @@ -1070,7 +1081,7 @@ class MessageLookup extends MessageLookupByLibrary { "mlIndexingDescription": MessageLookupByLibrary.simpleMessage( "Note que a aprendizagem automática resultará em uso de bateria e largura de banda maior até que todos os itens forem indexados. Considere-se usar o aplicativo para notebook para uma indexação mais rápida, todos os resultados serão sincronizados automaticamente."), "mobileWebDesktop": - MessageLookupByLibrary.simpleMessage("Mobile, Web, Desktop"), + MessageLookupByLibrary.simpleMessage("Celular, Web, Computador"), "moderateStrength": MessageLookupByLibrary.simpleMessage("Moderado"), "modifyYourQueryOrTrySearchingFor": MessageLookupByLibrary.simpleMessage( @@ -1080,19 +1091,20 @@ class MessageLookup extends MessageLookupByLibrary { "moreDetails": MessageLookupByLibrary.simpleMessage("Mais detalhes"), "mostRecent": MessageLookupByLibrary.simpleMessage("Mais recente"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Mais relevante"), - "moveItem": m39, - "moveToAlbum": MessageLookupByLibrary.simpleMessage("Mover para álbum"), + "moveItem": m40, + "moveToAlbum": + MessageLookupByLibrary.simpleMessage("Mover para o álbum"), "moveToHiddenAlbum": - MessageLookupByLibrary.simpleMessage("Mover para álbum oculto"), - "movedSuccessfullyTo": m40, + MessageLookupByLibrary.simpleMessage("Mover ao álbum oculto"), + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Movido para a lixeira"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( - "Enviando arquivos para o álbum..."), + "Movendo arquivos para o álbum..."), "name": MessageLookupByLibrary.simpleMessage("Nome"), "nameTheAlbum": MessageLookupByLibrary.simpleMessage("Nomear o álbum"), "networkConnectionRefusedErr": MessageLookupByLibrary.simpleMessage( - "Não foi possível conectar ao Ente, tente novamente após algum tempo. Se o erro persistir, entre em contato com o suporte."), + "Não foi possível conectar ao Ente, tente novamente mais tarde. Se o erro persistir, entre em contato com o suporte."), "networkHostLookUpErr": MessageLookupByLibrary.simpleMessage( "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."), "never": MessageLookupByLibrary.simpleMessage("Nunca"), @@ -1112,15 +1124,15 @@ class MessageLookup extends MessageLookupByLibrary { "noDuplicates": MessageLookupByLibrary.simpleMessage("✨ Sem duplicatas"), "noExifData": MessageLookupByLibrary.simpleMessage("Sem dados EXIF"), - "noHiddenPhotosOrVideos": MessageLookupByLibrary.simpleMessage( - "Nenhuma foto ou vídeos ocultos"), - "noImagesWithLocation": - MessageLookupByLibrary.simpleMessage("Nenhuma imagem com local"), + "noHiddenPhotosOrVideos": + MessageLookupByLibrary.simpleMessage("Sem fotos ou vídeos ocultos"), + "noImagesWithLocation": MessageLookupByLibrary.simpleMessage( + "Nenhuma imagem com localização"), "noInternetConnection": MessageLookupByLibrary.simpleMessage("Sem conexão à internet"), "noPhotosAreBeingBackedUpRightNow": MessageLookupByLibrary.simpleMessage( - "No momento não há backup de fotos sendo feito"), + "No momento não há fotos sendo copiadas com segurança"), "noPhotosFoundHere": MessageLookupByLibrary.simpleMessage( "Nenhuma foto encontrada aqui"), "noQuickLinksSelected": MessageLookupByLibrary.simpleMessage( @@ -1134,7 +1146,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Nenhum resultado encontrado"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage( "Nenhum bloqueio de sistema encontrado"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage( "Nada compartilhado com você ainda"), "nothingToSeeHere": @@ -1143,16 +1155,17 @@ class MessageLookup extends MessageLookupByLibrary { "ok": MessageLookupByLibrary.simpleMessage("OK"), "onDevice": MessageLookupByLibrary.simpleMessage("No dispositivo"), "onEnte": MessageLookupByLibrary.simpleMessage( - "Em ente"), - "onlyFamilyAdminCanChangeCode": m42, + "No ente"), + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Ops"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( - "Ops, não foi possível salvar edições"), + "Opa! Não foi possível salvar as edições"), "oopsSomethingWentWrong": MessageLookupByLibrary.simpleMessage("Ops, algo deu errado"), - "openSettings": - MessageLookupByLibrary.simpleMessage("Abrir Configurações"), - "openTheItem": MessageLookupByLibrary.simpleMessage("• Abra o item"), + "openSettings": MessageLookupByLibrary.simpleMessage("Abrir opções"), + "openTheItem": + MessageLookupByLibrary.simpleMessage("• Abra a foto ou vídeo"), "openstreetmapContributors": MessageLookupByLibrary.simpleMessage( "Contribuidores do OpenStreetMap"), "optionalAsShortAsYouLike": MessageLookupByLibrary.simpleMessage( @@ -1184,8 +1197,8 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("O pagamento falhou"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( - "Infelizmente o seu pagamento falhou. Entre em contato com o suporte e nós ajudaremos você!"), - "paymentFailedTalkToProvider": m43, + "Infelizmente o pagamento falhou. Entre em contato com o suporte e nós ajudaremos você!"), + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Itens pendentes"), "pendingSync": MessageLookupByLibrary.simpleMessage("Sincronização pendente"), @@ -1207,14 +1220,14 @@ class MessageLookup extends MessageLookupByLibrary { "photos": MessageLookupByLibrary.simpleMessage("Fotos"), "photosAddedByYouWillBeRemovedFromTheAlbum": MessageLookupByLibrary.simpleMessage( - "As fotos adicionadas por você serão removidas do álbum"), + "Suas fotos adicionadas serão removidas do álbum"), "pickCenterPoint": MessageLookupByLibrary.simpleMessage("Escolha o ponto central"), "pinAlbum": MessageLookupByLibrary.simpleMessage("Fixar álbum"), "pinLock": MessageLookupByLibrary.simpleMessage("Bloqueio PIN"), "playOnTv": MessageLookupByLibrary.simpleMessage("Reproduzir álbum na TV"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Assinatura da PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1226,27 +1239,26 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Por favor, contate o suporte se o problema persistir"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage( "Por favor, conceda as permissões"), - "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( - "Por favor, inicie sessão novamente"), + "pleaseLoginAgain": + MessageLookupByLibrary.simpleMessage("Registre-se novamente"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Selecione links rápidos para remover"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Tente novamente"), "pleaseVerifyTheCodeYouHaveEntered": - MessageLookupByLibrary.simpleMessage( - "Por favor, verifique o código que você inseriu"), + MessageLookupByLibrary.simpleMessage("Verifique o código inserido"), "pleaseWait": MessageLookupByLibrary.simpleMessage("Aguarde..."), - "pleaseWaitDeletingAlbum": MessageLookupByLibrary.simpleMessage( - "Por favor, aguarde, excluindo álbum"), + "pleaseWaitDeletingAlbum": + MessageLookupByLibrary.simpleMessage("Aguarde, excluindo álbum"), "pleaseWaitForSometimeBeforeRetrying": MessageLookupByLibrary.simpleMessage( - "Por favor, aguarde algum tempo antes de tentar novamente"), + "Por favor, aguarde mais algum tempo antes de tentar novamente"), "preparingLogs": - MessageLookupByLibrary.simpleMessage("Preparando logs..."), + MessageLookupByLibrary.simpleMessage("Preparando registros..."), "preserveMore": MessageLookupByLibrary.simpleMessage("Preservar mais"), "pressAndHoldToPlayVideo": MessageLookupByLibrary.simpleMessage( "Pressione e segure para reproduzir o vídeo"), @@ -1256,10 +1268,10 @@ class MessageLookup extends MessageLookupByLibrary { "privacyPolicyTitle": MessageLookupByLibrary.simpleMessage("Política de Privacidade"), "privateBackups": - MessageLookupByLibrary.simpleMessage("Backups privados"), + MessageLookupByLibrary.simpleMessage("Cópias privadas"), "privateSharing": MessageLookupByLibrary.simpleMessage("Compartilhamento privado"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Link público criado"), "publicLinkEnabled": @@ -1270,7 +1282,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Avalie o aplicativo"), "rateUs": MessageLookupByLibrary.simpleMessage("Avaliar"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Recuperar"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recuperar conta"), @@ -1300,12 +1312,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Reinserir senha"), "reenterPin": MessageLookupByLibrary.simpleMessage("Reinserir PIN"), "referFriendsAnd2xYourPlan": MessageLookupByLibrary.simpleMessage( - "Indique amigos e 2x seu plano"), + "Recomende seus amigos e duplique seu plano"), "referralStep1": MessageLookupByLibrary.simpleMessage( "1. Envie este código aos seus amigos"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Eles então se inscrevem num plano pago"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Referências"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "As referências estão atualmente pausadas"), @@ -1327,11 +1339,11 @@ class MessageLookup extends MessageLookupByLibrary { "removeFromAlbumTitle": MessageLookupByLibrary.simpleMessage("Remover do álbum?"), "removeFromFavorite": - MessageLookupByLibrary.simpleMessage("Remover dos favoritos"), + MessageLookupByLibrary.simpleMessage("Desfavoritar"), "removeLink": MessageLookupByLibrary.simpleMessage("Remover link"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Remover participante"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("Remover etiqueta da pessoa"), "removePublicLink": @@ -1349,7 +1361,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Renomear arquivo"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Renovar assinatura"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Informar um erro"), "reportBug": MessageLookupByLibrary.simpleMessage("Informar erro"), "resendEmail": MessageLookupByLibrary.simpleMessage("Reenviar e-mail"), @@ -1357,6 +1369,7 @@ class MessageLookup extends MessageLookupByLibrary { "Redefinir arquivos ignorados"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Redefinir senha"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("Redefinir para o padrão"), "restore": MessageLookupByLibrary.simpleMessage("Restaurar"), @@ -1368,7 +1381,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Envios retomáveis"), "retry": MessageLookupByLibrary.simpleMessage("Tentar novamente"), "reviewDeduplicateItems": MessageLookupByLibrary.simpleMessage( - "Por favor, reveja e exclua os itens que você acredita serem duplicados."), + "Reveja e exclua os itens que você acredita serem duplicados."), "reviewSuggestions": MessageLookupByLibrary.simpleMessage("Revisar sugestões"), "right": MessageLookupByLibrary.simpleMessage("Direita"), @@ -1399,13 +1412,13 @@ class MessageLookup extends MessageLookupByLibrary { "searchByAlbumNameHint": MessageLookupByLibrary.simpleMessage("Nome do álbum"), "searchByExamples": MessageLookupByLibrary.simpleMessage( - "• Nomes de álbuns (ex: \"Câmera\")\n• Tipos de arquivos (ex.: \"Vídeos\", \".gif\")\n• Anos e meses (e.. \"2022\", \"Janeiro\")\n• Feriados (por exemplo, \"Natal\")\n• Descrições de fotos (por exemplo, \"#divertido\")"), + "• Nomes de álbuns (ex: \"Câmera\")\n• Tipos de arquivos (ex.: \"Vídeos\", \".gif\")\n• Anos e meses (ex.: \"2022\", \"Janeiro\")\n• Temporadas (ex.: \"Natal\")\n• Tags (ex.: \"#divertido\")"), "searchCaptionEmptySection": MessageLookupByLibrary.simpleMessage( - "Adicione descrições como \"#trip\" nas informações das fotos para encontrá-las aqui rapidamente"), - "searchDatesEmptySection": MessageLookupByLibrary.simpleMessage( - "Pesquisar por data, mês ou ano"), + "Adicione marcações como \"#viagem\" nas informações das fotos para encontrá-las aqui com facilidade"), + "searchDatesEmptySection": + MessageLookupByLibrary.simpleMessage("Buscar por data, mês ou ano"), "searchFaceEmptySection": MessageLookupByLibrary.simpleMessage( - "Pessoas serão exibidas aqui uma vez que a indexação é feita"), + "As pessoas apareceram aqui quando a indexação for concluída"), "searchFileTypesAndNamesEmptySection": MessageLookupByLibrary.simpleMessage("Tipos de arquivo e nomes"), "searchHint1": MessageLookupByLibrary.simpleMessage( @@ -1421,7 +1434,7 @@ class MessageLookup extends MessageLookupByLibrary { "Fotos de grupo que estão sendo tiradas em algum raio da foto"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Convide pessoas e você verá todas as fotos compartilhadas por elas aqui"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Segurança"), "selectALocation": MessageLookupByLibrary.simpleMessage("Selecionar um local"), @@ -1434,7 +1447,7 @@ class MessageLookup extends MessageLookupByLibrary { "selectItemsToAdd": MessageLookupByLibrary.simpleMessage( "Selecionar itens para adicionar"), "selectLanguage": - MessageLookupByLibrary.simpleMessage("Selecionar Idioma"), + MessageLookupByLibrary.simpleMessage("Selecionar idioma"), "selectMorePhotos": MessageLookupByLibrary.simpleMessage("Selecionar mais fotos"), "selectReason": MessageLookupByLibrary.simpleMessage("Diga o motivo"), @@ -1448,8 +1461,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Os itens selecionados serão excluídos de todos os álbuns e movidos para a lixeira."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Enviar"), "sendEmail": MessageLookupByLibrary.simpleMessage("Enviar e-mail"), "sendInvite": MessageLookupByLibrary.simpleMessage("Enviar convite"), @@ -1477,16 +1490,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Compartilhar um álbum agora"), "shareLink": MessageLookupByLibrary.simpleMessage("Compartilhar link"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Compartilhar apenas com as pessoas que você quiser"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Baixe o Ente para que nós possamos compartilhar com facilidade fotos e vídeos de qualidade original\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Compartilhar com usuários não ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Compartilhar seu primeiro álbum"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1499,7 +1512,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Novas fotos compartilhadas"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Receber notificações quando alguém adicionar uma foto a um álbum compartilhado que você faz parte"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Compartilhado comigo"), "sharedWithYou": @@ -1516,16 +1529,16 @@ class MessageLookup extends MessageLookupByLibrary { "Encerrar sessão em outros dispositivos"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Eu concordo com os termos de serviço e a política de privacidade"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Ele será excluído de todos os álbuns."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Pular"), "social": MessageLookupByLibrary.simpleMessage("Redes sociais"), "someItemsAreInBothEnteAndYourDevice": MessageLookupByLibrary.simpleMessage( - "Alguns itens estão tanto no Ente quanto no seu dispositivo."), + "Alguns itens estão em ambos o Ente quanto no seu dispositivo."), "someOfTheFilesYouAreTryingToDeleteAre": MessageLookupByLibrary.simpleMessage( "Alguns dos arquivos que você está tentando excluir só estão disponíveis no seu dispositivo e não podem ser recuperados se forem excluídos"), @@ -1545,18 +1558,19 @@ class MessageLookup extends MessageLookupByLibrary { "Desculpe, não foi possível remover dos favoritos!"), "sorryTheCodeYouveEnteredIsIncorrect": MessageLookupByLibrary.simpleMessage( - "Desculpe, o código que você inseriu está incorreto"), + "O código inserido está incorreto"), "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": MessageLookupByLibrary.simpleMessage( "Desculpe, não foi possível gerar chaves seguras neste dispositivo.\n\ninicie sessão com um dispositivo diferente."), "sort": MessageLookupByLibrary.simpleMessage("Ordenar"), "sortAlbumsBy": MessageLookupByLibrary.simpleMessage("Ordenar por"), "sortNewestFirst": - MessageLookupByLibrary.simpleMessage("Mais recentes primeiro"), + MessageLookupByLibrary.simpleMessage("Recentes primeiro"), "sortOldestFirst": - MessageLookupByLibrary.simpleMessage("Mais antigos primeiro"), + MessageLookupByLibrary.simpleMessage("Antigos primeiro"), "sparkleSuccess": MessageLookupByLibrary.simpleMessage("✨ Sucesso"), - "startBackup": MessageLookupByLibrary.simpleMessage("Iniciar backup"), + "startBackup": + MessageLookupByLibrary.simpleMessage("Iniciar cópia de segurança"), "status": MessageLookupByLibrary.simpleMessage("Estado"), "stopCastingBody": MessageLookupByLibrary.simpleMessage( "Você quer parar a transmissão?"), @@ -1565,7 +1579,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Armazenamento"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Família"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Você"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage( "Limite de armazenamento excedido"), "storageUsageInfo": m62, @@ -1584,7 +1598,7 @@ class MessageLookup extends MessageLookupByLibrary { "successfullyUnarchived": MessageLookupByLibrary.simpleMessage("Desarquivado com sucesso"), "successfullyUnhid": - MessageLookupByLibrary.simpleMessage("Reexibido com sucesso"), + MessageLookupByLibrary.simpleMessage("Desocultado com sucesso"), "suggestFeatures": MessageLookupByLibrary.simpleMessage("Sugerir recurso"), "support": MessageLookupByLibrary.simpleMessage("Suporte"), @@ -1599,7 +1613,7 @@ class MessageLookup extends MessageLookupByLibrary { "tapToUnlock": MessageLookupByLibrary.simpleMessage("Toque para desbloquear"), "tempErrorContactSupportIfPersists": MessageLookupByLibrary.simpleMessage( - "Parece que algo deu errado. Por favor, tente novamente mais tarde. Se o erro persistir, entre em contato com nossa equipe de suporte."), + "Parece que algo deu errado. Tente novamente mais tarde. Caso o erro persistir, por favor, entre em contato com nossa equipe."), "terminate": MessageLookupByLibrary.simpleMessage("Encerrar"), "terminateSession": MessageLookupByLibrary.simpleMessage("Sair?"), "terms": MessageLookupByLibrary.simpleMessage("Termos"), @@ -1628,10 +1642,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Isso pode ser usado para recuperar sua conta se você perder seu segundo fator"), "thisDevice": MessageLookupByLibrary.simpleMessage("Este dispositivo"), - "thisEmailIsAlreadyInUse": - MessageLookupByLibrary.simpleMessage("Este e-mail já está em uso"), + "thisEmailIsAlreadyInUse": MessageLookupByLibrary.simpleMessage( + "Este e-mail já está sendo usado"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( - "Esta imagem não tem dados exif"), + "Esta imagem não possui dados EXIF"), "thisIsPersonVerificationId": m67, "thisIsYourVerificationId": MessageLookupByLibrary.simpleMessage( "Este é o seu ID de verificação"), @@ -1650,7 +1664,7 @@ class MessageLookup extends MessageLookupByLibrary { "Para ocultar uma foto ou vídeo"), "toResetVerifyEmail": MessageLookupByLibrary.simpleMessage( "Para redefinir sua senha, verifique seu e-mail primeiramente."), - "todaysLogs": MessageLookupByLibrary.simpleMessage("Logs de hoje"), + "todaysLogs": MessageLookupByLibrary.simpleMessage("Registros de hoje"), "tooManyIncorrectAttempts": MessageLookupByLibrary.simpleMessage( "Muitas tentativas incorretas"), "total": MessageLookupByLibrary.simpleMessage("total"), @@ -1660,7 +1674,7 @@ class MessageLookup extends MessageLookupByLibrary { "trim": MessageLookupByLibrary.simpleMessage("Cortar"), "tryAgain": MessageLookupByLibrary.simpleMessage("Tente novamente"), "turnOnBackupForAutoUpload": MessageLookupByLibrary.simpleMessage( - "Ative o backup para enviar automaticamente arquivos adicionados a esta pasta do dispositivo para o Ente."), + "Ative a cópia de segurança para automaticamente enviar arquivos adicionados à pasta do dispositivo para o Ente."), "twitter": MessageLookupByLibrary.simpleMessage("Twitter/X"), "twoMonthsFreeOnYearlyPlans": MessageLookupByLibrary.simpleMessage( "2 meses grátis em planos anuais"), @@ -1683,12 +1697,12 @@ class MessageLookup extends MessageLookupByLibrary { "unavailableReferralCode": MessageLookupByLibrary.simpleMessage( "Desculpe, este código está indisponível."), "uncategorized": MessageLookupByLibrary.simpleMessage("Sem categoria"), - "unhide": MessageLookupByLibrary.simpleMessage("Reexibir"), + "unhide": MessageLookupByLibrary.simpleMessage("Desocultar"), "unhideToAlbum": - MessageLookupByLibrary.simpleMessage("Reexibir para o álbum"), + MessageLookupByLibrary.simpleMessage("Desocultar para o álbum"), "unhiding": MessageLookupByLibrary.simpleMessage("Reexibindo..."), "unhidingFilesToAlbum": MessageLookupByLibrary.simpleMessage( - "Reexibindo arquivos para o álbum"), + "Desocultando arquivos para o álbum"), "unlock": MessageLookupByLibrary.simpleMessage("Desbloquear"), "unpinAlbum": MessageLookupByLibrary.simpleMessage("Desafixar álbum"), "unselectAll": MessageLookupByLibrary.simpleMessage("Desmarcar tudo"), @@ -1697,7 +1711,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Atualização disponível"), "updatingFolderSelection": MessageLookupByLibrary.simpleMessage( "Atualizando seleção de pasta..."), - "upgrade": MessageLookupByLibrary.simpleMessage("Aprimorar"), + "upgrade": MessageLookupByLibrary.simpleMessage("Atualizar"), "uploadingFilesToAlbum": MessageLookupByLibrary.simpleMessage( "Enviando arquivos para o álbum..."), "uploadingMultipleMemories": m69, @@ -1714,12 +1728,12 @@ class MessageLookup extends MessageLookupByLibrary { "useRecoveryKey": MessageLookupByLibrary.simpleMessage("Usar chave de recuperação"), "useSelectedPhoto": - MessageLookupByLibrary.simpleMessage("Utilizar foto selecionada"), - "usedSpace": MessageLookupByLibrary.simpleMessage("Espaço em uso"), + MessageLookupByLibrary.simpleMessage("Usar foto selecionada"), + "usedSpace": MessageLookupByLibrary.simpleMessage("Espaço usado"), "validTill": m70, "verificationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( - "Falha na verificação, por favor, tente novamente"), + "Falha na verificação. Tente novamente"), "verificationId": MessageLookupByLibrary.simpleMessage("ID de verificação"), "verify": MessageLookupByLibrary.simpleMessage("Verificar"), @@ -1748,7 +1762,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Arquivos grandes"), "viewLargeFilesDesc": MessageLookupByLibrary.simpleMessage( "Ver arquivos que consumem a maior parte do armazenamento."), - "viewLogs": MessageLookupByLibrary.simpleMessage("Ver logs"), + "viewLogs": MessageLookupByLibrary.simpleMessage("Ver registros"), "viewRecoveryKey": MessageLookupByLibrary.simpleMessage("Ver chave de recuperação"), "viewer": MessageLookupByLibrary.simpleMessage("Visualizador"), @@ -1763,7 +1777,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Não suportamos a edição de fotos e álbuns que você ainda não possui"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Fraca"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bem-vindo(a) de volta!"), @@ -1781,6 +1795,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Sim, encerrar sessão"), "yesRemove": MessageLookupByLibrary.simpleMessage("Sim, excluir"), "yesRenew": MessageLookupByLibrary.simpleMessage("Sim"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Você"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage( "Você está em um plano familiar!"), @@ -1793,7 +1809,7 @@ class MessageLookup extends MessageLookupByLibrary { "Você pode gerenciar seus links na aba de compartilhamento."), "youCanTrySearchingForADifferentQuery": MessageLookupByLibrary.simpleMessage( - "Você pode tentar procurar uma consulta diferente."), + "Você pode tentar buscar por outra consulta."), "youCannotDowngradeToThisPlan": MessageLookupByLibrary.simpleMessage( "Você não pode rebaixar para este plano"), "youCannotShareWithYourself": MessageLookupByLibrary.simpleMessage( @@ -1828,6 +1844,6 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Você não tem arquivos neste álbum que possam ser excluídos"), "zoomOutToSeePhotos": MessageLookupByLibrary.simpleMessage( - "Diminuir o zoom para ver fotos") + "Reduzir ampliação para ver as fotos") }; } diff --git a/mobile/lib/generated/intl/messages_ro.dart b/mobile/lib/generated/intl/messages_ro.dart index 88f2a38d1a..42f2c40113 100644 --- a/mobile/lib/generated/intl/messages_ro.dart +++ b/mobile/lib/generated/intl/messages_ro.dart @@ -20,29 +20,29 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ro'; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Adăugați articolul', few: 'Adăugați articolele', other: 'Adăugați articolele')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Suplimentul de ${storageAmount} este valabil până pe ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, one: 'Adăugați observator', few: 'Adăugați observatori', other: 'Adăugați observatori')}"; - static String m9(emailOrName) => "Adăugat de ${emailOrName}"; + static String m10(emailOrName) => "Adăugat de ${emailOrName}"; - static String m10(albumName) => "S-au adăugat cu succes la ${albumName}"; + static String m11(albumName) => "S-au adăugat cu succes la ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Fără participanți', one: '1 participant', other: '${count} de participanți')}"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Vă rugăm să vă anulați mai întâi abonamentul existent de la ${paymentProvider}"; - static String m15(user) => + static String m16(user) => "${user} nu va putea să mai adauge fotografii la acest album\n\nVa putea să elimine fotografii existente adăugate de el/ea"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Familia dvs. a revendicat ${storageAmountInGb} GB până acum', @@ -50,116 +50,130 @@ class MessageLookup extends MessageLookupByLibrary { 'other': 'Ați revendicat ${storageAmountInGb} de GB până acum!', })}"; - static String m17(albumName) => "Link colaborativ creat pentru ${albumName}"; + static String m18(albumName) => "Link colaborativ creat pentru ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Vă rugăm să contactați ${familyAdminEmail} pentru a gestiona abonamentul"; - static String m19(provider) => + static String m20(provider) => "Vă rugăm să ne contactați la support@ente.io pentru a vă gestiona abonamentul ${provider}."; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Ștergeți ${count} articol', other: 'Ștergeți ${count} de articole')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Se șterg ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Urmează să eliminați linkul public pentru accesarea „${albumName}”."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Vă rugăm să trimiteți un e-mail la ${supportEmail} de pe adresa de e-mail înregistrată"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Ați curățat ${Intl.plural(count, one: '${count} dublură', few: '${count} dubluri', other: '${count} de dubluri')}, economisind (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} fișiere, ${formattedSize} fiecare"; - static String m28(email) => + static String m29(email) => "${email} nu are un cont Ente.\n\nTrimiteți-le o invitație pentru a distribui fotografii."; - static String m31(storageAmountInGB) => + static String m30(count, formattedNumber) => + "${Intl.plural(count, one: 'Un fișier de pe acest dispozitiv a fost deja salvat în siguranță', few: '${formattedNumber} fișiere de pe acest dispozitiv au fost deja salvate în siguranță', other: '${formattedNumber} de fișiere de pe acest dispozitiv fost deja salvate în siguranță')}"; + + static String m31(count, formattedNumber) => + "${Intl.plural(count, one: 'Un fișier din acest album a fost deja salvat în siguranță', few: '${formattedNumber} fișiere din acest album au fost deja salvate în siguranță', other: '${formattedNumber} de fișiere din acest album au fost deja salvate în siguranță')}"; + + static String m32(storageAmountInGB) => "${storageAmountInGB} GB de fiecare dată când cineva se înscrie pentru un plan plătit și aplică codul dvs."; - static String m32(endDate) => + static String m33(endDate) => "Perioadă de încercare valabilă până pe ${endDate}"; - static String m36(currentlyProcessing, totalCount) => + static String m34(count) => + "Încă ${Intl.plural(count, one: 'îl puteți', few: 'le puteți', other: 'le puteți')} accesa pe Ente cât timp aveți un abonament activ"; + + static String m35(sizeInMBorGB) => "Eliberați ${sizeInMBorGB}"; + + static String m36(count, formattedSize) => + "${Intl.plural(count, one: 'Poate fi șters de pe dispozitiv pentru a elibera ${formattedSize}', few: 'Pot fi șterse de pe dispozitiv pentru a elibera ${formattedSize}', other: 'Pot fi șterse de pe dispozitiv pentru a elibera ${formattedSize}')}"; + + static String m37(currentlyProcessing, totalCount) => "Se procesează ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} articol', few: '${count} articole', other: '${count} de articole')}"; - static String m38(expiryTime) => "Linkul va expira pe ${expiryTime}"; + static String m39(expiryTime) => "Linkul va expira pe ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, one: '${formattedCount} amintire', few: '${formattedCount} amintiri', other: '${formattedCount} de amintiri')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Mutați articolul', few: 'Mutați articole', other: 'Mutați articolele')}"; - static String m40(albumName) => "S-au mutat cu succes în ${albumName}"; + static String m41(albumName) => "S-au mutat cu succes în ${albumName}"; - static String m41(name) => "Nu este ${name}?"; + static String m42(name) => "Nu este ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Vă rugăm să contactați ${familyAdminEmail} pentru a vă schimba codul."; static String m0(passwordStrengthValue) => "Complexitatea parolei: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Vă rugăm să vorbiți cu asistența ${providerName} dacă ați fost taxat"; - static String m44(endDate) => + static String m45(endDate) => "Perioada de încercare gratuită valabilă până pe ${endDate}.\nUlterior, puteți opta pentru un plan plătit."; - static String m46(toEmail) => + static String m47(toEmail) => "Vă rugăm să trimiteți jurnalele la \n${toEmail}"; - static String m48(storeName) => "Evaluați-ne pe ${storeName}"; + static String m49(storeName) => "Evaluați-ne pe ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Amândoi primiți ${storageInGB} GB* gratuit"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} va fi eliminat din acest album distribuit\n\nOrice fotografii adăugate de acesta vor fi, de asemenea, eliminate din album"; - static String m51(endDate) => "Abonamentul se reînnoiește pe ${endDate}"; + static String m52(endDate) => "Abonamentul se reînnoiește pe ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} rezultat găsit', few: '${count} rezultate găsite', other: '${count} de rezultate găsite')}"; - static String m3(count) => "${count} selectate"; + static String m4(count) => "${count} selectate"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "${count} selectate (${yourCount} ale dvs.)"; - static String m54(verificationID) => + static String m55(verificationID) => "Acesta este ID-ul meu de verificare: ${verificationID} pentru ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Poți confirma că acesta este ID-ul tău de verificare ente.io: ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Codul de recomandare Ente: ${referralCode}\n\nAplică-l în Setări → General → Recomandări pentru a obține ${referralStorageInGB} GB gratuit după ce te înscrii pentru un plan plătit\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Distribuiți cu anumite persoane', one: 'Distribuit cu o persoană', other: 'Distribuit cu ${numberOfPeople} de persoane')}"; - static String m57(emailIDs) => "Distribuit cu ${emailIDs}"; - - static String m58(fileType) => - "Fișierul de tip ${fileType} va fi șters din dispozitivul dvs."; + static String m58(emailIDs) => "Distribuit cu ${emailIDs}"; static String m59(fileType) => - "Fișierul de tip ${fileType} este atât în Ente, cât și în dispozitivul dvs."; + "Fișierul de tip ${fileType} va fi șters din dispozitivul dvs."; static String m60(fileType) => + "Fișierul de tip ${fileType} este atât în Ente, cât și în dispozitivul dvs."; + + static String m61(fileType) => "Fișierul de tip ${fileType} va fi șters din Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m63(id) => "${id} este deja legat la un alt cont Ente.\nDacă doriți să folosiți ${id} cu acest cont, vă rugăm să contactați asistența noastră"; @@ -175,7 +189,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Verificare ${email}"; - static String m1(email) => "Am trimis un e-mail la ${email}"; + static String m2(email) => "Am trimis un e-mail la ${email}"; static String m72(count) => "${Intl.plural(count, one: 'acum ${count} an', few: 'acum ${count} ani', other: 'acum ${count} de ani')}"; @@ -198,14 +212,14 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Adăugați un e-mail nou"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Adăugare colaborator"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Adăugare locație"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Adăugare"), "addMore": MessageLookupByLibrary.simpleMessage("Adăugați mai mulți"), "addNew": MessageLookupByLibrary.simpleMessage("Adăugare nou"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Detaliile suplimentelor"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Suplimente"), "addToAlbum": MessageLookupByLibrary.simpleMessage("Adăugare la album"), "addToEnte": MessageLookupByLibrary.simpleMessage("Adăugare la Ente"), @@ -213,12 +227,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Adăugați la album ascuns"), "addViewer": MessageLookupByLibrary.simpleMessage("Adăugare observator"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage( "Adăugați-vă fotografiile acum"), "addedAs": MessageLookupByLibrary.simpleMessage("Adăugat ca"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Se adaugă la favorite..."), "advanced": MessageLookupByLibrary.simpleMessage("Avansat"), @@ -229,12 +243,14 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("După o săptămâna"), "after1Year": MessageLookupByLibrary.simpleMessage("După un an"), "albumOwner": MessageLookupByLibrary.simpleMessage("Proprietar"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Titlu album"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Album actualizat"), "albums": MessageLookupByLibrary.simpleMessage("Albume"), "allClear": MessageLookupByLibrary.simpleMessage("✨ Totul e curat"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Permiteți persoanelor care au linkul să adauge și fotografii la albumul distribuit."), "allowAddingPhotos": MessageLookupByLibrary.simpleMessage( @@ -267,6 +283,9 @@ class MessageLookup extends MessageLookupByLibrary { "Sunteți sigur că doriți să vă deconectați?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Sunteți sigur că doriți să reînnoiți?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Abonamentul dvs. a fost anulat. Doriți să ne comunicați motivul?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -293,8 +312,17 @@ class MessageLookup extends MessageLookupByLibrary { "Vă rugăm să vă autentificați pentru a vedea sesiunile active"), "authToViewYourHiddenFiles": MessageLookupByLibrary.simpleMessage( "Vă rugăm să vă autentificați pentru a vedea fișierele ascunse"), + "authToViewYourMemories": MessageLookupByLibrary.simpleMessage( + "Vă rugăm să vă autentificați pentru a vă vizualiza amintirile"), "authToViewYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Vă rugăm să vă autentificați pentru a vedea cheia de recuperare"), + "authenticating": + MessageLookupByLibrary.simpleMessage("Autentificare..."), + "authenticationFailedPleaseTryAgain": + MessageLookupByLibrary.simpleMessage( + "Autentificare eșuată, încercați din nou"), + "authenticationSuccessful": + MessageLookupByLibrary.simpleMessage("Autentificare cu succes!"), "autoLogoutMessage": MessageLookupByLibrary.simpleMessage( "Din cauza unei probleme tehnice, ați fost deconectat. Ne cerem scuze pentru neplăcerile create."), "available": MessageLookupByLibrary.simpleMessage("Disponibil"), @@ -328,10 +356,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Puteți elimina numai fișierele deținute de dvs."), "cancel": MessageLookupByLibrary.simpleMessage("Anulare"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Anulare abonament"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Nu se pot șterge fișierele distribuite"), "centerPoint": MessageLookupByLibrary.simpleMessage("Punctul central"), @@ -360,7 +388,7 @@ class MessageLookup extends MessageLookupByLibrary { "claimMore": MessageLookupByLibrary.simpleMessage("Revendicați mai multe!"), "claimed": MessageLookupByLibrary.simpleMessage("Revendicat"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Curățare Necategorisite"), "clearCaches": @@ -387,7 +415,7 @@ class MessageLookup extends MessageLookupByLibrary { "Creați un link pentru a permite oamenilor să adauge și să vizualizeze fotografii în albumul dvs. distribuit, fără a avea nevoie de o aplicație sau un cont Ente. Excelent pentru colectarea fotografiilor de la evenimente."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Link colaborativ"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Colaborator"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -415,10 +443,10 @@ class MessageLookup extends MessageLookupByLibrary { "Confirmați cheia de recuperare"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Confirmați cheia de recuperare"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage( "Contactați serviciul de asistență"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Contacte"), "contents": MessageLookupByLibrary.simpleMessage("Conținuturi"), "continueLabel": MessageLookupByLibrary.simpleMessage("Continuare"), @@ -459,6 +487,8 @@ class MessageLookup extends MessageLookupByLibrary { "custom": MessageLookupByLibrary.simpleMessage("Particularizat"), "darkTheme": MessageLookupByLibrary.simpleMessage("Întunecată"), "decrypting": MessageLookupByLibrary.simpleMessage("Se decriptează..."), + "decryptingVideo": MessageLookupByLibrary.simpleMessage( + "Se decriptează videoclipul..."), "deduplicateFiles": MessageLookupByLibrary.simpleMessage("Elim. dubluri fișiere"), "delete": MessageLookupByLibrary.simpleMessage("Ștergere"), @@ -487,12 +517,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ștergeți de pe dispozitiv"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Ștergeți din Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Ștergeți locația"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Ștergeți fotografiile"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Lipsește o funcție cheie de care am nevoie"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -523,7 +553,7 @@ class MessageLookup extends MessageLookupByLibrary { "Observatorii pot să facă capturi de ecran sau să salveze o copie a fotografiilor dvs. folosind instrumente externe"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Rețineți"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Dezactivați al doilea factor"), "discord": MessageLookupByLibrary.simpleMessage("Discord"), @@ -559,9 +589,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Descărcarea nu a reușit"), "downloading": MessageLookupByLibrary.simpleMessage("Se descarcă..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Editare"), "editLocation": MessageLookupByLibrary.simpleMessage("Editare locaţie"), "editsSaved": MessageLookupByLibrary.simpleMessage("Editări salvate"), @@ -570,7 +600,7 @@ class MessageLookup extends MessageLookupByLibrary { "Editările locației vor fi vizibile doar pe Ente"), "eligible": MessageLookupByLibrary.simpleMessage("eligibil"), "email": MessageLookupByLibrary.simpleMessage("E-mail"), - "emailNoEnteAccount": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage( "Verificarea adresei de e-mail"), "emailYourLogs": MessageLookupByLibrary.simpleMessage( @@ -660,6 +690,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Tipuri de fișiere"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage( "Tipuri de fișiere și denumiri"), + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesSavedToGallery": MessageLookupByLibrary.simpleMessage("Fișiere salvate în galerie"), "flip": MessageLookupByLibrary.simpleMessage("Răsturnare"), @@ -669,22 +701,26 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Am uitat parola"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Spațiu gratuit revendicat"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Spațiu gratuit utilizabil"), "freeTrial": MessageLookupByLibrary.simpleMessage( "Perioadă de încercare gratuită"), - "freeTrialValidTill": m32, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Eliberați spațiu pe dispozitiv"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Economisiți spațiu pe dispozitivul dvs. prin ștergerea fișierelor cărora li s-a făcut copie de rezervă."), + "freeUpSpace": MessageLookupByLibrary.simpleMessage("Eliberați spațiu"), + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Până la 1000 de amintiri afișate în galerie"), "general": MessageLookupByLibrary.simpleMessage("General"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Se generează cheile de criptare..."), - "genericProgress": m36, + "genericProgress": m37, "googlePlayId": MessageLookupByLibrary.simpleMessage("ID Google Play"), "grantFullAccessPrompt": MessageLookupByLibrary.simpleMessage( "Vă rugăm să permiteți accesul la toate fotografiile în aplicația Setări"), @@ -707,8 +743,11 @@ class MessageLookup extends MessageLookupByLibrary { "ignoredFolderUploadReason": MessageLookupByLibrary.simpleMessage( "Unele fișiere din acest album sunt excluse de la încărcare deoarece au fost șterse anterior din Ente."), "importing": MessageLookupByLibrary.simpleMessage("Se importă...."), + "incorrectCode": MessageLookupByLibrary.simpleMessage("Cod incorect"), "incorrectPasswordTitle": MessageLookupByLibrary.simpleMessage("Parolă incorectă"), + "incorrectRecoveryKey": MessageLookupByLibrary.simpleMessage( + "Cheie de recuperare incorectă"), "incorrectRecoveryKeyBody": MessageLookupByLibrary.simpleMessage( "Cheia de recuperare introdusă este incorectă"), "incorrectRecoveryKeyTitle": MessageLookupByLibrary.simpleMessage( @@ -734,7 +773,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Se pare că ceva nu a mers bine. Vă rugăm să încercați din nou după ceva timp. Dacă eroarea persistă, vă rugăm să contactați echipa noastră de asistență."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Articolele afișează numărul de zile rămase până la ștergerea definitivă"), @@ -762,7 +801,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Limită de dispozitive"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Activat"), "linkExpired": MessageLookupByLibrary.simpleMessage("Expirat"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Expirarea linkului"), "linkHasExpired": @@ -808,6 +847,9 @@ class MessageLookup extends MessageLookupByLibrary { "logout": MessageLookupByLibrary.simpleMessage("Deconectare"), "logsDialogBody": MessageLookupByLibrary.simpleMessage( "Aceasta va trimite jurnalele pentru a ne ajuta să depistăm problema. Vă rugăm să rețineți că numele fișierelor vor fi incluse pentru a ne ajuta să urmărim problemele cu anumite fișiere."), + "longpressOnAnItemToViewInFullscreen": + MessageLookupByLibrary.simpleMessage( + "Apăsați lung pe un articol pentru a-l vizualiza pe tot ecranul"), "lostDevice": MessageLookupByLibrary.simpleMessage("Dispozitiv pierdut?"), "machineLearning": @@ -825,7 +867,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Gestionare abonament"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Produse"), "mlConsent": MessageLookupByLibrary.simpleMessage("Activați învățarea automată"), @@ -849,11 +891,11 @@ class MessageLookup extends MessageLookupByLibrary { "monthly": MessageLookupByLibrary.simpleMessage("Lunar"), "moreDetails": MessageLookupByLibrary.simpleMessage("Mai multe detalii"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Mutare în album"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Mutați în albumul ascuns"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("S-a mutat în coșul de gunoi"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -888,7 +930,7 @@ class MessageLookup extends MessageLookupByLibrary { "noResults": MessageLookupByLibrary.simpleMessage("Niciun rezultat"), "noResultsFound": MessageLookupByLibrary.simpleMessage("Nu s-au găsit rezultate"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingToSeeHere": MessageLookupByLibrary.simpleMessage("Nimic de văzut aici! 👀"), "notifications": MessageLookupByLibrary.simpleMessage("Notificări"), @@ -896,7 +938,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("Pe dispozitiv"), "onEnte": MessageLookupByLibrary.simpleMessage( "Pe ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Ups"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Hopa, nu s-au putut salva editările"), @@ -924,7 +967,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Plata nu a reușit"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Din păcate, plata dvs. nu a reușit. Vă rugăm să contactați asistență și vom fi bucuroși să vă ajutăm!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Elemente în așteptare"), "pendingSync": @@ -947,7 +990,7 @@ class MessageLookup extends MessageLookupByLibrary { "Fotografiile adăugate de dvs. vor fi eliminate din album"), "pickCenterPoint": MessageLookupByLibrary.simpleMessage("Alegeți punctul central"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Abonament PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -960,7 +1003,7 @@ class MessageLookup extends MessageLookupByLibrary { "Vă rugăm să acordați permisiuni"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage( "Vă rugăm, autentificați-vă din nou"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Vă rugăm să încercați din nou"), "pleaseWait": @@ -995,7 +1038,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Evaluați aplicația"), "rateUs": MessageLookupByLibrary.simpleMessage("Evaluați-ne"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Recuperare"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Recuperare cont"), @@ -1027,7 +1070,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Dați acest cod prietenilor"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Aceștia se înscriu la un plan cu plată"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Recomandări"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Recomandările sunt momentan întrerupte"), @@ -1055,7 +1098,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Eliminați linkul"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Eliminați participantul"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePublicLink": MessageLookupByLibrary.simpleMessage("Eliminați linkul public"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1068,7 +1111,7 @@ class MessageLookup extends MessageLookupByLibrary { "renameAlbum": MessageLookupByLibrary.simpleMessage("Redenumire album"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Reînnoire abonament"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Raportați o eroare"), "reportBug": MessageLookupByLibrary.simpleMessage("Raportare eroare"), @@ -1078,6 +1121,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Resetare fișiere ignorate"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Resetați parola"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage( "Resetare la valori implicite"), "restore": MessageLookupByLibrary.simpleMessage("Restaurare"), @@ -1139,7 +1183,7 @@ class MessageLookup extends MessageLookupByLibrary { "Grupare fotografii realizate în raza unei fotografii"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Invitați persoane și veți vedea aici toate fotografiile distribuite de acestea"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Securitate"), "selectALocation": MessageLookupByLibrary.simpleMessage("Selectați o locație"), @@ -1163,8 +1207,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Articolele selectate vor fi șterse din toate albumele și mutate în coșul de gunoi."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Trimitere"), "sendEmail": MessageLookupByLibrary.simpleMessage("Trimiteți e-mail"), "sendInvite": @@ -1187,16 +1231,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Distribuiți un album acum"), "shareLink": MessageLookupByLibrary.simpleMessage("Distribuiți linkul"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Distribuiți numai cu persoanele pe care le doriți"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Descarcă Ente pentru a putea distribui cu ușurință fotografii și videoclipuri în calitate originală\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Distribuiți cu utilizatori din afara Ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Distribuiți primul album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1209,7 +1253,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Fotografii partajate noi"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Primiți notificări atunci când cineva adaugă o fotografie la un album distribuit din care faceți parte"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Distribuit mie"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("Distribuite cu dvs."), @@ -1224,11 +1268,11 @@ class MessageLookup extends MessageLookupByLibrary { "Deconectați alte dispozitive"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Sunt de acord cu termenii de prestare ai serviciului și politica de confidențialitate"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Acesta va fi șters din toate albumele."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Omiteți"), "social": MessageLookupByLibrary.simpleMessage("Rețele socializare"), "someItemsAreInBothEnteAndYourDevice": @@ -1260,7 +1304,7 @@ class MessageLookup extends MessageLookupByLibrary { "startBackup": MessageLookupByLibrary.simpleMessage("Începeți copia de rezervă"), "status": MessageLookupByLibrary.simpleMessage("Status"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Limita de spațiu depășită"), "strongStrength": MessageLookupByLibrary.simpleMessage("Puternică"), @@ -1295,6 +1339,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Mulțumim pentru abonare!"), "theDownloadCouldNotBeCompleted": MessageLookupByLibrary.simpleMessage( "Descărcarea nu a putut fi finalizată"), + "theRecoveryKeyYouEnteredIsIncorrect": + MessageLookupByLibrary.simpleMessage( + "Cheia de recuperare introdusă este incorectă"), "theme": MessageLookupByLibrary.simpleMessage("Temă"), "theseItemsWillBeDeletedFromYourDevice": MessageLookupByLibrary.simpleMessage( @@ -1309,6 +1356,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Aceasta poate fi utilizată pentru a vă recupera contul în cazul în care pierdeți al doilea factor"), "thisDevice": MessageLookupByLibrary.simpleMessage("Acest dispozitiv"), + "thisEmailIsAlreadyInUse": MessageLookupByLibrary.simpleMessage( + "Această adresă de e-mail este deja folosită"), "thisImageHasNoExifData": MessageLookupByLibrary.simpleMessage( "Această imagine nu are date exif"), "thisIsPersonVerificationId": m67, @@ -1352,6 +1401,7 @@ class MessageLookup extends MessageLookupByLibrary { "unhiding": MessageLookupByLibrary.simpleMessage("Se reafișează..."), "unhidingFilesToAlbum": MessageLookupByLibrary.simpleMessage( "Se reafișează fișierele în album"), + "unlock": MessageLookupByLibrary.simpleMessage("Deblocare"), "unselectAll": MessageLookupByLibrary.simpleMessage("Deselectare totală"), "update": MessageLookupByLibrary.simpleMessage("Actualizare"), @@ -1375,6 +1425,9 @@ class MessageLookup extends MessageLookupByLibrary { "useSelectedPhoto": MessageLookupByLibrary.simpleMessage( "Folosiți fotografia selectată"), "validTill": m70, + "verificationFailedPleaseTryAgain": + MessageLookupByLibrary.simpleMessage( + "Verificare eșuată, încercați din nou"), "verificationId": MessageLookupByLibrary.simpleMessage("ID de verificare"), "verify": MessageLookupByLibrary.simpleMessage("Verificare"), @@ -1409,7 +1462,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Nu se acceptă editarea fotografiilor sau albumelor pe care nu le dețineți încă"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Slabă"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Bine ați revenit!"), @@ -1426,6 +1479,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("Da, mă deconectez"), "yesRemove": MessageLookupByLibrary.simpleMessage("Da, elimină"), "yesRenew": MessageLookupByLibrary.simpleMessage("Da, reînnoiește"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Dvs."), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage( "Sunteți pe un plan de familie!"), diff --git a/mobile/lib/generated/intl/messages_ru.dart b/mobile/lib/generated/intl/messages_ru.dart index e4f26a0e71..33b615966b 100644 --- a/mobile/lib/generated/intl/messages_ru.dart +++ b/mobile/lib/generated/intl/messages_ru.dart @@ -20,168 +20,168 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ru'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, one: 'Добавьте соавтора', few: 'Добавьте соавторов', many: 'Добавьте соавторов', other: 'Добавьте соавторов')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Добавить элемент', other: 'Добавить элементы')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Ваше дополнение ${storageAmount} действительно по ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, one: 'Добавьте зрителя', few: 'Добавьте зрителей', many: 'Добавьте зрителей', other: 'Добавьте зрителей')}"; - static String m9(emailOrName) => "Добавлено ${emailOrName}"; + static String m10(emailOrName) => "Добавлено ${emailOrName}"; - static String m10(albumName) => "Успешно добавлено в ${albumName}"; + static String m11(albumName) => "Успешно добавлено в ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Нет Участников', one: '1 Участник', other: '${count} Участника')}"; - static String m12(versionValue) => "Версия: ${versionValue}"; + static String m13(versionValue) => "Версия: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} свободно"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Пожалуйста, сначала отмените вашу существующую подписку от ${paymentProvider}"; - static String m15(user) => + static String m16(user) => "${user} больше не сможет добавлять фотографии в этот альбом\n\nОни все еще смогут удалять существующие фотографии, добавленные ими"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Ваша семья получила ${storageAmountInGb} ГБ', 'false': 'Вы уже получили ${storageAmountInGb} ГБ', 'other': 'Вы уже получили ${storageAmountInGb} ГБ!', })}"; - static String m17(albumName) => "Совместная ссылка создана для ${albumName}"; + static String m18(albumName) => "Совместная ссылка создана для ${albumName}"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Пожалуйста, свяжитесь с ${familyAdminEmail} для управления подпиской"; - static String m19(provider) => + static String m20(provider) => "Пожалуйста, свяжитесь с нами по адресу support@ente.io для управления подпиской ${provider}."; - static String m20(endpoint) => "Подключено к ${endpoint}"; + static String m21(endpoint) => "Подключено к ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Удалена ${count} штука', other: 'Удалено ${count} штук')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Удаление ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Это удалит публичную ссылку для доступа к \"${albumName}\"."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Пожалуйста, отправьте электронное письмо на адрес ${supportEmail} с вашего зарегистрированного адреса электронной почты"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Вы привели себя в порядок ${Intl.plural(count, one: '${count} duplicate file', other: '${count} duplicate files')}, экономия (${storageSaved}!)\n"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} файлов, ${formattedSize}"; - static String m27(newEmail) => + static String m28(newEmail) => "Адрес электронной почты изменен на ${newEmail}"; - static String m28(email) => + static String m29(email) => "У ${email} нет учетной записи Ente.\n\nОтправьте им приглашение для обмена фотографиями."; - static String m29(count, formattedNumber) => - "${Intl.plural(count, one: 'для 1 файла было создан бекап', other: 'для ${formattedNumber} файлов были созданы бекапы')}"; - static String m30(count, formattedNumber) => "${Intl.plural(count, one: 'для 1 файла было создан бекап', other: 'для ${formattedNumber} файлов были созданы бекапы')}"; - static String m31(storageAmountInGB) => + static String m31(count, formattedNumber) => + "${Intl.plural(count, one: 'для 1 файла было создан бекап', other: 'для ${formattedNumber} файлов были созданы бекапы')}"; + + static String m32(storageAmountInGB) => "${storageAmountInGB} Гигабайт каждый раз когда кто-то подписывается на платный план и применяет ваш код"; - static String m32(endDate) => + static String m33(endDate) => "Бесплатная пробная версия действительна до ${endDate}"; - static String m33(count) => + static String m34(count) => "Вы все еще можете получить доступ к ${Intl.plural(count, one: 'ниму', other: 'ним')} на Ente, пока у вас есть активная подписка"; - static String m34(sizeInMBorGB) => "Освободите ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "Освободите ${sizeInMBorGB}"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'Это можно удалить с устройства, чтобы освободить ${formattedSize}', other: 'Их можно удалить с устройства, чтобы освободить ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Обработка ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} штука', other: '${count} штук')}"; - static String m38(expiryTime) => "Ссылка истечёт через ${expiryTime}"; + static String m39(expiryTime) => "Ссылка истечёт через ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'нет воспоминаний', one: '${formattedCount} воспоминание', other: '${formattedCount} воспоминаний')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Переместить элемент', other: 'Переместить элементы')}"; - static String m40(albumName) => "Успешно перемещено в ${albumName}"; + static String m41(albumName) => "Успешно перемещено в ${albumName}"; - static String m41(name) => "Не ${name}?"; + static String m42(name) => "Не ${name}?"; static String m0(passwordStrengthValue) => "Мощность пароля: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Если с вас сняли оплату, обратитесь в службу поддержки ${providerName}"; - static String m44(endDate) => + static String m45(endDate) => "Бесплатный пробный период до ${endDate}.\nПосле, вы сможете выбрать платный план."; - static String m45(toEmail) => "Пожалуйста, напишите нам на ${toEmail}"; + static String m46(toEmail) => "Пожалуйста, напишите нам на ${toEmail}"; - static String m46(toEmail) => "Пожалуйста, отправьте логи на \n${toEmail}"; + static String m47(toEmail) => "Пожалуйста, отправьте логи на \n${toEmail}"; - static String m48(storeName) => "Оцените нас в ${storeName}"; + static String m49(storeName) => "Оцените нас в ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Вы оба получаете ${storageInGB} Гигабайт* бесплатно"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} будет удален из этого общего альбома\n\nВсе добавленные им фотографии также будут удалены из альбома"; - static String m51(endDate) => "Обновление подписки на ${endDate}"; + static String m52(endDate) => "Обновление подписки на ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} результат найден', other: '${count} результатов найдено')}"; - static String m3(count) => "${count} выбрано"; + static String m4(count) => "${count} выбрано"; - static String m53(count, yourCount) => "${count} выбрано (${yourCount} ваши)"; + static String m54(count, yourCount) => "${count} выбрано (${yourCount} ваши)"; - static String m54(verificationID) => + static String m55(verificationID) => "Вот мой проверочный ID: ${verificationID} для ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Эй, вы можете подтвердить, что это ваш идентификатор подтверждения ente.io: ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Реферальный код Ente: ${referralCode} \n\nПримените его в разделе «Настройки» → «Основные» → «Рефералы», чтобы получить ${referralStorageInGB} Гигабайт бесплатно после того как вы подпишетесь на платный план"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Поделится с конкретными людьми', one: 'Поделено с 1 человеком', other: 'Поделено с ${numberOfPeople} людьми')}"; - static String m57(emailIDs) => "Поделиться с ${emailIDs}"; - - static String m58(fileType) => - "Это ${fileType} будет удалено с вашего устройства."; + static String m58(emailIDs) => "Поделиться с ${emailIDs}"; static String m59(fileType) => + "Это ${fileType} будет удалено с вашего устройства."; + + static String m60(fileType) => "Этот ${fileType} есть и в Ente, и на вашем устройстве."; - static String m60(fileType) => "Этот ${fileType} будет удалён из Ente."; + static String m61(fileType) => "Этот ${fileType} будет удалён из Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} Гигабайт"; + static String m1(storageAmountInGB) => "${storageAmountInGB} Гигабайт"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -207,7 +207,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Подтвердить ${email}"; - static String m1(email) => "Мы отправили письмо на ${email}"; + static String m2(email) => "Мы отправили письмо на ${email}"; static String m72(count) => "${Intl.plural(count, one: '${count} год назад', other: '${count} лет назад')}"; @@ -231,17 +231,17 @@ class MessageLookup extends MessageLookupByLibrary { "Добавить новый адрес эл. почты"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Добавить соавтора"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Добавить с устройства"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Добавить место"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Добавить"), "addMore": MessageLookupByLibrary.simpleMessage("Добавить еще"), "addNew": MessageLookupByLibrary.simpleMessage("Добавить новое"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Подробнее о расширениях"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Расширения"), "addPhotos": MessageLookupByLibrary.simpleMessage("Добавить фотографии"), @@ -253,12 +253,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Добавить в скрытый альбом"), "addViewer": MessageLookupByLibrary.simpleMessage("Добавить наблюдателя"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Добавьте ваши фотографии"), "addedAs": MessageLookupByLibrary.simpleMessage("Добавлено как"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Добавление в избранное..."), "advanced": MessageLookupByLibrary.simpleMessage("Дополнительно"), @@ -270,13 +270,15 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Через неделю"), "after1Year": MessageLookupByLibrary.simpleMessage("Через 1 год"), "albumOwner": MessageLookupByLibrary.simpleMessage("Владелец"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Название альбома"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Альбом обновлен"), "albums": MessageLookupByLibrary.simpleMessage("Альбомы"), "allClear": MessageLookupByLibrary.simpleMessage("✨ Все чисто"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("Все воспоминания сохранены"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Разрешить пользователям со ссылкой также добавлять фотографии в общий альбом."), "allowAddingPhotos": @@ -308,7 +310,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Требуется аутентификация"), "appLock": MessageLookupByLibrary.simpleMessage("Блокировка приложения"), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Применить"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Применить код"), @@ -332,6 +334,9 @@ class MessageLookup extends MessageLookupByLibrary { "Вы уверены, что хотите выйти?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Вы уверены, что хотите продлить?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Ваша подписка была отменена. Хотите рассказать почему?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -382,7 +387,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "Автоматическое подключение работает только с устройствами, поддерживающими Chromecast."), "available": MessageLookupByLibrary.simpleMessage("Доступно"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Резервное копирование папок"), "backup": MessageLookupByLibrary.simpleMessage("Резервное копирование"), @@ -409,10 +414,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Можно удалять только файлы, принадлежащие вам"), "cancel": MessageLookupByLibrary.simpleMessage("Отменить"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Отменить подписку"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Невозможно удалить общие файлы"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -446,7 +451,7 @@ class MessageLookup extends MessageLookupByLibrary { "Получить бесплатное хранилище"), "claimMore": MessageLookupByLibrary.simpleMessage("Получите больше!"), "claimed": MessageLookupByLibrary.simpleMessage("Получено"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Очистить \"Без Категории\""), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -474,7 +479,7 @@ class MessageLookup extends MessageLookupByLibrary { "Создайте ссылку, чтобы позволить людям добавлять и просматривать фотографии в вашем общем альбоме без приложения или учетной записи Ente. Отлично подходит для сбора фотографий событий."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Совместная ссылка"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Соавтор"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -504,10 +509,10 @@ class MessageLookup extends MessageLookupByLibrary { "Подтвердите ваш ключ восстановления"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Подключиться к устройству"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Связаться с поддержкой"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Контакты"), "contents": MessageLookupByLibrary.simpleMessage("Содержимое"), "continueLabel": MessageLookupByLibrary.simpleMessage("Далее"), @@ -552,7 +557,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("Текущее использование "), "custom": MessageLookupByLibrary.simpleMessage("Свой"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Темная тема"), "dayToday": MessageLookupByLibrary.simpleMessage("Сегодня"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Вчера"), @@ -588,11 +593,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Удалить с устройства"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Удалить из Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Удалить местоположение"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Удалить фото"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "У вас отсутствует важная функция, которая мне нужна"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -632,7 +637,7 @@ class MessageLookup extends MessageLookupByLibrary { "Наблюдатели все еще могут делать скриншоты или копировать ваши фотографии с помощью других инструментов"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Обратите внимание"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Отключить двухфакторную аутентификацию"), "disablingTwofactorAuthentication": @@ -653,9 +658,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Загрузка не удалась"), "downloading": MessageLookupByLibrary.simpleMessage("Скачивание..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Редактировать"), "editLocation": MessageLookupByLibrary.simpleMessage("Изменить местоположение"), @@ -668,8 +673,8 @@ class MessageLookup extends MessageLookupByLibrary { "Редактирования в местоположении будут видны только внутри Ente"), "eligible": MessageLookupByLibrary.simpleMessage("подходящий"), "email": MessageLookupByLibrary.simpleMessage("Электронная почта"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Вход с кодом на почту"), "emailYourLogs": MessageLookupByLibrary.simpleMessage( @@ -777,8 +782,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Типы файлов"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Типы файлов и имена"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Файлы удалены"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage("Файлы сохранены в галерею"), @@ -791,26 +796,26 @@ class MessageLookup extends MessageLookupByLibrary { "foundFaces": MessageLookupByLibrary.simpleMessage("Найденные лица"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage( "Бесплатного хранилища получено"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage( "Бесплатного хранилища можно использовать"), "freeTrial": MessageLookupByLibrary.simpleMessage("Бесплатный пробный период"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage( "Освободите место на устройстве"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Сохраните место на вашем устройстве, очистив уже сохраненные файлы."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Освободить место"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "До 1000 воспоминаний, отображаемых в галерее"), "general": MessageLookupByLibrary.simpleMessage("Общее"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Генерируем ключи шифрования..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Перейти в настройки"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), @@ -889,7 +894,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Похоже, что-то пошло не так. Пожалуйста, повторите попытку через некоторое время. Если ошибка повторится, обратитесь в нашу службу поддержки."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Элементы показывают количество дней, оставшихся до окончательного удаления"), @@ -918,7 +923,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Лимит устройств"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Разрешён"), "linkExpired": MessageLookupByLibrary.simpleMessage("Истекшая"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Срок действия ссылки истек"), "linkHasExpired": @@ -1001,7 +1006,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Карты"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Товары"), "mlConsent": MessageLookupByLibrary.simpleMessage("Включить машинное обучение"), @@ -1024,12 +1029,12 @@ class MessageLookup extends MessageLookupByLibrary { "moments": MessageLookupByLibrary.simpleMessage("Мгновения"), "monthly": MessageLookupByLibrary.simpleMessage("Ежемесячно"), "moreDetails": MessageLookupByLibrary.simpleMessage("Подробнее"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Переместить в альбом"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Переместить в скрытый альбом"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Перемещено в корзину"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -1078,7 +1083,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ничего не найдено"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage( "Системная блокировка не найдена"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage( "Пока никто не поделился с вами"), "nothingToSeeHere": @@ -1088,6 +1093,7 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("На устройстве"), "onEnte": MessageLookupByLibrary.simpleMessage("В ente"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Ой"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "К сожалению, изменения не сохранены"), @@ -1128,7 +1134,7 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("Сбой платежа"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "К сожалению, ваш платеж не был выполнен. Пожалуйста, свяжитесь со службой поддержки, и мы вам поможем!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Отложенные элементы"), "pendingSync": @@ -1157,7 +1163,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinLock": MessageLookupByLibrary.simpleMessage("Блокировка PIN-кодом"), "playOnTv": MessageLookupByLibrary.simpleMessage("Воспроизвести альбом на ТВ"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("Подписка на PlayStore"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1169,14 +1175,14 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Если проблема не устранена, обратитесь в службу поддержки"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Предоставьте разрешение"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Пожалуйста, войдите снова"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Пожалуйста, выберите быстрые ссылки для удаления"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Пожалуйста, попробуйте ещё раз"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1213,7 +1219,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Оценить приложение"), "rateUs": MessageLookupByLibrary.simpleMessage("Оцените нас"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Восстановить"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Восстановить аккаунт"), @@ -1247,7 +1253,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Дайте этот код своим друзьям"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Они подписываются на платный план"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Рефералы"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Рефералы в настоящее время приостановлены"), @@ -1274,7 +1280,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Удалить ссылку"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Исключить участника"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("Удалить метку человека"), "removePublicLink": @@ -1294,7 +1300,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Переименовать файл"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Продлить подписку"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Сообщить об ошибке"), "reportBug": MessageLookupByLibrary.simpleMessage("Сообщить об ошибке"), @@ -1304,6 +1310,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Сбросить игнорируемые файлы"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Сбросить пароль"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("Сброс по умолчанию"), "restore": MessageLookupByLibrary.simpleMessage("Восстановить"), @@ -1366,7 +1373,7 @@ class MessageLookup extends MessageLookupByLibrary { "Групповые фотографии, сделанные в некотором радиусе от фотографии"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Пригласите людей, и вы увидите все фотографии, которыми они поделились здесь"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Безопасность"), "selectALocation": MessageLookupByLibrary.simpleMessage("Выбрать место"), @@ -1392,8 +1399,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Выбранные элементы будут удалены из всех альбомов и перемещены в корзину."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Отправить"), "sendEmail": MessageLookupByLibrary.simpleMessage( "Отправить электронное письмо"), @@ -1426,16 +1433,16 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Поделиться альбомом сейчас"), "shareLink": MessageLookupByLibrary.simpleMessage("Поделиться ссылкой"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Поделитесь только с теми людьми, с которыми вы хотите"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Скачай Ente, чтобы мы могли легко поделиться фотографиями и видео без сжатия\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Поделится с пользователями без Ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Поделиться первым альбомом"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1446,7 +1453,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Новые общие фотографии"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Получать уведомления, когда кто-то добавляет фото в общий альбом, в котором вы состоите"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Поделиться со мной"), "sharedWithYou": @@ -1462,11 +1469,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Выйти из других устройств"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Я согласен с условиями предоставления услуг и политикой конфиденциальности"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Он будет удален из всех альбомов."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Пропустить"), "social": MessageLookupByLibrary.simpleMessage("Соцсети"), "someItemsAreInBothEnteAndYourDevice": MessageLookupByLibrary.simpleMessage( @@ -1510,7 +1517,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Хранилище"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Семья"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Вы"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Превышен предел хранения"), "storageUsageInfo": m62, @@ -1701,7 +1708,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Мы не можем поддержать редактирование фотографий и альбомов, которыми вы не владеете"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Слабый"), "welcomeBack": MessageLookupByLibrary.simpleMessage("С возвращением!"), "whatsNew": MessageLookupByLibrary.simpleMessage("Что нового"), @@ -1717,6 +1724,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("Да, выйти"), "yesRemove": MessageLookupByLibrary.simpleMessage("Да, удалить"), "yesRenew": MessageLookupByLibrary.simpleMessage("Да, продлить"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Вы"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("Вы на семейном плане!"), diff --git a/mobile/lib/generated/intl/messages_sl.dart b/mobile/lib/generated/intl/messages_sl.dart index d41d848b0f..80617c98a5 100644 --- a/mobile/lib/generated/intl/messages_sl.dart +++ b/mobile/lib/generated/intl/messages_sl.dart @@ -21,5 +21,15 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'sl'; final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => {}; + static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") + }; } diff --git a/mobile/lib/generated/intl/messages_sv.dart b/mobile/lib/generated/intl/messages_sv.dart index e1e658524a..7d68d1410f 100644 --- a/mobile/lib/generated/intl/messages_sv.dart +++ b/mobile/lib/generated/intl/messages_sv.dart @@ -20,60 +20,60 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'sv'; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Lägg till objekt', other: 'Lägg till objekt')}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Inga deltagare', one: '1 deltagare', other: '${count} deltagare')}"; - static String m12(versionValue) => "Version: ${versionValue}"; + static String m13(versionValue) => "Version: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} gratis"; - static String m15(user) => + static String m16(user) => "${user} kommer inte att kunna lägga till fler foton till detta album\n\nDe kommer fortfarande att kunna ta bort befintliga foton som lagts till av dem"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Radera ${count} objekt', other: 'Radera ${count} objekt')}"; - static String m24(supportEmail) => + static String m25(supportEmail) => "Vänligen skicka ett e-postmeddelande till ${supportEmail} från din registrerade e-postadress"; - static String m28(email) => + static String m29(email) => "${email} har inte ett Ente-konto.\n\nSkicka dem en inbjudan för att dela bilder."; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} objekt', other: '${count} objekt')}"; - static String m38(expiryTime) => "Länken upphör att gälla ${expiryTime}"; + static String m39(expiryTime) => "Länken upphör att gälla ${expiryTime}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Flytta objekt', other: 'Flytta objekt')}"; - static String m41(name) => "Inte ${name}?"; + static String m42(name) => "Inte ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Kontakta ${familyAdminEmail} för att ändra din kod."; static String m0(passwordStrengthValue) => "Lösenordsstyrka: ${passwordStrengthValue}"; - static String m48(storeName) => "Betygsätt oss på ${storeName}"; + static String m49(storeName) => "Betygsätt oss på ${storeName}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} resultat hittades', other: '${count} resultat hittades')}"; - static String m54(verificationID) => + static String m55(verificationID) => "Här är mitt verifierings-ID: ${verificationID} för ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Hallå, kan du bekräfta att detta är ditt ente.io verifierings-ID: ${verificationID}"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Dela med specifika personer', one: 'Delad med en person', other: 'Delad med ${numberOfPeople} personer')}"; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m67(email) => "Detta är ${email}s verifierings-ID"; @@ -84,7 +84,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "Bekräfta ${email}"; - static String m1(email) => + static String m2(email) => "Vi har skickat ett e-postmeddelande till ${email}"; static String m72(count) => @@ -102,15 +102,17 @@ class MessageLookup extends MessageLookupByLibrary { "Jag förstår att om jag förlorar mitt lösenord kan jag förlora mina data eftersom min data är end-to-end-krypterad."), "activeSessions": MessageLookupByLibrary.simpleMessage("Aktiva sessioner"), + "add": MessageLookupByLibrary.simpleMessage("Lägg till"), "addANewEmail": MessageLookupByLibrary.simpleMessage( "Lägg till en ny e-postadress"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Lägg till samarbetspartner"), "addFromDevice": MessageLookupByLibrary.simpleMessage("Lägg till från enhet"), - "addItem": m6, + "addItem": m7, "addLocationButton": MessageLookupByLibrary.simpleMessage("Lägg till"), "addMore": MessageLookupByLibrary.simpleMessage("Lägg till fler"), + "addName": MessageLookupByLibrary.simpleMessage("Lägg till namn"), "addPhotos": MessageLookupByLibrary.simpleMessage("Lägg till foton"), "addViewer": MessageLookupByLibrary.simpleMessage("Lägg till bildvy"), "addedAs": MessageLookupByLibrary.simpleMessage("Lades till som"), @@ -120,10 +122,12 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Om en vecka"), "after1Year": MessageLookupByLibrary.simpleMessage("Om ett år"), "albumOwner": MessageLookupByLibrary.simpleMessage("Ägare"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumUpdated": MessageLookupByLibrary.simpleMessage("Album uppdaterat"), "albums": MessageLookupByLibrary.simpleMessage("Album"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Tillåt personer med länken att även lägga till foton i det delade albumet."), "allowAddingPhotos": @@ -131,20 +135,23 @@ class MessageLookup extends MessageLookupByLibrary { "allowDownloads": MessageLookupByLibrary.simpleMessage("Tillåt nedladdningar"), "androidCancelButton": MessageLookupByLibrary.simpleMessage("Avbryt"), - "appVersion": m12, + "appVersion": m13, "apply": MessageLookupByLibrary.simpleMessage("Verkställ"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Använd kod"), "areYouSureYouWantToLogout": MessageLookupByLibrary.simpleMessage( "Är du säker på att du vill logga ut?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Vad är den främsta anledningen till att du raderar ditt konto?"), "authenticationFailedPleaseTryAgain": MessageLookupByLibrary.simpleMessage( "Autentisering misslyckades, försök igen"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "blog": MessageLookupByLibrary.simpleMessage("Blogg"), "cancel": MessageLookupByLibrary.simpleMessage("Avbryt"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "change": MessageLookupByLibrary.simpleMessage("Ändra"), "changeEmail": MessageLookupByLibrary.simpleMessage("Ändra e-postadress"), @@ -215,7 +222,7 @@ class MessageLookup extends MessageLookupByLibrary { "Vänligen skicka ett e-postmeddelande till account-deletion@ente.io från din registrerade e-postadress."), "deleteFromDevice": MessageLookupByLibrary.simpleMessage("Radera från enhet"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deletePhotos": MessageLookupByLibrary.simpleMessage("Radera foton"), "deleteReason1": MessageLookupByLibrary.simpleMessage( "Det saknas en viktig funktion som jag behöver"), @@ -236,10 +243,10 @@ class MessageLookup extends MessageLookupByLibrary { "discover_receipts": MessageLookupByLibrary.simpleMessage("Kvitton"), "doThisLater": MessageLookupByLibrary.simpleMessage("Gör detta senare"), "done": MessageLookupByLibrary.simpleMessage("Klar"), - "dropSupportEmail": m24, + "dropSupportEmail": m25, "edit": MessageLookupByLibrary.simpleMessage("Redigera"), "email": MessageLookupByLibrary.simpleMessage("E-post"), - "emailNoEnteAccount": m28, + "emailNoEnteAccount": m29, "encryption": MessageLookupByLibrary.simpleMessage("Kryptering"), "encryptionKeys": MessageLookupByLibrary.simpleMessage("Krypteringsnycklar"), @@ -314,7 +321,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Bjud in dina vänner"), "inviteYourFriendsToEnte": MessageLookupByLibrary.simpleMessage( "Bjud in dina vänner till Ente"), - "itemCount": m37, + "itemCount": m38, "kiloMeterUnit": MessageLookupByLibrary.simpleMessage("km"), "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage( "Vänligen hjälp oss med denna information"), @@ -324,7 +331,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("Enhetsgräns"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Aktiverat"), "linkExpired": MessageLookupByLibrary.simpleMessage("Upphört"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Länken upphör"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("Länk har upphört att gälla"), @@ -351,7 +358,7 @@ class MessageLookup extends MessageLookupByLibrary { "mlConsentTitle": MessageLookupByLibrary.simpleMessage("Aktivera maskininlärning?"), "moderateStrength": MessageLookupByLibrary.simpleMessage("Måttligt"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Flytta till album"), "movingFilesToAlbum": @@ -359,6 +366,7 @@ class MessageLookup extends MessageLookupByLibrary { "name": MessageLookupByLibrary.simpleMessage("Namn"), "never": MessageLookupByLibrary.simpleMessage("Aldrig"), "newAlbum": MessageLookupByLibrary.simpleMessage("Nytt album"), + "newPerson": MessageLookupByLibrary.simpleMessage("Ny person"), "next": MessageLookupByLibrary.simpleMessage("Nästa"), "no": MessageLookupByLibrary.simpleMessage("Nej"), "noDeviceLimit": MessageLookupByLibrary.simpleMessage("Ingen"), @@ -372,9 +380,10 @@ class MessageLookup extends MessageLookupByLibrary { "noResults": MessageLookupByLibrary.simpleMessage("Inga resultat"), "noResultsFound": MessageLookupByLibrary.simpleMessage("Inga resultat hittades"), - "notPersonLabel": m41, + "notPersonLabel": m42, "ok": MessageLookupByLibrary.simpleMessage("OK"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Hoppsan"), "orPickAnExistingOne": MessageLookupByLibrary.simpleMessage("Eller välj en befintlig"), @@ -398,7 +407,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Integritetspolicy"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("Offentlig länk aktiverad"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Återställ"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Återställ konto"), @@ -432,6 +441,7 @@ class MessageLookup extends MessageLookupByLibrary { "Skicka e-postmeddelandet igen"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Återställ lösenord"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("Återställ till standard"), "retry": MessageLookupByLibrary.simpleMessage("Försök igen"), @@ -452,7 +462,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Albumnamn"), "searchFileTypesAndNamesEmptySection": MessageLookupByLibrary.simpleMessage("Filtyper och namn"), - "searchResultCount": m52, + "searchResultCount": m53, "selectAlbum": MessageLookupByLibrary.simpleMessage("Välj album"), "selectLanguage": MessageLookupByLibrary.simpleMessage("Välj språk"), "selectReason": MessageLookupByLibrary.simpleMessage("Välj anledning"), @@ -469,13 +479,13 @@ class MessageLookup extends MessageLookupByLibrary { "share": MessageLookupByLibrary.simpleMessage("Dela"), "shareALink": MessageLookupByLibrary.simpleMessage("Dela en länk"), "shareLink": MessageLookupByLibrary.simpleMessage("Dela länk"), - "shareMyVerificationID": m54, - "shareTextConfirmOthersVerificationID": m4, + "shareMyVerificationID": m55, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Ladda ner Ente så att vi enkelt kan dela bilder och videor med originell kvalitet\n\nhttps://ente.io"), "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Dela med icke-Ente användare"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("Dela ditt första album"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -500,7 +510,7 @@ class MessageLookup extends MessageLookupByLibrary { "sortAlbumsBy": MessageLookupByLibrary.simpleMessage("Sortera efter"), "status": MessageLookupByLibrary.simpleMessage("Status"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Du"), - "storageInGB": m61, + "storageInGB": m1, "strongStrength": MessageLookupByLibrary.simpleMessage("Starkt"), "subscribe": MessageLookupByLibrary.simpleMessage("Prenumerera"), "subscription": MessageLookupByLibrary.simpleMessage("Prenumeration"), @@ -572,7 +582,7 @@ class MessageLookup extends MessageLookupByLibrary { "viewRecoveryKey": MessageLookupByLibrary.simpleMessage("Visa återställningsnyckel"), "viewer": MessageLookupByLibrary.simpleMessage("Bildvy"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Svagt"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Välkommen tillbaka!"), @@ -585,6 +595,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesDelete": MessageLookupByLibrary.simpleMessage("Ja, radera"), "yesLogout": MessageLookupByLibrary.simpleMessage("Ja, logga ut"), "yesRenew": MessageLookupByLibrary.simpleMessage("Ja, förnya"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Du"), "yourAccountHasBeenDeleted": MessageLookupByLibrary.simpleMessage("Ditt konto har raderats") diff --git a/mobile/lib/generated/intl/messages_ta.dart b/mobile/lib/generated/intl/messages_ta.dart index 30c00c6d72..28211f5d23 100644 --- a/mobile/lib/generated/intl/messages_ta.dart +++ b/mobile/lib/generated/intl/messages_ta.dart @@ -24,6 +24,11 @@ class MessageLookup extends MessageLookupByLibrary { static Map _notInlinedMessages(_) => { "accountWelcomeBack": MessageLookupByLibrary.simpleMessage("மீண்டும் வருக!"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "உங்கள் கணக்கை நீக்குவதற்கான முக்கிய காரணம் என்ன?"), "cancel": MessageLookupByLibrary.simpleMessage("ரத்து செய்"), @@ -48,6 +53,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("தவறான மின்னஞ்சல் முகவரி"), "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage( "இந்த தகவலுடன் தயவுசெய்து எங்களுக்கு உதவுங்கள்"), - "verify": MessageLookupByLibrary.simpleMessage("சரிபார்க்கவும்") + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "verify": MessageLookupByLibrary.simpleMessage("சரிபார்க்கவும்"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") }; } diff --git a/mobile/lib/generated/intl/messages_te.dart b/mobile/lib/generated/intl/messages_te.dart index 5e415c9da0..6656e7fe23 100644 --- a/mobile/lib/generated/intl/messages_te.dart +++ b/mobile/lib/generated/intl/messages_te.dart @@ -21,5 +21,15 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'te'; final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => {}; + static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") + }; } diff --git a/mobile/lib/generated/intl/messages_th.dart b/mobile/lib/generated/intl/messages_th.dart index 4975d05fe0..45750c0928 100644 --- a/mobile/lib/generated/intl/messages_th.dart +++ b/mobile/lib/generated/intl/messages_th.dart @@ -20,25 +20,25 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'th'; - static String m6(count) => "${Intl.plural(count, other: 'เพิ่มรายการ')}"; + static String m7(count) => "${Intl.plural(count, other: 'เพิ่มรายการ')}"; - static String m12(versionValue) => "รุ่น: ${versionValue}"; + static String m13(versionValue) => "รุ่น: ${versionValue}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'ลบ ${count} รายการ', other: 'ลบ ${count} รายการ')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "กำลังลบ ${currentlyDeleting} / ${totalCount}"; - static String m24(supportEmail) => + static String m25(supportEmail) => "กรุณาส่งอีเมลไปที่ ${supportEmail} จากที่อยู่อีเมลที่คุณลงทะเบียนไว้"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "กำลังประมวลผล ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => "${Intl.plural(count, other: '${count} รายการ')}"; + static String m38(count) => "${Intl.plural(count, other: '${count} รายการ')}"; - static String m39(count) => "${Intl.plural(count, other: 'ย้ายรายการ')}"; + static String m40(count) => "${Intl.plural(count, other: 'ย้ายรายการ')}"; static String m0(passwordStrengthValue) => "ความแข็งแรงของรหัสผ่าน: ${passwordStrengthValue}"; @@ -47,7 +47,7 @@ class MessageLookup extends MessageLookupByLibrary { usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => "ใช้ไป ${usedAmount} ${usedStorageUnit} จาก ${totalAmount} ${totalStorageUnit}"; - static String m1(email) => "เราได้ส่งจดหมายไปยัง ${email}"; + static String m2(email) => "เราได้ส่งจดหมายไปยัง ${email}"; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -60,7 +60,7 @@ class MessageLookup extends MessageLookupByLibrary { "addANewEmail": MessageLookupByLibrary.simpleMessage("เพิ่มอีเมลใหม่"), "addCollaborator": MessageLookupByLibrary.simpleMessage("เพิ่มผู้ทำงานร่วมกัน"), - "addItem": m6, + "addItem": m7, "addMore": MessageLookupByLibrary.simpleMessage("เพิ่มอีก"), "addToAlbum": MessageLookupByLibrary.simpleMessage("เพิ่มไปยังอัลบั้ม"), "addViewer": MessageLookupByLibrary.simpleMessage("เพิ่มผู้ชม"), @@ -70,6 +70,8 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("หลังจาก 1 สัปดาห์"), "after1Year": MessageLookupByLibrary.simpleMessage("หลังจาก 1 ปี"), "albumOwner": MessageLookupByLibrary.simpleMessage("เจ้าของ"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddingPhotos": MessageLookupByLibrary.simpleMessage("อนุญาตให้เพิ่มรูปภาพ"), "allowDownloads": @@ -77,8 +79,11 @@ class MessageLookup extends MessageLookupByLibrary { "androidBiometricSuccess": MessageLookupByLibrary.simpleMessage("สำเร็จ"), "androidCancelButton": MessageLookupByLibrary.simpleMessage("ยกเลิก"), - "appVersion": m12, + "appVersion": m13, "apply": MessageLookupByLibrary.simpleMessage("นำไปใช้"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "เหตุผลหลักที่คุณลบบัญชีคืออะไร?"), "authToViewYourRecoveryKey": MessageLookupByLibrary.simpleMessage( @@ -130,8 +135,8 @@ class MessageLookup extends MessageLookupByLibrary { "deleteEmptyAlbumsWithQuestionMark": MessageLookupByLibrary.simpleMessage( "ลบอัลบั้มที่ว่างเปล่าหรือไม่?"), - "deleteItemCount": m21, - "deleteProgress": m22, + "deleteItemCount": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "ขาดคุณสมบัติสำคัญที่ฉันต้องการ"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -143,7 +148,7 @@ class MessageLookup extends MessageLookupByLibrary { "deleteRequestSLAText": MessageLookupByLibrary.simpleMessage( "คำขอของคุณจะได้รับการดำเนินการภายใน 72 ชั่วโมง"), "doThisLater": MessageLookupByLibrary.simpleMessage("ทำในภายหลัง"), - "dropSupportEmail": m24, + "dropSupportEmail": m25, "edit": MessageLookupByLibrary.simpleMessage("แก้ไข"), "editLocationTagTitle": MessageLookupByLibrary.simpleMessage("แก้ไขตำแหน่ง"), @@ -172,7 +177,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("เพิ่มคำอธิบาย..."), "forgotPassword": MessageLookupByLibrary.simpleMessage("ลืมรหัสผ่าน"), "freeTrial": MessageLookupByLibrary.simpleMessage("ทดลองใช้ฟรี"), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("ไปที่การตั้งค่า"), "hide": MessageLookupByLibrary.simpleMessage("ซ่อน"), "hostedAtOsmFrance": @@ -195,7 +200,7 @@ class MessageLookup extends MessageLookupByLibrary { "invalidKey": MessageLookupByLibrary.simpleMessage("รหัสไม่ถูกต้อง"), "invalidRecoveryKey": MessageLookupByLibrary.simpleMessage( "คีย์การกู้คืนที่คุณป้อนไม่ถูกต้อง โปรดตรวจสอบให้แน่ใจว่ามี 24 คำ และตรวจสอบการสะกดของแต่ละคำ\n\nหากคุณป้อนรหัสกู้คืนที่เก่ากว่า ตรวจสอบให้แน่ใจว่ามีความยาว 64 ตัวอักษร และตรวจสอบแต่ละตัวอักษร"), - "itemCount": m37, + "itemCount": m38, "kindlyHelpUsWithThisInformation": MessageLookupByLibrary.simpleMessage("กรุณาช่วยเราด้วยข้อมูลนี้"), "lastUpdated": MessageLookupByLibrary.simpleMessage("อัปเดตล่าสุด"), @@ -213,7 +218,7 @@ class MessageLookup extends MessageLookupByLibrary { "map": MessageLookupByLibrary.simpleMessage("แผนที่"), "maps": MessageLookupByLibrary.simpleMessage("แผนที่"), "moderateStrength": MessageLookupByLibrary.simpleMessage("ปานกลาง"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("ย้ายไปยังอัลบั้ม"), "name": MessageLookupByLibrary.simpleMessage("ชื่อ"), "newest": MessageLookupByLibrary.simpleMessage("ใหม่สุด"), @@ -224,6 +229,7 @@ class MessageLookup extends MessageLookupByLibrary { "ok": MessageLookupByLibrary.simpleMessage("ตกลง"), "onEnte": MessageLookupByLibrary.simpleMessage( "บน ente"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("อ๊ะ"), "oopsSomethingWentWrong": MessageLookupByLibrary.simpleMessage("อ๊ะ มีบางอย่างผิดพลาด"), @@ -274,6 +280,7 @@ class MessageLookup extends MessageLookupByLibrary { "resendEmail": MessageLookupByLibrary.simpleMessage("ส่งอีเมลอีกครั้ง"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("รีเซ็ตรหัสผ่าน"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "restore": MessageLookupByLibrary.simpleMessage(" กู้คืน"), "restoreToAlbum": MessageLookupByLibrary.simpleMessage("กู้คืนไปยังอัลบั้ม"), @@ -347,10 +354,12 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("ดูคีย์การกู้คืน"), "waitingForWifi": MessageLookupByLibrary.simpleMessage("กำลังรอ WiFi..."), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("อ่อน"), "welcomeBack": MessageLookupByLibrary.simpleMessage("ยินดีต้อนรับกลับมา!"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("คุณ"), "youCanManageYourLinksInTheShareTab": MessageLookupByLibrary.simpleMessage( diff --git a/mobile/lib/generated/intl/messages_ti.dart b/mobile/lib/generated/intl/messages_ti.dart index 775cc78213..e8f20bf9a4 100644 --- a/mobile/lib/generated/intl/messages_ti.dart +++ b/mobile/lib/generated/intl/messages_ti.dart @@ -21,5 +21,15 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'ti'; final messages = _notInlinedMessages(_notInlinedMessages); - static Map _notInlinedMessages(_) => {}; + static Map _notInlinedMessages(_) => { + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person") + }; } diff --git a/mobile/lib/generated/intl/messages_tr.dart b/mobile/lib/generated/intl/messages_tr.dart index a3bc65f3e3..e5c9fc41e2 100644 --- a/mobile/lib/generated/intl/messages_tr.dart +++ b/mobile/lib/generated/intl/messages_tr.dart @@ -20,149 +20,149 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'tr'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, zero: 'Ortak çalışan ekle', one: 'Ortak çalışan ekle', other: 'Ortak çalışan ekle')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Öğeyi taşı', other: 'Öğeleri taşı')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "${storageAmount} eklentiniz ${endDate} tarihine kadar geçerlidir"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, zero: 'Görüntüleyen ekle', one: 'Görüntüleyen ekle', other: 'Görüntüleyen ekle')}"; - static String m9(emailOrName) => "${emailOrName} tarafından eklendi"; + static String m10(emailOrName) => "${emailOrName} tarafından eklendi"; - static String m10(albumName) => "${albumName} albümüne başarıyla eklendi"; + static String m11(albumName) => "${albumName} albümüne başarıyla eklendi"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Katılımcı Yok', one: '1 Katılımcı', other: '${count} Katılımcı')}"; - static String m12(versionValue) => "Sürüm: ${versionValue}"; + static String m13(versionValue) => "Sürüm: ${versionValue}"; - static String m14(paymentProvider) => + static String m15(paymentProvider) => "Lütfen önce mevcut aboneliğinizi ${paymentProvider} adresinden iptal edin"; - static String m15(user) => + static String m16(user) => "${user}, bu albüme daha fazla fotoğraf ekleyemeyecek.\n\nAncak, kendi eklediği mevcut fotoğrafları kaldırmaya devam edebilecektir"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Şu ana kadar aileniz ${storageAmountInGb} GB aldı', 'false': 'Şu ana kadar ${storageAmountInGb} GB aldınız', 'other': 'Şu ana kadar ${storageAmountInGb} GB aldınız!', })}"; - static String m17(albumName) => + static String m18(albumName) => "${albumName} için ortak çalışma bağlantısı oluşturuldu"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "Aboneliğinizi yönetmek için lütfen ${familyAdminEmail} ile iletişime geçin"; - static String m19(provider) => + static String m20(provider) => "Lütfen ${provider} aboneliğinizi yönetmek için support@ente.io adresinden bizimle iletişime geçin."; - static String m20(endpoint) => "${endpoint}\'e bağlanıldı"; + static String m21(endpoint) => "${endpoint}\'e bağlanıldı"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Delete ${count} item', other: 'Delete ${count} items')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Siliniyor ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Bu, \"${albumName}\"e erişim için olan genel bağlantıyı kaldıracaktır."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Lütfen kayıtlı e-posta adresinizden ${supportEmail} adresine bir e-posta gönderin"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "You have cleaned up ${Intl.plural(count, one: '${count} duplicate file', other: '${count} duplicate files')}, saving (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} dosyalar, ${formattedSize} her biri"; - static String m27(newEmail) => "E-posta ${newEmail} olarak değiştirildi"; + static String m28(newEmail) => "E-posta ${newEmail} olarak değiştirildi"; - static String m28(email) => + static String m29(email) => "${email}, Ente hesabı bulunmamaktadır.\n\nOnlarla fotoğraf paylaşımı için bir davet gönder."; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "Bu cihazdaki ${Intl.plural(count, one: '1 file', other: '${formattedNumber} dosya')} güvenli bir şekilde yedeklendi"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "Bu albümdeki ${Intl.plural(count, one: '1 file', other: '${formattedNumber} dosya')} güvenli bir şekilde yedeklendi"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "Birisinin davet kodunuzu uygulayıp ücretli hesap açtığı her seferede ${storageAmountInGB} GB"; - static String m32(endDate) => "Ücretsiz deneme ${endDate} sona erir"; + static String m33(endDate) => "Ücretsiz deneme ${endDate} sona erir"; - static String m34(sizeInMBorGB) => "${sizeInMBorGB} yer açın"; + static String m35(sizeInMBorGB) => "${sizeInMBorGB} yer açın"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'Yer açmak için cihazdan silinebilir ${formattedSize}', other: 'Yer açmak için cihazdan silinebilir ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Siliniyor ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} öğe', other: '${count} öğeler')}"; - static String m38(expiryTime) => + static String m39(expiryTime) => "Bu bağlantı ${expiryTime} dan sonra geçersiz olacaktır"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'anı yok', one: '${formattedCount} anı', other: '${formattedCount} anılar')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Öğeyi taşı', other: 'Öğeleri taşı')}"; - static String m40(albumName) => "${albumName} adlı albüme başarıyla taşındı"; + static String m41(albumName) => "${albumName} adlı albüme başarıyla taşındı"; static String m0(passwordStrengthValue) => "Şifrenin güçlülük seviyesi: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Sizden ücret alındıysa lütfen ${providerName} destek ekibiyle görüşün"; - static String m45(toEmail) => "Lütfen bize ${toEmail} adresinden ulaşın"; + static String m46(toEmail) => "Lütfen bize ${toEmail} adresinden ulaşın"; - static String m46(toEmail) => + static String m47(toEmail) => "Lütfen günlükleri şu adrese gönderin\n${toEmail}"; - static String m48(storeName) => "Bizi ${storeName} üzerinden değerlendirin"; + static String m49(storeName) => "Bizi ${storeName} üzerinden değerlendirin"; - static String m49(storageInGB) => "3. Hepimiz ${storageInGB} GB* bedava alın"; + static String m50(storageInGB) => "3. Hepimiz ${storageInGB} GB* bedava alın"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} bu paylaşılan albümden kaldırılacaktır\n\nOnlar tarafından eklenen tüm fotoğraflar da albümden kaldırılacaktır"; - static String m51(endDate) => "Abonelik ${endDate} tarihinde yenilenir"; + static String m52(endDate) => "Abonelik ${endDate} tarihinde yenilenir"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: '${count} yıl önce', other: '${count} yıl önce')}"; - static String m3(count) => "${count} seçildi"; + static String m4(count) => "${count} seçildi"; - static String m53(count, yourCount) => + static String m54(count, yourCount) => "Seçilenler: ${count} (${yourCount} sizin seçiminiz)"; - static String m54(verificationID) => + static String m55(verificationID) => "İşte ente.io için doğrulama kimliğim: ${verificationID}."; - static String m4(verificationID) => + static String m5(verificationID) => "Merhaba, bu ente.io doğrulama kimliğinizin doğruluğunu onaylayabilir misiniz: ${verificationID}"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Belirli kişilerle paylaş', one: '1 kişiyle paylaşıldı', other: '${numberOfPeople} kişiyle paylaşıldı')}"; - static String m57(emailIDs) => "${emailIDs} ile paylaşıldı"; + static String m58(emailIDs) => "${emailIDs} ile paylaşıldı"; - static String m58(fileType) => "Bu ${fileType}, cihazınızdan silinecek."; + static String m59(fileType) => "Bu ${fileType}, cihazınızdan silinecek."; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -185,7 +185,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "${email} doğrula"; - static String m1(email) => + static String m2(email) => "E-postayı ${email} adresine gönderdik"; static String m72(count) => @@ -208,16 +208,16 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Yeni e-posta ekle"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Düzenleyici ekle"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Cihazdan ekle"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Konum Ekle"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Ekle"), "addMore": MessageLookupByLibrary.simpleMessage("Daha fazla ekle"), "addNew": MessageLookupByLibrary.simpleMessage("Yeni ekle"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Eklentilerin ayrıntıları"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Eklentiler"), "addPhotos": MessageLookupByLibrary.simpleMessage("Fotoğraf ekle"), "addSelected": MessageLookupByLibrary.simpleMessage("Seçileni ekle"), @@ -225,12 +225,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Gizli albüme ekle"), "addViewer": MessageLookupByLibrary.simpleMessage("Görüntüleyici ekle"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage( "Fotoğraflarınızı şimdi ekleyin"), "addedAs": MessageLookupByLibrary.simpleMessage("Eklendi"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Favorilere ekleniyor..."), "advanced": MessageLookupByLibrary.simpleMessage("Gelişmiş"), @@ -241,7 +241,7 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("1 hafta sonra"), "after1Year": MessageLookupByLibrary.simpleMessage("1 yıl sonra"), "albumOwner": MessageLookupByLibrary.simpleMessage("Sahip"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Albüm Başlığı"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Albüm güncellendi"), @@ -249,6 +249,8 @@ class MessageLookup extends MessageLookupByLibrary { "allClear": MessageLookupByLibrary.simpleMessage("✨ Tamamen temizle"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("Tüm anılar saklandı"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Bağlantıya sahip olan kişilere, paylaşılan albüme fotoğraf eklemelerine izin ver."), "allowAddingPhotos": @@ -278,7 +280,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Android, iOS, Web, Masaüstü"), "androidSignInTitle": MessageLookupByLibrary.simpleMessage("Kimlik doğrulaması gerekli"), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple kimliği"), "apply": MessageLookupByLibrary.simpleMessage("Uygula"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Kodu girin"), @@ -301,6 +303,9 @@ class MessageLookup extends MessageLookupByLibrary { "Çıkış yapmak istediğinize emin misiniz?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Yenilemek istediğinize emin misiniz?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( "Aboneliğiniz iptal edilmiştir. Bunun sebebini paylaşmak ister misiniz?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( @@ -365,10 +370,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Yalnızca size ait dosyaları kaldırabilir"), "cancel": MessageLookupByLibrary.simpleMessage("İptal Et"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("Abonelik iptali"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage("Dosyalar silinemiyor"), "castInstruction": MessageLookupByLibrary.simpleMessage( @@ -393,7 +398,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Bedava alan talep edin"), "claimMore": MessageLookupByLibrary.simpleMessage("Arttır!"), "claimed": MessageLookupByLibrary.simpleMessage("Alındı"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Temiz Genel"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -417,7 +422,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Sizin kullandığınız kod"), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Organizasyon bağlantısı"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Düzenleyici"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -445,10 +450,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Kurtarma anahtarını doğrula"), "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage( "Kurtarma anahtarını doğrulayın"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("Destek ile iletişim"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Kişiler"), "contents": MessageLookupByLibrary.simpleMessage("İçerikler"), "continueLabel": MessageLookupByLibrary.simpleMessage("Devam edin"), @@ -489,7 +494,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("Güncel kullanımınız "), "custom": MessageLookupByLibrary.simpleMessage("Kişisel"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Karanlık"), "dayToday": MessageLookupByLibrary.simpleMessage("Bugün"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Dün"), @@ -521,11 +526,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Her ikisinden de sil"), "deleteFromDevice": MessageLookupByLibrary.simpleMessage("Cihazınızdan silin"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Konumu sil"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Fotoğrafları sil"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "İhtiyacım olan önemli bir özellik eksik"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -560,7 +565,7 @@ class MessageLookup extends MessageLookupByLibrary { "Görüntüleyiciler, hala harici araçlar kullanarak ekran görüntüsü alabilir veya fotoğraflarınızın bir kopyasını kaydedebilir. Lütfen bunu göz önünde bulundurunuz"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Lütfen dikkate alın"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "İki Aşamalı Doğrulamayı Devre Dışı Bırak"), "disablingTwofactorAuthentication": @@ -581,9 +586,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("İndirme başarısız"), "downloading": MessageLookupByLibrary.simpleMessage("İndiriliyor..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Düzenle"), "editLocation": MessageLookupByLibrary.simpleMessage("Konumu düzenle"), "editLocationTagTitle": @@ -595,8 +600,8 @@ class MessageLookup extends MessageLookupByLibrary { "Konumda yapılan düzenlemeler yalnızca Ente\'de görülecektir"), "eligible": MessageLookupByLibrary.simpleMessage("uygun"), "email": MessageLookupByLibrary.simpleMessage("E-Posta"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("E-posta doğrulama"), "emailYourLogs": MessageLookupByLibrary.simpleMessage( @@ -692,8 +697,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Dosya türü"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Dosya türleri ve adları"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Dosyalar silinmiş"), "flip": MessageLookupByLibrary.simpleMessage("Çevir"), @@ -703,22 +708,22 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Şifremi unuttum"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Alınan bedava alan"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("Kullanılabilir bedava alan"), "freeTrial": MessageLookupByLibrary.simpleMessage("Ücretsiz deneme"), - "freeTrialValidTill": m32, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Cihaz alanını boşaltın"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Boş alan"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "Galeride 1000\'e kadar anı gösterilir"), "general": MessageLookupByLibrary.simpleMessage("Genel"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Şifreleme anahtarı oluşturuluyor..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Ayarlara git"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google play kimliği"), @@ -779,7 +784,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Bir şeyler ters gitmiş gibi görünüyor. Lütfen bir süre sonra tekrar deneyin. Hata devam ederse, lütfen destek ekibimizle iletişime geçin."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Öğeler, kalıcı olarak silinmeden önce kalan gün sayısını gösterir"), @@ -808,7 +813,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("Cihaz limiti"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Geçerli"), "linkExpired": MessageLookupByLibrary.simpleMessage("Süresi dolmuş"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("Linkin geçerliliği"), "linkHasExpired": @@ -880,7 +885,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("Haritalar"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Ürünler"), "mobileWebDesktop": MessageLookupByLibrary.simpleMessage("Mobil, Web, Masaüstü"), @@ -890,11 +895,11 @@ class MessageLookup extends MessageLookupByLibrary { "Sorgunuzu değiştirin veya aramayı deneyin"), "moments": MessageLookupByLibrary.simpleMessage("Anlar"), "monthly": MessageLookupByLibrary.simpleMessage("Aylık"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Albüme taşı"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("Gizli albüme ekle"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Cöp kutusuna taşı"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -943,6 +948,7 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("Bu cihaz"), "onEnte": MessageLookupByLibrary.simpleMessage( "ente üzerinde"), + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("Hay aksi"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Hata! Düzenlemeler kaydedilemedi"), @@ -973,7 +979,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ödeme başarısız oldu"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "Maalesef ödemeniz başarısız oldu. Lütfen destekle iletişime geçin, size yardımcı olacağız!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Bekleyen Öğeler"), "pendingSync": MessageLookupByLibrary.simpleMessage("Senkronizasyon bekleniyor"), @@ -1009,12 +1015,12 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Bu hata devam ederse lütfen desteğe başvurun"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Lütfen izin ver"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Lütfen tekrar giriş yapın"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Lütfen tekrar deneyiniz"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1051,7 +1057,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Uygulamaya puan verin"), "rateUs": MessageLookupByLibrary.simpleMessage("Bizi değerlendirin"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Kurtarma"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Hesabı kurtar"), "recoverButton": MessageLookupByLibrary.simpleMessage("Kurtar"), @@ -1080,7 +1086,7 @@ class MessageLookup extends MessageLookupByLibrary { "1. Bu kodu arkadaşlarınıza verin"), "referralStep2": MessageLookupByLibrary.simpleMessage( "2. Ücretli bir plan için kaydolsunlar"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Referanslar"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage( "Davetler şu anda durmuş durumda"), @@ -1103,7 +1109,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeLink": MessageLookupByLibrary.simpleMessage("Linki kaldır"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Katılımcıyı kaldır"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePublicLink": MessageLookupByLibrary.simpleMessage("Herkese açık link oluştur"), "removeShareItemsWarning": MessageLookupByLibrary.simpleMessage( @@ -1119,7 +1125,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Dosyayı yeniden adlandır"), "renewSubscription": MessageLookupByLibrary.simpleMessage("Abonelik yenileme"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Hatayı bildir"), "reportBug": MessageLookupByLibrary.simpleMessage("Hata bildir"), "resendEmail": @@ -1128,6 +1134,7 @@ class MessageLookup extends MessageLookupByLibrary { "Yok sayılan dosyaları sıfırla"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Parolanızı sıfırlayın"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("Varsayılana sıfırla"), "restore": MessageLookupByLibrary.simpleMessage("Yenile"), @@ -1178,7 +1185,7 @@ class MessageLookup extends MessageLookupByLibrary { "Bir fotoğrafın belli bir yarıçapında çekilen fotoğrafları gruplandırın"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "İnsanları davet ettiğinizde onların paylaştığı tüm fotoğrafları burada göreceksiniz"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Güvenlik"), "selectALocation": MessageLookupByLibrary.simpleMessage("Bir konum seçin"), @@ -1203,8 +1210,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Seçilen öğeler tüm albümlerden silinecek ve çöp kutusuna taşınacak."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Gönder"), "sendEmail": MessageLookupByLibrary.simpleMessage("E-posta gönder"), "sendInvite": MessageLookupByLibrary.simpleMessage("Davet kodu gönder"), @@ -1229,13 +1236,13 @@ class MessageLookup extends MessageLookupByLibrary { "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("Şimdi bir albüm paylaşın"), "shareLink": MessageLookupByLibrary.simpleMessage("Linki paylaş"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Yalnızca istediğiniz kişilerle paylaşın"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Ente kullanıcısı olmayanlar için paylaş"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("İlk albümünüzü paylaşın"), "sharedByMe": @@ -1245,7 +1252,7 @@ class MessageLookup extends MessageLookupByLibrary { "Paylaşılan fotoğrafları ekle"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Birisi sizin de parçası olduğunuz paylaşılan bir albüme fotoğraf eklediğinde bildirim alın"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Benimle paylaşılan"), "sharedWithYou": @@ -1260,7 +1267,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Diğer cihazlardan çıkış yap"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Hizmet Şartları\'nı ve Gizlilik Politikası\'nı kabul ediyorum"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage("Tüm albümlerden silinecek."), "skip": MessageLookupByLibrary.simpleMessage("Geç"), @@ -1299,7 +1306,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Depolama"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Aile"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Sen"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Depolama sınırı aşıldı"), "storageUsageInfo": m62, @@ -1471,7 +1478,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Henüz sahibi olmadığınız fotoğraf ve albümlerin düzenlenmesini desteklemiyoruz"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Zayıf"), "welcomeBack": MessageLookupByLibrary.simpleMessage("Tekrardan hoşgeldin!"), @@ -1488,6 +1495,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Evet, oturumu kapat"), "yesRemove": MessageLookupByLibrary.simpleMessage("Evet, sil"), "yesRenew": MessageLookupByLibrary.simpleMessage("Evet, yenile"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Sen"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("Aile planı kullanıyorsunuz!"), diff --git a/mobile/lib/generated/intl/messages_uk.dart b/mobile/lib/generated/intl/messages_uk.dart index fca15145b4..9a07608d24 100644 --- a/mobile/lib/generated/intl/messages_uk.dart +++ b/mobile/lib/generated/intl/messages_uk.dart @@ -20,171 +20,171 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'uk'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, one: 'Додано співавтора', other: 'Додано співавторів')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: 'Додавання елемента', other: 'Додавання елементів')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "Ваше доповнення ${storageAmount} діє до ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, one: 'Додано глядача', other: 'Додано глядачів')}"; - static String m9(emailOrName) => "Додано ${emailOrName}"; + static String m10(emailOrName) => "Додано ${emailOrName}"; - static String m10(albumName) => "Успішно додано до «${albumName}»"; + static String m11(albumName) => "Успішно додано до «${albumName}»"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: 'Немає учасників', one: '1 учасник', other: '${count} учасників')}"; - static String m12(versionValue) => "Версія: ${versionValue}"; + static String m13(versionValue) => "Версія: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} вільно"; - static String m14(paymentProvider) => - "Спочатку скасуйте вашу підписку від ${paymentProvider}"; + static String m15(paymentProvider) => + "Спочатку скасуйте вашу передплату від ${paymentProvider}"; - static String m15(user) => + static String m16(user) => "${user} не зможе додавати більше фотографій до цього альбому\n\nВони все ще зможуть видаляти додані ними фотографії"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': 'Ваша сім\'я отримала ${storageAmountInGb} ГБ', 'false': 'Ви отримали ${storageAmountInGb} ГБ', 'other': 'Ви отримали ${storageAmountInGb} ГБ!', })}"; - static String m17(albumName) => + static String m18(albumName) => "Створено спільне посилання для «${albumName}»"; - static String m18(familyAdminEmail) => - "Зв\'яжіться з ${familyAdminEmail} для керування вашою підпискою"; + static String m19(familyAdminEmail) => + "Зв\'яжіться з ${familyAdminEmail} для керування вашою передплатою"; - static String m19(provider) => - "Зв\'яжіться з нами за адресою support@ente.io для управління вашою підпискою ${provider}."; + static String m20(provider) => + "Зв\'яжіться з нами за адресою support@ente.io для управління вашою передплатою ${provider}."; - static String m20(endpoint) => "Під\'єднано до ${endpoint}"; + static String m21(endpoint) => "Під\'єднано до ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: 'Видалено ${count} елемент', few: 'Видалено ${count} елементи', many: 'Видалено ${count} елементів', other: 'Видалено ${count} елементів')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "Видалення ${currentlyDeleting} / ${totalCount}"; - static String m23(albumName) => + static String m24(albumName) => "Це видалить публічне посилання для доступу до «${albumName}»."; - static String m24(supportEmail) => + static String m25(supportEmail) => "Надішліть листа на ${supportEmail} з вашої зареєстрованої поштової адреси"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "Ви очистили ${Intl.plural(count, one: '${count} дублікат файлу', other: '${count} дублікатів файлів')}, збережено (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} файлів, кожен по ${formattedSize}"; - static String m27(newEmail) => "Поштову адресу змінено на ${newEmail}"; + static String m28(newEmail) => "Поштову адресу змінено на ${newEmail}"; - static String m28(email) => + static String m29(email) => "У ${email} немає облікового запису Ente.\n\nНадішліть їм запрошення для обміну фотографіями."; - static String m29(count, formattedNumber) => + static String m30(count, formattedNumber) => "${Intl.plural(count, one: 'Для 1 файлу', other: 'Для ${formattedNumber} файлів')} на цьому пристрої було створено резервну копію"; - static String m30(count, formattedNumber) => + static String m31(count, formattedNumber) => "${Intl.plural(count, one: 'Для 1 файлу', few: 'Для ${formattedNumber} файлів', many: 'Для ${formattedNumber} файлів', other: 'Для ${formattedNumber} файлів')} у цьому альбомі було створено резервну копію"; - static String m31(storageAmountInGB) => - "${storageAmountInGB} ГБ щоразу, коли хтось підписується на платний тариф і застосовує ваш код"; + static String m32(storageAmountInGB) => + "${storageAmountInGB} ГБ щоразу, коли хтось оформлює передплату і застосовує ваш код"; - static String m32(endDate) => "Безплатна пробна версія діє до ${endDate}"; + static String m33(endDate) => "Безплатна пробна версія діє до ${endDate}"; - static String m33(count) => - "Ви все ще можете отримати доступ до ${Intl.plural(count, one: 'нього', other: 'них')} в Ente, доки у вас активна підписка"; + static String m34(count) => + "Ви все ще можете отримати доступ до ${Intl.plural(count, one: 'нього', other: 'них')} в Ente, доки у вас активна передплата"; - static String m34(sizeInMBorGB) => "Звільніть ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "Звільніть ${sizeInMBorGB}"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: 'Його можна видалити з пристрою, щоб звільнити ${formattedSize}', other: 'Їх можна видалити з пристрою, щоб звільнити ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "Обробка ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} елемент', few: '${count} елементи', many: '${count} елементів', other: '${count} елементів')}"; - static String m38(expiryTime) => "Посилання закінчується через ${expiryTime}"; + static String m39(expiryTime) => "Посилання закінчується через ${expiryTime}"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: 'немає спогадів', one: '${formattedCount} спогад', other: '${formattedCount} спогадів')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: 'Переміщення елемента', other: 'Переміщення елементів')}"; - static String m40(albumName) => "Успішно перенесено до «${albumName}»"; + static String m41(albumName) => "Успішно перенесено до «${albumName}»"; - static String m41(name) => "Не ${name}?"; + static String m42(name) => "Не ${name}?"; - static String m42(familyAdminEmail) => + static String m43(familyAdminEmail) => "Зв\'яжіться з ${familyAdminEmail}, щоб змінити код."; static String m0(passwordStrengthValue) => "Надійність пароля: ${passwordStrengthValue}"; - static String m43(providerName) => + static String m44(providerName) => "Зверніться до ${providerName}, якщо було знято платіж"; - static String m44(endDate) => + static String m45(endDate) => "Безплатна пробна версія діє до ${endDate}.\nПісля цього ви можете обрати платний план."; - static String m45(toEmail) => "Напишіть нам на ${toEmail}"; + static String m46(toEmail) => "Напишіть нам на ${toEmail}"; - static String m46(toEmail) => "Надішліть журнали на \n${toEmail}"; + static String m47(toEmail) => "Надішліть журнали на \n${toEmail}"; - static String m47(folderName) => "Оброблюємо «${folderName}»..."; + static String m48(folderName) => "Оброблюємо «${folderName}»..."; - static String m48(storeName) => "Оцініть нас в ${storeName}"; + static String m49(storeName) => "Оцініть нас в ${storeName}"; - static String m49(storageInGB) => + static String m50(storageInGB) => "3. Ви обоє отримуєте ${storageInGB} ГБ* безплатно"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} буде видалено з цього спільного альбому\n\nБудь-які додані вами фото, будуть також видалені з альбому"; - static String m51(endDate) => "Підписка поновиться ${endDate}"; + static String m52(endDate) => "Передплата поновиться ${endDate}"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, one: 'Знайдено ${count} результат', few: 'Знайдено ${count} результати', many: 'Знайдено ${count} результатів', other: 'Знайдено ${count} результати')}"; - static String m3(count) => "${count} вибрано"; + static String m4(count) => "${count} вибрано"; - static String m53(count, yourCount) => "${count} вибрано (${yourCount} ваші)"; + static String m54(count, yourCount) => "${count} вибрано (${yourCount} ваші)"; - static String m54(verificationID) => + static String m55(verificationID) => "Ось мій ідентифікатор підтвердження: ${verificationID} для ente.io."; - static String m4(verificationID) => + static String m5(verificationID) => "Гей, ви можете підтвердити, що це ваш ідентифікатор підтвердження: ${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Реферальний код Ente: ${referralCode} \n\nЗастосуйте його в «Налаштування» → «Загальні» → «Реферали», щоб отримати ${referralStorageInGB} ГБ безплатно після переходу на платний тариф\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: 'Поділитися з конкретними людьми', one: 'Поділитися з 1 особою', other: 'Поділитися з ${numberOfPeople} людьми')}"; - static String m57(emailIDs) => "Поділилися з ${emailIDs}"; + static String m58(emailIDs) => "Поділилися з ${emailIDs}"; - static String m58(fileType) => "Цей ${fileType} буде видалено з пристрою."; + static String m59(fileType) => "Цей ${fileType} буде видалено з пристрою."; - static String m59(fileType) => + static String m60(fileType) => "Цей ${fileType} знаходиться і в Ente, і на вашому пристрої."; - static String m60(fileType) => "Цей ${fileType} буде видалено з Ente."; + static String m61(fileType) => "Цей ${fileType} буде видалено з Ente."; - static String m61(storageAmountInGB) => "${storageAmountInGB} ГБ"; + static String m1(storageAmountInGB) => "${storageAmountInGB} ГБ"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -193,7 +193,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m63(id) => "Ваш ${id} вже пов\'язаний з іншим обліковим записом Ente.\nЯкщо ви хочете використовувати свій ${id} з цим обліковим записом, зверніться до нашої служби підтримки"; - static String m64(endDate) => "Вашу підписку буде скасовано ${endDate}"; + static String m64(endDate) => "Вашу передплату буде скасовано ${endDate}"; static String m65(completed, total) => "${completed} / ${total} спогадів збережено"; @@ -206,11 +206,13 @@ class MessageLookup extends MessageLookupByLibrary { static String m68(count) => "${Intl.plural(count, zero: '', one: '1 день', few: '${count} дні', many: '${count} днів', other: '${count} днів')}"; + static String m69(count) => "Збереження ${count} спогадів..."; + static String m70(endDate) => "Діє до ${endDate}"; static String m71(email) => "Підтвердити ${email}"; - static String m1(email) => "Ми надіслали листа на ${email}"; + static String m2(email) => "Ми надіслали листа на ${email}"; static String m72(count) => "${Intl.plural(count, one: '${count} рік тому', few: '${count} роки тому', many: '${count} років тому', other: '${count} років тому')}"; @@ -229,23 +231,29 @@ class MessageLookup extends MessageLookupByLibrary { "Я розумію, що якщо я втрачу свій пароль, я можу втратити свої дані, тому що вони є захищені наскрізним шифруванням."), "activeSessions": MessageLookupByLibrary.simpleMessage("Активні сеанси"), + "add": MessageLookupByLibrary.simpleMessage("Додати"), "addAName": MessageLookupByLibrary.simpleMessage("Додати ім\'я"), "addANewEmail": MessageLookupByLibrary.simpleMessage("Додати нову пошту"), "addCollaborator": MessageLookupByLibrary.simpleMessage("Додати співавтора"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("Додати з пристрою"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("Додати розташування"), "addLocationButton": MessageLookupByLibrary.simpleMessage("Додати"), "addMore": MessageLookupByLibrary.simpleMessage("Додати більше"), + "addName": MessageLookupByLibrary.simpleMessage("Додати ім\'я"), + "addNameOrMerge": + MessageLookupByLibrary.simpleMessage("Додати назву або об\'єднати"), "addNew": MessageLookupByLibrary.simpleMessage("Додати нове"), + "addNewPerson": + MessageLookupByLibrary.simpleMessage("Додати нову особу"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("Подробиці доповнень"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("Доповнення"), "addPhotos": MessageLookupByLibrary.simpleMessage("Додати фотографії"), "addSelected": MessageLookupByLibrary.simpleMessage("Додати вибране"), @@ -254,12 +262,12 @@ class MessageLookup extends MessageLookupByLibrary { "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Додати до прихованого альбому"), "addViewer": MessageLookupByLibrary.simpleMessage("Додати глядача"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("Додайте свої фотографії"), "addedAs": MessageLookupByLibrary.simpleMessage("Додано як"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("Додавання до обраного..."), "advanced": MessageLookupByLibrary.simpleMessage("Додатково"), @@ -270,13 +278,15 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("Через 1 тиждень"), "after1Year": MessageLookupByLibrary.simpleMessage("Через 1 рік"), "albumOwner": MessageLookupByLibrary.simpleMessage("Власник"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("Назва альбому"), "albumUpdated": MessageLookupByLibrary.simpleMessage("Альбом оновлено"), "albums": MessageLookupByLibrary.simpleMessage("Альбоми"), "allClear": MessageLookupByLibrary.simpleMessage("✨ Все чисто"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("Всі спогади збережені"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage( "Дозволити людям з посиланням також додавати фотографії до спільного альбому."), "allowAddingPhotos": MessageLookupByLibrary.simpleMessage( @@ -311,13 +321,13 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Блокування застосунку"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "Виберіть між типовим екраном блокування вашого пристрою та власним екраном блокування з PIN-кодом або паролем."), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("Застосувати"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("Застосувати код"), "appstoreSubscription": - MessageLookupByLibrary.simpleMessage("Підписка App Store"), + MessageLookupByLibrary.simpleMessage("Передплата App Store"), "archive": MessageLookupByLibrary.simpleMessage("Архів"), "archiveAlbum": MessageLookupByLibrary.simpleMessage("Архівувати альбом"), @@ -336,8 +346,11 @@ class MessageLookup extends MessageLookupByLibrary { "Ви впевнені, що хочете вийти з облікового запису?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage( "Ви впевнені, що хочете поновити?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage( - "Підписку було скасовано. Ви хотіли б поділитися причиною?"), + "Передплату було скасовано. Ви хотіли б поділитися причиною?"), "askDeleteReason": MessageLookupByLibrary.simpleMessage( "Яка основна причина видалення вашого облікового запису?"), "askYourLovedOnesToShare": MessageLookupByLibrary.simpleMessage( @@ -389,7 +402,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage( "Автоматичне створення пари працює лише з пристроями, що підтримують Chromecast."), "available": MessageLookupByLibrary.simpleMessage("Доступно"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("Резервне копіювання тек"), "backup": MessageLookupByLibrary.simpleMessage("Резервне копіювання"), @@ -419,10 +432,10 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage( "Ви можете видалити лише файли, що належать вам"), "cancel": MessageLookupByLibrary.simpleMessage("Скасувати"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": - MessageLookupByLibrary.simpleMessage("Скасувати підписку"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + MessageLookupByLibrary.simpleMessage("Скасувати передплату"), + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage( "Не можна видалити спільні файли"), "castIPMismatchBody": MessageLookupByLibrary.simpleMessage( @@ -455,7 +468,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Отримайте безплатне сховище"), "claimMore": MessageLookupByLibrary.simpleMessage("Отримайте більше!"), "claimed": MessageLookupByLibrary.simpleMessage("Отримано"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("Очистити «Без категорії»"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage( @@ -485,7 +498,7 @@ class MessageLookup extends MessageLookupByLibrary { "Створіть посилання, щоб дозволити людям додавати й переглядати фотографії у вашому спільному альбомі без використання застосунку Ente або облікового запису. Чудово підходить для збору фотографій з подій."), "collaborativeLink": MessageLookupByLibrary.simpleMessage("Спільне посилання"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("Співавтор"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage( @@ -501,6 +514,7 @@ class MessageLookup extends MessageLookupByLibrary { "collectPhotosDescription": MessageLookupByLibrary.simpleMessage( "Створіть посилання, за яким ваші друзі зможуть завантажувати фотографії в оригінальній якості."), "color": MessageLookupByLibrary.simpleMessage("Колір"), + "configuration": MessageLookupByLibrary.simpleMessage("Налаштування"), "confirm": MessageLookupByLibrary.simpleMessage("Підтвердити"), "confirm2FADisable": MessageLookupByLibrary.simpleMessage( "Ви впевнені, що хочете вимкнути двоетапну перевірку?"), @@ -518,10 +532,10 @@ class MessageLookup extends MessageLookupByLibrary { "Підтвердіть ваш ключ відновлення"), "connectToDevice": MessageLookupByLibrary.simpleMessage("Під\'єднатися до пристрою"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage( "Звернутися до служби підтримки"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("Контакти"), "contents": MessageLookupByLibrary.simpleMessage("Вміст"), "continueLabel": MessageLookupByLibrary.simpleMessage("Продовжити"), @@ -539,8 +553,8 @@ class MessageLookup extends MessageLookupByLibrary { "Не вдалося створити резервну копію даних.\nМи спробуємо пізніше."), "couldNotFreeUpSpace": MessageLookupByLibrary.simpleMessage("Не вдалося звільнити місце"), - "couldNotUpdateSubscription": - MessageLookupByLibrary.simpleMessage("Не вдалося оновити підписку"), + "couldNotUpdateSubscription": MessageLookupByLibrary.simpleMessage( + "Не вдалося оновити передплату"), "count": MessageLookupByLibrary.simpleMessage("Кількість"), "crashReporting": MessageLookupByLibrary.simpleMessage("Звіти про помилки"), @@ -566,7 +580,7 @@ class MessageLookup extends MessageLookupByLibrary { "currentUsageIs": MessageLookupByLibrary.simpleMessage("Поточне використання "), "custom": MessageLookupByLibrary.simpleMessage("Власне"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("Темна"), "dayToday": MessageLookupByLibrary.simpleMessage("Сьогодні"), "dayYesterday": MessageLookupByLibrary.simpleMessage("Вчора"), @@ -602,11 +616,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Видалити з пристрою"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("Видалити з Ente"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("Видалити розташування"), "deletePhotos": MessageLookupByLibrary.simpleMessage("Видалити фото"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage( "Мені бракує ключової функції"), "deleteReason2": MessageLookupByLibrary.simpleMessage( @@ -646,7 +660,7 @@ class MessageLookup extends MessageLookupByLibrary { "Переглядачі все ще можуть робити знімки екрана або зберігати копію ваших фотографій за допомогою зовнішніх інструментів"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("Зверніть увагу"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage( "Вимкнути двоетапну перевірку"), "disablingTwofactorAuthentication": @@ -689,9 +703,9 @@ class MessageLookup extends MessageLookupByLibrary { "downloadFailed": MessageLookupByLibrary.simpleMessage("Не вдалося завантажити"), "downloading": MessageLookupByLibrary.simpleMessage("Завантаження..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("Редагувати"), "editLocation": MessageLookupByLibrary.simpleMessage("Змінити розташування"), @@ -704,8 +718,8 @@ class MessageLookup extends MessageLookupByLibrary { "eligible": MessageLookupByLibrary.simpleMessage("придатний"), "email": MessageLookupByLibrary.simpleMessage("Адреса електронної пошти"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("Підтвердження через пошту"), "emailYourLogs": MessageLookupByLibrary.simpleMessage( @@ -778,6 +792,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Експортування журналів"), "exportYourData": MessageLookupByLibrary.simpleMessage("Експортувати дані"), + "extraPhotosFound": MessageLookupByLibrary.simpleMessage( + "Знайдено додаткові фотографії"), + "extraPhotosFoundFor": MessageLookupByLibrary.simpleMessage( + "Знайдено додаткові фотографії для \$text"), "faceRecognition": MessageLookupByLibrary.simpleMessage("Розпізнавання обличчя"), "faces": MessageLookupByLibrary.simpleMessage("Обличчя"), @@ -814,8 +832,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileTypes": MessageLookupByLibrary.simpleMessage("Типи файлів"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("Типи та назви файлів"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("Файли видалено"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage("Файли збережено до галереї"), @@ -829,26 +847,26 @@ class MessageLookup extends MessageLookupByLibrary { "foundFaces": MessageLookupByLibrary.simpleMessage("Знайдені обличчя"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("Безплатне сховище отримано"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage( "Безплатне сховище можна використовувати"), "freeTrial": MessageLookupByLibrary.simpleMessage("Безплатний пробний період"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("Звільніть місце на пристрої"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage( "Збережіть місце на вашому пристрої, очистивши файли, які вже збережено."), "freeUpSpace": MessageLookupByLibrary.simpleMessage("Звільнити місце"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage( "До 1000 спогадів, показаних у галереї"), "general": MessageLookupByLibrary.simpleMessage("Загальні"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage( "Створення ключів шифрування..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("Перейти до налаштувань"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), @@ -925,7 +943,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "Схоже, що щось пішло не так. Спробуйте ще раз через деякий час. Якщо помилка не зникне, зв\'яжіться з нашою командою підтримки."), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage( "Елементи показують кількість днів, що залишилися до остаточного видалення"), @@ -954,7 +972,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Досягнуто ліміту пристроїв"), "linkEnabled": MessageLookupByLibrary.simpleMessage("Увімкнено"), "linkExpired": MessageLookupByLibrary.simpleMessage("Закінчився"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage( "Термін дії посилання закінчився"), "linkHasExpired": @@ -962,7 +980,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkNeverExpires": MessageLookupByLibrary.simpleMessage("Ніколи"), "livePhotos": MessageLookupByLibrary.simpleMessage("Живі фото"), "loadMessage1": MessageLookupByLibrary.simpleMessage( - "Ви можете поділитися своєю підпискою з родиною"), + "Ви можете поділитися своєю передплатою з родиною"), "loadMessage2": MessageLookupByLibrary.simpleMessage( "На цей час ми зберегли понад 30 мільйонів спогадів"), "loadMessage3": MessageLookupByLibrary.simpleMessage( @@ -991,6 +1009,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Завантажуємо фотографії..."), "localGallery": MessageLookupByLibrary.simpleMessage("Локальна галерея"), + "localIndexing": + MessageLookupByLibrary.simpleMessage("Локальне індексування"), "localSyncErrorMessage": MessageLookupByLibrary.simpleMessage( "Схоже, щось пішло не так, оскільки локальна синхронізація фотографій займає більше часу, ніж очікувалося. Зверніться до нашої служби підтримки"), "location": MessageLookupByLibrary.simpleMessage("Розташування"), @@ -1038,15 +1058,17 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Керувати посиланням"), "manageParticipants": MessageLookupByLibrary.simpleMessage("Керування"), "manageSubscription": - MessageLookupByLibrary.simpleMessage("Керування підпискою"), + MessageLookupByLibrary.simpleMessage("Керування передплатою"), "manualPairDesc": MessageLookupByLibrary.simpleMessage( "Створення пари з PIN-кодом працює з будь-яким екраном, на яку ви хочете переглянути альбом."), "map": MessageLookupByLibrary.simpleMessage("Мапа"), "maps": MessageLookupByLibrary.simpleMessage("Мапи"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("Товари"), + "mergeWithExisting": + MessageLookupByLibrary.simpleMessage("Об\'єднати з наявним"), "mlConsent": MessageLookupByLibrary.simpleMessage("Увімкнути машинне навчання"), "mlConsentConfirmation": MessageLookupByLibrary.simpleMessage( @@ -1070,12 +1092,12 @@ class MessageLookup extends MessageLookupByLibrary { "moreDetails": MessageLookupByLibrary.simpleMessage("Детальніше"), "mostRecent": MessageLookupByLibrary.simpleMessage("Останні"), "mostRelevant": MessageLookupByLibrary.simpleMessage("Найактуальніші"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("Перемістити до альбому"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage( "Перемістити до прихованого альбому"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("Переміщено у смітник"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage( @@ -1088,6 +1110,7 @@ class MessageLookup extends MessageLookupByLibrary { "Не вдалося під\'єднатися до Ente. Перевірте налаштування мережі. Зверніться до нашої команди підтримки, якщо помилка залишиться."), "never": MessageLookupByLibrary.simpleMessage("Ніколи"), "newAlbum": MessageLookupByLibrary.simpleMessage("Новий альбом"), + "newPerson": MessageLookupByLibrary.simpleMessage("Нова особа"), "newToEnte": MessageLookupByLibrary.simpleMessage("Уперше на Ente"), "newest": MessageLookupByLibrary.simpleMessage("Найновіші"), "next": MessageLookupByLibrary.simpleMessage("Далі"), @@ -1124,7 +1147,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Нічого не знайдено"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage( "Не знайдено системного блокування"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage( "Поки що з вами ніхто не поділився"), "nothingToSeeHere": MessageLookupByLibrary.simpleMessage( @@ -1134,7 +1157,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("На пристрої"), "onEnte": MessageLookupByLibrary.simpleMessage("В Ente"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("От халепа"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage( "Ой, не вдалося зберегти зміни"), @@ -1177,7 +1201,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Не вдалося оплатити"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "На жаль, ваш платіж не вдався. Зв\'яжіться зі службою підтримки і ми вам допоможемо!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("Елементи на розгляді"), "pendingSync": @@ -1191,6 +1215,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Остаточно видалити"), "permanentlyDeleteFromDevice": MessageLookupByLibrary.simpleMessage( "Остаточно видалити з пристрою?"), + "personName": MessageLookupByLibrary.simpleMessage("Ім\'я особи"), "photoDescriptions": MessageLookupByLibrary.simpleMessage("Опис фотографії"), "photoGridSize": @@ -1206,9 +1231,9 @@ class MessageLookup extends MessageLookupByLibrary { "pinLock": MessageLookupByLibrary.simpleMessage("Блокування PIN-кодом"), "playOnTv": MessageLookupByLibrary.simpleMessage("Відтворити альбом на ТБ"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": - MessageLookupByLibrary.simpleMessage("Підписка Play Store"), + MessageLookupByLibrary.simpleMessage("Передплата Play Store"), "pleaseCheckYourInternetConnectionAndTryAgain": MessageLookupByLibrary.simpleMessage( "Перевірте з\'єднання з мережею та спробуйте ще раз."), @@ -1218,14 +1243,14 @@ class MessageLookup extends MessageLookupByLibrary { "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage( "Зверніться до служби підтримки, якщо проблема не зникне"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("Надайте дозволи"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("Увійдіть знову"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage( "Виберіть посилання для видалення"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("Спробуйте ще раз"), "pleaseVerifyTheCodeYouHaveEntered": @@ -1251,7 +1276,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Приватні резервні копії"), "privateSharing": MessageLookupByLibrary.simpleMessage("Приватне поширення"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("Публічне посилання створено"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage( @@ -1262,7 +1287,7 @@ class MessageLookup extends MessageLookupByLibrary { "rateTheApp": MessageLookupByLibrary.simpleMessage("Оцініть застосунок"), "rateUs": MessageLookupByLibrary.simpleMessage("Оцініть нас"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("Відновити"), "recoverAccount": MessageLookupByLibrary.simpleMessage("Відновити обліковий запис"), @@ -1296,8 +1321,8 @@ class MessageLookup extends MessageLookupByLibrary { "referralStep1": MessageLookupByLibrary.simpleMessage("1. Дайте цей код друзям"), "referralStep2": MessageLookupByLibrary.simpleMessage( - "2. Вони підписуються на платний план"), - "referralStep3": m49, + "2. Вони оформлюють передплату"), + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("Реферали"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage("Реферали зараз призупинені"), @@ -1325,7 +1350,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Вилучити посилання"), "removeParticipant": MessageLookupByLibrary.simpleMessage("Видалити учасника"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("Видалити мітку особи"), "removePublicLink": @@ -1344,8 +1369,8 @@ class MessageLookup extends MessageLookupByLibrary { "renameFile": MessageLookupByLibrary.simpleMessage("Перейменувати файл"), "renewSubscription": - MessageLookupByLibrary.simpleMessage("Поновити підписку"), - "renewsOn": m51, + MessageLookupByLibrary.simpleMessage("Поновити передплату"), + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("Повідомити про помилку"), "reportBug": @@ -1356,6 +1381,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Скинути ігноровані файли"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("Скинути пароль"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("Скинути до типових"), "restore": MessageLookupByLibrary.simpleMessage("Відновити"), @@ -1418,7 +1444,7 @@ class MessageLookup extends MessageLookupByLibrary { "Групові фотографії, які зроблені в певному радіусі від фотографії"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage( "Запросіть людей, і ви побачите всі фотографії, якими вони поділилися, тут"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("Безпека"), "selectALocation": MessageLookupByLibrary.simpleMessage("Виберіть місце"), @@ -1443,8 +1469,8 @@ class MessageLookup extends MessageLookupByLibrary { "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage( "Вибрані елементи будуть видалені з усіх альбомів і переміщені в смітник."), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("Надіслати"), "sendEmail": MessageLookupByLibrary.simpleMessage( "Надіслати електронного листа"), @@ -1479,16 +1505,16 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Поділитися альбомом зараз"), "shareLink": MessageLookupByLibrary.simpleMessage("Поділитися посиланням"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage( "Поділіться тільки з тими людьми, якими ви хочете"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage( "Завантажте Ente для того, щоб легко поділитися фотографіями оригінальної якості та відео\n\nhttps://ente.io"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage( "Поділитися з користувачами без Ente"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage( "Поділитися вашим першим альбомом"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1499,7 +1525,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Нові спільні фотографії"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage( "Отримувати сповіщення, коли хтось додасть фото до спільного альбому, в якому ви перебуваєте"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("Поділитися зі мною"), "sharedWithYou": @@ -1516,11 +1542,11 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Вийти на інших пристроях"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "Я приймаю умови використання і політику приватності"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage( "Воно буде видалено з усіх альбомів."), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("Пропустити"), "social": MessageLookupByLibrary.simpleMessage("Соцмережі"), "someItemsAreInBothEnteAndYourDevice": @@ -1566,17 +1592,17 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("Сховище"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("Сім\'я"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("Ви"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("Перевищено ліміт сховища"), "storageUsageInfo": m62, "strongStrength": MessageLookupByLibrary.simpleMessage("Надійний"), "subAlreadyLinkedErrMessage": m63, "subWillBeCancelledOn": m64, - "subscribe": MessageLookupByLibrary.simpleMessage("Підписатися"), + "subscribe": MessageLookupByLibrary.simpleMessage("Передплачувати"), "subscribeToEnableSharing": MessageLookupByLibrary.simpleMessage( - "Вам потрібна активна платна підписка, щоб увімкнути спільне поширення."), - "subscription": MessageLookupByLibrary.simpleMessage("Підписка"), + "Вам потрібна активна передплата, щоб увімкнути спільне поширення."), + "subscription": MessageLookupByLibrary.simpleMessage("Передплата"), "success": MessageLookupByLibrary.simpleMessage("Успішно"), "successfullyArchived": MessageLookupByLibrary.simpleMessage("Успішно архівовано"), @@ -1609,7 +1635,7 @@ class MessageLookup extends MessageLookupByLibrary { "termsOfServicesTitle": MessageLookupByLibrary.simpleMessage("Умови"), "thankYou": MessageLookupByLibrary.simpleMessage("Дякуємо"), "thankYouForSubscribing": - MessageLookupByLibrary.simpleMessage("Спасибі за підписку!"), + MessageLookupByLibrary.simpleMessage("Спасибі за передплату!"), "theDownloadCouldNotBeCompleted": MessageLookupByLibrary.simpleMessage( "Завантаження не може бути завершено"), "theRecoveryKeyYouEnteredIsIncorrect": @@ -1703,6 +1729,7 @@ class MessageLookup extends MessageLookupByLibrary { "upgrade": MessageLookupByLibrary.simpleMessage("Покращити"), "uploadingFilesToAlbum": MessageLookupByLibrary.simpleMessage( "Завантажуємо файли до альбому..."), + "uploadingMultipleMemories": m69, "uploadingSingleMemory": MessageLookupByLibrary.simpleMessage("Зберігаємо 1 спогад..."), "upto50OffUntil4thDec": @@ -1756,7 +1783,7 @@ class MessageLookup extends MessageLookupByLibrary { "Переглянути ключ відновлення"), "viewer": MessageLookupByLibrary.simpleMessage("Глядач"), "visitWebToManage": MessageLookupByLibrary.simpleMessage( - "Відвідайте web.ente.io, щоб керувати підпискою"), + "Відвідайте web.ente.io, щоб керувати передплатою"), "waitingForVerification": MessageLookupByLibrary.simpleMessage("Очікується підтвердження..."), "waitingForWifi": @@ -1766,7 +1793,7 @@ class MessageLookup extends MessageLookupByLibrary { "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage( "Ми не підтримуємо редагування фотографій та альбомів, якими ви ще не володієте"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("Слабкий"), "welcomeBack": MessageLookupByLibrary.simpleMessage("З поверненням!"), "whatsNew": MessageLookupByLibrary.simpleMessage("Що нового"), @@ -1783,6 +1810,8 @@ class MessageLookup extends MessageLookupByLibrary { "Так, вийти з облікового запису"), "yesRemove": MessageLookupByLibrary.simpleMessage("Так, видалити"), "yesRenew": MessageLookupByLibrary.simpleMessage("Так, поновити"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("Ви"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("Ви на сімейному плані!"), @@ -1817,10 +1846,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "Не вдалося отримати деталі про ваше сховище"), "yourSubscriptionHasExpired": MessageLookupByLibrary.simpleMessage( - "Термін дії вашої підписки скінчився"), + "Термін дії вашої передплати скінчився"), "yourSubscriptionWasUpdatedSuccessfully": MessageLookupByLibrary.simpleMessage( - "Вашу підписку успішно оновлено"), + "Вашу передплату успішно оновлено"), "yourVerificationCodeHasExpired": MessageLookupByLibrary.simpleMessage( "Термін дії коду підтвердження минув"), "youveNoDuplicateFilesThatCanBeCleared": diff --git a/mobile/lib/generated/intl/messages_zh.dart b/mobile/lib/generated/intl/messages_zh.dart index f9f5747818..9ae12a5ce3 100644 --- a/mobile/lib/generated/intl/messages_zh.dart +++ b/mobile/lib/generated/intl/messages_zh.dart @@ -20,158 +20,158 @@ typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { String get localeName => 'zh'; - static String m5(count) => + static String m6(count) => "${Intl.plural(count, zero: '添加协作者', one: '添加协作者', other: '添加协作者')}"; - static String m6(count) => + static String m7(count) => "${Intl.plural(count, one: '添加一个项目', other: '添加一些项目')}"; - static String m7(storageAmount, endDate) => + static String m8(storageAmount, endDate) => "您的 ${storageAmount} 插件有效期至 ${endDate}"; - static String m8(count) => + static String m9(count) => "${Intl.plural(count, zero: '添加查看者', one: '添加查看者', other: '添加查看者')}"; - static String m9(emailOrName) => "由 ${emailOrName} 添加"; + static String m10(emailOrName) => "由 ${emailOrName} 添加"; - static String m10(albumName) => "成功添加到 ${albumName}"; + static String m11(albumName) => "成功添加到 ${albumName}"; - static String m11(count) => + static String m12(count) => "${Intl.plural(count, zero: '无参与者', one: '1个参与者', other: '${count} 个参与者')}"; - static String m12(versionValue) => "版本: ${versionValue}"; + static String m13(versionValue) => "版本: ${versionValue}"; - static String m13(freeAmount, storageUnit) => + static String m14(freeAmount, storageUnit) => "${freeAmount} ${storageUnit} 空闲"; - static String m14(paymentProvider) => "请先取消您现有的订阅 ${paymentProvider}"; + static String m15(paymentProvider) => "请先取消您现有的订阅 ${paymentProvider}"; - static String m15(user) => "${user} 将无法添加更多照片到此相册\n\n他们仍然能够删除他们添加的现有照片"; + static String m16(user) => "${user} 将无法添加更多照片到此相册\n\n他们仍然能够删除他们添加的现有照片"; - static String m16(isFamilyMember, storageAmountInGb) => + static String m17(isFamilyMember, storageAmountInGb) => "${Intl.select(isFamilyMember, { 'true': '到目前为止,您的家庭已经领取了 ${storageAmountInGb} GB', 'false': '到目前为止,您已经领取了 ${storageAmountInGb} GB', 'other': '到目前为止,您已经领取了${storageAmountInGb} GB', })}"; - static String m17(albumName) => "为 ${albumName} 创建了协作链接"; + static String m18(albumName) => "为 ${albumName} 创建了协作链接"; - static String m18(familyAdminEmail) => + static String m19(familyAdminEmail) => "请联系 ${familyAdminEmail} 来管理您的订阅"; - static String m19(provider) => + static String m20(provider) => "请通过support@ente.io 用英语联系我们来管理您的 ${provider} 订阅。"; - static String m20(endpoint) => "已连接至 ${endpoint}"; + static String m21(endpoint) => "已连接至 ${endpoint}"; - static String m21(count) => + static String m22(count) => "${Intl.plural(count, one: '删除 ${count} 个项目', other: '删除 ${count} 个项目')}"; - static String m22(currentlyDeleting, totalCount) => + static String m23(currentlyDeleting, totalCount) => "正在删除 ${currentlyDeleting} /共 ${totalCount}"; - static String m23(albumName) => "这将删除用于访问\"${albumName}\"的公开链接。"; + static String m24(albumName) => "这将删除用于访问\"${albumName}\"的公开链接。"; - static String m24(supportEmail) => "请从您注册的邮箱发送一封邮件到 ${supportEmail}"; + static String m25(supportEmail) => "请从您注册的邮箱发送一封邮件到 ${supportEmail}"; - static String m25(count, storageSaved) => + static String m26(count, storageSaved) => "您已经清理了 ${Intl.plural(count, other: '${count} 个重复文件')}, 释放了 (${storageSaved}!)"; - static String m26(count, formattedSize) => + static String m27(count, formattedSize) => "${count} 个文件,每个文件 ${formattedSize}"; - static String m27(newEmail) => "电子邮件已更改为 ${newEmail}"; + static String m28(newEmail) => "电子邮件已更改为 ${newEmail}"; - static String m28(email) => "${email} 没有 Ente 帐户。\n\n向他们发出共享照片的邀请。"; - - static String m29(count, formattedNumber) => - "此设备上的 ${Intl.plural(count, one: '1 个文件', other: '${formattedNumber} 个文件')} 已安全备份"; + static String m29(email) => "${email} 没有 Ente 帐户。\n\n向他们发出共享照片的邀请。"; static String m30(count, formattedNumber) => + "此设备上的 ${Intl.plural(count, one: '1 个文件', other: '${formattedNumber} 个文件')} 已安全备份"; + + static String m31(count, formattedNumber) => "此相册中的 ${Intl.plural(count, one: '1 个文件', other: '${formattedNumber} 个文件')} 已安全备份"; - static String m31(storageAmountInGB) => + static String m32(storageAmountInGB) => "每当有人使用您的代码注册付费计划时您将获得${storageAmountInGB} GB"; - static String m32(endDate) => "免费试用有效期至 ${endDate}"; + static String m33(endDate) => "免费试用有效期至 ${endDate}"; - static String m33(count) => + static String m34(count) => "只要您有有效的订阅,您仍然可以在 Ente 上访问 ${Intl.plural(count, one: '它', other: '它们')}"; - static String m34(sizeInMBorGB) => "释放 ${sizeInMBorGB}"; + static String m35(sizeInMBorGB) => "释放 ${sizeInMBorGB}"; - static String m35(count, formattedSize) => + static String m36(count, formattedSize) => "${Intl.plural(count, one: '它可以从设备中删除以释放 ${formattedSize}', other: '它们可以从设备中删除以释放 ${formattedSize}')}"; - static String m36(currentlyProcessing, totalCount) => + static String m37(currentlyProcessing, totalCount) => "正在处理 ${currentlyProcessing} / ${totalCount}"; - static String m37(count) => + static String m38(count) => "${Intl.plural(count, one: '${count} 个项目', other: '${count} 个项目')}"; - static String m38(expiryTime) => "链接将在 ${expiryTime} 过期"; + static String m39(expiryTime) => "链接将在 ${expiryTime} 过期"; - static String m2(count, formattedCount) => + static String m3(count, formattedCount) => "${Intl.plural(count, zero: '没有回忆', one: '${formattedCount} 个回忆', other: '${formattedCount} 个回忆')}"; - static String m39(count) => + static String m40(count) => "${Intl.plural(count, one: '移动一个项目', other: '移动一些项目')}"; - static String m40(albumName) => "成功移动到 ${albumName}"; + static String m41(albumName) => "成功移动到 ${albumName}"; - static String m41(name) => "不是 ${name}?"; + static String m42(name) => "不是 ${name}?"; - static String m42(familyAdminEmail) => "请联系${familyAdminEmail} 以更改您的代码。"; + static String m43(familyAdminEmail) => "请联系${familyAdminEmail} 以更改您的代码。"; static String m0(passwordStrengthValue) => "密码强度: ${passwordStrengthValue}"; - static String m43(providerName) => "如果您被收取费用,请用英语与 ${providerName} 的客服聊天"; + static String m44(providerName) => "如果您被收取费用,请用英语与 ${providerName} 的客服聊天"; - static String m44(endDate) => "免费试用有效期至 ${endDate}。\n在此之后您可以选择付费计划。"; + static String m45(endDate) => "免费试用有效期至 ${endDate}。\n在此之后您可以选择付费计划。"; - static String m45(toEmail) => "请给我们发送电子邮件至 ${toEmail}"; + static String m46(toEmail) => "请给我们发送电子邮件至 ${toEmail}"; - static String m46(toEmail) => "请将日志发送至 \n${toEmail}"; + static String m47(toEmail) => "请将日志发送至 \n${toEmail}"; - static String m47(folderName) => "正在处理 ${folderName}..."; + static String m48(folderName) => "正在处理 ${folderName}..."; - static String m48(storeName) => "在 ${storeName} 上给我们评分"; + static String m49(storeName) => "在 ${storeName} 上给我们评分"; - static String m49(storageInGB) => "3. 你和朋友都将免费获得 ${storageInGB} GB*"; + static String m50(storageInGB) => "3. 你和朋友都将免费获得 ${storageInGB} GB*"; - static String m50(userEmail) => + static String m51(userEmail) => "${userEmail} 将从这个共享相册中删除\n\nTA们添加的任何照片也将从相册中删除"; - static String m51(endDate) => "在 ${endDate} 前续费"; + static String m52(endDate) => "在 ${endDate} 前续费"; - static String m52(count) => + static String m53(count) => "${Intl.plural(count, other: '已找到 ${count} 个结果')}"; - static String m3(count) => "已选择 ${count} 个"; + static String m4(count) => "已选择 ${count} 个"; - static String m53(count, yourCount) => "选择了 ${count} 个 (您的 ${yourCount} 个)"; + static String m54(count, yourCount) => "选择了 ${count} 个 (您的 ${yourCount} 个)"; - static String m54(verificationID) => "这是我的ente.io 的验证 ID: ${verificationID}。"; + static String m55(verificationID) => "这是我的ente.io 的验证 ID: ${verificationID}。"; - static String m4(verificationID) => + static String m5(verificationID) => "嘿,你能确认这是你的 ente.io 验证 ID吗:${verificationID}"; - static String m55(referralCode, referralStorageInGB) => + static String m56(referralCode, referralStorageInGB) => "Ente 推荐代码:${referralCode}\n\n在 \"设置\"→\"通用\"→\"推荐 \"中应用它,即可在注册付费计划后免费获得 ${referralStorageInGB} GB 存储空间\n\nhttps://ente.io"; - static String m56(numberOfPeople) => + static String m57(numberOfPeople) => "${Intl.plural(numberOfPeople, zero: '与特定人员共享', one: '与 1 人共享', other: '与 ${numberOfPeople} 人共享')}"; - static String m57(emailIDs) => "与 ${emailIDs} 共享"; + static String m58(emailIDs) => "与 ${emailIDs} 共享"; - static String m58(fileType) => "此 ${fileType} 将从您的设备中删除。"; + static String m59(fileType) => "此 ${fileType} 将从您的设备中删除。"; - static String m59(fileType) => "${fileType} 已同时存在于 Ente 和您的设备中。"; + static String m60(fileType) => "${fileType} 已同时存在于 Ente 和您的设备中。"; - static String m60(fileType) => "${fileType} 将从 Ente 中删除。"; + static String m61(fileType) => "${fileType} 将从 Ente 中删除。"; - static String m61(storageAmountInGB) => "${storageAmountInGB} GB"; + static String m1(storageAmountInGB) => "${storageAmountInGB} GB"; static String m62( usedAmount, usedStorageUnit, totalAmount, totalStorageUnit) => @@ -197,7 +197,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m71(email) => "验证 ${email}"; - static String m1(email) => "我们已经发送邮件到 ${email}"; + static String m2(email) => "我们已经发送邮件到 ${email}"; static String m72(count) => "${Intl.plural(count, one: '${count} 年前', other: '${count} 年前')}"; @@ -217,15 +217,15 @@ class MessageLookup extends MessageLookupByLibrary { "addAName": MessageLookupByLibrary.simpleMessage("添加一个名称"), "addANewEmail": MessageLookupByLibrary.simpleMessage("添加新的电子邮件"), "addCollaborator": MessageLookupByLibrary.simpleMessage("添加协作者"), - "addCollaborators": m5, + "addCollaborators": m6, "addFromDevice": MessageLookupByLibrary.simpleMessage("从设备添加"), - "addItem": m6, + "addItem": m7, "addLocation": MessageLookupByLibrary.simpleMessage("添加地点"), "addLocationButton": MessageLookupByLibrary.simpleMessage("添加"), "addMore": MessageLookupByLibrary.simpleMessage("添加更多"), "addNew": MessageLookupByLibrary.simpleMessage("新建"), "addOnPageSubtitle": MessageLookupByLibrary.simpleMessage("附加组件详情"), - "addOnValidTill": m7, + "addOnValidTill": m8, "addOns": MessageLookupByLibrary.simpleMessage("附加组件"), "addPhotos": MessageLookupByLibrary.simpleMessage("添加照片"), "addSelected": MessageLookupByLibrary.simpleMessage("添加所选项"), @@ -233,11 +233,11 @@ class MessageLookup extends MessageLookupByLibrary { "addToEnte": MessageLookupByLibrary.simpleMessage("添加到 Ente"), "addToHiddenAlbum": MessageLookupByLibrary.simpleMessage("添加到隐藏相册"), "addViewer": MessageLookupByLibrary.simpleMessage("添加查看者"), - "addViewers": m8, + "addViewers": m9, "addYourPhotosNow": MessageLookupByLibrary.simpleMessage("立即添加您的照片"), "addedAs": MessageLookupByLibrary.simpleMessage("已添加为"), - "addedBy": m9, - "addedSuccessfullyTo": m10, + "addedBy": m10, + "addedSuccessfullyTo": m11, "addingToFavorites": MessageLookupByLibrary.simpleMessage("正在添加到收藏..."), "advanced": MessageLookupByLibrary.simpleMessage("高级设置"), "advancedSettings": MessageLookupByLibrary.simpleMessage("高级设置"), @@ -247,13 +247,15 @@ class MessageLookup extends MessageLookupByLibrary { "after1Week": MessageLookupByLibrary.simpleMessage("1 周后"), "after1Year": MessageLookupByLibrary.simpleMessage("1 年后"), "albumOwner": MessageLookupByLibrary.simpleMessage("所有者"), - "albumParticipantsCount": m11, + "albumParticipantsCount": m12, "albumTitle": MessageLookupByLibrary.simpleMessage("相册标题"), "albumUpdated": MessageLookupByLibrary.simpleMessage("相册已更新"), "albums": MessageLookupByLibrary.simpleMessage("相册"), "allClear": MessageLookupByLibrary.simpleMessage("✨ 全部清除"), "allMemoriesPreserved": MessageLookupByLibrary.simpleMessage("所有回忆都已保存"), + "allPersonGroupingWillReset": MessageLookupByLibrary.simpleMessage( + "All groupings for this person will be reset, and you will lose all suggestions made for this person"), "allowAddPhotosDescription": MessageLookupByLibrary.simpleMessage("允许具有链接的人也将照片添加到共享相册。"), "allowAddingPhotos": MessageLookupByLibrary.simpleMessage("允许添加照片"), @@ -279,7 +281,7 @@ class MessageLookup extends MessageLookupByLibrary { "appLock": MessageLookupByLibrary.simpleMessage("应用锁"), "appLockDescriptions": MessageLookupByLibrary.simpleMessage( "在设备的默认锁定屏幕和带有 PIN 或密码的自定义锁定屏幕之间进行选择。"), - "appVersion": m12, + "appVersion": m13, "appleId": MessageLookupByLibrary.simpleMessage("Apple ID"), "apply": MessageLookupByLibrary.simpleMessage("应用"), "applyCodeTitle": MessageLookupByLibrary.simpleMessage("应用代码"), @@ -300,6 +302,9 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("您确定要退出登录吗?"), "areYouSureYouWantToRenew": MessageLookupByLibrary.simpleMessage("您确定要续费吗?"), + "areYouSureYouWantToResetThisPerson": + MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset this person?"), "askCancelReason": MessageLookupByLibrary.simpleMessage("您的订阅已取消。您想分享原因吗?"), "askDeleteReason": @@ -347,7 +352,7 @@ class MessageLookup extends MessageLookupByLibrary { "autoPairDesc": MessageLookupByLibrary.simpleMessage("自动配对仅适用于支持 Chromecast 的设备。"), "available": MessageLookupByLibrary.simpleMessage("可用"), - "availableStorageSpace": m13, + "availableStorageSpace": m14, "backedUpFolders": MessageLookupByLibrary.simpleMessage("已备份的文件夹"), "backup": MessageLookupByLibrary.simpleMessage("备份"), "backupFailed": MessageLookupByLibrary.simpleMessage("备份失败"), @@ -369,9 +374,9 @@ class MessageLookup extends MessageLookupByLibrary { "canOnlyRemoveFilesOwnedByYou": MessageLookupByLibrary.simpleMessage("只能删除您拥有的文件"), "cancel": MessageLookupByLibrary.simpleMessage("取消"), - "cancelOtherSubscription": m14, + "cancelOtherSubscription": m15, "cancelSubscription": MessageLookupByLibrary.simpleMessage("取消订阅"), - "cannotAddMorePhotosAfterBecomingViewer": m15, + "cannotAddMorePhotosAfterBecomingViewer": m16, "cannotDeleteSharedFiles": MessageLookupByLibrary.simpleMessage("无法删除共享文件"), "castIPMismatchBody": @@ -397,7 +402,7 @@ class MessageLookup extends MessageLookupByLibrary { "claimFreeStorage": MessageLookupByLibrary.simpleMessage("领取免费存储"), "claimMore": MessageLookupByLibrary.simpleMessage("领取更多!"), "claimed": MessageLookupByLibrary.simpleMessage("已领取"), - "claimedStorageSoFar": m16, + "claimedStorageSoFar": m17, "cleanUncategorized": MessageLookupByLibrary.simpleMessage("清除未分类的"), "cleanUncategorizedDescription": MessageLookupByLibrary.simpleMessage("从“未分类”中删除其他相册中存在的所有文件"), @@ -419,7 +424,7 @@ class MessageLookup extends MessageLookupByLibrary { "collabLinkSectionDescription": MessageLookupByLibrary.simpleMessage( "创建一个链接来让他人无需 Ente 应用程序或账户即可在您的共享相册中添加和查看照片。非常适合收集活动照片。"), "collaborativeLink": MessageLookupByLibrary.simpleMessage("协作链接"), - "collaborativeLinkCreatedFor": m17, + "collaborativeLinkCreatedFor": m18, "collaborator": MessageLookupByLibrary.simpleMessage("协作者"), "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": MessageLookupByLibrary.simpleMessage("协作者可以将照片和视频添加到共享相册中。"), @@ -444,9 +449,9 @@ class MessageLookup extends MessageLookupByLibrary { "confirmYourRecoveryKey": MessageLookupByLibrary.simpleMessage("确认您的恢复密钥"), "connectToDevice": MessageLookupByLibrary.simpleMessage("连接到设备"), - "contactFamilyAdmin": m18, + "contactFamilyAdmin": m19, "contactSupport": MessageLookupByLibrary.simpleMessage("联系支持"), - "contactToManageSubscription": m19, + "contactToManageSubscription": m20, "contacts": MessageLookupByLibrary.simpleMessage("联系人"), "contents": MessageLookupByLibrary.simpleMessage("内容"), "continueLabel": MessageLookupByLibrary.simpleMessage("继续"), @@ -479,7 +484,7 @@ class MessageLookup extends MessageLookupByLibrary { "crop": MessageLookupByLibrary.simpleMessage("裁剪"), "currentUsageIs": MessageLookupByLibrary.simpleMessage("当前用量 "), "custom": MessageLookupByLibrary.simpleMessage("自定义"), - "customEndpoint": m20, + "customEndpoint": m21, "darkTheme": MessageLookupByLibrary.simpleMessage("深色"), "dayToday": MessageLookupByLibrary.simpleMessage("今天"), "dayYesterday": MessageLookupByLibrary.simpleMessage("昨天"), @@ -508,10 +513,10 @@ class MessageLookup extends MessageLookupByLibrary { "deleteFromBoth": MessageLookupByLibrary.simpleMessage("同时从两者中删除"), "deleteFromDevice": MessageLookupByLibrary.simpleMessage("从设备中删除"), "deleteFromEnte": MessageLookupByLibrary.simpleMessage("从 Ente 中删除"), - "deleteItemCount": m21, + "deleteItemCount": m22, "deleteLocation": MessageLookupByLibrary.simpleMessage("删除位置"), "deletePhotos": MessageLookupByLibrary.simpleMessage("删除照片"), - "deleteProgress": m22, + "deleteProgress": m23, "deleteReason1": MessageLookupByLibrary.simpleMessage("找不到我想要的功能"), "deleteReason2": MessageLookupByLibrary.simpleMessage("应用或某个功能没有按我的预期运行"), @@ -543,7 +548,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("查看者仍然可以使用外部工具截图或保存您的照片副本"), "disableDownloadWarningTitle": MessageLookupByLibrary.simpleMessage("请注意"), - "disableLinkMessage": m23, + "disableLinkMessage": m24, "disableTwofactor": MessageLookupByLibrary.simpleMessage("禁用双重认证"), "disablingTwofactorAuthentication": MessageLookupByLibrary.simpleMessage("正在禁用双重认证..."), @@ -576,9 +581,9 @@ class MessageLookup extends MessageLookupByLibrary { "download": MessageLookupByLibrary.simpleMessage("下载"), "downloadFailed": MessageLookupByLibrary.simpleMessage("下載失敗"), "downloading": MessageLookupByLibrary.simpleMessage("正在下载..."), - "dropSupportEmail": m24, - "duplicateFileCountWithStorageSaved": m25, - "duplicateItemsGroup": m26, + "dropSupportEmail": m25, + "duplicateFileCountWithStorageSaved": m26, + "duplicateItemsGroup": m27, "edit": MessageLookupByLibrary.simpleMessage("编辑"), "editLocation": MessageLookupByLibrary.simpleMessage("编辑位置"), "editLocationTagTitle": MessageLookupByLibrary.simpleMessage("编辑位置"), @@ -587,8 +592,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("对位置的编辑只能在 Ente 内看到"), "eligible": MessageLookupByLibrary.simpleMessage("符合资格"), "email": MessageLookupByLibrary.simpleMessage("电子邮件地址"), - "emailChangedTo": m27, - "emailNoEnteAccount": m28, + "emailChangedTo": m28, + "emailNoEnteAccount": m29, "emailVerificationToggle": MessageLookupByLibrary.simpleMessage("电子邮件验证"), "emailYourLogs": MessageLookupByLibrary.simpleMessage("通过电子邮件发送您的日志"), @@ -674,8 +679,8 @@ class MessageLookup extends MessageLookupByLibrary { "fileSavedToGallery": MessageLookupByLibrary.simpleMessage("文件已保存到相册"), "fileTypes": MessageLookupByLibrary.simpleMessage("文件类型"), "fileTypesAndNames": MessageLookupByLibrary.simpleMessage("文件类型和名称"), - "filesBackedUpFromDevice": m29, - "filesBackedUpInAlbum": m30, + "filesBackedUpFromDevice": m30, + "filesBackedUpInAlbum": m31, "filesDeleted": MessageLookupByLibrary.simpleMessage("文件已删除"), "filesSavedToGallery": MessageLookupByLibrary.simpleMessage("多个文件已保存到相册"), @@ -685,23 +690,23 @@ class MessageLookup extends MessageLookupByLibrary { "forgotPassword": MessageLookupByLibrary.simpleMessage("忘记密码"), "foundFaces": MessageLookupByLibrary.simpleMessage("已找到的人脸"), "freeStorageClaimed": MessageLookupByLibrary.simpleMessage("已领取的免费存储"), - "freeStorageOnReferralSuccess": m31, + "freeStorageOnReferralSuccess": m32, "freeStorageUsable": MessageLookupByLibrary.simpleMessage("可用的免费存储"), "freeTrial": MessageLookupByLibrary.simpleMessage("免费试用"), - "freeTrialValidTill": m32, - "freeUpAccessPostDelete": m33, - "freeUpAmount": m34, + "freeTrialValidTill": m33, + "freeUpAccessPostDelete": m34, + "freeUpAmount": m35, "freeUpDeviceSpace": MessageLookupByLibrary.simpleMessage("释放设备空间"), "freeUpDeviceSpaceDesc": MessageLookupByLibrary.simpleMessage("通过清除已备份的文件来节省设备空间。"), "freeUpSpace": MessageLookupByLibrary.simpleMessage("释放空间"), - "freeUpSpaceSaving": m35, + "freeUpSpaceSaving": m36, "galleryMemoryLimitInfo": MessageLookupByLibrary.simpleMessage("在图库中显示最多1000个回忆"), "general": MessageLookupByLibrary.simpleMessage("通用"), "generatingEncryptionKeys": MessageLookupByLibrary.simpleMessage("正在生成加密密钥..."), - "genericProgress": m36, + "genericProgress": m37, "goToSettings": MessageLookupByLibrary.simpleMessage("前往设置"), "googlePlayId": MessageLookupByLibrary.simpleMessage("Google Play ID"), "grantFullAccessPrompt": @@ -767,7 +772,7 @@ class MessageLookup extends MessageLookupByLibrary { "itLooksLikeSomethingWentWrongPleaseRetryAfterSome": MessageLookupByLibrary.simpleMessage( "看起来出了点问题。 请稍后重试。 如果错误仍然存在,请联系我们的支持团队。"), - "itemCount": m37, + "itemCount": m38, "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": MessageLookupByLibrary.simpleMessage("项目显示永久删除前剩余的天数"), "itemsWillBeRemovedFromAlbum": @@ -791,7 +796,7 @@ class MessageLookup extends MessageLookupByLibrary { "linkDeviceLimit": MessageLookupByLibrary.simpleMessage("设备限制"), "linkEnabled": MessageLookupByLibrary.simpleMessage("已启用"), "linkExpired": MessageLookupByLibrary.simpleMessage("已过期"), - "linkExpiresOn": m38, + "linkExpiresOn": m39, "linkExpiry": MessageLookupByLibrary.simpleMessage("链接过期"), "linkHasExpired": MessageLookupByLibrary.simpleMessage("链接已过期"), "linkNeverExpires": MessageLookupByLibrary.simpleMessage("永不"), @@ -862,7 +867,7 @@ class MessageLookup extends MessageLookupByLibrary { "maps": MessageLookupByLibrary.simpleMessage("地图"), "mastodon": MessageLookupByLibrary.simpleMessage("Mastodon"), "matrix": MessageLookupByLibrary.simpleMessage("Matrix"), - "memoryCount": m2, + "memoryCount": m3, "merchandise": MessageLookupByLibrary.simpleMessage("商品"), "mlConsent": MessageLookupByLibrary.simpleMessage("启用机器学习"), "mlConsentConfirmation": @@ -884,10 +889,10 @@ class MessageLookup extends MessageLookupByLibrary { "moreDetails": MessageLookupByLibrary.simpleMessage("更多详情"), "mostRecent": MessageLookupByLibrary.simpleMessage("最近"), "mostRelevant": MessageLookupByLibrary.simpleMessage("最相关"), - "moveItem": m39, + "moveItem": m40, "moveToAlbum": MessageLookupByLibrary.simpleMessage("移动到相册"), "moveToHiddenAlbum": MessageLookupByLibrary.simpleMessage("移至隐藏相册"), - "movedSuccessfullyTo": m40, + "movedSuccessfullyTo": m41, "movedToTrash": MessageLookupByLibrary.simpleMessage("已移至回收站"), "movingFilesToAlbum": MessageLookupByLibrary.simpleMessage("正在将文件移动到相册..."), @@ -926,7 +931,7 @@ class MessageLookup extends MessageLookupByLibrary { "noResults": MessageLookupByLibrary.simpleMessage("无结果"), "noResultsFound": MessageLookupByLibrary.simpleMessage("未找到任何结果"), "noSystemLockFound": MessageLookupByLibrary.simpleMessage("未找到系统锁"), - "notPersonLabel": m41, + "notPersonLabel": m42, "nothingSharedWithYouYet": MessageLookupByLibrary.simpleMessage("尚未与您共享任何内容"), "nothingToSeeHere": MessageLookupByLibrary.simpleMessage("这里空空如也! 👀"), @@ -935,7 +940,8 @@ class MessageLookup extends MessageLookupByLibrary { "onDevice": MessageLookupByLibrary.simpleMessage("在设备上"), "onEnte": MessageLookupByLibrary.simpleMessage( "在 ente 上"), - "onlyFamilyAdminCanChangeCode": m42, + "onlyFamilyAdminCanChangeCode": m43, + "onlyThem": MessageLookupByLibrary.simpleMessage("Only them"), "oops": MessageLookupByLibrary.simpleMessage("哎呀"), "oopsCouldNotSaveEdits": MessageLookupByLibrary.simpleMessage("糟糕,无法保存编辑"), @@ -970,7 +976,7 @@ class MessageLookup extends MessageLookupByLibrary { "paymentFailed": MessageLookupByLibrary.simpleMessage("支付失败"), "paymentFailedMessage": MessageLookupByLibrary.simpleMessage( "不幸的是,您的付款失败。请联系支持人员,我们将为您提供帮助!"), - "paymentFailedTalkToProvider": m43, + "paymentFailedTalkToProvider": m44, "pendingItems": MessageLookupByLibrary.simpleMessage("待处理项目"), "pendingSync": MessageLookupByLibrary.simpleMessage("正在等待同步"), "people": MessageLookupByLibrary.simpleMessage("人物"), @@ -990,7 +996,7 @@ class MessageLookup extends MessageLookupByLibrary { "pinAlbum": MessageLookupByLibrary.simpleMessage("置顶相册"), "pinLock": MessageLookupByLibrary.simpleMessage("PIN 锁定"), "playOnTv": MessageLookupByLibrary.simpleMessage("在电视上播放相册"), - "playStoreFreeTrialValidTill": m44, + "playStoreFreeTrialValidTill": m45, "playstoreSubscription": MessageLookupByLibrary.simpleMessage("PlayStore 订阅"), "pleaseCheckYourInternetConnectionAndTryAgain": @@ -1000,12 +1006,12 @@ class MessageLookup extends MessageLookupByLibrary { "请用英语联系 support@ente.io ,我们将乐意提供帮助!"), "pleaseContactSupportIfTheProblemPersists": MessageLookupByLibrary.simpleMessage("如果问题仍然存在,请联系支持"), - "pleaseEmailUsAt": m45, + "pleaseEmailUsAt": m46, "pleaseGrantPermissions": MessageLookupByLibrary.simpleMessage("请授予权限"), "pleaseLoginAgain": MessageLookupByLibrary.simpleMessage("请重新登录"), "pleaseSelectQuickLinksToRemove": MessageLookupByLibrary.simpleMessage("请选择要删除的快速链接"), - "pleaseSendTheLogsTo": m46, + "pleaseSendTheLogsTo": m47, "pleaseTryAgain": MessageLookupByLibrary.simpleMessage("请重试"), "pleaseVerifyTheCodeYouHaveEntered": MessageLookupByLibrary.simpleMessage("请验证您输入的代码"), @@ -1024,7 +1030,7 @@ class MessageLookup extends MessageLookupByLibrary { "privacyPolicyTitle": MessageLookupByLibrary.simpleMessage("隐私政策"), "privateBackups": MessageLookupByLibrary.simpleMessage("私人备份"), "privateSharing": MessageLookupByLibrary.simpleMessage("私人分享"), - "processingImport": m47, + "processingImport": m48, "publicLinkCreated": MessageLookupByLibrary.simpleMessage("公共链接已创建"), "publicLinkEnabled": MessageLookupByLibrary.simpleMessage("公开链接已启用"), "quickLinks": MessageLookupByLibrary.simpleMessage("快速链接"), @@ -1032,7 +1038,7 @@ class MessageLookup extends MessageLookupByLibrary { "raiseTicket": MessageLookupByLibrary.simpleMessage("提升工单"), "rateTheApp": MessageLookupByLibrary.simpleMessage("为此应用评分"), "rateUs": MessageLookupByLibrary.simpleMessage("给我们评分"), - "rateUsOnStore": m48, + "rateUsOnStore": m49, "recover": MessageLookupByLibrary.simpleMessage("恢复"), "recoverAccount": MessageLookupByLibrary.simpleMessage("恢复账户"), "recoverButton": MessageLookupByLibrary.simpleMessage("恢复"), @@ -1059,7 +1065,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("把我们推荐给你的朋友然后获得延长一倍的订阅计划"), "referralStep1": MessageLookupByLibrary.simpleMessage("1. 将此代码提供给您的朋友"), "referralStep2": MessageLookupByLibrary.simpleMessage("2. 他们注册一个付费计划"), - "referralStep3": m49, + "referralStep3": m50, "referrals": MessageLookupByLibrary.simpleMessage("推荐"), "referralsAreCurrentlyPaused": MessageLookupByLibrary.simpleMessage("推荐已暂停"), @@ -1080,7 +1086,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeFromFavorite": MessageLookupByLibrary.simpleMessage("从收藏中移除"), "removeLink": MessageLookupByLibrary.simpleMessage("移除链接"), "removeParticipant": MessageLookupByLibrary.simpleMessage("移除参与者"), - "removeParticipantBody": m50, + "removeParticipantBody": m51, "removePersonLabel": MessageLookupByLibrary.simpleMessage("移除人物标签"), "removePublicLink": MessageLookupByLibrary.simpleMessage("删除公开链接"), "removePublicLinks": MessageLookupByLibrary.simpleMessage("删除公开链接"), @@ -1093,12 +1099,13 @@ class MessageLookup extends MessageLookupByLibrary { "renameAlbum": MessageLookupByLibrary.simpleMessage("重命名相册"), "renameFile": MessageLookupByLibrary.simpleMessage("重命名文件"), "renewSubscription": MessageLookupByLibrary.simpleMessage("续费订阅"), - "renewsOn": m51, + "renewsOn": m52, "reportABug": MessageLookupByLibrary.simpleMessage("报告错误"), "reportBug": MessageLookupByLibrary.simpleMessage("报告错误"), "resendEmail": MessageLookupByLibrary.simpleMessage("重新发送电子邮件"), "resetIgnoredFiles": MessageLookupByLibrary.simpleMessage("重置忽略的文件"), "resetPasswordTitle": MessageLookupByLibrary.simpleMessage("重置密码"), + "resetPerson": MessageLookupByLibrary.simpleMessage("Reset person"), "resetToDefault": MessageLookupByLibrary.simpleMessage("重置为默认设置"), "restore": MessageLookupByLibrary.simpleMessage("恢复"), "restoreToAlbum": MessageLookupByLibrary.simpleMessage("恢复到相册"), @@ -1146,7 +1153,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("在照片的一定半径内拍摄的几组照片"), "searchPeopleEmptySection": MessageLookupByLibrary.simpleMessage("邀请他人,您将在此看到他们分享的所有照片"), - "searchResultCount": m52, + "searchResultCount": m53, "security": MessageLookupByLibrary.simpleMessage("安全"), "selectALocation": MessageLookupByLibrary.simpleMessage("选择一个位置"), "selectALocationFirst": @@ -1166,8 +1173,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("所选文件夹将被加密并备份"), "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": MessageLookupByLibrary.simpleMessage("所选项目将从所有相册中删除并移动到回收站。"), - "selectedPhotos": m3, - "selectedPhotosWithYours": m53, + "selectedPhotos": m4, + "selectedPhotosWithYours": m54, "send": MessageLookupByLibrary.simpleMessage("发送"), "sendEmail": MessageLookupByLibrary.simpleMessage("发送电子邮件"), "sendInvite": MessageLookupByLibrary.simpleMessage("发送邀请"), @@ -1189,16 +1196,16 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("打开相册并点击右上角的分享按钮进行分享"), "shareAnAlbumNow": MessageLookupByLibrary.simpleMessage("立即分享相册"), "shareLink": MessageLookupByLibrary.simpleMessage("分享链接"), - "shareMyVerificationID": m54, + "shareMyVerificationID": m55, "shareOnlyWithThePeopleYouWant": MessageLookupByLibrary.simpleMessage("仅与您想要的人分享"), - "shareTextConfirmOthersVerificationID": m4, + "shareTextConfirmOthersVerificationID": m5, "shareTextRecommendUsingEnte": MessageLookupByLibrary.simpleMessage("下载 Ente,让我们轻松共享高质量的原始照片和视频"), - "shareTextReferralCode": m55, + "shareTextReferralCode": m56, "shareWithNonenteUsers": MessageLookupByLibrary.simpleMessage("与非 Ente 用户共享"), - "shareWithPeopleSectionTitle": m56, + "shareWithPeopleSectionTitle": m57, "shareYourFirstAlbum": MessageLookupByLibrary.simpleMessage("分享您的第一个相册"), "sharedAlbumSectionDescription": MessageLookupByLibrary.simpleMessage( @@ -1209,7 +1216,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("新共享的照片"), "sharedPhotoNotificationsExplanation": MessageLookupByLibrary.simpleMessage("当有人将照片添加到您所属的共享相册时收到通知"), - "sharedWith": m57, + "sharedWith": m58, "sharedWithMe": MessageLookupByLibrary.simpleMessage("与我共享"), "sharedWithYou": MessageLookupByLibrary.simpleMessage("已与您共享"), "sharing": MessageLookupByLibrary.simpleMessage("正在分享..."), @@ -1222,11 +1229,11 @@ class MessageLookup extends MessageLookupByLibrary { "signOutOtherDevices": MessageLookupByLibrary.simpleMessage("登出其他设备"), "signUpTerms": MessageLookupByLibrary.simpleMessage( "我同意 服务条款隐私政策"), - "singleFileDeleteFromDevice": m58, + "singleFileDeleteFromDevice": m59, "singleFileDeleteHighlight": MessageLookupByLibrary.simpleMessage("它将从所有相册中删除。"), - "singleFileInBothLocalAndRemote": m59, - "singleFileInRemoteOnly": m60, + "singleFileInBothLocalAndRemote": m60, + "singleFileInRemoteOnly": m61, "skip": MessageLookupByLibrary.simpleMessage("跳过"), "social": MessageLookupByLibrary.simpleMessage("社交"), "someItemsAreInBothEnteAndYourDevice": @@ -1260,7 +1267,7 @@ class MessageLookup extends MessageLookupByLibrary { "storage": MessageLookupByLibrary.simpleMessage("存储空间"), "storageBreakupFamily": MessageLookupByLibrary.simpleMessage("家庭"), "storageBreakupYou": MessageLookupByLibrary.simpleMessage("您"), - "storageInGB": m61, + "storageInGB": m1, "storageLimitExceeded": MessageLookupByLibrary.simpleMessage("已超出存储限制"), "storageUsageInfo": m62, "strongStrength": MessageLookupByLibrary.simpleMessage("强"), @@ -1420,7 +1427,7 @@ class MessageLookup extends MessageLookupByLibrary { "weAreOpenSource": MessageLookupByLibrary.simpleMessage("我们是开源的 !"), "weDontSupportEditingPhotosAndAlbumsThatYouDont": MessageLookupByLibrary.simpleMessage("我们不支持编辑您尚未拥有的照片和相册"), - "weHaveSendEmailTo": m1, + "weHaveSendEmailTo": m2, "weakStrength": MessageLookupByLibrary.simpleMessage("弱"), "welcomeBack": MessageLookupByLibrary.simpleMessage("欢迎回来!"), "whatsNew": MessageLookupByLibrary.simpleMessage("更新日志"), @@ -1434,6 +1441,8 @@ class MessageLookup extends MessageLookupByLibrary { "yesLogout": MessageLookupByLibrary.simpleMessage("是的,退出登陆"), "yesRemove": MessageLookupByLibrary.simpleMessage("是,移除"), "yesRenew": MessageLookupByLibrary.simpleMessage("是的,续费"), + "yesResetPerson": + MessageLookupByLibrary.simpleMessage("Yes, reset person"), "you": MessageLookupByLibrary.simpleMessage("您"), "youAreOnAFamilyPlan": MessageLookupByLibrary.simpleMessage("你在一个家庭计划中!"), diff --git a/mobile/lib/generated/l10n.dart b/mobile/lib/generated/l10n.dart index c80a65da27..79766659ee 100644 --- a/mobile/lib/generated/l10n.dart +++ b/mobile/lib/generated/l10n.dart @@ -9835,6 +9835,76 @@ class S { args: [], ); } + + /// `Configuration` + String get configuration { + return Intl.message( + 'Configuration', + name: 'configuration', + desc: '', + args: [], + ); + } + + /// `Local indexing` + String get localIndexing { + return Intl.message( + 'Local indexing', + name: 'localIndexing', + desc: '', + args: [], + ); + } + + /// `Reset person` + String get resetPerson { + return Intl.message( + 'Reset person', + name: 'resetPerson', + desc: '', + args: [], + ); + } + + /// `Are you sure you want to reset this person?` + String get areYouSureYouWantToResetThisPerson { + return Intl.message( + 'Are you sure you want to reset this person?', + name: 'areYouSureYouWantToResetThisPerson', + desc: '', + args: [], + ); + } + + /// `All groupings for this person will be reset, and you will lose all suggestions made for this person` + String get allPersonGroupingWillReset { + return Intl.message( + 'All groupings for this person will be reset, and you will lose all suggestions made for this person', + name: 'allPersonGroupingWillReset', + desc: '', + args: [], + ); + } + + /// `Yes, reset person` + String get yesResetPerson { + return Intl.message( + 'Yes, reset person', + name: 'yesResetPerson', + desc: '', + args: [], + ); + } + + /// `Only them` + String get onlyThem { + return Intl.message( + 'Only them', + name: 'onlyThem', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/mobile/lib/l10n/intl_ar.arb b/mobile/lib/l10n/intl_ar.arb index 86273581a6..3069e48793 100644 --- a/mobile/lib/l10n/intl_ar.arb +++ b/mobile/lib/l10n/intl_ar.arb @@ -23,5 +23,10 @@ "noRecoveryKeyNoDecryption": "لا يمكن فك تشفير بياناتك دون كلمة المرور أو مفتاح الاسترداد بسبب طبيعة بروتوكول التشفير الخاص بنا من النهاية إلى النهاية", "verifyEmail": "التحقق من البريد الإلكتروني", "toResetVerifyEmail": "لإعادة تعيين كلمة المرور، يرجى التحقق من بريدك الإلكتروني أولاً.", - "ackPasswordLostWarning": "أُدركُ أنّني فقدتُ كلمة مروري، فقد أفقد بياناتي لأن بياناتي مشفرة تشفيرًا تامًّا من النهاية إلى النهاية." + "ackPasswordLostWarning": "أُدركُ أنّني فقدتُ كلمة مروري، فقد أفقد بياناتي لأن بياناتي مشفرة تشفيرًا تامًّا من النهاية إلى النهاية.", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_be.arb b/mobile/lib/l10n/intl_be.arb index 29dcdc72b2..888d2567b7 100644 --- a/mobile/lib/l10n/intl_be.arb +++ b/mobile/lib/l10n/intl_be.arb @@ -86,5 +86,123 @@ }, "message": "Password Strength: {passwordStrengthText}" }, - "passwordChangedSuccessfully": "Пароль паспяхова зменены" + "passwordChangedSuccessfully": "Пароль паспяхова зменены", + "generatingEncryptionKeys": "Генерацыя ключоў шыфравання...", + "pleaseWait": "Пачакайце...", + "continueLabel": "Працягнуць", + "insecureDevice": "Небяспечная прылада", + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Немагчыма згенерыраваць ключы бяспекі на гэтай прыладзе.\n\nЗарэгіструйцеся з іншай прылады.", + "howItWorks": "Як гэта працуе", + "encryption": "Шыфраванне", + "ackPasswordLostWarning": "Я ўсведамляю, што калі я страчу свой пароль, то я магу згубіць свае даныя, бо мае даныя абаронены скразным шыфраваннем.", + "privacyPolicyTitle": "Палітыка прыватнасці", + "termsOfServicesTitle": "Умовы", + "signUpTerms": "Я пагаджаюся з умовамі абслугоўвання і палітыкай прыватнасці", + "logInLabel": "Увайсці", + "loginTerms": "Націскаючы ўвайсці, я пагаджаюся з умовамі абслугоўвання і палітыкай прыватнасці", + "changeEmail": "Змяніць адрас электроннай пошты", + "enterYourPassword": "Увядзіце свой пароль", + "welcomeBack": "З вяртаннем!", + "contactSupport": "Звярніцеся ў службу падтрымкі", + "incorrectPasswordTitle": "Няправільны пароль", + "pleaseTryAgain": "Паспрабуйце яшчэ раз", + "recreatePasswordTitle": "Стварыць пароль паўторна", + "useRecoveryKey": "Выкарыстоўваць ключ аднаўлення", + "recreatePasswordBody": "У бягучай прылады недастаткова вылічальнай здольнасці для праверкі вашага паролю, але мы можам регенерыраваць яго, бо гэта працуе з усімі прыладамі.\n\nУвайдзіце, выкарыстоўваючы свой ключа аднаўлення і регенерыруйце свой пароль (калі хочаце, то можаце выбраць папярэдні пароль).", + "verifyPassword": "Праверыць пароль", + "recoveryKey": "Ключ аднаўлення", + "recoveryKeyOnForgotPassword": "Адзіным спосабам аднавіць вашы даныя з'яўляецца гэты ключ, калі вы забылі свой пароль.", + "recoveryKeySaveDescription": "Захавайце гэты ключ, які складаецца з 24 слоў, у наедзеным месцы. Ён не захоўваецца на нашым серверы.", + "doThisLater": "Зрабіць гэта пазней", + "saveKey": "Захаваць ключ", + "recoveryKeyCopiedToClipboard": "Ключ аднаўлення скапіяваны ў буфер абмену", + "recoverAccount": "Аднавіць уліковы запіс", + "recover": "Аднавіць", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "enterCode": "Увядзіце код", + "scanCode": "Сканіраваць код", + "confirm": "Пацвердзіць", + "setupComplete": "Наладжванне завершана", + "twofactorAuthenticationPageTitle": "Двухфактарная аўтэнтыфікацыя", + "albumOwner": "Уладальнік", + "@albumOwner": { + "description": "Role of the album owner" + }, + "you": "Вы", + "addMore": "Дадаць яшчэ", + "@addMore": { + "description": "Button text to add more collaborators/viewers" + }, + "viewer": "Праглядальнік", + "remove": "Выдаліць", + "removeParticipant": "Выдаліць удзельніка", + "@removeParticipant": { + "description": "menuSectionTitle for removing a participant" + }, + "manage": "Кіраванне", + "never": "Ніколі", + "after1Hour": "Праз 1 гадзіну", + "after1Day": "Праз 1 дзень", + "after1Week": "Праз 1 тыдзень", + "after1Month": "Праз 1 месяц", + "after1Year": "Праз 1 год", + "manageParticipants": "Кіраванне", + "sendLink": "Адправіць спасылку", + "copyLink": "Скапіяваць спасылку", + "done": "Гатова", + "apply": "Ужыць", + "codeAppliedPageTitle": "Код ужыты", + "change": "Змяніць", + "storageInGB": "{storageAmountInGB} Гб", + "details": "Падрабязнасці", + "deleteAlbum": "Выдаліць альбом", + "yesRemove": "Так, выдаліць", + "removeWithQuestionMark": "Выдаліць?", + "deletePhotos": "Выдаліць фота", + "trash": "Сметніца", + "uncategorized": "Без катэгорыі", + "videoSmallCase": "відэа", + "photoSmallCase": "фота", + "deleteFromEnte": "Выдаліць з Ente", + "yesDelete": "Так, выдаліць", + "magicSearch": "Магічны пошук", + "discover_screenshots": "Скрыншоты", + "discover_receipts": "Чэкі", + "discover_notes": "Нататкі", + "discover_pets": "Хатнія жывёлы", + "discover_selfies": "Сэлфi", + "discover_wallpapers": "Шпалеры", + "discover_food": "Ежа", + "status": "Стан", + "selectAll": "Абраць усё", + "skip": "Прапусціць", + "about": "Пра праграму", + "logout": "Выйсці", + "yesLogout": "Так, выйсці", + "update": "Абнавіць", + "installManually": "Усталяваць уручную", + "updateAvailable": "Даступна абнаўленне", + "ignoreUpdate": "Iгнараваць", + "retry": "Паўтарыць", + "backup": "Рэзервовая копія", + "removeDuplicates": "Выдаліць дублікаты", + "viewLargeFiles": "Вялікія файлы", + "noDuplicates": "✨ Няма дублікатаў", + "rateUs": "Ацаніце нас", + "familyPlans": "Сямейныя тарыфныя планы", + "notifications": "Апавяшчэнні", + "general": "Асноўныя", + "security": "Бяспека", + "lockscreen": "Экран блакіроўкі", + "support": "Падтрымка", + "theme": "Тема", + "lightTheme": "Светлая", + "darkTheme": "Цёмная", + "systemTheme": "Сістэма", + "freeTrial": "Бясплатная пробная версія", + "faqs": "Частыя пытанні", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_bg.arb b/mobile/lib/l10n/intl_bg.arb index c8494661c6..43569df71a 100644 --- a/mobile/lib/l10n/intl_bg.arb +++ b/mobile/lib/l10n/intl_bg.arb @@ -1,3 +1,8 @@ { - "@@locale ": "en" + "@@locale ": "en", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ca.arb b/mobile/lib/l10n/intl_ca.arb index c8494661c6..43569df71a 100644 --- a/mobile/lib/l10n/intl_ca.arb +++ b/mobile/lib/l10n/intl_ca.arb @@ -1,3 +1,8 @@ { - "@@locale ": "en" + "@@locale ": "en", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_cs.arb b/mobile/lib/l10n/intl_cs.arb index 2bd9d2da70..0e569cf3c3 100644 --- a/mobile/lib/l10n/intl_cs.arb +++ b/mobile/lib/l10n/intl_cs.arb @@ -2,5 +2,10 @@ "@@locale ": "en", "askDeleteReason": "Jaký je váš hlavní důvod, proč mažete svůj účet?", "incorrectRecoveryKeyBody": "", - "checkInboxAndSpamFolder": "Zkontrolujte prosím svou doručenou poštu (a spam) pro dokončení ověření" + "checkInboxAndSpamFolder": "Zkontrolujte prosím svou doručenou poštu (a spam) pro dokončení ověření", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_da.arb b/mobile/lib/l10n/intl_da.arb index e4b2cc656b..52fef4db14 100644 --- a/mobile/lib/l10n/intl_da.arb +++ b/mobile/lib/l10n/intl_da.arb @@ -84,5 +84,10 @@ "longPressAnEmailToVerifyEndToEndEncryption": "Langt tryk på en e-mail for at bekræfte slutningen af krypteringen.", "developerSettingsWarning": "Er du sikker på, at du vil ændre udviklerindstillingerne?", "next": "Næste", - "enterPin": "Indtast PIN" + "enterPin": "Indtast PIN", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_de.arb b/mobile/lib/l10n/intl_de.arb index 110e15d75f..93145fe083 100644 --- a/mobile/lib/l10n/intl_de.arb +++ b/mobile/lib/l10n/intl_de.arb @@ -1352,5 +1352,12 @@ "addName": "Name hinzufügen", "add": "Hinzufügen", "extraPhotosFoundFor": "Zusätzliche Fotos gefunden für $text", - "extraPhotosFound": "Zusätzliche Fotos gefunden" + "extraPhotosFound": "Zusätzliche Fotos gefunden", + "configuration": "Konfiguration", + "localIndexing": "Lokale Indizierung", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_el.arb b/mobile/lib/l10n/intl_el.arb index ce8b1a1a54..2663d4c7a2 100644 --- a/mobile/lib/l10n/intl_el.arb +++ b/mobile/lib/l10n/intl_el.arb @@ -1,4 +1,9 @@ { "@@locale ": "en", - "enterYourEmailAddress": "Εισάγετε την διεύθυνση ηλ. ταχυδρομείου σας" + "enterYourEmailAddress": "Εισάγετε την διεύθυνση ηλ. ταχυδρομείου σας", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_en.arb b/mobile/lib/l10n/intl_en.arb index 417ab6ddc6..ed1a09d001 100644 --- a/mobile/lib/l10n/intl_en.arb +++ b/mobile/lib/l10n/intl_en.arb @@ -1352,5 +1352,12 @@ "addName": "Add name", "add": "Add", "extraPhotosFoundFor": "Extra photos found for $text", - "extraPhotosFound": "Extra photos found" + "extraPhotosFound": "Extra photos found", + "configuration": "Configuration", + "localIndexing": "Local indexing", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_es.arb b/mobile/lib/l10n/intl_es.arb index 482714f70c..53e0100765 100644 --- a/mobile/lib/l10n/intl_es.arb +++ b/mobile/lib/l10n/intl_es.arb @@ -1343,5 +1343,10 @@ "mostRecent": "Más reciente", "mostRelevant": "Más relevante", "loadingYourPhotos": "Cargando tus fotos...", - "processingImport": "Procesando {folderName}..." + "processingImport": "Procesando {folderName}...", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_et.arb b/mobile/lib/l10n/intl_et.arb index c8494661c6..43569df71a 100644 --- a/mobile/lib/l10n/intl_et.arb +++ b/mobile/lib/l10n/intl_et.arb @@ -1,3 +1,8 @@ { - "@@locale ": "en" + "@@locale ": "en", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_fa.arb b/mobile/lib/l10n/intl_fa.arb index 8d957cf574..a7268cb4eb 100644 --- a/mobile/lib/l10n/intl_fa.arb +++ b/mobile/lib/l10n/intl_fa.arb @@ -307,5 +307,10 @@ "developerSettings": "تنظیمات توسعه‌دهنده", "search": "جستجو", "whatsNew": "تغییرات جدید", - "reviewSuggestions": "مرور پیشنهادها" + "reviewSuggestions": "مرور پیشنهادها", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_fr.arb b/mobile/lib/l10n/intl_fr.arb index 91e87efbed..cca10148a1 100644 --- a/mobile/lib/l10n/intl_fr.arb +++ b/mobile/lib/l10n/intl_fr.arb @@ -1343,5 +1343,10 @@ "mostRecent": "Les plus récents", "mostRelevant": "Les plus pertinents", "loadingYourPhotos": "Chargement de vos photos...", - "processingImport": "Traitement de {folderName}..." + "processingImport": "Traitement de {folderName}...", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_gu.arb b/mobile/lib/l10n/intl_gu.arb index c8494661c6..43569df71a 100644 --- a/mobile/lib/l10n/intl_gu.arb +++ b/mobile/lib/l10n/intl_gu.arb @@ -1,3 +1,8 @@ { - "@@locale ": "en" + "@@locale ": "en", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_he.arb b/mobile/lib/l10n/intl_he.arb index 961b9f38d6..d0e1ab9789 100644 --- a/mobile/lib/l10n/intl_he.arb +++ b/mobile/lib/l10n/intl_he.arb @@ -816,5 +816,10 @@ "addPhotos": "הוסף תמונות", "create": "צור", "viewAll": "הצג הכל", - "hiding": "מחביא..." + "hiding": "מחביא...", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_hi.arb b/mobile/lib/l10n/intl_hi.arb index b79d9682f2..719678c8fc 100644 --- a/mobile/lib/l10n/intl_hi.arb +++ b/mobile/lib/l10n/intl_hi.arb @@ -48,5 +48,10 @@ "sorry": "क्षमा करें!", "noRecoveryKeyNoDecryption": "हमारे एंड-टू-एंड एन्क्रिप्शन प्रोटोकॉल की प्रकृति के कारण, आपके डेटा को आपके पासवर्ड या रिकवरी कुंजी के बिना डिक्रिप्ट नहीं किया जा सकता है", "verifyEmail": "ईमेल सत्यापित करें", - "toResetVerifyEmail": "अपना पासवर्ड रीसेट करने के लिए, कृपया पहले अपना ईमेल सत्यापित करें।" + "toResetVerifyEmail": "अपना पासवर्ड रीसेट करने के लिए, कृपया पहले अपना ईमेल सत्यापित करें।", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_id.arb b/mobile/lib/l10n/intl_id.arb index 8a72ca4da5..157bb707e4 100644 --- a/mobile/lib/l10n/intl_id.arb +++ b/mobile/lib/l10n/intl_id.arb @@ -1143,5 +1143,10 @@ "rotate": "Putar", "left": "Kiri", "right": "Kanan", - "whatsNew": "Hal yang baru" + "whatsNew": "Hal yang baru", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_it.arb b/mobile/lib/l10n/intl_it.arb index f96fd0f7ad..61c9e2f898 100644 --- a/mobile/lib/l10n/intl_it.arb +++ b/mobile/lib/l10n/intl_it.arb @@ -1343,5 +1343,10 @@ "mostRecent": "Più recenti", "mostRelevant": "Più rilevanti", "loadingYourPhotos": "Caricando le tue foto...", - "processingImport": "Elaborando {folderName}..." + "processingImport": "Elaborando {folderName}...", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ja.arb b/mobile/lib/l10n/intl_ja.arb index 97a7e21359..ab2cb93f24 100644 --- a/mobile/lib/l10n/intl_ja.arb +++ b/mobile/lib/l10n/intl_ja.arb @@ -1343,5 +1343,10 @@ "mostRecent": "新しい順", "mostRelevant": "関連度順", "loadingYourPhotos": "写真を読み込んでいます...", - "processingImport": "{folderName} を処理中..." + "processingImport": "{folderName} を処理中...", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_km.arb b/mobile/lib/l10n/intl_km.arb index c8494661c6..43569df71a 100644 --- a/mobile/lib/l10n/intl_km.arb +++ b/mobile/lib/l10n/intl_km.arb @@ -1,3 +1,8 @@ { - "@@locale ": "en" + "@@locale ": "en", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ko.arb b/mobile/lib/l10n/intl_ko.arb index 06c81195f7..e275016f29 100644 --- a/mobile/lib/l10n/intl_ko.arb +++ b/mobile/lib/l10n/intl_ko.arb @@ -12,5 +12,10 @@ "feedback": "피드백", "confirmAccountDeletion": "계정 삭제 확인", "deleteAccountPermanentlyButton": "계정을 영구적으로 삭제", - "yourAccountHasBeenDeleted": "계정이 삭제되었습니다." + "yourAccountHasBeenDeleted": "계정이 삭제되었습니다.", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_lt.arb b/mobile/lib/l10n/intl_lt.arb index e33098b3be..2b35f84ae6 100644 --- a/mobile/lib/l10n/intl_lt.arb +++ b/mobile/lib/l10n/intl_lt.arb @@ -5,7 +5,7 @@ "email": "El. paštas", "cancel": "Atšaukti", "verify": "Patvirtinti", - "invalidEmailAddress": "Netinkamas el. pašto adresas.", + "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ą?", @@ -13,10 +13,10 @@ "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ą", + "confirmAccountDeletion": "Patvirtinkite paskyros ištrynimą", "deleteAccountPermanentlyButton": "Ištrinti paskyrą negrįžtamai", - "yourAccountHasBeenDeleted": "Jūsų paskyra buvo ištrinta", - "selectReason": "Pasirinkti priežastį", + "yourAccountHasBeenDeleted": "Jūsų paskyra ištrinta", + "selectReason": "Pasirinkite 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", @@ -29,22 +29,72 @@ "createAccount": "Kurti paskyrą", "createNewAccount": "Kurti naują paskyrą", "password": "Slaptažodis", - "confirmPassword": "Patvirtinti slaptažodį", + "confirmPassword": "Patvirtinkite 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:", + "terminateSession": "Baigti seansą?", + "terminate": "Baigti", "thisDevice": "Šis įrenginys", "recoverButton": "Atkurti", "recoverySuccessful": "Atkūrimas sėkmingas.", "decrypting": "Iššifruojama...", + "incorrectRecoveryKeyTitle": "Neteisingas atkūrimo raktas", + "incorrectRecoveryKeyBody": "Įvestas atkūrimo raktas yra neteisingas.", + "forgotPassword": "Pamiršau slaptažodį", + "enterYourRecoveryKey": "Įveskite atkūrimo raktą", + "noRecoveryKey": "Neturite atkūrimo rakto?", "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ą", + "toResetVerifyEmail": "Kad iš naujo nustatytumėte slaptažodį, pirmiausia patvirtinkite savo el. paštą.", + "checkInboxAndSpamFolder": "Patikrinkite savo gautieją (ir šlamštą), kad užbaigtumėte patvirtinimą", + "tapToEnterCode": "Palieskite, kad įvestumėte kodą", + "resendEmail": "Iš naujo siųsti el. laišką", + "weHaveSendEmailTo": "Išsiuntėme laišką adresu {email}", + "@weHaveSendEmailTo": { + "description": "Text to indicate that we have sent a mail to the user", + "placeholders": { + "email": { + "description": "The email address of the user", + "type": "String", + "example": "example@ente.io" + } + } + }, + "setPasswordTitle": "Nustatyti slaptažodį", + "changePasswordTitle": "Keisti slaptažodį", + "resetPasswordTitle": "Nustatyti slaptažodį iš naujo", + "encryptionKeys": "Šifravimo raktai", + "passwordWarning": "Šio slaptažodžio nesaugome, todėl jei jį pamiršite, negalėsime iššifruoti jūsų duomenų", + "enterPasswordToEncrypt": "Įveskite slaptažodį, kurį galime naudoti jūsų duomenims šifruoti", + "enterNewPasswordToEncrypt": "Įveskite naują slaptažodį, kurį galime naudoti jūsų duomenims šifruoti", + "weakStrength": "Silpna", + "strongStrength": "Stipri", + "moderateStrength": "Vidutinė", + "passwordStrength": "Slaptažodžio stiprumas: {passwordStrengthValue}", + "@passwordStrength": { + "description": "Text to indicate the password strength", + "placeholders": { + "passwordStrengthValue": { + "description": "The strength of the password as a string", + "type": "String", + "example": "Weak or Moderate or Strong" + } + }, + "message": "Password Strength: {passwordStrengthText}" + }, + "passwordChangedSuccessfully": "Slaptažodis sėkmingai pakeistas", + "generatingEncryptionKeys": "Generuojami šifravimo raktai...", + "pleaseWait": "Palaukite...", + "continueLabel": "Tęsti", + "insecureDevice": "Nesaugus įrenginys", + "sorryWeCouldNotGenerateSecureKeysOnThisDevicennplease": "Atsiprašome, šiame įrenginyje nepavyko sugeneruoti saugių raktų.\n\nRegistruokitės iš kito įrenginio.", "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.", + "ackPasswordLostWarning": "Suprantu, kad jei prarasiu slaptažodį, galiu prarasti savo duomenis, kadangi mano duomenys yra visapusiškai užšifruoti.", "privacyPolicyTitle": "Privatumo politika", "termsOfServicesTitle": "Sąlygos", "signUpTerms": "Sutinku su paslaugų sąlygomis ir privatumo politika", @@ -54,16 +104,187 @@ "enterYourPassword": "Įveskite savo slaptažodį", "welcomeBack": "Sveiki sugrįžę!", "contactSupport": "Susisiekti su palaikymo komanda", - "incorrectPasswordTitle": "Neteisingas slaptažodis.", + "incorrectPasswordTitle": "Neteisingas slaptažodis", + "pleaseTryAgain": "Bandykite dar kartą.", + "recreatePasswordTitle": "Iš naujo sukurti slaptažodį", + "useRecoveryKey": "Naudoti atkūrimo raktą", + "recreatePasswordBody": "Dabartinis įrenginys nėra pakankamai galingas, kad patvirtintų jūsų slaptažodį, bet mes galime iš naujo sugeneruoti taip, kad jis veiktų su visais įrenginiais.\n\nPrisijunkite naudojant atkūrimo raktą ir sugeneruokite iš naujo slaptažodį (jei norite, galite vėl naudoti tą patį).", + "verifyPassword": "Patvirtinkite slaptažodį", + "recoveryKey": "Atkūrimo raktas", + "recoveryKeyOnForgotPassword": "Jei pamiršote slaptažodį, vienintelis būdas atkurti duomenis – naudoti šį raktą.", + "recoveryKeySaveDescription": "Šio rakto nesaugome, todėl išsaugokite šį 24 žodžių raktą saugioje vietoje.", + "doThisLater": "Daryti tai vėliau", + "saveKey": "Išsaugoti raktą", + "recoveryKeyCopiedToClipboard": "Nukopijuotas atkūrimo raktas į iškarpinę", + "recoverAccount": "Atkurti paskyrą", + "recover": "Atkurti", + "dropSupportEmail": "Iš savo registruoto el. pašto adreso atsiųskite el. laišką adresu {supportEmail}", + "@dropSupportEmail": { + "placeholders": { + "supportEmail": { + "description": "The support email address", + "type": "String", + "example": "support@ente.io" + } + } + }, + "twofactorSetup": "Dvigubo tapatybės nustatymo sąranka", + "enterCode": "Įvesti kodą", + "scanCode": "Skenuoti kodą", + "codeCopiedToClipboard": "Nukopijuotas kodas į iškarpinę", + "copypasteThisCodentoYourAuthenticatorApp": "Nukopijuokite ir įklijuokite šį kodą\nį autentifikatoriaus programą", + "tapToCopy": "palieskite, kad nukopijuotumėte", + "scanThisBarcodeWithnyourAuthenticatorApp": "Skenuokite šį QR kodą\nsu autentifikatoriaus programa", + "enterThe6digitCodeFromnyourAuthenticatorApp": "Įveskite 6 skaitmenų kodą\niš autentifikatoriaus programos", + "confirm": "Patvirtinti", + "setupComplete": "Sąranka baigta", + "saveYourRecoveryKeyIfYouHaventAlready": "Išsaugokite atkūrimo raktą, jei dar to nepadarėte", + "thisCanBeUsedToRecoverYourAccountIfYou": "Tai gali būti naudojama paskyrai atkurti, jei prarandate dvigubo tapatybės nustatymą", + "twofactorAuthenticationPageTitle": "Dvigubas tapatybės nustatymas", + "lostDevice": "Prarastas įrenginys?", + "verifyingRecoveryKey": "Patvirtinima atkūrimo raktą...", + "recoveryKeyVerified": "Patvirtintas atkūrimo raktas", + "recoveryKeySuccessBody": "Puiku! Jūsų atkūrimo raktas tinkamas. Dėkojame už patvirtinimą.\n\nNepamirškite sukurti saugią atkūrimo rakto atsarginę kopiją.", + "invalidRecoveryKey": "Įvestas atkūrimo raktas yra netinkamas. Įsitikinkite, kad jame yra 24 žodžiai, ir patikrinkite kiekvieno iš jų rašybą.\n\nJei įvedėte senesnį atkūrimo kodą, įsitikinkite, kad jis yra 64 simbolių ilgio, ir patikrinkite kiekvieną iš jų.", + "invalidKey": "Netinkamas raktas.", + "tryAgain": "Bandyti dar kartą", + "viewRecoveryKey": "Peržiūrėti atkūrimo raktą", + "confirmRecoveryKey": "Patvirtinkite atkūrimo raktą", + "recoveryKeyVerifyReason": "Atkūrimo raktas – vienintelis būdas atkurti nuotraukas, jei pamiršote slaptažodį. Atkūrimo raktą galite rasti Nustatymose > Paskyra.\n\nĮveskite savo atkūrimo raktą čia, kad patvirtintumėte, ar teisingai jį išsaugojote.", + "confirmYourRecoveryKey": "Patvirtinkite savo atkūrimo raktą", + "addViewer": "Pridėti žiūrėtoją", + "addCollaborator": "Pridėti bendradarbį", + "addANewEmail": "Pridėti naują el. paštą", + "orPickAnExistingOne": "Arba pasirinkite esamą", + "collaboratorsCanAddPhotosAndVideosToTheSharedAlbum": "Bendradarbiai gali pridėti nuotraukų ir vaizdo įrašų į bendrintą albumą.", + "enterEmail": "Įveskite el. paštą", + "addMore": "Pridėti daugiau", + "@addMore": { + "description": "Button text to add more collaborators/viewers" + }, + "remove": "Šalinti", + "removeParticipant": "Šalinti dalyvį", + "@removeParticipant": { + "description": "menuSectionTitle for removing a participant" + }, + "changePermissions": "Keisti leidimus?", + "yesConvertToViewer": "Taip, keisti į žiūrėtoją", + "cannotAddMorePhotosAfterBecomingViewer": "{user} negalės pridėti daugiau nuotraukų į šį albumą\n\nJie vis tiek galės pašalinti esamas pridėtas nuotraukas", + "allowAddingPhotos": "Leisti pridėti nuotraukų", + "@allowAddingPhotos": { + "description": "Switch button to enable uploading photos to a public link" + }, + "allowAddPhotosDescription": "Leiskite nuorodą turintiems asmenims taip pat pridėti nuotraukų į bendrinamą albumą.", + "passwordLock": "Slaptažodžio užraktas", + "disableDownloadWarningTitle": "Atkreipkite dėmesį", + "disableDownloadWarningBody": "Žiūrėtojai vis tiek gali daryti ekrano kopijas arba išsaugoti nuotraukų kopijas naudojant išorinius įrankius", + "allowDownloads": "Leisti atsisiuntimus", + "linkDeviceLimit": "Įrenginių riba", + "noDeviceLimit": "Jokio", + "@noDeviceLimit": { + "description": "Text to indicate that there is limit on number of devices" + }, + "linkExpiry": "Nuorodos galiojimo laikas", + "linkEnabled": "Įjungta", + "linkNeverExpires": "Niekada", + "setAPassword": "Nustatyti slaptažodį", + "lockButtonLabel": "Užrakinti", + "enterPassword": "Įveskite slaptažodį", + "removeLink": "Šalinti nuorodą", + "manageLink": "Tvarkyti nuorodą", + "albumUpdated": "Atnaujintas albumas", + "never": "Niekada", + "custom": "Pasirinktinis", + "@custom": { + "description": "Label for setting custom value for link expiry" + }, + "after1Hour": "Po 1 valandos", + "after1Day": "Po 1 dienos", + "after1Week": "Po 1 savaitės", + "after1Month": "Po 1 mėnesio", + "after1Year": "Po 1 metų", + "manageParticipants": "Tvarkyti", + "collabLinkSectionDescription": "Sukurkite nuorodą, kad asmenys galėtų pridėti ir peržiūrėti nuotraukas bendrinamame albume, nereikalaujant „Ente“ programos ar paskyros. Puikiai tinka renginių nuotraukoms rinkti.", + "sendLink": "Siųsti nuorodą", + "copyLink": "Kopijuoti nuorodą", + "emailNoEnteAccount": "{email} neturi „Ente“ paskyros.\n\nSiųskite jiems kvietimą bendrinti nuotraukas.", + "applyCodeTitle": "Taikyti kodą", + "apply": "Taikyti", + "codeAppliedPageTitle": "Pritaikytas kodas", + "change": "Keisti", + "unavailableReferralCode": "Atsiprašome, šis kodas nepasiekiamas.", + "codeChangeLimitReached": "Atsiprašome, pasiekėte kodo pakeitimų ribą.", "storageInGB": "{storageAmountInGB} GB", "faq": "DUK", + "total": "iš viso", + "removeFromAlbumTitle": "Pašalinti iš albumo?", + "removeFromAlbum": "Šalinti iš albumo", + "itemsWillBeRemovedFromAlbum": "Pasirinkti elementai bus pašalinti iš šio albumo", + "removeShareItemsWarning": "Kai kuriuos elementus, kuriuos šalinate, pridėjo kiti asmenys, todėl prarasite prieigą prie jų", + "sorryCouldNotRemoveFromFavorites": "Atsiprašome, nepavyko pašalinti iš mėgstamų.", "subscribeToEnableSharing": "Kad įjungtumėte bendrinimą, reikia aktyvios mokamos prenumeratos.", "subscribe": "Prenumeruoti", + "canOnlyRemoveFilesOwnedByYou": "Galima pašalinti tik jums priklausančius failus", + "deleteAlbum": "Ištrinti albumą", + "deleteAlbumDialog": "Taip pat ištrinti šiame albume esančias nuotraukas (ir vaizdo įrašus) iš visų kitų albumų, kuriuose jos yra dalis?", + "yesRemove": "Taip, šalinti", + "creatingLink": "Kuriama nuoroda...", + "removeWithQuestionMark": "Šalinti?", + "removeParticipantBody": "{userEmail} bus pašalintas iš šio bendrinamo albumo\n\nVisos jų pridėtos nuotraukos taip pat bus pašalintos iš albumo", "keepPhotos": "Palikti nuotraukas", "deletePhotos": "Ištrinti nuotraukas", "inviteToEnte": "Kviesti į „Ente“", + "removePublicLink": "Šalinti viešą nuorodą", + "importing": "Importuojama....", + "hidden": "Paslėpti", + "uncategorized": "Nekategorizuoti", + "videoSmallCase": "vaizdo įrašas", "photoSmallCase": "nuotrauka", - "machineLearning": "Kompiuterinis mokymasis", + "singleFileInBothLocalAndRemote": "Šis {fileType} yra ir platformoje „Ente“ bei įrenginyje.", + "singleFileInRemoteOnly": "Šis {fileType} bus ištrintas iš „Ente“.", + "deleteFromEnte": "Ištrinti iš „Ente“", + "yesDelete": "Taip, ištrinti", + "movedToTrash": "Perkelta į šiukšlinę", + "deleteFromDevice": "Ištrinti iš įrenginio", + "deleteFromBoth": "Ištrinti iš abiejų", + "newAlbum": "Naujas albumas", + "albums": "Albumai", + "selectedPhotos": "{count} pasirinkta", + "@selectedPhotos": { + "description": "Display the number of selected photos", + "type": "text", + "placeholders": { + "count": { + "example": "5", + "type": "int" + } + } + }, + "selectedPhotosWithYours": "{count} pasirinkta ({yourCount} jūsų)", + "@selectedPhotosWithYours": { + "description": "Display the number of selected photos, including the number of selected photos owned by the user", + "type": "text", + "placeholders": { + "count": { + "example": "12", + "type": "int" + }, + "yourCount": { + "example": "2", + "type": "int" + } + } + }, + "advancedSettings": "Išplėstiniai", + "@advancedSettings": { + "description": "The text to display in the advanced settings section" + }, + "machineLearning": "Mašininis mokymasis", + "mlConsent": "Įjungti mašininį mokymąsi", + "mlConsentTitle": "Įjungti mašininį mokymąsi?", + "mlConsentDescription": "Jei įjungsite mašininį mokymąsi, „Ente“ išsitrauks tokią informaciją kaip veido geometrija iš failų, įskaitant tuos, kuriais su jumis bendrinama.\n\nTai bus daroma jūsų įrenginyje, o visa sugeneruota biometrinė informacija bus visapusiškai užšifruota.", + "mlConsentPrivacy": "Spustelėkite čia dėl išsamesnės informacijos apie šią funkciją mūsų privatumo politikoje", + "mlConsentConfirmation": "Suprantu ir noriu įjungti mašininį mokymąsi", "magicSearch": "Magiška paieška", "discover": "Atraskite", "@discover": { @@ -73,6 +294,7 @@ "discover_screenshots": "Ekrano kopijos", "discover_receipts": "Kvitai", "discover_notes": "Užrašai", + "discover_memes": "Mėmai", "discover_visiting_cards": "Lankymo kortelės", "discover_babies": "Kūdikiai", "discover_pets": "Gyvūnai", @@ -83,7 +305,51 @@ "discover_sunset": "Saulėlydis", "discover_hills": "Kalvos", "discover_greenery": "Žaluma", + "status": "Būsena", + "indexedItems": "Indeksuoti elementai", + "pendingItems": "Laukiami elementai", + "skip": "Praleisti", + "duplicateItemsGroup": "{count} failai (-ų), kiekvienas {formattedSize}", + "@duplicateItemsGroup": { + "description": "Display the number of duplicate files and their size", + "type": "text", + "placeholders": { + "count": { + "example": "12", + "type": "int" + }, + "formattedSize": { + "example": "2.3 MB", + "type": "String" + } + } + }, + "about": "Apie", + "weAreOpenSource": "Esame atviro kodo!", + "privacy": "Privatumas", + "terms": "Sąlygos", + "checkForUpdates": "Tikrinti, ar yra atnaujinimų", + "checkStatus": "Tikrinti būseną", + "checking": "Tikrinama...", + "youAreOnTheLatestVersion": "Esate naujausioje versijoje", + "account": "Paskyra", + "manageSubscription": "Tvarkyti prenumeratą", + "authToChangeYourEmail": "Nustatykite tapatybę, kad pakeistumėte savo el. paštą", + "changePassword": "Keisti slaptažodį", + "authToChangeYourPassword": "Nustatykite tapatybę, kad pakeistumėte slaptažodį", + "emailVerificationToggle": "El. pašto patvirtinimas", + "authToChangeEmailVerificationSetting": "Nustatykite tapatybę, kad pakeistumėte el. pašto patvirtinimą", + "exportYourData": "Eksportuoti duomenis", + "logout": "Atsijungti", + "authToInitiateAccountDeletion": "Nustatykite tapatybę, kad pradėtumėte paskyros ištrynimą", + "areYouSureYouWantToLogout": "Ar tikrai norite atsijungti?", + "yesLogout": "Taip, atsijungti", + "removeDuplicates": "Šalinti dublikatus", + "youveNoDuplicateFilesThatCanBeCleared": "Neturite dubliuotų failų, kuriuos būtų galima išvalyti", + "no": "Ne", + "yes": "Taip", "social": "Socialinės", + "rateUsOnStore": "Vertinti mus parduotuvėje „{storeName}“", "blog": "Tinklaraštis", "merchandise": "Atributika", "twitter": "„Twitter“", @@ -100,13 +366,199 @@ "lightTheme": "Šviesi", "darkTheme": "Tamsi", "systemTheme": "Sistemos", - "upgrade": "Atnaujinti", + "freeTrial": "Nemokamas bandomasis laikotarpis", + "selectYourPlan": "Pasirinkite planą", + "enteSubscriptionPitch": "„Ente“ išsaugo jūsų prisiminimus, todėl jie visada bus pasiekiami, net jei prarasite įrenginį.", + "currentUsageIs": "Dabartinis naudojimas – ", + "@currentUsageIs": { + "description": "This text is followed by storage usage", + "examples": { + "0": "Current usage is 1.2 GB" + }, + "type": "text" + }, + "faqs": "DUK", + "freeTrialValidTill": "Nemokamas bandomasis laikotarpis galioja iki {endDate}", + "validTill": "Galioja iki {endDate}", + "subscription": "Prenumerata", + "paymentDetails": "Mokėjimo duomenys", + "manageFamily": "Tvarkyti šeimą", + "renewSubscription": "Atnaujinti prenumeratą", + "cancelSubscription": "Atsisakyti prenumeratos", + "yesCancel": "Taip, atsisakyti", + "failedToCancel": "Nepavyko atsisakyti", + "twoMonthsFreeOnYearlyPlans": "2 mėnesiai nemokamai metiniuose planuose", + "monthly": "Mėnesinis", + "@monthly": { + "description": "The text to display for monthly plans", + "type": "text" + }, + "yearly": "Metinis", + "@yearly": { + "description": "The text to display for yearly plans", + "type": "text" + }, + "confirmPlanChange": "Patvirtinkite plano pakeitimą", + "areYouSureYouWantToChangeYourPlan": "Ar tikrai norite keisti planą?", + "youCannotDowngradeToThisPlan": "Negalite pakeisti į šį planą", + "cancelOtherSubscription": "Pirmiausia atsisakykite esamos prenumeratos iš {paymentProvider}", + "@cancelOtherSubscription": { + "description": "The text to display when the user has an existing subscription from a different payment provider", + "type": "text", + "placeholders": { + "paymentProvider": { + "example": "Apple", + "type": "String" + } + } + }, + "optionalAsShortAsYouLike": "Nebūtina, trumpai, kaip jums patinka...", + "send": "Siųsti", + "googlePlayId": "„Google Play“ ID", + "appleId": "„Apple ID“", + "playstoreSubscription": "„PlayStore“ prenumerata", + "subAlreadyLinkedErrMessage": "Jūsų {id} jau susietas su kita „Ente“ paskyra.\nJei norite naudoti savo {id} su šia paskyra, susisiekite su mūsų palaikymo komanda.", + "visitWebToManage": "Aplankykite web.ente.io, kad tvarkytumėte savo prenumeratą", + "paymentFailed": "Mokėjimas nepavyko", + "paymentFailedTalkToProvider": "Kreipkitės į {providerName} palaikymo komandą, jei jums buvo nuskaičiuota.", + "@paymentFailedTalkToProvider": { + "description": "The text to display when the payment failed", + "type": "text", + "placeholders": { + "providerName": { + "example": "AppStore|PlayStore", + "type": "String" + } + } + }, + "continueOnFreeTrial": "Tęsti nemokame bandomajame laikotarpyje", + "areYouSureYouWantToExit": "Ar tikrai norite išeiti?", + "thankYou": "Dėkojame", + "failedToVerifyPaymentStatus": "Nepavyko patvirtinti mokėjimo būsenos", + "paymentFailedMessage": "Deja, jūsų mokėjimas nepavyko. Susisiekite su palaikymo komanda ir mes jums padėsime!", + "leaveFamily": "Palikti šeimą", + "areYouSureThatYouWantToLeaveTheFamily": "Ar tikrai norite palikti šeimos planą?", + "leave": "Palikti", + "rateTheApp": "Vertinti programą", + "startBackup": "Pradėti kurti atsarginę kopiją", + "existingUser": "Esamas naudotojas", + "available": "Prieinama", + "everywhere": "visur", + "androidIosWebDesktop": "„Android“, „iOS“, internete ir darbalaukyje", + "mobileWebDesktop": "Mobiliuosiuose, internete ir darbalaukyje", + "newToEnte": "Naujas platformoje „Ente“", + "pleaseLoginAgain": "Prisijunkite iš naujo.", + "autoLogoutMessage": "Dėl techninio trikdžio buvote atjungti. Atsiprašome už nepatogumus.", + "yourSubscriptionHasExpired": "Jūsų prenumerata baigėsi.", + "storageLimitExceeded": "Viršyta saugyklos riba.", + "upgrade": "Keisti planą", + "raiseTicket": "Sukurti paraišką", + "@raiseTicket": { + "description": "Button text for raising a support tickets in case of unhandled errors during backup", + "type": "text" + }, + "@onDevice": { + "description": "The text displayed above folders/albums stored on device", + "type": "text" + }, + "onDevice": "Įrenginyje", + "@onEnte": { + "description": "The text displayed above albums backed up to Ente", + "type": "text" + }, + "onEnte": "Saugykloje ente", + "name": "Pavadinimą", + "newest": "Naujausią", + "lastUpdated": "Paskutinį kartą atnaujintą", + "removeFromFavorite": "Šalinti iš mėgstamų", + "addToEnte": "Pridėti į „Ente“", + "addToAlbum": "Pridėti į albumą", + "delete": "Ištrinti", + "hide": "Slėpti", + "share": "Bendrinti", + "restoreToAlbum": "Atkurti į albumą", + "moveItem": "{count, plural, one {Perkelti elementą} few {Perkelti elementus} many {Perkelti elemento} other {Perkelti elementų}}", + "@moveItem": { + "description": "Page title while moving one or more items to an album" + }, + "shareAlbumHint": "Atidarykite albumą ir palieskite bendrinimo mygtuką viršuje dešinėje, kad bendrintumėte.", + "setCover": "Nustatyti viršelį", + "@setCover": { + "description": "Text to set cover photo for an album" + }, + "sortAlbumsBy": "Rikiuoti pagal", + "sortNewestFirst": "Naujausią pirmiausiai", + "sortOldestFirst": "Seniausią pirmiausiai", + "rename": "Pervadinti", + "leaveAlbum": "Palikti albumą", + "photosAddedByYouWillBeRemovedFromTheAlbum": "Jūsų pridėtos nuotraukos bus pašalintos iš albumo", "noExifData": "Nėra EXIF duomenų", - "thisImageHasNoExifData": "Šis vaizdas neturi EXIF duomenų", + "thisImageHasNoExifData": "Šis vaizdas neturi Exif duomenų", "exif": "EXIF", "noResults": "Rezultatų nėra", + "close": "Uždaryti", + "setAs": "Nustatyti kaip", + "download": "Atsisiųsti", + "pressAndHoldToPlayVideo": "Paspauskite ir palaikykite, kad paleistumėte vaizdo įrašą", + "downloadFailed": "Atsisiuntimas nepavyko.", + "deduplicateFiles": "Atdubliuoti failus", + "reviewDeduplicateItems": "Peržiūrėkite ir ištrinkite elementus, kurie, jūsų manymu, yra dublikatai.", + "unlock": "Atrakinti", + "freeUpAmount": "Atlaisvinti {sizeInMBorGB}", + "verificationFailedPleaseTryAgain": "Patvirtinimas nepavyko. Bandykite dar kartą.", + "pleaseVerifyTheCodeYouHaveEntered": "Patvirtinkite įvestą kodą.", + "yourVerificationCodeHasExpired": "Jūsų patvirtinimo kodo laikas nebegaliojantis.", + "verifying": "Patvirtinama...", + "loadingGallery": "Įkeliama galerija...", + "syncing": "Sinchronizuojama...", + "syncStopped": "Sinchronizavimas sustabdytas", + "syncProgress": "{completed} / {total} išsaugomi prisiminimai", + "@syncProgress": { + "description": "Text to tell user how many memories have been preserved", + "placeholders": { + "completed": { + "type": "String" + }, + "total": { + "type": "String" + } + } + }, + "archiving": "Archyvuojama...", + "renameFile": "Pervadinti failą", + "selectedFilesAreNotOnEnte": "Pasirinkti failai nėra platformoje „Ente“", + "emptyTrash": "Ištuštinti šiukšlinę?", + "empty": "Ištuštinti", + "couldNotFreeUpSpace": "Nepavyko atlaisvinti vietos.", + "permanentlyDeleteFromDevice": "Ištrinti negrįžtamai iš įrenginio?", + "error": "Klaida", + "tempErrorContactSupportIfPersists": "Atrodo, kad kažkas nutiko ne taip. Bandykite dar kartą po kurio laiko. Jei klaida tęsiasi, susisiekite su mūsų palaikymo komanda.", + "networkHostLookUpErr": "Nepavyksta prisijungti prie „Ente“. Patikrinkite tinklo nustatymus ir susisiekite su palaikymo komanda, jei klaida tęsiasi.", + "networkConnectionRefusedErr": "Nepavyksta prisijungti prie „Ente“. Bandykite dar kartą po kurio laiko. Jei klaida tęsiasi, susisiekite su palaikymo komanda.", + "cachedData": "Podėliuoti duomenis", + "clearCaches": "Valyti podėlius", + "remoteImages": "Nuotoliniai vaizdai", + "remoteVideos": "Nuotoliniai vaizdo įrašai", + "remoteThumbnails": "Nuotolinės miniatiūros", + "pendingSync": "Laukiama sinchronizacija", + "localGallery": "Vietinė galerija", + "todaysLogs": "Šiandienos žurnalai", + "viewLogs": "Peržiūrėti žurnalus", + "location": "Vietovė", + "searchLocationEmptySection": "Grupės nuotraukos, kurios padarytos tam tikru spinduliu nuo nuotraukos", + "selectLanguage": "Pasirinkite kalbą", + "locationName": "Vietovės pavadinimas", + "addLocation": "Pridėti vietovę", "kiloMeterUnit": "km", "addLocationButton": "Pridėti", + "locationTagFeatureDescription": "Vietos žymė grupuoja visas nuotraukas, kurios buvo padarytos tam tikru spinduliu nuo nuotraukos", + "centerPoint": "Vidurio taškas", + "resetToDefault": "Atkurti numatytąsias reikšmes", + "@resetToDefault": { + "description": "Button text to reset cover photo to default" + }, + "edit": "Redaguoti", + "deleteLocation": "Ištrinti vietovę", "light": "Šviesi", "color": "Spalva", "distanceInKMUnit": "km", @@ -123,22 +575,199 @@ }, "appVersion": "Versija: {versionValue}", "verifyIDLabel": "Patvirtinti", + "editLocationTagTitle": "Redaguoti vietovę", + "setLabel": "Nustatyti", + "@setLabel": { + "description": "Label of confirm button to add a new custom radius to the radius selector of a location tag" + }, + "androidBiometricHint": "Patvirtinkite tapatybę", + "@androidBiometricHint": { + "description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters." + }, + "androidCancelButton": "Atšaukti", + "@androidCancelButton": { + "description": "Message showed on a button that the user can click to leave the current dialog. It is used on Android side. Maximum 30 characters." + }, + "androidSignInTitle": "Privalomas tapatybės nustatymas", + "@androidSignInTitle": { + "description": "Message showed as a title in a dialog which indicates the user that they need to scan biometric to continue. It is used on Android side. Maximum 60 characters." + }, + "goToSettings": "Eiti į nustatymus", + "@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." + }, + "iOSOkButton": "Gerai", + "@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." + }, + "map": "Žemėlapis", + "@map": { + "description": "Label for the map view" + }, + "enableMapsDesc": "Tai parodys jūsų nuotraukas pasaulio žemėlapyje.\n\nŠį žemėlapį talpina „OpenStreetMap“, o tiksliomis nuotraukų vietovėmis niekada nebendrinama.\n\nŠią funkciją bet kada galite išjungti iš nustatymų.", + "noImagesWithLocation": "Nėra vaizdų su vietove", + "unpinAlbum": "Atsegti albumą", + "pinAlbum": "Prisegti albumą", + "create": "Kurti", + "viewAll": "Peržiūrėti viską", + "deleteConfirmDialogBody": "Ši paskyra susieta su kitomis „Ente“ programomis, jei jas naudojate. Jūsų įkelti duomenys per visas „Ente“ programas bus planuojama ištrinti, o jūsų paskyra bus ištrinta negrįžtamai.", + "viewAddOnButton": "Peržiūrėti priedus", + "searchHint4": "Vietovė", + "searchResultCount": "{count, plural, one{Rastas {count} rezultatas} few {Rasti {count} rezultatai} many {Rasta {count} rezultato} other{Rasta {count} rezultatų}}", + "@searchResultCount": { + "description": "Text to tell user how many results were found for their search query", + "placeholders": { + "count": { + "example": "1|2|3", + "type": "int" + } + } + }, + "faces": "Veidai", + "people": "Asmenys", + "addNew": "Pridėti naują", + "@addNew": { + "description": "Text to add a new item (location tag, album, caption etc)" + }, + "contacts": "Kontaktai", + "noInternetConnection": "Nėra interneto ryšio", + "pleaseCheckYourInternetConnectionAndTryAgain": "Patikrinkite savo interneto ryšį ir bandykite dar kartą.", + "signOutOtherBody": "Jei manote, kad kas nors gali žinoti jūsų slaptažodį, galite priverstinai atsijungti iš visų kitų įrenginių, naudojančių jūsų paskyrą.", + "doNotSignOut": "Neatsijungti", + "editLocation": "Redaguoti vietovę", + "selectALocation": "Pasirinkite vietovę", + "selectALocationFirst": "Pirmiausia pasirinkite vietovę", + "changeLocationOfSelectedItems": "Keisti pasirinktų elementų vietovę?", + "editsToLocationWillOnlyBeSeenWithinEnte": "Vietovės pakeitimai bus matomi tik per „Ente“", + "cleanUncategorized": "Valyti nekategorizuotą", + "cleanUncategorizedDescription": "Pašalinkite iš nekategorizuotą visus failus, esančius kituose albumuose", + "waitingForVerification": "Laukiama patvirtinimo...", "passkey": "Slaptaraktas", + "passkeyAuthTitle": "Slaptarakto patvirtinimas", + "passKeyPendingVerification": "Vis dar laukiama patvirtinimo", + "loginSessionExpired": "Seansas baigėsi", + "loginSessionExpiredDetails": "Jūsų seansas baigėsi. Prisijunkite iš naujo.", + "verifyPasskey": "Patvirtinti slaptaraktą", + "playOnTv": "Paleisti albumą televizoriuje", + "pair": "Susieti", + "deviceNotFound": "Įrenginys nerastas", + "castInstruction": "Aplankykite cast.ente.io įrenginyje, kurį norite susieti.\n\nĮveskite toliau esantį kodą, kad paleistumėte albumą televizoriuje.", + "deviceCodeHint": "Įveskite kodą", + "joinDiscord": "Jungtis prie „Discord“", + "locations": "Vietovės", + "descriptions": "Aprašymai", + "addAName": "Pridėti vardą", + "findPeopleByName": "Greitai suraskite žmones pagal vardą", + "addViewers": "{count, plural, one {Pridėti žiūrėtoją} few {Pridėti žiūrėtojus} many {Pridėti žiūrėtojo} other {Pridėti žiūrėtojų}}", + "addCollaborators": "{count, plural, one {Pridėti bendradarbį} few {Pridėti bendradarbius} many {Pridėti bendradarbio} other {Pridėti bendradarbių}}", + "longPressAnEmailToVerifyEndToEndEncryption": "Ilgai paspauskite el. paštą, kad patvirtintumėte visapusį šifravimą.", + "developerSettingsWarning": "Ar tikrai norite modifikuoti kūrėjo nustatymus?", + "developerSettings": "Kūrėjo nustatymai", + "serverEndpoint": "Serverio galutinis taškas", + "invalidEndpoint": "Netinkamas galutinis taškas", + "invalidEndpointMessage": "Atsiprašome, įvestas galutinis taškas netinkamas. Įveskite tinkamą galutinį tašką ir bandykite dar kartą.", + "endpointUpdatedMessage": "Galutinis taškas sėkmingai atnaujintas", + "customEndpoint": "Prijungta prie {endpoint}", + "createCollaborativeLink": "Kurti bendradarbiavimo nuorodą", + "search": "Ieškoti", + "enterPersonName": "Įveskite asmens vardą", + "removePersonLabel": "Šalinti asmens žymą", + "autoPairDesc": "Automatinis susiejimas veikia tik su įrenginiais, kurie palaiko „Chromecast“.", + "manualPairDesc": "Susieti su PIN kodu veikia bet kuriame ekrane, kuriame norite peržiūrėti albumą.", + "connectToDevice": "Prijungti prie įrenginio", + "autoCastDialogBody": "Čia matysite pasiekiamus perdavimo įrenginius.", + "noDeviceFound": "Įrenginys nerastas", + "stopCastingTitle": "Stabdyti perdavimą", + "stopCastingBody": "Ar norite sustabdyti perdavimą?", + "castIPMismatchTitle": "Nepavyko perduoti albumo", + "castIPMismatchBody": "Įsitikinkite, kad esate tame pačiame tinkle kaip ir televizorius.", + "pairingComplete": "Susiejimas baigtas", + "savingEdits": "Išsaugomi redagavimai...", + "autoPair": "Automatiškai susieti", + "pairWithPin": "Susieti su PIN", + "faceRecognition": "Veido atpažinimas", + "foundFaces": "Rasti veidai", + "clusteringProgress": "Sankaupos vykdymas", + "indexingIsPaused": "Indeksavimas pristabdytas. Jis bus automatiškai tęsiamas, kai įrenginys yra paruoštas.", + "trim": "Trumpinti", + "crop": "Apkirpti", + "rotate": "Sukti", + "left": "Kairė", + "right": "Dešinė", + "whatsNew": "Kas naujo", + "reviewSuggestions": "Peržiūrėti pasiūlymus", + "useAsCover": "Naudoti kaip viršelį", + "notPersonLabel": "Ne {name}?", + "@notPersonLabel": { + "description": "Label to indicate that the person in the photo is not the person whose name is mentioned", + "placeholders": { + "name": { + "content": "{name}", + "type": "String" + } + } + }, + "enable": "Įjungti", + "enabled": "Įjungta", + "moreDetails": "Daugiau išsamios informacijos", + "enableMLIndexingDesc": "„Ente“ palaiko įrenginyje mašininį mokymąsi, skirtą veidų atpažinimui, magiškai paieškai ir kitoms išplėstinėms paieškos funkcijoms", + "magicSearchHint": "Magiška paieška leidžia ieškoti nuotraukų pagal jų turinį, pvz., „gėlė“, „raudonas automobilis“, „tapatybės dokumentai“", + "panorama": "Panorama", + "reenterPassword": "Įveskite slaptažodį iš naujo", + "reenterPin": "Įveskite PIN iš naujo", + "deviceLock": "Įrenginio užraktas", + "pinLock": "PIN užrakinimas", + "next": "Toliau", + "setNewPassword": "Nustatykite naują slaptažodį", + "enterPin": "Įveskite PIN", + "setNewPin": "Nustatykite naują PIN", + "appLock": "Programos užraktas", + "noSystemLockFound": "Nerastas sistemos užraktas", + "tapToUnlock": "Palieskite, kad atrakintumėte", + "tooManyIncorrectAttempts": "Per daug neteisingų bandymų.", + "videoInfo": "Vaizdo įrašo informacija", + "autoLock": "Automatinis užraktas", + "immediately": "Iš karto", + "autoLockFeatureDescription": "Laikas, po kurio programa užrakinama perkėlus ją į foną", + "hideContent": "Slėpti turinį", + "hideContentDescriptionAndroid": "Paslepia programų turinį programų perjungiklyje ir išjungia ekrano kopijas", + "hideContentDescriptionIos": "Paslepia programos turinį programos perjungiklyje", + "passwordStrengthInfo": "Slaptažodžio stiprumas apskaičiuojamas atsižvelgiant į slaptažodžio ilgį, naudotus simbolius ir į tai, ar slaptažodis patenka į 10 000 dažniausiai naudojamų slaptažodžių.", + "noQuickLinksSelected": "Nėra pasirinktų sparčiųjų nuorodų", + "pleaseSelectQuickLinksToRemove": "Pasirinkite sparčiąsias nuorodas, kad pašalintumėte", + "removePublicLinks": "Šalinti viešąsias nuorodas", + "thisWillRemovePublicLinksOfAllSelectedQuickLinks": "Tai pašalins visų pasirinktų sparčiųjų nuorodų viešąsias nuorodas.", + "guestView": "Svečio peržiūra", + "guestViewEnablePreSteps": "Kad įjungtumėte svečio peržiūrą, sistemos nustatymuose nustatykite įrenginio prieigos kodą arba ekrano užraktą.", + "nameTheAlbum": "Pavadinti albumą", + "collectPhotosDescription": "Sukurkite nuorodą, į kurią draugai gali įkelti originalios kokybės nuotraukas.", "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ą", + "loopVideoOn": "Įjungtas vaizdo įrašo ciklas", + "loopVideoOff": "Išjungtas vaizdo įrašo ciklas", "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", + "mostRecent": "Naujausią", + "mostRelevant": "Aktualiausią", "loadingYourPhotos": "Įkeliamos nuotraukos...", "processingImport": "Apdorojama {folderName}...", "personName": "Asmens vardas", "addNewPerson": "Pridėti naują asmenį", + "addNameOrMerge": "Pridėti vardą arba sujungti", + "mergeWithExisting": "Sujungti su esamais", "newPerson": "Naujas asmuo", + "addName": "Pridėti vardą", "add": "Pridėti", "extraPhotosFoundFor": "Rastos papildomos nuotraukos, skirtos $text", - "extraPhotosFound": "Rastos papildomos nuotraukos" + "extraPhotosFound": "Rastos papildomos nuotraukos", + "configuration": "Konfiguracija", + "localIndexing": "Vietinis indeksavimas", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_nl.arb b/mobile/lib/l10n/intl_nl.arb index 7e0f481684..8f30cb0841 100644 --- a/mobile/lib/l10n/intl_nl.arb +++ b/mobile/lib/l10n/intl_nl.arb @@ -1343,5 +1343,10 @@ "mostRecent": "Meest recent", "mostRelevant": "Meest relevant", "loadingYourPhotos": "Je foto's worden geladen...", - "processingImport": "Verwerken van {folderName}..." + "processingImport": "Verwerken van {folderName}...", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_no.arb b/mobile/lib/l10n/intl_no.arb index a42eec2d70..a7e36baa9b 100644 --- a/mobile/lib/l10n/intl_no.arb +++ b/mobile/lib/l10n/intl_no.arb @@ -371,5 +371,10 @@ "advanced": "Avansert", "general": "Generelt", "security": "Sikkerhet", - "authToViewYourRecoveryKey": "Vennligst autentiser deg for å se gjennopprettingsnøkkelen din" + "authToViewYourRecoveryKey": "Vennligst autentiser deg for å se gjennopprettingsnøkkelen din", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_pl.arb b/mobile/lib/l10n/intl_pl.arb index a21c0c1494..272d04fd35 100644 --- a/mobile/lib/l10n/intl_pl.arb +++ b/mobile/lib/l10n/intl_pl.arb @@ -1352,5 +1352,12 @@ "addName": "Dodaj nazwę", "add": "Dodaj", "extraPhotosFoundFor": "Znaleziono dodatkowe zdjęcia dla $text", - "extraPhotosFound": "Znaleziono dodatkowe zdjęcia" + "extraPhotosFound": "Znaleziono dodatkowe zdjęcia", + "configuration": "Konfiguracja", + "localIndexing": "Indeksowanie lokalne", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_pt.arb b/mobile/lib/l10n/intl_pt.arb index e2950a8771..b7a300277e 100644 --- a/mobile/lib/l10n/intl_pt.arb +++ b/mobile/lib/l10n/intl_pt.arb @@ -676,53 +676,53 @@ "areYouSureYouWantToExit": "Tem certeza de que queira sair?", "thankYou": "Obrigado", "failedToVerifyPaymentStatus": "Falhou ao verificar estado do pagamento", - "pleaseWaitForSometimeBeforeRetrying": "Por favor, aguarde algum tempo antes de tentar novamente", - "paymentFailedMessage": "Infelizmente o seu pagamento falhou. Entre em contato com o suporte e nós ajudaremos você!", + "pleaseWaitForSometimeBeforeRetrying": "Por favor, aguarde mais algum tempo antes de tentar novamente", + "paymentFailedMessage": "Infelizmente o pagamento falhou. Entre em contato com o suporte e nós ajudaremos você!", "youAreOnAFamilyPlan": "Você está em um plano familiar!", "contactFamilyAdmin": "Entre em contato com {familyAdminEmail} para gerenciar sua assinatura", - "leaveFamily": "Sair da família", - "areYouSureThatYouWantToLeaveTheFamily": "Tem certeza que deseja sair do plano familiar?", + "leaveFamily": "Sair do plano familiar", + "areYouSureThatYouWantToLeaveTheFamily": "Você tem certeza que queira sair do plano familiar?", "leave": "Sair", "rateTheApp": "Avalie o aplicativo", - "startBackup": "Iniciar backup", - "noPhotosAreBeingBackedUpRightNow": "No momento não há backup de fotos sendo feito", + "startBackup": "Iniciar cópia de segurança", + "noPhotosAreBeingBackedUpRightNow": "No momento não há fotos sendo copiadas com segurança", "preserveMore": "Preservar mais", - "grantFullAccessPrompt": "Por favor, permita o acesso a todas as fotos nas configurações do aplicativo", - "openSettings": "Abrir Configurações", + "grantFullAccessPrompt": "Permita o acesso a todas as fotos nas opções do aplicativo", + "openSettings": "Abrir opções", "selectMorePhotos": "Selecionar mais fotos", "existingUser": "Usuário existente", - "privateBackups": "Backups privados", + "privateBackups": "Cópias privadas", "forYourMemories": "para suas memórias", - "endtoendEncryptedByDefault": "Criptografia de ponta a ponta por padrão", + "endtoendEncryptedByDefault": "Criptografado de ponta a ponta por padrão", "safelyStored": "Armazenado com segurança", "atAFalloutShelter": "em um abrigo avançado", "designedToOutlive": "Feito para ter longevidade", "available": "Disponível", - "everywhere": "em todos os lugares", - "androidIosWebDesktop": "Android, iOS, Web, Desktop", - "mobileWebDesktop": "Mobile, Web, Desktop", + "everywhere": "em todas as partes", + "androidIosWebDesktop": "Android, iOS, Web, Computador", + "mobileWebDesktop": "Celular, Web, Computador", "newToEnte": "Novo no Ente", - "pleaseLoginAgain": "Por favor, inicie sessão novamente", - "autoLogoutMessage": "Devido a erros técnicos, você foi desconectado. Pedimos desculpas pelo inconveniente.", + "pleaseLoginAgain": "Registre-se novamente", + "autoLogoutMessage": "Devido ao ocorrido de erros técnicos, você foi desconectado. Pedimos desculpas pela inconveniência.", "yourSubscriptionHasExpired": "A sua assinatura expirou", "storageLimitExceeded": "Limite de armazenamento excedido", - "upgrade": "Aprimorar", + "upgrade": "Atualizar", "raiseTicket": "Abrir ticket", "@raiseTicket": { "description": "Button text for raising a support tickets in case of unhandled errors during backup", "type": "text" }, - "backupFailed": "Erro ao efetuar o backup", - "couldNotBackUpTryLater": "Não foi possível fazer o backup de seus dados.\nTentaremos novamente mais tarde.", + "backupFailed": "Falhou ao copiar com segurança", + "couldNotBackUpTryLater": "Nós não podemos copiar com segurança seus dados.\nNós tentaremos novamente mais tarde.", "enteCanEncryptAndPreserveFilesOnlyIfYouGrant": "Ente pode criptografar e preservar arquivos apenas se você conceder acesso a eles", "pleaseGrantPermissions": "Por favor, conceda as permissões", - "grantPermission": "Conceder permissão", + "grantPermission": "Conceder permissões", "privateSharing": "Compartilhamento privado", "shareOnlyWithThePeopleYouWant": "Compartilhar apenas com as pessoas que você quiser", "usePublicLinksForPeopleNotOnEnte": "Usar links públicos para pessoas que não estão no Ente", "allowPeopleToAddPhotos": "Permitir que pessoas adicionem fotos", "shareAnAlbumNow": "Compartilhar um álbum agora", - "collectEventPhotos": "Coletar fotos do evento", + "collectEventPhotos": "Coletar fotos de evento", "sessionExpired": "Sessão expirada", "loggingOut": "Desconectando...", "@onDevice": { @@ -734,13 +734,13 @@ "description": "The text displayed above albums backed up to Ente", "type": "text" }, - "onEnte": "Em ente", + "onEnte": "No ente", "name": "Nome", "newest": "Mais recente", "lastUpdated": "Última atualização", "deleteEmptyAlbums": "Excluir álbuns vazios", "deleteEmptyAlbumsWithQuestionMark": "Excluir álbuns vazios?", - "deleteAlbumsDialogBody": "Isto irá apagar todos os álbuns vazios. Isso é útil quando você deseja reduzir a bagunça na sua lista de álbuns.", + "deleteAlbumsDialogBody": "Isso excluirá todos os álbuns vazios. Isso é útil quando você quiser reduzir a desordem no seu álbum.", "deleteProgress": "Excluindo {currentlyDeleting} / {totalCount}", "genericProgress": "Processando {currentlyProcessing} / {totalCount}", "@genericProgress": { @@ -767,11 +767,11 @@ "description": "Display text for an action which triggers a restore of item from trash", "type": "text" }, - "moveToAlbum": "Mover para álbum", - "unhide": "Reexibir", + "moveToAlbum": "Mover para o álbum", + "unhide": "Desocultar", "unarchive": "Desarquivar", "favorite": "Favorito", - "removeFromFavorite": "Remover dos favoritos", + "removeFromFavorite": "Desfavoritar", "shareLink": "Compartilhar link", "createCollage": "Criar colagem", "saveCollage": "Salvar colagem", @@ -782,7 +782,7 @@ "delete": "Excluir", "hide": "Ocultar", "share": "Compartilhar", - "unhideToAlbum": "Reexibir para o álbum", + "unhideToAlbum": "Desocultar para o álbum", "restoreToAlbum": "Restaurar para álbum", "moveItem": "{count, plural, one {Mover item} other {Mover itens}}", "@moveItem": { @@ -796,10 +796,10 @@ "selectAlbum": "Selecionar álbum", "searchByAlbumNameHint": "Nome do álbum", "albumTitle": "Título do álbum", - "enterAlbumName": "Digite o nome do álbum", + "enterAlbumName": "Inserir nome do álbum", "restoringFiles": "Restaurando arquivos...", - "movingFilesToAlbum": "Enviando arquivos para o álbum...", - "unhidingFilesToAlbum": "Reexibindo arquivos para o álbum", + "movingFilesToAlbum": "Movendo arquivos para o álbum...", + "unhidingFilesToAlbum": "Desocultando arquivos para o álbum", "canNotUploadToAlbumsOwnedByOthers": "Não é possível enviar para álbuns pertencentes a outros", "uploadingFilesToAlbum": "Enviando arquivos para o álbum...", "addedSuccessfullyTo": "Adicionado com sucesso a {albumName}", @@ -812,10 +812,10 @@ "sharedWith": "Compartilhado com {emailIDs}", "sharedWithMe": "Compartilhado comigo", "sharedByMe": "Compartilhada por mim", - "doubleYourStorage": "Dobre seu armazenamento", - "referFriendsAnd2xYourPlan": "Indique amigos e 2x seu plano", + "doubleYourStorage": "Duplique seu armazenamento", + "referFriendsAnd2xYourPlan": "Recomende seus amigos e duplique seu plano", "shareAlbumHint": "Abra um álbum e toque no botão compartilhar no canto superior direito para compartilhar.", - "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": "Os itens mostram o número de dias restantes antes da exclusão permanente", + "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": "Os itens exibem o número de dias restantes antes da exclusão permanente", "trashDaysLeft": "{count, plural, =0 {} =1 {1 dia} other {{count} dias}}", "@trashDaysLeft": { "description": "Text to indicate number of days remaining before permanent deletion", @@ -826,7 +826,7 @@ } } }, - "deleteAll": "Excluir Tudo", + "deleteAll": "Excluir tudo", "renameAlbum": "Renomear álbum", "convertToAlbum": "Converter para álbum", "setCover": "Definir capa", @@ -834,63 +834,63 @@ "description": "Text to set cover photo for an album" }, "sortAlbumsBy": "Ordenar por", - "sortNewestFirst": "Mais recentes primeiro", - "sortOldestFirst": "Mais antigos primeiro", + "sortNewestFirst": "Recentes primeiro", + "sortOldestFirst": "Antigos primeiro", "rename": "Renomear", "leaveSharedAlbum": "Sair do álbum compartilhado?", "leaveAlbum": "Sair do álbum", - "photosAddedByYouWillBeRemovedFromTheAlbum": "As fotos adicionadas por você serão removidas do álbum", + "photosAddedByYouWillBeRemovedFromTheAlbum": "Suas fotos adicionadas serão removidas do álbum", "youveNoFilesInThisAlbumThatCanBeDeleted": "Você não tem arquivos neste álbum que possam ser excluídos", "youDontHaveAnyArchivedItems": "Você não tem nenhum item arquivado.", - "ignoredFolderUploadReason": "Alguns arquivos neste álbum são ignorados do envio porque eles tinham sido anteriormente excluídos do Ente.", + "ignoredFolderUploadReason": "Alguns arquivos neste álbum são ignorados do envio porque eles foram anteriormente excluídos do Ente.", "resetIgnoredFiles": "Redefinir arquivos ignorados", - "deviceFilesAutoUploading": "Arquivos adicionados a este álbum do dispositivo serão automaticamente enviados para o Ente.", - "turnOnBackupForAutoUpload": "Ative o backup para enviar automaticamente arquivos adicionados a esta pasta do dispositivo para o Ente.", - "noHiddenPhotosOrVideos": "Nenhuma foto ou vídeos ocultos", + "deviceFilesAutoUploading": "Arquivos adicionados ao álbum do dispositivo serão automaticamente enviados para o Ente.", + "turnOnBackupForAutoUpload": "Ative a cópia de segurança para automaticamente enviar arquivos adicionados à pasta do dispositivo para o Ente.", + "noHiddenPhotosOrVideos": "Sem fotos ou vídeos ocultos", "toHideAPhotoOrVideo": "Para ocultar uma foto ou vídeo", - "openTheItem": "• Abra o item", + "openTheItem": "• Abra a foto ou vídeo", "clickOnTheOverflowMenu": "• Clique no menu adicional", - "click": "Clique", + "click": "• Clique", "nothingToSeeHere": "Nada para ver aqui! 👀", "unarchiveAlbum": "Desarquivar álbum", "archiveAlbum": "Arquivar álbum", "calculating": "Calculando...", - "pleaseWaitDeletingAlbum": "Por favor, aguarde, excluindo álbum", - "searchByExamples": "• Nomes de álbuns (ex: \"Câmera\")\n• Tipos de arquivos (ex.: \"Vídeos\", \".gif\")\n• Anos e meses (e.. \"2022\", \"Janeiro\")\n• Feriados (por exemplo, \"Natal\")\n• Descrições de fotos (por exemplo, \"#divertido\")", - "youCanTrySearchingForADifferentQuery": "Você pode tentar procurar uma consulta diferente.", + "pleaseWaitDeletingAlbum": "Aguarde, excluindo álbum", + "searchByExamples": "• Nomes de álbuns (ex: \"Câmera\")\n• Tipos de arquivos (ex.: \"Vídeos\", \".gif\")\n• Anos e meses (ex.: \"2022\", \"Janeiro\")\n• Temporadas (ex.: \"Natal\")\n• Tags (ex.: \"#divertido\")", + "youCanTrySearchingForADifferentQuery": "Você pode tentar buscar por outra consulta.", "noResultsFound": "Nenhum resultado encontrado", "addedBy": "Adicionado por {emailOrName}", "loadingExifData": "Carregando dados EXIF...", "viewAllExifData": "Ver todos os dados EXIF", "noExifData": "Sem dados EXIF", - "thisImageHasNoExifData": "Esta imagem não tem dados exif", + "thisImageHasNoExifData": "Esta imagem não possui dados EXIF", "exif": "EXIF", "noResults": "Nenhum resultado", "weDontSupportEditingPhotosAndAlbumsThatYouDont": "Não suportamos a edição de fotos e álbuns que você ainda não possui", - "failedToFetchOriginalForEdit": "Falha ao obter original para edição", + "failedToFetchOriginalForEdit": "Falhou ao obter original para edição", "close": "Fechar", "setAs": "Definir como", - "fileSavedToGallery": "Vídeo salvo na galeria", + "fileSavedToGallery": "Arquivo salvo na galeria", "filesSavedToGallery": "Arquivos salvos na galeria", - "fileFailedToSaveToGallery": "Falha ao salvar o arquivo na galeria", + "fileFailedToSaveToGallery": "Falhou ao salvar arquivo na galeria", "download": "Baixar", "pressAndHoldToPlayVideo": "Pressione e segure para reproduzir o vídeo", "pressAndHoldToPlayVideoDetailed": "Pressione e segure na imagem para reproduzir o vídeo", - "downloadFailed": "Falha no download", + "downloadFailed": "Falhou ao baixar", "deduplicateFiles": "Arquivos duplicados", - "deselectAll": "Desmarcar todos", - "reviewDeduplicateItems": "Por favor, reveja e exclua os itens que você acredita serem duplicados.", + "deselectAll": "Deselecionar tudo", + "reviewDeduplicateItems": "Reveja e exclua os itens que você acredita serem duplicados.", "clubByCaptureTime": "Agrupar por tempo de captura", - "clubByFileName": "Agrupar pelo nome de arquivo", + "clubByFileName": "Agrupar por nome do arquivo", "count": "Contagem", "totalSize": "Tamanho total", - "longpressOnAnItemToViewInFullscreen": "Pressione e segure em um item para exibir em tela cheia", + "longpressOnAnItemToViewInFullscreen": "Mantenha pressionado em um item para visualizá-lo em tela cheia", "decryptingVideo": "Descriptografando vídeo...", - "authToViewYourMemories": "Por favor, autentique-se para ver suas memórias", + "authToViewYourMemories": "Autentique-se para ver suas memórias", "unlock": "Desbloquear", "freeUpSpace": "Liberar espaço", - "freeUpSpaceSaving": "{count, plural, one {Pode ser excluído do dispositivo para liberar {formattedSize}} other {Eles podem ser excluídos do dispositivo para liberar {formattedSize}}}", - "filesBackedUpInAlbum": "{count, plural, one {1 arquivo} other {{formattedNumber} arquivos}} neste álbum teve um backup seguro", + "freeUpSpaceSaving": "{count, plural, one {Ele pode ser excluído do dispositivo para liberar {formattedSize}} other {Eles podem ser excluídos do dispositivo para liberar {formattedSize}}}", + "filesBackedUpInAlbum": "{count, plural, one {1 arquivo} other {{formattedNumber} arquivos}} deste álbum foi copiado com segurança", "@filesBackedUpInAlbum": { "description": "Text to tell user how many files have been backed up in the album", "placeholders": { @@ -905,7 +905,7 @@ } } }, - "filesBackedUpFromDevice": "{count, plural, one {1 arquivo} other {{formattedNumber} arquivos}} neste dispositivo teve um backup seguro", + "filesBackedUpFromDevice": "{count, plural, one {1 arquivo} other {{formattedNumber} arquivos}} deste dispositivo foi copiado com segurança", "@filesBackedUpFromDevice": { "description": "Text to tell user how many files have been backed up from this device", "placeholders": { @@ -923,7 +923,7 @@ "@freeUpSpaceSaving": { "description": "Text to tell user how much space they can free up by deleting items from the device" }, - "freeUpAccessPostDelete": "Você ainda pode acessar {count, plural, one {ele} other {eles}} no Ente contanto que você tenha uma assinatura ativa", + "freeUpAccessPostDelete": "Você ainda pode acessá-{count, plural, one {lo} other {los}} no Ente, contanto que você tenha uma assinatura ativa", "@freeUpAccessPostDelete": { "placeholders": { "count": { @@ -933,19 +933,19 @@ } }, "freeUpAmount": "Liberar {sizeInMBorGB}", - "thisEmailIsAlreadyInUse": "Este e-mail já está em uso", + "thisEmailIsAlreadyInUse": "Este e-mail já está sendo usado", "incorrectCode": "Código incorreto", - "authenticationFailedPleaseTryAgain": "Falha na autenticação. Por favor, tente novamente", - "verificationFailedPleaseTryAgain": "Falha na verificação, por favor, tente novamente", + "authenticationFailedPleaseTryAgain": "Falha na autenticação. Tente novamente", + "verificationFailedPleaseTryAgain": "Falha na verificação. Tente novamente", "authenticating": "Autenticando...", - "authenticationSuccessful": "Autenticação bem-sucedida!", + "authenticationSuccessful": "Autenticado com sucesso!", "incorrectRecoveryKey": "Chave de recuperação incorreta", "theRecoveryKeyYouEnteredIsIncorrect": "A chave de recuperação inserida está incorreta", "twofactorAuthenticationSuccessfullyReset": "Autenticação de dois fatores redefinida com sucesso", - "pleaseVerifyTheCodeYouHaveEntered": "Por favor, verifique o código que você inseriu", + "pleaseVerifyTheCodeYouHaveEntered": "Verifique o código inserido", "pleaseContactSupportIfTheProblemPersists": "Por favor, contate o suporte se o problema persistir", "twofactorAuthenticationHasBeenDisabled": "A autenticação de dois fatores foi desativada", - "sorryTheCodeYouveEnteredIsIncorrect": "Desculpe, o código que você inseriu está incorreto", + "sorryTheCodeYouveEnteredIsIncorrect": "O código inserido está incorreto", "yourVerificationCodeHasExpired": "O código de verificação expirou", "emailChangedTo": "E-mail alterado para {newEmail}", "verifying": "Verificando...", @@ -953,7 +953,7 @@ "allMemoriesPreserved": "Todas as memórias preservadas", "loadingGallery": "Carregando galeria...", "syncing": "Sincronizando...", - "encryptingBackup": "Criptografando backup...", + "encryptingBackup": "Criptografando cópia de segurança...", "syncStopped": "Sincronização interrompida", "syncProgress": "{completed}/{total} memórias preservadas", "uploadingMultipleMemories": "Preservando {count} memórias...", @@ -974,7 +974,7 @@ "successfullyArchived": "Arquivado com sucesso", "successfullyUnarchived": "Desarquivado com sucesso", "renameFile": "Renomear arquivo", - "enterFileName": "Digite o nome do arquivo", + "enterFileName": "Inserir nome do arquivo", "filesDeleted": "Arquivos excluídos", "selectedFilesAreNotOnEnte": "Os arquivos selecionados não estão no Ente", "thisActionCannotBeUndone": "Esta ação não pode ser desfeita", @@ -985,73 +985,73 @@ "permanentlyDeleteFromDevice": "Excluir permanentemente do dispositivo?", "someOfTheFilesYouAreTryingToDeleteAre": "Alguns dos arquivos que você está tentando excluir só estão disponíveis no seu dispositivo e não podem ser recuperados se forem excluídos", "theyWillBeDeletedFromAllAlbums": "Eles serão excluídos de todos os álbuns.", - "someItemsAreInBothEnteAndYourDevice": "Alguns itens estão tanto no Ente quanto no seu dispositivo.", + "someItemsAreInBothEnteAndYourDevice": "Alguns itens estão em ambos o Ente quanto no seu dispositivo.", "selectedItemsWillBeDeletedFromAllAlbumsAndMoved": "Os itens selecionados serão excluídos de todos os álbuns e movidos para a lixeira.", "theseItemsWillBeDeletedFromYourDevice": "Estes itens serão excluídos do seu dispositivo.", - "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. Caso o erro persistir, por favor, entre em contato com nossa equipe.", "error": "Erro", - "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. Caso o erro persistir, por favor, entre em contato com nossa equipe.", "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.", - "cachedData": "Dados em cache", + "networkConnectionRefusedErr": "Não foi possível conectar ao Ente, tente novamente mais tarde. Se o erro persistir, entre em contato com o suporte.", + "cachedData": "Dados armazenados em cache", "clearCaches": "Limpar cache", "remoteImages": "Imagens remotas", "remoteVideos": "Vídeos remotos", "remoteThumbnails": "Miniaturas remotas", "pendingSync": "Sincronização pendente", "localGallery": "Galeria local", - "todaysLogs": "Logs de hoje", - "viewLogs": "Ver logs", - "logsDialogBody": "Isso enviará através dos logs para nos ajudar a depurar o seu problema. Por favor, note que nomes de arquivos serão incluídos para ajudar a rastrear problemas com arquivos específicos.", - "preparingLogs": "Preparando logs...", - "emailYourLogs": "Enviar logs por e-mail", - "pleaseSendTheLogsTo": "Por favor, envie os logs para \n{toEmail}", + "todaysLogs": "Registros de hoje", + "viewLogs": "Ver registros", + "logsDialogBody": "Isso enviará através dos registros para ajudar-nos a resolver seu problema. Saiba que, nome de arquivos serão incluídos para ajudar a buscar problemas com arquivos específicos.", + "preparingLogs": "Preparando registros...", + "emailYourLogs": "Enviar registros por e-mail", + "pleaseSendTheLogsTo": "Envie os registros para \n{toEmail}", "copyEmailAddress": "Copiar endereço de e-mail", - "exportLogs": "Exportar logs", - "pleaseEmailUsAt": "Por favor, envie-nos um e-mail para {toEmail}", + "exportLogs": "Exportar registros", + "pleaseEmailUsAt": "Envie-nos um e-mail para {toEmail}", "dismiss": "Descartar", "didYouKnow": "Você sabia?", "loadingMessage": "Carregando suas fotos...", - "loadMessage1": "Você pode compartilhar sua assinatura com sua família", - "loadMessage2": "Nós preservamos mais de 30 milhões de memórias até agora", + "loadMessage1": "Você pode compartilhar sua assinatura com seus familiares", + "loadMessage2": "Nós preservamos mais de 30 milhões de memórias até então", "loadMessage3": "Mantemos 3 cópias dos seus dados, uma em um abrigo subterrâneo", "loadMessage4": "Todos os nossos aplicativos são de código aberto", "loadMessage5": "Nosso código-fonte e criptografia foram auditadas externamente", "loadMessage6": "Você pode compartilhar links para seus álbuns com seus entes queridos", - "loadMessage7": "Nossos aplicativos móveis são executados em segundo plano para criptografar e fazer backup de quaisquer novas fotos que você clique", - "loadMessage8": "web.ente.io tem um envio mais rápido", + "loadMessage7": "Nossos aplicativos móveis são executados em segundo plano para criptografar e copiar com segurança quaisquer fotos novas que você acessar", + "loadMessage8": "web.ente.io tem um enviador mais rápido", "loadMessage9": "Nós usamos Xchacha20Poly1305 para criptografar seus dados com segurança", "photoDescriptions": "Descrições das fotos", "fileTypesAndNames": "Tipos de arquivo e nomes", - "location": "Local", + "location": "Localização", "moments": "Momentos", - "searchFaceEmptySection": "Pessoas serão exibidas aqui uma vez que a indexação é feita", - "searchDatesEmptySection": "Pesquisar por data, mês ou ano", + "searchFaceEmptySection": "As pessoas apareceram aqui quando a indexação for concluída", + "searchDatesEmptySection": "Buscar por data, mês ou ano", "searchLocationEmptySection": "Fotos de grupo que estão sendo tiradas em algum raio da foto", "searchPeopleEmptySection": "Convide pessoas e você verá todas as fotos compartilhadas por elas aqui", "searchAlbumsEmptySection": "Álbuns", "searchFileTypesAndNamesEmptySection": "Tipos de arquivo e nomes", - "searchCaptionEmptySection": "Adicione descrições como \"#trip\" nas informações das fotos para encontrá-las aqui rapidamente", + "searchCaptionEmptySection": "Adicione marcações como \"#viagem\" nas informações das fotos para encontrá-las aqui com facilidade", "language": "Idioma", - "selectLanguage": "Selecionar Idioma", - "locationName": "Nome do Local", - "addLocation": "Adicionar local", + "selectLanguage": "Selecionar idioma", + "locationName": "Nome da localização", + "addLocation": "Adicionar localização", "groupNearbyPhotos": "Agrupar fotos próximas", "kiloMeterUnit": "km", "addLocationButton": "Adicionar", "radius": "Raio", - "locationTagFeatureDescription": "Uma tag em grupo de todas as fotos que foram tiradas dentro de algum raio de uma foto", - "galleryMemoryLimitInfo": "Até 1000 memórias mostradas na galeria", + "locationTagFeatureDescription": "Uma etiqueta de localização agrupa todas as fotos fotografadas em algum raio de uma foto", + "galleryMemoryLimitInfo": "Até 1.000 memórias exibidas na galeria", "save": "Salvar", "centerPoint": "Ponto central", "pickCenterPoint": "Escolha o ponto central", - "useSelectedPhoto": "Utilizar foto selecionada", + "useSelectedPhoto": "Usar foto selecionada", "resetToDefault": "Redefinir para o padrão", "@resetToDefault": { "description": "Button text to reset cover photo to default" }, "edit": "Editar", - "deleteLocation": "Excluir Local", + "deleteLocation": "Excluir localização", "rotateLeft": "Girar para a esquerda", "flip": "Inverter", "rotateRight": "Girar para a direita", @@ -1062,7 +1062,7 @@ "doYouWantToDiscardTheEditsYouHaveMade": "Você quer descartar as edições que você fez?", "saving": "Salvando...", "editsSaved": "Edições salvas", - "oopsCouldNotSaveEdits": "Ops, não foi possível salvar edições", + "oopsCouldNotSaveEdits": "Opa! Não foi possível salvar as edições", "distanceInKMUnit": "km", "@distanceInKMUnit": { "description": "Unit for distance in km" @@ -1070,7 +1070,7 @@ "dayToday": "Hoje", "dayYesterday": "Ontem", "storage": "Armazenamento", - "usedSpace": "Espaço em uso", + "usedSpace": "Espaço usado", "storageBreakupFamily": "Família", "storageBreakupYou": "Você", "@storageBreakupYou": { @@ -1084,14 +1084,14 @@ "appVersion": "Versão: {versionValue}", "verifyIDLabel": "Verificar", "fileInfoAddDescHint": "Adicionar descrição...", - "editLocationTagTitle": "Editar local", + "editLocationTagTitle": "Editar localização", "setLabel": "Definir", "@setLabel": { "description": "Label of confirm button to add a new custom radius to the radius selector of a location tag" }, "setRadius": "Definir raio", "familyPlanPortalTitle": "Família", - "familyPlanOverview": "Adicione 5 membros da família ao seu plano existente sem pagar a mais.\n\nCada membro recebe seu próprio espaço privado, e nenhum membro pode ver os arquivos uns dos outros a menos que sejam compartilhados.\n\nPlanos de família estão disponíveis para os clientes que têm uma assinatura do Ente paga.\n\nAssine agora para começar!", + "familyPlanOverview": "Adicione 5 familiares para seu plano existente sem pagar nenhum custo adicional.\n\nCada membro ganha seu espaço privado, significando que eles não podem ver os arquivos dos outros a menos que eles sejam compartilhados.\n\nOs planos familiares estão disponíveis para clientes que já tem uma assinatura paga do Ente.\n\nAssine agora para iniciar!", "androidBiometricHint": "Verificar identidade", "@androidBiometricHint": { "description": "Hint message advising the user how to authenticate with biometrics. It is used on Android side. Maximum 60 characters." @@ -1116,27 +1116,27 @@ "@androidBiometricRequiredTitle": { "description": "Message showed as a title in a dialog which indicates the user has not set up biometric authentication on their device. It is used on Android side. Maximum 60 characters." }, - "androidDeviceCredentialsRequiredTitle": "Credenciais do dispositivo necessárias", + "androidDeviceCredentialsRequiredTitle": "Credenciais necessários", "@androidDeviceCredentialsRequiredTitle": { "description": "Message showed as a title in a dialog which indicates the user has not set up credentials authentication on their device. It is used on Android side. Maximum 60 characters." }, - "androidDeviceCredentialsSetupDescription": "Credenciais do dispositivo necessárias", + "androidDeviceCredentialsSetupDescription": "Credenciais necessários", "@androidDeviceCredentialsSetupDescription": { "description": "Message advising the user to go to the settings and configure device credentials on their device. It shows in a dialog on Android side." }, - "goToSettings": "Ir para Configurações", + "goToSettings": "Ir às opções", "@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á definida no dispositivo. Vá em 'Opçõ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á definida no dispositivo. Ative o Touch ID ou Face ID no dispositivo.", "@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." }, @@ -1145,22 +1145,22 @@ "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." }, "openstreetmapContributors": "Contribuidores do OpenStreetMap", - "hostedAtOsmFrance": "Hospedado na OSM France", + "hostedAtOsmFrance": "Hospedado em OSM France", "map": "Mapa", "@map": { "description": "Label for the map view" }, "maps": "Mapas", - "enableMaps": "Habilitar Mapa", - "enableMapsDesc": "Isto mostrará suas fotos em um mapa do mundo.\n\nEste mapa é hospedado pelo OpenStreetMap, e os exatos locais de suas fotos nunca são compartilhados.\n\nVocê pode desativar esse recurso a qualquer momento nas Configurações.", + "enableMaps": "Ativar mapas", + "enableMapsDesc": "Isso exibirá suas fotos em um mapa mundial.\n\nEste mapa é hospedado por Open Street Map, e as exatas localizações das fotos nunca serão compartilhadas.\n\nVocê pode desativar esta função a qualquer momento em Opções.", "quickLinks": "Links rápidos", "selectItemsToAdd": "Selecionar itens para adicionar", "addSelected": "Adicionar selecionado", - "addFromDevice": "Adicionar a partir do dispositivo", + "addFromDevice": "Adicionar do dispositivo", "addPhotos": "Adicionar fotos", "noPhotosFoundHere": "Nenhuma foto encontrada aqui", - "zoomOutToSeePhotos": "Diminuir o zoom para ver fotos", - "noImagesWithLocation": "Nenhuma imagem com local", + "zoomOutToSeePhotos": "Reduzir ampliação para ver as fotos", + "noImagesWithLocation": "Nenhuma imagem com localização", "unpinAlbum": "Desafixar álbum", "pinAlbum": "Fixar álbum", "create": "Criar", @@ -1170,19 +1170,19 @@ "sharedWithYou": "Compartilhado com você", "sharedByYou": "Compartilhado por você", "inviteYourFriendsToEnte": "Convide seus amigos ao Ente", - "failedToDownloadVideo": "Falha ao fazer download do vídeo", + "failedToDownloadVideo": "Falhou ao baixar vídeo", "hiding": "Ocultando...", "unhiding": "Reexibindo...", "successfullyHid": "Ocultado com sucesso", - "successfullyUnhid": "Reexibido com sucesso", - "crashReporting": "Relatório de falhas", + "successfullyUnhid": "Desocultado com sucesso", + "crashReporting": "Relatório de erros", "resumableUploads": "Envios retomáveis", - "addToHiddenAlbum": "Adicionar a álbum oculto", - "moveToHiddenAlbum": "Mover para álbum oculto", + "addToHiddenAlbum": "Adicionar ao álbum oculto", + "moveToHiddenAlbum": "Mover ao álbum oculto", "fileTypes": "Tipos de arquivo", - "deleteConfirmDialogBody": "Esta conta está vinculada a outros aplicativos Ente, se você usar algum. Seus dados enviados, em todos os aplicativos Ente, serão agendados para exclusão, e sua conta será excluída permanentemente.", - "hearUsWhereTitle": "Como você ouviu sobre o Ente? (opcional)", - "hearUsExplanation": "Não rastreamos instalações do aplicativo. Seria útil se você nos contasse onde nos encontrou!", + "deleteConfirmDialogBody": "Esta conta está vinculada aos outros aplicativos do Ente, se você usar algum. Seus dados baixados, entre todos os aplicativos do Ente, serão programados para exclusão, e sua conta será permanentemente excluída.", + "hearUsWhereTitle": "Como você soube do Ente? (opcional)", + "hearUsExplanation": "Não rastreamos instalações de aplicativo. Seria útil se você contasse onde nos encontrou!", "viewAddOnButton": "Ver complementos", "addOns": "Complementos", "addOnPageSubtitle": "Detalhes dos complementos", @@ -1297,8 +1297,8 @@ } } }, - "enable": "Habilitar", - "enabled": "Habilitado", + "enable": "Ativar", + "enabled": "Ativado", "moreDetails": "Mais detalhes", "enableMLIndexingDesc": "Ente suporta aprendizado de máquina no dispositivo para reconhecimento facial, busca mágica e outros recursos avançados de busca", "magicSearchHint": "A busca mágica permite pesquisar fotos por seu conteúdo, por exemplo, 'carro', 'carro vermelho', 'Ferrari'", @@ -1352,5 +1352,12 @@ "addName": "Adicionar pessoa", "add": "Adicionar", "extraPhotosFoundFor": "Fotos adicionais encontradas para $text", - "extraPhotosFound": "Fotos adicionais encontradas" + "extraPhotosFound": "Fotos adicionais encontradas", + "configuration": "Configuração", + "localIndexing": "Indexação local", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ro.arb b/mobile/lib/l10n/intl_ro.arb index b479a114b7..3d94be773b 100644 --- a/mobile/lib/l10n/intl_ro.arb +++ b/mobile/lib/l10n/intl_ro.arb @@ -816,15 +816,6 @@ "referFriendsAnd2xYourPlan": "Recomandați un prieten și dublați-vă planul", "shareAlbumHint": "Deschideți un album și atingeți butonul de distribuire din dreapta sus pentru a distribui.", "itemsShowTheNumberOfDaysRemainingBeforePermanentDeletion": "Articolele afișează numărul de zile rămase până la ștergerea definitivă", - "@trashDaysLeft": { - "description": "Text to indicate number of days remaining before permanent deletion", - "placeholders": { - "count": { - "example": "1|2|3", - "type": "int" - } - } - }, "deleteAll": "Ștergeți tot", "renameAlbum": "Redenumire album", "convertToAlbum": "Convertire în album", @@ -883,6 +874,63 @@ "clubByFileName": "Grupare după numele fișierului", "count": "Total", "totalSize": "Dimensiune totală", + "longpressOnAnItemToViewInFullscreen": "Apăsați lung pe un articol pentru a-l vizualiza pe tot ecranul", + "decryptingVideo": "Se decriptează videoclipul...", + "authToViewYourMemories": "Vă rugăm să vă autentificați pentru a vă vizualiza amintirile", + "unlock": "Deblocare", + "freeUpSpace": "Eliberați spațiu", + "freeUpSpaceSaving": "{count, plural, one {Poate fi șters de pe dispozitiv pentru a elibera {formattedSize}} few {Pot fi șterse de pe dispozitiv pentru a elibera {formattedSize}} other {Pot fi șterse de pe dispozitiv pentru a elibera {formattedSize}}}", + "filesBackedUpInAlbum": "{count, plural, one {Un fișier din acest album a fost deja salvat în siguranță} few {{formattedNumber} fișiere din acest album au fost deja salvate în siguranță} other {{formattedNumber} de fișiere din acest album au fost deja salvate în siguranță}}", + "@filesBackedUpInAlbum": { + "description": "Text to tell user how many files have been backed up in the album", + "placeholders": { + "count": { + "example": "1", + "type": "int" + }, + "formattedNumber": { + "content": "{formattedNumber}", + "example": "1,000", + "type": "String" + } + } + }, + "filesBackedUpFromDevice": "{count, plural, one {Un fișier de pe acest dispozitiv a fost deja salvat în siguranță} few {{formattedNumber} fișiere de pe acest dispozitiv au fost deja salvate în siguranță} other {{formattedNumber} de fișiere de pe acest dispozitiv fost deja salvate în siguranță}}", + "@filesBackedUpFromDevice": { + "description": "Text to tell user how many files have been backed up from this device", + "placeholders": { + "count": { + "example": "1", + "type": "int" + }, + "formattedNumber": { + "content": "{formattedNumber}", + "example": "1,000", + "type": "String" + } + } + }, + "@freeUpSpaceSaving": { + "description": "Text to tell user how much space they can free up by deleting items from the device" + }, + "freeUpAccessPostDelete": "Încă {count, plural, one {îl puteți} few {le puteți} other {le puteți}} accesa pe Ente cât timp aveți un abonament activ", + "@freeUpAccessPostDelete": { + "placeholders": { + "count": { + "example": "1", + "type": "int" + } + } + }, + "freeUpAmount": "Eliberați {sizeInMBorGB}", + "thisEmailIsAlreadyInUse": "Această adresă de e-mail este deja folosită", + "incorrectCode": "Cod incorect", + "authenticationFailedPleaseTryAgain": "Autentificare eșuată, încercați din nou", + "verificationFailedPleaseTryAgain": "Verificare eșuată, încercați din nou", + "authenticating": "Autentificare...", + "authenticationSuccessful": "Autentificare cu succes!", + "incorrectRecoveryKey": "Cheie de recuperare incorectă", + "theRecoveryKeyYouEnteredIsIncorrect": "Cheia de recuperare introdusă este incorectă", "emptyTrash": "Goliți coșul de gunoi?", "permDeleteWarning": "Toate articolele din coșul de gunoi vor fi șterse definitiv\n\nAceastă acțiune nu poate fi anulată", "theyWillBeDeletedFromAllAlbums": "Acestea vor fi șterse din toate albumele.", @@ -1044,5 +1092,10 @@ }, "enable": "Activare", "enabled": "Activat", - "moreDetails": "Mai multe detalii" + "moreDetails": "Mai multe detalii", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ru.arb b/mobile/lib/l10n/intl_ru.arb index 28fb8ea904..2ab9d3ef59 100644 --- a/mobile/lib/l10n/intl_ru.arb +++ b/mobile/lib/l10n/intl_ru.arb @@ -1300,5 +1300,10 @@ "removePublicLinks": "Удалить публичные ссылки", "thisWillRemovePublicLinksOfAllSelectedQuickLinks": "Это удалит публичные ссылки на все выбранные быстрые ссылки.", "guestView": "Гостевой вид", - "guestViewEnablePreSteps": "Чтобы включить гостевой вид, настройте пароль устройства или блокировку экрана в настройках системы." + "guestViewEnablePreSteps": "Чтобы включить гостевой вид, настройте пароль устройства или блокировку экрана в настройках системы.", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_sl.arb b/mobile/lib/l10n/intl_sl.arb index c8494661c6..43569df71a 100644 --- a/mobile/lib/l10n/intl_sl.arb +++ b/mobile/lib/l10n/intl_sl.arb @@ -1,3 +1,8 @@ { - "@@locale ": "en" + "@@locale ": "en", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_sv.arb b/mobile/lib/l10n/intl_sv.arb index 197a99447a..60a5972fee 100644 --- a/mobile/lib/l10n/intl_sv.arb +++ b/mobile/lib/l10n/intl_sv.arb @@ -452,5 +452,13 @@ "next": "Nästa", "guestView": "Gästvy", "showPerson": "Visa person", - "sort": "Sortera" + "sort": "Sortera", + "newPerson": "Ny person", + "addName": "Lägg till namn", + "add": "Lägg till", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ta.arb b/mobile/lib/l10n/intl_ta.arb index d3d26e203c..e1e0db4c8f 100644 --- a/mobile/lib/l10n/intl_ta.arb +++ b/mobile/lib/l10n/intl_ta.arb @@ -15,5 +15,10 @@ "confirmDeletePrompt": "ஆம், எல்லா செயலிகளிலும் இந்தக் கணக்கையும் அதன் தரவையும் நிரந்தரமாக நீக்க விரும்புகிறேன்.", "confirmAccountDeletion": "கணக்கு நீக்குதலை உறுதிப்படுத்தவும்", "deleteAccountPermanentlyButton": "கணக்கை நிரந்தரமாக நீக்கவும்", - "deleteReason1": "எனக்கு தேவையான ஒரு முக்கிய அம்சம் இதில் இல்லை" + "deleteReason1": "எனக்கு தேவையான ஒரு முக்கிய அம்சம் இதில் இல்லை", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_te.arb b/mobile/lib/l10n/intl_te.arb index c8494661c6..43569df71a 100644 --- a/mobile/lib/l10n/intl_te.arb +++ b/mobile/lib/l10n/intl_te.arb @@ -1,3 +1,8 @@ { - "@@locale ": "en" + "@@locale ": "en", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_th.arb b/mobile/lib/l10n/intl_th.arb index 375d1cc22d..bdb4d85eb0 100644 --- a/mobile/lib/l10n/intl_th.arb +++ b/mobile/lib/l10n/intl_th.arb @@ -295,5 +295,10 @@ "description": "Label for the map view" }, "maps": "แผนที่", - "enableMaps": "เปิดใช้งานแผนที่" + "enableMaps": "เปิดใช้งานแผนที่", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_ti.arb b/mobile/lib/l10n/intl_ti.arb index c8494661c6..43569df71a 100644 --- a/mobile/lib/l10n/intl_ti.arb +++ b/mobile/lib/l10n/intl_ti.arb @@ -1,3 +1,8 @@ { - "@@locale ": "en" + "@@locale ": "en", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_tr.arb b/mobile/lib/l10n/intl_tr.arb index dbf015f443..edade696da 100644 --- a/mobile/lib/l10n/intl_tr.arb +++ b/mobile/lib/l10n/intl_tr.arb @@ -1169,5 +1169,10 @@ "invalidEndpoint": "Geçersiz uç nokta", "invalidEndpointMessage": "Üzgünüz, girdiğiniz uç nokta geçersiz. Lütfen geçerli bir uç nokta girin ve tekrar deneyin.", "endpointUpdatedMessage": "Fatura başarıyla güncellendi", - "customEndpoint": "{endpoint}'e bağlanıldı" + "customEndpoint": "{endpoint}'e bağlanıldı", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_uk.arb b/mobile/lib/l10n/intl_uk.arb index 75e5805e99..99d293103d 100644 --- a/mobile/lib/l10n/intl_uk.arb +++ b/mobile/lib/l10n/intl_uk.arb @@ -286,13 +286,13 @@ "details": "Подробиці", "claimMore": "Отримайте більше!", "theyAlsoGetXGb": "Вони також отримують {storageAmountInGB} ГБ", - "freeStorageOnReferralSuccess": "{storageAmountInGB} ГБ щоразу, коли хтось підписується на платний тариф і застосовує ваш код", + "freeStorageOnReferralSuccess": "{storageAmountInGB} ГБ щоразу, коли хтось оформлює передплату і застосовує ваш код", "shareTextReferralCode": "Реферальний код Ente: {referralCode} \n\nЗастосуйте його в «Налаштування» → «Загальні» → «Реферали», щоб отримати {referralStorageInGB} ГБ безплатно після переходу на платний тариф\n\nhttps://ente.io", "claimFreeStorage": "Отримайте безплатне сховище", "inviteYourFriends": "Запросити своїх друзів", "failedToFetchReferralDetails": "Не вдається отримати відомості про реферала. Спробуйте ще раз пізніше.", "referralStep1": "1. Дайте цей код друзям", - "referralStep2": "2. Вони підписуються на платний план", + "referralStep2": "2. Вони оформлюють передплату", "referralStep3": "3. Ви обоє отримуєте {storageInGB} ГБ* безплатно", "referralsAreCurrentlyPaused": "Реферали зараз призупинені", "youCanAtMaxDoubleYourStorage": "* Ви можете максимально подвоїти своє сховище", @@ -327,8 +327,8 @@ "removingFromFavorites": "Видалення з обраного...", "sorryCouldNotAddToFavorites": "Неможливо додати до обраного!", "sorryCouldNotRemoveFromFavorites": "Не вдалося видалити з обраного!", - "subscribeToEnableSharing": "Вам потрібна активна платна підписка, щоб увімкнути спільне поширення.", - "subscribe": "Підписатися", + "subscribeToEnableSharing": "Вам потрібна активна передплата, щоб увімкнути спільне поширення.", + "subscribe": "Передплачувати", "canOnlyRemoveFilesOwnedByYou": "Ви можете видалити лише файли, що належать вам", "deleteSharedAlbum": "Видалити спільний альбом?", "deleteAlbum": "Видалити альбом", @@ -487,7 +487,7 @@ "checking": "Перевірка...", "youAreOnTheLatestVersion": "Ви використовуєте останню версію", "account": "Обліковий запис", - "manageSubscription": "Керування підпискою", + "manageSubscription": "Керування передплатою", "authToChangeYourEmail": "Авторизуйтесь, щоб змінити поштову адресу", "changePassword": "Змінити пароль", "authToChangeYourPassword": "Авторизуйтесь, щоб змінити пароль", @@ -601,18 +601,18 @@ "type": "text" }, "faqs": "ЧаПи", - "renewsOn": "Підписка поновиться {endDate}", + "renewsOn": "Передплата поновиться {endDate}", "freeTrialValidTill": "Безплатна пробна версія діє до {endDate}", "validTill": "Діє до {endDate}", "addOnValidTill": "Ваше доповнення {storageAmount} діє до {endDate}", "playStoreFreeTrialValidTill": "Безплатна пробна версія діє до {endDate}.\nПісля цього ви можете обрати платний план.", - "subWillBeCancelledOn": "Вашу підписку буде скасовано {endDate}", - "subscription": "Підписка", + "subWillBeCancelledOn": "Вашу передплату буде скасовано {endDate}", + "subscription": "Передплата", "paymentDetails": "Деталі платежу", "manageFamily": "Керування сім'єю", - "contactToManageSubscription": "Зв'яжіться з нами за адресою support@ente.io для управління вашою підпискою {provider}.", - "renewSubscription": "Поновити підписку", - "cancelSubscription": "Скасувати підписку", + "contactToManageSubscription": "Зв'яжіться з нами за адресою support@ente.io для управління вашою передплатою {provider}.", + "renewSubscription": "Поновити передплату", + "cancelSubscription": "Скасувати передплату", "areYouSureYouWantToRenew": "Ви впевнені, що хочете поновити?", "yesRenew": "Так, поновити", "areYouSureYouWantToCancel": "Ви дійсно хочете скасувати?", @@ -633,7 +633,7 @@ "confirmPlanChange": "Підтвердити зміну плану", "areYouSureYouWantToChangeYourPlan": "Ви впевнені, що хочете змінити свій план?", "youCannotDowngradeToThisPlan": "Ви не можете перейти до цього плану", - "cancelOtherSubscription": "Спочатку скасуйте вашу підписку від {paymentProvider}", + "cancelOtherSubscription": "Спочатку скасуйте вашу передплату від {paymentProvider}", "@cancelOtherSubscription": { "description": "The text to display when the user has an existing subscription from a different payment provider", "type": "text", @@ -646,19 +646,19 @@ }, "optionalAsShortAsYouLike": "Необов'язково, так коротко, як ви хочете...", "send": "Надіслати", - "askCancelReason": "Підписку було скасовано. Ви хотіли б поділитися причиною?", - "thankYouForSubscribing": "Спасибі за підписку!", + "askCancelReason": "Передплату було скасовано. Ви хотіли б поділитися причиною?", + "thankYouForSubscribing": "Спасибі за передплату!", "yourPurchaseWasSuccessful": "Ваша покупка пройшла успішно", "yourPlanWasSuccessfullyUpgraded": "Ваш план успішно покращено", "yourPlanWasSuccessfullyDowngraded": "Ваш план був успішно знижено", - "yourSubscriptionWasUpdatedSuccessfully": "Вашу підписку успішно оновлено", + "yourSubscriptionWasUpdatedSuccessfully": "Вашу передплату успішно оновлено", "googlePlayId": "Google Play ID", "appleId": "Apple ID", - "playstoreSubscription": "Підписка Play Store", - "appstoreSubscription": "Підписка App Store", + "playstoreSubscription": "Передплата Play Store", + "appstoreSubscription": "Передплата App Store", "subAlreadyLinkedErrMessage": "Ваш {id} вже пов'язаний з іншим обліковим записом Ente.\nЯкщо ви хочете використовувати свій {id} з цим обліковим записом, зверніться до нашої служби підтримки", - "visitWebToManage": "Відвідайте web.ente.io, щоб керувати підпискою", - "couldNotUpdateSubscription": "Не вдалося оновити підписку", + "visitWebToManage": "Відвідайте web.ente.io, щоб керувати передплатою", + "couldNotUpdateSubscription": "Не вдалося оновити передплату", "pleaseContactSupportAndWeWillBeHappyToHelp": "Зв'яжіться з support@ente.io і ми будемо раді допомогти!", "paymentFailed": "Не вдалося оплатити", "paymentFailedTalkToProvider": "Зверніться до {providerName}, якщо було знято платіж", @@ -679,7 +679,7 @@ "pleaseWaitForSometimeBeforeRetrying": "Зачекайте деякий час перед повторною спробою", "paymentFailedMessage": "На жаль, ваш платіж не вдався. Зв'яжіться зі службою підтримки і ми вам допоможемо!", "youAreOnAFamilyPlan": "Ви на сімейному плані!", - "contactFamilyAdmin": "Зв'яжіться з {familyAdminEmail} для керування вашою підпискою", + "contactFamilyAdmin": "Зв'яжіться з {familyAdminEmail} для керування вашою передплатою", "leaveFamily": "Покинути сім'ю", "areYouSureThatYouWantToLeaveTheFamily": "Ви впевнені, що хочете залишити сімейний план?", "leave": "Покинути", @@ -704,7 +704,7 @@ "newToEnte": "Уперше на Ente", "pleaseLoginAgain": "Увійдіть знову", "autoLogoutMessage": "Через технічні збої ви вийшли з системи. Перепрошуємо за незручності.", - "yourSubscriptionHasExpired": "Термін дії вашої підписки скінчився", + "yourSubscriptionHasExpired": "Термін дії вашої передплати скінчився", "storageLimitExceeded": "Перевищено ліміт сховища", "upgrade": "Покращити", "raiseTicket": "Подати заявку", @@ -923,7 +923,7 @@ "@freeUpSpaceSaving": { "description": "Text to tell user how much space they can free up by deleting items from the device" }, - "freeUpAccessPostDelete": "Ви все ще можете отримати доступ до {count, plural, one {нього} other {них}} в Ente, доки у вас активна підписка", + "freeUpAccessPostDelete": "Ви все ще можете отримати доступ до {count, plural, one {нього} other {них}} в Ente, доки у вас активна передплата", "@freeUpAccessPostDelete": { "placeholders": { "count": { @@ -956,6 +956,7 @@ "encryptingBackup": "Шифруємо резервну копію...", "syncStopped": "Синхронізацію зупинено", "syncProgress": "{completed} / {total} спогадів збережено", + "uploadingMultipleMemories": "Збереження {count} спогадів...", "uploadingSingleMemory": "Зберігаємо 1 спогад...", "@syncProgress": { "description": "Text to tell user how many memories have been preserved", @@ -1011,7 +1012,7 @@ "dismiss": "Відхилити", "didYouKnow": "Чи знали ви?", "loadingMessage": "Завантажуємо ваші фотографії...", - "loadMessage1": "Ви можете поділитися своєю підпискою з родиною", + "loadMessage1": "Ви можете поділитися своєю передплатою з родиною", "loadMessage2": "На цей час ми зберегли понад 30 мільйонів спогадів", "loadMessage3": "Ми зберігаємо 3 копії ваших даних, одну в підземному бункері", "loadMessage4": "Всі наші застосунки мають відкритий код", @@ -1342,5 +1343,21 @@ "mostRecent": "Останні", "mostRelevant": "Найактуальніші", "loadingYourPhotos": "Завантажуємо фотографії...", - "processingImport": "Оброблюємо «{folderName}»..." + "processingImport": "Оброблюємо «{folderName}»...", + "personName": "Ім'я особи", + "addNewPerson": "Додати нову особу", + "addNameOrMerge": "Додати назву або об'єднати", + "mergeWithExisting": "Об'єднати з наявним", + "newPerson": "Нова особа", + "addName": "Додати ім'я", + "add": "Додати", + "extraPhotosFoundFor": "Знайдено додаткові фотографії для $text", + "extraPhotosFound": "Знайдено додаткові фотографії", + "configuration": "Налаштування", + "localIndexing": "Локальне індексування", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/l10n/intl_zh.arb b/mobile/lib/l10n/intl_zh.arb index a445996f40..ba458d7334 100644 --- a/mobile/lib/l10n/intl_zh.arb +++ b/mobile/lib/l10n/intl_zh.arb @@ -1343,5 +1343,10 @@ "mostRecent": "最近", "mostRelevant": "最相关", "loadingYourPhotos": "正在加载您的照片...", - "processingImport": "正在处理 {folderName}..." + "processingImport": "正在处理 {folderName}...", + "resetPerson": "Reset person", + "areYouSureYouWantToResetThisPerson": "Are you sure you want to reset this person?", + "allPersonGroupingWillReset": "All groupings for this person will be reset, and you will lose all suggestions made for this person", + "yesResetPerson": "Yes, reset person", + "onlyThem": "Only them" } \ No newline at end of file diff --git a/mobile/lib/models/search/album_search_result.dart b/mobile/lib/models/search/album_search_result.dart index 543012b467..6a74b17871 100644 --- a/mobile/lib/models/search/album_search_result.dart +++ b/mobile/lib/models/search/album_search_result.dart @@ -1,5 +1,7 @@ import 'package:photos/models/collection/collection_items.dart'; import 'package:photos/models/file/file.dart'; +import "package:photos/models/search/hierarchical/album_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; import 'package:photos/models/search/search_result.dart'; import "package:photos/models/search/search_types.dart"; @@ -28,4 +30,13 @@ class AlbumSearchResult extends SearchResult { // for album search result, we should open the album page directly throw UnimplementedError(); } + + @override + HierarchicalSearchFilter getHierarchicalSearchFilter() { + return AlbumFilter( + collectionID: collectionWithThumbnail.collection.id, + albumName: collectionWithThumbnail.collection.displayName, + occurrence: kMostRelevantFilter, + ); + } } diff --git a/mobile/lib/models/search/file_search_result.dart b/mobile/lib/models/search/file_search_result.dart index 8648236c89..53582e034c 100644 --- a/mobile/lib/models/search/file_search_result.dart +++ b/mobile/lib/models/search/file_search_result.dart @@ -1,4 +1,5 @@ import 'package:photos/models/file/file.dart'; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; import 'package:photos/models/search/search_result.dart'; import "package:photos/models/search/search_types.dart"; @@ -27,4 +28,9 @@ class FileSearchResult extends SearchResult { // for fileSearchResult, the file detailed page view will be opened throw UnimplementedError(); } + + @override + HierarchicalSearchFilter getHierarchicalSearchFilter() { + throw UnimplementedError(); + } } diff --git a/mobile/lib/models/search/generic_search_result.dart b/mobile/lib/models/search/generic_search_result.dart index a40f71fd32..ac99dc3fec 100644 --- a/mobile/lib/models/search/generic_search_result.dart +++ b/mobile/lib/models/search/generic_search_result.dart @@ -1,5 +1,6 @@ import "package:flutter/cupertino.dart"; import 'package:photos/models/file/file.dart'; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; import 'package:photos/models/search/search_result.dart'; import "package:photos/models/search/search_types.dart"; @@ -9,11 +10,13 @@ class GenericSearchResult extends SearchResult { final ResultType _type; final Function(BuildContext context)? onResultTap; final Map params; + final HierarchicalSearchFilter hierarchicalSearchFilter; GenericSearchResult( this._type, this._name, this._files, { + required this.hierarchicalSearchFilter, this.onResultTap, this.params = const {}, }); @@ -37,4 +40,9 @@ class GenericSearchResult extends SearchResult { List resultFiles() { return _files; } + + @override + HierarchicalSearchFilter getHierarchicalSearchFilter() { + return hierarchicalSearchFilter; + } } diff --git a/mobile/lib/models/search/hierarchical/album_filter.dart b/mobile/lib/models/search/hierarchical/album_filter.dart new file mode 100644 index 0000000000..3b15479828 --- /dev/null +++ b/mobile/lib/models/search/hierarchical/album_filter.dart @@ -0,0 +1,47 @@ +import "package:flutter/material.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; + +class AlbumFilter extends HierarchicalSearchFilter { + final int collectionID; + final String albumName; + + ///Number of files in the gallery that are from [collectionID] + final int occurrence; + + AlbumFilter({ + required this.collectionID, + required this.albumName, + required this.occurrence, + super.filterTypeName = "albumFilter", + super.matchedUploadedIDs, + }); + + @override + String name() { + return albumName; + } + + @override + IconData icon() { + return Icons.photo_library_outlined; + } + + @override + int relevance() { + return occurrence; + } + + @override + bool isMatch(EnteFile file) { + return file.collectionID == collectionID; + } + + @override + bool isSameFilter(HierarchicalSearchFilter other) { + if (other is AlbumFilter) { + return other.collectionID == collectionID; + } + return false; + } +} diff --git a/mobile/lib/models/search/hierarchical/contacts_filter.dart b/mobile/lib/models/search/hierarchical/contacts_filter.dart new file mode 100644 index 0000000000..100061cc22 --- /dev/null +++ b/mobile/lib/models/search/hierarchical/contacts_filter.dart @@ -0,0 +1,47 @@ +import "package:flutter/material.dart"; +import "package:photos/models/api/collection/user.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; + +class ContactsFilter extends HierarchicalSearchFilter { + final User user; + final int occurrence; + + ContactsFilter({ + required this.user, + required this.occurrence, + super.filterTypeName = "contactsFilter", + super.matchedUploadedIDs, + }); + + @override + String name() { + if (user.name == null || user.name!.isEmpty) { + return user.email.split("@")[0]; + } + return user.name!; + } + + @override + int relevance() { + return occurrence; + } + + @override + bool isMatch(EnteFile file) { + return file.ownerID == user.id; + } + + @override + bool isSameFilter(HierarchicalSearchFilter other) { + if (other is ContactsFilter) { + return other.user.id == user.id; + } + return false; + } + + @override + IconData? icon() { + return Icons.person_outlined; + } +} diff --git a/mobile/lib/models/search/hierarchical/face_filter.dart b/mobile/lib/models/search/hierarchical/face_filter.dart new file mode 100644 index 0000000000..e845f46c30 --- /dev/null +++ b/mobile/lib/models/search/hierarchical/face_filter.dart @@ -0,0 +1,54 @@ +import "package:flutter/material.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; + +class FaceFilter extends HierarchicalSearchFilter { + final String? personId; + final String? clusterId; + final String? faceName; + final EnteFile faceFile; + final int occurrence; + + FaceFilter({ + required this.personId, + required this.clusterId, + required this.faceName, + required this.faceFile, + required this.occurrence, + super.filterTypeName = "faceFilter", + super.matchedUploadedIDs, + }) : assert( + personId != null || clusterId != null, + "personId or clusterId must be provided", + ); + + @override + String name() { + return faceName ?? ""; + } + + @override + int relevance() { + return occurrence; + } + + @override + IconData? icon() { + throw UnimplementedError( + "FaceFilter does not use an icon, the face crop should be used instead", + ); + } + + @override + bool isMatch(EnteFile file) { + throw UnimplementedError(); + } + + @override + bool isSameFilter(HierarchicalSearchFilter other) { + if (other is FaceFilter) { + return other.personId == personId && other.clusterId == clusterId; + } + return false; + } +} diff --git a/mobile/lib/models/search/hierarchical/file_type_filter.dart b/mobile/lib/models/search/hierarchical/file_type_filter.dart new file mode 100644 index 0000000000..807fdfe777 --- /dev/null +++ b/mobile/lib/models/search/hierarchical/file_type_filter.dart @@ -0,0 +1,61 @@ +import "package:flutter/material.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/file/file_type.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; + +extension FileTypeExtension on FileType { + IconData get icon { + switch (this) { + case FileType.image: + return Icons.image; + case FileType.video: + return Icons.videocam; + case FileType.livePhoto: + return Icons.album_outlined; + default: + return Icons.insert_drive_file; + } + } +} + +class FileTypeFilter extends HierarchicalSearchFilter { + final FileType fileType; + final String typeName; + final int occurrence; + + FileTypeFilter({ + required this.fileType, + required this.typeName, + required this.occurrence, + super.filterTypeName = "fileTypeFilter", + super.matchedUploadedIDs, + }); + + @override + String name() { + return typeName; + } + + @override + IconData icon() { + return fileType.icon; + } + + @override + int relevance() { + return occurrence; + } + + @override + bool isMatch(EnteFile file) { + return file.fileType == fileType; + } + + @override + bool isSameFilter(HierarchicalSearchFilter other) { + if (other is FileTypeFilter) { + return other.fileType == fileType; + } + return false; + } +} diff --git a/mobile/lib/models/search/hierarchical/hierarchical_search_filter.dart b/mobile/lib/models/search/hierarchical/hierarchical_search_filter.dart new file mode 100644 index 0000000000..0f30de888b --- /dev/null +++ b/mobile/lib/models/search/hierarchical/hierarchical_search_filter.dart @@ -0,0 +1,46 @@ +import "package:flutter/widgets.dart"; +import "package:photos/models/file/file.dart"; + +int kMostRelevantFilter = 10000; +int kLeastRelevantFilter = -1; + +enum FilterTypeNames { + albumFilter, + contactsFilter, + faceFilter, + fileTypeFilter, + locationFilter, + magicFilter, + topLevelGenericFilter, + onlyThemFilter, +} + +abstract class HierarchicalSearchFilter { + //These matches should be from list of all files in db and not just all files + //in gallery since this is used as cache for faster filtering when + //adding/removing applied filters. + final String filterTypeName; + final Set matchedUploadedIDs; + bool isApplied = false; + + HierarchicalSearchFilter({required this.filterTypeName, matchedUploadedIDs}) + : matchedUploadedIDs = matchedUploadedIDs ?? {}, + //Check to ensure that when a new filter extends HierarchicalSearchFilter, + //it's filterTypeName is added to FilterTypeNames enum. + assert( + FilterTypeNames.values + .map((e) => e.toString().split(".").last) + .contains(filterTypeName), + "filterTypeName = $filterTypeName is not a valid filter type in FilterTypeNames enum. Please add it to the enum if it's missing or else, cross check spelling ", + ); + + String name(); + IconData? icon(); + + /// Will be [kmostRelevantFilter] if the filter is a Top-level filter. For + /// example, when searching for an album 'A' and opening it, when + /// hierarchical search starts, the album 'A' will be the top level filter. + int relevance(); + bool isMatch(EnteFile file); + bool isSameFilter(HierarchicalSearchFilter other); +} diff --git a/mobile/lib/models/search/hierarchical/location_filter.dart b/mobile/lib/models/search/hierarchical/location_filter.dart new file mode 100644 index 0000000000..b9614eb88e --- /dev/null +++ b/mobile/lib/models/search/hierarchical/location_filter.dart @@ -0,0 +1,55 @@ +import "package:flutter/material.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/location_tag/location_tag.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/services/location_service.dart"; + +class LocationFilter extends HierarchicalSearchFilter { + final LocationTag locationTag; + final int occurrence; + + LocationFilter({ + required this.locationTag, + required this.occurrence, + super.filterTypeName = "locationFilter", + super.matchedUploadedIDs, + }); + + @override + String name() { + return locationTag.name; + } + + @override + int relevance() { + return occurrence; + } + + @override + bool isMatch(EnteFile file) { + if (!file.hasLocation) return false; + return isFileInsideLocationTag( + locationTag.centerPoint, + file.location!, + locationTag.radius, + ); + } + + @override + bool isSameFilter(HierarchicalSearchFilter other) { + if (other is LocationFilter) { + return other.locationTag.radius.toString() + + other.locationTag.centerPoint.toString() + + other.locationTag.name == + locationTag.radius.toString() + + locationTag.centerPoint.toString() + + locationTag.name; + } + return false; + } + + @override + IconData icon() { + return Icons.location_pin; + } +} diff --git a/mobile/lib/models/search/hierarchical/magic_filter.dart b/mobile/lib/models/search/hierarchical/magic_filter.dart new file mode 100644 index 0000000000..5b8a2951c1 --- /dev/null +++ b/mobile/lib/models/search/hierarchical/magic_filter.dart @@ -0,0 +1,44 @@ +import "package:flutter/material.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; + +class MagicFilter extends HierarchicalSearchFilter { + final String filterName; + final int occurrence; + + MagicFilter({ + required this.filterName, + required this.occurrence, + super.filterTypeName = "magicFilter", + super.matchedUploadedIDs, + }); + + @override + IconData? icon() { + return Icons.auto_awesome; + } + + @override + bool isMatch(EnteFile file) { + throw UnimplementedError(); + } + + @override + bool isSameFilter(HierarchicalSearchFilter other) { + if (other is MagicFilter && other.name() == name()) { + return true; + } + + return false; + } + + @override + String name() { + return filterName; + } + + @override + int relevance() { + return occurrence; + } +} diff --git a/mobile/lib/models/search/hierarchical/only_them_filter.dart b/mobile/lib/models/search/hierarchical/only_them_filter.dart new file mode 100644 index 0000000000..d4483ec71f --- /dev/null +++ b/mobile/lib/models/search/hierarchical/only_them_filter.dart @@ -0,0 +1,48 @@ +import "package:flutter/material.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; + +class OnlyThemFilter extends HierarchicalSearchFilter { + final List faceFilters; + final int occurrence; + + /// Workaround to avoid passing context to the filter to avoid making context + /// a long lived object. + final String onlyThemString; + + OnlyThemFilter({ + required this.faceFilters, + required this.occurrence, + required this.onlyThemString, + super.filterTypeName = "onlyThemFilter", + }); + + @override + String name() { + return onlyThemString; + } + + @override + int relevance() { + return occurrence; + } + + @override + IconData? icon() { + return Icons.face; + } + + @override + bool isMatch(EnteFile file) { + throw UnimplementedError(); + } + + @override + bool isSameFilter(HierarchicalSearchFilter other) { + if (other is OnlyThemFilter) { + return true; + } + return false; + } +} diff --git a/mobile/lib/models/search/hierarchical/top_level_generic_filter.dart b/mobile/lib/models/search/hierarchical/top_level_generic_filter.dart new file mode 100644 index 0000000000..3654a3a1c0 --- /dev/null +++ b/mobile/lib/models/search/hierarchical/top_level_generic_filter.dart @@ -0,0 +1,57 @@ +import "package:flutter/material.dart"; +import "package:flutter/widgets.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/search_types.dart"; + +///Not necessary that all top level filters in hierarchical search have to be +///a [TopLevelGenericFilter]. This is just a generic filter that can be used +///for dates, descriptions etc which do not have a specific +///[HierarchicalSearchFilter]. +class TopLevelGenericFilter extends HierarchicalSearchFilter { + final String filterName; + final int occurrence; + final IconData? filterIcon; + final ResultType filterResultType; + + TopLevelGenericFilter({ + required this.filterName, + required this.occurrence, + required this.filterResultType, + required super.matchedUploadedIDs, + super.filterTypeName = "topLevelGenericFilter", + this.filterIcon, + }); + + @override + bool isMatch(EnteFile file) { + throw UnimplementedError( + "isMatch is not ment to be called by design for TopLevelGenericFilter. " + "isMatch is used for checking if files match the filter and then to add " + "the file's uploaded fileIDs to the filter's matchingFileIDs list. For " + "top level filters, matchingFileIDs should be set when the filter is " + "initialised since the results are passed to the widget where it's " + "initialised.", + ); + } + + @override + bool isSameFilter(HierarchicalSearchFilter other) { + return other.name() == name(); + } + + @override + String name() { + return filterName; + } + + @override + IconData? icon() { + return filterIcon; + } + + @override + int relevance() { + return occurrence; + } +} diff --git a/mobile/lib/models/search/search_result.dart b/mobile/lib/models/search/search_result.dart index 02c922af0d..7d4b0081d3 100644 --- a/mobile/lib/models/search/search_result.dart +++ b/mobile/lib/models/search/search_result.dart @@ -1,4 +1,5 @@ import "package:photos/models/file/file.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; import "package:photos/models/search/search_types.dart"; abstract class SearchResult { @@ -13,4 +14,6 @@ abstract class SearchResult { } List resultFiles(); + + HierarchicalSearchFilter getHierarchicalSearchFilter(); } diff --git a/mobile/lib/module/upload/service/multipart.dart b/mobile/lib/module/upload/service/multipart.dart index f31e30248c..a1c83059a1 100644 --- a/mobile/lib/module/upload/service/multipart.dart +++ b/mobile/lib/module/upload/service/multipart.dart @@ -135,11 +135,21 @@ class MultiPartUploader { if (multipartInfo.status != MultipartStatus.completed) { // complete the multipart upload - await _completeMultipartUpload( - multipartInfo.urls.objectKey, - etags, - multipartInfo.urls.completeURL, - ); + try { + await _completeMultipartUpload( + multipartInfo.urls.objectKey, + etags, + multipartInfo.urls.completeURL, + ); + } on DioError catch (e) { + if (e.response?.statusCode == 404) { + _logger.severe( + "Multipart upload not found for key ${multipartInfo.urls.objectKey}", + ); + await _db.deleteMultipartTrack(localId); + } + rethrow; + } } return multipartInfo.urls.objectKey; @@ -263,7 +273,7 @@ class MultiPartUploader { MultipartStatus.completed, ); } catch (e) { - Logger("MultipartUpload").severe(e); + Logger("MultipartUpload").severe("upload failed for key $objectKey}", e); rethrow; } } diff --git a/mobile/lib/services/filedata/filedata_service.dart b/mobile/lib/services/filedata/filedata_service.dart index 51048905a1..cc629ed0fe 100644 --- a/mobile/lib/services/filedata/filedata_service.dart +++ b/mobile/lib/services/filedata/filedata_service.dart @@ -5,6 +5,8 @@ import "package:flutter/foundation.dart" show Uint8List; import "package:logging/logging.dart"; import "package:photos/core/network/network.dart"; import "package:photos/db/files_db.dart"; +import "package:photos/db/ml/db.dart"; +import "package:photos/db/ml/filedata.dart"; import "package:photos/models/file/file.dart"; import "package:photos/services/filedata/model/enc_file_data.dart"; import "package:photos/services/filedata/model/file_data.dart"; @@ -20,8 +22,11 @@ class FileDataService { static final FileDataService instance = FileDataService._privateConstructor(); final _logger = Logger("FileDataService"); final _dio = NetworkClient.instance.enteDio; + late final SharedPreferences _prefs; - void init(SharedPreferences prefs) {} + void init(SharedPreferences prefs) { + _prefs = prefs; + } Future putFileData(EnteFile file, FileDataEntity data) async { data.validate(); @@ -88,7 +93,7 @@ class FileDataService { } final inputs = <_DecoderInput>[]; final fileMap = await FilesDB.instance - .getFilesFromIDs(remoteData.map((e) => e.fileID).toList()); + .getFileIDToFileFromIDs(remoteData.map((e) => e.fileID).toList()); for (final data in remoteData) { final file = fileMap[data.fileID]; if (file == null) { @@ -105,6 +110,38 @@ class FileDataService { }, ); } + + Future syncFDStatus() async { + try { + bool hasMoreData = false; + do { + final lastTime = _prefs.getInt("fd.lastSyncTime") ?? 0; + final res = await _dio.post( + "/files/data/status-diff", + data: { + "lastUpdatedAt": lastTime, + }, + ); + final r = res.data; + final data = (r["diff"] ?? []) as List; + final List result = []; + int maxUpdatedAt = lastTime; + for (var entry in data) { + result.add(FDStatus.fromJson(entry)); + if (entry["updatedAt"] > maxUpdatedAt) { + maxUpdatedAt = entry["updatedAt"]; + } + } + await MLDataDB.instance.putFDStatus(result); + await _prefs.setInt("fd.lastSyncTime", maxUpdatedAt); + _logger.info('found ${result.length} fd entries'); + hasMoreData = result.isNotEmpty; + } while (hasMoreData); + } catch (e) { + _logger.severe("Failed to syncDiff", e); + rethrow; + } + } } Future> _decryptFileDataComputer( diff --git a/mobile/lib/services/filedata/model/file_data.dart b/mobile/lib/services/filedata/model/file_data.dart index e9dd6fc14b..4e479bdc7d 100644 --- a/mobile/lib/services/filedata/model/file_data.dart +++ b/mobile/lib/services/filedata/model/file_data.dart @@ -154,3 +154,38 @@ class RemoteClipEmbedding { ); } } + +// FDStatus represents the status of a file data entry. +class FDStatus { + final int fileID; + final int userID; + final String type; + final bool isDeleted; + final int size; + final int updatedAt; + final String? objectID; + final String? objectNonce; + FDStatus({ + required this.fileID, + required this.userID, + required this.type, + required this.size, + required this.updatedAt, + this.isDeleted = false, + this.objectID, + this.objectNonce, + }); + + factory FDStatus.fromJson(Map json) { + return FDStatus( + fileID: json['fileID'] as int, + userID: json['userID'] as int, + type: json['type'] as String, + isDeleted: json['isDeleted'] as bool? ?? false, + size: json['size'] as int, + objectID: json['objectID'] as String?, + objectNonce: json['objectNonce'] as String?, + updatedAt: json['updatedAt'] as int, + ); + } +} diff --git a/mobile/lib/services/filter/db_filters.dart b/mobile/lib/services/filter/db_filters.dart index 0c969dc525..5329b4825c 100644 --- a/mobile/lib/services/filter/db_filters.dart +++ b/mobile/lib/services/filter/db_filters.dart @@ -3,6 +3,7 @@ import 'package:photos/models/file/file.dart'; import "package:photos/services/filter/collection_ignore.dart"; import "package:photos/services/filter/dedupe_by_upload_id.dart"; import "package:photos/services/filter/filter.dart"; +import "package:photos/services/filter/only_uploaded_files_filter.dart"; import "package:photos/services/filter/upload_ignore.dart"; import "package:photos/services/ignored_files_service.dart"; @@ -15,12 +16,14 @@ class DBFilterOptions { bool hideIgnoredForUpload; // If true, shared files that are already saved in the users account will be ignored. bool ignoreSavedFiles; + bool onlyUploadedFiles; DBFilterOptions({ this.ignoredCollectionIDs, this.hideIgnoredForUpload = false, this.dedupeUploadID = true, this.ignoreSavedFiles = false, + this.onlyUploadedFiles = false, }); static DBFilterOptions dedupeOption = DBFilterOptions( @@ -58,6 +61,10 @@ Future> applyDBFilters( filters.add(collectionIgnoreFilter); } + if (options.onlyUploadedFiles) { + filters.add(OnlyUploadedFilesFilter()); + } + final List filterFiles = []; for (final file in files) { if (filters.every((f) => f.filter(file))) { diff --git a/mobile/lib/services/filter/only_uploaded_files_filter.dart b/mobile/lib/services/filter/only_uploaded_files_filter.dart new file mode 100644 index 0000000000..71132ea479 --- /dev/null +++ b/mobile/lib/services/filter/only_uploaded_files_filter.dart @@ -0,0 +1,9 @@ +import "package:photos/models/file/file.dart"; +import "package:photos/services/filter/filter.dart"; + +class OnlyUploadedFilesFilter extends Filter { + @override + bool filter(EnteFile file) { + return file.isUploaded; + } +} diff --git a/mobile/lib/services/location_service.dart b/mobile/lib/services/location_service.dart index 6c90408950..6a3aeb9ceb 100644 --- a/mobile/lib/services/location_service.dart +++ b/mobile/lib/services/location_service.dart @@ -45,6 +45,19 @@ class LocationService { ); } + Future> getLocationTagsToOccurance( + List files, + ) async { + final locationTagEntities = await locationService.getLocationTags(); + + final locationTagToOccurrence = await _computer.compute( + _getLocationTagsToOccurenceForIsolate, + param: {"files": files, "locationTagEntities": locationTagEntities}, + ); + + return locationTagToOccurrence; + } + Future>> getFilesInCity( List allFiles, String query, @@ -86,7 +99,7 @@ class LocationService { try { final a = - (radius * _scaleFactor(centerPoint.latitude!)) / kilometersPerDegree; + (radius * scaleFactor(centerPoint.latitude!)) / kilometersPerDegree; final b = radius / kilometersPerDegree; final locationTag = LocationTag( name: location, @@ -175,7 +188,7 @@ class LocationService { return; } final a = - (radius * _scaleFactor(centerPoint.latitude!)) / kilometersPerDegree; + (radius * scaleFactor(centerPoint.latitude!)) / kilometersPerDegree; final b = radius / kilometersPerDegree; final updatedLoationTag = locationTagEntity.item.copyWith( centerPoint: centerPoint, @@ -242,6 +255,39 @@ class LocationService { } } +Map _getLocationTagsToOccurenceForIsolate( + Map args, +) { + final List files = args["files"]; + + final locationTagToOccurence = {}; + final locationTagEntities = + args["locationTagEntities"] as Iterable>; + + for (EnteFile file in files) { + if (file.uploadedFileID == null || + file.uploadedFileID == -1 || + !file.hasLocation) continue; + for (LocalEntity locationTagEntity in locationTagEntities) { + final locationTag = locationTagEntity.item; + final fileCoordinates = file.location!; + if (isFileInsideLocationTag( + locationTag.centerPoint, + fileCoordinates, + locationTag.radius, + )) { + locationTagToOccurence.update( + locationTag, + (value) => value + 1, + ifAbsent: () => 1, + ); + } + } + } + + return locationTagToOccurence; +} + Future> parseCities(Map args) async { final file = File(args["filePath"]); final citiesJson = json.decode(await file.readAsString()); @@ -286,8 +332,7 @@ bool isFileInsideLocationTag( Location fileCoordinates, double radius, ) { - final a = - (radius * _scaleFactor(centerPoint.latitude!)) / kilometersPerDegree; + final a = (radius * scaleFactor(centerPoint.latitude!)) / kilometersPerDegree; final b = radius / kilometersPerDegree; final x = centerPoint.latitude! - fileCoordinates.latitude!; final y = centerPoint.longitude! - fileCoordinates.longitude!; @@ -301,7 +346,7 @@ bool isFileInsideLocationTag( ///in the magnitude of the latitude on the caritesian plane. When latitude is ///0 degrees, the ellipse is a circle with a = b = r. When latitude incrases, ///the major axis (a) has to be scaled by the secant of the latitude. -double _scaleFactor(double lat) { +double scaleFactor(double lat) { return 1 / cos(lat * (pi / 180)); } diff --git a/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart b/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart index e6462fb8f5..2f17010180 100644 --- a/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart +++ b/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart @@ -84,7 +84,7 @@ class ClusterFeedbackService { final clusterIdToFaceIDs = await MLDataDB.instance.getClusterToFaceIDs(suggestionClusterIDs); final Map> clusterIDToFiles = {}; - final allFiles = await SearchService.instance.getAllFiles(); + final allFiles = await SearchService.instance.getAllFilesForSearch(); for (final f in allFiles) { if (!fileIdToClusterID.containsKey(f.uploadedFileID ?? -1)) { continue; diff --git a/mobile/lib/services/machine_learning/ml_indexing_isolate.dart b/mobile/lib/services/machine_learning/ml_indexing_isolate.dart index 91dae6906b..11e5375a61 100644 --- a/mobile/lib/services/machine_learning/ml_indexing_isolate.dart +++ b/mobile/lib/services/machine_learning/ml_indexing_isolate.dart @@ -9,7 +9,10 @@ import 'package:photos/services/machine_learning/face_ml/face_embedding/face_emb import "package:photos/services/machine_learning/ml_models_overview.dart"; import 'package:photos/services/machine_learning/ml_result.dart'; import "package:photos/services/machine_learning/semantic_search/clip/clip_image_encoder.dart"; +import "package:photos/services/remote_assets_service.dart"; import "package:photos/utils/ml_util.dart"; +import "package:photos/utils/network_util.dart"; +import "package:synchronized/synchronized.dart"; class MLIndexingIsolate extends SuperIsolate { @override @@ -25,6 +28,11 @@ class MLIndexingIsolate extends SuperIsolate { @override bool get shouldAutomaticDispose => true; + final _initModelLock = Lock(); + final _downloadModelLock = Lock(); + + bool areModelsDownloaded = false; + @override Future onDispose() async { await _releaseModels(); @@ -86,7 +94,63 @@ class MLIndexingIsolate extends SuperIsolate { return result; } - Future loadModels({ + void triggerModelsDownload() { + if (!areModelsDownloaded && !_downloadModelLock.locked) { + _logger.info("Models not downloaded, starting download"); + unawaited(ensureDownloadedModels()); + } + } + + Future ensureDownloadedModels([bool forceRefresh = false]) async { + if (_downloadModelLock.locked) { + _logger.finest("Download models already in progress"); + return; + } + return _downloadModelLock.synchronized(() async { + if (areModelsDownloaded) { + _logger.finest("Models already downloaded"); + return; + } + final goodInternet = await canUseHighBandwidth(); + if (!goodInternet) { + _logger.info( + "Cannot download models because user is not connected to wifi", + ); + return; + } + _logger.info('Downloading models'); + await Future.wait([ + FaceDetectionService.instance.downloadModel(forceRefresh), + FaceEmbeddingService.instance.downloadModel(forceRefresh), + ClipImageEncoder.instance.downloadModel(forceRefresh), + ]); + areModelsDownloaded = true; + }); + } + + Future ensureLoadedModels(FileMLInstruction instruction) async { + return _initModelLock.synchronized(() async { + final faceDetectionLoaded = FaceDetectionService.instance.isInitialized; + final faceEmbeddingLoaded = FaceEmbeddingService.instance.isInitialized; + final facesModelsLoaded = faceDetectionLoaded && faceEmbeddingLoaded; + final clipModelsLoaded = ClipImageEncoder.instance.isInitialized; + + final shouldLoadFaces = instruction.shouldRunFaces && !facesModelsLoaded; + final shouldLoadClip = instruction.shouldRunClip && !clipModelsLoaded; + if (!shouldLoadFaces && !shouldLoadClip) { + return; + } + + _logger.info( + 'Loading models. faces: $shouldLoadFaces, clip: $shouldLoadClip', + ); + await MLIndexingIsolate.instance + ._loadModels(loadFaces: shouldLoadFaces, loadClip: shouldLoadClip); + _logger.info('Models loaded'); + }); + } + + Future _loadModels({ required bool loadFaces, required bool loadClip, }) async { @@ -129,6 +193,25 @@ class MLIndexingIsolate extends SuperIsolate { } } + Future cleanupLocalIndexingModels({bool delete = false}) async { + if (!areModelsDownloaded) return; + await _releaseModels(); + + if (delete) { + final List remoteModelPaths = []; + + for (final model in MLModels.values) { + if (!model.isIndexingModel) continue; + final mlModel = model.model; + remoteModelPaths.add(mlModel.modelRemotePath); + } + await RemoteAssetsService.instance + .cleanupSelectedModels(remoteModelPaths); + + areModelsDownloaded = false; + } + } + Future _releaseModels() async { final List modelNames = []; final List modelAddresses = []; diff --git a/mobile/lib/services/machine_learning/ml_service.dart b/mobile/lib/services/machine_learning/ml_service.dart index 4e73ae0f3a..ef064068fd 100644 --- a/mobile/lib/services/machine_learning/ml_service.dart +++ b/mobile/lib/services/machine_learning/ml_service.dart @@ -17,17 +17,15 @@ import "package:photos/services/filedata/filedata_service.dart"; import "package:photos/services/filedata/model/file_data.dart"; import 'package:photos/services/machine_learning/face_ml/face_clustering/face_clustering_service.dart'; import "package:photos/services/machine_learning/face_ml/face_clustering/face_db_info_for_clustering.dart"; -import 'package:photos/services/machine_learning/face_ml/face_detection/face_detection_service.dart'; -import 'package:photos/services/machine_learning/face_ml/face_embedding/face_embedding_service.dart'; import 'package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart'; import "package:photos/services/machine_learning/face_ml/person/person_service.dart"; import "package:photos/services/machine_learning/ml_indexing_isolate.dart"; import 'package:photos/services/machine_learning/ml_result.dart'; -import "package:photos/services/machine_learning/semantic_search/clip/clip_image_encoder.dart"; import "package:photos/services/machine_learning/semantic_search/semantic_search_service.dart"; +import "package:photos/services/user_remote_flag_service.dart"; import "package:photos/utils/ml_util.dart"; import "package:photos/utils/network_util.dart"; -import "package:synchronized/synchronized.dart"; +import "package:photos/utils/ram_check_util.dart"; class MLService { final _logger = Logger("MLService"); @@ -37,11 +35,10 @@ class MLService { static final instance = MLService._privateConstructor(); factory MLService() => instance; - final _initModelLock = Lock(); - final _downloadModelLock = Lock(); - bool _isInitialized = false; - bool areModelsDownloaded = false; + + int? lastRemoteFetch; + static const int _kRemoteFetchCooldownOnLite = 1000 * 60 * 5; late String client; @@ -59,12 +56,15 @@ class MLService { static const _kForceClusteringFaceCount = 8000; /// Only call this function once at app startup, after that you can directly call [runAllML] - Future init({bool firstTime = false}) async { - if (localSettings.isMLIndexingEnabled == false || _isInitialized) { - return; - } + Future init() async { + if (_isInitialized) return; + if (!userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled)) return; _logger.info("init called"); + // Check if the device has enough RAM to run local indexing + await checkDeviceTotalRAM(); + // Get client name final packageInfo = ServiceLocator.instance.packageInfo; client = "${packageInfo.packageName}/${packageInfo.version}"; @@ -72,9 +72,9 @@ class MLService { // Listen on MachineLearningController Bus.instance.on().listen((event) { - if (localSettings.isMLIndexingEnabled == false) { - return; - } + if (!userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled)) return; + _mlControllerStatus = event.shouldRun; if (_mlControllerStatus) { if (_shouldPauseIndexingAndClustering) { @@ -100,7 +100,22 @@ class MLService { _logger.info('init done'); } + bool canFetch() { + if (localSettings.isMLLocalIndexingEnabled) return true; + if (lastRemoteFetch == null) { + lastRemoteFetch = DateTime.now().millisecondsSinceEpoch; + return true; + } + final intDiff = DateTime.now().millisecondsSinceEpoch - lastRemoteFetch!; + final bool canFetch = intDiff > _kRemoteFetchCooldownOnLite; + if (canFetch) { + lastRemoteFetch = DateTime.now().millisecondsSinceEpoch; + } + return canFetch; + } + Future sync() async { + await FileDataService.instance.syncFDStatus(); await faceRecognitionService.sync(); } @@ -111,7 +126,6 @@ class MLService { } if (_cannotRunMLFunction() && !force) return; _isRunningML = true; - await sync(); final int unclusteredFacesCount = @@ -126,7 +140,9 @@ class MLService { // refresh discover section magicCacheService.updateCache(forced: force).ignore(); } - await indexAllImages(); + if (canFetch()) { + await fetchAndIndexAllImages(); + } if ((await MLDataDB.instance.getUnclusteredFaceCount()) > 0) { await clusterAllImages(); } @@ -162,10 +178,11 @@ class MLService { MLIndexingIsolate.instance.shouldPauseIndexingAndClustering = false; } - /// Analyzes all the images in the database with the latest ml version and stores the results in the database. + /// Analyzes all the images in the user library with the latest ml version and stores the results in the database. /// - /// This function first checks if the image has already been analyzed with the lastest faceMlVersion and stored in the database. If so, it skips the image. - Future indexAllImages() async { + /// This function first fetches from remote and checks if the image has already been analyzed + /// with the lastest faceMlVersion and stored on remote or local database. If so, it skips the image. + Future fetchAndIndexAllImages() async { if (_cannotRunMLFunction()) return; try { @@ -179,13 +196,16 @@ class MLService { stream: await for (final chunk in instructionStream) { - if (!await canUseHighBandwidth()) { + if (!localSettings.isMLLocalIndexingEnabled) { + await MLIndexingIsolate.instance.cleanupLocalIndexingModels(); + continue; + } else if (!await canUseHighBandwidth()) { _logger.info( 'stopping indexing because user is not connected to wifi', ); break stream; } else { - await _ensureDownloadedModels(); + await MLIndexingIsolate.instance.ensureDownloadedModels(); } final futures = >[]; for (final instruction in chunk) { @@ -193,7 +213,7 @@ class MLService { _logger.info("indexAllImages() was paused, stopping"); break stream; } - await _ensureLoadedModels(instruction); + await MLIndexingIsolate.instance.ensureLoadedModels(instruction); futures.add(processImage(instruction)); } final awaitedFutures = await Future.wait(futures); @@ -501,62 +521,6 @@ class MLService { } } - void triggerModelsDownload() { - if (!areModelsDownloaded && !_downloadModelLock.locked) { - _logger.info("Models not downloaded, starting download"); - unawaited(_ensureDownloadedModels()); - } - } - - Future _ensureDownloadedModels([bool forceRefresh = false]) async { - if (_downloadModelLock.locked) { - _logger.finest("Download models already in progress"); - } - return _downloadModelLock.synchronized(() async { - if (areModelsDownloaded) { - _logger.finest("Models already downloaded"); - return; - } - final goodInternet = await canUseHighBandwidth(); - if (!goodInternet) { - _logger.info( - "Cannot download models because user is not connected to wifi", - ); - return; - } - _logger.info('Downloading models'); - await Future.wait([ - FaceDetectionService.instance.downloadModel(forceRefresh), - FaceEmbeddingService.instance.downloadModel(forceRefresh), - ClipImageEncoder.instance.downloadModel(forceRefresh), - ]); - areModelsDownloaded = true; - }); - } - - Future _ensureLoadedModels(FileMLInstruction instruction) async { - return _initModelLock.synchronized(() async { - final faceDetectionLoaded = FaceDetectionService.instance.isInitialized; - final faceEmbeddingLoaded = FaceEmbeddingService.instance.isInitialized; - final facesModelsLoaded = faceDetectionLoaded && faceEmbeddingLoaded; - final clipModelsLoaded = ClipImageEncoder.instance.isInitialized; - - final shouldLoadFaces = instruction.shouldRunFaces && !facesModelsLoaded; - final shouldLoadClip = instruction.shouldRunClip && !clipModelsLoaded; - if (!shouldLoadFaces && !shouldLoadClip) { - return; - } - - _logger.info( - 'Loading models. faces: $shouldLoadFaces, clip: $shouldLoadClip', - ); - await MLIndexingIsolate.instance - .loadModels(loadFaces: shouldLoadFaces, loadClip: shouldLoadClip); - _logger.info('Models loaded'); - _logStatus(); - }); - } - bool _cannotRunMLFunction({String function = ""}) { if (kDebugMode && Platform.isIOS && !_isIndexingOrClusteringRunning) { return false; @@ -596,7 +560,7 @@ class MLService { void _logStatus() { final String status = ''' isInternalUser: ${flagService.internalUser} - isMLIndexingEnabled: ${localSettings.isMLIndexingEnabled} + Local indexing: ${localSettings.isMLLocalIndexingEnabled} canRunMLController: $_mlControllerStatus isIndexingOrClusteringRunning: $_isIndexingOrClusteringRunning shouldPauseIndexingAndClustering: $_shouldPauseIndexingAndClustering diff --git a/mobile/lib/services/machine_learning/semantic_search/semantic_search_service.dart b/mobile/lib/services/machine_learning/semantic_search/semantic_search_service.dart index e6eb268f52..835db22a87 100644 --- a/mobile/lib/services/machine_learning/semantic_search/semantic_search_service.dart +++ b/mobile/lib/services/machine_learning/semantic_search/semantic_search_service.dart @@ -22,6 +22,7 @@ import "package:photos/services/collections_service.dart"; import "package:photos/services/machine_learning/ml_computer.dart"; import "package:photos/services/machine_learning/ml_result.dart"; import "package:photos/services/machine_learning/semantic_search/clip/clip_image_encoder.dart"; +import "package:photos/services/user_remote_flag_service.dart"; import "package:shared_preferences/shared_preferences.dart"; class SemanticSearchService { @@ -43,13 +44,15 @@ class SemanticSearchService { String? _latestPendingQuery; Future init() async { - if (!localSettings.isMLIndexingEnabled) { - return; - } if (_hasInitialized) { _logger.info("Initialized already"); return; } + final hasGivenConsent = userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled); + if (!hasGivenConsent) return; + + _logger.info("init called"); _hasInitialized = true; // call getClipEmbeddings after 5 seconds @@ -64,7 +67,8 @@ class SemanticSearchService { } bool isMagicSearchEnabledAndReady() { - return localSettings.isMLIndexingEnabled && _textModelIsLoaded; + return userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled) && _textModelIsLoaded; } // searchScreenQuery should only be used for the user initiate query on the search screen. @@ -73,7 +77,8 @@ class SemanticSearchService { if (!isMagicSearchEnabledAndReady()) { if (flagService.internalUser) { _logger.info( - "Magic search enabled: ${localSettings.isMLIndexingEnabled}, loaded: $_textModelIsLoaded ", + "ML global consent: ${userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled)}, loaded: $_textModelIsLoaded ", ); } return (query, []); @@ -150,7 +155,7 @@ class SemanticSearchService { } final filesMap = await FilesDB.instance - .getFilesFromIDs(queryResults.map((e) => e.id).toList()); + .getFileIDToFileFromIDs(queryResults.map((e) => e.id).toList()); final ignoredCollections = CollectionsService.instance.getHiddenCollectionIds(); diff --git a/mobile/lib/services/magic_cache_service.dart b/mobile/lib/services/magic_cache_service.dart index 895db2061b..fc9d02a0a9 100644 --- a/mobile/lib/services/magic_cache_service.dart +++ b/mobile/lib/services/magic_cache_service.dart @@ -16,12 +16,16 @@ import "package:photos/models/file/extensions/file_props.dart"; import "package:photos/models/file/file.dart"; import "package:photos/models/ml/discover/prompt.dart"; import "package:photos/models/search/generic_search_result.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/hierarchical/magic_filter.dart"; import "package:photos/models/search/search_types.dart"; import "package:photos/service_locator.dart"; import "package:photos/services/machine_learning/semantic_search/semantic_search_service.dart"; import "package:photos/services/remote_assets_service.dart"; import "package:photos/services/search_service.dart"; +import "package:photos/services/user_remote_flag_service.dart"; import "package:photos/ui/viewer/search/result/magic_result_screen.dart"; +import "package:photos/utils/file_util.dart"; import "package:photos/utils/navigation_util.dart"; import "package:shared_preferences/shared_preferences.dart"; @@ -140,10 +144,25 @@ GenericSearchResult? toGenericSearchResult( ResultType.magic, title, enteFilesInMagicCache, + hierarchicalSearchFilter: MagicFilter( + filterName: title, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(enteFilesInMagicCache), + ), ).heroTag(), + magicFilter: MagicFilter( + filterName: title, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(enteFilesInMagicCache), + ), ), ); }, + hierarchicalSearchFilter: MagicFilter( + filterName: title, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(enteFilesInMagicCache), + ), ); } @@ -173,8 +192,6 @@ class MagicCacheService { }); } - - Future _resetLastMagicCacheUpdateTime() async { await _prefs.setInt( _lastMagicCacheUpdateTime, @@ -186,7 +203,8 @@ class MagicCacheService { return _prefs.getInt(_lastMagicCacheUpdateTime) ?? 0; } - bool get enableDiscover => localSettings.isMLIndexingEnabled; + bool get enableDiscover => + userRemoteFlagService.getCachedBoolValue(UserRemoteFlagService.mlEnabled); void queueUpdate(String reason) { _pendingUpdateReason.add(reason); @@ -263,7 +281,7 @@ class MagicCacheService { return _promptFuture!; } - Future> _getMagicCache() async { + Future> getMagicCache() async { if (_magicCacheFuture != null) { return _magicCacheFuture!; } @@ -304,7 +322,7 @@ class MagicCacheService { final EnteWatch? w = kDebugMode ? EnteWatch("magicGenericSearchResult") : null; w?.start(); - final magicCaches = await _getMagicCache(); + final magicCaches = await getMagicCache(); final List prompts = await getPrompts(); if (magicCaches.isEmpty) { w?.log("No magic cache found"); @@ -324,7 +342,8 @@ class MagicCacheService { promptMap[p.title] = p; } final List genericSearchResults = []; - final List files = await SearchService.instance.getAllFiles(); + final List files = + await SearchService.instance.getAllFilesForSearch(); for (EnteFile file in files) { if (!file.isUploaded) continue; for (MagicCache magicCache in magicCaches) { diff --git a/mobile/lib/services/remote_assets_service.dart b/mobile/lib/services/remote_assets_service.dart index e14155af1b..e3b27a8a9f 100644 --- a/mobile/lib/services/remote_assets_service.dart +++ b/mobile/lib/services/remote_assets_service.dart @@ -128,7 +128,14 @@ class RemoteAssetsService { "https://models.ente.io/yolov5s_face_opset18_rgba_opt_nosplits.onnx", ]; - for (final remotePath in oldModelNames) { + await cleanupSelectedModels(oldModelNames); + + checkRemovedOldAssets = true; + _logger.info("Old ML models cleaned up"); + } + + Future cleanupSelectedModels(List modelRemotePaths) async { + for (final remotePath in modelRemotePaths) { final localPath = await _getLocalPath(remotePath); if (File(localPath).existsSync()) { _logger.info( @@ -137,8 +144,5 @@ class RemoteAssetsService { await File(localPath).delete(); } } - - checkRemovedOldAssets = true; - _logger.info("Old ML models cleaned up"); } } diff --git a/mobile/lib/services/remote_sync_service.dart b/mobile/lib/services/remote_sync_service.dart index 3de481fc95..1134955e05 100644 --- a/mobile/lib/services/remote_sync_service.dart +++ b/mobile/lib/services/remote_sync_service.dart @@ -312,7 +312,7 @@ class RemoteSyncService { await _db.deleteFilesFromCollection(collectionID, fileIDs); if (localDeleteCount > 0) { final collectionFiles = - (await _db.getFilesFromIDs(fileIDs)).values.toList(); + (await _db.getFileIDToFileFromIDs(fileIDs)).values.toList(); collectionFiles.removeWhere((f) => f.collectionID != collectionID); Bus.instance.fire( CollectionUpdatedEvent( diff --git a/mobile/lib/services/search_service.dart b/mobile/lib/services/search_service.dart index 22b02d953b..0bb3fb95bc 100644 --- a/mobile/lib/services/search_service.dart +++ b/mobile/lib/services/search_service.dart @@ -1,6 +1,7 @@ import "dart:math"; import "package:flutter/cupertino.dart"; +import "package:flutter/material.dart"; import "package:intl/intl.dart"; import 'package:logging/logging.dart'; import "package:photos/core/constants.dart"; @@ -24,14 +25,23 @@ import "package:photos/models/location_tag/location_tag.dart"; import "package:photos/models/ml/face/person.dart"; import 'package:photos/models/search/album_search_result.dart'; import 'package:photos/models/search/generic_search_result.dart'; +import "package:photos/models/search/hierarchical/contacts_filter.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/models/search/hierarchical/file_type_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/hierarchical/location_filter.dart"; +import "package:photos/models/search/hierarchical/magic_filter.dart"; +import "package:photos/models/search/hierarchical/top_level_generic_filter.dart"; import "package:photos/models/search/search_constants.dart"; import "package:photos/models/search/search_types.dart"; import "package:photos/service_locator.dart"; import 'package:photos/services/collections_service.dart'; +import "package:photos/services/filter/db_filters.dart"; import "package:photos/services/location_service.dart"; import "package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart"; import "package:photos/services/machine_learning/face_ml/person/person_service.dart"; import 'package:photos/services/machine_learning/semantic_search/semantic_search_service.dart'; +import "package:photos/services/user_remote_flag_service.dart"; import "package:photos/states/location_screen_state.dart"; import "package:photos/ui/viewer/location/add_location_sheet.dart"; import "package:photos/ui/viewer/location/location_screen.dart"; @@ -39,11 +49,14 @@ import "package:photos/ui/viewer/people/cluster_page.dart"; import "package:photos/ui/viewer/people/people_page.dart"; import "package:photos/ui/viewer/search/result/magic_result_screen.dart"; import 'package:photos/utils/date_time_util.dart'; +import "package:photos/utils/file_util.dart"; import "package:photos/utils/navigation_util.dart"; import 'package:tuple/tuple.dart'; class SearchService { Future>? _cachedFilesFuture; + Future>? _cachedFilesForSearch; + Future>? _cachedFilesForHierarchicalSearch; Future>? _cachedHiddenFilesFuture; final _logger = Logger((SearchService).toString()); final _collectionService = CollectionsService.instance; @@ -57,6 +70,8 @@ class SearchService { Bus.instance.on().listen((event) { // only invalidate, let the load happen on demand _cachedFilesFuture = null; + _cachedFilesForSearch = null; + _cachedFilesForHierarchicalSearch = null; _cachedHiddenFilesFuture = null; }); } @@ -65,16 +80,56 @@ class SearchService { return CollectionsService.instance.getHiddenCollectionIds(); } - Future> getAllFiles() async { - if (_cachedFilesFuture != null) { - return _cachedFilesFuture!; + Future> getAllFilesForSearch() async { + if (_cachedFilesFuture != null && _cachedFilesForSearch != null) { + return _cachedFilesForSearch!; } - _logger.fine("Reading all files from db"); - _cachedFilesFuture = FilesDB.instance.getAllFilesFromDB( - ignoreCollections(), - dedupeByUploadId: true, - ); - return _cachedFilesFuture!; + + if (_cachedFilesFuture == null) { + _logger.fine("Reading all files from db"); + _cachedFilesFuture = FilesDB.instance.getAllFilesFromDB( + ignoreCollections(), + dedupeByUploadId: false, + ); + } + + _cachedFilesForSearch = _cachedFilesFuture!.then((files) { + return applyDBFilters( + files, + DBFilterOptions( + dedupeUploadID: true, + ), + ); + }); + + return _cachedFilesForSearch!; + } + + Future> getAllFilesForHierarchicalSearch() async { + if (_cachedFilesFuture != null && + _cachedFilesForHierarchicalSearch != null) { + return _cachedFilesForHierarchicalSearch!; + } + + if (_cachedFilesFuture == null) { + _logger.fine("Reading all files from db"); + _cachedFilesFuture = FilesDB.instance.getAllFilesFromDB( + ignoreCollections(), + dedupeByUploadId: false, + ); + } + + _cachedFilesForHierarchicalSearch = _cachedFilesFuture!.then((files) { + return applyDBFilters( + files, + DBFilterOptions( + dedupeUploadID: false, + onlyUploadedFiles: true, + ), + ); + }); + + return _cachedFilesForHierarchicalSearch!; } Future> getHiddenFiles() async { @@ -91,6 +146,8 @@ class SearchService { void clearCache() { _cachedFilesFuture = null; + _cachedFilesForSearch = null; + _cachedFilesForHierarchicalSearch = null; _cachedHiddenFilesFuture = null; } @@ -168,6 +225,13 @@ class SearchService { ResultType.year, yearData.year, filesInYear, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: yearData.year, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.year, + matchedUploadedIDs: filesToUploadedFileIDs(filesInYear), + filterIcon: Icons.calendar_month_outlined, + ), ), ); } @@ -179,7 +243,8 @@ class SearchService { Future> getMagicSectionResults( BuildContext context, ) async { - if (localSettings.isMLIndexingEnabled) { + if (userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled)) { return magicCacheService.getMagicGenericSearchResult(context); } else { return []; @@ -222,6 +287,13 @@ class SearchService { ResultType.year, yearData.year, filesInYear, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: yearData.year, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.year, + matchedUploadedIDs: filesToUploadedFileIDs(filesInYear), + filterIcon: Icons.calendar_month_outlined, + ), ); } } @@ -247,6 +319,13 @@ class SearchService { ResultType.month, month.name, matchedFiles, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: month.name, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.month, + matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), + filterIcon: Icons.calendar_month_outlined, + ), ), ); } @@ -270,6 +349,13 @@ class SearchService { ResultType.month, month.name, matchedFiles, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: month.name, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.month, + matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), + filterIcon: Icons.calendar_month_outlined, + ), ); } } @@ -296,7 +382,18 @@ class SearchService { ); if (matchedFiles.isNotEmpty) { searchResults.add( - GenericSearchResult(ResultType.event, holiday.name, matchedFiles), + GenericSearchResult( + ResultType.event, + holiday.name, + matchedFiles, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: holiday.name, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.event, + matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), + filterIcon: Icons.event_outlined, + ), + ), ); } } @@ -320,6 +417,13 @@ class SearchService { ResultType.event, holiday.name, matchedFiles, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: holiday.name, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.event, + matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), + filterIcon: Icons.event_outlined, + ), ); } } @@ -331,7 +435,7 @@ class SearchService { String query, ) async { final List searchResults = []; - final List allFiles = await getAllFiles(); + final List allFiles = await getAllFilesForSearch(); for (var fileType in FileType.values) { final String fileTypeString = getHumanReadableString(context, fileType); if (fileTypeString.toLowerCase().startsWith(query.toLowerCase())) { @@ -343,6 +447,12 @@ class SearchService { ResultType.fileType, fileTypeString, matchedFiles, + hierarchicalSearchFilter: FileTypeFilter( + fileType: fileType, + typeName: fileTypeString, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), + ), ), ); } @@ -356,7 +466,7 @@ class SearchService { int? limit, ) async { final List searchResults = []; - final List allFiles = await getAllFiles(); + final List allFiles = await getAllFilesForSearch(); final fileTypesAndMatchingFiles = >{}; final extensionsAndMatchingFiles = >{}; try { @@ -382,11 +492,18 @@ class SearchService { } fileTypesAndMatchingFiles.forEach((key, value) { + final name = getHumanReadableString(context, key); searchResults.add( GenericSearchResult( ResultType.fileType, - getHumanReadableString(context, key), + name, value, + hierarchicalSearchFilter: FileTypeFilter( + fileType: key, + typeName: name, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(value), + ), ), ); }); @@ -397,6 +514,13 @@ class SearchService { ResultType.fileExtension, key + "s", value, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: key + "s", + occurrence: kMostRelevantFilter, + filterResultType: ResultType.fileExtension, + matchedUploadedIDs: filesToUploadedFileIDs(value), + filterIcon: CupertinoIcons.doc_text, + ), ), ); }); @@ -422,7 +546,7 @@ class SearchService { ) async { try { final List searchResults = []; - final List allFiles = await getAllFiles(); + final List allFiles = await getAllFilesForSearch(); //each list element will be substrings from a description mapped by //word count = 1 and word count > 1 @@ -544,8 +668,20 @@ class SearchService { } relevantDescAndFiles.forEach((key, value) { + final listOfFiles = value.toList(); searchResults.add( - GenericSearchResult(ResultType.fileCaption, key, value.toList()), + GenericSearchResult( + ResultType.fileCaption, + key, + listOfFiles, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: key, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.fileCaption, + matchedUploadedIDs: filesToUploadedFileIDs(listOfFiles), + filterIcon: Icons.description_outlined, + ), + ), ); }); if (limit != null) { @@ -567,7 +703,7 @@ class SearchService { return searchResults; } final RegExp pattern = RegExp(query, caseSensitive: false); - final List allFiles = await getAllFiles(); + final List allFiles = await getAllFilesForSearch(); final List captionMatch = []; final List displayNameMatch = []; for (EnteFile eachFile in allFiles) { @@ -584,6 +720,13 @@ class SearchService { ResultType.fileCaption, query, captionMatch, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: query, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.fileCaption, + matchedUploadedIDs: filesToUploadedFileIDs(captionMatch), + filterIcon: Icons.description_outlined, + ), ), ); } @@ -593,6 +736,12 @@ class SearchService { ResultType.file, query, displayNameMatch, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: query, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.file, + matchedUploadedIDs: filesToUploadedFileIDs(displayNameMatch), + ), ), ); } @@ -607,7 +756,7 @@ class SearchService { return searchResults; } - final List allFiles = await getAllFiles(); + final List allFiles = await getAllFilesForSearch(); final Map> resultMap = >{}; for (EnteFile eachFile in allFiles) { @@ -626,6 +775,13 @@ class SearchService { ResultType.fileExtension, entry.key.toUpperCase(), entry.value, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: entry.key.toUpperCase(), + occurrence: kMostRelevantFilter, + filterResultType: ResultType.fileExtension, + matchedUploadedIDs: filesToUploadedFileIDs(entry.value), + filterIcon: CupertinoIcons.doc_text, + ), ), ); } @@ -645,7 +801,7 @@ class SearchService { result[tag] = []; } } - final allFiles = await getAllFiles(); + final allFiles = await getAllFilesForSearch(); for (EnteFile file in allFiles) { if (file.hasLocation) { for (LocalEntity tag in result.keys) { @@ -684,6 +840,13 @@ class SearchService { ResultType.fileType, "No Location Tag", noLocationTagFiles, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: "No Location Tag", + occurrence: kMostRelevantFilter, + filterResultType: ResultType.fileType, + matchedUploadedIDs: filesToUploadedFileIDs(noLocationTagFiles), + filterIcon: Icons.not_listed_location_outlined, + ), ), ); } @@ -708,6 +871,11 @@ class SearchService { ), ); }, + hierarchicalSearchFilter: LocationFilter( + locationTag: entry.key.item, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(entry.value), + ), ), ); } @@ -724,11 +892,25 @@ class SearchService { for (final city in sortedByResultCount) { // If the location tag already exists for a city, don't add it again if (!locationTagNames.contains(city.city)) { + final a = + (defaultCityRadius * scaleFactor(city.lat)) / kilometersPerDegree; + const b = defaultCityRadius / kilometersPerDegree; searchResults.add( GenericSearchResult( ResultType.location, city.city, results[city]!, + hierarchicalSearchFilter: LocationFilter( + locationTag: LocationTag( + name: city.city, + radius: defaultCityRadius, + centerPoint: Location(latitude: city.lat, longitude: city.lng), + aSquare: a * a, + bSquare: b * b, + ), + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(results[city]!), + ), ), ); } @@ -744,7 +926,7 @@ class SearchService { await MLDataDB.instance.getFileIdToClusterIDSet(personID); _logger.info('faceDbDone getClusterFilesForPersonID $personID'); final Map> clusterIDToFiles = {}; - final allFiles = await getAllFiles(); + final allFiles = await getAllFilesForSearch(); for (final f in allFiles) { if (!fileIdToClusterID.containsKey(f.uploadedFileID ?? -1)) { continue; @@ -778,13 +960,13 @@ class SearchService { final List facesResult = []; final Map> clusterIdToFiles = {}; final Map> personIdToFiles = {}; - final allFiles = await getAllFiles(); + final allFiles = await getAllFilesForSearch(); for (final f in allFiles) { if (!fileIdToClusterID.containsKey(f.uploadedFileID ?? -1)) { continue; } - final cluserIds = fileIdToClusterID[f.uploadedFileID ?? -1]!; - for (final cluster in cluserIds) { + final clusterIds = fileIdToClusterID[f.uploadedFileID ?? -1]!; + for (final cluster in clusterIds) { final PersonEntity? p = personIdToPerson[clusterIDToPersonID[cluster] ?? ""]; if (p != null) { @@ -831,9 +1013,34 @@ class SearchService { PeoplePage( tagPrefix: "${ResultType.faces.toString()}_${p.data.name}", person: p, + searchResult: GenericSearchResult( + ResultType.faces, + p.data.name, + files, + params: { + kPersonParamID: personID, + kFileID: files.first.uploadedFileID, + }, + hierarchicalSearchFilter: FaceFilter( + personId: p.remoteID, + clusterId: null, + faceName: p.data.name, + faceFile: files.first, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(files), + ), + ), ), ); }, + hierarchicalSearchFilter: FaceFilter( + personId: p.remoteID, + clusterId: null, + faceName: p.data.name, + faceFile: files.first, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(files), + ), ), ); } @@ -877,6 +1084,14 @@ class SearchService { ), ); }, + hierarchicalSearchFilter: FaceFilter( + personId: null, + clusterId: clusterId, + faceName: null, + faceFile: files.first, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(files), + ), ), ); } @@ -910,7 +1125,7 @@ class SearchService { final Map, List> tagToItemsMap = {}; final List tagSearchResults = []; final locationTagEntities = (await locationService.getLocationTags()); - final allFiles = await getAllFiles(); + final allFiles = await getAllFilesForSearch(); final List filesWithNoLocTag = []; for (int i = 0; i < locationTagEntities.length; i++) { @@ -960,6 +1175,11 @@ class SearchService { ), ); }, + hierarchicalSearchFilter: LocationFilter( + locationTag: entry.key.item, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(entry.value), + ), ), ); } @@ -971,6 +1191,9 @@ class SearchService { ..sort((a, b) => results[b]!.length.compareTo(results[a]!.length)); for (final city in sortedByResultCount) { if (results[city]!.length <= 1) continue; + final a = + (defaultCityRadius * scaleFactor(city.lat)) / kilometersPerDegree; + const b = defaultCityRadius / kilometersPerDegree; tagSearchResults.add( GenericSearchResult( ResultType.locationSuggestion, @@ -984,6 +1207,18 @@ class SearchService { radius: defaultCityRadius, ); }, + hierarchicalSearchFilter: LocationFilter( + locationTag: LocationTag( + name: city.city, + radius: defaultCityRadius, + centerPoint: + Location(latitude: city.lat, longitude: city.lng), + aSquare: a * a, + bSquare: b * b, + ), + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(results[city]!), + ), ), ); } @@ -1013,11 +1248,19 @@ class SearchService { order: 'DESC', ); if (matchedFiles.isNotEmpty) { + final name = '$day ${potentialDate.item2.name} ${year ?? ''}'; searchResults.add( GenericSearchResult( ResultType.event, - '$day ${potentialDate.item2.name} ${year ?? ''}', + name, matchedFiles, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: name, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.event, + matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), + filterIcon: Icons.event_outlined, + ), ), ); } @@ -1052,11 +1295,29 @@ class SearchService { files, name: query, enableGrouping: false, - heroTag: GenericSearchResult(ResultType.magic, query, files) - .heroTag(), + heroTag: GenericSearchResult( + ResultType.magic, + query, + files, + hierarchicalSearchFilter: MagicFilter( + filterName: query, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(files), + ), + ).heroTag(), + magicFilter: MagicFilter( + filterName: query, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(files), + ), ), ); }, + hierarchicalSearchFilter: MagicFilter( + filterName: query, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(files), + ), ), ); } @@ -1066,7 +1327,7 @@ class SearchService { Future getRandomDateResults( BuildContext context, ) async { - final allFiles = await getAllFiles(); + final allFiles = await getAllFilesForSearch(); if (allFiles.isEmpty) return null; final length = allFiles.length; @@ -1097,12 +1358,19 @@ class SearchService { order: 'DESC', ); + final name = DateFormat.yMMMd(Localizations.localeOf(context).languageCode) + .format(originalDateTime.toLocal()); return GenericSearchResult( ResultType.event, - DateFormat.yMMMd(Localizations.localeOf(context).languageCode).format( - DateTime.fromMicrosecondsSinceEpoch(creationTime).toLocal(), - ), + name, matchedFiles, + hierarchicalSearchFilter: TopLevelGenericFilter( + filterName: name, + occurrence: kMostRelevantFilter, + filterResultType: ResultType.event, + matchedUploadedIDs: filesToUploadedFileIDs(matchedFiles), + filterIcon: Icons.event_outlined, + ), ); } @@ -1111,7 +1379,7 @@ class SearchService { ) async { final lowerCaseQuery = query.toLowerCase(); final searchResults = []; - final allFiles = await getAllFiles(); + final allFiles = await getAllFilesForSearch(); final peopleToSharedFiles = >{}; for (EnteFile file in allFiles) { if (file.isOwner) continue; @@ -1135,6 +1403,11 @@ class SearchService { ResultType.shared, key.name != null && key.name!.isNotEmpty ? key.name! : key.email, value, + hierarchicalSearchFilter: ContactsFilter( + user: key, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(value), + ), ), ); }); @@ -1147,7 +1420,7 @@ class SearchService { ) async { try { final searchResults = []; - final allFiles = await getAllFiles(); + final allFiles = await getAllFilesForSearch(); final peopleToSharedFiles = >{}; int peopleCount = 0; for (EnteFile file in allFiles) { @@ -1165,13 +1438,19 @@ class SearchService { } peopleToSharedFiles.forEach((key, value) { + final name = key.name != null && key.name!.isNotEmpty + ? key.name! + : key.email.split("@")[0]; searchResults.add( GenericSearchResult( ResultType.shared, - key.name != null && key.name!.isNotEmpty - ? key.name! - : key.email.split("@")[0], + name, value, + hierarchicalSearchFilter: ContactsFilter( + user: key, + occurrence: kMostRelevantFilter, + matchedUploadedIDs: filesToUploadedFileIDs(value), + ), ), ); }); diff --git a/mobile/lib/ui/common/popup_item.dart b/mobile/lib/ui/common/popup_item.dart index 5f32104af0..845bdb7b85 100644 --- a/mobile/lib/ui/common/popup_item.dart +++ b/mobile/lib/ui/common/popup_item.dart @@ -4,13 +4,17 @@ class EntePopupMenuItem extends PopupMenuItem { final String label; final IconData? icon; final Widget? iconWidget; + final Color? iconColor; + final Color? labelColor; EntePopupMenuItem( this.label, { - required T value, + required T super.value, this.icon, this.iconWidget, - Key? key, + this.iconColor, + this.labelColor, + super.key, }) : assert( icon != null || iconWidget != null, 'Either icon or iconWidget must be provided.', @@ -20,18 +24,19 @@ class EntePopupMenuItem extends PopupMenuItem { 'Only one of icon or iconWidget can be provided.', ), super( - value: value, - key: key, child: Row( children: [ if (iconWidget != null) iconWidget else if (icon != null) - Icon(icon), + Icon(icon, color: iconColor), const Padding( padding: EdgeInsets.all(8), ), - Text(label), + Text( + label, + style: TextStyle(color: labelColor), + ), ], ), // Initially empty, will be populated in build ); diff --git a/mobile/lib/ui/components/expandable_menu_item_widget.dart b/mobile/lib/ui/components/expandable_menu_item_widget.dart index 91c2c8d87b..e212282f68 100644 --- a/mobile/lib/ui/components/expandable_menu_item_widget.dart +++ b/mobile/lib/ui/components/expandable_menu_item_widget.dart @@ -97,9 +97,9 @@ class _ExpandableMenuItemWidgetState extends State { void _expandableControllerListener() { setState(() { if (expandableController.expanded) { - InheritedSettingsState.of(context).increment(); + InheritedSettingsState.maybeOf(context)?.increment(); } else { - InheritedSettingsState.of(context).decrement(); + InheritedSettingsState.maybeOf(context)?.decrement(); } }); } diff --git a/mobile/lib/ui/payment/subscription_plan_widget.dart b/mobile/lib/ui/payment/subscription_plan_widget.dart index d5723e4a86..7869a3ee17 100644 --- a/mobile/lib/ui/payment/subscription_plan_widget.dart +++ b/mobile/lib/ui/payment/subscription_plan_widget.dart @@ -162,19 +162,25 @@ class _Price extends StatelessWidget { final priceWithoutCurrency = price.substring(1); final priceDouble = double.parse(priceWithoutCurrency); final pricePerMonth = priceDouble / 12; - final pricePerMonthString = pricePerMonth.toStringAsFixed(2); + String pricePerMonthString = pricePerMonth.toStringAsFixed(2); + + if (pricePerMonthString.endsWith(".00")) { + pricePerMonthString = + pricePerMonthString.substring(0, pricePerMonthString.length - 3); + } + final bool isPlayStore = updateService.isPlayStoreFlavor(); return Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ if (isPlayStore) Text( - price + " / " + "yr", + currencySymbol + pricePerMonthString + ' / ' + 'month', style: textTheme.largeBold.copyWith(color: textBaseLight), ), if (isPlayStore) Text( - currencySymbol + pricePerMonthString + ' / ' + 'month', + price + " / " + "yr", style: textTheme.small.copyWith(color: textFaintLight), ), if (!isPlayStore) diff --git a/mobile/lib/ui/settings/backup/backup_status_screen.dart b/mobile/lib/ui/settings/backup/backup_status_screen.dart index f8f5a34af6..d37f3f79bb 100644 --- a/mobile/lib/ui/settings/backup/backup_status_screen.dart +++ b/mobile/lib/ui/settings/backup/backup_status_screen.dart @@ -35,7 +35,7 @@ class _BackupStatusScreenState extends State { } Future getAllFiles() async { - result = (await SearchService.instance.getAllFiles()) + result = (await SearchService.instance.getAllFilesForSearch()) .where( (e) => e.uploadedFileID != null && e.isOwner, ) diff --git a/mobile/lib/ui/settings/debug/ml_debug_section_widget.dart b/mobile/lib/ui/settings/debug/ml_debug_section_widget.dart index bfac4549c1..098845c657 100644 --- a/mobile/lib/ui/settings/debug/ml_debug_section_widget.dart +++ b/mobile/lib/ui/settings/debug/ml_debug_section_widget.dart @@ -8,8 +8,10 @@ import "package:photos/events/people_changed_event.dart"; import "package:photos/models/ml/face/person.dart"; import "package:photos/service_locator.dart"; import "package:photos/services/machine_learning/face_ml/person/person_service.dart"; +import "package:photos/services/machine_learning/ml_indexing_isolate.dart"; import 'package:photos/services/machine_learning/ml_service.dart'; import "package:photos/services/machine_learning/semantic_search/semantic_search_service.dart"; +import "package:photos/services/user_remote_flag_service.dart"; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/components/captioned_text_widget.dart'; import 'package:photos/ui/components/expandable_menu_item_widget.dart'; @@ -56,7 +58,6 @@ class _MLDebugSectionWidgetState extends State { Widget _getSectionOptions(BuildContext context) { final Logger logger = Logger("MLDebugSectionWidget"); - final colorScheme = getEnteColorScheme(context); return Column( children: [ sectionOptionSpacing, @@ -73,19 +74,28 @@ class _MLDebugSectionWidgetState extends State { return const SizedBox.shrink(); }, ), - menuItemColor: colorScheme.fillFaint, trailingWidget: ToggleSwitchWidget( - value: () => localSettings.isMLIndexingEnabled, + value: () => userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled), onChanged: () async { try { - final isEnabled = await localSettings.toggleMLIndexing(); - logger.info('ML indexing turned ${isEnabled ? 'on' : 'off'}'); - if (isEnabled) { + final oldMlConsent = userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled); + final mlConsent = !oldMlConsent; + await userRemoteFlagService.setBoolValue( + UserRemoteFlagService.mlEnabled, + mlConsent, + ); + logger.info('ML consent turned ${mlConsent ? 'on' : 'off'}'); + if (!mlConsent) { + MLService.instance.pauseIndexingAndClustering(); + unawaited( + MLIndexingIsolate.instance.cleanupLocalIndexingModels(), + ); + } else { await MLService.instance.init(); await SemanticSearchService.instance.init(); unawaited(MLService.instance.runAllML(force: true)); - } else { - MLService.instance.pauseIndexingAndClustering(); } if (mounted) { setState(() {}); @@ -104,7 +114,6 @@ class _MLDebugSectionWidgetState extends State { captionedTextWidget: const CaptionedTextWidget( title: "Remote fetch", ), - menuItemColor: colorScheme.fillFaint, trailingWidget: ToggleSwitchWidget( value: () => localSettings.remoteFetchEnabled, onChanged: () async { @@ -133,11 +142,36 @@ class _MLDebugSectionWidgetState extends State { isGestureDetectorDisabled: true, ), sectionOptionSpacing, + MenuItemWidget( + captionedTextWidget: const CaptionedTextWidget( + title: "Local indexing", + ), + trailingWidget: ToggleSwitchWidget( + value: () => localSettings.isMLLocalIndexingEnabled, + onChanged: () async { + final localIndexing = await localSettings.toggleLocalMLIndexing(); + if (localIndexing) { + unawaited(MLService.instance.runAllML(force: true)); + } else { + MLService.instance.pauseIndexingAndClustering(); + unawaited( + MLIndexingIsolate.instance.cleanupLocalIndexingModels(), + ); + } + + if (mounted) { + setState(() {}); + } + }, + ), + singleBorderRadius: 8, + isGestureDetectorDisabled: true, + ), + sectionOptionSpacing, MenuItemWidget( captionedTextWidget: const CaptionedTextWidget( title: "Auto indexing", ), - menuItemColor: colorScheme.fillFaint, trailingWidget: ToggleSwitchWidget( value: () => !MLService.instance.debugIndexingDisabled, onChanged: () async { @@ -190,7 +224,7 @@ class _MLDebugSectionWidgetState extends State { onTap: () async { try { MLService.instance.debugIndexingDisabled = false; - unawaited(MLService.instance.indexAllImages()); + unawaited(MLService.instance.fetchAndIndexAllImages()); } catch (e, s) { logger.warning('indexing failed ', e, s); await showGenericErrorDialog(context: context, error: e); diff --git a/mobile/lib/ui/settings/ml/machine_learning_settings_page.dart b/mobile/lib/ui/settings/ml/machine_learning_settings_page.dart index ec873100ca..867c559102 100644 --- a/mobile/lib/ui/settings/ml/machine_learning_settings_page.dart +++ b/mobile/lib/ui/settings/ml/machine_learning_settings_page.dart @@ -7,6 +7,7 @@ import "package:photos/l10n/l10n.dart"; import "package:photos/service_locator.dart"; import "package:photos/services/machine_learning/face_ml/face_detection/face_detection_service.dart"; import "package:photos/services/machine_learning/face_ml/face_embedding/face_embedding_service.dart"; +import "package:photos/services/machine_learning/ml_indexing_isolate.dart"; import "package:photos/services/machine_learning/ml_service.dart"; import "package:photos/services/machine_learning/semantic_search/clip/clip_image_encoder.dart"; import "package:photos/services/machine_learning/semantic_search/clip/clip_text_encoder.dart"; @@ -19,6 +20,7 @@ import "package:photos/ui/common/web_page.dart"; import "package:photos/ui/components/buttons/button_widget.dart"; import "package:photos/ui/components/buttons/icon_button_widget.dart"; import "package:photos/ui/components/captioned_text_widget.dart"; +import "package:photos/ui/components/expandable_menu_item_widget.dart"; import "package:photos/ui/components/menu_item_widget/menu_item_widget.dart"; import "package:photos/ui/components/menu_section_description_widget.dart"; import "package:photos/ui/components/menu_section_title.dart"; @@ -26,6 +28,7 @@ import "package:photos/ui/components/models/button_type.dart"; import "package:photos/ui/components/title_bar_title_widget.dart"; import "package:photos/ui/components/title_bar_widget.dart"; import "package:photos/ui/components/toggle_switch_widget.dart"; +import "package:photos/ui/settings/common_settings.dart"; import "package:photos/ui/settings/ml/enable_ml_consent.dart"; import "package:photos/ui/settings/ml/ml_user_dev_screen.dart"; import "package:photos/utils/ml_util.dart"; @@ -52,7 +55,7 @@ class _MachineLearningSettingsPageState super.initState(); _wakeLock.enable(); machineLearningController.forceOverrideML(turnOn: true); - if (!MLService.instance.areModelsDownloaded) { + if (!MLIndexingIsolate.instance.areModelsDownloaded) { _timer = Timer.periodic(const Duration(seconds: 10), (timer) { if (mounted) { setState(() {}); @@ -75,7 +78,8 @@ class _MachineLearningSettingsPageState @override Widget build(BuildContext context) { - final hasEnabled = localSettings.isMLIndexingEnabled; + final hasEnabled = userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled); return Scaffold( body: CustomScrollView( primary: false, @@ -90,7 +94,6 @@ class _MachineLearningSettingsPageState _titleTapCount++; if (_titleTapCount >= 7) { _titleTapCount = 0; - // showShortToast(context, "Advanced options enabled"); Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) { @@ -168,7 +171,7 @@ class _MachineLearningSettingsPageState buttonType: ButtonType.primary, labelText: context.l10n.enable, onTap: () async { - await toggleIndexingState(); + await toggleMlConsent(); }, ), const SizedBox(height: 12), @@ -208,10 +211,11 @@ class _MachineLearningSettingsPageState ); } - Future toggleIndexingState() async { - final hasGivenConsent = userRemoteFlagService + Future toggleMlConsent() async { + final oldMlConsent = userRemoteFlagService .getCachedBoolValue(UserRemoteFlagService.mlEnabled); - if (!localSettings.isMLIndexingEnabled && !hasGivenConsent) { + // Go to consent page first if not enabled + if (!oldMlConsent) { final result = await Navigator.push( context, MaterialPageRoute( @@ -224,17 +228,20 @@ class _MachineLearningSettingsPageState return; } } - final isEnabled = await localSettings.toggleMLIndexing(); - if (isEnabled) { - await MLService.instance.init(firstTime: true); + final mlConsent = !oldMlConsent; + await userRemoteFlagService.setBoolValue( + UserRemoteFlagService.mlEnabled, + mlConsent, + ); + if (!mlConsent) { + MLService.instance.pauseIndexingAndClustering(); + unawaited( + MLIndexingIsolate.instance.cleanupLocalIndexingModels(), + ); + } else { + await MLService.instance.init(); await SemanticSearchService.instance.init(); unawaited(MLService.instance.runAllML(force: true)); - } else { - MLService.instance.pauseIndexingAndClustering(); - await userRemoteFlagService.setBoolValue( - UserRemoteFlagService.mlEnabled, - false, - ); } if (mounted) { setState(() {}); @@ -242,34 +249,69 @@ class _MachineLearningSettingsPageState } Widget _getMlSettings(BuildContext context) { - final colorScheme = getEnteColorScheme(context); - final hasEnabled = localSettings.isMLIndexingEnabled; + final hasEnabled = userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled); + if (!hasEnabled) { + return const SizedBox.shrink(); + } return Column( children: [ - if (hasEnabled) - MenuItemWidget( - captionedTextWidget: CaptionedTextWidget( - title: S.of(context).enabled, - ), - menuItemColor: colorScheme.fillFaint, - trailingWidget: ToggleSwitchWidget( - value: () => localSettings.isMLIndexingEnabled, - onChanged: () async { - await toggleIndexingState(); - }, - ), - singleBorderRadius: 8, - alignCaptionedTextToLeft: true, - isGestureDetectorDisabled: true, + ExpandableMenuItemWidget( + title: S.of(context).configuration, + selectionOptionsWidget: Column( + children: [ + sectionOptionSpacing, + MenuItemWidget( + captionedTextWidget: CaptionedTextWidget( + title: S.of(context).enabled, + ), + trailingWidget: ToggleSwitchWidget( + value: () => hasEnabled, + onChanged: () async { + await toggleMlConsent(); + }, + ), + singleBorderRadius: 8, + isGestureDetectorDisabled: true, + ), + sectionOptionSpacing, + MenuItemWidget( + captionedTextWidget: CaptionedTextWidget( + title: S.of(context).localIndexing, + ), + trailingWidget: ToggleSwitchWidget( + value: () => localSettings.isMLLocalIndexingEnabled, + onChanged: () async { + final localIndexing = + await localSettings.toggleLocalMLIndexing(); + if (localIndexing) { + unawaited(MLService.instance.runAllML(force: true)); + } else { + MLService.instance.pauseIndexingAndClustering(); + unawaited( + MLIndexingIsolate.instance.cleanupLocalIndexingModels(), + ); + } + + if (mounted) { + setState(() {}); + } + }, + ), + singleBorderRadius: 8, + isGestureDetectorDisabled: true, + ), + ], ), + leadingIcon: Icons.settings_outlined, + ), const SizedBox( height: 12, ), - hasEnabled - ? MLService.instance.areModelsDownloaded - ? const MLStatusWidget() - : const ModelLoadingState() - : const SizedBox.shrink(), + MLIndexingIsolate.instance.areModelsDownloaded || + !localSettings.isMLLocalIndexingEnabled + ? const MLStatusWidget() + : const ModelLoadingState(), ], ); } @@ -333,7 +375,7 @@ class _ModelLoadingStateState extends State { builder: (context, snapshot) { if (snapshot.hasData) { if (snapshot.data!) { - MLService.instance.triggerModelsDownload(); + MLIndexingIsolate.instance.triggerModelsDownload(); return CaptionedTextWidget( title: S.of(context).loadingModel, key: const ValueKey("loading_model"), diff --git a/mobile/lib/ui/viewer/actions/file_selection_overlay_bar.dart b/mobile/lib/ui/viewer/actions/file_selection_overlay_bar.dart index a6b98b4e7f..5f4c80718b 100644 --- a/mobile/lib/ui/viewer/actions/file_selection_overlay_bar.dart +++ b/mobile/lib/ui/viewer/actions/file_selection_overlay_bar.dart @@ -2,11 +2,16 @@ import 'package:flutter/material.dart'; import 'package:photos/models/collection/collection.dart'; import 'package:photos/models/gallery_type.dart'; import "package:photos/models/ml/face/person.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/hierarchical/only_them_filter.dart"; import 'package:photos/models/selected_files.dart'; import "package:photos/theme/effects.dart"; import "package:photos/theme/ente_theme.dart"; import 'package:photos/ui/components/bottom_action_bar/bottom_action_bar_widget.dart'; import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; import "package:photos/ui/viewer/gallery/state/selection_state.dart"; class FileSelectionOverlayBar extends StatefulWidget { @@ -34,10 +39,14 @@ class FileSelectionOverlayBar extends StatefulWidget { class _FileSelectionOverlayBarState extends State { final ValueNotifier _hasSelectedFilesNotifier = ValueNotifier(false); + late GalleryType _galleryType; + SearchFilterDataProvider? _searchFilterDataProvider; + bool? _galleryInitialFilterStillApplied; @override void initState() { super.initState(); + _galleryType = widget.galleryType; widget.selectedFiles.addListener(_selectedFilesListener); } @@ -45,16 +54,46 @@ class _FileSelectionOverlayBarState extends State { void dispose() { _hasSelectedFilesNotifier.dispose(); widget.selectedFiles.removeListener(_selectedFilesListener); + _searchFilterDataProvider?.removeListener( + listener: _filterAppliedListener, + fromApplied: true, + ); super.dispose(); } + @override + void didUpdateWidget(covariant FileSelectionOverlayBar oldWidget) { + super.didUpdateWidget(oldWidget); + _galleryType = widget.galleryType; + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + final inheritedSearchFilterData = + InheritedSearchFilterData.maybeOf(context); + if (inheritedSearchFilterData?.isHierarchicalSearchable ?? false) { + _searchFilterDataProvider = + inheritedSearchFilterData!.searchFilterDataProvider; + + _searchFilterDataProvider!.removeListener( + listener: _filterAppliedListener, + fromApplied: true, + ); + _searchFilterDataProvider!.addListener( + listener: _filterAppliedListener, + toApplied: true, + ); + } + } + @override Widget build(BuildContext context) { debugPrint( '$runtimeType building with ${widget.selectedFiles.files.length}', ); - return widget.galleryType == GalleryType.homepage + return _galleryType == GalleryType.homepage ? _body() : PopScope( canPop: false, @@ -99,7 +138,7 @@ class _FileSelectionOverlayBarState extends State { ), child: BottomActionBarWidget( selectedFiles: widget.selectedFiles, - galleryType: widget.galleryType, + galleryType: _galleryType, collection: widget.collection, person: widget.person, clusterID: widget.clusterID, @@ -122,6 +161,54 @@ class _FileSelectionOverlayBarState extends State { _selectedFilesListener() { _hasSelectedFilesNotifier.value = widget.selectedFiles.files.isNotEmpty; } + + void _filterAppliedListener() { + widget.selectedFiles.clearAll(); + _updateGalleryTypeIfRequired(); + } + + /// This method is used to update the GalleryType if the initial filter is + /// removed from the applied filters. As long as the inital filter is present + /// in the applied filters, the gallery type will remain the same as the type + /// initally passed in the widget constructor. Once the inital filter is + /// removed, the gallery type will be updated to GalleryType.searchResults + /// and never be updated again. + void _updateGalleryTypeIfRequired() { + if (_galleryInitialFilterStillApplied != null && + !_galleryInitialFilterStillApplied!) { + return; + } + + final appliedFilters = _searchFilterDataProvider!.appliedFilters; + final initialFilter = _searchFilterDataProvider!.initialGalleryFilter; + bool initalFilterIsInAppliedFiters = false; + for (HierarchicalSearchFilter filter in appliedFilters) { + if (filter.isSameFilter(initialFilter)) { + initalFilterIsInAppliedFiters = true; + break; + } + if (initialFilter is FaceFilter) { + for (HierarchicalSearchFilter filter in appliedFilters) { + if (filter is OnlyThemFilter) { + if (filter.faceFilters + .any((faceFilter) => faceFilter.isSameFilter(initialFilter))) { + initalFilterIsInAppliedFiters = true; + break; + } + } + } + } + } + + if (!initalFilterIsInAppliedFiters) { + setState(() { + _galleryInitialFilterStillApplied = false; + _galleryType = GalleryType.searchResults; + }); + } else { + _galleryInitialFilterStillApplied = true; + } + } } class SelectAllButton extends StatefulWidget { diff --git a/mobile/lib/ui/viewer/file/file_details_widget.dart b/mobile/lib/ui/viewer/file/file_details_widget.dart index 21318523ba..0d3d403655 100644 --- a/mobile/lib/ui/viewer/file/file_details_widget.dart +++ b/mobile/lib/ui/viewer/file/file_details_widget.dart @@ -18,6 +18,7 @@ import "package:photos/models/location/location.dart"; import "package:photos/models/metadata/file_magic.dart"; import "package:photos/service_locator.dart"; import "package:photos/services/file_magic_service.dart"; +import "package:photos/services/user_remote_flag_service.dart"; import 'package:photos/theme/ente_theme.dart'; import 'package:photos/ui/components/buttons/icon_button_widget.dart'; import "package:photos/ui/components/divider_widget.dart"; @@ -280,7 +281,8 @@ class _FileDetailsWidgetState extends State { ]); } - if (localSettings.isMLIndexingEnabled) { + if (userRemoteFlagService + .getCachedBoolValue(UserRemoteFlagService.mlEnabled)) { fileDetailsTiles.addAll([ FacesItemWidget(file), const FileDetailsDivider(), diff --git a/mobile/lib/ui/viewer/file_details/face_widget.dart b/mobile/lib/ui/viewer/file_details/face_widget.dart index 58c2338812..15c506021a 100644 --- a/mobile/lib/ui/viewer/file_details/face_widget.dart +++ b/mobile/lib/ui/viewer/file_details/face_widget.dart @@ -79,7 +79,8 @@ class _FaceWidgetState extends State { if (existingClusterID != null) { final fileIdsToClusterIds = await MLDataDB.instance.getFileIdToClusterIds(); - final files = await SearchService.instance.getAllFiles(); + final files = + await SearchService.instance.getAllFilesForSearch(); final clusterFiles = files .where( (file) => @@ -119,13 +120,15 @@ class _FaceWidgetState extends State { MaterialPageRoute( builder: (context) => PeoplePage( person: widget.person!, + searchResult: null, ), ), ); } else if (widget.clusterID != null) { final fileIdsToClusterIds = await MLDataDB.instance.getFileIdToClusterIds(); - final files = await SearchService.instance.getAllFiles(); + final files = + await SearchService.instance.getAllFilesForSearch(); final clusterFiles = files .where( (file) => diff --git a/mobile/lib/ui/viewer/file_details/location_tags_widget.dart b/mobile/lib/ui/viewer/file_details/location_tags_widget.dart index 29bcee4da3..fd85ef491b 100644 --- a/mobile/lib/ui/viewer/file_details/location_tags_widget.dart +++ b/mobile/lib/ui/viewer/file_details/location_tags_widget.dart @@ -347,7 +347,7 @@ class _InfoMapState extends State { .push( MaterialPageRoute( builder: (context) => MapScreen( - filesFutureFn: SearchService.instance.getAllFiles, + filesFutureFn: SearchService.instance.getAllFilesForSearch, center: LatLng( _fileLat, _fileLng, diff --git a/mobile/lib/ui/viewer/gallery/collection_page.dart b/mobile/lib/ui/viewer/gallery/collection_page.dart index fdfa8494f3..b4f1a12c82 100644 --- a/mobile/lib/ui/viewer/gallery/collection_page.dart +++ b/mobile/lib/ui/viewer/gallery/collection_page.dart @@ -9,6 +9,8 @@ import 'package:photos/models/collection/collection_items.dart'; import 'package:photos/models/file/file.dart'; import 'package:photos/models/file_load_result.dart'; import 'package:photos/models/gallery_type.dart'; +import "package:photos/models/search/hierarchical/album_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; import 'package:photos/models/selected_files.dart'; import 'package:photos/services/ignored_files_service.dart'; import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.dart'; @@ -17,7 +19,10 @@ import "package:photos/ui/viewer/gallery/empty_album_state.dart"; import 'package:photos/ui/viewer/gallery/empty_state.dart'; import 'package:photos/ui/viewer/gallery/gallery.dart'; import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart'; +import "package:photos/ui/viewer/gallery/hierarchical_search_gallery.dart"; import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; import "package:photos/ui/viewer/gallery/state/selection_state.dart"; class CollectionPage extends StatelessWidget { @@ -99,36 +104,62 @@ class CollectionPage extends StatelessWidget { ? const SizedBox(height: 20) : const SizedBox(height: 212), ); + return GalleryFilesState( - child: Scaffold( - appBar: PreferredSize( - preferredSize: const Size.fromHeight(50.0), - child: GalleryAppBarWidget( - galleryType, - c.collection.displayName, - _selectedFiles, - collection: c.collection, - isFromCollectPhotos: isFromCollectPhotos, + child: InheritedSearchFilterDataWrapper( + searchFilterDataProvider: SearchFilterDataProvider( + initialGalleryFilter: AlbumFilter( + collectionID: c.collection.id, + albumName: c.collection.displayName, + occurrence: kMostRelevantFilter, ), ), - bottomNavigationBar: isFromCollectPhotos - ? CollectPhotosBottomButtons( - c.collection, - selectedFiles: _selectedFiles, - ) - : const SizedBox.shrink(), - body: SelectionState( - selectedFiles: _selectedFiles, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - gallery, - FileSelectionOverlayBar( - galleryType, - _selectedFiles, - collection: c.collection, - ), - ], + child: Scaffold( + appBar: PreferredSize( + preferredSize: const Size.fromHeight(90.0), + child: GalleryAppBarWidget( + galleryType, + c.collection.displayName, + _selectedFiles, + collection: c.collection, + isFromCollectPhotos: isFromCollectPhotos, + ), + ), + bottomNavigationBar: isFromCollectPhotos + ? CollectPhotosBottomButtons( + c.collection, + selectedFiles: _selectedFiles, + ) + : const SizedBox.shrink(), + body: SelectionState( + selectedFiles: _selectedFiles, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Builder( + builder: (context) { + return ValueListenableBuilder( + valueListenable: InheritedSearchFilterData.of(context) + .searchFilterDataProvider! + .isSearchingNotifier, + builder: (context, value, _) { + return value + ? HierarchicalSearchGallery( + tagPrefix: tagPrefix, + selectedFiles: _selectedFiles, + ) + : gallery; + }, + ); + }, + ), + FileSelectionOverlayBar( + galleryType, + _selectedFiles, + collection: c.collection, + ), + ], + ), ), ), ), diff --git a/mobile/lib/ui/viewer/gallery/gallery.dart b/mobile/lib/ui/viewer/gallery/gallery.dart index c9c0f35a4b..1788866697 100644 --- a/mobile/lib/ui/viewer/gallery/gallery.dart +++ b/mobile/lib/ui/viewer/gallery/gallery.dart @@ -17,7 +17,9 @@ import "package:photos/ui/viewer/gallery/component/multiple_groups_gallery_view. import 'package:photos/ui/viewer/gallery/empty_state.dart'; import "package:photos/ui/viewer/gallery/state/gallery_context_state.dart"; import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; import "package:photos/utils/debouncer.dart"; +import "package:photos/utils/hierarchical_search_util.dart"; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; typedef GalleryLoader = Future Function( @@ -110,7 +112,7 @@ class GalleryState extends State { final _forceReloadEventSubscriptions = >[]; late String _logTag; bool _sortOrderAsc = false; - List _allFiles = []; + List _allGalleryFiles = []; @override void initState() { @@ -189,36 +191,10 @@ class GalleryState extends State { } } - Future _loadFiles({int? limit}) async { - _logger.info("Loading ${limit ?? "all"} files"); - try { - final startTime = DateTime.now().microsecondsSinceEpoch; - final result = await widget.asyncLoader( - galleryLoadStartTime, - galleryLoadEndTime, - limit: limit, - asc: _sortOrderAsc, - ); - final endTime = DateTime.now().microsecondsSinceEpoch; - final duration = Duration(microseconds: endTime - startTime); - _logger.info( - "Time taken to load " + - result.files.length.toString() + - " files :" + - duration.inMilliseconds.toString() + - "ms", - ); - return result; - } catch (e, s) { - _logger.severe("failed to load files", e, s); - rethrow; - } - } - // group files into multiple groups and returns `true` if it resulted in a // gallery reload bool _onFilesLoaded(List files) { - _allFiles = files; + _allGalleryFiles = files; final updatedGroupedFiles = widget.enableFileGrouping && widget.groupType.timeGrouping() @@ -239,6 +215,46 @@ class GalleryState extends State { } } + Future _loadFiles({int? limit}) async { + _logger.info("Loading ${limit ?? "all"} files"); + try { + final startTime = DateTime.now().microsecondsSinceEpoch; + final result = await widget.asyncLoader( + galleryLoadStartTime, + galleryLoadEndTime, + limit: limit, + asc: _sortOrderAsc, + ); + final endTime = DateTime.now().microsecondsSinceEpoch; + final duration = Duration(microseconds: endTime - startTime); + _logger.info( + "Time taken to load " + + result.files.length.toString() + + " files :" + + duration.inMilliseconds.toString() + + "ms", + ); + + /// To curate filters when a gallery is first opened. + if (!result.hasMore) { + final searchFilterDataProvider = + InheritedSearchFilterData.maybeOf(context) + ?.searchFilterDataProvider; + if (searchFilterDataProvider != null && + !searchFilterDataProvider.isSearchingNotifier.value) { + unawaited( + curateFilters(searchFilterDataProvider, result.files, context), + ); + } + } + + return result; + } catch (e, s) { + _logger.severe("failed to load files", e, s); + rethrow; + } + } + @override void dispose() { _reloadEventSubscription?.cancel(); @@ -253,7 +269,7 @@ class GalleryState extends State { @override Widget build(BuildContext context) { _logger.finest("Building Gallery ${widget.tagPrefix}"); - GalleryFilesState.of(context).setGalleryFiles = _allFiles; + GalleryFilesState.of(context).setGalleryFiles = _allGalleryFiles; if (!_hasLoadedFiles) { return widget.loadingWidget; } diff --git a/mobile/lib/ui/viewer/gallery/gallery_app_bar_widget.dart b/mobile/lib/ui/viewer/gallery/gallery_app_bar_widget.dart index 8f4f3771a6..5672fcc5c1 100644 --- a/mobile/lib/ui/viewer/gallery/gallery_app_bar_widget.dart +++ b/mobile/lib/ui/viewer/gallery/gallery_app_bar_widget.dart @@ -7,6 +7,7 @@ import "package:flutter/foundation.dart"; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:photos/core/configuration.dart'; +import "package:photos/core/constants.dart"; import 'package:photos/core/event_bus.dart'; import "package:photos/core/network/network.dart"; import "package:photos/db/files_db.dart"; @@ -24,6 +25,8 @@ import 'package:photos/models/selected_files.dart'; import 'package:photos/service_locator.dart'; import 'package:photos/services/collections_service.dart'; import 'package:photos/services/sync_service.dart'; +import "package:photos/states/location_screen_state.dart"; +import "package:photos/theme/colors.dart"; import 'package:photos/ui/actions/collection/collection_sharing_actions.dart'; import "package:photos/ui/cast/auto.dart"; import "package:photos/ui/cast/choose.dart"; @@ -39,6 +42,10 @@ import 'package:photos/ui/sharing/share_collection_page.dart'; import 'package:photos/ui/tools/free_space_page.dart'; import "package:photos/ui/viewer/gallery/hooks/add_photos_sheet.dart"; import 'package:photos/ui/viewer/gallery/hooks/pick_cover_photo.dart'; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/hierarchicial_search/applied_filters_for_appbar.dart"; +import "package:photos/ui/viewer/hierarchicial_search/recommended_filters_for_appbar.dart"; +import "package:photos/ui/viewer/location/edit_location_sheet.dart"; import 'package:photos/utils/data_util.dart'; import 'package:photos/utils/dialog_util.dart'; import 'package:photos/utils/magic_util.dart'; @@ -85,7 +92,9 @@ enum AlbumPopupAction { removeLink, cleanUncategorized, sortByMostRecent, - sortByMostRelevant + sortByMostRelevant, + editLocation, + deleteLocation, } class _GalleryAppBarWidgetState extends State { @@ -124,22 +133,61 @@ class _GalleryAppBarWidgetState extends State { @override Widget build(BuildContext context) { + final inheritedSearchFilterData = + InheritedSearchFilterData.maybeOf(context); + final isHierarchicalSearchable = + inheritedSearchFilterData?.isHierarchicalSearchable ?? false; return galleryType == GalleryType.homepage ? const SizedBox.shrink() - : AppBar( - elevation: 0, - centerTitle: false, - title: Text( - _appBarTitle!, - style: Theme.of(context) - .textTheme - .headlineSmall! - .copyWith(fontSize: 16), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - actions: _getDefaultActions(context), - ); + : isHierarchicalSearchable + ? ValueListenableBuilder( + valueListenable: inheritedSearchFilterData! + .searchFilterDataProvider!.isSearchingNotifier, + child: const PreferredSize( + preferredSize: Size.fromHeight(0), + child: Flexible(child: RecommendedFiltersForAppbar()), + ), + builder: (context, isSearching, child) { + return AppBar( + elevation: 0, + centerTitle: false, + title: isSearching + ? const SizedBox( + // +1 to account for the filter's outer stroke width + height: kFilterChipHeight + 1, + child: AppliedFiltersForAppbar(), + ) + : Text( + _appBarTitle!, + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 16), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + actions: isSearching ? null : _getDefaultActions(context), + bottom: child as PreferredSizeWidget, + surfaceTintColor: Colors.transparent, + scrolledUnderElevation: 4, + shadowColor: Colors.black.withOpacity(0.15), + ); + }, + ) + : AppBar( + elevation: 0, + centerTitle: false, + title: Text( + _appBarTitle!, + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 16), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + actions: _getDefaultActions(context), + ); } Future _renameAlbum(BuildContext context) async { @@ -428,6 +476,20 @@ class _GalleryAppBarWidgetState extends State { child: const Icon(CupertinoIcons.pin), ), ), + if (galleryType == GalleryType.locationTag) + EntePopupMenuItem( + S.of(context).editLocation, + value: AlbumPopupAction.editLocation, + icon: Icons.edit_outlined, + ), + if (galleryType == GalleryType.locationTag) + EntePopupMenuItem( + S.of(context).deleteLocation, + value: AlbumPopupAction.deleteLocation, + icon: Icons.delete_outline, + iconColor: warning500, + labelColor: warning500, + ), ]); final bool isArchived = widget.collection?.isArchived() ?? false; final bool isHidden = widget.collection?.isHidden() ?? false; @@ -547,6 +609,10 @@ class _GalleryAppBarWidgetState extends State { await showOnMap(); } else if (value == AlbumPopupAction.cleanUncategorized) { await onCleanUncategorizedClick(context); + } else if (value == AlbumPopupAction.editLocation) { + editLocation(); + } else if (value == AlbumPopupAction.deleteLocation) { + await deleteLocation(); } else { showToast(context, S.of(context).somethingWentWrong); } @@ -558,6 +624,24 @@ class _GalleryAppBarWidgetState extends State { return actions; } + void editLocation() { + showEditLocationSheet( + context, + InheritedLocationScreenState.of(context).locationTagEntity, + ); + } + + Future deleteLocation() async { + try { + await locationService.deleteLocationTag( + InheritedLocationScreenState.of(context).locationTagEntity.id, + ); + Navigator.of(context).pop(); + } catch (e) { + await showGenericErrorDialog(context: context, error: e); + } + } + Future onCleanUncategorizedClick(BuildContext buildContext) async { final actionResult = await showChoiceActionSheet( context, diff --git a/mobile/lib/ui/viewer/gallery/hierarchical_search_gallery.dart b/mobile/lib/ui/viewer/gallery/hierarchical_search_gallery.dart new file mode 100644 index 0000000000..106130af98 --- /dev/null +++ b/mobile/lib/ui/viewer/gallery/hierarchical_search_gallery.dart @@ -0,0 +1,220 @@ +import "dart:async"; +import "package:flutter/material.dart"; +import "package:logging/logging.dart"; +import "package:photos/core/event_bus.dart"; +import "package:photos/events/files_updated_event.dart"; +import "package:photos/events/local_photos_updated_event.dart"; +import "package:photos/generated/l10n.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/file_load_result.dart"; +import "package:photos/models/ml/face/person.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/selected_files.dart"; +import "package:photos/ui/common/loading_widget.dart"; +import "package:photos/ui/viewer/gallery/gallery.dart"; +import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; +import "package:photos/ui/viewer/people/add_person_action_sheet.dart"; +import "package:photos/ui/viewer/people/people_banner.dart"; +import "package:photos/ui/viewer/people/people_page.dart"; +import "package:photos/ui/viewer/search/result/person_face_widget.dart"; +import "package:photos/utils/hierarchical_search_util.dart"; +import "package:photos/utils/navigation_util.dart"; + +class HierarchicalSearchGallery extends StatefulWidget { + final String tagPrefix; + final SelectedFiles? selectedFiles; + const HierarchicalSearchGallery({ + required this.tagPrefix, + this.selectedFiles, + super.key, + }); + + @override + State createState() => + _HierarchicalSearchGalleryState(); +} + +class _HierarchicalSearchGalleryState extends State { + final _logger = Logger("HierarchicalSearchGallery"); + StreamSubscription? _filesUpdatedEvent; + late SearchFilterDataProvider? _searchFilterDataProvider; + List _filterdFiles = []; + int _filteredFilesVersion = 0; + final _isLoading = ValueNotifier(true); + FaceFilter? _firstUnnamedAppliedFaceFilter; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + try { + if (_filesUpdatedEvent != null) { + _filesUpdatedEvent!.cancel(); + } + _filesUpdatedEvent = + Bus.instance.on().listen((event) { + if (event.type == EventType.deletedFromDevice || + event.type == EventType.deletedFromEverywhere || + event.type == EventType.deletedFromRemote || + event.type == EventType.hide) { + for (var updatedFile in event.updatedFiles) { + _filterdFiles.remove(updatedFile); + GalleryFilesState.of(context).galleryFiles.remove(updatedFile); + } + setState(() {}); + } + }); + + _searchFilterDataProvider = + InheritedSearchFilterData.of(context).searchFilterDataProvider; + assert(_searchFilterDataProvider != null); + + _searchFilterDataProvider! + .removeListener(fromApplied: true, listener: _onFiltersUpdated); + _searchFilterDataProvider! + .addListener(toApplied: true, listener: _onFiltersUpdated); + + _onFiltersUpdated(); + } catch (e) { + _logger.severe('Something went wrong: $e'); + } + }); + } + + void _onFiltersUpdated() async { + final filters = _searchFilterDataProvider!.appliedFilters; + if (filters.isEmpty) { + Navigator.of(context).pop(); + return; + } + + _isLoading.value = true; + final filterdFiles = await getFilteredFiles(filters); + + _setFilteredFiles(filterdFiles); + await curateFilters(_searchFilterDataProvider!, filterdFiles, context); + _setUnnamedFaceFilter(filters); + + _isLoading.value = false; + } + + void _setUnnamedFaceFilter(List filters) { + for (HierarchicalSearchFilter filter in filters) { + if (filter is FaceFilter && filter.clusterId != null) { + if (filters.last == filter) { + _firstUnnamedAppliedFaceFilter = filter; + } + break; + } + _firstUnnamedAppliedFaceFilter = null; + } + } + + void _setFilteredFiles(List files) { + _filterdFiles = files; + GalleryFilesState.of(context).setGalleryFiles = files; + _filteredFilesVersion++; + } + + @override + void dispose() { + _filesUpdatedEvent?.cancel(); + _isLoading.dispose(); + if (_searchFilterDataProvider != null) { + _searchFilterDataProvider! + .removeListener(fromApplied: true, listener: _onFiltersUpdated); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return ValueListenableBuilder( + valueListenable: _isLoading, + builder: (context, isLoading, _) { + return AnimatedSwitcher( + duration: const Duration(milliseconds: 500), + switchInCurve: Curves.easeInOutExpo, + switchOutCurve: Curves.easeInOutExpo, + child: isLoading + ? const EnteLoadingWidget() + : Gallery( + key: ValueKey(_filteredFilesVersion), + asyncLoader: ( + creationStartTime, + creationEndTime, { + limit, + asc, + }) async { + final files = _filterdFiles + .where( + (file) => + file.creationTime! >= creationStartTime && + file.creationTime! <= creationEndTime, + ) + .toList(); + return FileLoadResult(files, false); + }, + tagPrefix: widget.tagPrefix, + reloadEvent: Bus.instance.on(), + removalEventTypes: const { + EventType.deletedFromRemote, + EventType.deletedFromEverywhere, + EventType.hide, + }, + selectedFiles: widget.selectedFiles, + header: _firstUnnamedAppliedFaceFilter != null + ? PeopleBanner( + type: PeopleBannerType.addName, + faceWidget: PersonFaceWidget( + _firstUnnamedAppliedFaceFilter!.faceFile, + clusterID: + _firstUnnamedAppliedFaceFilter!.clusterId, + thumbnailFallback: false, + ), + actionIcon: Icons.add_outlined, + text: S.of(context).addAName, + subText: S.of(context).findPeopleByName, + onTap: () async { + final result = await showAssignPersonAction( + context, + clusterID: + _firstUnnamedAppliedFaceFilter!.clusterId!, + ); + if (result != null && + result is (PersonEntity, EnteFile)) { + Navigator.of(context).pop(); + unawaited( + routeToPage( + context, + PeoplePage( + person: result.$1, + searchResult: null, + ), + ), + ); + } else if (result != null && + result is PersonEntity) { + Navigator.of(context).pop(); + unawaited( + routeToPage( + context, + PeoplePage( + person: result, + searchResult: null, + ), + ), + ); + } + }, + ) + : null, + ), + ); + }, + ); + } +} diff --git a/mobile/lib/ui/viewer/gallery/large_files_page.dart b/mobile/lib/ui/viewer/gallery/large_files_page.dart index 057adb222b..a935d2a2c8 100644 --- a/mobile/lib/ui/viewer/gallery/large_files_page.dart +++ b/mobile/lib/ui/viewer/gallery/large_files_page.dart @@ -35,7 +35,7 @@ class LargeFilesPagePage extends StatelessWidget { final gallery = Gallery( asyncLoader: (creationStartTime, creationEndTime, {limit, asc}) async { final List allFiles = - await SearchService.instance.getAllFiles(); + await SearchService.instance.getAllFilesForSearch(); final Set alreadyTracked = {}; final filesWithSize = []; diff --git a/mobile/lib/ui/viewer/gallery/state/gallery_files_inherited_widget.dart b/mobile/lib/ui/viewer/gallery/state/gallery_files_inherited_widget.dart index 27ae8943b7..bd07d93309 100644 --- a/mobile/lib/ui/viewer/gallery/state/gallery_files_inherited_widget.dart +++ b/mobile/lib/ui/viewer/gallery/state/gallery_files_inherited_widget.dart @@ -18,6 +18,10 @@ class GalleryFilesState extends InheritedWidget { _galleryFiles = galleryFiles; } + void removeFile(EnteFile file) { + _galleryFiles!.remove(file); + } + List get galleryFiles { if (_galleryFiles == null) { throw Exception( diff --git a/mobile/lib/ui/viewer/gallery/state/inherited_search_filter_data.dart b/mobile/lib/ui/viewer/gallery/state/inherited_search_filter_data.dart new file mode 100644 index 0000000000..ff0cd40a7a --- /dev/null +++ b/mobile/lib/ui/viewer/gallery/state/inherited_search_filter_data.dart @@ -0,0 +1,64 @@ +import "package:flutter/material.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; + +class InheritedSearchFilterDataWrapper extends StatefulWidget { + const InheritedSearchFilterDataWrapper({ + super.key, + required this.child, + required this.searchFilterDataProvider, + }); + + final Widget child; + final SearchFilterDataProvider? searchFilterDataProvider; + + @override + State createState() => + _InheritedSearchFilterDataWrapperState(); +} + +class _InheritedSearchFilterDataWrapperState + extends State { + @override + void dispose() { + widget.searchFilterDataProvider?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return InheritedSearchFilterData( + searchFilterDataProvider: widget.searchFilterDataProvider, + child: widget.child, + ); + } +} + +/// Use [InheritedSearchFilterDataWrapper] instead if using +/// [InheritedSearchFilterData] as a parent widget +class InheritedSearchFilterData extends InheritedWidget { + const InheritedSearchFilterData({ + super.key, + required this.searchFilterDataProvider, + required super.child, + }); + + /// Pass null if gallery doesn't need hierarchical search + final SearchFilterDataProvider? searchFilterDataProvider; + + bool get isHierarchicalSearchable => searchFilterDataProvider != null; + + static InheritedSearchFilterData? maybeOf(BuildContext context) { + return context + .dependOnInheritedWidgetOfExactType(); + } + + static InheritedSearchFilterData of(BuildContext context) { + final InheritedSearchFilterData? result = maybeOf(context); + assert(result != null, 'No InheritedSearchFilterData found in context'); + return result!; + } + + @override + bool updateShouldNotify(InheritedSearchFilterData oldWidget) => + searchFilterDataProvider != oldWidget.searchFilterDataProvider; +} diff --git a/mobile/lib/ui/viewer/gallery/state/search_filter_data_provider.dart b/mobile/lib/ui/viewer/gallery/state/search_filter_data_provider.dart new file mode 100644 index 0000000000..995b2fde0c --- /dev/null +++ b/mobile/lib/ui/viewer/gallery/state/search_filter_data_provider.dart @@ -0,0 +1,181 @@ +import "package:flutter/material.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/hierarchical/only_them_filter.dart"; + +class SearchFilterDataProvider { + final _appliedFiltersNotifier = _AppliedFiltersNotifier(); + + /// [_recommededFiltersNotifier.value] are filters sorted by decreasing + /// order of relevance + final _recommendedFiltersNotifier = _RecommendedFiltersNotifier(); + final isSearchingNotifier = ValueNotifier(false); + HierarchicalSearchFilter initialGalleryFilter; + + SearchFilterDataProvider({required this.initialGalleryFilter}); + + /// [recommendations] are sorted by decreasing order of relevance + List get recommendations => + _recommendedFiltersNotifier.recommendedFilters; + List get appliedFilters => + _appliedFiltersNotifier.appliedFilters; + + void clearAndAddRecommendations(List filters) { + _recommendedFiltersNotifier.clearFilters(); + _safelyAddToRecommended(filters); + } + + void applyFilters(List filters) { + _recommendedFiltersNotifier.removeFilters(filters); + + late final List allFiltersToAdd; + if (!isSearchingNotifier.value) { + isSearchingNotifier.value = true; + allFiltersToAdd = [initialGalleryFilter, ...filters]; + } else { + allFiltersToAdd = filters; + } + + for (HierarchicalSearchFilter filter in allFiltersToAdd) { + filter.isApplied = true; + } + _appliedFiltersNotifier.addFilters(allFiltersToAdd); + + if (filters.any((e) => e is OnlyThemFilter)) { + _appliedFiltersNotifier.removeAllFaceFilters(); + } + } + + void removeAppliedFilters(List filters) { + _appliedFiltersNotifier.removeFilters(filters); + for (HierarchicalSearchFilter filter in filters) { + filter.isApplied = false; + } + _safelyAddToRecommended(filters); + } + + void addListener({ + bool toApplied = false, + bool toRecommended = false, + required VoidCallback listener, + }) { + assert( + toApplied != false || toRecommended != false, + "Listener not added to any notifier", + ); + if (toApplied) { + _appliedFiltersNotifier.addListener(listener); + } else if (toRecommended) { + _recommendedFiltersNotifier.addListener(listener); + } + } + + void removeListener({ + bool fromApplied = false, + bool fromRecommended = false, + required VoidCallback listener, + }) { + assert( + fromApplied != false || fromRecommended != false, + "Listener not removed from any notifier", + ); + if (fromApplied) { + _appliedFiltersNotifier.removeListener(listener); + } else if (fromRecommended) { + _recommendedFiltersNotifier.removeListener(listener); + } + } + + void _safelyAddToRecommended(List filters) { + if (_appliedFiltersNotifier.appliedFilters + .any((e) => e is OnlyThemFilter)) { + filters.removeWhere((e) => e is FaceFilter); + } + + filters.sort((a, b) => b.relevance().compareTo(a.relevance())); + + final List filtersToAvoid = [ + ...appliedFilters, + ...recommendations, + ]; + + if (appliedFilters.isEmpty) { + filtersToAvoid.add(initialGalleryFilter); + } + + _recommendedFiltersNotifier.addFilters( + filters, + filtersToAvoid: filtersToAvoid, + ); + } + + /// [InheritedSearchFilterDataWrapper] calls this method in its [dispose] so + /// if [InheritedSearchFilterDataWrapper] is an ancestor on the widget where + /// [SearchFilterDataProvider] is used, it's not necessary to call this method + /// explicitly + void dispose() { + _appliedFiltersNotifier.dispose(); + _recommendedFiltersNotifier.dispose(); + isSearchingNotifier.dispose(); + } +} + +class _AppliedFiltersNotifier extends ChangeNotifier { + final List _appliedFilters = []; + + List get appliedFilters => _appliedFilters; + + void addFilters(List filters) { + _appliedFilters.addAll(filters); + notifyListeners(); + } + + void removeFilters(List filters) { + _appliedFilters.removeWhere((filter) => filters.contains(filter)); + notifyListeners(); + } + + void removeAllFaceFilters() { + _appliedFilters.removeWhere((element) => element is FaceFilter); + notifyListeners(); + } +} + +class _RecommendedFiltersNotifier extends ChangeNotifier { + final List _recommendedFilters = []; + + List get recommendedFilters => _recommendedFilters; + + void addFilters( + List filters, { + ///This is to ensure that the filters that are being added are not already + ///already in recommendations or applied filters + required List filtersToAvoid, + }) { + for (HierarchicalSearchFilter filter in filters) { + bool avoidFilter = false; + for (HierarchicalSearchFilter filterToAvoid in filtersToAvoid) { + if (filter.isSameFilter(filterToAvoid)) { + avoidFilter = true; + break; + } + } + if (avoidFilter) { + continue; + } + _recommendedFilters.add(filter); + } + + notifyListeners(); + } + + void removeFilters(List filters) { + _recommendedFilters.removeWhere((filter) => filters.contains(filter)); + notifyListeners(); + } + + void clearFilters() { + _recommendedFilters.clear(); + notifyListeners(); + } +} diff --git a/mobile/lib/ui/viewer/gallery/uncategorized_page.dart b/mobile/lib/ui/viewer/gallery/uncategorized_page.dart index b2faeab9f8..a6dbffcbf1 100644 --- a/mobile/lib/ui/viewer/gallery/uncategorized_page.dart +++ b/mobile/lib/ui/viewer/gallery/uncategorized_page.dart @@ -8,12 +8,17 @@ import "package:photos/generated/l10n.dart"; import 'package:photos/models/collection/collection.dart'; import 'package:photos/models/file_load_result.dart'; import 'package:photos/models/gallery_type.dart'; +import "package:photos/models/search/hierarchical/album_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; import 'package:photos/models/selected_files.dart'; import 'package:photos/services/ignored_files_service.dart'; import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.dart'; import 'package:photos/ui/viewer/gallery/gallery.dart'; import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart'; +import "package:photos/ui/viewer/gallery/hierarchical_search_gallery.dart"; import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; import "package:photos/ui/viewer/gallery/state/selection_state.dart"; class UnCategorizedPage extends StatelessWidget { @@ -75,27 +80,52 @@ class UnCategorizedPage extends StatelessWidget { albumName: S.of(context).uncategorized, ); return GalleryFilesState( - child: Scaffold( - appBar: PreferredSize( - preferredSize: const Size.fromHeight(50.0), - child: GalleryAppBarWidget( - appBarType, - S.of(context).uncategorized, - _selectedFiles, - collection: collection, + child: InheritedSearchFilterDataWrapper( + searchFilterDataProvider: SearchFilterDataProvider( + initialGalleryFilter: AlbumFilter( + collectionID: collection.id, + albumName: collection.displayName, + occurrence: kMostRelevantFilter, ), ), - body: SelectionState( - selectedFiles: _selectedFiles, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - gallery, - FileSelectionOverlayBar( - overlayType, - _selectedFiles, - ), - ], + child: Scaffold( + appBar: PreferredSize( + preferredSize: const Size.fromHeight(90.0), + child: GalleryAppBarWidget( + appBarType, + S.of(context).uncategorized, + _selectedFiles, + collection: collection, + ), + ), + body: SelectionState( + selectedFiles: _selectedFiles, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Builder( + builder: (context) { + return ValueListenableBuilder( + valueListenable: InheritedSearchFilterData.of(context) + .searchFilterDataProvider! + .isSearchingNotifier, + builder: (context, isSearching, _) { + return isSearching + ? HierarchicalSearchGallery( + tagPrefix: tagPrefix, + selectedFiles: _selectedFiles, + ) + : gallery; + }, + ); + }, + ), + FileSelectionOverlayBar( + overlayType, + _selectedFiles, + ), + ], + ), ), ), ), diff --git a/mobile/lib/ui/viewer/hierarchicial_search/applied_filters_for_appbar.dart b/mobile/lib/ui/viewer/hierarchicial_search/applied_filters_for_appbar.dart new file mode 100644 index 0000000000..bc41ed77af --- /dev/null +++ b/mobile/lib/ui/viewer/hierarchicial_search/applied_filters_for_appbar.dart @@ -0,0 +1,131 @@ +import "package:flutter/material.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/hierarchical/only_them_filter.dart"; +import "package:photos/theme/ente_theme.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; +import "package:photos/ui/viewer/hierarchicial_search/chip_widgets/face_filter_chip.dart"; +import "package:photos/ui/viewer/hierarchicial_search/chip_widgets/generic_filter_chip.dart"; +import "package:photos/ui/viewer/hierarchicial_search/chip_widgets/only_them_filter_chip.dart"; + +class AppliedFiltersForAppbar extends StatefulWidget { + const AppliedFiltersForAppbar({super.key}); + + @override + State createState() => + _AppliedFiltersForAppbarState(); +} + +class _AppliedFiltersForAppbarState extends State { + late SearchFilterDataProvider _searchFilterDataProvider; + late List _appliedFilters; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + final inheritedSearchFilterData = InheritedSearchFilterData.of(context); + assert( + inheritedSearchFilterData.isHierarchicalSearchable, + "Do not use this widget if gallery is not hierarchical searchable", + ); + _searchFilterDataProvider = + inheritedSearchFilterData.searchFilterDataProvider!; + _appliedFilters = _searchFilterDataProvider.appliedFilters; + + _searchFilterDataProvider.removeListener( + fromApplied: true, + listener: onAppliedFiltersUpdate, + ); + _searchFilterDataProvider.addListener( + toApplied: true, + listener: onAppliedFiltersUpdate, + ); + } + + @override + void dispose() { + _searchFilterDataProvider.removeListener( + fromApplied: true, + listener: onAppliedFiltersUpdate, + ); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Stack( + alignment: Alignment.centerLeft, + children: [ + ListView.builder( + itemBuilder: (context, index) { + final filter = _appliedFilters[index]; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: filter is FaceFilter + ? FaceFilterChip( + personId: filter.personId, + clusterId: filter.clusterId, + faceThumbnailFile: filter.faceFile, + apply: () { + _searchFilterDataProvider.applyFilters([filter]); + }, + remove: () { + _searchFilterDataProvider + .removeAppliedFilters([filter]); + }, + isApplied: filter.isApplied, + ) + : filter is OnlyThemFilter + ? OnlyThemFilterChip( + faceFilters: filter.faceFilters, + apply: () { + _searchFilterDataProvider.applyFilters([filter]); + }, + remove: () { + _searchFilterDataProvider + .removeAppliedFilters([filter]); + }, + isApplied: filter.isApplied, + ) + : GenericFilterChip( + label: filter.name(), + apply: () { + _searchFilterDataProvider.applyFilters([filter]); + }, + remove: () { + _searchFilterDataProvider + .removeAppliedFilters([filter]); + }, + leadingIcon: filter.icon(), + isApplied: filter.isApplied, + ), + ); + }, + scrollDirection: Axis.horizontal, + itemCount: _appliedFilters.length, + padding: const EdgeInsets.symmetric(horizontal: 4), + ), + Container( + width: 12, + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + getEnteColorScheme(context).backdropBase, + getEnteColorScheme(context).backdropBase.withOpacity(0), + ], + begin: Alignment.centerLeft, + end: Alignment.centerRight, + ), + ), + ), + ], + ); + } + + void onAppliedFiltersUpdate() { + setState(() { + _appliedFilters = _searchFilterDataProvider.appliedFilters; + }); + } +} diff --git a/mobile/lib/ui/viewer/hierarchicial_search/chip_widgets/face_filter_chip.dart b/mobile/lib/ui/viewer/hierarchicial_search/chip_widgets/face_filter_chip.dart new file mode 100644 index 0000000000..20fda3f9c5 --- /dev/null +++ b/mobile/lib/ui/viewer/hierarchicial_search/chip_widgets/face_filter_chip.dart @@ -0,0 +1,127 @@ +import "package:flutter/material.dart"; +import "package:photos/core/constants.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/theme/ente_theme.dart"; +import "package:photos/ui/viewer/search/result/person_face_widget.dart"; + +class FaceFilterChip extends StatefulWidget { + final String? personId; + final String? clusterId; + final EnteFile faceThumbnailFile; + final VoidCallback apply; + final VoidCallback remove; + final bool isApplied; + final bool isInAllFiltersView; + + const FaceFilterChip({ + required this.personId, + required this.clusterId, + required this.faceThumbnailFile, + required this.apply, + required this.remove, + required this.isApplied, + this.isInAllFiltersView = false, + super.key, + }); + + @override + State createState() => _FaceFilterChipState(); +} + +class _FaceFilterChipState extends State { + double scale = 1.0; + + @override + void initState() { + super.initState(); + if (widget.isInAllFiltersView) { + scale = 1.75; + } + } + + @override + Widget build(BuildContext context) { + return Stack( + clipBehavior: Clip.none, + children: [ + GestureDetector( + onTap: () { + if (widget.isApplied) { + widget.remove(); + } else { + widget.apply(); + } + }, + child: Container( + decoration: BoxDecoration( + color: getEnteColorScheme(context).fillFaint, + borderRadius: BorderRadius.all( + Radius.circular(kFilterChipHeight * scale / 2), + ), + border: Border.all( + color: getEnteColorScheme(context).strokeFaint, + width: widget.isInAllFiltersView ? 1 : 0.5, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ClipOval( + child: SizedBox( + width: kFilterChipHeight * scale, + height: kFilterChipHeight * scale, + child: PersonFaceWidget( + widget.faceThumbnailFile, + personId: widget.personId, + clusterID: widget.clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + ), + widget.isApplied && !widget.isInAllFiltersView + ? const SizedBox(width: 4) + : const SizedBox.shrink(), + widget.isApplied && !widget.isInAllFiltersView + ? Icon( + Icons.close_rounded, + size: 16, + color: getEnteColorScheme(context).textMuted, + ) + : const SizedBox.shrink(), + widget.isApplied && !widget.isInAllFiltersView + ? const SizedBox(width: 8) + : const SizedBox.shrink(), + ], + ), + ), + ), + widget.isApplied && widget.isInAllFiltersView + ? Positioned( + top: -4, + right: -4, + child: Container( + padding: const EdgeInsets.all(1), + decoration: BoxDecoration( + color: getEnteColorScheme(context).backgroundElevated2, + border: Border.all( + color: getEnteColorScheme(context).strokeMuted, + width: 0.5, + ), + borderRadius: BorderRadius.all( + Radius.circular(8 * scale), + ), + ), + child: Icon( + Icons.close_rounded, + size: 14, + color: getEnteColorScheme(context).textMuted, + ), + ), + ) + : const SizedBox.shrink(), + ], + ); + } +} diff --git a/mobile/lib/ui/viewer/hierarchicial_search/chip_widgets/generic_filter_chip.dart b/mobile/lib/ui/viewer/hierarchicial_search/chip_widgets/generic_filter_chip.dart new file mode 100644 index 0000000000..2b54476f73 --- /dev/null +++ b/mobile/lib/ui/viewer/hierarchicial_search/chip_widgets/generic_filter_chip.dart @@ -0,0 +1,88 @@ +import "package:flutter/material.dart"; +import "package:photos/core/constants.dart"; +import "package:photos/theme/ente_theme.dart"; + +class GenericFilterChip extends StatefulWidget { + final String label; + final IconData? leadingIcon; + final VoidCallback apply; + final VoidCallback remove; + final bool isApplied; + final bool isInAllFiltersView; + + const GenericFilterChip({ + required this.label, + required this.apply, + required this.remove, + required this.isApplied, + this.leadingIcon, + this.isInAllFiltersView = false, + super.key, + }); + + @override + State createState() => _GenericFilterChipState(); +} + +class _GenericFilterChipState extends State { + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + if (widget.isApplied) { + widget.remove(); + } else { + widget.apply(); + } + }, + child: SizedBox( + // +1 to account for the filter's outer stroke width + height: kFilterChipHeight + 1, + child: Container( + decoration: BoxDecoration( + color: getEnteColorScheme(context).fillFaint, + borderRadius: const BorderRadius.all( + Radius.circular(kFilterChipHeight / 2), + ), + border: Border.all( + color: getEnteColorScheme(context).strokeFaint, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + widget.leadingIcon != null + ? Icon( + widget.leadingIcon, + size: 16, + ) + : const SizedBox.shrink(), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Text( + widget.label, + style: getEnteTextTheme(context).miniBold, + ), + ), + widget.isApplied + ? const SizedBox(width: 2) + : const SizedBox.shrink(), + widget.isApplied + ? Icon( + Icons.close_rounded, + size: 16, + color: getEnteColorScheme(context).textMuted, + ) + : const SizedBox.shrink(), + ], + ), + ), + ), + ), + ); + } +} diff --git a/mobile/lib/ui/viewer/hierarchicial_search/chip_widgets/only_them_filter_chip.dart b/mobile/lib/ui/viewer/hierarchicial_search/chip_widgets/only_them_filter_chip.dart new file mode 100644 index 0000000000..ce0d9efa5c --- /dev/null +++ b/mobile/lib/ui/viewer/hierarchicial_search/chip_widgets/only_them_filter_chip.dart @@ -0,0 +1,273 @@ +import "package:flutter/material.dart"; +import "package:photos/core/constants.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/theme/ente_theme.dart"; +import "package:photos/ui/viewer/search/result/person_face_widget.dart"; + +class OnlyThemFilterChip extends StatelessWidget { + final List faceFilters; + final VoidCallback apply; + final VoidCallback remove; + final bool isApplied; + final bool isInAllFiltersView; + const OnlyThemFilterChip({ + required this.faceFilters, + required this.apply, + required this.remove, + required this.isApplied, + this.isInAllFiltersView = false, + super.key, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + if (isApplied) { + remove(); + } else { + apply(); + } + }, + child: Container( + decoration: BoxDecoration( + color: getEnteColorScheme(context).fillFaint, + borderRadius: const BorderRadius.all( + Radius.circular(kFilterChipHeight / 2), + ), + border: Border.all( + color: getEnteColorScheme(context).strokeFaint, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _OnlyThemFilterThumbnail( + faceFilters: faceFilters, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Text( + "Only them", + style: getEnteTextTheme(context).miniBold, + ), + ), + isApplied ? const SizedBox(width: 2) : const SizedBox.shrink(), + isApplied + ? Icon( + Icons.close_rounded, + size: 16, + color: getEnteColorScheme(context).textMuted, + ) + : const SizedBox.shrink(), + ], + ), + ), + ), + ); + } +} + +class _OnlyThemFilterThumbnail extends StatelessWidget { + final List faceFilters; + const _OnlyThemFilterThumbnail({ + required this.faceFilters, + }) : assert(faceFilters.length > 0 && faceFilters.length <= 4); + + @override + Widget build(BuildContext context) { + final numberOfFaces = faceFilters.length; + if (numberOfFaces == 1) { + return ClipOval( + child: SizedBox( + width: kFilterChipHeight, + height: kFilterChipHeight, + child: PersonFaceWidget( + faceFilters.first.faceFile, + personId: faceFilters.first.personId, + clusterID: faceFilters.first.clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + ); + } else if (numberOfFaces == 2) { + return ClipOval( + child: Row( + children: [ + SizedBox( + width: kFilterChipHeight / 2, + height: kFilterChipHeight, + child: PersonFaceWidget( + faceFilters.first.faceFile, + personId: faceFilters.first.personId, + clusterID: faceFilters.first.clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + const SizedBox(width: 1), + SizedBox( + width: kFilterChipHeight / 2, + height: kFilterChipHeight, + child: PersonFaceWidget( + faceFilters.last.faceFile, + personId: faceFilters.last.personId, + clusterID: faceFilters.last.clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + ], + ), + ); + } else if (faceFilters.length == 3) { + return ClipOval( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: kFilterChipHeight, + width: kFilterChipHeight / 2 - 0.5, + child: PersonFaceWidget( + faceFilters[0].faceFile, + personId: faceFilters[0].personId, + clusterID: faceFilters[0].clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + const SizedBox(width: 1), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: kFilterChipHeight / 2 - 0.5, + height: kFilterChipHeight / 2 - 0.5, + child: ClipRRect( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(1), + ), + child: PersonFaceWidget( + faceFilters[1].faceFile, + personId: faceFilters[1].personId, + clusterID: faceFilters[1].clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + ), + const SizedBox(height: 1), + SizedBox( + width: kFilterChipHeight / 2 - 0.5, + height: kFilterChipHeight / 2 - 0.5, + child: ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(1), + ), + child: PersonFaceWidget( + faceFilters[2].faceFile, + personId: faceFilters[2].personId, + clusterID: faceFilters[2].clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + ), + ], + ), + ], + ), + ); + } else { + return ClipOval( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: kFilterChipHeight / 2 - 0.5, + height: kFilterChipHeight / 2 - 0.5, + child: ClipRRect( + borderRadius: const BorderRadius.only( + bottomRight: Radius.circular(1), + ), + child: PersonFaceWidget( + faceFilters[0].faceFile, + personId: faceFilters[0].personId, + clusterID: faceFilters[0].clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + ), + const SizedBox(width: 1), + SizedBox( + width: kFilterChipHeight / 2 - 0.5, + height: kFilterChipHeight / 2 - 0.5, + child: ClipRRect( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(1), + ), + child: PersonFaceWidget( + faceFilters[1].faceFile, + personId: faceFilters[1].personId, + clusterID: faceFilters[1].clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + ), + ], + ), + const SizedBox(height: 1), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: kFilterChipHeight / 2 - 0.5, + height: kFilterChipHeight / 2 - 0.5, + child: ClipRRect( + borderRadius: const BorderRadius.only( + topRight: Radius.circular(1), + ), + child: PersonFaceWidget( + faceFilters[2].faceFile, + personId: faceFilters[2].personId, + clusterID: faceFilters[2].clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + ), + const SizedBox(width: 1), + SizedBox( + width: kFilterChipHeight / 2 - 0.5, + height: kFilterChipHeight / 2 - 0.5, + child: ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(1), + ), + child: PersonFaceWidget( + faceFilters[3].faceFile, + personId: faceFilters[3].personId, + clusterID: faceFilters[3].clusterId, + thumbnailFallback: false, + useFullFile: false, + ), + ), + ), + ], + ), + ], + ), + ); + } + } +} diff --git a/mobile/lib/ui/viewer/hierarchicial_search/filter_options_bottom_sheet.dart b/mobile/lib/ui/viewer/hierarchicial_search/filter_options_bottom_sheet.dart new file mode 100644 index 0000000000..bd9c245ed9 --- /dev/null +++ b/mobile/lib/ui/viewer/hierarchicial_search/filter_options_bottom_sheet.dart @@ -0,0 +1,116 @@ +import "package:flutter/material.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/hierarchical/only_them_filter.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; +import "package:photos/ui/viewer/hierarchicial_search/chip_widgets/face_filter_chip.dart"; +import "package:photos/ui/viewer/hierarchicial_search/chip_widgets/generic_filter_chip.dart"; +import "package:photos/ui/viewer/hierarchicial_search/chip_widgets/only_them_filter_chip.dart"; +import "package:photos/utils/hierarchical_search_util.dart"; + +class FilterOptionsBottomSheet extends StatefulWidget { + final SearchFilterDataProvider searchFilterDataProvider; + const FilterOptionsBottomSheet( + this.searchFilterDataProvider, { + super.key, + }); + + @override + State createState() => + _FilterOptionsBottomSheetState(); +} + +class _FilterOptionsBottomSheetState extends State { + late final Map> _filters; + + @override + void initState() { + super.initState(); + _filters = getFiltersForBottomSheet(widget.searchFilterDataProvider); + _filters.removeWhere((key, value) => value.isEmpty); + } + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + clipBehavior: Clip.none, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: SizedBox( + width: MediaQuery.sizeOf(context).width, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + for (String filterName in _filters.keys) + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + child: Wrap( + spacing: 6, + runSpacing: 6, + children: [ + for (HierarchicalSearchFilter filter + in _filters[filterName]!) + if (filter is FaceFilter) + FaceFilterChip( + personId: filter.personId, + clusterId: filter.clusterId, + faceThumbnailFile: filter.faceFile, + isInAllFiltersView: true, + apply: () { + widget.searchFilterDataProvider + .applyFilters([filter]); + Navigator.of(context).pop(); + }, + remove: () { + widget.searchFilterDataProvider + .removeAppliedFilters([filter]); + Navigator.of(context).pop(); + }, + isApplied: filter.isApplied, + ) + else if (filter is OnlyThemFilter) + OnlyThemFilterChip( + faceFilters: filter.faceFilters, + apply: () { + widget.searchFilterDataProvider + .applyFilters([filter]); + Navigator.of(context).pop(); + }, + remove: () { + widget.searchFilterDataProvider + .removeAppliedFilters([filter]); + Navigator.of(context).pop(); + }, + isApplied: filter.isApplied, + isInAllFiltersView: true, + ) + else + GenericFilterChip( + label: filter.name(), + leadingIcon: filter.icon(), + apply: () { + widget.searchFilterDataProvider + .applyFilters([filter]); + Navigator.of(context).pop(); + }, + remove: () { + widget.searchFilterDataProvider + .removeAppliedFilters([filter]); + Navigator.of(context).pop(); + }, + isApplied: filter.isApplied, + isInAllFiltersView: true, + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/mobile/lib/ui/viewer/hierarchicial_search/recommended_filters_for_appbar.dart b/mobile/lib/ui/viewer/hierarchicial_search/recommended_filters_for_appbar.dart new file mode 100644 index 0000000000..132f3a2b2b --- /dev/null +++ b/mobile/lib/ui/viewer/hierarchicial_search/recommended_filters_for_appbar.dart @@ -0,0 +1,177 @@ +import "package:flutter/material.dart"; +import "package:modal_bottom_sheet/modal_bottom_sheet.dart"; +import "package:photos/core/constants.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/hierarchical/only_them_filter.dart"; +import "package:photos/theme/ente_theme.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; +import "package:photos/ui/viewer/hierarchicial_search/chip_widgets/face_filter_chip.dart"; +import "package:photos/ui/viewer/hierarchicial_search/chip_widgets/generic_filter_chip.dart"; +import "package:photos/ui/viewer/hierarchicial_search/chip_widgets/only_them_filter_chip.dart"; +import "package:photos/ui/viewer/hierarchicial_search/filter_options_bottom_sheet.dart"; +import "package:photos/utils/hierarchical_search_util.dart"; + +class RecommendedFiltersForAppbar extends StatefulWidget { + const RecommendedFiltersForAppbar({super.key}); + + @override + State createState() => + _RecommendedFiltersForAppbarState(); +} + +class _RecommendedFiltersForAppbarState + extends State { + late SearchFilterDataProvider _searchFilterDataProvider; + late List _recommendations; + int _filtersUpdateCount = 0; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + final inheritedSearchFilterData = InheritedSearchFilterData.of(context); + assert( + inheritedSearchFilterData.isHierarchicalSearchable, + "Do not use this widget if gallery is not hierarchical searchable", + ); + _searchFilterDataProvider = + inheritedSearchFilterData.searchFilterDataProvider!; + _recommendations = + getRecommendedFiltersForAppBar(_searchFilterDataProvider); + _filtersUpdateCount++; + + _searchFilterDataProvider.removeListener( + fromRecommended: true, + listener: onRecommendedFiltersUpdate, + ); + _searchFilterDataProvider.addListener( + toRecommended: true, + listener: onRecommendedFiltersUpdate, + ); + } + + @override + void dispose() { + _searchFilterDataProvider.removeListener( + fromRecommended: true, + listener: onRecommendedFiltersUpdate, + ); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(bottom: 8), + child: SizedBox( + // +1 to account for the filter's outer stroke width + height: kFilterChipHeight + 1, + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 500), + switchInCurve: Curves.easeInOutExpo, + switchOutCurve: Curves.easeInOutExpo, + child: ListView.builder( + key: ValueKey(_filtersUpdateCount), + itemBuilder: (context, index) { + if (index == 0) { + return GestureDetector( + onTap: () { + showBarModalBottomSheet( + context: context, + builder: (context) { + return SafeArea( + child: FilterOptionsBottomSheet( + _searchFilterDataProvider, + ), + ); + }, + backgroundColor: + getEnteColorScheme(context).backgroundElevated2, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Container( + decoration: BoxDecoration( + color: getEnteColorScheme(context).fillFaint, + borderRadius: const BorderRadius.all( + Radius.circular(kFilterChipHeight / 2), + ), + border: Border.all( + color: getEnteColorScheme(context).strokeFaint, + width: 0.5, + ), + ), + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon( + Icons.filter_list_rounded, + size: 20, + ), + ), + ), + ), + ); + } + final filter = _recommendations[index - 1]; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: filter is FaceFilter + ? FaceFilterChip( + personId: filter.personId, + clusterId: filter.clusterId, + faceThumbnailFile: filter.faceFile, + apply: () { + _searchFilterDataProvider.applyFilters([filter]); + }, + remove: () { + _searchFilterDataProvider + .removeAppliedFilters([filter]); + }, + isApplied: filter.isApplied, + ) + : filter is OnlyThemFilter + ? OnlyThemFilterChip( + faceFilters: filter.faceFilters, + apply: () { + _searchFilterDataProvider.applyFilters([filter]); + }, + remove: () { + _searchFilterDataProvider + .removeAppliedFilters([filter]); + }, + isApplied: filter.isApplied, + ) + : GenericFilterChip( + label: filter.name(), + apply: () { + _searchFilterDataProvider.applyFilters([filter]); + }, + remove: () { + _searchFilterDataProvider + .removeAppliedFilters([filter]); + }, + leadingIcon: filter.icon(), + isApplied: filter.isApplied, + ), + ); + }, + clipBehavior: Clip.none, + scrollDirection: Axis.horizontal, + itemCount: _recommendations.length + 1, + padding: const EdgeInsets.symmetric(horizontal: 4), + ), + ), + ), + ); + } + + void onRecommendedFiltersUpdate() { + setState(() { + _filtersUpdateCount++; + _recommendations = + getRecommendedFiltersForAppBar(_searchFilterDataProvider); + }); + } +} diff --git a/mobile/lib/ui/viewer/location/location_screen.dart b/mobile/lib/ui/viewer/location/location_screen.dart index e6dee31a38..d76360763a 100644 --- a/mobile/lib/ui/viewer/location/location_screen.dart +++ b/mobile/lib/ui/viewer/location/location_screen.dart @@ -2,132 +2,80 @@ import "dart:async"; import 'dart:developer' as dev; import "package:flutter/material.dart"; -import "package:intl/intl.dart"; import "package:photos/core/constants.dart"; import "package:photos/core/event_bus.dart"; import "package:photos/db/files_db.dart"; import "package:photos/events/files_updated_event.dart"; import "package:photos/events/local_photos_updated_event.dart"; -import "package:photos/generated/l10n.dart"; import 'package:photos/models/file/file.dart'; import "package:photos/models/file_load_result.dart"; import "package:photos/models/gallery_type.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/hierarchical/location_filter.dart"; import "package:photos/models/selected_files.dart"; -import "package:photos/service_locator.dart"; import "package:photos/services/collections_service.dart"; import "package:photos/services/filter/db_filters.dart"; import "package:photos/services/location_service.dart"; import "package:photos/states/location_screen_state.dart"; -import "package:photos/theme/colors.dart"; import "package:photos/theme/ente_theme.dart"; import "package:photos/ui/common/loading_widget.dart"; -import "package:photos/ui/components/buttons/icon_button_widget.dart"; -import "package:photos/ui/components/title_bar_title_widget.dart"; -import "package:photos/ui/components/title_bar_widget.dart"; import "package:photos/ui/viewer/actions/file_selection_overlay_bar.dart"; import "package:photos/ui/viewer/gallery/gallery.dart"; +import "package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart"; +import "package:photos/ui/viewer/gallery/hierarchical_search_gallery.dart"; import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; import "package:photos/ui/viewer/gallery/state/selection_state.dart"; -import "package:photos/ui/viewer/location/edit_location_sheet.dart"; -import "package:photos/utils/dialog_util.dart"; -class LocationScreen extends StatelessWidget { +class LocationScreen extends StatefulWidget { final String tagPrefix; const LocationScreen({this.tagPrefix = "", super.key}); @override - Widget build(BuildContext context) { - final heightOfStatusBar = MediaQuery.of(context).viewPadding.top; - const heightOfAppBar = 48.0; - return GalleryFilesState( - child: Scaffold( - appBar: const PreferredSize( - preferredSize: Size(double.infinity, heightOfAppBar), - child: TitleBarWidget( - isSliver: false, - isFlexibleSpaceDisabled: true, - actionIcons: [LocationScreenPopUpMenu()], - ), - ), - body: Column( - children: [ - SizedBox( - height: MediaQuery.of(context).size.height - - (heightOfAppBar + heightOfStatusBar), - width: double.infinity, - child: LocationGalleryWidget( - tagPrefix: tagPrefix, - ), - ), - ], - ), - ), - ); - } + State createState() => _LocationScreenState(); } -class LocationScreenPopUpMenu extends StatelessWidget { - const LocationScreenPopUpMenu({super.key}); +class _LocationScreenState extends State { + final selectedFiles = SelectedFiles(); @override Widget build(BuildContext context) { - final textTheme = getEnteTextTheme(context); - final colorScheme = getEnteColorScheme(context); - return Padding( - padding: const EdgeInsets.only(right: 4), - child: Theme( - data: Theme.of(context).copyWith( - highlightColor: Colors.transparent, - splashColor: Colors.transparent, + final heightOfStatusBar = MediaQuery.of(context).viewPadding.top; + const heightOfAppBar = 90.0; + final locationTag = + InheritedLocationScreenState.of(context).locationTagEntity.item; + + return GalleryFilesState( + child: InheritedSearchFilterDataWrapper( + searchFilterDataProvider: SearchFilterDataProvider( + initialGalleryFilter: LocationFilter( + locationTag: locationTag, + occurrence: kMostRelevantFilter, + ), ), - child: PopupMenuButton( - elevation: 2, - offset: const Offset(10, 50), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), + child: Scaffold( + appBar: PreferredSize( + preferredSize: const Size(double.infinity, heightOfAppBar), + child: GalleryAppBarWidget( + GalleryType.locationTag, + locationTag.name, + selectedFiles, + ), ), - color: colorScheme.backgroundElevated2, - child: const IconButtonWidget( - icon: Icons.more_horiz, - iconButtonType: IconButtonType.primary, - disableGestureDetector: true, - ), - itemBuilder: (context) { - return [ - PopupMenuItem( - value: "edit", - child: Text( - S.of(context).edit, - style: textTheme.bodyBold, + body: Column( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height - + (heightOfAppBar + heightOfStatusBar), + width: double.infinity, + child: LocationGalleryWidget( + tagPrefix: widget.tagPrefix, + selectedFiles: selectedFiles, ), ), - PopupMenuItem( - onTap: () {}, - value: "delete", - child: Text( - S.of(context).deleteLocation, - style: textTheme.bodyBold.copyWith(color: warning500), - ), - ), - ]; - }, - onSelected: (value) async { - if (value == "edit") { - showEditLocationSheet( - context, - InheritedLocationScreenState.of(context).locationTagEntity, - ); - } else if (value == "delete") { - try { - await locationService.deleteLocationTag( - InheritedLocationScreenState.of(context).locationTagEntity.id, - ); - Navigator.of(context).pop(); - } catch (e) { - await showGenericErrorDialog(context: context, error: e); - } - } - }, + ], + ), ), ), ); @@ -136,7 +84,12 @@ class LocationScreenPopUpMenu extends StatelessWidget { class LocationGalleryWidget extends StatefulWidget { final String tagPrefix; - const LocationGalleryWidget({required this.tagPrefix, super.key}); + final SelectedFiles selectedFiles; + const LocationGalleryWidget({ + required this.tagPrefix, + required this.selectedFiles, + super.key, + }); @override State createState() => _LocationGalleryWidgetState(); @@ -146,7 +99,6 @@ class _LocationGalleryWidgetState extends State { late final Future fileLoadResult; late final List allFilesWithLocation; - late Widget galleryHeaderWidget; final _selectedFiles = SelectedFiles(); late final StreamSubscription _filesUpdateEvent; @override @@ -154,7 +106,7 @@ class _LocationGalleryWidgetState extends State { super.initState(); final collectionsToHide = - CollectionsService.instance.archivedOrHiddenCollectionIds(); + CollectionsService.instance.getHiddenCollectionIds(); fileLoadResult = FilesDB.instance .fetchAllUploadedAndSharedFilesWithLocation( galleryLoadStartTime, @@ -184,8 +136,6 @@ class _LocationGalleryWidgetState extends State { }); return value; }); - - galleryHeaderWidget = const GalleryHeaderWidget(); } @override @@ -241,31 +191,47 @@ class _LocationGalleryWidgetState extends State { child: Stack( alignment: Alignment.bottomCenter, children: [ - Gallery( - loadingWidget: Column( - children: [ - galleryHeaderWidget, - EnteLoadingWidget( - color: getEnteColorScheme(context).strokeMuted, - ), - ], - ), - header: galleryHeaderWidget, - asyncLoader: ( - creationStartTime, - creationEndTime, { - limit, - asc, - }) async { - return snapshot.data as FileLoadResult; + Builder( + builder: (context) { + return ValueListenableBuilder( + valueListenable: InheritedSearchFilterData.of(context) + .searchFilterDataProvider! + .isSearchingNotifier, + builder: (context, value, _) { + return value + ? HierarchicalSearchGallery( + tagPrefix: widget.tagPrefix, + selectedFiles: _selectedFiles, + ) + : Gallery( + loadingWidget: Column( + children: [ + EnteLoadingWidget( + color: getEnteColorScheme(context) + .strokeMuted, + ), + ], + ), + asyncLoader: ( + creationStartTime, + creationEndTime, { + limit, + asc, + }) async { + return snapshot.data as FileLoadResult; + }, + reloadEvent: + Bus.instance.on(), + removalEventTypes: const { + EventType.deletedFromRemote, + EventType.deletedFromEverywhere, + }, + selectedFiles: _selectedFiles, + tagPrefix: widget.tagPrefix, + ); + }, + ); }, - reloadEvent: Bus.instance.on(), - removalEventTypes: const { - EventType.deletedFromRemote, - EventType.deletedFromEverywhere, - }, - selectedFiles: _selectedFiles, - tagPrefix: widget.tagPrefix, ), FileSelectionOverlayBar( GalleryType.locationTag, @@ -275,10 +241,9 @@ class _LocationGalleryWidgetState extends State { ), ); } else { - return Column( + return const Column( children: [ - galleryHeaderWidget, - const Expanded( + Expanded( child: EnteLoadingWidget(), ), ], @@ -289,65 +254,3 @@ class _LocationGalleryWidgetState extends State { ); } } - -class GalleryHeaderWidget extends StatefulWidget { - const GalleryHeaderWidget({super.key}); - - @override - State createState() => _GalleryHeaderWidgetState(); -} - -class _GalleryHeaderWidgetState extends State { - @override - Widget build(BuildContext context) { - final locationName = - InheritedLocationScreenState.of(context).locationTagEntity.item.name; - return Padding( - padding: const EdgeInsets.only(bottom: 20), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - key: ValueKey(locationName), - width: double.infinity, - child: TitleBarTitleWidget( - title: locationName, - onTap: () { - showEditLocationSheet( - context, - InheritedLocationScreenState.of(context).locationTagEntity, - ); - }, - ), - ), - ValueListenableBuilder( - valueListenable: InheritedLocationScreenState.memoryCountNotifier, - builder: (context, int? value, _) { - if (value == null) { - return RepaintBoundary( - child: EnteLoadingWidget( - size: 12, - color: getEnteColorScheme(context).strokeMuted, - alignment: Alignment.centerLeft, - padding: 2.5, - ), - ); - } else { - return Text( - S - .of(context) - .memoryCount(value, NumberFormat().format(value)), - style: getEnteTextTheme(context).smallMuted, - ); - } - }, - ), - ], - ), - ), - ); - } -} diff --git a/mobile/lib/ui/viewer/people/add_person_action_sheet.dart b/mobile/lib/ui/viewer/people/add_person_action_sheet.dart index ecfa6b56b5..9aa05b16e4 100644 --- a/mobile/lib/ui/viewer/people/add_person_action_sheet.dart +++ b/mobile/lib/ui/viewer/people/add_person_action_sheet.dart @@ -93,11 +93,6 @@ class _PersonActionSheetState extends State { String _searchQuery = ""; bool userAlreadyAssigned = false; - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { final bottomInset = MediaQuery.of(context).viewInsets.bottom; @@ -290,6 +285,7 @@ class _PersonActionSheetState extends State { String initValue = '', required String clusterID, }) async { + PersonEntity? personEntity; final result = await showTextInputDialog( context, title: S.of(context).newPerson, @@ -308,15 +304,16 @@ class _PersonActionSheetState extends State { } try { userAlreadyAssigned = true; - final PersonEntity p = + personEntity = await PersonService.instance.addPerson(text, clusterID); - final bool extraPhotosFound = await ClusterFeedbackService.instance - .checkAndDoAutomaticMerges(p, personClusterID: clusterID); + final bool extraPhotosFound = + await ClusterFeedbackService.instance.checkAndDoAutomaticMerges( + personEntity!, + personClusterID: clusterID, + ); if (extraPhotosFound) { showShortToast(context, S.of(context).extraPhotosFound); } - Bus.instance.fire(PeopleChangedEvent()); - Navigator.pop(context, p); } catch (e, s) { Logger("_PersonActionSheetState") .severe("Failed to add person", e, s); @@ -327,6 +324,10 @@ class _PersonActionSheetState extends State { if (result is Exception) { await showGenericErrorDialog(context: context, error: result); } + if (personEntity != null) { + Bus.instance.fire(PeopleChangedEvent()); + Navigator.pop(context, personEntity); + } } Future> _getPersonsWithRecentFile({ diff --git a/mobile/lib/ui/viewer/people/cluster_app_bar.dart b/mobile/lib/ui/viewer/people/cluster_app_bar.dart index a5e6ef7815..8ea245f1a2 100644 --- a/mobile/lib/ui/viewer/people/cluster_app_bar.dart +++ b/mobile/lib/ui/viewer/people/cluster_app_bar.dart @@ -95,6 +95,9 @@ class _AppBarWidgetState extends State { overflow: TextOverflow.ellipsis, ), actions: _getDefaultActions(context), + scrolledUnderElevation: 4, + shadowColor: Colors.black.withOpacity(0.15), + surfaceTintColor: Colors.transparent, ); } @@ -199,8 +202,7 @@ class _AppBarWidgetState extends State { await MLDataDB.instance.deleteClusterSummary(widget.clusterID); await MLDataDB.instance .clusterSummaryUpdate(breakupResult.newClusterSummaries); - await MLDataDB.instance - .updateFaceIdToClusterId(newFaceIdToClusterID); + await MLDataDB.instance.updateFaceIdToClusterId(newFaceIdToClusterID); // Find the biggest cluster biggestClusterID = ''; @@ -217,7 +219,7 @@ class _AppBarWidgetState extends State { .map((e) => getFileIdFromFaceId(e)) .toList(); biggestClusterFiles = await FilesDB.instance - .getFilesFromIDs( + .getFileIDToFileFromIDs( biggestClusterFileIDs, ) .then((mapping) => mapping.values.toList()); @@ -261,7 +263,7 @@ class _AppBarWidgetState extends State { .map((e) => getFileIdFromFaceId(e)) .toList(); - final fileIDtoFile = await FilesDB.instance.getFilesFromIDs( + final fileIDtoFile = await FilesDB.instance.getFileIDToFileFromIDs( allFileIDs, ); diff --git a/mobile/lib/ui/viewer/people/cluster_page.dart b/mobile/lib/ui/viewer/people/cluster_page.dart index 8185228c64..cca4e2b6d2 100644 --- a/mobile/lib/ui/viewer/people/cluster_page.dart +++ b/mobile/lib/ui/viewer/people/cluster_page.dart @@ -59,11 +59,6 @@ class _ClusterPageState extends State { late final StreamSubscription _filesUpdatedEvent; late final StreamSubscription _peopleChangedEvent; - bool get showNamingBanner => - (!userDismissedNamingBanner && widget.showNamingBanner); - - bool userDismissedNamingBanner = false; - @override void initState() { super.initState(); @@ -138,6 +133,46 @@ class _ClusterPageState extends State { selectedFiles: _selectedFiles, enableFileGrouping: widget.enableGrouping, initialFiles: [widget.searchResult.first], + header: widget.showNamingBanner + ? PeopleBanner( + type: PeopleBannerType.addName, + faceWidget: PersonFaceWidget( + files.first, + clusterID: widget.clusterID, + ), + actionIcon: Icons.add_outlined, + text: S.of(context).addAName, + subText: S.of(context).findPeopleByName, + onTap: () async { + if (widget.personID == null) { + final result = await showAssignPersonAction( + context, + clusterID: widget.clusterID, + ); + if (result != null && result is (PersonEntity, EnteFile)) { + Navigator.pop(context); + // ignore: unawaited_futures + routeToPage( + context, + PeoplePage(person: result.$1, searchResult: null), + ); + } else if (result != null && result is PersonEntity) { + Navigator.pop(context); + // ignore: unawaited_futures + routeToPage( + context, + PeoplePage( + person: result, + searchResult: null, + ), + ); + } + } else { + showShortToast(context, "No personID or clusterID"); + } + }, + ) + : null, ); return GalleryFilesState( child: Scaffold( @@ -151,69 +186,19 @@ class _ClusterPageState extends State { key: ValueKey(files.length), ), ), - body: Column( - children: [ - showNamingBanner - ? Dismissible( - key: const Key("namingBanner"), - direction: DismissDirection.horizontal, - onDismissed: (direction) { - setState(() { - userDismissedNamingBanner = true; - }); - }, - child: PeopleBanner( - type: PeopleBannerType.addName, - faceWidget: PersonFaceWidget( - files.first, - clusterID: widget.clusterID, - ), - actionIcon: Icons.add_outlined, - text: S.of(context).addAName, - subText: S.of(context).findPeopleByName, - onTap: () async { - if (widget.personID == null) { - final result = await showAssignPersonAction( - context, - clusterID: widget.clusterID, - ); - if (result != null && - result is (PersonEntity, EnteFile)) { - Navigator.pop(context); - // ignore: unawaited_futures - routeToPage( - context, - PeoplePage(person: result.$1), - ); - } else if (result != null && result is PersonEntity) { - Navigator.pop(context); - // ignore: unawaited_futures - routeToPage(context, PeoplePage(person: result)); - } - } else { - showShortToast(context, "No personID or clusterID"); - } - }, - ), - ) - : const SizedBox.shrink(), - Expanded( - child: SelectionState( - selectedFiles: _selectedFiles, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - gallery, - FileSelectionOverlayBar( - ClusterPage.overlayType, - _selectedFiles, - clusterID: widget.clusterID, - ), - ], - ), + body: SelectionState( + selectedFiles: _selectedFiles, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + gallery, + FileSelectionOverlayBar( + ClusterPage.overlayType, + _selectedFiles, + clusterID: widget.clusterID, ), - ), - ], + ], + ), ), ), ); diff --git a/mobile/lib/ui/viewer/people/people_app_bar.dart b/mobile/lib/ui/viewer/people/people_app_bar.dart index 76fd73f5e6..05da13c8b2 100644 --- a/mobile/lib/ui/viewer/people/people_app_bar.dart +++ b/mobile/lib/ui/viewer/people/people_app_bar.dart @@ -4,6 +4,7 @@ import "package:flutter/cupertino.dart"; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:photos/core/configuration.dart'; +import "package:photos/core/constants.dart"; import 'package:photos/core/event_bus.dart'; import "package:photos/events/people_changed_event.dart"; import 'package:photos/events/subscription_purchased_event.dart'; @@ -15,6 +16,9 @@ import 'package:photos/models/selected_files.dart'; import 'package:photos/services/collections_service.dart'; import "package:photos/services/machine_learning/face_ml/person/person_service.dart"; import 'package:photos/ui/actions/collection/collection_sharing_actions.dart'; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/hierarchicial_search/applied_filters_for_appbar.dart"; +import "package:photos/ui/viewer/hierarchicial_search/recommended_filters_for_appbar.dart"; import "package:photos/ui/viewer/people/add_person_action_sheet.dart"; import "package:photos/ui/viewer/people/people_page.dart"; import "package:photos/ui/viewer/people/person_cluster_suggestion.dart"; @@ -34,8 +38,8 @@ class PeopleAppBar extends StatefulWidget { this.title, this.selectedFiles, this.person, { - Key? key, - }) : super(key: key); + super.key, + }); @override State createState() => _AppBarWidgetState(); @@ -84,18 +88,59 @@ class _AppBarWidgetState extends State { @override Widget build(BuildContext context) { - return AppBar( - elevation: 0, - centerTitle: false, - title: Text( - _appBarTitle!, - style: - Theme.of(context).textTheme.headlineSmall!.copyWith(fontSize: 16), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - actions: _getDefaultActions(context), - ); + final inheritedSearchFilterData = + InheritedSearchFilterData.maybeOf(context); + final isHierarchicalSearchable = + inheritedSearchFilterData?.isHierarchicalSearchable ?? false; + return isHierarchicalSearchable + ? ValueListenableBuilder( + valueListenable: inheritedSearchFilterData! + .searchFilterDataProvider!.isSearchingNotifier, + child: const PreferredSize( + preferredSize: Size.fromHeight(0), + child: Flexible(child: RecommendedFiltersForAppbar()), + ), + builder: (context, isSearching, child) { + return AppBar( + elevation: 0, + centerTitle: false, + title: isSearching + ? const SizedBox( + // +1 to account for the filter's outer stroke width + height: kFilterChipHeight + 1, + child: AppliedFiltersForAppbar(), + ) + : Text( + _appBarTitle!, + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 16), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + bottom: child as PreferredSizeWidget, + actions: isSearching ? null : _getDefaultActions(context), + surfaceTintColor: Colors.transparent, + scrolledUnderElevation: 4, + shadowColor: Colors.black.withOpacity(0.15), + ); + }, + ) + : AppBar( + elevation: 0, + centerTitle: false, + title: Text( + _appBarTitle!, + style: Theme.of(context) + .textTheme + .headlineSmall! + .copyWith(fontSize: 16), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + actions: _getDefaultActions(context), + ); } Future _renamePerson(BuildContext context) async { @@ -178,7 +223,7 @@ class _AppBarWidgetState extends State { const Padding( padding: EdgeInsets.all(8), ), - Text(S.of(context).removePersonLabel), + Text(S.of(context).resetPerson), ], ), ), @@ -239,7 +284,7 @@ class _AppBarWidgetState extends State { } else if (value == PeoplePopupAction.unignore) { await _showPerson(context); } else if (value == PeoplePopupAction.removeLabel) { - await _removePersonLabel(context); + await _resetPerson(context); } }, ), @@ -249,19 +294,18 @@ class _AppBarWidgetState extends State { return actions; } - Future _removePersonLabel(BuildContext context) async { + Future _resetPerson(BuildContext context) async { await showChoiceDialog( context, - title: "Are you sure you want to remove this person label?", - body: - "All groupings for this person will be reset, and you will lose all suggestions made for this person", - firstButtonLabel: "Yes, remove person", + title: S.of(context).areYouSureYouWantToResetThisPerson, + body: S.of(context).allPersonGroupingWillReset, + firstButtonLabel: S.of(context).yesResetPerson, firstButtonOnTap: () async { try { await PersonService.instance.deletePerson(widget.person.remoteID); Navigator.of(context).pop(); } catch (e, s) { - _logger.severe('Removing person label failed', e, s); + _logger.severe('Resetting person failed', e, s); } }, ); @@ -294,10 +338,22 @@ class _AppBarWidgetState extends State { Navigator.pop(context); if (result != null && result is (PersonEntity, EnteFile)) { // ignore: unawaited_futures - routeToPage(context, PeoplePage(person: result.$1)); + routeToPage( + context, + PeoplePage( + person: result.$1, + searchResult: null, + ), + ); } else if (result != null && result is PersonEntity) { // ignore: unawaited_futures - routeToPage(context, PeoplePage(person: result)); + routeToPage( + context, + PeoplePage( + person: result, + searchResult: null, + ), + ); } } } diff --git a/mobile/lib/ui/viewer/people/people_banner.dart b/mobile/lib/ui/viewer/people/people_banner.dart index 01aeab6361..7a27990935 100644 --- a/mobile/lib/ui/viewer/people/people_banner.dart +++ b/mobile/lib/ui/viewer/people/people_banner.dart @@ -1,6 +1,4 @@ import "package:flutter/material.dart"; -import "package:flutter_animate/flutter_animate.dart"; -import "package:photos/ente_theme_data.dart"; import "package:photos/theme/ente_theme.dart"; import "package:photos/ui/components/buttons/icon_button_widget.dart"; import "package:photos/ui/viewer/search/result/person_face_widget.dart"; @@ -20,7 +18,7 @@ class PeopleBanner extends StatelessWidget { final GestureTapCallback onTap; const PeopleBanner({ - Key? key, + super.key, required this.type, this.startIcon, this.faceWidget, @@ -28,7 +26,7 @@ class PeopleBanner extends StatelessWidget { required this.text, required this.onTap, this.subText, - }) : super(key: key); + }); @override Widget build(BuildContext context) { @@ -72,13 +70,19 @@ class PeopleBanner extends StatelessWidget { final Widget banner = Center( child: GestureDetector( onTap: onTap, - child: Container( - decoration: BoxDecoration( - boxShadow: Theme.of(context).colorScheme.enteTheme.shadowMenu, - color: backgroundColor, - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 2), + child: Padding( + padding: const EdgeInsets.all(4), + child: Container( + decoration: BoxDecoration( + color: backgroundColor, + border: Border.all( + color: colorScheme.strokeFaint, + width: 1, + ), + borderRadius: const BorderRadius.all( + Radius.circular(5), + ), + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -122,11 +126,7 @@ class PeopleBanner extends StatelessWidget { ), ), ), - ).animate(onPlay: (controller) => controller.repeat()).shimmer( - duration: 1000.ms, - delay: 3200.ms, - size: 0.6, - ); + ); if (type == PeopleBannerType.suggestion) { return SafeArea( diff --git a/mobile/lib/ui/viewer/people/people_page.dart b/mobile/lib/ui/viewer/people/people_page.dart index 2f908947db..2534df7189 100644 --- a/mobile/lib/ui/viewer/people/people_page.dart +++ b/mobile/lib/ui/viewer/people/people_page.dart @@ -11,13 +11,17 @@ import 'package:photos/models/file/file.dart'; import 'package:photos/models/file_load_result.dart'; import 'package:photos/models/gallery_type.dart'; import "package:photos/models/ml/face/person.dart"; +import "package:photos/models/search/search_result.dart"; import 'package:photos/models/selected_files.dart'; import "package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart"; import "package:photos/services/machine_learning/face_ml/feedback/cluster_feedback.dart"; import "package:photos/services/search_service.dart"; import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.dart'; import 'package:photos/ui/viewer/gallery/gallery.dart'; +import "package:photos/ui/viewer/gallery/hierarchical_search_gallery.dart"; import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; import "package:photos/ui/viewer/gallery/state/selection_state.dart"; import "package:photos/ui/viewer/people/people_app_bar.dart"; import "package:photos/ui/viewer/people/people_banner.dart"; @@ -26,6 +30,7 @@ import "package:photos/ui/viewer/people/person_cluster_suggestion.dart"; class PeoplePage extends StatefulWidget { final String tagPrefix; final PersonEntity person; + final SearchResult? searchResult; static const GalleryType appBarType = GalleryType.peopleTag; static const GalleryType overlayType = GalleryType.peopleTag; @@ -33,8 +38,9 @@ class PeoplePage extends StatefulWidget { const PeoplePage({ this.tagPrefix = "", required this.person, - Key? key, - }) : super(key: key); + required this.searchResult, + super.key, + }); @override State createState() => _PeoplePageState(); @@ -111,113 +117,169 @@ class _PeoplePageState extends State { Widget build(BuildContext context) { _logger.info("Building for ${widget.person.data.name}"); return GalleryFilesState( - child: Scaffold( - appBar: PreferredSize( - preferredSize: const Size.fromHeight(50.0), - child: PeopleAppBar( - GalleryType.peopleTag, - widget.person.data.name, - _selectedFiles, - widget.person, + child: InheritedSearchFilterDataWrapper( + searchFilterDataProvider: widget.searchResult != null + ? SearchFilterDataProvider( + initialGalleryFilter: + widget.searchResult!.getHierarchicalSearchFilter(), + ) + : null, + child: Scaffold( + appBar: PreferredSize( + preferredSize: + Size.fromHeight(widget.searchResult != null ? 90.0 : 50.0), + child: PeopleAppBar( + GalleryType.peopleTag, + widget.person.data.name, + _selectedFiles, + widget.person, + ), ), - ), - body: FutureBuilder>( - future: filesFuture, - builder: (context, snapshot) { - if (snapshot.hasData) { - final personFiles = snapshot.data as List; - return Column( - children: [ - Expanded( - child: SelectionState( - selectedFiles: _selectedFiles, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Gallery( - asyncLoader: ( - creationStartTime, - creationEndTime, { - limit, - asc, - }) async { - final result = await loadPersonFiles(); - return Future.value( - FileLoadResult( - result, - false, - ), - ); - }, - reloadEvent: - Bus.instance.on(), - forceReloadEvents: [ - Bus.instance.on(), - ], - removalEventTypes: const { - EventType.deletedFromRemote, - EventType.deletedFromEverywhere, - EventType.hide, - }, - tagPrefix: widget.tagPrefix + widget.tagPrefix, - selectedFiles: _selectedFiles, - initialFiles: personFiles.isNotEmpty - ? [personFiles.first] - : [], - ), - FileSelectionOverlayBar( - PeoplePage.overlayType, - _selectedFiles, - person: widget.person, - ), - ], + body: FutureBuilder>( + future: filesFuture, + builder: (context, snapshot) { + final inheritedSearchFilterData = InheritedSearchFilterData.of( + context, + ); + if (snapshot.hasData) { + final personFiles = snapshot.data as List; + return Column( + children: [ + Expanded( + child: SelectionState( + selectedFiles: _selectedFiles, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + inheritedSearchFilterData.isHierarchicalSearchable + ? ValueListenableBuilder( + valueListenable: inheritedSearchFilterData + .searchFilterDataProvider! + .isSearchingNotifier, + builder: ( + context, + value, + _, + ) { + return value + ? HierarchicalSearchGallery( + tagPrefix: widget.tagPrefix, + selectedFiles: _selectedFiles, + ) + : _Gallery( + tagPrefix: widget.tagPrefix, + selectedFiles: _selectedFiles, + personFiles: personFiles, + loadPersonFiles: loadPersonFiles, + ); + }, + ) + : _Gallery( + tagPrefix: widget.tagPrefix, + selectedFiles: _selectedFiles, + personFiles: personFiles, + loadPersonFiles: loadPersonFiles, + ), + FileSelectionOverlayBar( + PeoplePage.overlayType, + _selectedFiles, + person: widget.person, + ), + ], + ), ), ), - ), - showSuggestionBanner - ? Dismissible( - key: const Key("suggestionBanner"), - direction: DismissDirection.horizontal, - onDismissed: (direction) { - setState(() { - userDismissedSuggestionBanner = true; - }); - }, - child: PeopleBanner( - type: PeopleBannerType.suggestion, - startIcon: Icons.face_retouching_natural, - actionIcon: Icons.search_outlined, - text: "Review suggestions", - subText: "Improve the results", - onTap: () async { - unawaited( - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => - PersonReviewClusterSuggestion( - widget.person, + showSuggestionBanner + ? Dismissible( + key: const Key("suggestionBanner"), + direction: DismissDirection.horizontal, + onDismissed: (direction) { + setState(() { + userDismissedSuggestionBanner = true; + }); + }, + child: PeopleBanner( + type: PeopleBannerType.suggestion, + startIcon: Icons.face_retouching_natural, + actionIcon: Icons.search_outlined, + text: "Review suggestions", + subText: "Improve the results", + onTap: () async { + unawaited( + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + PersonReviewClusterSuggestion( + widget.person, + ), ), ), - ), - ); - }, - ), - ) - : const SizedBox.shrink(), - ], - ); - } else if (snapshot.hasError) { - log("Error: ${snapshot.error} ${snapshot.stackTrace}}"); - //Need to show an error on the UI here - return const SizedBox.shrink(); - } else { - return const Center( - child: CircularProgressIndicator(), - ); - } - }, + ); + }, + ), + ) + : const SizedBox.shrink(), + ], + ); + } else if (snapshot.hasError) { + log("Error: ${snapshot.error} ${snapshot.stackTrace}}"); + //Need to show an error on the UI here + return const SizedBox.shrink(); + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + }, + ), ), ), ); } } + +class _Gallery extends StatelessWidget { + final String tagPrefix; + final SelectedFiles selectedFiles; + final List personFiles; + final Future> Function() loadPersonFiles; + + const _Gallery({ + required this.tagPrefix, + required this.selectedFiles, + required this.personFiles, + required this.loadPersonFiles, + }); + + @override + Widget build(BuildContext context) { + return Gallery( + asyncLoader: ( + creationStartTime, + creationEndTime, { + limit, + asc, + }) async { + final result = await loadPersonFiles(); + return Future.value( + FileLoadResult( + result, + false, + ), + ); + }, + reloadEvent: Bus.instance.on(), + forceReloadEvents: [ + Bus.instance.on(), + ], + removalEventTypes: const { + EventType.deletedFromRemote, + EventType.deletedFromEverywhere, + EventType.hide, + }, + tagPrefix: tagPrefix + tagPrefix, + selectedFiles: selectedFiles, + initialFiles: personFiles.isNotEmpty ? [personFiles.first] : [], + ); + } +} diff --git a/mobile/lib/ui/viewer/search/result/go_to_map_widget.dart b/mobile/lib/ui/viewer/search/result/go_to_map_widget.dart index 728268c927..d358972157 100644 --- a/mobile/lib/ui/viewer/search/result/go_to_map_widget.dart +++ b/mobile/lib/ui/viewer/search/result/go_to_map_widget.dart @@ -19,7 +19,7 @@ class GoToMap extends StatelessWidget { Navigator.of(context).push( MaterialPageRoute( builder: (context) => MapScreen( - filesFutureFn: SearchService.instance.getAllFiles, + filesFutureFn: SearchService.instance.getAllFilesForSearch, ), ), ); diff --git a/mobile/lib/ui/viewer/search/result/magic_result_screen.dart b/mobile/lib/ui/viewer/search/result/magic_result_screen.dart index c8c4e3697d..b3f1b72d44 100644 --- a/mobile/lib/ui/viewer/search/result/magic_result_screen.dart +++ b/mobile/lib/ui/viewer/search/result/magic_result_screen.dart @@ -9,11 +9,15 @@ import "package:photos/events/magic_sort_change_event.dart"; import 'package:photos/models/file/file.dart'; import 'package:photos/models/file_load_result.dart'; import 'package:photos/models/gallery_type.dart'; +import "package:photos/models/search/hierarchical/magic_filter.dart"; import 'package:photos/models/selected_files.dart'; import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.dart'; import 'package:photos/ui/viewer/gallery/gallery.dart'; import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart'; +import "package:photos/ui/viewer/gallery/hierarchical_search_gallery.dart"; import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; import "package:photos/ui/viewer/gallery/state/selection_state.dart"; class MagicResultScreen extends StatefulWidget { @@ -24,6 +28,7 @@ class MagicResultScreen extends StatefulWidget { final String heroTag; final bool enableGrouping; final Map fileIdToPosMap; + final MagicFilter magicFilter; static const GalleryType appBarType = GalleryType.magic; static const GalleryType overlayType = GalleryType.magic; @@ -31,6 +36,7 @@ class MagicResultScreen extends StatefulWidget { const MagicResultScreen( this.files, { required this.name, + required this.magicFilter, this.enableGrouping = false, this.fileIdToPosMap = const {}, this.heroTag = "", @@ -157,31 +163,52 @@ class _MagicResultScreenState extends State { initialFiles: [files.first], ); return GalleryFilesState( - child: Scaffold( - appBar: PreferredSize( - preferredSize: const Size.fromHeight(50.0), - child: GalleryAppBarWidget( - MagicResultScreen.appBarType, - widget.name, - _selectedFiles, - ), + child: InheritedSearchFilterDataWrapper( + searchFilterDataProvider: SearchFilterDataProvider( + initialGalleryFilter: widget.magicFilter, ), - body: SelectionState( - selectedFiles: _selectedFiles, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - AnimatedSwitcher( - duration: const Duration(milliseconds: 250), - switchInCurve: Curves.easeInOutQuad, - switchOutCurve: Curves.easeInOutQuad, - child: gallery, - ), - FileSelectionOverlayBar( - MagicResultScreen.overlayType, - _selectedFiles, - ), - ], + child: Scaffold( + appBar: PreferredSize( + preferredSize: const Size.fromHeight(90.0), + child: GalleryAppBarWidget( + MagicResultScreen.appBarType, + widget.name, + _selectedFiles, + ), + ), + body: SelectionState( + selectedFiles: _selectedFiles, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Builder( + builder: (context) { + return ValueListenableBuilder( + valueListenable: InheritedSearchFilterData.of(context) + .searchFilterDataProvider! + .isSearchingNotifier, + builder: (context, value, _) { + return value + ? HierarchicalSearchGallery( + tagPrefix: widget.heroTag, + selectedFiles: _selectedFiles, + ) + : AnimatedSwitcher( + duration: const Duration(milliseconds: 250), + switchInCurve: Curves.easeInOutQuad, + switchOutCurve: Curves.easeInOutQuad, + child: gallery, + ); + }, + ); + }, + ), + FileSelectionOverlayBar( + MagicResultScreen.overlayType, + _selectedFiles, + ), + ], + ), ), ), ), diff --git a/mobile/lib/ui/viewer/search/result/person_face_widget.dart b/mobile/lib/ui/viewer/search/result/person_face_widget.dart index b5e9882833..cb82dfc130 100644 --- a/mobile/lib/ui/viewer/search/result/person_face_widget.dart +++ b/mobile/lib/ui/viewer/search/result/person_face_widget.dart @@ -8,6 +8,7 @@ import 'package:photos/models/file/file.dart'; import "package:photos/models/ml/face/face.dart"; import "package:photos/models/ml/face/person.dart"; import "package:photos/services/machine_learning/face_ml/person/person_service.dart"; +import "package:photos/theme/ente_theme.dart"; import "package:photos/ui/common/loading_widget.dart"; import "package:photos/ui/viewer/file/thumbnail_widget.dart"; import "package:photos/utils/face/face_box_crop.dart"; @@ -31,12 +32,11 @@ class PersonFaceWidget extends StatelessWidget { this.useFullFile = true, this.thumbnailFallback = true, this.faceCrop, - Key? key, - }) : assert( + super.key, + }) : assert( personId != null || clusterID != null, "PersonFaceWidget requires either personId or clusterID to be non-null", - ), - super(key: key); + ); @override Widget build(BuildContext context) { @@ -71,7 +71,9 @@ class PersonFaceWidget extends StatelessWidget { } return thumbnailFallback ? ThumbnailWidget(file) - : const EnteLoadingWidget(); + : EnteLoadingWidget( + color: getEnteColorScheme(context).fillMuted, + ); } }, ); diff --git a/mobile/lib/ui/viewer/search/result/search_result_page.dart b/mobile/lib/ui/viewer/search/result/search_result_page.dart index ee0ed6ad45..19a3c7f25e 100644 --- a/mobile/lib/ui/viewer/search/result/search_result_page.dart +++ b/mobile/lib/ui/viewer/search/result/search_result_page.dart @@ -12,7 +12,10 @@ import 'package:photos/models/selected_files.dart'; import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.dart'; import 'package:photos/ui/viewer/gallery/gallery.dart'; import 'package:photos/ui/viewer/gallery/gallery_app_bar_widget.dart'; +import "package:photos/ui/viewer/gallery/hierarchical_search_gallery.dart"; import "package:photos/ui/viewer/gallery/state/gallery_files_inherited_widget.dart"; +import "package:photos/ui/viewer/gallery/state/inherited_search_filter_data.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; import "package:photos/ui/viewer/gallery/state/selection_state.dart"; class SearchResultPage extends StatefulWidget { @@ -92,27 +95,50 @@ class _SearchResultPageState extends State { enableFileGrouping: widget.enableGrouping, initialFiles: [widget.searchResult.resultFiles().first], ); + return GalleryFilesState( - child: Scaffold( - appBar: PreferredSize( - preferredSize: const Size.fromHeight(50.0), - child: GalleryAppBarWidget( - SearchResultPage.appBarType, - widget.searchResult.name(), - _selectedFiles, - ), + child: InheritedSearchFilterDataWrapper( + searchFilterDataProvider: SearchFilterDataProvider( + initialGalleryFilter: + widget.searchResult.getHierarchicalSearchFilter(), ), - body: SelectionState( - selectedFiles: _selectedFiles, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - gallery, - FileSelectionOverlayBar( - SearchResultPage.overlayType, - _selectedFiles, - ), - ], + child: Scaffold( + appBar: PreferredSize( + preferredSize: const Size.fromHeight(90.0), + child: GalleryAppBarWidget( + SearchResultPage.appBarType, + widget.searchResult.name(), + _selectedFiles, + ), + ), + body: SelectionState( + selectedFiles: _selectedFiles, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Builder( + builder: (context) { + return ValueListenableBuilder( + valueListenable: InheritedSearchFilterData.of(context) + .searchFilterDataProvider! + .isSearchingNotifier, + builder: (context, value, _) { + return value + ? HierarchicalSearchGallery( + tagPrefix: widget.tagPrefix, + selectedFiles: _selectedFiles, + ) + : gallery; + }, + ); + }, + ), + FileSelectionOverlayBar( + SearchResultPage.overlayType, + _selectedFiles, + ), + ], + ), ), ), ), diff --git a/mobile/lib/ui/viewer/search/result/search_section_all_page.dart b/mobile/lib/ui/viewer/search/result/search_section_all_page.dart index c7585ed51c..0eae57792f 100644 --- a/mobile/lib/ui/viewer/search/result/search_section_all_page.dart +++ b/mobile/lib/ui/viewer/search/result/search_section_all_page.dart @@ -7,6 +7,7 @@ import "package:photos/events/event.dart"; import "package:photos/extensions/list.dart"; import "package:photos/models/search/album_search_result.dart"; import "package:photos/models/search/generic_search_result.dart"; +import "package:photos/models/search/hierarchical/magic_filter.dart"; import "package:photos/models/search/recent_searches.dart"; import "package:photos/models/search/search_result.dart"; import "package:photos/models/search/search_types.dart"; @@ -177,6 +178,9 @@ class _SearchSectionAllPageState extends State { as Map, heroTag: "searchable_item" + magicSectionResult.heroTag(), + magicFilter: magicSectionResult + .getHierarchicalSearchFilter() + as MagicFilter, ), ); }, diff --git a/mobile/lib/ui/viewer/search_tab/locations_section.dart b/mobile/lib/ui/viewer/search_tab/locations_section.dart index e0c890752c..3ecf6e5515 100644 --- a/mobile/lib/ui/viewer/search_tab/locations_section.dart +++ b/mobile/lib/ui/viewer/search_tab/locations_section.dart @@ -383,7 +383,7 @@ class GoToMapWithBG extends StatelessWidget { Navigator.of(context).push( MaterialPageRoute( builder: (context) => MapScreen( - filesFutureFn: SearchService.instance.getAllFiles, + filesFutureFn: SearchService.instance.getAllFilesForSearch, ), ), ); diff --git a/mobile/lib/ui/viewer/search_tab/people_section.dart b/mobile/lib/ui/viewer/search_tab/people_section.dart index 33e7a6740e..f118e101c3 100644 --- a/mobile/lib/ui/viewer/search_tab/people_section.dart +++ b/mobile/lib/ui/viewer/search_tab/people_section.dart @@ -6,7 +6,6 @@ import "package:photos/core/constants.dart"; import "package:photos/events/event.dart"; import "package:photos/models/file/file.dart"; import "package:photos/models/ml/face/person.dart"; -import "package:photos/models/search/album_search_result.dart"; import "package:photos/models/search/generic_search_result.dart"; import "package:photos/models/search/recent_searches.dart"; import "package:photos/models/search/search_constants.dart"; @@ -213,25 +212,13 @@ class SearchExample extends StatelessWidget { return GestureDetector( onTap: () { RecentSearches().add(searchResult.name()); - - if (searchResult is GenericSearchResult) { - final genericSearchResult = searchResult as GenericSearchResult; - if (genericSearchResult.onResultTap != null) { - genericSearchResult.onResultTap!(context); - } else { - routeToPage( - context, - SearchResultPage(searchResult), - ); - } - } else if (searchResult is AlbumSearchResult) { - final albumSearchResult = searchResult as GenericSearchResult; + final genericSearchResult = searchResult as GenericSearchResult; + if (genericSearchResult.onResultTap != null) { + genericSearchResult.onResultTap!(context); + } else { routeToPage( context, - SearchResultPage( - albumSearchResult, - tagPrefix: albumSearchResult.heroTag(), - ), + SearchResultPage(searchResult), ); } }, @@ -278,10 +265,22 @@ class SearchExample extends StatelessWidget { if (result != null && result is (PersonEntity, EnteFile)) { // ignore: unawaited_futures - routeToPage(context, PeoplePage(person: result.$1)); + routeToPage( + context, + PeoplePage( + person: result.$1, + searchResult: null, + ), + ); } else if (result != null && result is PersonEntity) { // ignore: unawaited_futures - routeToPage(context, PeoplePage(person: result)); + routeToPage( + context, + PeoplePage( + person: result, + searchResult: null, + ), + ); } }, child: Padding( diff --git a/mobile/lib/ui/viewer/search_tab/search_tab.dart b/mobile/lib/ui/viewer/search_tab/search_tab.dart index 650eb1be11..46b25614a7 100644 --- a/mobile/lib/ui/viewer/search_tab/search_tab.dart +++ b/mobile/lib/ui/viewer/search_tab/search_tab.dart @@ -9,6 +9,7 @@ import "package:photos/models/search/index_of_indexed_stack.dart"; import "package:photos/models/search/search_result.dart"; import "package:photos/models/search/search_types.dart"; import "package:photos/service_locator.dart"; +import "package:photos/services/user_remote_flag_service.dart"; import "package:photos/states/all_sections_examples_state.dart"; import "package:photos/ui/common/loading_widget.dart"; import "package:photos/ui/viewer/search/result/no_result_widget.dart"; @@ -115,7 +116,9 @@ class _AllSearchSectionsState extends State { itemBuilder: (context, index) { switch (searchTypes[index]) { case SectionType.face: - if (!localSettings.isMLIndexingEnabled) { + if (!userRemoteFlagService.getCachedBoolValue( + UserRemoteFlagService.mlEnabled, + )) { return const SizedBox.shrink(); } return PeopleSection( diff --git a/mobile/lib/utils/date_time_util.dart b/mobile/lib/utils/date_time_util.dart index d60cd5d79f..afcd92aa16 100644 --- a/mobile/lib/utils/date_time_util.dart +++ b/mobile/lib/utils/date_time_util.dart @@ -195,7 +195,7 @@ DateTime? parseDateTimeFromFileNameV2( } } else if (countOfHyphen == 2) { valForParser = val.replaceAll(".", ":"); - } else if (countOfHyphen == 6) { + } else if (countOfHyphen == 6 || countOfHyphen == 7) { final splits = val.split("-"); valForParser = "${splits[0]}${splits[1]}${splits[2]}T${splits[3]}${splits[4]}${splits[5]}"; diff --git a/mobile/lib/utils/file_util.dart b/mobile/lib/utils/file_util.dart index 35240a3cc6..8b0f76669f 100644 --- a/mobile/lib/utils/file_util.dart +++ b/mobile/lib/utils/file_util.dart @@ -377,3 +377,13 @@ class _LivePhoto { _LivePhoto(this.image, this.video); } + +Set filesToUploadedFileIDs(List files) { + final uploadedFileIDs = {}; + for (final file in files) { + if (file.isUploaded) { + uploadedFileIDs.add(file.uploadedFileID!); + } + } + return uploadedFileIDs; +} diff --git a/mobile/lib/utils/hierarchical_search_util.dart b/mobile/lib/utils/hierarchical_search_util.dart new file mode 100644 index 0000000000..1d8198943c --- /dev/null +++ b/mobile/lib/utils/hierarchical_search_util.dart @@ -0,0 +1,594 @@ +import "package:flutter/material.dart"; +import "package:logging/logging.dart"; +import "package:photos/core/configuration.dart"; +import "package:photos/core/constants.dart"; +import "package:photos/db/files_db.dart"; +import "package:photos/db/ml/db.dart"; +import "package:photos/generated/l10n.dart"; +import "package:photos/models/file/file.dart"; +import "package:photos/models/file/file_type.dart"; +import "package:photos/models/location_tag/location_tag.dart"; +import "package:photos/models/ml/face/person.dart"; +import "package:photos/models/search/hierarchical/album_filter.dart"; +import "package:photos/models/search/hierarchical/contacts_filter.dart"; +import "package:photos/models/search/hierarchical/face_filter.dart"; +import "package:photos/models/search/hierarchical/file_type_filter.dart"; +import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart"; +import "package:photos/models/search/hierarchical/location_filter.dart"; +import "package:photos/models/search/hierarchical/magic_filter.dart"; +import "package:photos/models/search/hierarchical/only_them_filter.dart"; +import "package:photos/models/search/hierarchical/top_level_generic_filter.dart"; +import "package:photos/service_locator.dart"; +import "package:photos/services/collections_service.dart"; +import "package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart"; +import "package:photos/services/machine_learning/face_ml/person/person_service.dart"; +import "package:photos/services/magic_cache_service.dart"; +import "package:photos/services/search_service.dart"; +import "package:photos/ui/viewer/gallery/state/search_filter_data_provider.dart"; +import "package:photos/utils/file_util.dart"; + +Future> getFilteredFiles( + List filters, +) async { + final logger = Logger("HierarchicalSearchUtil"); + late final List filteredFiles; + final files = await SearchService.instance.getAllFilesForHierarchicalSearch(); + final resultsNeverComputedFilters = []; + final ignoredCollections = + CollectionsService.instance.getHiddenCollectionIds(); + + logger.info("Getting filtered files for Filters: $filters"); + for (HierarchicalSearchFilter filter in filters) { + if (filter is FaceFilter && filter.matchedUploadedIDs.isEmpty) { + try { + if (filter.personId != null) { + final fileIDs = await MLDataDB.instance.getFileIDsOfPersonID( + filter.personId!, + ); + filter.matchedUploadedIDs.addAll(fileIDs); + } else if (filter.clusterId != null) { + final fileIDs = await MLDataDB.instance.getFileIDsOfClusterID( + filter.clusterId!, + ); + filter.matchedUploadedIDs.addAll(fileIDs); + } + } catch (e) { + logger.severe("Error in filtering face filter: $e"); + } + } else if (filter is OnlyThemFilter && filter.matchedUploadedIDs.isEmpty) { + try { + late Set intersectionOfSelectedFaceFiltersFileIDs; + final selectedClusterIDs = []; + final selectedPersonIDs = []; + int index = 0; + + for (final faceFilter in filter.faceFilters) { + if (index == 0) { + intersectionOfSelectedFaceFiltersFileIDs = + faceFilter.matchedUploadedIDs; + } else { + intersectionOfSelectedFaceFiltersFileIDs = + intersectionOfSelectedFaceFiltersFileIDs + .intersection(faceFilter.matchedUploadedIDs); + } + index++; + + if (faceFilter.clusterId != null) { + selectedClusterIDs.add(faceFilter.clusterId!); + } else { + selectedPersonIDs.add(faceFilter.personId!); + } + } + + await MLDataDB.instance + .getPersonsClusterIDs(selectedPersonIDs) + .then((clusterIDs) { + selectedClusterIDs.addAll(clusterIDs); + }); + + final fileIDsToAvoid = + await MLDataDB.instance.getAllFilesAssociatedWithAllClusters( + exceptClusters: selectedClusterIDs, + ); + + final filesOfFaceIDsNotInAnyCluster = + await MLDataDB.instance.getAllFileIDsOfFaceIDsNotInAnyCluster(); + + fileIDsToAvoid.addAll(filesOfFaceIDsNotInAnyCluster); + + final result = + intersectionOfSelectedFaceFiltersFileIDs.difference(fileIDsToAvoid); + filter.matchedUploadedIDs.addAll(result); + } catch (e) { + logger.severe("Error in filtering only them filter: $e"); + } + } else if (filter.matchedUploadedIDs.isEmpty) { + resultsNeverComputedFilters.add(filter); + } + } + + try { + for (EnteFile file in files) { + if (file.uploadedFileID == null || file.uploadedFileID == -1) { + continue; + } + for (HierarchicalSearchFilter filter in resultsNeverComputedFilters) { + if (filter.isMatch(file)) { + filter.matchedUploadedIDs.add(file.uploadedFileID!); + } + } + } + + Set filteredUploadedIDs = {}; + for (int i = 0; i < filters.length; i++) { + if (i == 0) { + filteredUploadedIDs = + filteredUploadedIDs.union(filters[i].matchedUploadedIDs); + } else { + filteredUploadedIDs = + filteredUploadedIDs.intersection(filters[i].matchedUploadedIDs); + } + } + + filteredFiles = await FilesDB.instance.getFilesFromIDs( + filteredUploadedIDs.toList(), + dedupeByUploadId: true, + collectionsToIgnore: ignoredCollections, + ); + } catch (e) { + Logger("HierarchicalSearchUtil").severe("Failed to get filtered files: $e"); + } + + return filteredFiles; +} + +Future curateFilters( + SearchFilterDataProvider searchFilterDataProvider, + List files, + BuildContext context, +) async { + try { + final albumFilters = await _curateAlbumFilters(files); + final fileTypeFilters = _curateFileTypeFilters(files, context); + final locationFilters = await _curateLocationFilters( + files, + ); + final contactsFilters = _curateContactsFilter(files); + final faceFilters = await curateFaceFilters(files); + final magicFilters = await curateMagicFilters(files); + final onlyThemFilter = getOnlyThemFilter( + searchFilterDataProvider, + context, + ); + + searchFilterDataProvider.clearAndAddRecommendations( + [ + ...onlyThemFilter, + ...magicFilters, + ...faceFilters, + ...fileTypeFilters, + ...contactsFilters, + ...albumFilters, + ...locationFilters, + ], + ); + } catch (e) { + Logger("HierarchicalSearchUtil").severe("Failed to curate filters", e); + } +} + +List getOnlyThemFilter( + SearchFilterDataProvider searchFilterDataProvider, + BuildContext context, +) { + if (searchFilterDataProvider.initialGalleryFilter is FaceFilter && + searchFilterDataProvider.appliedFilters.isEmpty) { + return [ + OnlyThemFilter( + faceFilters: [ + searchFilterDataProvider.initialGalleryFilter as FaceFilter, + ], + onlyThemString: S.of(context).onlyThem, + occurrence: kMostRelevantFilter, + ), + ]; + } + + final appliedFaceFilters = + searchFilterDataProvider.appliedFilters.whereType().toList(); + if (appliedFaceFilters.isEmpty || appliedFaceFilters.length > 4) { + return []; + } else { + final onlyThemFilter = OnlyThemFilter( + faceFilters: appliedFaceFilters, + onlyThemString: S.of(context).onlyThem, + occurrence: kMostRelevantFilter, + ); + return [onlyThemFilter]; + } +} + +Future> _curateAlbumFilters( + List files, +) async { + final albumFilters = []; + final idToOccurrence = {}; + final uploadedIDs = []; + for (EnteFile file in files) { + if (file.uploadedFileID != null && file.uploadedFileID != -1) { + uploadedIDs.add(file.uploadedFileID!); + } + } + final collectionIDsOfFiles = + await FilesDB.instance.getAllCollectionIDsOfFiles(uploadedIDs); + + for (int collectionID in collectionIDsOfFiles) { + idToOccurrence[collectionID] = (idToOccurrence[collectionID] ?? 0) + 1; + } + + for (int id in idToOccurrence.keys) { + final collection = CollectionsService.instance.getCollectionByID(id); + if (collection == null) { + continue; + } + albumFilters.add( + AlbumFilter( + collectionID: id, + albumName: collection.displayName, + occurrence: idToOccurrence[id]!, + ), + ); + } + + return albumFilters; +} + +List _curateFileTypeFilters( + List files, + BuildContext context, +) { + final fileTypeFilters = []; + int photosCount = 0; + int videosCount = 0; + int livePhotosCount = 0; + + for (EnteFile file in files) { + final id = file.uploadedFileID; + if (id != null && id != -1) { + if (file.fileType == FileType.image) { + photosCount++; + } else if (file.fileType == FileType.video) { + videosCount++; + } else if (file.fileType == FileType.livePhoto) { + livePhotosCount++; + } + } + } + + if (photosCount > 0) { + fileTypeFilters.add( + FileTypeFilter( + fileType: FileType.image, + typeName: S.of(context).photos, + occurrence: photosCount, + ), + ); + } + if (videosCount > 0) { + fileTypeFilters.add( + FileTypeFilter( + fileType: FileType.video, + typeName: S.of(context).videos, + occurrence: videosCount, + ), + ); + } + if (livePhotosCount > 0) { + fileTypeFilters.add( + FileTypeFilter( + fileType: FileType.livePhoto, + typeName: S.of(context).livePhotos, + occurrence: livePhotosCount, + ), + ); + } + + return fileTypeFilters; +} + +Future> _curateLocationFilters( + List files, +) async { + final locationFilters = []; + final locationTagToOccurrence = + await locationService.getLocationTagsToOccurance(files); + + for (LocationTag locationTag in locationTagToOccurrence.keys) { + locationFilters.add( + LocationFilter( + locationTag: locationTag, + occurrence: locationTagToOccurrence[locationTag]!, + ), + ); + } + + return locationFilters; +} + +List _curateContactsFilter( + List files, +) { + final contactsFilters = []; + final ownerIdToOccurrence = {}; + + for (EnteFile file in files) { + if (file.ownerID == Configuration.instance.getUserID() || + file.uploadedFileID == null || + file.uploadedFileID == -1 || + file.ownerID == null) continue; + ownerIdToOccurrence[file.ownerID!] = + (ownerIdToOccurrence[file.ownerID] ?? 0) + 1; + } + + for (int id in ownerIdToOccurrence.keys) { + final user = CollectionsService.instance.getFileOwner(id, null); + contactsFilters.add( + ContactsFilter( + user: user, + occurrence: ownerIdToOccurrence[id]!, + ), + ); + } + + return contactsFilters; +} + +Future> curateFaceFilters( + List files, +) async { + try { + final faceFilters = []; + final Map> fileIdToClusterID = + await MLDataDB.instance.getFileIdToClusterIds(); + final Map personIdToPerson = + await PersonService.instance.getPersonsMap(); + final clusterIDToPersonID = + await MLDataDB.instance.getClusterIDToPersonID(); + + final Map> clusterIdToFiles = {}; + final Map> personIdToFiles = {}; + for (final f in files) { + if (!fileIdToClusterID.containsKey(f.uploadedFileID ?? -1)) { + continue; + } + final clusterIds = fileIdToClusterID[f.uploadedFileID ?? -1]!; + for (final clusterId in clusterIds) { + final PersonEntity? p = + personIdToPerson[clusterIDToPersonID[clusterId] ?? ""]; + if (p != null) { + if (personIdToFiles.containsKey(p.remoteID)) { + personIdToFiles[p.remoteID]!.add(f); + } else { + personIdToFiles[p.remoteID] = [f]; + } + } else { + if (clusterIdToFiles.containsKey(clusterId)) { + clusterIdToFiles[clusterId]!.add(f); + } else { + clusterIdToFiles[clusterId] = [f]; + } + } + } + } + + for (final personID in personIdToFiles.keys) { + final files = personIdToFiles[personID]!; + if (files.isEmpty) { + continue; + } + final PersonEntity p = personIdToPerson[personID]!; + if (p.data.isIgnored) continue; + + faceFilters.add( + FaceFilter( + personId: personID, + clusterId: null, + faceName: p.data.name, + faceFile: files.first, + occurrence: files.length, + ), + ); + } + + for (final clusterId in clusterIdToFiles.keys) { + final files = clusterIdToFiles[clusterId]!; + + if (clusterIDToPersonID[clusterId] != null) { + // This should not happen, means a faceID is assigned to multiple persons. + Logger("hierarchical_search_util").severe( + "`getAllFace`: Cluster $clusterId should not have person id ${clusterIDToPersonID[clusterId]}", + ); + } + if (files.length < kMinimumClusterSizeSearchResult) continue; + + faceFilters.add( + FaceFilter( + personId: null, + clusterId: clusterId, + faceName: null, + faceFile: files.first, + occurrence: files.length, + ), + ); + } + + return faceFilters; + } catch (e, s) { + Logger("hierarchical_search_util") + .severe("Error in curating face filters", e, s); + rethrow; + } +} + +Future> curateMagicFilters(List files) async { + final magicFilters = []; + + final magicCaches = await magicCacheService.getMagicCache(); + final filesUploadedFileIDs = filesToUploadedFileIDs(files); + for (MagicCache magicCache in magicCaches) { + final uploadedIDs = magicCache.fileUploadedIDs.toSet(); + final intersection = uploadedIDs.intersection(filesUploadedFileIDs); + + if (intersection.length > 3) { + magicFilters.add( + MagicFilter( + filterName: magicCache.title, + occurrence: intersection.length, + matchedUploadedIDs: magicCache.fileUploadedIDs.toSet(), + ), + ); + } + } + + return magicFilters; +} + +Map> getFiltersForBottomSheet( + SearchFilterDataProvider searchFilterDataProvider, +) { + final onlyThemFilter = searchFilterDataProvider.appliedFilters + .whereType() + .toList(); + onlyThemFilter.addAll( + searchFilterDataProvider.recommendations.whereType(), + ); + + final faceFilters = + searchFilterDataProvider.appliedFilters.whereType().toList(); + faceFilters + .addAll(searchFilterDataProvider.recommendations.whereType()); + + final albumFilters = + searchFilterDataProvider.appliedFilters.whereType().toList(); + albumFilters.addAll( + searchFilterDataProvider.recommendations.whereType(), + ); + + final fileTypeFilters = searchFilterDataProvider.appliedFilters + .whereType() + .toList(); + fileTypeFilters.addAll( + searchFilterDataProvider.recommendations.whereType(), + ); + + final locationFilters = searchFilterDataProvider.appliedFilters + .whereType() + .toList(); + locationFilters.addAll( + searchFilterDataProvider.recommendations.whereType(), + ); + + final contactsFilters = searchFilterDataProvider.appliedFilters + .whereType() + .toList(); + contactsFilters.addAll( + searchFilterDataProvider.recommendations.whereType(), + ); + + final magicFilters = + searchFilterDataProvider.appliedFilters.whereType().toList(); + magicFilters.addAll( + searchFilterDataProvider.recommendations.whereType(), + ); + + final topLevelGenericFilter = searchFilterDataProvider.appliedFilters + .whereType() + .toList(); + + return { + "onlyThemFilter": onlyThemFilter, + "faceFilters": faceFilters, + "magicFilters": magicFilters, + "locationFilters": locationFilters, + "contactsFilters": contactsFilters, + "albumFilters": albumFilters, + "fileTypeFilters": fileTypeFilters, + "topLevelGenericFilter": topLevelGenericFilter, + }; +} + +List getRecommendedFiltersForAppBar( + SearchFilterDataProvider searchFilterDataProvider, +) { + final recommendations = searchFilterDataProvider.recommendations; + + final mostRelevantFilterFromEachType = []; + int index = 0; + final totalRecommendations = recommendations.length; + + // Add the most relevant filter from each type available in the first half of + // the recommendations list + for (final filter in recommendations) { + if (mostRelevantFilterFromEachType + .every((element) => element.runtimeType != filter.runtimeType)) { + mostRelevantFilterFromEachType.add(filter); + } + + if (mostRelevantFilterFromEachType.length == + (FilterTypeNames.values.length) || + (index + 1) / totalRecommendations > 0.5) { + break; + } + index++; + } + + final curatedRecommendations = [ + ...mostRelevantFilterFromEachType, + ]; + for (HierarchicalSearchFilter recommendation in recommendations) { + if (curatedRecommendations.length >= kMaxAppbarFilters) { + break; + } + if (mostRelevantFilterFromEachType.every( + (element) => !element.isSameFilter(recommendation), + )) { + curatedRecommendations.add(recommendation); + } + } + + final faceReccos = []; + final magicReccos = []; + final locationReccos = []; + final contactsReccos = []; + final albumReccos = []; + final fileTypeReccos = []; + final onlyThemFilter = []; + + for (var recommendation in curatedRecommendations) { + if (recommendation is OnlyThemFilter) { + onlyThemFilter.add(recommendation); + } else if (recommendation is FaceFilter) { + faceReccos.add(recommendation); + } else if (recommendation is MagicFilter) { + magicReccos.add(recommendation); + } else if (recommendation is LocationFilter) { + locationReccos.add(recommendation); + } else if (recommendation is ContactsFilter) { + contactsReccos.add(recommendation); + } else if (recommendation is AlbumFilter) { + albumReccos.add(recommendation); + } else if (recommendation is FileTypeFilter) { + fileTypeReccos.add(recommendation); + } + } + + return [ + ...onlyThemFilter, + ...faceReccos, + ...magicReccos, + ...locationReccos, + ...contactsReccos, + ...albumReccos, + ...fileTypeReccos, + ]; +} diff --git a/mobile/lib/utils/local_settings.dart b/mobile/lib/utils/local_settings.dart index 1ea9c4af95..e293375653 100644 --- a/mobile/lib/utils/local_settings.dart +++ b/mobile/lib/utils/local_settings.dart @@ -1,4 +1,5 @@ import 'package:photos/core/constants.dart'; +import "package:photos/utils/ram_check_util.dart"; import 'package:shared_preferences/shared_preferences.dart'; enum AlbumSortKey { @@ -10,7 +11,7 @@ enum AlbumSortKey { class LocalSettings { static const kCollectionSortPref = "collection_sort_pref"; static const kPhotoGridSize = "photo_grid_size"; - static const _kisMLIndexingEnabled = "ls.enable_ml_idx"; + static const _kisMLLocalIndexingEnabled = "ls.ml_local_indexing"; static const kRateUsShownCount = "rate_us_shown_count"; static const kEnableMultiplePart = "ls.enable_multiple_part"; static const kRateUsPromptThreshold = 2; @@ -57,11 +58,8 @@ class LocalSettings { return getRateUsShownCount() < kRateUsPromptThreshold; } - // remove `enable_face_indexing`fallback after sometime, affects internal users only - bool get isMLIndexingEnabled => - _prefs.getBool(_kisMLIndexingEnabled) ?? - _prefs.getBool('enable_face_indexing') ?? - false; + bool get isMLLocalIndexingEnabled => + _prefs.getBool(_kisMLLocalIndexingEnabled) ?? enoughRamForLocalIndexing; bool get userEnabledMultiplePart => _prefs.getBool(kEnableMultiplePart) ?? false; @@ -72,9 +70,9 @@ class LocalSettings { } /// toggleFaceIndexing toggles the face indexing setting and returns the new value - Future toggleMLIndexing() async { - await _prefs.setBool(_kisMLIndexingEnabled, !isMLIndexingEnabled); - return isMLIndexingEnabled; + Future toggleLocalMLIndexing() async { + await _prefs.setBool(_kisMLLocalIndexingEnabled, !isMLLocalIndexingEnabled); + return isMLLocalIndexingEnabled; } //#region todo:(NG) remove this section, only needed for internal testing to see diff --git a/mobile/lib/utils/ml_util.dart b/mobile/lib/utils/ml_util.dart index 3818821a6b..788ae313c2 100644 --- a/mobile/lib/utils/ml_util.dart +++ b/mobile/lib/utils/ml_util.dart @@ -7,6 +7,7 @@ import "package:photos/core/configuration.dart"; import "package:photos/db/files_db.dart"; import "package:photos/db/ml/clip_db.dart"; import "package:photos/db/ml/db.dart"; +import "package:photos/db/ml/filedata.dart"; import "package:photos/extensions/list.dart"; import "package:photos/models/file/extensions/file_props.dart"; import "package:photos/models/file/file.dart"; @@ -87,8 +88,11 @@ Future> getFilesForMlIndexing() async { await MLDataDB.instance.clipIndexedFileWithVersion(); final Set queuedFiledIDs = {}; + final Set filesWithFDStatus = + await MLDataDB.instance.getFileIDsWithFDData(); + // Get all regular files and all hidden files - final enteFiles = await SearchService.instance.getAllFiles(); + final enteFiles = await SearchService.instance.getAllFilesForSearch(); final hiddenFiles = await SearchService.instance.getHiddenFiles(); // Sort out what should be indexed and in what order @@ -149,10 +153,17 @@ Future> getFilesForMlIndexing() async { ...filesWithoutLocalID, ...hiddenFilesToIndex, ]; + final splitResult = sortedBylocalID.splitMatch( + (i) => filesWithFDStatus.contains(i.file.uploadedFileID!), + ); + _logger.info( "Getting list of files to index for ML took ${DateTime.now().difference(time).inMilliseconds} ms", ); - return sortedBylocalID; + if (!localSettings.isMLLocalIndexingEnabled) { + return splitResult.matched; + } + return [...splitResult.matched, ...splitResult.unmatched]; } Stream> fetchEmbeddingsAndInstructions( diff --git a/mobile/lib/utils/ram_check_util.dart b/mobile/lib/utils/ram_check_util.dart new file mode 100644 index 0000000000..f6f230fb84 --- /dev/null +++ b/mobile/lib/utils/ram_check_util.dart @@ -0,0 +1,13 @@ +import "package:system_info_plus/system_info_plus.dart"; + +/// The total amount of RAM in the device in MB +int? deviceTotalRAM; + +bool get enoughRamForLocalIndexing => + deviceTotalRAM == null || deviceTotalRAM! >= 5 * 1024; + +/// Return the total amount of RAM in the device in MB +Future checkDeviceTotalRAM() async { + deviceTotalRAM ??= await SystemInfoPlus.physicalMemory; // returns in MB + return deviceTotalRAM; +} diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index bfa149c66c..994a38a205 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -2395,6 +2395,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.3.0+3" + system_info_plus: + dependency: "direct main" + description: + name: system_info_plus + sha256: b915c811c6605b802f3988859bc2bb79c95f735762a75b5451741f7a2b949d1b + url: "https://pub.dev" + source: hosted + version: "0.0.5" term_glyph: dependency: transitive description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index c156af766f..03ca492576 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.53+953 +version: 0.9.58+958 publish_to: none environment: @@ -166,6 +166,7 @@ dependencies: syncfusion_flutter_core: ^25.2.5 syncfusion_flutter_sliders: ^25.2.5 synchronized: ^3.1.0 + system_info_plus: ^0.0.5 tuple: ^2.0.0 ua_client_hints: ^1.4.0 uni_links: ^0.5.1 diff --git a/mobile/test/utils/date_time_util_test.dart b/mobile/test/utils/date_time_util_test.dart index cfa3b7302a..5025299a1c 100644 --- a/mobile/test/utils/date_time_util_test.dart +++ b/mobile/test/utils/date_time_util_test.dart @@ -18,6 +18,7 @@ void main() { "Screenshot_2022-06-21-16-51-29-164_newFormat.heic", "Screenshot 20221106 211633.com.google.android.apps.nbu.paisa.user.jpg", "signal-2022-12-17-15-16-04-718.jpg", + "signal-2022-12-17-15-16-04-718-2.jpg", ]; for (String val in validParsing) { final parsedValue = parseDateTimeFromFileNameV2(val); diff --git a/server/cmd/museum/main.go b/server/cmd/museum/main.go index 6e15ad56b8..480d21d32b 100644 --- a/server/cmd/museum/main.go +++ b/server/cmd/museum/main.go @@ -424,6 +424,7 @@ func main() { privateAPI.GET("/files/preview/v2/:fileID", fileHandler.GetThumbnail) privateAPI.PUT("/files/data", fileHandler.PutFileData) + privateAPI.POST("/files/data/status-diff", fileHandler.FileDataStatusDiff) privateAPI.POST("/files/data/fetch", fileHandler.GetFilesData) privateAPI.GET("/files/data/fetch", fileHandler.GetFileData) privateAPI.GET("/files/data/preview-upload-url", fileHandler.GetPreviewUploadURL) diff --git a/server/ente/filedata/filedata.go b/server/ente/filedata/filedata.go index 3db26fefb0..534ff468da 100644 --- a/server/ente/filedata/filedata.go +++ b/server/ente/filedata/filedata.go @@ -12,6 +12,19 @@ type Entity struct { DecryptionHeader string `json:"decryptionHeader"` } +type FDDiffRequest struct { + LastUpdatedAt *int64 `form:"lastUpdated" binding:"required"` +} + +type FDStatus struct { + FileID int64 `json:"fileID" binding:"required"` + UserID int64 `json:"userID" binding:"required"` + Type ente.ObjectType `json:"type" binding:"required"` + IsDeleted bool `json:"isDeleted" binding:"required"` + Size int64 `json:"size" binding:"required"` + UpdatedAt int64 `json:"updatedAt" binding:"required"` +} + // GetFilesData should only be used for getting the preview video playlist and derived metadata. type GetFilesData struct { FileIDs []int64 `json:"fileIDs" binding:"required"` diff --git a/server/pkg/api/file_data.go b/server/pkg/api/file_data.go index 36c863e65c..5eeacf7f74 100644 --- a/server/pkg/api/file_data.go +++ b/server/pkg/api/file_data.go @@ -48,6 +48,28 @@ func (h *FileHandler) GetFilesData(ctx *gin.Context) { ctx.JSON(http.StatusOK, resp) } +// FileDataStatusDiff API won't really return status/diff for deleted files. The clients will primarily use this data to identify for which all files we already have preview generated or it's ML inference is done. +// This doesn't simulate perfect diff behaviour as we won't maintain a tombstone entries for the deleted API. +func (h *FileHandler) FileDataStatusDiff(ctx *gin.Context) { + var req fileData.FDDiffRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + ctx.JSON(http.StatusBadRequest, ente.NewBadRequestWithMessage(err.Error())) + return + } + if req.LastUpdatedAt == nil || *req.LastUpdatedAt < 0 { + ctx.JSON(http.StatusBadRequest, ente.NewBadRequestWithMessage("lastUpdated is required and should be greater than or equal to 0")) + return + } + diff, err := h.FileDataCtrl.FileDataStatusDiff(ctx, req) + if err != nil { + handler.Error(ctx, err) + return + } + ctx.JSON(http.StatusOK, gin.H{ + "diff": diff, + }) +} + func (h *FileHandler) GetFileData(ctx *gin.Context) { var req fileData.GetFileData if err := ctx.ShouldBindJSON(&req); err != nil { diff --git a/server/pkg/api/user.go b/server/pkg/api/user.go index b919572aba..f0ede26f2f 100644 --- a/server/pkg/api/user.go +++ b/server/pkg/api/user.go @@ -4,6 +4,8 @@ import ( "database/sql" "errors" "fmt" + "github.com/gin-contrib/requestid" + "github.com/sirupsen/logrus" "net/http" "strconv" "strings" @@ -340,6 +342,10 @@ func (h *UserHandler) FinishPasskeyAuthenticationCeremony(c *gin.Context) { err = h.UserController.PasskeyRepo.FinishAuthentication(&user, c.Request, uuid.MustParse(request.CeremonySessionID)) if err != nil { + reqID := requestid.Get(c) + logrus.WithField("req_id", reqID). + WithField("user_id", userID). + WithError(err).Error("Failed to finish passkey authentication ceremony") handler.Error(c, stacktrace.Propagate(err, "")) return } diff --git a/server/pkg/controller/filedata/controller.go b/server/pkg/controller/filedata/controller.go index 1c8465d870..2c5880251e 100644 --- a/server/pkg/controller/filedata/controller.go +++ b/server/pkg/controller/filedata/controller.go @@ -313,3 +313,8 @@ func (c *Controller) _validatePermission(ctx *gin.Context, fileID int64, actorID } return nil } + +func (c *Controller) FileDataStatusDiff(ctx *gin.Context, req fileData.FDDiffRequest) ([]fileData.FDStatus, error) { + userID := auth.GetUserID(ctx.Request.Header) + return c.Repo.GetFDForUser(ctx, userID, *req.LastUpdatedAt, 5000) +} diff --git a/server/pkg/controller/filedata/replicate.go b/server/pkg/controller/filedata/replicate.go index fa34aa2e9b..45b6786564 100644 --- a/server/pkg/controller/filedata/replicate.go +++ b/server/pkg/controller/filedata/replicate.go @@ -57,7 +57,7 @@ func (c *Controller) replicate(i int) { } func (c *Controller) tryReplicate() error { - newLockTime := enteTime.MicrosecondsAfterMinutes(60) + newLockTime := enteTime.MicrosecondsAfterMinutes(240) ctx, cancelFun := context.WithTimeout(context.Background(), 20*time.Minute) defer cancelFun() row, err := c.Repo.GetPendingSyncDataAndExtendLock(ctx, newLockTime, false) @@ -69,7 +69,12 @@ func (c *Controller) tryReplicate() error { } err = c.replicateRowData(ctx, *row) if err != nil { - log.Errorf("Could not delete file data: %s", err) + log.WithFields(log.Fields{ + "file_id": row.FileID, + "type": row.Type, + "size": row.Size, + "userID": row.UserID, + }).Errorf("Could not replicate file data: %s", err) return err } else { // If the replication was completed without any errors, we can reset the lock time diff --git a/server/pkg/repo/filedata/repository.go b/server/pkg/repo/filedata/repository.go index ae024e5d2b..3af9158613 100644 --- a/server/pkg/repo/filedata/repository.go +++ b/server/pkg/repo/filedata/repository.go @@ -24,11 +24,13 @@ const ( ) func (r *Repository) InsertOrUpdate(ctx context.Context, data filedata.Row) error { + // During insert, we set the sync_locked_till to 5 minutes in the future. This is to prevent + // immediate replication of the file data row, that can result in failure of update/retry requests query := ` INSERT INTO file_data - (file_id, user_id, data_type, size, latest_bucket) + (file_id, user_id, data_type, size, latest_bucket, sync_locked_till) VALUES - ($1, $2, $3, $4, $5) + ($1, $2, $3, $4, $5, now_utc_micro_seconds() + 5 * 60 * 1000*1000) ON CONFLICT (file_id, data_type) DO UPDATE SET size = EXCLUDED.size, @@ -124,6 +126,26 @@ func (r *Repository) RemoveBucket(row filedata.Row, bucketID string, columnName return nil } +func (r *Repository) GetFDForUser(ctx context.Context, userID int64, lastUpdatedAt int64, limit int64) ([]filedata.FDStatus, error) { + rows, err := r.DB.QueryContext(ctx, `SELECT file_id, user_id, data_type, size, is_deleted, updated_at + FROM file_data + WHERE user_id = $1 AND updated_at > $2 ORDER BY updated_at + LIMIT $3`, userID, lastUpdatedAt, limit) + if err != nil { + return nil, stacktrace.Propagate(err, "") + } + var fdStatuses []filedata.FDStatus + for rows.Next() { + var status filedata.FDStatus + scanErr := rows.Scan(&status.FileID, &status.UserID, &status.Type, &status.Size, &status.IsDeleted, &status.UpdatedAt) + if scanErr != nil { + return nil, stacktrace.Propagate(scanErr, "") + } + fdStatuses = append(fdStatuses, status) + } + return fdStatuses, nil +} + func (r *Repository) MoveBetweenBuckets(row filedata.Row, bucketID string, sourceColumn string, destColumn string) error { query := fmt.Sprintf(` UPDATE file_data diff --git a/server/pkg/repo/public_collection.go b/server/pkg/repo/public_collection.go index 6c6106a77a..91b96fca78 100644 --- a/server/pkg/repo/public_collection.go +++ b/server/pkg/repo/public_collection.go @@ -11,7 +11,7 @@ import ( "github.com/lib/pq" ) -const BaseShareURL = "https://albums.ente.io?t=%s" +const BaseShareURL = "https://albums.ente.io/?t=%s" // PublicCollectionRepository defines the methods for inserting, updating and // retrieving entities related to public collections @@ -32,7 +32,7 @@ func NewPublicCollectionRepository(db *sql.DB, albumHost string) *PublicCollecti } func (pcr *PublicCollectionRepository) GetAlbumUrl(token string) string { - return fmt.Sprintf("%s?t=%s", pcr.albumHost, token) + return fmt.Sprintf("%s/?t=%s", pcr.albumHost, token) } func (pcr *PublicCollectionRepository) Insert(ctx context.Context, diff --git a/web/apps/accounts/src/pages/_app.tsx b/web/apps/accounts/src/pages/_app.tsx index e52d4abc28..3b425cb965 100644 --- a/web/apps/accounts/src/pages/_app.tsx +++ b/web/apps/accounts/src/pages/_app.tsx @@ -2,12 +2,12 @@ import { staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; import { AttributedMiniDialog } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; +import { Overlay } from "@/base/components/mui/Container"; import { AppNavbar } from "@/base/components/Navbar"; import { useAttributedMiniDialog } from "@/base/components/utils/dialog"; import { setupI18n } from "@/base/i18n"; import { disableDiskLogs } from "@/base/log"; import { logUnhandledErrorsAndRejections } from "@/base/log-web"; -import { Overlay } from "@ente/shared/components/Container"; import { getTheme } from "@ente/shared/themes"; import { THEME_COLOR } from "@ente/shared/themes/constants"; import { CssBaseline } from "@mui/material"; diff --git a/web/apps/accounts/src/pages/passkeys/index.tsx b/web/apps/accounts/src/pages/passkeys/index.tsx index 485fdf841d..ce1b928ddc 100644 --- a/web/apps/accounts/src/pages/passkeys/index.tsx +++ b/web/apps/accounts/src/pages/passkeys/index.tsx @@ -1,5 +1,5 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemDivider, MenuItemGroup } from "@/base/components/Menu"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { Titlebar } from "@/base/components/Titlebar"; import { errorDialogAttributes } from "@/base/components/utils/dialog"; import log from "@/base/log"; @@ -283,7 +283,7 @@ const ManagePasskeyDrawer: React.FC = ({ return ( <> - + {token && passkey && ( = ({ )} - + {token && passkey && ( void; - finishLoading: () => void; themeColor: THEME_COLOR; setThemeColor: (themeColor: THEME_COLOR) => void; somethingWentWrong: () => void; @@ -68,8 +59,6 @@ const App: React.FC = ({ Component, pageProps }) => { typeof window !== "undefined" && !window.navigator.onLine, ); const [showNavbar, setShowNavBar] = useState(false); - const isLoadingBarRunning = useRef(false); - const loadingBar = useRef(null); const { showMiniDialog, miniDialogProps } = useAttributedMiniDialog(); const [themeColor, setThemeColor] = useLocalState( @@ -113,18 +102,6 @@ const App: React.FC = ({ Component, pageProps }) => { const showNavBar = (show: boolean) => setShowNavBar(show); - const startLoading = () => { - !isLoadingBarRunning.current && loadingBar.current?.continuousStart(); - isLoadingBarRunning.current = true; - }; - - const finishLoading = () => { - setTimeout(() => { - isLoadingBarRunning.current && loadingBar.current?.complete(); - isLoadingBarRunning.current = false; - }, 100); - }; - const somethingWentWrong = () => showMiniDialog(genericErrorDialogAttributes()); @@ -136,8 +113,6 @@ const App: React.FC = ({ Component, pageProps }) => { logout, showNavBar, showMiniDialog, - startLoading, - finishLoading, themeColor, setThemeColor, somethingWentWrong, @@ -156,8 +131,6 @@ const App: React.FC = ({ Component, pageProps }) => { {isI18nReady && offline && t("OFFLINE_MSG")} - - diff --git a/web/apps/photos/package.json b/web/apps/photos/package.json index 76f9bf1d8e..ad2f3323d2 100644 --- a/web/apps/photos/package.json +++ b/web/apps/photos/package.json @@ -5,6 +5,7 @@ "dependencies": { "@/accounts": "*", "@/base": "*", + "@/gallery": "*", "@/media": "*", "@/new": "*", "@ente/eslint-config": "*", @@ -24,12 +25,10 @@ "ml-matrix": "^6.11", "p-debounce": "^4.0.0", "photoswipe": "file:./thirdparty/photoswipe", - "piexifjs": "^1.0.6", "pure-react-carousel": "^1.30.1", "react-dropzone": "^14.2", - "react-otp-input": "^2.3.1", "react-select": "^5.8.0", - "react-top-loading-bar": "^2.0.1", + "react-top-loading-bar": "^2.3.1", "react-virtualized-auto-sizer": "^1.0", "react-window": "^1.8.10", "sanitize-filename": "^1.6.3", diff --git a/web/apps/photos/public/.well-known/assetlinks.json b/web/apps/photos/public/.well-known/assetlinks.json index 555a572373..292dbcfdaf 100644 --- a/web/apps/photos/public/.well-known/assetlinks.json +++ b/web/apps/photos/public/.well-known/assetlinks.json @@ -47,7 +47,7 @@ "namespace": "android_app", "package_name": "io.ente.photos", "sha256_cert_fingerprints": [ - "35:ED:56:81:B7:0B:B3:BD:35:D9:0D:85:6A:F5:69:4C:50:4D:EF:46:AA:D8:3F:77:7B:1C:67:5C:F4:51:35:0B" + "37:D4:0B:10:3B:BF:86:43:EB:AE:23:B3:BB:73:F8:65:B4:E9:3A:BF:65:45:EF:37:12:8A:4C:EA:5B:C2:7E:2E" ] } }, @@ -57,7 +57,7 @@ "namespace": "android_app", "package_name": "io.ente.photos.independent", "sha256_cert_fingerprints": [ - "35:ED:56:81:B7:0B:B3:BD:35:D9:0D:85:6A:F5:69:4C:50:4D:EF:46:AA:D8:3F:77:7B:1C:67:5C:F4:51:35:0B" + "37:D4:0B:10:3B:BF:86:43:EB:AE:23:B3:BB:73:F8:65:B4:E9:3A:BF:65:45:EF:37:12:8A:4C:EA:5B:C2:7E:2E" ] } }, diff --git a/web/apps/photos/src/components/Collections/CollectionHeader.tsx b/web/apps/photos/src/components/Collections/CollectionHeader.tsx index 188d3dbdc4..706de41ac7 100644 --- a/web/apps/photos/src/components/Collections/CollectionHeader.tsx +++ b/web/apps/photos/src/components/Collections/CollectionHeader.tsx @@ -1,5 +1,6 @@ import { assertionFailed } from "@/base/assert"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; +import { SpaceBetweenFlex } from "@/base/components/mui/Container"; import { useModalVisibility } from "@/base/components/utils/modal"; import log from "@/base/log"; import type { Collection } from "@/media/collection"; @@ -8,7 +9,6 @@ import { GalleryItemsHeaderAdapter, GalleryItemsSummary, } from "@/new/photos/components/gallery/ListHeader"; -import { SpaceBetweenFlex } from "@/new/photos/components/mui"; import { ALL_SECTION, HIDDEN_ITEMS_SECTION, @@ -37,7 +37,8 @@ import LinkIcon from "@mui/icons-material/Link"; import LogoutIcon from "@mui/icons-material/Logout"; import MoreHoriz from "@mui/icons-material/MoreHoriz"; import PeopleIcon from "@mui/icons-material/People"; -import PushPinOutlined from "@mui/icons-material/PushPinOutlined"; +import PushPinIcon from "@mui/icons-material/PushPin"; +import PushPinOutlinedIcon from "@mui/icons-material/PushPinOutlined"; import SortIcon from "@mui/icons-material/Sort"; import TvIcon from "@mui/icons-material/Tv"; import Unarchive from "@mui/icons-material/Unarchive"; @@ -45,7 +46,6 @@ import VisibilityOffOutlined from "@mui/icons-material/VisibilityOffOutlined"; import VisibilityOutlined from "@mui/icons-material/VisibilityOutlined"; import { Box, IconButton, Stack, Tooltip } from "@mui/material"; import { SetCollectionNamerAttributes } from "components/Collections/CollectionNamer"; -import { UnPinIcon } from "components/icons/UnPinIcon"; import { t } from "i18next"; import { GalleryContext } from "pages/gallery"; import React, { useCallback, useContext, useRef } from "react"; @@ -141,7 +141,7 @@ const CollectionOptions: React.FC = ({ setFilesDownloadProgressAttributesCreator, isActiveCollectionDownloadInProgress, }) => { - const { startLoading, finishLoading, setDialogMessage } = + const { showLoadingBar, hideLoadingBar, setDialogMessage } = useContext(AppContext); const { syncWithRemote } = useContext(GalleryContext); const overFlowMenuIconRef = useRef(null); @@ -169,19 +169,19 @@ const CollectionOptions: React.FC = ({ const wrap = useCallback( (f: () => Promise) => { const wrapped = async () => { - startLoading(); + showLoadingBar(); try { await f(); } catch (e) { handleError(e); } finally { void syncWithRemote(false, true); - finishLoading(); + hideLoadingBar(); } }; return (): void => void wrapped(); }, - [handleError, syncWithRemote, startLoading, finishLoading], + [handleError, syncWithRemote, showLoadingBar, hideLoadingBar], ); const showRenameCollectionModal = () => { @@ -654,14 +654,14 @@ const AlbumCollectionOptions: React.FC = ({ {isPinned ? ( } + startIcon={} > {t("unpin_album")} ) : ( } + startIcon={} > {t("pin_album")} diff --git a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipant.tsx b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipant.tsx index d42243a813..563b6b62af 100644 --- a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipant.tsx +++ b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/AddParticipant.tsx @@ -1,4 +1,4 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { Titlebar } from "@/base/components/Titlebar"; import { COLLECTION_ROLE, type Collection } from "@/media/collection"; import { DialogProps, Stack } from "@mui/material"; @@ -87,38 +87,36 @@ export default function AddParticipant({ }; return ( - <> - - - - - - - + + + + + + ); } diff --git a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/ManageEmailShare.tsx b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/ManageEmailShare.tsx index caf6e732a5..23cb8a4d62 100644 --- a/web/apps/photos/src/components/Collections/CollectionShare/emailShare/ManageEmailShare.tsx +++ b/web/apps/photos/src/components/Collections/CollectionShare/emailShare/ManageEmailShare.tsx @@ -1,9 +1,9 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemDivider, MenuItemGroup, MenuSectionTitle, } from "@/base/components/Menu"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { Titlebar } from "@/base/components/Titlebar"; import { COLLECTION_ROLE, @@ -41,7 +41,7 @@ export default function ManageEmailShare({ onRootClose, peopleCount, }: Iprops) { - const appContext = useContext(AppContext); + const { showLoadingBar, hideLoadingBar } = useContext(AppContext); const galleryContext = useContext(GalleryContext); const [addParticipantView, setAddParticipantView] = useState(false); @@ -80,11 +80,11 @@ export default function ManageEmailShare({ const collectionUnshare = async (email: string) => { try { - appContext.startLoading(); + showLoadingBar(); await unshareCollection(collection, email); await galleryContext.syncWithRemote(false, true); } finally { - appContext.finishLoading(); + hideLoadingBar(); } }; @@ -116,7 +116,11 @@ export default function ManageEmailShare({ return ( <> - + - + - - - + + + - - + + + + {t("ADDED_AS")} + + + + } + endIcon={ + selectedParticipant.role === + "COLLABORATOR" && + } + /> + + + } + endIcon={ + selectedParticipant.role === "VIEWER" && ( + + ) + } + /> + + + + {t("COLLABORATOR_RIGHTS")} + + + - {t("ADDED_AS")} + {t("REMOVE_PARTICIPANT_HEAD")} } - endIcon={ - selectedParticipant.role === - "COLLABORATOR" && - } - /> - - - } - endIcon={ - selectedParticipant.role === - "VIEWER" && - } + onClick={removeParticipant} + label={"Remove"} + startIcon={} /> - - - {t("COLLABORATOR_RIGHTS")} - - - - - {t("REMOVE_PARTICIPANT_HEAD")} - - - - } - /> - - - - + + ); } diff --git a/web/apps/photos/src/components/Collections/CollectionShare/index.tsx b/web/apps/photos/src/components/Collections/CollectionShare/index.tsx index 5fda2e00c8..a1804f8652 100644 --- a/web/apps/photos/src/components/Collections/CollectionShare/index.tsx +++ b/web/apps/photos/src/components/Collections/CollectionShare/index.tsx @@ -1,4 +1,4 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { Titlebar } from "@/base/components/Titlebar"; import type { Collection } from "@/media/collection"; import type { CollectionSummary } from "@/new/photos/services/collection/ui"; @@ -32,7 +32,7 @@ function CollectionShare({ collectionSummary, ...props }: Props) { const { type } = collectionSummary; return ( - - + ); } export default CollectionShare; diff --git a/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/deviceLimit.tsx b/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/deviceLimit.tsx index 99517c4cd2..60e3198550 100644 --- a/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/deviceLimit.tsx +++ b/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/deviceLimit.tsx @@ -1,5 +1,5 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemDivider, MenuItemGroup } from "@/base/components/Menu"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { Titlebar } from "@/base/components/Titlebar"; import type { Collection, @@ -68,7 +68,7 @@ export function ManageDeviceLimit({ endIcon={} /> - - + ); } diff --git a/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/index.tsx b/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/index.tsx index 79f46d1dc8..801b77a5ae 100644 --- a/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/index.tsx +++ b/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/index.tsx @@ -1,5 +1,5 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemDivider, MenuItemGroup } from "@/base/components/Menu"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { Titlebar } from "@/base/components/Titlebar"; import type { Collection, @@ -86,24 +86,32 @@ export default function ManagePublicShareOptions({ navigator.clipboard.writeText(text); }; return ( - <> - - - - - - - + + + + + + + + - - - - - - - - - } - onClick={copyToClipboardHelper( - publicShareUrl, - )} - label={t("COPY_LINK")} - /> - - - } - onClick={disablePublicSharing} - label={t("REMOVE_LINK")} - /> - - - {sharableLinkError && ( - theme.colors.danger.A700, - mt: 0.5, - }} - > - {sharableLinkError} - - )} + + + + + + + } + onClick={copyToClipboardHelper(publicShareUrl)} + label={t("COPY_LINK")} + /> + + + } + onClick={disablePublicSharing} + label={t("REMOVE_LINK")} + /> + + {sharableLinkError && ( + theme.colors.danger.A700, + mt: 0.5, + }} + > + {sharableLinkError} + + )} - - + + ); } diff --git a/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/linkExpiry.tsx b/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/linkExpiry.tsx index 8487240274..3bc1c7f2c5 100644 --- a/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/linkExpiry.tsx +++ b/web/apps/photos/src/components/Collections/CollectionShare/publicShare/manage/linkExpiry.tsx @@ -1,5 +1,5 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemDivider, MenuItemGroup } from "@/base/components/Menu"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { Titlebar } from "@/base/components/Titlebar"; import type { Collection, @@ -84,7 +84,7 @@ export function ManageLinkExpiry({ } /> - - + ); } diff --git a/web/apps/photos/src/components/MemberSubscriptionManage.tsx b/web/apps/photos/src/components/MemberSubscriptionManage.tsx index 5fec26cbdf..62be7e4473 100644 --- a/web/apps/photos/src/components/MemberSubscriptionManage.tsx +++ b/web/apps/photos/src/components/MemberSubscriptionManage.tsx @@ -1,4 +1,5 @@ import { useIsSmallWidth } from "@/base/hooks"; +import { getFamilyPlanAdmin } from "@/new/photos/services/user"; import { AppContext } from "@/new/photos/types/context"; import { FlexWrapper, @@ -9,7 +10,6 @@ import { Box, Button, Dialog, DialogContent, Typography } from "@mui/material"; import { t } from "i18next"; import { useContext } from "react"; import billingService from "services/billingService"; -import { getFamilyPlanAdmin } from "utils/user/family"; export function MemberSubscriptionManage({ open, userDetails, onClose }) { const { setDialogMessage } = useContext(AppContext); diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx index 875fd404bb..ec62ec87e0 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/index.tsx @@ -1,6 +1,5 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; -import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { Titlebar } from "@/base/components/Titlebar"; import { EllipsizedTypography } from "@/base/components/Typography"; import { useModalVisibility } from "@/base/components/utils/modal"; @@ -20,6 +19,10 @@ import { type ButtonishProps } from "@/new/photos/components/mui"; import { ChipButton } from "@/new/photos/components/mui/ChipButton"; import { FilePeopleList } from "@/new/photos/components/PeopleList"; import { PhotoDateTimePicker } from "@/new/photos/components/PhotoDateTimePicker"; +import { + confirmDisableMapsDialogAttributes, + confirmEnableMapsDialogAttributes, +} from "@/new/photos/components/utils/dialog"; import { fileInfoDrawerZIndex } from "@/new/photos/components/utils/z-index"; import { tagNumericValue, type RawExifTags } from "@/new/photos/services/exif"; import { @@ -27,6 +30,11 @@ import { isMLEnabled, type AnnotatedFaceID, } from "@/new/photos/services/ml"; +import { + settingsSnapshot, + settingsSubscribe, + updateMapEnabled, +} from "@/new/photos/services/settings"; import { AppContext } from "@/new/photos/types/context"; import { formattedByteSize } from "@/new/photos/utils/units"; import CopyButton from "@ente/shared/components/CodeBlock/CopyButton"; @@ -55,8 +63,13 @@ import { 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 React, { + useContext, + useEffect, + useMemo, + useState, + useSyncExternalStore, +} from "react"; import { changeFileName, updateExistingFilePubMetadata } from "utils/file"; import { PublicCollectionGalleryContext } from "utils/publicCollectionGallery"; import { FileNameEditDialog } from "./FileNameEditDialog"; @@ -100,8 +113,12 @@ export const FileInfo: React.FC = ({ closePhotoViewer, onSelectPerson, }) => { - const { mapEnabled, updateMapEnabled, showMiniDialog } = - useContext(AppContext); + const { mapEnabled } = useSyncExternalStore( + settingsSubscribe, + settingsSnapshot, + ); + + const { showMiniDialog } = useContext(AppContext); const galleryContext = useContext(GalleryContext); const publicCollectionGalleryContext = useContext( PublicCollectionGalleryContext, @@ -275,7 +292,6 @@ export const FileInfo: React.FC = ({ /> {isMLEnabled() && annotatedFaces.length > 0 && ( }> - {/*t("UNIDENTIFIED_FACES") TODO-Cluster remove */} void, -): MiniDialogAttributes => ({ - title: t("enable_maps_confirm"), - message: ( - - ), - }} - /> - ), - continue: { text: t("enable"), action: onConfirm }, -}); - -const confirmDisableMapsDialogAttributes = ( - onConfirm: () => void, -): MiniDialogAttributes => ({ - title: t("disable_maps_confirm"), - message: , - continue: { text: t("disable"), color: "critical", action: onConfirm }, -}); - const FileInfoSidebar = styled((props: DialogProps) => ( - + ))({ zIndex: fileInfoDrawerZIndex, "& .MuiPaper-root": { diff --git a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx index 931b70d690..de5afca30b 100644 --- a/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/ImageEditorOverlay/index.tsx @@ -1,10 +1,10 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemDivider, MenuItemGroup, MenuSectionTitle, } from "@/base/components/Menu"; import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { nameAndExtension } from "@/base/file"; import log from "@/base/log"; import { downloadAndRevokeObjectURL } from "@/base/utils/web"; @@ -614,7 +614,7 @@ const ImageEditorOverlay = (props: IProps) => { - { title={t("PHOTO_EDIT_REQUIRED_TO_SAVE")} /> )} - + ); diff --git a/web/apps/photos/src/components/PhotoViewer/index.tsx b/web/apps/photos/src/components/PhotoViewer/index.tsx index 961201b46d..d1ee5f59de 100644 --- a/web/apps/photos/src/components/PhotoViewer/index.tsx +++ b/web/apps/photos/src/components/PhotoViewer/index.tsx @@ -1,9 +1,10 @@ import { isDesktop } from "@/base/app"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; +import { Overlay } from "@/base/components/mui/Container"; import { lowercaseExtension } from "@/base/file"; import log from "@/base/log"; import type { LoadedLivePhotoSourceURL } from "@/media/file"; -import { type EnteFile, fileLogID } from "@/media/file"; +import { fileLogID, type EnteFile } from "@/media/file"; import { FileType } from "@/media/file-type"; import { isHEICExtension, needsJPEGConversion } from "@/media/formats"; import downloadManager from "@/new/photos/services/download"; @@ -25,7 +26,16 @@ import FullscreenOutlinedIcon from "@mui/icons-material/FullscreenOutlined"; import InfoIcon from "@mui/icons-material/InfoOutlined"; import ReplayIcon from "@mui/icons-material/Replay"; import ZoomInOutlinedIcon from "@mui/icons-material/ZoomInOutlined"; -import { Box, Button, styled } from "@mui/material"; +import { + Box, + Button, + CircularProgress, + Paper, + styled, + Typography, + type CircularProgressProps, +} from "@mui/material"; +import Notification from "components/Notification"; import { t } from "i18next"; import isElectron from "is-electron"; import { GalleryContext } from "pages/gallery"; @@ -48,9 +58,6 @@ import { PublicCollectionGalleryContext } from "utils/publicCollectionGallery"; import { getTrashFileMessage } from "utils/ui"; import { FileInfo, type FileInfoExif, type FileInfoProps } from "./FileInfo"; import ImageEditorOverlay from "./ImageEditorOverlay"; -import CircularProgressWithLabel from "./styledComponents/CircularProgressWithLabel"; -import { ConversionFailedNotification } from "./styledComponents/ConversionFailedNotification"; -import { LivePhotoBtnContainer } from "./styledComponents/LivePhotoBtn"; interface PhotoswipeFullscreenAPI { enter: () => void; @@ -118,7 +125,8 @@ export interface PhotoViewerProps { function PhotoViewer(props: PhotoViewerProps) { const galleryContext = useContext(GalleryContext); - const appContext = useContext(AppContext); + const { showLoadingBar, hideLoadingBar, setDialogMessage } = + useContext(AppContext); const publicCollectionGalleryContext = useContext( PublicCollectionGalleryContext, ); @@ -537,9 +545,12 @@ function PhotoViewer(props: PhotoViewerProps) { const trashFile = async (file: EnteFile) => { try { - appContext.startLoading(); - await trashFiles([file]); - appContext.finishLoading(); + showLoadingBar(); + try { + await trashFiles([file]); + } finally { + hideLoadingBar(); + } markTempDeleted?.([file]); updateItems(props.items.filter((item) => item.id !== file.id)); needUpdate.current = true; @@ -552,7 +563,7 @@ function PhotoViewer(props: PhotoViewerProps) { if (!file || !isOwnFile || props.isTrashCollection) { return; } - appContext.setDialogMessage(getTrashFileMessage(() => trashFile(file))); + setDialogMessage(getTrashFileMessage(() => trashFile(file))); }; const handleArrowClick = ( @@ -683,9 +694,9 @@ function PhotoViewer(props: PhotoViewerProps) { const copyToClipboardHelper = async (file: EnteFile) => { if (file && props.enableDownload && shouldShowCopyOption) { - appContext.startLoading(); + showLoadingBar(); await copyFileToClipboard(file.src); - appContext.finishLoading(); + hideLoadingBar(); } }; @@ -979,3 +990,60 @@ function PhotoViewer(props: PhotoViewerProps) { } export default PhotoViewer; + +function CircularProgressWithLabel( + props: CircularProgressProps & { value: number }, +) { + return ( + <> + + + {`${Math.round(props.value)}%`} + + + ); +} + +interface ConversionFailedNotificationProps { + open: boolean; + onClose: () => void; + onClick: () => void; +} + +const ConversionFailedNotification: React.FC< + ConversionFailedNotificationProps +> = ({ open, onClose, onClick }) => { + return ( + + ); +}; + +const LivePhotoBtnContainer = styled(Paper)` + border-radius: 4px; + position: absolute; + bottom: 10vh; + right: 6vh; + z-index: 10; +`; diff --git a/web/apps/photos/src/components/PhotoViewer/styledComponents/CircularProgressWithLabel.tsx b/web/apps/photos/src/components/PhotoViewer/styledComponents/CircularProgressWithLabel.tsx deleted file mode 100644 index 9556a3a855..0000000000 --- a/web/apps/photos/src/components/PhotoViewer/styledComponents/CircularProgressWithLabel.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Overlay } from "@ente/shared/components/Container"; -import { - CircularProgress, - Typography, - type CircularProgressProps, -} from "@mui/material"; - -function CircularProgressWithLabel( - props: CircularProgressProps & { value: number }, -) { - return ( - <> - - - {`${Math.round(props.value)}%`} - - - ); -} - -export default CircularProgressWithLabel; diff --git a/web/apps/photos/src/components/PhotoViewer/styledComponents/ConversionFailedNotification.tsx b/web/apps/photos/src/components/PhotoViewer/styledComponents/ConversionFailedNotification.tsx deleted file mode 100644 index fe504d1805..0000000000 --- a/web/apps/photos/src/components/PhotoViewer/styledComponents/ConversionFailedNotification.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import Notification from "components/Notification"; -import { t } from "i18next"; - -interface Iprops { - open: boolean; - onClose: () => void; - onClick: () => void; -} - -export const ConversionFailedNotification = ({ - open, - onClose, - onClick, -}: Iprops) => { - return ( - - ); -}; diff --git a/web/apps/photos/src/components/PhotoViewer/styledComponents/LivePhotoBtn.tsx b/web/apps/photos/src/components/PhotoViewer/styledComponents/LivePhotoBtn.tsx deleted file mode 100644 index 00b8979d5a..0000000000 --- a/web/apps/photos/src/components/PhotoViewer/styledComponents/LivePhotoBtn.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Paper, styled } from "@mui/material"; - -export const LivePhotoBtnContainer = styled(Paper)` - border-radius: 4px; - position: absolute; - bottom: 10vh; - right: 6vh; - z-index: 10; -`; diff --git a/web/apps/photos/src/components/PhotoViewer/styledComponents/Pre.tsx b/web/apps/photos/src/components/PhotoViewer/styledComponents/Pre.tsx deleted file mode 100644 index b088ec9f83..0000000000 --- a/web/apps/photos/src/components/PhotoViewer/styledComponents/Pre.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { styled } from "@mui/material"; -export const Pre = styled("pre")` - color: #aaa; - padding: 7px 15px; -`; diff --git a/web/apps/photos/src/components/Sidebar/AdvancedSettings.tsx b/web/apps/photos/src/components/Sidebar/AdvancedSettings.tsx deleted file mode 100644 index 24efe9a000..0000000000 --- a/web/apps/photos/src/components/Sidebar/AdvancedSettings.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; -import { MenuItemGroup, MenuSectionTitle } from "@/base/components/Menu"; -import { Titlebar } from "@/base/components/Titlebar"; -import type { NestedDrawerVisibilityProps } from "@/base/components/utils/modal"; -import { AppContext } from "@/new/photos/types/context"; -import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem"; -import { Box, DialogProps, Stack } from "@mui/material"; -import { t } from "i18next"; -import React, { useContext } from "react"; - -export const AdvancedSettings: React.FC = ({ - open, - onClose, - onRootClose, -}) => { - const appContext = useContext(AppContext); - - const handleRootClose = () => { - onClose(); - onRootClose(); - }; - - const handleDrawerClose: DialogProps["onClose"] = (_, reason) => { - if (reason === "backdropClick") { - handleRootClose(); - } else { - onClose(); - } - }; - - const toggleCFProxy = () => { - appContext.setIsCFProxyDisabled(!appContext.isCFProxyDisabled); - }; - - return ( - - - - - - - - - - - - - - - - - ); -}; diff --git a/web/apps/photos/src/components/Sidebar/MapSetting.tsx b/web/apps/photos/src/components/Sidebar/MapSetting.tsx deleted file mode 100644 index 6fe1851eb1..0000000000 --- a/web/apps/photos/src/components/Sidebar/MapSetting.tsx +++ /dev/null @@ -1,232 +0,0 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; -import { MenuItemGroup } from "@/base/components/Menu"; -import { Titlebar } from "@/base/components/Titlebar"; -import type { NestedDrawerVisibilityProps } from "@/base/components/utils/modal"; -import log from "@/base/log"; -import { AppContext } from "@/new/photos/types/context"; -import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem"; -import { - Box, - Button, - DialogProps, - Link, - Stack, - Typography, -} from "@mui/material"; -import { t } from "i18next"; -import React, { useContext, useEffect, useState } from "react"; -import { Trans } from "react-i18next"; -import { getMapEnabledStatus } from "services/userService"; - -export const MapSettings: React.FC = ({ - open, - onClose, - onRootClose, -}) => { - const { mapEnabled, updateMapEnabled } = useContext(AppContext); - const [modifyMapEnabledView, setModifyMapEnabledView] = useState(false); - - const openModifyMapEnabled = () => setModifyMapEnabledView(true); - const closeModifyMapEnabled = () => setModifyMapEnabledView(false); - - useEffect(() => { - if (!open) { - return; - } - const main = async () => { - const remoteMapValue = await getMapEnabledStatus(); - updateMapEnabled(remoteMapValue); - }; - main(); - }, [open]); - - const handleRootClose = () => { - onClose(); - onRootClose(); - }; - - const handleDrawerClose: DialogProps["onClose"] = (_, reason) => { - if (reason === "backdropClick") { - handleRootClose(); - } else { - onClose(); - } - }; - - return ( - - - - - - - - - - - - - - - - - ); -}; - -const ModifyMapEnabled = ({ open, onClose, onRootClose, mapEnabled }) => { - const { somethingWentWrong, updateMapEnabled } = useContext(AppContext); - - const disableMap = async () => { - try { - await updateMapEnabled(false); - onClose(); - } catch (e) { - log.error("Disable Map failed", e); - somethingWentWrong(); - } - }; - - const enableMap = async () => { - try { - await updateMapEnabled(true); - onClose(); - } catch (e) { - log.error("Enable Map failed", e); - somethingWentWrong(); - } - }; - - const handleRootClose = () => { - onClose(); - onRootClose(); - }; - - const handleDrawerClose: DialogProps["onClose"] = (_, reason) => { - if (reason === "backdropClick") { - handleRootClose(); - } else { - onClose(); - } - }; - - return ( - - - {mapEnabled ? ( - - ) : ( - - )} - - - ); -}; - -function EnableMap({ onClose, enableMap, onRootClose }) { - return ( - - - - - {" "} - - - ), - }} - /> - - - - - - - - - ); -} - -function DisableMap({ onClose, disableMap, onRootClose }) { - return ( - - - - - - - - - - - - - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/Preferences.tsx b/web/apps/photos/src/components/Sidebar/Preferences.tsx index 17c5da18a3..ba6800d463 100644 --- a/web/apps/photos/src/components/Sidebar/Preferences.tsx +++ b/web/apps/photos/src/components/Sidebar/Preferences.tsx @@ -1,29 +1,39 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemGroup, MenuSectionTitle } from "@/base/components/Menu"; -import { Titlebar } from "@/base/components/Titlebar"; import { - useModalVisibility, - type NestedDrawerVisibilityProps, -} from "@/base/components/utils/modal"; + NestedSidebarDrawer, + SidebarDrawerTitlebar, + type NestedSidebarDrawerVisibilityProps, +} from "@/base/components/mui/SidebarDrawer"; +import { useModalVisibility } from "@/base/components/utils/modal"; import { getLocaleInUse, setLocaleInUse, supportedLocales, type SupportedLocale, } from "@/base/i18n"; -import { MLSettings } from "@/new/photos/components/MLSettings"; +import { MLSettings } from "@/new/photos/components/sidebar/MLSettings"; +import { + confirmDisableMapsDialogAttributes, + confirmEnableMapsDialogAttributes, +} from "@/new/photos/components/utils/dialog"; import { isMLSupported } from "@/new/photos/services/ml"; +import { + settingsSnapshot, + settingsSubscribe, + syncSettings, + updateCFProxyDisabledPreference, + updateMapEnabled, +} from "@/new/photos/services/settings"; +import { useAppContext } from "@/new/photos/types/context"; import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem"; import ChevronRight from "@mui/icons-material/ChevronRight"; import ScienceIcon from "@mui/icons-material/Science"; -import { Box, DialogProps, Stack } from "@mui/material"; +import { Box, Stack } from "@mui/material"; import DropdownInput from "components/DropdownInput"; import { t } from "i18next"; -import React from "react"; -import { AdvancedSettings } from "./AdvancedSettings"; -import { MapSettings } from "./MapSetting"; +import React, { useCallback, useEffect, useSyncExternalStore } from "react"; -export const Preferences: React.FC = ({ +export const Preferences: React.FC = ({ open, onClose, onRootClose, @@ -37,64 +47,51 @@ export const Preferences: React.FC = ({ const { show: showMLSettings, props: mlSettingsVisibilityProps } = useModalVisibility(); + useEffect(() => { + if (open) void syncSettings(); + }, [open]); + const handleRootClose = () => { onClose(); onRootClose(); }; - const handleDrawerClose: DialogProps["onClose"] = (_, reason) => { - if (reason === "backdropClick") { - handleRootClose(); - } else { - onClose(); - } - }; - return ( - - - + + - - - - } - label={t("map")} - /> - } - label={t("advanced")} - /> - {isMLSupported && ( - - } + + + } + label={t("map")} + /> + } + label={t("advanced")} + /> + {isMLSupported && ( + + } + /> + + } + onClick={showMLSettings} + label={t("ml_search")} /> - - } - onClick={showMLSettings} - label={t("ml_search")} - /> - - - )} - - + + + )} + = ({ {...mlSettingsVisibilityProps} onRootClose={handleRootClose} /> - + ); }; @@ -165,5 +162,115 @@ const localeName = (locale: SupportedLocale) => { return "Italiano"; case "lt-LT": return "Lietuvių kalba"; + case "uk-UA": + return "Українська"; } }; + +export const MapSettings: React.FC = ({ + open, + onClose, + onRootClose, +}) => { + const { showMiniDialog } = useAppContext(); + + const { mapEnabled } = useSyncExternalStore( + settingsSubscribe, + settingsSnapshot, + ); + + const confirmToggle = useCallback( + () => + showMiniDialog( + mapEnabled + ? confirmDisableMapsDialogAttributes(() => + updateMapEnabled(false), + ) + : confirmEnableMapsDialogAttributes(() => + updateMapEnabled(true), + ), + ), + [showMiniDialog, mapEnabled], + ); + + const handleRootClose = () => { + onClose(); + onRootClose(); + }; + + return ( + + + + + + + + + + + + ); +}; + +export const AdvancedSettings: React.FC = ({ + open, + onClose, + onRootClose, +}) => { + const { cfUploadProxyDisabled } = useSyncExternalStore( + settingsSubscribe, + settingsSnapshot, + ); + + const handleRootClose = () => { + onClose(); + onRootClose(); + }; + + const toggle = () => + void updateCFProxyDisabledPreference(!cfUploadProxyDisabled); + + return ( + + + + + + + + + + + + + + + ); +}; diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard.tsx new file mode 100644 index 0000000000..090b4c949f --- /dev/null +++ b/web/apps/photos/src/components/Sidebar/SubscriptionCard.tsx @@ -0,0 +1,358 @@ +import { Overlay } from "@/base/components/mui/Container"; +import type { ButtonishProps } from "@/new/photos/components/mui"; +import { + hasNonAdminFamilyMembers, + isPartOfFamily, +} from "@/new/photos/services/user"; +import { bytesInGB, formattedStorageByteSize } from "@/new/photos/utils/units"; +import { SpaceBetweenFlex } from "@ente/shared/components/Container"; +import ChevronRightIcon from "@mui/icons-material/ChevronRight"; +import CircleIcon from "@mui/icons-material/Circle"; +import { + Box, + LinearProgress, + Skeleton, + Stack, + Typography, + styled, + type LinearProgressProps, +} from "@mui/material"; +import { t } from "i18next"; +import type React from "react"; +import { useMemo } from "react"; +import type { UserDetails } from "types/user"; + +interface SubscriptionCardProps { + userDetails: UserDetails; + onClick: () => void; +} + +export const SubscriptionCard: React.FC = ({ + userDetails, + onClick, +}) => { + if (!userDetails) { + return ( + + ); + } + + return ( + + + + + + ); +}; + +const BackgroundOverlay: React.FC = () => { + return ( + + ); +}; + +const ClickOverlay: React.FC = ({ onClick }) => ( + + + +); + +interface SubscriptionCardContentOverlayProps { + userDetails: UserDetails; +} + +export const SubscriptionCardContentOverlay: React.FC< + SubscriptionCardContentOverlayProps +> = ({ userDetails }) => { + return ( + + + {hasNonAdminFamilyMembers(userDetails.familyData) ? ( + + ) : ( + + )} + + + ); +}; + +interface IndividualSubscriptionCardContentProps { + userDetails: UserDetails; +} + +const IndividualSubscriptionCardContent: React.FC< + IndividualSubscriptionCardContentProps +> = ({ userDetails }) => { + const totalStorage = + userDetails.subscription.storage + (userDetails.storageBonus ?? 0); + return ( + <> + + + + ); +}; + +const MobileSmallBox = styled(Box)` + display: none; + @media (max-width: 359px) { + display: block; + } +`; + +const DefaultBox = styled(Box)` + display: none; + @media (min-width: 360px) { + display: block; + } +`; + +interface StorageSectionProps { + usage: number; + storage: number; +} + +const StorageSection: React.FC = ({ usage, storage }) => { + return ( + + + {t("STORAGE")} + + + + {`${formattedStorageByteSize(usage, { round: true })} ${t( + "OF", + )} ${formattedStorageByteSize(storage)} ${t("USED")}`} + + + + + {`${bytesInGB(usage)} / ${bytesInGB(storage)} ${t("storage_unit.gb")} ${t("USED")}`} + + + + ); +}; + +interface IndividualUsageSectionProps { + usage: number; + fileCount: number; + storage: number; +} + +const IndividualUsageSection: React.FC = ({ + usage, + storage, + fileCount, +}) => { + // [Note: Fallback translation for languages with multiple plurals] + // + // Languages like Polish and Arabian have multiple plural forms, and + // currently i18n falls back to the base language translation instead of the + // "_other" form if all the plural forms are not listed out. + // + // As a workaround, name the _other form as the unprefixed name. That is, + // instead of calling the most general plural form as foo_count_other, call + // it foo_count (To keep our heads straight, we adopt the convention that + // all such pluralizable strings use the _count suffix, but that's not a + // requirement from the library). + return ( + + + + {`${formattedStorageByteSize( + storage - usage, + )} ${t("FREE")}`} + + {t("photos_count", { count: fileCount ?? 0 })} + + + + ); +}; + +interface FamilySubscriptionCardContentProps { + userDetails: UserDetails; +} + +const FamilySubscriptionCardContent: React.FC< + FamilySubscriptionCardContentProps +> = ({ userDetails }) => { + const totalUsage = useMemo(() => { + if (isPartOfFamily(userDetails.familyData)) { + return userDetails.familyData.members.reduce( + (sum, currentMember) => sum + currentMember.usage, + 0, + ); + } else { + return userDetails.usage; + } + }, [userDetails]); + const totalStorage = + userDetails.familyData.storage + (userDetails.storageBonus ?? 0); + + return ( + <> + + + + ); +}; + +interface FamilyUsageSectionProps { + userUsage: number; + totalUsage: number; + fileCount: number; + totalStorage: number; +} + +const FamilyUsageSection: React.FC = ({ + userUsage, + totalUsage, + fileCount, + totalStorage, +}) => { + return ( + + + + + + + + + {t("photos_count", { count: fileCount ?? 0 })} + + + + ); +}; + +interface FamilyUsageBarProps { + userUsage: number; + totalUsage: number; + totalStorage: number; +} + +const FamilyUsageBar: React.FC = ({ + userUsage, + totalUsage, + totalStorage, +}) => ( + + + + +); + +type UsageBarProps = Pick & { + used: number; + total: number; +}; + +const UsageBar: React.FC = ({ used, total, sx }) => ( + +); + +const UsageBar_ = styled(LinearProgress)(() => ({ + ".MuiLinearProgress-bar": { + borderRadius: "2px", + }, + borderRadius: "2px", + backgroundColor: "rgba(255, 255, 255, 0.2)", +})); + +interface LegendProps { + label: string; + color: string; +} + +const Legend: React.FC = ({ label, color }) => ( + + + + {label} + + +); + +const LegendDot = styled(CircleIcon)` + font-size: 8.71px; + margin: 0; + margin-inline-end: 4px; + color: inherit; +`; diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/index.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/index.tsx deleted file mode 100644 index 77776745dc..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { useMemo } from "react"; -import { UserDetails } from "types/user"; -import { isPartOfFamily } from "utils/user/family"; -import StorageSection from "../storageSection"; -import { FamilyUsageSection } from "./usageSection"; - -interface Iprops { - userDetails: UserDetails; -} -export function FamilySubscriptionCardContent({ userDetails }: Iprops) { - const totalUsage = useMemo(() => { - if (isPartOfFamily(userDetails.familyData)) { - return userDetails.familyData.members.reduce( - (sum, currentMember) => sum + currentMember.usage, - 0, - ); - } else { - return userDetails.usage; - } - }, [userDetails]); - const totalStorage = - userDetails.familyData.storage + (userDetails.storageBonus ?? 0); - - return ( - <> - - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/usageSection/index.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/usageSection/index.tsx deleted file mode 100644 index 4c0b1904f2..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/usageSection/index.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { SpaceBetweenFlex } from "@ente/shared/components/Container"; -import { Box, Stack, Typography } from "@mui/material"; -import { t } from "i18next"; -import { Legend } from "./legend"; -import { FamilyUsageProgressBar } from "./progressBar"; - -interface Iprops { - userUsage: number; - totalUsage: number; - fileCount: number; - totalStorage: number; -} - -export function FamilyUsageSection({ - userUsage, - totalUsage, - fileCount, - totalStorage, -}: Iprops) { - return ( - - - - - - - - - {t("photos_count", { count: fileCount ?? 0 })} - - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/usageSection/legend.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/usageSection/legend.tsx deleted file mode 100644 index 6caaa2374d..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/usageSection/legend.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { FlexWrapper } from "@ente/shared/components/Container"; -import { Typography } from "@mui/material"; -import { LegendIndicator } from "../../../styledComponents"; - -interface Iprops { - label: string; - color: string; -} -export function Legend({ label, color }: Iprops) { - return ( - - - - {label} - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/usageSection/progressBar.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/usageSection/progressBar.tsx deleted file mode 100644 index ab28b5b8f1..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/family/usageSection/progressBar.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Box } from "@mui/material"; -import { Progressbar } from "../../../styledComponents"; -interface Iprops { - userUsage: number; - totalUsage: number; - totalStorage: number; -} - -export function FamilyUsageProgressBar({ - userUsage, - totalUsage, - totalStorage, -}: Iprops) { - return ( - - - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/index.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/index.tsx deleted file mode 100644 index 238058534c..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { Overlay, SpaceBetweenFlex } from "@ente/shared/components/Container"; -import { UserDetails } from "types/user"; -import { hasNonAdminFamilyMembers } from "utils/user/family"; -import { FamilySubscriptionCardContent } from "./family"; -import { IndividualSubscriptionCardContent } from "./individual"; - -interface Iprops { - userDetails: UserDetails; -} - -export function SubscriptionCardContentOverlay({ userDetails }: Iprops) { - return ( - - - {hasNonAdminFamilyMembers(userDetails.familyData) ? ( - - ) : ( - - )} - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/index.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/index.tsx deleted file mode 100644 index 9bdc3292c1..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/index.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { UserDetails } from "types/user"; -import StorageSection from "../storageSection"; -import { IndividualUsageSection } from "./usageSection"; - -interface Iprops { - userDetails: UserDetails; -} - -export function IndividualSubscriptionCardContent({ userDetails }: Iprops) { - const totalStorage = - userDetails.subscription.storage + (userDetails.storageBonus ?? 0); - return ( - <> - - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx deleted file mode 100644 index 857ac9c633..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { formattedStorageByteSize } from "@/new/photos/utils/units"; -import { SpaceBetweenFlex } from "@ente/shared/components/Container"; -import { Box, Typography } from "@mui/material"; -import { t } from "i18next"; - -import { Progressbar } from "../../styledComponents"; - -interface Iprops { - usage: number; - fileCount: number; - storage: number; -} -export function IndividualUsageSection({ usage, storage, fileCount }: Iprops) { - // [Note: Fallback translation for languages with multiple plurals] - // - // Languages like Polish and Arabian have multiple plural forms, and - // currently i18n falls back to the base language translation instead of the - // "_other" form if all the plural forms are not listed out. - // - // As a workaround, name the _other form as the unprefixed name. That is, - // instead of calling the most general plural form as foo_count_other, call - // it foo_count (To keep our heads straight, we adopt the convention that - // all such pluralizable strings use the _count suffix, but that's not a - // requirement from the library). - return ( - - - - {`${formattedStorageByteSize( - storage - usage, - )} ${t("FREE")}`} - - {t("photos_count", { count: fileCount ?? 0 })} - - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx deleted file mode 100644 index 4ad0ed2149..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { bytesInGB, formattedStorageByteSize } from "@/new/photos/utils/units"; -import { Box, Typography, styled } from "@mui/material"; -import { t } from "i18next"; - -const MobileSmallBox = styled(Box)` - display: none; - @media (max-width: 359px) { - display: block; - } -`; - -const DefaultBox = styled(Box)` - display: none; - @media (min-width: 360px) { - display: block; - } -`; -interface Iprops { - usage: number; - storage: number; -} -export default function StorageSection({ usage, storage }: Iprops) { - return ( - - - {t("STORAGE")} - - - - {`${formattedStorageByteSize(usage, { round: true })} ${t( - "OF", - )} ${formattedStorageByteSize(storage)} ${t("USED")}`} - - - - - {`${bytesInGB(usage)} / ${bytesInGB(storage)} ${t("storage_unit.gb")} ${t("USED")}`} - - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/index.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/index.tsx deleted file mode 100644 index 514c43df81..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { FlexWrapper, Overlay } from "@ente/shared/components/Container"; -import ChevronRightIcon from "@mui/icons-material/ChevronRight"; -import { Box, Skeleton } from "@mui/material"; -import { UserDetails } from "types/user"; -import { SubscriptionCardContentOverlay } from "./contentOverlay"; - -const SUBSCRIPTION_CARD_SIZE = 152; - -interface Iprops { - userDetails: UserDetails; - onClick: () => void; -} - -export default function SubscriptionCard({ userDetails, onClick }: Iprops) { - if (!userDetails) { - return ( - - ); - } - - return ( - - - - - - ); -} - -function BackgroundOverlay() { - return ( - - ); -} - -function ClickOverlay({ onClick }) { - return ( - - - - - - ); -} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/styledComponents.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/styledComponents.tsx deleted file mode 100644 index 90bea72ce7..0000000000 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/styledComponents.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import CircleIcon from "@mui/icons-material/Circle"; -import { LinearProgress, styled } from "@mui/material"; - -export const Progressbar = styled(LinearProgress)(() => ({ - ".MuiLinearProgress-bar": { - borderRadius: "2px", - }, - borderRadius: "2px", - backgroundColor: "rgba(255, 255, 255, 0.2)", -})); - -Progressbar.defaultProps = { - variant: "determinate", -}; - -const DotSeparator = styled(CircleIcon)` - font-size: 4px; - margin: 0 ${({ theme }) => theme.spacing(1)}; - color: inherit; -`; - -export const LegendIndicator = styled(DotSeparator)` - font-size: 8.71px; - margin: 0; - margin-right: 4px; - color: inherit; -`; diff --git a/web/apps/photos/src/components/Sidebar/index.tsx b/web/apps/photos/src/components/Sidebar/index.tsx index 1ae907e4d1..425c7d291e 100644 --- a/web/apps/photos/src/components/Sidebar/index.tsx +++ b/web/apps/photos/src/components/Sidebar/index.tsx @@ -1,14 +1,15 @@ import { RecoveryKey } from "@/accounts/components/RecoveryKey"; import { openAccountsManagePasskeysPage } from "@/accounts/services/passkey"; import { isDesktop } from "@/base/app"; -import { EnteDrawer } from "@/base/components/EnteDrawer"; import { EnteLogo } from "@/base/components/EnteLogo"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; +import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer"; import { useModalVisibility } from "@/base/components/utils/modal"; import log from "@/base/log"; import { savedLogs } from "@/base/log-web"; import { customAPIHost } from "@/base/origins"; import { downloadString } from "@/base/utils/web"; +import { TwoFactorSettings } from "@/new/photos/components/sidebar/TwoFactorSettings"; import { downloadAppDialogAttributes } from "@/new/photos/components/utils/download"; import { ARCHIVE_SECTION, @@ -16,6 +17,8 @@ import { TRASH_SECTION, } from "@/new/photos/services/collection"; import type { CollectionSummaries } from "@/new/photos/services/collection/ui"; +import { isInternalUser } from "@/new/photos/services/settings"; +import { isFamilyAdmin, isPartOfFamily } from "@/new/photos/services/user"; import { AppContext, useAppContext } from "@/new/photos/types/context"; import { initiateEmail, openURL } from "@/new/photos/utils/web"; import { SpaceBetweenFlex } from "@ente/shared/components/Container"; @@ -46,7 +49,6 @@ import { } from "@mui/material"; import Typography from "@mui/material/Typography"; import DeleteAccountModal from "components/DeleteAccountModal"; -import TwoFactorModal from "components/TwoFactor/Modal"; import { WatchFolder } from "components/WatchFolder"; import LinkButton from "components/pages/gallery/LinkButton"; import { t } from "i18next"; @@ -76,24 +78,24 @@ import { isSubscriptionCancelled, isSubscriptionPastDue, } from "utils/billing"; -import { isFamilyAdmin, isPartOfFamily } from "utils/user/family"; import { testUpload } from "../../../tests/upload.test"; import { MemberSubscriptionManage } from "../MemberSubscriptionManage"; import { Preferences } from "./Preferences"; -import SubscriptionCard from "./SubscriptionCard"; +import { SubscriptionCard } from "./SubscriptionCard"; interface Iprops { collectionSummaries: CollectionSummaries; sidebarView: boolean; closeSidebar: () => void; } + export default function Sidebar({ collectionSummaries, sidebarView, closeSidebar, }: Iprops) { return ( - + @@ -110,18 +112,16 @@ export default function Sidebar({ - + ); } -const DrawerSidebar = styled(EnteDrawer)(({ theme }) => ({ +const RootSidebarDrawer = styled(SidebarDrawer)(({ theme }) => ({ "& .MuiPaper-root": { padding: theme.spacing(1.5), }, })); -DrawerSidebar.defaultProps = { anchor: "left" }; - interface HeaderSectionProps { closeSidebar: () => void; } @@ -426,15 +426,13 @@ interface UtilitySectionProps { const UtilitySection: React.FC = ({ closeSidebar }) => { const router = useRouter(); - const appContext = useContext(AppContext); const { - startLoading, watchFolderView, setWatchFolderView, themeColor, setThemeColor, showMiniDialog, - } = appContext; + } = useAppContext(); const { show: showRecoveryKey, props: recoveryKeyVisibilityProps } = useModalVisibility(); @@ -484,7 +482,7 @@ const UtilitySection: React.FC = ({ closeSidebar }) => { onClick={showRecoveryKey} label={t("recovery_key")} /> - {isInternalUserViaEmailCheck() && ( + {isInternalUser() && ( = ({ closeSidebar }) => { = ({ closeSidebar }) => { {...recoveryKeyVisibilityProps} {...{ showMiniDialog }} /> - {isElectron() && ( { return ( <> - {isInternalUserViaEmailCheck() && ( + {isInternalUser() && ( { ); }; - -// TODO: Legacy synchronous check, use the one for feature-flags.ts instead. -const isInternalUserViaEmailCheck = () => { - const userEmail = getData(LS_KEYS.USER)?.email; - if (!userEmail) return false; - - return userEmail.endsWith("@ente.io"); -}; diff --git a/web/apps/photos/src/components/TwoFactor/Modal/Manage.tsx b/web/apps/photos/src/components/TwoFactor/Modal/Manage.tsx deleted file mode 100644 index 241164653f..0000000000 --- a/web/apps/photos/src/components/TwoFactor/Modal/Manage.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { t } from "i18next"; -import { useContext } from "react"; - -import { disableTwoFactor } from "@/accounts/api/user"; -import { AppContext } from "@/new/photos/types/context"; -import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; -import { LS_KEYS, getData, setLSUser } from "@ente/shared/storage/localStorage"; -import { Button, Grid } from "@mui/material"; -import router from "next/router"; - -interface Iprops { - closeDialog: () => void; -} - -export default function TwoFactorModalManageSection(props: Iprops) { - const { closeDialog } = props; - const { setDialogMessage } = useContext(AppContext); - - const warnTwoFactorDisable = async () => { - setDialogMessage({ - title: t("DISABLE_TWO_FACTOR"), - - content: t("DISABLE_TWO_FACTOR_MESSAGE"), - close: { text: t("cancel") }, - proceed: { - variant: "critical", - text: t("disable"), - action: twoFactorDisable, - }, - }); - }; - - const twoFactorDisable = async () => { - try { - await disableTwoFactor(); - await setLSUser({ - ...getData(LS_KEYS.USER), - isTwoFactorEnabled: false, - }); - closeDialog(); - } catch (e) { - setDialogMessage({ - title: t("TWO_FACTOR_DISABLE_FAILED"), - close: {}, - }); - } - }; - - const warnTwoFactorReconfigure = async () => { - setDialogMessage({ - title: t("UPDATE_TWO_FACTOR"), - - content: t("UPDATE_TWO_FACTOR_MESSAGE"), - close: { text: t("cancel") }, - proceed: { - variant: "accent", - text: t("UPDATE"), - action: reconfigureTwoFactor, - }, - }); - }; - - const reconfigureTwoFactor = async () => { - closeDialog(); - router.push(PAGES.TWO_FACTOR_SETUP); - }; - - return ( - <> - - - {t("UPDATE_TWO_FACTOR_LABEL")} - - - - - - - - {t("DISABLE_TWO_FACTOR_LABEL")}{" "} - - - - - - - - ); -} diff --git a/web/apps/photos/src/components/TwoFactor/Modal/Setup.tsx b/web/apps/photos/src/components/TwoFactor/Modal/Setup.tsx deleted file mode 100644 index dbe724b469..0000000000 --- a/web/apps/photos/src/components/TwoFactor/Modal/Setup.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; -import LockIcon from "@mui/icons-material/Lock"; -import { t } from "i18next"; -import { useRouter } from "next/router"; - -import { VerticallyCentered } from "@ente/shared/components/Container"; -import { Button, Typography } from "@mui/material"; - -interface Iprops { - closeDialog: () => void; -} - -export default function TwoFactorModalSetupSection({ closeDialog }: Iprops) { - const router = useRouter(); - const redirectToTwoFactorSetup = () => { - closeDialog(); - router.push(PAGES.TWO_FACTOR_SETUP); - }; - - return ( - - theme.spacing(5), mb: 2 }} /> - {t("TWO_FACTOR_INFO")} - - - ); -} diff --git a/web/apps/photos/src/components/TwoFactor/Modal/index.tsx b/web/apps/photos/src/components/TwoFactor/Modal/index.tsx deleted file mode 100644 index bebd1810d4..0000000000 --- a/web/apps/photos/src/components/TwoFactor/Modal/index.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import type { ModalVisibilityProps } from "@/base/components/utils/modal"; -import DialogTitleWithCloseButton from "@ente/shared/components/DialogBox/TitleWithCloseButton"; -import { LS_KEYS, getData, setLSUser } from "@ente/shared/storage/localStorage"; -import { Dialog, DialogContent, styled } from "@mui/material"; -import { t } from "i18next"; -import { useEffect, useState } from "react"; -import { getTwoFactorStatus } from "services/userService"; -import { SetLoading } from "types/gallery"; -import TwoFactorModalManageSection from "./Manage"; -import TwoFactorModalSetupSection from "./Setup"; - -const TwoFactorDialog = styled(Dialog)(({ theme }) => ({ - "& .MuiDialogContent-root": { - padding: theme.spacing(2, 4), - }, -})); - -type Props = ModalVisibilityProps & { - setLoading: SetLoading; - closeSidebar: () => void; -}; - -function TwoFactorModal(props: Props) { - const [isTwoFactorEnabled, setTwoFactorStatus] = useState(false); - - useEffect(() => { - const isTwoFactorEnabled = - getData(LS_KEYS.USER).isTwoFactorEnabled ?? false; - setTwoFactorStatus(isTwoFactorEnabled); - }, []); - - useEffect(() => { - if (!props.open) { - return; - } - const main = async () => { - const isTwoFactorEnabled = await getTwoFactorStatus(); - setTwoFactorStatus(isTwoFactorEnabled); - await setLSUser({ - ...getData(LS_KEYS.USER), - isTwoFactorEnabled, - }); - }; - main(); - }, [props.open]); - - const closeDialog = () => { - props.onClose(); - props.closeSidebar(); - }; - - return ( - - - {t("TWO_FACTOR_AUTHENTICATION")} - - - {isTwoFactorEnabled ? ( - - ) : ( - - )} - - - ); -} -export default TwoFactorModal; diff --git a/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx b/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx index 3d267cab03..2aec5562f0 100644 --- a/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx +++ b/web/apps/photos/src/components/Upload/UploadTypeSelector.tsx @@ -1,6 +1,6 @@ +import { SpaceBetweenFlex } from "@/base/components/mui/Container"; 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 DialogTitleWithCloseButton, { dialogCloseHandler, diff --git a/web/apps/photos/src/components/Upload/Uploader.tsx b/web/apps/photos/src/components/Upload/Uploader.tsx index bc5a08fa26..163d72e6e8 100644 --- a/web/apps/photos/src/components/Upload/Uploader.tsx +++ b/web/apps/photos/src/components/Upload/Uploader.tsx @@ -244,7 +244,6 @@ export default function Uploader({ }, onUploadFile, publicCollectionGalleryContext, - appContext.isCFProxyDisabled, ); if (uploadManager.isUploadRunning()) { @@ -287,7 +286,6 @@ export default function Uploader({ publicCollectionGalleryContext.accessedThroughSharedURL, publicCollectionGalleryContext.token, publicCollectionGalleryContext.passwordToken, - appContext.isCFProxyDisabled, ]); // Handle selected files when user selects files for upload through the open diff --git a/web/apps/photos/src/components/icons/ObjectIcon.tsx b/web/apps/photos/src/components/icons/ObjectIcon.tsx deleted file mode 100644 index 9971cd395a..0000000000 --- a/web/apps/photos/src/components/icons/ObjectIcon.tsx +++ /dev/null @@ -1,18 +0,0 @@ -export default function ObjectIcon(props) { - return ( - - - - ); -} - -ObjectIcon.defaultProps = { - height: 20, - width: 20, - viewBox: "0 0 24 24", -}; diff --git a/web/apps/photos/src/components/icons/TextIcon.tsx b/web/apps/photos/src/components/icons/TextIcon.tsx deleted file mode 100644 index 62d37fbe28..0000000000 --- a/web/apps/photos/src/components/icons/TextIcon.tsx +++ /dev/null @@ -1,18 +0,0 @@ -export default function TextIcon(props) { - return ( - - - - ); -} - -TextIcon.defaultProps = { - height: 16, - width: 16, - viewBox: "0 0 28 28", -}; diff --git a/web/apps/photos/src/components/icons/UnPinIcon.tsx b/web/apps/photos/src/components/icons/UnPinIcon.tsx deleted file mode 100644 index da50e0a1a0..0000000000 --- a/web/apps/photos/src/components/icons/UnPinIcon.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import SvgIcon from "@mui/material/SvgIcon"; - -export const UnPinIcon = (props) => { - return ( - - - - - - - - - - - - - - ); -}; - -UnPinIcon.defaultProps = { - height: 20, - width: 20, -}; diff --git a/web/apps/photos/src/components/pages/gallery/PlanSelector.tsx b/web/apps/photos/src/components/pages/gallery/PlanSelector.tsx index 3e840eaa03..a64a302e46 100644 --- a/web/apps/photos/src/components/pages/gallery/PlanSelector.tsx +++ b/web/apps/photos/src/components/pages/gallery/PlanSelector.tsx @@ -1,5 +1,9 @@ import { genericRetriableErrorDialogAttributes } from "@/base/components/utils/dialog"; import log from "@/base/log"; +import { + getTotalFamilyUsage, + isPartOfFamily, +} from "@/new/photos/services/user"; import { AppContext } from "@/new/photos/types/context"; import { bytesInGB, formattedStorageByteSize } from "@/new/photos/utils/units"; import { openURL } from "@/new/photos/utils/web"; @@ -8,6 +12,7 @@ import { FluidContainer, SpaceBetweenFlex, } from "@ente/shared/components/Container"; +import { getData, LS_KEYS } from "@ente/shared/storage/localStorage"; import ArrowForward from "@mui/icons-material/ArrowForward"; import ChevronRight from "@mui/icons-material/ChevronRight"; import Close from "@mui/icons-material/Close"; @@ -34,7 +39,7 @@ import billingService, { type PlansResponse } from "services/billingService"; import { getFamilyPortalRedirectURL } from "services/userService"; import { Plan, PLAN_PERIOD, Subscription } from "types/billing"; import { SetLoading } from "types/gallery"; -import { BonusData } from "types/user"; +import { BonusData, UserDetails } from "types/user"; import { activateSubscription, cancelSubscription, @@ -52,8 +57,6 @@ import { updatePaymentMethod, updateSubscription, } from "utils/billing"; -import { getLocalUserDetails } from "utils/user"; -import { getTotalFamilyUsage, isPartOfFamily } from "utils/user/family"; interface PlanSelectorProps { modalView: boolean; @@ -796,3 +799,7 @@ const ManageSubscriptionButton = ({ children, ...props }: ButtonProps) => ( {children} ); + +function getLocalUserDetails(): UserDetails { + return getData(LS_KEYS.USER_DETAILS)?.value; +} diff --git a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx index 0f66a27ed6..64a44ff335 100644 --- a/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx +++ b/web/apps/photos/src/components/pages/gallery/PreviewCard.tsx @@ -1,3 +1,4 @@ +import { Overlay } from "@/base/components/mui/Container"; import log from "@/base/log"; import { EnteFile } from "@/media/file"; import { FileType } from "@/media/file-type"; @@ -11,7 +12,6 @@ import { } from "@/new/photos/components/PlaceholderThumbnails"; import { TRASH_SECTION } from "@/new/photos/services/collection"; import DownloadManager from "@/new/photos/services/download"; -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"; diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index 35b316b55c..7a1582b8e4 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -2,6 +2,7 @@ import { clientPackageName, staticAppTitle } from "@/base/app"; import { CustomHead } from "@/base/components/Head"; import { AttributedMiniDialog } from "@/base/components/MiniDialog"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; +import { Overlay } from "@/base/components/mui/Container"; import { AppNavbar } from "@/base/components/Navbar"; import { genericErrorDialogAttributes, @@ -18,12 +19,12 @@ import { updateAvailableForDownloadDialogAttributes, updateReadyToInstallDialogAttributes, } from "@/new/photos/components/utils/download"; +import { useLoadingBar } from "@/new/photos/components/utils/use-loading-bar"; import { photosDialogZIndex } from "@/new/photos/components/utils/z-index"; import DownloadManager from "@/new/photos/services/download"; import { runMigrations } from "@/new/photos/services/migrations"; import { initML, isMLSupported } from "@/new/photos/services/ml"; import { AppContext } from "@/new/photos/types/context"; -import { Overlay } from "@ente/shared/components/Container"; import DialogBox from "@ente/shared/components/DialogBox"; import { DialogBoxAttributes } from "@ente/shared/components/DialogBox/types"; import { MessageContainer } from "@ente/shared/components/MessageContainer"; @@ -34,11 +35,7 @@ import { getData, migrateKVToken, } from "@ente/shared/storage/localStorage"; -import { - getLocalMapEnabled, - getToken, - setLocalMapEnabled, -} from "@ente/shared/storage/localStorage/helpers"; +import { getToken } from "@ente/shared/storage/localStorage/helpers"; import { getTheme } from "@ente/shared/themes"; import { THEME_COLOR } from "@ente/shared/themes/constants"; import type { User } from "@ente/shared/user/types"; @@ -51,14 +48,11 @@ import isElectron from "is-electron"; import type { AppProps } from "next/app"; import { useRouter } from "next/router"; import "photoswipe/dist/photoswipe.css"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import LoadingBar from "react-top-loading-bar"; import { resumeExportsIfNeeded } from "services/export"; import { photosLogout } from "services/logout"; -import { - getFamilyPortalRedirectURL, - updateMapEnabledStatus, -} from "services/userService"; +import { getFamilyPortalRedirectURL } from "services/userService"; import "styles/global.css"; import { NotificationAttributes } from "types/Notification"; @@ -70,9 +64,6 @@ export default function App({ Component, pageProps }: AppProps) { typeof window !== "undefined" && !window.navigator.onLine, ); const [showNavbar, setShowNavBar] = useState(false); - const [mapEnabled, setMapEnabled] = useState(false); - const isLoadingBarRunning = useRef(false); - const loadingBar = useRef(null); const [dialogMessage, setDialogMessage] = useState(); const [messageDialogView, setMessageDialogView] = useState(false); const [watchFolderView, setWatchFolderView] = useState(false); @@ -83,14 +74,11 @@ export default function App({ Component, pageProps }: AppProps) { useState(null); const { showMiniDialog, miniDialogProps } = useAttributedMiniDialog(); + const { loadingBarRef, showLoadingBar, hideLoadingBar } = useLoadingBar(); const [themeColor, setThemeColor] = useLocalState( LS_KEYS.THEME, THEME_COLOR.DARK, ); - const [isCFProxyDisabled, setIsCFProxyDisabled] = useLocalState( - LS_KEYS.CF_PROXY_DISABLED, - false, - ); useEffect(() => { void setupI18n().finally(() => setIsI18nReady(true)); @@ -143,10 +131,6 @@ export default function App({ Component, pageProps }: AppProps) { }; }, []); - useEffect(() => { - setMapEnabled(getLocalMapEnabled()); - }, []); - useEffect(() => { if (!isElectron()) { return; @@ -207,23 +191,6 @@ export default function App({ Component, pageProps }: AppProps) { const showNavBar = (show: boolean) => setShowNavBar(show); - const updateMapEnabled = async (enabled: boolean) => { - await updateMapEnabledStatus(enabled); - setLocalMapEnabled(enabled); - setMapEnabled(enabled); - }; - - const startLoading = () => { - !isLoadingBarRunning.current && loadingBar.current?.continuousStart(); - isLoadingBarRunning.current = true; - }; - const finishLoading = () => { - setTimeout(() => { - isLoadingBarRunning.current && loadingBar.current?.complete(); - isLoadingBarRunning.current = false; - }, 100); - }; - // Use `onGenericError` instead. const somethingWentWrong = useCallback( () => @@ -236,7 +203,7 @@ export default function App({ Component, pageProps }: AppProps) { ); const onGenericError = useCallback((e: unknown) => { - log.error("Error", e); + log.error(e); showMiniDialog(genericErrorDialogAttributes()); }, []); @@ -246,8 +213,8 @@ export default function App({ Component, pageProps }: AppProps) { const appContext = { showNavBar, - startLoading, // <- changes on each render (TODO Fix) - finishLoading, // <- changes on each render + showLoadingBar, + hideLoadingBar, setDialogMessage, watchFolderView, setWatchFolderView, @@ -259,10 +226,6 @@ export default function App({ Component, pageProps }: AppProps) { showMiniDialog, somethingWentWrong, onGenericError, - mapEnabled, - updateMapEnabled, // <- changes on each render - isCFProxyDisabled, - setIsCFProxyDisabled, logout, }; @@ -278,7 +241,7 @@ export default function App({ Component, pageProps }: AppProps) { {isI18nReady && offline && t("OFFLINE_MSG")} - + (null); const [collectionNameMap, setCollectionNameMap] = useState( new Map(), @@ -70,42 +70,48 @@ export default function Deduplicate() { }, []); const syncWithRemote = async () => { - startLoading(); - const collections = await getLocalCollections(); - const collectionNameMap = new Map(); - for (const collection of collections) { - collectionNameMap.set(collection.id, collection.name); - } - setCollectionNameMap(collectionNameMap); - const files = await getLocalFiles(); - const duplicateFiles = await getDuplicates(files, collectionNameMap); - const currFileSizeMap = new Map(); - let toSelectFileIDs: number[] = []; - let count = 0; - for (const dupe of duplicateFiles) { - // select all except first file - toSelectFileIDs = [ - ...toSelectFileIDs, - ...dupe.files.slice(1).map((f) => f.id), - ]; - count += dupe.files.length - 1; - - for (const file of dupe.files) { - currFileSizeMap.set(file.id, dupe.size); + showLoadingBar(); + try { + const collections = await getLocalCollections(); + const collectionNameMap = new Map(); + for (const collection of collections) { + collectionNameMap.set(collection.id, collection.name); } + setCollectionNameMap(collectionNameMap); + const files = await getLocalFiles(); + const duplicateFiles = await getDuplicates( + files, + collectionNameMap, + ); + const currFileSizeMap = new Map(); + let toSelectFileIDs: number[] = []; + let count = 0; + for (const dupe of duplicateFiles) { + // select all except first file + toSelectFileIDs = [ + ...toSelectFileIDs, + ...dupe.files.slice(1).map((f) => f.id), + ]; + count += dupe.files.length - 1; + + for (const file of dupe.files) { + currFileSizeMap.set(file.id, dupe.size); + } + } + setDuplicates(duplicateFiles); + const selectedFiles = { + count: count, + ownCount: count, + collectionID: ALL_SECTION, + context: undefined, + }; + for (const fileID of toSelectFileIDs) { + selectedFiles[fileID] = true; + } + setSelected(selectedFiles); + } finally { + hideLoadingBar(); } - setDuplicates(duplicateFiles); - const selectedFiles = { - count: count, - ownCount: count, - collectionID: ALL_SECTION, - context: undefined, - }; - for (const fileID of toSelectFileIDs) { - selectedFiles[fileID] = true; - } - setSelected(selectedFiles); - finishLoading(); }; const duplicateFiles = useMemoSingleThreaded(() => { @@ -120,7 +126,7 @@ export default function Deduplicate() { const deleteFileHelper = async () => { try { - startLoading(); + showLoadingBar(); const selectedFiles = getSelectedFiles(selected, duplicateFiles); await trashFiles(selectedFiles); @@ -160,7 +166,7 @@ export default function Deduplicate() { } } finally { await syncWithRemote(); - finishLoading(); + hideLoadingBar(); } }; diff --git a/web/apps/photos/src/pages/gallery.tsx b/web/apps/photos/src/pages/gallery.tsx index 48081a92c1..ff039f7a67 100644 --- a/web/apps/photos/src/pages/gallery.tsx +++ b/web/apps/photos/src/pages/gallery.tsx @@ -1,3 +1,4 @@ +import { sessionExpiredDialogAttributes } from "@/accounts/components/LoginComponents"; import { stashRedirect } from "@/accounts/services/redirect"; import { NavbarBase } from "@/base/components/Navbar"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; @@ -43,7 +44,9 @@ import { setSearchCollectionsAndFiles, } from "@/new/photos/services/search"; import type { SearchOption } from "@/new/photos/services/search/types"; -import { AppContext } from "@/new/photos/types/context"; +import { initSettings } from "@/new/photos/services/settings"; +import { getLocalFamilyData } from "@/new/photos/services/user"; +import { useAppContext } from "@/new/photos/types/context"; import { splitByPredicate } from "@/utils/array"; import { ensure } from "@/utils/ensure"; import { @@ -100,14 +103,7 @@ import PlanSelector from "components/pages/gallery/PlanSelector"; import SelectedFileOptions from "components/pages/gallery/SelectedFileOptions"; import { t } from "i18next"; import { useRouter } from "next/router"; -import { - createContext, - useCallback, - useContext, - useEffect, - useRef, - useState, -} from "react"; +import { createContext, useCallback, useEffect, useRef, useState } from "react"; import { useDropzone } from "react-dropzone"; import { constructEmailList, @@ -135,8 +131,6 @@ import { handleCollectionOps, } from "utils/collection"; import { FILE_OPS_TYPE, getSelectedFiles, handleFileOps } from "utils/file"; -import { getSessionExpiredMessage } from "utils/ui"; -import { getLocalFamilyData } from "utils/user/family"; const defaultGalleryContext: GalleryContextType = { showPlanSelectorModal: () => null, @@ -231,12 +225,13 @@ export default function Gallery() { const resync = useRef<{ force: boolean; silent: boolean }>(); const { - startLoading, - finishLoading, + showLoadingBar, + hideLoadingBar, setDialogMessage, + showMiniDialog, logout, ...appContext - } = useContext(AppContext); + } = useAppContext(); const [userIDToEmailMap, setUserIDToEmailMap] = useState>(null); const [emailList, setEmailList] = useState(null); @@ -348,6 +343,7 @@ export default function Gallery() { if (!valid) { return; } + initSettings(); await downloadManager.init(token); setupSelectAllKeyBoardShortcutHandler(); dispatch({ type: "showAll" }); @@ -553,9 +549,8 @@ export default function Gallery() { }; }, [selectAll, clearSelection]); - const showSessionExpiredMessage = () => { - setDialogMessage(getSessionExpiredMessage(logout)); - }; + const showSessionExpiredDialog = () => + showMiniDialog(sessionExpiredDialogAttributes(logout)); const syncWithRemote = async (force = false, silent = false) => { if (!navigator.onLine) return; @@ -574,7 +569,7 @@ export default function Gallery() { if (!tokenValid) { throw new Error(CustomError.SESSION_EXPIRED); } - !silent && startLoading(); + !silent && showLoadingBar(); await preFileInfoSync(); const allCollections = await getAllLatestCollections(); const [hiddenCollections, collections] = splitByPredicate( @@ -614,7 +609,7 @@ export default function Gallery() { } catch (e) { switch (e.message) { case CustomError.SESSION_EXPIRED: - showSessionExpiredMessage(); + showSessionExpiredDialog(); break; case CustomError.KEY_MISSING: clearKeys(); @@ -626,7 +621,7 @@ export default function Gallery() { } finally { dispatch({ type: "clearTempDeleted" }); dispatch({ type: "clearTempHidden" }); - !silent && finishLoading(); + !silent && hideLoadingBar(); } syncInProgress.current = false; if (resync.current) { @@ -690,7 +685,7 @@ export default function Gallery() { const collectionOpsHelper = (ops: COLLECTION_OPS_TYPE) => async (collection: Collection) => { - startLoading(); + showLoadingBar(); try { setOpenCollectionSelector(false); const selectedFiles = getSelectedFiles(selected, filteredFiles); @@ -719,12 +714,12 @@ export default function Gallery() { content: t("generic_error_retry"), }); } finally { - finishLoading(); + hideLoadingBar(); } }; const fileOpsHelper = (ops: FILE_OPS_TYPE) => async () => { - startLoading(); + showLoadingBar(); try { // passing files here instead of filteredData for hide ops because we want to move all files copies to hidden collection const selectedFiles = getSelectedFiles( @@ -758,14 +753,14 @@ export default function Gallery() { content: t("generic_error_retry"), }); } finally { - finishLoading(); + hideLoadingBar(); } }; const showCreateCollectionModal = (ops: COLLECTION_OPS_TYPE) => { const callback = async (collectionName: string) => { try { - startLoading(); + showLoadingBar(); const collection = await createAlbum(collectionName); await collectionOpsHelper(ops)(collection); } catch (e) { @@ -777,7 +772,7 @@ export default function Gallery() { content: t("generic_error_retry"), }); } finally { - finishLoading(); + hideLoadingBar(); } }; return () => @@ -1031,6 +1026,7 @@ export default function Gallery() { isFirstUpload={areOnlySystemCollections( collectionSummaries, )} + showSessionExpiredMessage={showSessionExpiredDialog} {...{ dragAndDropFiles, openFileSelector, @@ -1041,7 +1037,6 @@ export default function Gallery() { fileSelectorZipFiles, uploadTypeSelectorIntent, uploadTypeSelectorView, - showSessionExpiredMessage, }} /> (null); const [publicCollection, setPublicCollection] = useState(null); const [errorMessage, setErrorMessage] = useState(null); - const appContext = useContext(AppContext); + const { showLoadingBar, hideLoadingBar, setDialogMessage } = + useAppContext(); const [loading, setLoading] = useState(true); const router = useRouter(); const [isPasswordProtected, setIsPasswordProtected] = @@ -185,7 +187,7 @@ export default function PublicCollectionGallery() { }; const showPublicLinkExpiredMessage = () => - appContext.setDialogMessage({ + setDialogMessage({ title: t("LINK_EXPIRED"), content: t("LINK_EXPIRED_MESSAGE"), @@ -239,6 +241,7 @@ export default function PublicCollectionGallery() { : await cryptoWorker.fromHex(ck); token.current = t; downloadManager.updateToken(token.current); + await updateShouldDisableCFUploadProxy(); collectionKey.current = dck; url.current = window.location.href; const localCollection = await getLocalPublicCollection( @@ -316,7 +319,7 @@ export default function PublicCollectionGallery() { const syncWithRemote = async () => { const collectionUID = getPublicCollectionUID(token.current); try { - appContext.startLoading(); + showLoadingBar(); setLoading(true); const [collection, userReferralCode] = await getPublicCollection( token.current, @@ -381,7 +384,7 @@ export default function PublicCollectionGallery() { log.error("failed to sync public album with remote", e); } } finally { - appContext.finishLoading(); + hideLoadingBar(); setLoading(false); } }; @@ -427,7 +430,7 @@ export default function PublicCollectionGallery() { throw e; } await syncWithRemote(); - appContext.finishLoading(); + hideLoadingBar(); } catch (e) { log.error("failed to verifyLinkPassword", e); setFieldError(`${t("generic_error_retry")} ${e.message}`); diff --git a/web/apps/photos/src/services/export/index.ts b/web/apps/photos/src/services/export/index.ts index e31e5d0494..53192409a7 100644 --- a/web/apps/photos/src/services/export/index.ts +++ b/web/apps/photos/src/services/export/index.ts @@ -14,7 +14,6 @@ import { getCollectionUserFacingName, } from "@/new/photos/services/collection"; import downloadManager from "@/new/photos/services/download"; -import { updateExifIfNeededAndPossible } from "@/new/photos/services/exif-update"; import { exportMetadataDirectoryName, exportTrashDirectoryName, @@ -939,16 +938,12 @@ class ExportService { try { const fileUID = getExportRecordFileUID(file); const originalFileStream = await downloadManager.getFile(file); - const updatedFileStream = await updateExifIfNeededAndPossible( - file, - originalFileStream, - ); if (file.metadata.fileType === FileType.livePhoto) { await this.exportLivePhoto( exportDir, fileUID, collectionExportPath, - updatedFileStream, + originalFileStream, file, ); } else { @@ -965,7 +960,7 @@ class ExportService { await writeStream( electron, `${collectionExportPath}/${fileExportName}`, - updatedFileStream, + originalFileStream, ); await this.addFileExportedRecord( exportDir, diff --git a/web/apps/photos/src/services/logout.ts b/web/apps/photos/src/services/logout.ts index fa36e4f8fa..5349914fb1 100644 --- a/web/apps/photos/src/services/logout.ts +++ b/web/apps/photos/src/services/logout.ts @@ -1,9 +1,10 @@ import { accountLogout } from "@/accounts/services/logout"; import log from "@/base/log"; +import { resetUploadState } from "@/gallery/upload"; import DownloadManager from "@/new/photos/services/download"; -import { clearFeatureFlagSessionState } from "@/new/photos/services/feature-flags"; import { logoutML, terminateMLWorker } from "@/new/photos/services/ml"; import { logoutSearch } from "@/new/photos/services/search"; +import { logoutSettings } from "@/new/photos/services/settings"; import exportService from "./export"; /** @@ -37,9 +38,15 @@ export const photosLogout = async () => { log.info("logout (photos)"); try { - clearFeatureFlagSessionState(); + logoutSettings(); } catch (e) { - ignoreError("feature-flag", e); + ignoreError("settings", e); + } + + try { + resetUploadState(); + } catch (e) { + ignoreError("upload", e); } try { diff --git a/web/apps/photos/src/services/sync.ts b/web/apps/photos/src/services/sync.ts index 012af2fe11..065fa45917 100644 --- a/web/apps/photos/src/services/sync.ts +++ b/web/apps/photos/src/services/sync.ts @@ -1,14 +1,12 @@ -import { triggerFeatureFlagsFetchIfNeeded } from "@/new/photos/services/feature-flags"; import { isMLSupported, mlStatusSync, mlSync } from "@/new/photos/services/ml"; import { searchDataSync } from "@/new/photos/services/search"; -import { syncMapEnabled } from "services/userService"; +import { syncSettings } from "@/new/photos/services/settings"; /** * Part 1 of {@link sync}. See TODO below for why this is split. */ export const preFileInfoSync = async () => { - triggerFeatureFlagsFetchIfNeeded(); - await Promise.all([isMLSupported && mlStatusSync()]); + await Promise.all([syncSettings(), isMLSupported && mlStatusSync()]); }; /** @@ -31,7 +29,7 @@ export const preFileInfoSync = async () => { * before doing the file sync and thus should run immediately after login. */ export const sync = async () => { - await Promise.all([syncMapEnabled(), searchDataSync()]); + await Promise.all([searchDataSync()]); // ML sync might take a very long time for initial indexing, so don't wait // for it to finish. void mlSync(); diff --git a/web/apps/photos/src/services/upload/upload-service.ts b/web/apps/photos/src/services/upload/upload-service.ts index 113d42b788..35a1937c60 100644 --- a/web/apps/photos/src/services/upload/upload-service.ts +++ b/web/apps/photos/src/services/upload/upload-service.ts @@ -37,6 +37,7 @@ import { } from "@/new/photos/services/upload/types"; import { detectFileTypeInfoFromChunk } from "@/new/photos/utils/detect-type"; import { readStream } from "@/new/photos/utils/native-stream"; +import { mergeUint8Arrays } from "@/utils/array"; import { ensure, ensureInteger, ensureNumber } from "@/utils/ensure"; import { CustomError, handleUploadError } from "@ente/shared/error"; import { addToCollection } from "services/collectionService"; @@ -1573,9 +1574,7 @@ async function combineChunksToFormUploadPart( if (done) { break; } - for (let index = 0; index < chunk.length; index++) { - combinedChunks.push(chunk[index]); - } + combinedChunks.push(chunk); } - return Uint8Array.from(combinedChunks); + return mergeUint8Arrays(combinedChunks); } diff --git a/web/apps/photos/src/services/upload/uploadManager.ts b/web/apps/photos/src/services/upload/uploadManager.ts index 96ec37c3c3..c3989ee91f 100644 --- a/web/apps/photos/src/services/upload/uploadManager.ts +++ b/web/apps/photos/src/services/upload/uploadManager.ts @@ -4,6 +4,7 @@ import { lowercaseExtension, nameAndExtension } from "@/base/file"; import log from "@/base/log"; import type { Electron } from "@/base/types/ipc"; import { ComlinkWorker } from "@/base/worker/comlink-worker"; +import { shouldDisableCFUploadProxy } from "@/gallery/upload"; import type { Collection } from "@/media/collection"; import { EncryptedEnteFile, EnteFile } from "@/media/file"; import { FileType } from "@/media/file-type"; @@ -25,7 +26,6 @@ import { getLocalPublicFiles, getPublicCollectionUID, } from "services/publicCollectionService"; -import { getDisableCFUploadProxyFlag } from "services/userService"; import watcher from "services/watch"; import { decryptFile, getUserOwnedFiles } from "utils/file"; import { @@ -331,7 +331,6 @@ class UploadManager { private publicUploadProps: PublicUploadProps; private uploaderName: string; private uiService: UIService; - private isCFUploadProxyDisabled: boolean = false; constructor() { this.uiService = new UIService(); @@ -341,15 +340,8 @@ class UploadManager { progressUpdater: ProgressUpdater, onUploadFile: (file: EnteFile) => void, publicCollectProps: PublicUploadProps, - isCFUploadProxyDisabled: boolean, ) { this.uiService.init(progressUpdater); - const remoteIsCFUploadProxyDisabled = - await getDisableCFUploadProxyFlag(); - if (remoteIsCFUploadProxyDisabled) { - isCFUploadProxyDisabled = remoteIsCFUploadProxyDisabled; - } - this.isCFUploadProxyDisabled = isCFUploadProxyDisabled; UploadService.init(publicCollectProps); this.onUploadFile = onUploadFile; this.publicUploadProps = publicCollectProps; @@ -543,7 +535,7 @@ class UploadManager { this.existingFiles, this.parsedMetadataJSONMap, worker, - this.isCFUploadProxyDisabled, + shouldDisableCFUploadProxy(), () => { this.abortIfCancelled(); }, @@ -897,25 +889,8 @@ const clusterLivePhotos = async ( }; /** - * [Note: Memory pressure when uploading video files] - * - * A user (Fedora 39 VM on Qubes OS with 32 GB RAM, both AppImage and RPM) has - * reported that their app runs out of memory when the app tries to upload - * multiple large videos simultaneously. For example, 4 parallel uploads of 4 - * 700 MB videos. - * - * I am unable to reproduce this: tested on macOS and Linux, with videos up to - * 3.8 G x 1 + 3 x 700 M uploaded in parallel. The memory usage remains constant - * as expected (hovering around 2 G), since we don't pull the entire videos in - * memory and instead do a streaming disk read + encryption + upload. - * - * The JavaScript heap for the renderer process (when we're running in the - * context of our desktop app) is limited to 4 GB. See - * https://www.electronjs.org/blog/v8-memory-cage. - * - * For now, add logs if our usage increases some high water mark. This is solely - * so we can better understand the issue if it arises again (and can deal with - * it in an informed manner). + * Add logs if our usage increases some high water mark. This is solely so that + * we have some indication in the logs if we get a user report of OOM crashes. */ const logAboutMemoryPressureIfNeeded = () => { if (!globalThis.electron) return; diff --git a/web/apps/photos/src/services/userService.ts b/web/apps/photos/src/services/userService.ts index 133c560584..171ebf7d2e 100644 --- a/web/apps/photos/src/services/userService.ts +++ b/web/apps/photos/src/services/userService.ts @@ -1,21 +1,13 @@ import { putAttributes } from "@/accounts/api/user"; import log from "@/base/log"; -import { apiURL, customAPIOrigin, familyAppOrigin } from "@/base/origins"; +import { apiURL, familyAppOrigin } from "@/base/origins"; +import { getLocalFamilyData, isPartOfFamily } from "@/new/photos/services/user"; import { ApiError } from "@ente/shared/error"; import HTTPService from "@ente/shared/network/HTTPService"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; -import { - getToken, - setLocalMapEnabled, -} from "@ente/shared/storage/localStorage/helpers"; -import { HttpStatusCode, type AxiosResponse } from "axios"; -import { - DeleteChallengeResponse, - GetFeatureFlagResponse, - GetRemoteStoreValueResponse, - UserDetails, -} from "types/user"; -import { getLocalFamilyData, isPartOfFamily } from "utils/user/family"; +import { getToken } from "@ente/shared/storage/localStorage/helpers"; +import { HttpStatusCode } from "axios"; +import { DeleteChallengeResponse, UserDetails } from "types/user"; const HAS_SET_KEYS = "hasSetKeys"; @@ -103,17 +95,6 @@ export const isTokenValid = async (token: string) => { } }; -export const getTwoFactorStatus = async () => { - const resp = await HTTPService.get( - await apiURL("/users/two-factor/status"), - null, - { - "X-Auth-Token": getToken(), - }, - ); - return resp.data["status"]; -}; - export const getUserDetailsV2 = async (): Promise => { try { const token = getToken(); @@ -187,87 +168,3 @@ export const deleteAccount = async ( throw e; } }; - -export const syncMapEnabled = async () => { - try { - const status = await getMapEnabledStatus(); - setLocalMapEnabled(status); - } catch (e) { - log.error("failed to sync map enabled status", e); - throw e; - } -}; - -export const getMapEnabledStatus = async () => { - try { - const token = getToken(); - const resp: AxiosResponse = - await HTTPService.get( - await apiURL("/remote-store"), - { - key: "mapEnabled", - defaultValue: false, - }, - { - "X-Auth-Token": token, - }, - ); - return resp.data.value === "true"; - } catch (e) { - log.error("failed to get map enabled status", e); - throw e; - } -}; - -export const updateMapEnabledStatus = async (newStatus: boolean) => { - try { - const token = getToken(); - await HTTPService.post( - await apiURL("/remote-store/update"), - { - key: "mapEnabled", - value: newStatus.toString(), - }, - null, - { - "X-Auth-Token": token, - }, - ); - } catch (e) { - log.error("failed to update map enabled status", e); - throw e; - } -}; - -/** - * Return true to disable the upload of files via Cloudflare Workers. - * - * These workers were introduced as a way of make file uploads faster: - * https://ente.io/blog/tech/making-uploads-faster/ - * - * By default, that's the route we take. However, during development or when - * self-hosting it can be convenient to turn this flag on to directly upload to - * the S3-compatible URLs returned by the ente API. - * - * Note the double negative (Enhancement: maybe remove the double negative, - * rename this to say getUseDirectUpload). - */ -export async function getDisableCFUploadProxyFlag(): Promise { - // If a custom origin is set, that means we're not running a production - // deployment (maybe we're running locally, or being self-hosted). - // - // In such cases, disable the Cloudflare upload proxy (which won't work for - // self-hosters), and instead just directly use the upload URLs that museum - // gives us. - if (await customAPIOrigin()) return true; - - try { - const featureFlags = ( - await fetch("https://static.ente.io/feature_flags.json") - ).json() as GetFeatureFlagResponse; - return featureFlags.disableCFUploadProxy; - } catch (e) { - log.error("failed to get feature flags", e); - return false; - } -} diff --git a/web/apps/photos/src/styles/global.css b/web/apps/photos/src/styles/global.css index f9adccd3d5..c30221d644 100644 --- a/web/apps/photos/src/styles/global.css +++ b/web/apps/photos/src/styles/global.css @@ -124,47 +124,3 @@ body { .pswp__caption--empty { display: none; } - -.bg-upload-progress-bar { - background-color: #51cd7c; -} - -.carousel-inner { - padding-bottom: 50px !important; -} - -.carousel-indicators li { - width: 10px; - height: 10px; - border-radius: 50%; - margin-right: 12px; -} - -.carousel-indicators .active { - background-color: #51cd7c; -} - -div.otp-input input { - width: 36px !important; - height: 36px; - margin: 0 10px; -} - -div.otp-input input::placeholder { - opacity: 0; -} - -div.otp-input input:not(:placeholder-shown), -div.otp-input input:focus { - border: 2px solid #51cd7c; - border-radius: 1px; - -webkit-transition: 0.5s; - transition: 0.5s; - outline: none; -} - -.flash-message { - padding: 16px; - display: flex; - align-items: center; -} diff --git a/web/apps/photos/src/types/user/index.ts b/web/apps/photos/src/types/user/index.ts index ca407980f8..bbdbd5d021 100644 --- a/web/apps/photos/src/types/user/index.ts +++ b/web/apps/photos/src/types/user/index.ts @@ -83,7 +83,3 @@ export interface CreateSRPSessionResponse { sessionID: string; srpB: string; } - -export interface GetFeatureFlagResponse { - disableCFUploadProxy?: boolean; -} diff --git a/web/apps/photos/src/utils/billing/index.ts b/web/apps/photos/src/utils/billing/index.ts index a1ff2c7b56..84d6b0c457 100644 --- a/web/apps/photos/src/utils/billing/index.ts +++ b/web/apps/photos/src/utils/billing/index.ts @@ -1,4 +1,8 @@ import log from "@/base/log"; +import { + getTotalFamilyUsage, + isPartOfFamily, +} from "@/new/photos/services/user"; import { SetDialogBoxAttributes } from "@ente/shared/components/DialogBox/types"; import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; import { t } from "i18next"; @@ -8,7 +12,6 @@ import { Plan, Subscription } from "types/billing"; import { SetLoading } from "types/gallery"; import { BonusData, UserDetails } from "types/user"; import { getSubscriptionPurchaseSuccessMessage } from "utils/ui"; -import { getTotalFamilyUsage, isPartOfFamily } from "utils/user/family"; const PAYMENT_PROVIDER_STRIPE = "stripe"; const FREE_PLAN = "free"; diff --git a/web/apps/photos/src/utils/file/index.ts b/web/apps/photos/src/utils/file/index.ts index c9f2280c7c..01680217db 100644 --- a/web/apps/photos/src/utils/file/index.ts +++ b/web/apps/photos/src/utils/file/index.ts @@ -16,7 +16,6 @@ import { ItemVisibility } from "@/media/file-metadata"; import { FileType } from "@/media/file-type"; import { decodeLivePhoto } from "@/media/live-photo"; import DownloadManager from "@/new/photos/services/download"; -import { updateExifIfNeededAndPossible } from "@/new/photos/services/exif-update"; import { isArchivedFile, updateMagicMetadata, @@ -79,9 +78,6 @@ export async function downloadFile(file: EnteFile) { const fileType = await detectFileTypeInfo( new File([fileBlob], file.metadata.title), ); - fileBlob = await new Response( - await updateExifIfNeededAndPossible(file, fileBlob.stream()), - ).blob(); fileBlob = new Blob([fileBlob], { type: fileType.mimeType }); const tempURL = URL.createObjectURL(fileBlob); downloadAndRevokeObjectURL(tempURL, file.metadata.title); @@ -397,10 +393,9 @@ async function downloadFileDesktop( const fs = electron.fs; const stream = await DownloadManager.getFile(file); - const updatedStream = await updateExifIfNeededAndPossible(file, stream); if (file.metadata.fileType === FileType.livePhoto) { - const fileBlob = await new Response(updatedStream).blob(); + const fileBlob = await new Response(stream).blob(); const { imageFileName, imageData, videoFileName, videoData } = await decodeLivePhoto(file.metadata.title, fileBlob); const imageExportName = await safeFileName( @@ -436,11 +431,7 @@ async function downloadFileDesktop( file.metadata.title, fs.exists, ); - await writeStream( - electron, - `${downloadDir}/${fileExportName}`, - updatedStream, - ); + await writeStream(electron, `${downloadDir}/${fileExportName}`, stream); } } diff --git a/web/apps/photos/src/utils/ui/index.tsx b/web/apps/photos/src/utils/ui/index.tsx index 497948d52d..f29d6179e2 100644 --- a/web/apps/photos/src/utils/ui/index.tsx +++ b/web/apps/photos/src/utils/ui/index.tsx @@ -13,7 +13,6 @@ export const getTrashFilesMessage = ( action: deleteFileHelper, text: t("MOVE_TO_TRASH"), variant: "critical", - autoFocus: true, }, close: { text: t("cancel") }, }); @@ -61,17 +60,3 @@ export const getSubscriptionPurchaseSuccessMessage = ( /> ), }); - -export const getSessionExpiredMessage = ( - action: () => void, -): DialogBoxAttributes => ({ - title: t("session_expired"), - content: t("session_expired_message"), - - nonClosable: true, - proceed: { - text: t("login"), - action, - variant: "accent", - }, -}); diff --git a/web/apps/photos/src/utils/user/family.ts b/web/apps/photos/src/utils/user/family.ts deleted file mode 100644 index 0456976cc2..0000000000 --- a/web/apps/photos/src/utils/user/family.ts +++ /dev/null @@ -1,43 +0,0 @@ -import log from "@/base/log"; -import type { FamilyData, FamilyMember } from "@/new/photos/services/user"; -import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; -import type { User } from "@ente/shared/user/types"; - -export function getLocalFamilyData(): FamilyData { - return getData(LS_KEYS.FAMILY_DATA); -} - -// isPartOfFamily return true if the current user is part of some family plan -export function isPartOfFamily(familyData: FamilyData): boolean { - return Boolean( - familyData && familyData.members && familyData.members.length > 0, - ); -} - -// hasNonAdminFamilyMembers return true if the admin user has members in his family -export function hasNonAdminFamilyMembers(familyData: FamilyData): boolean { - return Boolean(isPartOfFamily(familyData) && familyData.members.length > 1); -} - -export function isFamilyAdmin(familyData: FamilyData): boolean { - const familyAdmin: FamilyMember = getFamilyPlanAdmin(familyData); - const user: User = getData(LS_KEYS.USER); - return familyAdmin.email === user.email; -} - -export function getFamilyPlanAdmin(familyData: FamilyData): FamilyMember { - if (isPartOfFamily(familyData)) { - return familyData.members.find((x) => x.isAdmin); - } else { - log.error( - "invalid getFamilyPlanAdmin call - verify user is part of family plan before calling this method", - ); - } -} - -export function getTotalFamilyUsage(familyData: FamilyData): number { - return familyData.members.reduce( - (sum, currentMember) => sum + currentMember.usage, - 0, - ); -} diff --git a/web/apps/photos/src/utils/user/index.ts b/web/apps/photos/src/utils/user/index.ts deleted file mode 100644 index 7404fb5887..0000000000 --- a/web/apps/photos/src/utils/user/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { getData, LS_KEYS } from "@ente/shared/storage/localStorage"; -import { UserDetails } from "types/user"; - -export function getLocalUserDetails(): UserDetails { - return getData(LS_KEYS.USER_DETAILS)?.value; -} diff --git a/web/docs/dependencies.md b/web/docs/dependencies.md index ab544e2004..ba6d2f677b 100644 --- a/web/docs/dependencies.md +++ b/web/docs/dependencies.md @@ -132,7 +132,7 @@ with Next.js. For more details, see [translations.md](translations.md). -### Others +### Other UI components - [formik](https://github.com/jaredpalmer/formik) provides an easier to use abstraction for dealing with form state, validation and submission states @@ -140,6 +140,9 @@ For more details, see [translations.md](translations.md). - [react-select](https://react-select.com/) is used for search dropdowns. +- [react-otp-input](https://github.com/devfolioco/react-otp-input) is used to + render a segmented OTP input field for 2FA authentication. + ## Utilities - [comlink](https://github.com/GoogleChromeLabs/comlink) provides a minimal @@ -164,8 +167,7 @@ For more details, see [translations.md](translations.md). ## Media - [ExifReader](https://github.com/mattiasw/ExifReader) is used for Exif - parsing. [piexifjs](https://github.com/hMatoba/piexifjs) is used for writing - back Exif (only supports JPEG). + parsing. - [jszip](https://github.com/Stuk/jszip) is used for reading zip files in the web code (Live photos are zip files under the hood). Note that the desktop @@ -181,8 +183,6 @@ For more details, see [translations.md](translations.md). ## Photos app specific -### General - - [react-dropzone](https://github.com/react-dropzone/react-dropzone/) is a React hook to create a drag-and-drop input zone. @@ -193,13 +193,21 @@ For more details, see [translations.md](translations.md). - [chrono-node](https://github.com/wanasit/chrono) is used for parsing natural language queries into dates for showing search results. -### Face search - -- [matrix](https://github.com/mljs/matrix) is mathematical matrix abstraction. - It is used alongwith +- [matrix](https://github.com/mljs/matrix) is mathematical matrix abstraction + by the machine learning code. It is used alongwith [similarity-transformation](https://github.com/shaileshpandit/similarity-transformation-js) during face alignment. +### UI + +- [react-top-loading-bar](https://github.com/klendi/react-top-loading-bar) is + used for showing a progress indicator for global actions (This shouldn't be + used always, it is only meant as a fallback when there isn't an otherwise + suitable place for showing a local activity indicator). + +- [pure-react-carousel](https://github.com/express-labs/pure-react-carousel) + is used for the feature carousel on the welcome (login / signup) screen. + ## Auth app specific - [otpauth](https://github.com/hectorm/otpauth) is used for the generation of diff --git a/web/docs/new.md b/web/docs/new.md index c850e97141..8485a5dcd1 100644 --- a/web/docs/new.md +++ b/web/docs/new.md @@ -12,6 +12,9 @@ development, here is a recommended workflow: 4. Install **node** on your machine. There are myriad ways to do this, here are some examples: + - OS agnostic: Install [NVM](https://github.com/nvm-sh/nvm), then + `nvm install 20 && corepack enable`. + - macOS: `brew install node@20` - Ubuntu: `sudo apt install nodejs npm && sudo npm i -g corepack` @@ -20,7 +23,6 @@ development, here is a recommended workflow: manager (**Yarn**): ```sh - corepack enable ``` diff --git a/web/package.json b/web/package.json index 2dac8360a7..0641a36e44 100644 --- a/web/package.json +++ b/web/package.json @@ -13,7 +13,6 @@ "build:cast": "yarn workspace cast next build", "build:payments": "yarn workspace payments build", "build:photos": "yarn workspace photos next build", - "build:staff": "yarn workspace staff build", "dev": "yarn dev:photos", "dev:accounts": "yarn workspace accounts next dev -p 3001", "dev:albums": "yarn workspace photos next dev -p 3002", @@ -21,7 +20,6 @@ "dev:cast": "yarn workspace cast next dev -p 3001", "dev:payments": "yarn workspace payments dev", "dev:photos": "yarn workspace photos next dev -p 3000", - "dev:staff": "yarn workspace staff dev", "lint": "concurrently --names 'prettier,eslint,tsc' \"yarn prettier --check --log-level warn .\" \"yarn workspaces run eslint --report-unused-disable-directives .\" \"yarn workspaces run tsc\"", "lint-fix": "concurrently --names 'prettier,eslint,tsc' \"yarn prettier --write --log-level warn .\" \"yarn workspaces run eslint --report-unused-disable-directives --fix .\" \"yarn workspaces run tsc\"", "preview": "yarn preview:photos", @@ -29,8 +27,7 @@ "preview:auth": "yarn build:auth && python3 -m http.server -d apps/auth/out 3000", "preview:cast": "yarn build:cast && python3 -m http.server -d apps/accounts/out 3001", "preview:payments": "yarn workspace payments preview", - "preview:photos": "yarn build:photos && python3 -m http.server -d apps/photos/out 3000", - "preview:staff": "yarn workspace staff preview" + "preview:photos": "yarn build:photos && python3 -m http.server -d apps/photos/out 3000" }, "resolutions": { "@emotion/cache": "11.13.1", diff --git a/web/packages/accounts/api/user.ts b/web/packages/accounts/api/user.ts index 667eaf10c9..763dbb190a 100644 --- a/web/packages/accounts/api/user.ts +++ b/web/packages/accounts/api/user.ts @@ -176,14 +176,3 @@ export const setRecoveryKey = async (token: string, recoveryKey: RecoveryKey) => "X-Auth-Token": token, }, ); - -export const disableTwoFactor = async () => { - await HTTPService.post( - await apiURL("/users/two-factor/disable"), - null, - undefined, - { - "X-Auth-Token": getToken(), - }, - ); -}; diff --git a/web/packages/accounts/components/two-factor/VerifyForm.tsx b/web/packages/accounts/components/two-factor/VerifyForm.tsx index 3a3d7ac7f3..765b8aa235 100644 --- a/web/packages/accounts/components/two-factor/VerifyForm.tsx +++ b/web/packages/accounts/components/two-factor/VerifyForm.tsx @@ -4,10 +4,10 @@ import { CenteredFlex, VerticallyCentered, } from "@ente/shared/components/Container"; -import { Box, Typography } from "@mui/material"; +import { Box, Typography, styled } from "@mui/material"; import { Formik, type FormikHelpers } from "formik"; import { t } from "i18next"; -import { useRef, useState } from "react"; +import { useState } from "react"; import OtpInput from "react-otp-input"; interface formValues { @@ -25,7 +25,7 @@ export type VerifyTwoFactorCallback = ( export default function VerifyTwoFactor(props: Props) { const [waiting, setWaiting] = useState(false); - const otpInputRef = useRef(null); + const [shouldAutoFocus, setShouldAutoFocus] = useState(true); const markSuccessful = async () => { setWaiting(false); @@ -40,11 +40,13 @@ export default function VerifyTwoFactor(props: Props) { await props.onSubmit(otp, markSuccessful); } catch (e) { resetForm(); - for (let i = 0; i < 6; i++) { - otpInputRef.current?.focusPrevInput(); - } const message = e instanceof Error ? e.message : ""; setFieldError("otp", `${t("generic_error_retry")} ${message}`); + // Workaround (toggling shouldAutoFocus) to reset the focus back to + // the first input field in case of errors. + // https://github.com/devfolioco/react-otp-input/issues/420 + setShouldAutoFocus(false); + setTimeout(() => setShouldAutoFocus(true), 100); } setWaiting(false); }; @@ -71,17 +73,17 @@ export default function VerifyTwoFactor(props: Props) { -} + renderInput={(props) => ( + + )} /> {errors.otp && ( @@ -107,3 +109,23 @@ export default function VerifyTwoFactor(props: Props) { ); } + +const IndividualInput = styled("input")( + ({ theme }) => ` + font-size: 1.5rem; + padding: 4px; + width: 40px !important; + aspect-ratio: 1; + margin-inline: 8px; + border: 1px solid ${theme.colors.accent.A700}; + border-radius: 1px; + outline-color: ${theme.colors.accent.A300}; + transition: 0.5s; + + ${theme.breakpoints.down("sm")} { + font-size: 1rem; + padding: 4px; + width: 32px !important; + } +`, +); diff --git a/web/packages/accounts/package.json b/web/packages/accounts/package.json index 574276df1a..c5f7b0b881 100644 --- a/web/packages/accounts/package.json +++ b/web/packages/accounts/package.json @@ -5,6 +5,7 @@ "dependencies": { "@/base": "*", "@ente/eslint-config": "*", - "@ente/shared": "*" + "@ente/shared": "*", + "react-otp-input": "^3.1.1" } } diff --git a/web/packages/accounts/pages/two-factor/setup.tsx b/web/packages/accounts/pages/two-factor/setup.tsx index 2fbba6345d..2f1cc66bd4 100644 --- a/web/packages/accounts/pages/two-factor/setup.tsx +++ b/web/packages/accounts/pages/two-factor/setup.tsx @@ -68,7 +68,7 @@ const Page: React.FC = () => { - {t("TWO_FACTOR")} + {t("two_factor")} diff --git a/web/packages/accounts/pages/two-factor/verify.tsx b/web/packages/accounts/pages/two-factor/verify.tsx index a60a3fc935..3d22e11f24 100644 --- a/web/packages/accounts/pages/two-factor/verify.tsx +++ b/web/packages/accounts/pages/two-factor/verify.tsx @@ -75,7 +75,7 @@ const Page: React.FC = ({ appContext }) => { return ( - {t("TWO_FACTOR")} + {t("two_factor")} diff --git a/web/packages/base/components/EnteDrawer.tsx b/web/packages/base/components/EnteDrawer.tsx deleted file mode 100644 index e6fc35bb15..0000000000 --- a/web/packages/base/components/EnteDrawer.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { Drawer, styled } from "@mui/material"; - -export const EnteDrawer = styled(Drawer)(({ theme }) => ({ - "& .MuiPaper-root": { - maxWidth: "375px", - width: "100%", - scrollbarWidth: "thin", - padding: theme.spacing(1), - }, -})); diff --git a/web/packages/base/components/ErrorIndicator.tsx b/web/packages/base/components/ErrorIndicator.tsx new file mode 100644 index 0000000000..fb2afe7087 --- /dev/null +++ b/web/packages/base/components/ErrorIndicator.tsx @@ -0,0 +1,41 @@ +import ErrorOutline from "@mui/icons-material/ErrorOutline"; +import { Box, Stack, Typography } from "@mui/material"; +import { t } from "i18next"; +import type React from "react"; + +/** + * An error message indicator, styled to complement {@link ActivityIndicator}. + * + * If a child is provided, it is used as the error message to show (after being + * wrapped in a suitable {@link Typography}). Otherwise the default generic + * error message is shown. + */ +export const ActivityErrorIndicator: React.FC = ({ + children, +}) => ( + + + + {children ?? t("generic_error")} + + +); + +/** + * An smaller error message indicator suitable for being shown above or below + * text fields. + * + * If a child is provided, it is used as the error message to show (after being + * wrapped in a suitable {@link Typography}). Otherwise the default generic + * error message is shown. + */ +export const InlineErrorIndicator: React.FC = ({ + children, +}) => ( + + + + {children ?? t("generic_error")} + + +); diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index a0ba423e47..a8b4767903 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -13,6 +13,7 @@ import { import { t } from "i18next"; import React, { useState } from "react"; import log from "../log"; +import { InlineErrorIndicator } from "./ErrorIndicator"; /** * Customize the contents of an {@link AttributedMiniDialog}. @@ -161,12 +162,6 @@ export const AttributedMiniDialog: React.FC< const { PaperProps, ...rest } = props; - const errorIndicator = phase == "failed" && ( - - {t("generic_error")} - - ); - const loadingButton = attributes.continue && ( - {errorIndicator} + {phase == "failed" && } {attributes.buttonDirection == "row" ? ( <> {cancelButton} diff --git a/web/packages/base/components/Titlebar.tsx b/web/packages/base/components/Titlebar.tsx index e46fb92ce0..1029dff467 100644 --- a/web/packages/base/components/Titlebar.tsx +++ b/web/packages/base/components/Titlebar.tsx @@ -13,6 +13,8 @@ interface TitlebarProps { actionButton?: JSX.Element; } +// TODO: Deprecated in favor of SidebarDrawerTitlebarProps where possible (will +// revisit the remaining use cases once those have migrated). export const Titlebar: React.FC = ({ title, caption, diff --git a/web/packages/base/components/mui/Container.tsx b/web/packages/base/components/mui/Container.tsx index 45e6e2913e..abaa0e2dce 100644 --- a/web/packages/base/components/mui/Container.tsx +++ b/web/packages/base/components/mui/Container.tsx @@ -1,5 +1,19 @@ import { styled } from "@mui/material"; +/** + * A flexbox with justify content set to space-between and center alignment. + * + * There is also another SpaceBetweenFlex in the old shared package, but that + * one also sets width: 100%. As such, that one should be considered deprecated + * and its uses moved to this one when possible (so that we can then see where + * the width: 100% is essential). + */ +export const SpaceBetweenFlex = styled("div")` + display: flex; + justify-content: space-between; + align-items: center; +`; + /** * A flex child that fills the entire flex direction, and shows its children * after centering them both vertically and horizontally. @@ -10,3 +24,15 @@ export const CenteredBox = styled("div")` justify-content: center; align-items: center; `; + +/** + * An absolute positioned div that fills the entire nearest relatively + * positioned ancestor. + */ +export const Overlay = styled("div")` + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; +`; diff --git a/web/packages/base/components/mui/SidebarDrawer.tsx b/web/packages/base/components/mui/SidebarDrawer.tsx new file mode 100644 index 0000000000..5ce5d12559 --- /dev/null +++ b/web/packages/base/components/mui/SidebarDrawer.tsx @@ -0,0 +1,141 @@ +import ArrowBack from "@mui/icons-material/ArrowBack"; +import Close from "@mui/icons-material/Close"; +import { + Box, + Drawer, + IconButton, + Stack, + styled, + Typography, + type DrawerProps, +} from "@mui/material"; +import React from "react"; +import type { ModalVisibilityProps } from "../utils/modal"; +import { SpaceBetweenFlex } from "./Container"; + +/** + * A MUI {@link Drawer} with a standard set of styling that we use for our left + * and right sidebar panels. + * + * It is width limited to 375px, and always at full width. It also has a default + * padding. + */ +export const SidebarDrawer = styled(Drawer)(({ theme }) => ({ + "& .MuiPaper-root": { + maxWidth: "375px", + width: "100%", + scrollbarWidth: "thin", + padding: theme.spacing(1), + }, +})); + +/** + * Common props for a {@link NestedSidebarDrawer} component. In addition to the + * regular modal visibility controls for opening and closing itself, these also + * surface an option to close the entire drawer. + */ +export type NestedSidebarDrawerVisibilityProps = ModalVisibilityProps & { + /** + * Called when the user wants to close the entire stack of drawers. + * + * Note that this does not automatically imply onClose. Each step in the + * nesting will have to chain their own onCloses to construct a new + * `onRootClose` suitable for passing to its children. + */ + onRootClose: () => void; +}; + +/** + * A variant of {@link SidebarDrawer} for second level, nested drawers that are + * shown atop an already visible {@link SidebarDrawer}. + */ +export const NestedSidebarDrawer: React.FC< + NestedSidebarDrawerVisibilityProps & DrawerProps +> = ({ onClose, onRootClose, ...rest }) => { + // Intercept backdrop taps and repurpose them to close the entire stack. + const handleClose: DrawerProps["onClose"] = (_, reason) => { + if (reason == "backdropClick") { + onClose(); + onRootClose(); + } else { + onClose(); + } + }; + + // MUI doesn't (currently, AFAIK) have support for nested drawers, so we + // emulate that by showing a drawer atop another. To make it fit, we need to + // modify a few knobs. + + return ( + + ); +}; + +type SidebarDrawerTitlebarProps = Pick< + NestedSidebarDrawerVisibilityProps, + "onClose" | "onRootClose" +> & { + /** Title for the drawer. */ + title: string; + /** An optional secondary caption shown below the title. */ + caption?: string; + /** + * An optional action button shown alongwith the close button at the + * trailing edge of the sidebar. + */ + actionButton?: React.ReactNode; +}; + +/** + * A bar with a title and back / close buttons, suitable for being used in + * tandem with a {@link NestedSidebarDrawer}. + */ +export const SidebarDrawerTitlebar: React.FC = ({ + title, + caption, + onClose, + onRootClose, + actionButton, +}) => ( + + + + + + + {actionButton && actionButton} + + + + + + + + {title} + + + {caption} + + + +); diff --git a/web/packages/base/components/utils/modal.ts b/web/packages/base/components/utils/modal.ts index 0a2dd1588e..0b40c9d786 100644 --- a/web/packages/base/components/utils/modal.ts +++ b/web/packages/base/components/utils/modal.ts @@ -11,22 +11,6 @@ export interface ModalVisibilityProps { onClose: () => void; } -/** - * Common props for a nested drawer component. In addition to the regular modal - * visibility controls for opening and closing itself, these also surface an - * option to close the entire drawer. - */ -export type NestedDrawerVisibilityProps = ModalVisibilityProps & { - /** - * Called when the user wants to close the entire stack of drawers. - * - * Note that this does not automatically imply onClose. Each step in the - * nesting will have to chain their own onCloses to construct a new - * `onRootClose` suitable for passing to its children. - */ - onRootClose: () => void; -}; - /** * A convenience hook for keeping the state for opening and closing a modal, and * exposing a function to close the modal whose identity is stable. diff --git a/web/packages/base/i18n.ts b/web/packages/base/i18n.ts index 9c842829b7..3e4dc5ca47 100644 --- a/web/packages/base/i18n.ts +++ b/web/packages/base/i18n.ts @@ -30,6 +30,7 @@ export const supportedLocales = [ "pl-PL" /* Polish */, "it-IT" /* Italian */, "lt-LT" /* Lithuanian */, + "uk-UA" /* Ukrainian */, ] as const; /** The type of {@link supportedLocales}. */ @@ -183,6 +184,8 @@ const closestSupportedLocale = ( return "it-IT"; } else if (ls.startsWith("lt")) { return "lt-LT"; + } else if (ls.startsWith("uk")) { + return "uk-UA"; } } diff --git a/web/packages/base/locales/ar-SA/translation.json b/web/packages/base/locales/ar-SA/translation.json index f945260ddf..bc07799a53 100644 --- a/web/packages/base/locales/ar-SA/translation.json +++ b/web/packages/base/locales/ar-SA/translation.json @@ -47,6 +47,7 @@ "close_key": "إغلاق (Esc)", "enter_file_name": "إسم الملف", "close": "إغلاق", + "yes": "", "no": "لا", "nothing_here": "", "upload": "تحميل", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "وجوه غير محددة", - "OBJECTS": "عناصر", - "TEXT": "نص", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "معلومات ", "INFO_OPTION": "معلومات (I)", "file_name": "إسم الملف", @@ -238,7 +256,6 @@ "location": "الموقع", "view_on_map": "عرض على OpenStreetMap", "map": "خريطة", - "map_settings": "إعدادات الخريطة", "enable_map": "تمكين الخريطة", "enable_maps_confirm": "تمكين الخرائط ؟", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "لا توجد بيانات Exif", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "المصادقة الثنائية", + "two_factor": "", + "two_factor_authentication": "المصادقة الثنائية", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "أدخل الرمز يدويا", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "مسح رمز QR بدلاً من ذلك", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "تفعيل", "enabled": "مفعل", "LOST_DEVICE": "", "INCORRECT_CODE": "رمز غير صحيح", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "تعطيل", "reconfigure": "إعادة التهيئة", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "تحديث", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "تحديث", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "تصدير البيانات", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/be-BY/translation.json b/web/packages/base/locales/be-BY/translation.json index 8e990166e6..2eef302bee 100644 --- a/web/packages/base/locales/be-BY/translation.json +++ b/web/packages/base/locales/be-BY/translation.json @@ -4,18 +4,18 @@ "intro_slide_2_title": "", "intro_slide_2": "", "intro_slide_3_title": "", - "intro_slide_3": "", + "intro_slide_3": "Android, iOS, Інтэрнэт, Камп’ютар", "login": "Увайсці", "sign_up": "Рэгістрацыя", - "NEW_USER": "", - "EXISTING_USER": "", - "enter_name": "", + "NEW_USER": "Новы ў Ente", + "EXISTING_USER": "Існуючы карыстальнік", + "enter_name": "Увядзіце імя", "PUBLIC_UPLOADER_NAME_MESSAGE": "", - "ENTER_EMAIL": "", - "EMAIL_ERROR": "", - "required": "", + "ENTER_EMAIL": "Увядзіце адрас электроннай пошты", + "EMAIL_ERROR": "Увядзіце сапраўдны адрас электроннай пошты", + "required": "патрабуецца", "EMAIL_SENT": "", - "CHECK_INBOX": "", + "CHECK_INBOX": "Праверце свае ўваходныя лісты (і спам) для завяршэння праверкі", "ENTER_OTT": "Код пацвярджэння", "RESEND_MAIL": "Паўторна адправіць код", "VERIFY": "", @@ -28,14 +28,14 @@ "password": "Пароль", "link_password_description": "", "unlock": "Разблакіраваць", - "SET_PASSPHRASE": "", + "SET_PASSPHRASE": "Задаць пароль", "VERIFY_PASSPHRASE": "Увайсці", "INCORRECT_PASSPHRASE": "Няправільны пароль", "ENTER_ENC_PASSPHRASE": "", "PASSPHRASE_DISCLAIMER": "", "key_generation_in_progress": "", "PASSPHRASE_HINT": "Пароль", - "CONFIRM_PASSPHRASE": "", + "CONFIRM_PASSPHRASE": "Пацвердзіць пароль", "REFERRAL_CODE_HINT": "", "REFERRAL_INFO": "", "PASSPHRASE_MATCH_ERROR": "", @@ -45,17 +45,18 @@ "create_albums": "", "enter_album_name": "", "close_key": "", - "enter_file_name": "", + "enter_file_name": "Назва файла", "close": "Закрыць", + "yes": "", "no": "Не", "nothing_here": "", - "upload": "", - "import": "", - "add_photos": "", - "add_more_photos": "", + "upload": "Запампаваць", + "import": "Імпартаваць", + "add_photos": "Дадаць фота", + "add_more_photos": "Дадаць больш фота", "add_photos_count_one": "", "add_photos_count": "", - "select_photos": "", + "select_photos": "Абраць фота", "FILE_UPLOAD": "", "UPLOAD_STAGE_MESSAGE": { "0": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/bg-BG/translation.json b/web/packages/base/locales/bg-BG/translation.json index 86407f4604..54528ffdcf 100644 --- a/web/packages/base/locales/bg-BG/translation.json +++ b/web/packages/base/locales/bg-BG/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/ca-ES/translation.json b/web/packages/base/locales/ca-ES/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/ca-ES/translation.json +++ b/web/packages/base/locales/ca-ES/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/da-DK/translation.json b/web/packages/base/locales/da-DK/translation.json index 647f22a614..e5cc660f1d 100644 --- a/web/packages/base/locales/da-DK/translation.json +++ b/web/packages/base/locales/da-DK/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/de-DE/translation.json b/web/packages/base/locales/de-DE/translation.json index a41f43486f..bfc505b2f7 100644 --- a/web/packages/base/locales/de-DE/translation.json +++ b/web/packages/base/locales/de-DE/translation.json @@ -47,6 +47,7 @@ "close_key": "Schließen (Esc)", "enter_file_name": "Dateiname", "close": "Schließen", + "yes": "", "no": "Nein", "nothing_here": "", "upload": "Hochladen", @@ -228,9 +229,26 @@ "indexing_fetching": "Indizes abrufen ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "Indiziere Personen in {{nSyncedFiles, number}} Fotos...", "indexing_done": "{{nSyncedFiles, number}} Fotos wurden indiziert", - "UNIDENTIFIED_FACES": "Unidentifizierte Gesichter", - "OBJECTS": "Objekte", - "TEXT": "Text", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Info ", "INFO_OPTION": "Info (I)", "file_name": "Dateiname", @@ -238,7 +256,6 @@ "location": "Standort", "view_on_map": "In OpenStreetMap öffnen", "map": "Karte", - "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.

", @@ -250,28 +267,26 @@ "no_exif": "Keine Exif-Daten", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Zwei-Faktor", - "TWO_FACTOR_AUTHENTICATION": "Zwei-Faktor-Authentifizierung", + "two_factor": "Zwei-Faktor", + "two_factor_authentication": "Zwei-Faktor-Authentifizierung", "TWO_FACTOR_QR_INSTRUCTION": "Scanne den QR-Code unten mit deiner bevorzugten Authentifizierungs-App", "ENTER_CODE_MANUALLY": "Geben Sie den Code manuell ein", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Bitte gib diesen Code in deiner bevorzugten Authentifizierungs-App ein", "SCAN_QR_CODE": "QR‐Code stattdessen scannen", - "ENABLE_TWO_FACTOR": "Zwei-Faktor-Authentifizierung aktivieren", + "enable_two_factor": "Zwei-Faktor-Authentifizierung aktivieren", "enable": "Aktivieren", "enabled": "Aktiviert", "LOST_DEVICE": "Zwei-Faktor-Gerät verloren", "INCORRECT_CODE": "Falscher Code", - "TWO_FACTOR_INFO": "Fügen Sie eine zusätzliche Sicherheitsebene hinzu, indem Sie mehr als Ihre E-Mail und Ihr Passwort benötigen, um sich mit Ihrem Account anzumelden", - "DISABLE_TWO_FACTOR_LABEL": "Deaktiviere die Zwei-Faktor-Authentifizierung", - "UPDATE_TWO_FACTOR_LABEL": "Authentifizierungsgerät aktualisieren", + "two_factor_info": "Fügen Sie eine zusätzliche Sicherheitsebene hinzu, indem Sie mehr als Ihre E-Mail und Ihr Passwort benötigen, um sich mit Ihrem Account anzumelden", "disable": "Deaktivieren", "reconfigure": "Neu einrichten", - "UPDATE_TWO_FACTOR": "Zweiten Faktor aktualisieren", - "UPDATE_TWO_FACTOR_MESSAGE": "Fahren Sie fort, werden alle Ihre zuvor konfigurierten Authentifikatoren ungültig", - "UPDATE": "Aktualisierung", - "DISABLE_TWO_FACTOR": "Zweiten Faktor deaktivieren", - "DISABLE_TWO_FACTOR_MESSAGE": "Bist du sicher, dass du die Zwei-Faktor-Authentifizierung deaktivieren willst", - "TWO_FACTOR_DISABLE_FAILED": "Fehler beim Deaktivieren des zweiten Faktors, bitte versuchen Sie es erneut", + "reconfigure_two_factor_hint": "Authentifizierungsgerät aktualisieren", + "update_two_factor": "Zweiten Faktor aktualisieren", + "update_two_factor_message": "Fahren Sie fort, werden alle Ihre zuvor konfigurierten Authentifikatoren ungültig", + "update": "Aktualisierung", + "disable_two_factor": "Zweiten Faktor deaktivieren", + "disable_two_factor_message": "Bist du sicher, dass du die Zwei-Faktor-Authentifizierung deaktivieren willst", "EXPORT_DATA": "Daten exportieren", "select_folder": "Ordner auswählen", "select_zips": "Zip-Dateien auswählen", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "Dateien in einem freigegebenen Album können nicht gelöscht werden", "CONFIRM_SELF_REMOVE_MESSAGE": "Ausgewählte Elemente werden aus diesem Album entfernt. Elemente, die sich nur in diesem Album befinden, werden nach Unkategorisiert verschoben.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Einige der Elemente, die du entfernst, wurden von anderen Nutzern hinzugefügt und du wirst den Zugriff auf sie verlieren.", - "sort_by_creation_time_ascending": "Ältestem", - "sort_by_updation_time_descending": "Zuletzt aktualisiert", - "sort_by_name": "Name", + "oldest": "Ältestem", + "last_updated": "Zuletzt aktualisiert", + "name": "", "FIX_CREATION_TIME": "Zeit reparieren", "FIX_CREATION_TIME_IN_PROGRESS": "Zeit wird repariert", "CREATION_TIME_UPDATED": "Datei-Zeit aktualisiert", @@ -594,8 +609,8 @@ "ROTATION": "Drehen", "reset": "Zurücksetzen", "PHOTO_EDITOR": "Foto-Editor", - "FASTER_UPLOAD": "Schnelleres Hochladen", - "FASTER_UPLOAD_DESCRIPTION": "Uploads über nahegelegene Server leiten", + "faster_upload": "Schnelleres Hochladen", + "faster_upload_description": "Uploads über nahegelegene Server leiten", "cast_album_to_tv": "Album auf Fernseher wiedergeben", "enter_cast_pin_code": "Gib den Code auf dem Fernseher unten ein, um dieses Gerät zu koppeln.", "pair_device_to_tv": "Geräte koppeln", diff --git a/web/packages/base/locales/el-GR/translation.json b/web/packages/base/locales/el-GR/translation.json index 0d23d41829..71dd9396b3 100644 --- a/web/packages/base/locales/el-GR/translation.json +++ b/web/packages/base/locales/el-GR/translation.json @@ -47,6 +47,7 @@ "close_key": "Κλείσιμο (Esc)", "enter_file_name": "Όνομα αρχείου", "close": "Κλείσιμο", + "yes": "", "no": "Όχι", "nothing_here": "", "upload": "Μεταφόρτωση", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "Απροσδιόριστα πρόσωπα", - "OBJECTS": "αντικείμενα", - "TEXT": "κείμενο", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Πληροφορίες ", "INFO_OPTION": "Πληροφορίες (I)", "file_name": "Όνομα αρχείου", @@ -238,7 +256,6 @@ "location": "Τοποθεσία", "view_on_map": "Προβολή στο OpenStreetMap", "map": "Χάρτης", - "map_settings": "Ρυθμίσεις Χάρτη", "enable_map": "Ενεργοποίηση χάρτη", "enable_maps_confirm": "Ενεργοποίηση Χαρτών;", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "Χωρίς δεδομένα Exif", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "Αυθεντικοποίηση δύο παραγόντων", + "two_factor": "", + "two_factor_authentication": "Αυθεντικοποίηση δύο παραγόντων", "TWO_FACTOR_QR_INSTRUCTION": "Σαρώστε τον παρακάτω κωδικό QR με την αγαπημένη σας εφαρμογή αυθεντικοποίησης", "ENTER_CODE_MANUALLY": "Εισάγετε τον κωδικό χειροκίνητα", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "Ενεργοποίηση", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "Εσφαλμένος κωδικός", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "Απενεργοποίηση", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "Ενημέρωση", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "Ενημέρωση", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "Εξαγωγή δεδομένων", "select_folder": "Επιλέξτε φάκελο", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "Τελευταία ενημέρωση", - "sort_by_name": "Όνομα", + "oldest": "", + "last_updated": "Τελευταία ενημέρωση", + "name": "Όνομα", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "Ο χρόνος αρχείου ενημερώθηκε", @@ -594,8 +609,8 @@ "ROTATION": "Περιστροφή", "reset": "Επαναφορά", "PHOTO_EDITOR": "Επεξεργαστής φωτογραφιών", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "Αναπαραγωγή άλμπουμ στην τηλεόραση", "enter_cast_pin_code": "", "pair_device_to_tv": "Ζεύξη συσκευών", diff --git a/web/packages/base/locales/en-US/translation.json b/web/packages/base/locales/en-US/translation.json index e54390813f..16338eaccf 100644 --- a/web/packages/base/locales/en-US/translation.json +++ b/web/packages/base/locales/en-US/translation.json @@ -47,6 +47,7 @@ "close_key": "Close (Esc)", "enter_file_name": "File name", "close": "Close", + "yes": "Yes", "no": "No", "nothing_here": "Nothing here yet", "upload": "Upload", @@ -228,9 +229,26 @@ "indexing_fetching": "Fetching indexes ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "Indexing people in {{nSyncedFiles, number}} photos...", "indexing_done": "Indexed {{nSyncedFiles, number}} photos", - "UNIDENTIFIED_FACES": "Unidentified faces", - "OBJECTS": "objects", - "TEXT": "text", + "syncing_wait": "Syncing...", + "people_empty_too_few": "People will be shown here when there are sufficient photos of a person", + "unnamed_person": "Unnamed person", + "add_a_name": "Add a name", + "new_person": "New person", + "add_name": "Add name", + "rename_person": "Rename person", + "reset_person_confirm": "Reset person?", + "reset_person_confirm_message": "The name, face groupings and suggestions for this person will be reset", + "ignore": "Ignore", + "ignore_person_confirm": "Ignore person?", + "ignore_person_confirm_message": "This face grouping will not be shown in the people list", + "ignored": "Ignored", + "show_person": "Show person", + "review_suggestions": "Review suggestions", + "saved_choices": "Saved choices", + "discard_changes": "Discard changes", + "discard_changes_confirm_message": "You have unsaved changes. These will be lost if you close without saving", + "people_suggestions_finding": "Finding similar faces...", + "people_suggestions_empty": "No more suggestions for now", "INFO": "Info ", "INFO_OPTION": "Info (I)", "file_name": "File name", @@ -238,40 +256,37 @@ "location": "Location", "view_on_map": "View on OpenStreetMap", "map": "Map", - "map_settings": "Map settings", "enable_map": "Enable map", - "enable_maps_confirm": "Enable 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_map": "Disable map", - "disable_maps_confirm": "Disable Maps?", + "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", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Two-factor", - "TWO_FACTOR_AUTHENTICATION": "Two-factor authentication", + "two_factor": "Two-factor", + "two_factor_authentication": "Two-factor authentication", "TWO_FACTOR_QR_INSTRUCTION": "Scan the QR code below with your favorite authenticator app", "ENTER_CODE_MANUALLY": "Enter the code manually", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Please enter this code in your favorite authenticator app", "SCAN_QR_CODE": "Scan QR code instead", - "ENABLE_TWO_FACTOR": "Enable two-factor", + "enable_two_factor": "Enable two-factor", "enable": "Enable", "enabled": "Enabled", "LOST_DEVICE": "Lost two-factor device", "INCORRECT_CODE": "Incorrect code", - "TWO_FACTOR_INFO": "Add an additional layer of security by requiring more than your email and password to log in to your account", - "DISABLE_TWO_FACTOR_LABEL": "Disable two-factor authentication", - "UPDATE_TWO_FACTOR_LABEL": "Update your authenticator device", + "two_factor_info": "Add an additional layer of security by requiring more than your email and password to log in to your account", "disable": "Disable", "reconfigure": "Reconfigure", - "UPDATE_TWO_FACTOR": "Update two-factor", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuing forward will void any previously configured authenticators", - "UPDATE": "Update", - "DISABLE_TWO_FACTOR": "Disable two-factor", - "DISABLE_TWO_FACTOR_MESSAGE": "Are you sure you want to disable your two-factor authentication", - "TWO_FACTOR_DISABLE_FAILED": "Failed to disable two factor, please try again", + "reconfigure_two_factor_hint": "Update your authenticator device", + "update_two_factor": "Update two-factor", + "update_two_factor_message": "Continuing forward will void any previously configured authenticators", + "update": "Update", + "disable_two_factor": "Disable two-factor", + "disable_two_factor_message": "Are you sure you want to disable your two-factor authentication", "EXPORT_DATA": "Export data", "select_folder": "Select folder", "select_zips": "Select zips", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "You cannot delete files in a shared album", "CONFIRM_SELF_REMOVE_MESSAGE": "Selected items will be removed from this album. Items which are only in this album will be moved to Uncategorized.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Some of the items you are removing were added by other people, and you will lose access to them.", - "sort_by_creation_time_ascending": "Oldest", - "sort_by_updation_time_descending": "Last updated", - "sort_by_name": "Name", + "oldest": "Oldest", + "last_updated": "Last updated", + "name": "Name", "FIX_CREATION_TIME": "Fix time", "FIX_CREATION_TIME_IN_PROGRESS": "Fixing time", "CREATION_TIME_UPDATED": "File time updated", @@ -594,8 +609,8 @@ "ROTATION": "Rotation", "reset": "Reset", "PHOTO_EDITOR": "Photo Editor", - "FASTER_UPLOAD": "Faster uploads", - "FASTER_UPLOAD_DESCRIPTION": "Route uploads through nearby servers", + "faster_upload": "Faster uploads", + "faster_upload_description": "Route uploads through nearby servers", "cast_album_to_tv": "Play album on TV", "enter_cast_pin_code": "Enter the code you see on the TV below to pair this device.", "pair_device_to_tv": "Pair devices", diff --git a/web/packages/base/locales/es-ES/translation.json b/web/packages/base/locales/es-ES/translation.json index e53662be20..507ee306f3 100644 --- a/web/packages/base/locales/es-ES/translation.json +++ b/web/packages/base/locales/es-ES/translation.json @@ -47,6 +47,7 @@ "close_key": "Cerrar (Esc)", "enter_file_name": "Nombre del archivo", "close": "Cerrar", + "yes": "", "no": "No", "nothing_here": "", "upload": "Cargar", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "Indexando personas en {{nSyncedFiles, number}} fotos...", "indexing_done": "", - "UNIDENTIFIED_FACES": "Caras no identificadas", - "OBJECTS": "objetos", - "TEXT": "texto", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Info ", "INFO_OPTION": "Info (I)", "file_name": "Nombre del archivo", @@ -238,40 +256,37 @@ "location": "Localización", "view_on_map": "Ver en OpenStreetMap", "map": "Mapa", - "map_settings": "", "enable_map": "Activar mapa", - "enable_maps_confirm": "¿Activar Mapas?", + "enable_maps_confirm": "¿Activar mapas?", "enable_maps_confirm_message": "", "disable_map": "Desactivar mapa", - "disable_maps_confirm": "¿Desactivar Mapas?", + "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", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Dos factores", - "TWO_FACTOR_AUTHENTICATION": "Autenticación de dos factores", + "two_factor": "Dos factores", + "two_factor_authentication": "Autenticación de dos factores", "TWO_FACTOR_QR_INSTRUCTION": "Escanea el código QR de abajo con tu aplicación de autenticación favorita", "ENTER_CODE_MANUALLY": "Ingrese el código manualmente", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Por favor, introduce este código en tu aplicación de autenticación favorita", "SCAN_QR_CODE": "Escanear código QR en su lugar", - "ENABLE_TWO_FACTOR": "Activar dos factores", + "enable_two_factor": "Activar dos factores", "enable": "Activar", "enabled": "", "LOST_DEVICE": "Perdido el dispositivo de doble factor", "INCORRECT_CODE": "Código incorrecto", - "TWO_FACTOR_INFO": "Añade una capa adicional de seguridad al requerir más de tu email y contraseña para iniciar sesión en tu cuenta", - "DISABLE_TWO_FACTOR_LABEL": "Deshabilitar la autenticación de dos factores", - "UPDATE_TWO_FACTOR_LABEL": "Actualice su dispositivo de autenticación", + "two_factor_info": "Añade una capa adicional de seguridad al requerir más de tu email y contraseña para iniciar sesión en tu cuenta", "disable": "Desactivar", "reconfigure": "Reconfigurar", - "UPDATE_TWO_FACTOR": "Actualizar doble factor", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuar adelante anulará los autenticadores previamente configurados", - "UPDATE": "Actualizar", - "DISABLE_TWO_FACTOR": "Desactivar doble factor", - "DISABLE_TWO_FACTOR_MESSAGE": "¿Estás seguro de que desea deshabilitar la autenticación de doble factor?", - "TWO_FACTOR_DISABLE_FAILED": "Error al desactivar dos factores, inténtalo de nuevo", + "reconfigure_two_factor_hint": "Actualice su dispositivo de autenticación", + "update_two_factor": "Actualizar doble factor", + "update_two_factor_message": "Continuar adelante anulará los autenticadores previamente configurados", + "update": "Actualizar", + "disable_two_factor": "Desactivar doble factor", + "disable_two_factor_message": "¿Estás seguro de que desea deshabilitar la autenticación de doble factor?", "EXPORT_DATA": "Exportar datos", "select_folder": "Seleccionar carpeta", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "No puedes eliminar archivos de un álbum compartido", "CONFIRM_SELF_REMOVE_MESSAGE": "Los elementos seleccionados serán eliminados de este álbum. Los elementos que estén sólo en este álbum serán movidos a Sin categorizar.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Algunos de los elementos que estás eliminando fueron añadidos por otras personas, y perderás el acceso a ellos.", - "sort_by_creation_time_ascending": "Antiguo", - "sort_by_updation_time_descending": "Última actualización", - "sort_by_name": "Nombre", + "oldest": "Antiguo", + "last_updated": "Última actualización", + "name": "Nombre", "FIX_CREATION_TIME": "Fijar hora", "FIX_CREATION_TIME_IN_PROGRESS": "Fijar hora", "CREATION_TIME_UPDATED": "Hora del archivo actualizada", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/et-EE/translation.json b/web/packages/base/locales/et-EE/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/et-EE/translation.json +++ b/web/packages/base/locales/et-EE/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/fa-IR/translation.json b/web/packages/base/locales/fa-IR/translation.json index 62157117f2..f6149bebed 100644 --- a/web/packages/base/locales/fa-IR/translation.json +++ b/web/packages/base/locales/fa-IR/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/fi-FI/translation.json b/web/packages/base/locales/fi-FI/translation.json index b8ab67d9b5..ade0c47604 100644 --- a/web/packages/base/locales/fi-FI/translation.json +++ b/web/packages/base/locales/fi-FI/translation.json @@ -47,6 +47,7 @@ "close_key": "Sulje (Esc)", "enter_file_name": "Tiedoston nimi", "close": "Sulje", + "yes": "", "no": "Ei", "nothing_here": "", "upload": "Lataa", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/fr-FR/translation.json b/web/packages/base/locales/fr-FR/translation.json index 42600bdb9f..57db7befdf 100644 --- a/web/packages/base/locales/fr-FR/translation.json +++ b/web/packages/base/locales/fr-FR/translation.json @@ -47,6 +47,7 @@ "close_key": "Fermer (Échap)", "enter_file_name": "Nom du fichier", "close": "Fermer", + "yes": "", "no": "Non", "nothing_here": "", "upload": "Charger", @@ -228,9 +229,26 @@ "indexing_fetching": "Récupération des index ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "Indexation des personnes dans {{nSyncedFiles, number}} photos...", "indexing_done": "Indexation des {{nSyncedFiles, number}} photos", - "UNIDENTIFIED_FACES": "Visages non-identifiés", - "OBJECTS": "objets", - "TEXT": "texte", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Info ", "INFO_OPTION": "Info (I)", "file_name": "Nom de fichier", @@ -238,7 +256,6 @@ "location": "Emplacement", "view_on_map": "Visualiser sur OpenStreetMap", "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.

", @@ -250,28 +267,26 @@ "no_exif": "Aucune donnée Exif", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Double authentification", - "TWO_FACTOR_AUTHENTICATION": "Authentification double-facteur", + "two_factor": "Double authentification", + "two_factor_authentication": "Authentification double-facteur", "TWO_FACTOR_QR_INSTRUCTION": "Scannez le QRCode ci-dessous avec une appli d'authentification", "ENTER_CODE_MANUALLY": "Saisir le code manuellement", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Veuillez saisir ce code dans votre appli d'authentification", "SCAN_QR_CODE": "Scannez le QRCode de préférence", - "ENABLE_TWO_FACTOR": "Activer la double-authentification", + "enable_two_factor": "Activer la double-authentification", "enable": "Activer", "enabled": "Activé", "LOST_DEVICE": "Perte de l'appareil identificateur", "INCORRECT_CODE": "Code non valide", - "TWO_FACTOR_INFO": "Rajoutez une couche de sécurité supplémentaire afin de pas utiliser simplement votre e-mail et mot de passe pour vous connecter à votre compte", - "DISABLE_TWO_FACTOR_LABEL": "Désactiver la double-authentification", - "UPDATE_TWO_FACTOR_LABEL": "Mise à jour de votre appareil identificateur", + "two_factor_info": "Rajoutez une couche de sécurité supplémentaire afin de pas utiliser simplement votre e-mail et mot de passe pour vous connecter à votre compte", "disable": "Désactiver", "reconfigure": "Reconfigurer", - "UPDATE_TWO_FACTOR": "Mise à jour de la double-authentification", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuer annulera tous les identificateurs précédemment configurés", - "UPDATE": "Mise à jour", - "DISABLE_TWO_FACTOR": "Désactiver la double-authentification", - "DISABLE_TWO_FACTOR_MESSAGE": "Êtes-vous certains de vouloir désactiver la double-authentification", - "TWO_FACTOR_DISABLE_FAILED": "Échec de désactivation de la double-authentification, veuillez réessayer", + "reconfigure_two_factor_hint": "Mise à jour de votre appareil identificateur", + "update_two_factor": "Mise à jour de la double-authentification", + "update_two_factor_message": "Continuer annulera tous les identificateurs précédemment configurés", + "update": "Mise à jour", + "disable_two_factor": "Désactiver la double-authentification", + "disable_two_factor_message": "Êtes-vous certains de vouloir désactiver la double-authentification", "EXPORT_DATA": "Exporter les données", "select_folder": "Sélectionner un dossier", "select_zips": "Sélectionner les zips", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "Vous ne pouvez pas supprimer les fichiers d'un album partagé", "CONFIRM_SELF_REMOVE_MESSAGE": "Choisir les objets qui seront retirés de cet album. Ceux qui sont présents uniquement dans cet album seront déplacés comme hors catégorie.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Certains des objets que vous êtes en train de retirer ont été ajoutés par d'autres personnes, vous perdrez l'accès vers ces objets.", - "sort_by_creation_time_ascending": "Plus anciens", - "sort_by_updation_time_descending": "Dernière mise à jour", - "sort_by_name": "Nom", + "oldest": "Plus anciens", + "last_updated": "Dernière mise à jour", + "name": "Nom", "FIX_CREATION_TIME": "Réajuster l'heure", "FIX_CREATION_TIME_IN_PROGRESS": "Réajustement de l'heure", "CREATION_TIME_UPDATED": "L'heure du fichier a été réajustée", @@ -594,8 +609,8 @@ "ROTATION": "Rotation", "reset": "Réinitialiser", "PHOTO_EDITOR": "Éditeur de photos", - "FASTER_UPLOAD": "Chargements plus rapides", - "FASTER_UPLOAD_DESCRIPTION": "Router les chargements vers les serveurs à proximité", + "faster_upload": "Chargements plus rapides", + "faster_upload_description": "Router les chargements vers les serveurs à proximité", "cast_album_to_tv": "Jouer l'album sur la TV", "enter_cast_pin_code": "Entrez le code que vous voyez sur la TV ci-dessous pour appairer cet appareil.", "pair_device_to_tv": "Associer les appareils", diff --git a/web/packages/base/locales/gu-IN/translation.json b/web/packages/base/locales/gu-IN/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/gu-IN/translation.json +++ b/web/packages/base/locales/gu-IN/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/hi-IN/translation.json b/web/packages/base/locales/hi-IN/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/hi-IN/translation.json +++ b/web/packages/base/locales/hi-IN/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/id-ID/translation.json b/web/packages/base/locales/id-ID/translation.json index 0e5742ce24..3558c949c1 100644 --- a/web/packages/base/locales/id-ID/translation.json +++ b/web/packages/base/locales/id-ID/translation.json @@ -47,6 +47,7 @@ "close_key": "Tutup (Esc)", "enter_file_name": "Nama file", "close": "Tutup", + "yes": "", "no": "Tidak", "nothing_here": "", "upload": "Unggah", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Info ", "INFO_OPTION": "Informasi (I)", "file_name": "Nama file", @@ -238,40 +256,37 @@ "location": "", "view_on_map": "Lihat di OpenStreetMap", "map": "Peta", - "map_settings": "Pengaturan Peta", "enable_map": "Aktifkan peta", - "enable_maps_confirm": "Aktifkan Peta?", + "enable_maps_confirm": "Aktifkan peta?", "enable_maps_confirm_message": "", "disable_map": "Nonaktifkan peta", - "disable_maps_confirm": "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", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Autentikasi dua langkah", - "TWO_FACTOR_AUTHENTICATION": "Autentikasi dua langkah", + "two_factor": "Autentikasi dua langkah", + "two_factor_authentication": "Autentikasi dua langkah", "TWO_FACTOR_QR_INSTRUCTION": "Pindai kode QR di bawah menggunakan app autentikator favoritmu", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Masukkan kode ini ke app autentikator favoritmu", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "Aktifkan autentikasi dua langkah", + "enable_two_factor": "Aktifkan autentikasi dua langkah", "enable": "Aktifkan", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "Kode salah", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "Nonaktifkan autentikasi dua langkah", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "Nonaktifkan", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "Nonaktifkan autentikasi dua langkah", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "Gagal menonaktifkan autentikasi dua langkah, silakan coba lagi", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "Nonaktifkan autentikasi dua langkah", + "disable_two_factor_message": "", "EXPORT_DATA": "Ekspor data", "select_folder": "Pilih folder", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "Nama", + "oldest": "", + "last_updated": "", + "name": "Nama", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "Editor Foto", - "FASTER_UPLOAD": "Pengunggahan lebih cepat", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "Pengunggahan lebih cepat", + "faster_upload_description": "", "cast_album_to_tv": "Putar album di TV", "enter_cast_pin_code": "Masukkan kode yang ditampilkan TV di bawah untuk menautkan perangkat ini.", "pair_device_to_tv": "Tautkan perangkat", diff --git a/web/packages/base/locales/is-IS/translation.json b/web/packages/base/locales/is-IS/translation.json index f3426643cd..292b9e4e04 100644 --- a/web/packages/base/locales/is-IS/translation.json +++ b/web/packages/base/locales/is-IS/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "Loka", + "yes": "", "no": "Nei", "nothing_here": "", "upload": "Hlaða upp", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/it-IT/translation.json b/web/packages/base/locales/it-IT/translation.json index ead0a22393..b2b9ac439b 100644 --- a/web/packages/base/locales/it-IT/translation.json +++ b/web/packages/base/locales/it-IT/translation.json @@ -47,6 +47,7 @@ "close_key": "Chiudi (Esc)", "enter_file_name": "Nome del file", "close": "Chiudi", + "yes": "", "no": "No", "nothing_here": "Non c'e ancora niente qui", "upload": "Carica", @@ -228,9 +229,26 @@ "indexing_fetching": "Recupero degli indici ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "Indicizzazione delle persone in {{nSyncedFiles, number}} foto...", "indexing_done": "Indicizzate {{nSyncedFiles, number}} foto", - "UNIDENTIFIED_FACES": "Volti non identificati", - "OBJECTS": "oggetti", - "TEXT": "testo", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Info ", "INFO_OPTION": "Informazioni (I)", "file_name": "Nome file", @@ -238,40 +256,37 @@ "location": "Posizione", "view_on_map": "Guarda su OpenStreetMap", "map": "Mappa", - "map_settings": "Impostazioni Mappa", "enable_map": "Attivare mappa", - "enable_maps_confirm": "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.

", - "disable_map": "Disattivare Mappa", - "disable_maps_confirm": "Disattivare Mappa?", + "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", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Due fattori", - "TWO_FACTOR_AUTHENTICATION": "Autenticazione a due fattori", + "two_factor": "Due fattori", + "two_factor_authentication": "Autenticazione a due fattori", "TWO_FACTOR_QR_INSTRUCTION": "Scansiona il codice QR qui sotto con la tua app di autenticazione preferita", "ENTER_CODE_MANUALLY": "Inserisci il codice manualmente", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Inserisci questo codice nella tua app di autenticazione preferita", "SCAN_QR_CODE": "Oppure scansiona il codice QR", - "ENABLE_TWO_FACTOR": "Attiva due fattori", + "enable_two_factor": "Attiva due fattori", "enable": "Attiva", "enabled": "Abilitato", "LOST_DEVICE": "Non ho più l'accesso al dispositivo a due fattori", "INCORRECT_CODE": "Codice errato", - "TWO_FACTOR_INFO": "Aggiungi un ulteriore livello di sicurezza richiedendo più informazioni rispetto a email e password per eseguire l'accesso al tuo account", - "DISABLE_TWO_FACTOR_LABEL": "Disabilita l'autenticazione a due fattori", - "UPDATE_TWO_FACTOR_LABEL": "Aggiorna il tuo dispositivo di autenticazione", + "two_factor_info": "Aggiungi un ulteriore livello di sicurezza richiedendo più informazioni rispetto a email e password per eseguire l'accesso al tuo account", "disable": "Disabilita", "reconfigure": "Riconfigura", - "UPDATE_TWO_FACTOR": "Aggiorna autenticazione a due fattori", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuare invaliderà qualsiasi autenticatore configurato in precedenza", - "UPDATE": "Aggiorna", - "DISABLE_TWO_FACTOR": "Disabilita autenticazione a due fattori", - "DISABLE_TWO_FACTOR_MESSAGE": "Sei sicuro di voler disattivare l'autenticazione a due fattori", - "TWO_FACTOR_DISABLE_FAILED": "Impossibile disattivare autenticazione a due fattori, si prega di riprovare", + "reconfigure_two_factor_hint": "Aggiorna il tuo dispositivo di autenticazione", + "update_two_factor": "Aggiorna autenticazione a due fattori", + "update_two_factor_message": "Continuare invaliderà qualsiasi autenticatore configurato in precedenza", + "update": "Aggiorna", + "disable_two_factor": "Disabilita autenticazione a due fattori", + "disable_two_factor_message": "Sei sicuro di voler disattivare l'autenticazione a due fattori", "EXPORT_DATA": "Esporta dati", "select_folder": "Seleziona cartella", "select_zips": "Seleziona i file zip", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "Non puoi eliminare file in un album condiviso", "CONFIRM_SELF_REMOVE_MESSAGE": "Gli elementi selezionati saranno rimossi da questo album. Gli elementi che si trovano solo in questo album saranno spostati in Senza categoria.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Alcuni degli elementi che stai rimuovendo sono stati aggiunti da altre persone e ne perderai l'accesso.", - "sort_by_creation_time_ascending": "Meno recente", - "sort_by_updation_time_descending": "Ultimo aggiornamento", - "sort_by_name": "Nome", + "oldest": "Meno recente", + "last_updated": "Ultimo aggiornamento", + "name": "Nome", "FIX_CREATION_TIME": "Correggi data", "FIX_CREATION_TIME_IN_PROGRESS": "Sto correggendo la data", "CREATION_TIME_UPDATED": "Data del file aggiornata", @@ -594,8 +609,8 @@ "ROTATION": "Rotazione", "reset": "Reimposta", "PHOTO_EDITOR": "Editor Foto", - "FASTER_UPLOAD": "Upload più veloci", - "FASTER_UPLOAD_DESCRIPTION": "Effettua l'upload attraverso i server vicini", + "faster_upload": "Upload più veloci", + "faster_upload_description": "Effettua l'upload attraverso i server vicini", "cast_album_to_tv": "Riproduci album sulla TV", "enter_cast_pin_code": "Inserisci il codice che vedi sulla TV qui sotto per associare questo dispositivo.", "pair_device_to_tv": "Associa dispositivi", diff --git a/web/packages/base/locales/ja-JP/translation.json b/web/packages/base/locales/ja-JP/translation.json index 52bd4606d6..7383ff808d 100644 --- a/web/packages/base/locales/ja-JP/translation.json +++ b/web/packages/base/locales/ja-JP/translation.json @@ -47,6 +47,7 @@ "close_key": "閉じる (Esc)", "enter_file_name": "ファイル名", "close": "閉じる", + "yes": "", "no": "いいえ", "nothing_here": "まだ何もありません", "upload": "アップロード", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/km-KH/translation.json b/web/packages/base/locales/km-KH/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/km-KH/translation.json +++ b/web/packages/base/locales/km-KH/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/ko-KR/translation.json b/web/packages/base/locales/ko-KR/translation.json index 44328cc20f..1ae2e517e1 100644 --- a/web/packages/base/locales/ko-KR/translation.json +++ b/web/packages/base/locales/ko-KR/translation.json @@ -47,6 +47,7 @@ "close_key": "닫기 (Esc)", "enter_file_name": "파일 이름", "close": "닫기", + "yes": "", "no": "아니오", "nothing_here": "", "upload": "업로드", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/lt-LT/translation.json b/web/packages/base/locales/lt-LT/translation.json index 5d3c4252a4..739e2cf95d 100644 --- a/web/packages/base/locales/lt-LT/translation.json +++ b/web/packages/base/locales/lt-LT/translation.json @@ -7,14 +7,14 @@ "intro_slide_3": "„Android“, „iOS“, internete, darbalaukyje", "login": "Prisijungti", "sign_up": "Registruotis", - "NEW_USER": "Naujas platformoje „Ente“", + "NEW_USER": "Naujas sistemoje „Ente“", "EXISTING_USER": "Esamas naudotojas", "enter_name": "Įveskite vardą", "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", - "EMAIL_SENT": "Patvirtinimo kodas išsiųstas į {{email}}", + "EMAIL_SENT": "Patvirtinimo kodas išsiųstas adresu {{email}}", "CHECK_INBOX": "Patikrinkite savo gautieją (ir šlamštą), kad užbaigtumėte patvirtinimą", "ENTER_OTT": "Patvirtinimo kodas", "RESEND_MAIL": "Siųsti kodą iš naujo", @@ -47,6 +47,7 @@ "close_key": "Uždaryti (Gr)", "enter_file_name": "Failo pavadinimas", "close": "Uždaryti", + "yes": "", "no": "Ne", "nothing_here": "Kol kas nieko čia nėra", "upload": "Įkelti", @@ -228,9 +229,26 @@ "indexing_fetching": "Gaunami indeksai ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "Indeksuojami asmenys, esantys {{nSyncedFiles, number}} nuotraukose...", "indexing_done": "Indeksuotos {{nSyncedFiles, number}} nuotraukos", - "UNIDENTIFIED_FACES": "Neatpažinti veidai", - "OBJECTS": "objektai", - "TEXT": "tekstas", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "informacija ", "INFO_OPTION": "Informacija (I)", "file_name": "Failo pavadinimas", @@ -238,7 +256,6 @@ "location": "Vietovė", "view_on_map": "Peržiūrėti žemėlapyje „OpenStreetMap“", "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ų.

", @@ -250,28 +267,26 @@ "no_exif": "Nėra Exif duomenų", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Dvigubas tapatybės nustatymas", - "TWO_FACTOR_AUTHENTICATION": "Dvigubas tapatybės nustatymas", + "two_factor": "Dvigubas tapatybės nustatymas", + "two_factor_authentication": "Dvigubas tapatybės nustatymas", "TWO_FACTOR_QR_INSTRUCTION": "Skenuokite toliau esantį QR kodą su mėgstama autentifikatoriaus programa", "ENTER_CODE_MANUALLY": "Įvesti kodą rankiniu būdu", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Įveskite šį kodą savo mėgstamoje autentifikatoriaus programoje", "SCAN_QR_CODE": "Vietoj to skenuoti QR kodą", - "ENABLE_TWO_FACTOR": "Įjungti dvigubą tapatybės nustatymą", + "enable_two_factor": "Įjungti dvigubą tapatybės nustatymą", "enable": "Įjungti", "enabled": "Įjungta", "LOST_DEVICE": "Prarastas dvigubo tapatybės nustatymo įrenginys", "INCORRECT_CODE": "Neteisingas kodas.", - "TWO_FACTOR_INFO": "Pridėkite papildomą saugumo lygį, reikalaudami daugiau nei tik el. pašto ir slaptažodžio, kad prisijungtumėte prie savo paskyros", - "DISABLE_TWO_FACTOR_LABEL": "Išjungti dvigubo tapatybės nustatymą", - "UPDATE_TWO_FACTOR_LABEL": "Atnaujinti autentifikatoriaus įrenginį", + "two_factor_info": "Pridėkite papildomą saugumo lygį, reikalaudami daugiau nei tik el. pašto ir slaptažodžio, kad prisijungtumėte prie savo paskyros", "disable": "Išjungti", "reconfigure": "Perkonfigūruoti", - "UPDATE_TWO_FACTOR": "Atnaujinti dvigubą tapatybės nustatymą", - "UPDATE_TWO_FACTOR_MESSAGE": "Tęsiant toliau, visi anksčiau sukonfigūruoti autentifikatoriai bus anuliuoti", - "UPDATE": "Atnaujinti", - "DISABLE_TWO_FACTOR": "Išjungti dvigubą tapatybės nustatymą", - "DISABLE_TWO_FACTOR_MESSAGE": "Ar tikrai norite išjungti dvigubo tapatybės nustatymą?", - "TWO_FACTOR_DISABLE_FAILED": "Nepavyko išjungti dvigubo tapatybės nustatymo. Bandykite dar kartą.", + "reconfigure_two_factor_hint": "Atnaujinkite autentifikatoriaus įrenginį", + "update_two_factor": "Atnaujinti dvigubą tapatybės nustatymą", + "update_two_factor_message": "Tęsiant toliau, visi anksčiau sukonfigūruoti autentifikatoriai bus anuliuoti", + "update": "Atnaujinti", + "disable_two_factor": "Išjungti dvigubą tapatybės nustatymą", + "disable_two_factor_message": "Ar tikrai norite išjungti dvigubo tapatybės nustatymą?", "EXPORT_DATA": "Eksportuoti duomenis", "select_folder": "Pasirinkti aplanką", "select_zips": "Pasirinkti ZIP failus", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "Negalite ištrinti failų bendrinamame albume.", "CONFIRM_SELF_REMOVE_MESSAGE": "Pasirinkti elementai bus pašalinti iš šio albumo. Elementai, kurie yra tik šiame albume, bus perkelti į Nekategorizuoti.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Kai kuriuos elementus, kuriuos šalinate, pridėjo kiti asmenys, todėl prarasite prieigą prie jų.", - "sort_by_creation_time_ascending": "Seniausią", - "sort_by_updation_time_descending": "Paskutinį kartą atnaujintą", - "sort_by_name": "Pavadinimą", + "oldest": "Seniausią", + "last_updated": "Paskutinį kartą atnaujintą", + "name": "Pavadinimą", "FIX_CREATION_TIME": "Taisyti laiką", "FIX_CREATION_TIME_IN_PROGRESS": "Pataisomas laikas", "CREATION_TIME_UPDATED": "Atnaujintas failo laikas", @@ -594,8 +609,8 @@ "ROTATION": "Sukimas", "reset": "Atkurti", "PHOTO_EDITOR": "Nuotraukų rengyklė", - "FASTER_UPLOAD": "Spartesni įkėlimai", - "FASTER_UPLOAD_DESCRIPTION": "Nukreipkite įkėlimus per netoliese esančius serverius", + "faster_upload": "Spartesni įkėlimai", + "faster_upload_description": "Nukreipkite įkėlimus per netoliese esančius serverius", "cast_album_to_tv": "Paleisti albumą televizoriuje", "enter_cast_pin_code": "Įveskite žemiau esančiame televizoriuje matomą kodą, kad susietumėte šį įrenginį.", "pair_device_to_tv": "Susieti įrenginius", diff --git a/web/packages/base/locales/nl-NL/translation.json b/web/packages/base/locales/nl-NL/translation.json index bd45264436..79463cfdb8 100644 --- a/web/packages/base/locales/nl-NL/translation.json +++ b/web/packages/base/locales/nl-NL/translation.json @@ -47,6 +47,7 @@ "close_key": "Sluiten (Esc)", "enter_file_name": "Bestandsnaam", "close": "Sluiten", + "yes": "", "no": "Nee", "nothing_here": "Hier is nog niets te zien", "upload": "Uploaden", @@ -228,9 +229,26 @@ "indexing_fetching": "Indexen ophalen ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "Mensen analyseren in {{nSyncedFiles, number}} photos...", "indexing_done": "{{nSyncedFiles, number}} foto's geanalyseerd", - "UNIDENTIFIED_FACES": "Ongeïdentificeerde gezichten", - "OBJECTS": "objecten", - "TEXT": "tekst", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Info ", "INFO_OPTION": "Info (I)", "file_name": "Bestandsnaam", @@ -238,7 +256,6 @@ "location": "Locatie", "view_on_map": "Bekijk op OpenStreetMap", "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.

", @@ -250,28 +267,26 @@ "no_exif": "Geen Exif gegevens", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Tweestaps", - "TWO_FACTOR_AUTHENTICATION": "Tweestapsverificatie", + "two_factor": "Tweestaps", + "two_factor_authentication": "Tweestapsverificatie", "TWO_FACTOR_QR_INSTRUCTION": "Scan de onderstaande QR-code met uw favoriete verificatie app", "ENTER_CODE_MANUALLY": "Voer de code handmatig in", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Voer deze code in in uw favoriete verificatie app", "SCAN_QR_CODE": "Scan QR-code in plaats daarvan", - "ENABLE_TWO_FACTOR": "Tweestapsverificatie inschakelen", + "enable_two_factor": "Tweestapsverificatie inschakelen", "enable": "Inschakelen", "enabled": "Ingeschakeld", "LOST_DEVICE": "Tweestapsverificatie apparaat verloren", "INCORRECT_CODE": "Onjuiste code", - "TWO_FACTOR_INFO": "Voeg een extra beveiligingslaag toe door meer dan uw e-mailadres en wachtwoord te vereisen om in te loggen op uw account", - "DISABLE_TWO_FACTOR_LABEL": "Schakel tweestapsverificatie uit", - "UPDATE_TWO_FACTOR_LABEL": "Update uw verificatie apparaat", + "two_factor_info": "Voeg een extra beveiligingslaag toe door meer dan uw e-mailadres en wachtwoord te vereisen om in te loggen op uw account", "disable": "Uitschakelen", "reconfigure": "Herconfigureren", - "UPDATE_TWO_FACTOR": "Tweestapsverificatie bijwerken", - "UPDATE_TWO_FACTOR_MESSAGE": "Verder gaan zal elk eerder geconfigureerde verificatie apparaat ontzeggen", - "UPDATE": "Bijwerken", - "DISABLE_TWO_FACTOR": "Tweestapsverificatie uitschakelen", - "DISABLE_TWO_FACTOR_MESSAGE": "Weet u zeker dat u tweestapsverificatie wilt uitschakelen", - "TWO_FACTOR_DISABLE_FAILED": "Uitschakelen van tweestapsverificatie is mislukt, probeer het opnieuw", + "reconfigure_two_factor_hint": "Update uw verificatie apparaat", + "update_two_factor": "Tweestapsverificatie bijwerken", + "update_two_factor_message": "Verder gaan zal elk eerder geconfigureerde verificatie apparaat ontzeggen", + "update": "Bijwerken", + "disable_two_factor": "Tweestapsverificatie uitschakelen", + "disable_two_factor_message": "Weet u zeker dat u tweestapsverificatie wilt uitschakelen", "EXPORT_DATA": "Gegevens exporteren", "select_folder": "Map selecteren", "select_zips": "Selecteer zip", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "U kunt bestanden niet verwijderen in een gedeeld album", "CONFIRM_SELF_REMOVE_MESSAGE": "De geselecteerde items worden verwijderd uit dit album. De items die alleen in dit album staan, worden verplaatst naar 'Niet gecategoriseerd'.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Sommige van de items die u verwijdert zijn door andere mensen toegevoegd, en u verliest de toegang daartoe.", - "sort_by_creation_time_ascending": "Oudste", - "sort_by_updation_time_descending": "Laatst gewijzigd op", - "sort_by_name": "Naam", + "oldest": "Oudste", + "last_updated": "Laatst gewijzigd op", + "name": "Naam", "FIX_CREATION_TIME": "Herstel tijd", "FIX_CREATION_TIME_IN_PROGRESS": "Tijd aan het herstellen", "CREATION_TIME_UPDATED": "Bestandstijd bijgewerkt", @@ -594,8 +609,8 @@ "ROTATION": "Draaiing", "reset": "Herstellen", "PHOTO_EDITOR": "Fotobewerker", - "FASTER_UPLOAD": "Snellere uploads", - "FASTER_UPLOAD_DESCRIPTION": "Uploaden door nabije servers", + "faster_upload": "Snellere uploads", + "faster_upload_description": "Uploaden door nabije servers", "cast_album_to_tv": "Album afspelen op TV", "enter_cast_pin_code": "Voer de code in die u op de TV ziet om dit apparaat te koppelen.", "pair_device_to_tv": "Koppel apparaten", diff --git a/web/packages/base/locales/pl-PL/translation.json b/web/packages/base/locales/pl-PL/translation.json index 948215e362..bac2263328 100644 --- a/web/packages/base/locales/pl-PL/translation.json +++ b/web/packages/base/locales/pl-PL/translation.json @@ -47,6 +47,7 @@ "close_key": "Zamknij (Esc)", "enter_file_name": "Nazwa pliku", "close": "Zamknij", + "yes": "", "no": "Nie", "nothing_here": "Nic tu jeszcze nie ma", "upload": "Prześlij", @@ -228,9 +229,26 @@ "indexing_fetching": "Pobieranie indeksów ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "Indeksowanie ludzi w {{nSyncedFiles, number}} zdjęć...", "indexing_done": "Zindeksowano {{nSyncedFiles, number}} zdjęć", - "UNIDENTIFIED_FACES": "Niezidentyfikowane twarze", - "OBJECTS": "obiekty", - "TEXT": "tekst", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Informacje ", "INFO_OPTION": "Informacje (I)", "file_name": "Nazwa pliku", @@ -238,40 +256,37 @@ "location": "Lokalizacja", "view_on_map": "Pokaż na OpenStreetMap", "map": "Mapa", - "map_settings": "Ustawienia Mapy", "enable_map": "Włącz mapę", - "enable_maps_confirm": "Włą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_map": "Wyłącz mapę", - "disable_maps_confirm": "Wyłączyć Mapy?", + "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", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Uwierzytelnianie dwustopniowe", - "TWO_FACTOR_AUTHENTICATION": "Uwierzytelnianie dwustopniowe", + "two_factor": "Uwierzytelnianie dwustopniowe", + "two_factor_authentication": "Uwierzytelnianie dwustopniowe", "TWO_FACTOR_QR_INSTRUCTION": "Zeskanuj poniższy kod QR za pomocą swojej ulubionej aplikacji uwierzytelniającej", "ENTER_CODE_MANUALLY": "Wprowadź kod ręcznie", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Wprowadź ten kod w swojej ulubionej aplikacji uwierzytelniającej", "SCAN_QR_CODE": "Zamiast tego zeskanuj kod QR", - "ENABLE_TWO_FACTOR": "Włącz uwierzytelnianie dwustopniowe", + "enable_two_factor": "Włącz uwierzytelnianie dwustopniowe", "enable": "Włącz", "enabled": "Włączone", "LOST_DEVICE": "Utracono urządzenie dwustopniowe", "INCORRECT_CODE": "Nieprawidłowy kod", - "TWO_FACTOR_INFO": "Dodaj dodatkową warstwę bezpieczeństwa, wymagając więcej niż Twojego adresu e-mail i hasła, aby zalogować się na swoje konto", - "DISABLE_TWO_FACTOR_LABEL": "Wyłącz uwierzytelnianie dwustopniowe", - "UPDATE_TWO_FACTOR_LABEL": "Zaktualizuj swoje urządzenie uwierzytelniające", + "two_factor_info": "Dodaj dodatkową warstwę bezpieczeństwa, wymagając więcej niż Twojego adresu e-mail i hasła, aby zalogować się na swoje konto", "disable": "Wyłącz", "reconfigure": "Konfiguruj ponownie", - "UPDATE_TWO_FACTOR": "Aktualizuj uwierzytelnianie dwustopniowe", - "UPDATE_TWO_FACTOR_MESSAGE": "Kontynuowanie spowoduje unieważnienie wszystkich poprzednio skonfigurowanych uwierzytelniaczy", - "UPDATE": "Aktualizuj", - "DISABLE_TWO_FACTOR": "Wyłącz uwierzytelnianie dwustopniowe", - "DISABLE_TWO_FACTOR_MESSAGE": "Czy na pewno chcesz wyłączyć uwierzytelnianie dwustopniowe", - "TWO_FACTOR_DISABLE_FAILED": "Nie udało się wyłączyć uwierzytelniania dwustopniowego, spróbuj ponownie", + "reconfigure_two_factor_hint": "Zaktualizuj swoje urządzenie uwierzytelniające", + "update_two_factor": "Aktualizuj uwierzytelnianie dwustopniowe", + "update_two_factor_message": "Kontynuowanie spowoduje unieważnienie wszystkich poprzednio skonfigurowanych uwierzytelniaczy", + "update": "Aktualizuj", + "disable_two_factor": "Wyłącz uwierzytelnianie dwustopniowe", + "disable_two_factor_message": "Czy na pewno chcesz wyłączyć uwierzytelnianie dwustopniowe", "EXPORT_DATA": "Eksportuj dane", "select_folder": "Wybierz folder", "select_zips": "Wybierz zipy", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "Nie można usunąć plików w udostępnionym albumie", "CONFIRM_SELF_REMOVE_MESSAGE": "Wybrane elementy zostaną usunięte z tego albumu. Elementy, które są tylko w tym albumie, zostaną przeniesione do Nieskategoryzowanych.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Niektóre z usuwanych elementów zostały dodane przez inne osoby i utracisz do nich dostęp.", - "sort_by_creation_time_ascending": "Najstarsze", - "sort_by_updation_time_descending": "Ostatnia aktualizacja", - "sort_by_name": "Nazwa", + "oldest": "Najstarsze", + "last_updated": "Ostatnia aktualizacja", + "name": "Nazwa", "FIX_CREATION_TIME": "Napraw czas", "FIX_CREATION_TIME_IN_PROGRESS": "Naprawianie czasu", "CREATION_TIME_UPDATED": "Czas pliku zaktualizowany", @@ -594,8 +609,8 @@ "ROTATION": "Rotacja", "reset": "Zresetuj", "PHOTO_EDITOR": "Edytor Zdjęć", - "FASTER_UPLOAD": "Szybsze przesłania", - "FASTER_UPLOAD_DESCRIPTION": "Kieruj przesłania przez pobliskie serwery", + "faster_upload": "Szybsze przesłania", + "faster_upload_description": "Kieruj przesłania przez pobliskie serwery", "cast_album_to_tv": "Odtwórz album na telewizorze", "enter_cast_pin_code": "Wprowadź kod, który widzisz na telewizorze poniżej, aby sparować to urządzenie.", "pair_device_to_tv": "Sparuj urządzenia", diff --git a/web/packages/base/locales/pt-BR/translation.json b/web/packages/base/locales/pt-BR/translation.json index 6de35201f4..3d6176283c 100644 --- a/web/packages/base/locales/pt-BR/translation.json +++ b/web/packages/base/locales/pt-BR/translation.json @@ -47,6 +47,7 @@ "close_key": "Fechar (Esc)", "enter_file_name": "Nome do arquivo", "close": "Fechar", + "yes": "", "no": "Não", "nothing_here": "Nada aqui ainda", "upload": "Enviar", @@ -228,9 +229,26 @@ "indexing_fetching": "Obtendo índices ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "Indexando pessoas em {{nSyncedFiles, number}} fotos...", "indexing_done": "Foram indexadas {{nSyncedFiles, number}} fotos", - "UNIDENTIFIED_FACES": "Rostos não identificados", - "OBJECTS": "objetos", - "TEXT": "texto", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Informações ", "INFO_OPTION": "Informações (I)", "file_name": "Nome do arquivo", @@ -238,40 +256,37 @@ "location": "Local", "view_on_map": "Ver no OpenStreetMap", "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.

", "disable_map": "Desabilitar mapa", - "disable_maps_confirm": "Desativar Mapas?", + "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", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Dois fatores", - "TWO_FACTOR_AUTHENTICATION": "Autenticação de dois fatores", + "two_factor": "Dois fatores", + "two_factor_authentication": "Autenticação de dois fatores", "TWO_FACTOR_QR_INSTRUCTION": "Digitalize o código QR abaixo com o seu aplicativo de autenticador favorito", "ENTER_CODE_MANUALLY": "Inserir código manualmente", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Por favor, insira este código no seu aplicativo autenticador favorito", "SCAN_QR_CODE": "Em vez disso, escaneie um Código QR", - "ENABLE_TWO_FACTOR": "Ativar autenticação de dois fatores", + "enable_two_factor": "Ativar autenticação de dois fatores", "enable": "Habilitar", "enabled": "Ativado", "LOST_DEVICE": "Dispositivo de dois fatores perdido", "INCORRECT_CODE": "Código incorreto", - "TWO_FACTOR_INFO": "Adicione uma camada adicional de segurança, exigindo mais do que seu e-mail e senha para entrar na sua conta", - "DISABLE_TWO_FACTOR_LABEL": "Desativar autenticação de dois fatores", - "UPDATE_TWO_FACTOR_LABEL": "Atualize seu dispositivo autenticador", + "two_factor_info": "Adicione uma camada adicional de segurança, exigindo mais do que seu e-mail e senha para entrar na sua conta", "disable": "Desativar", "reconfigure": "Reconfigurar", - "UPDATE_TWO_FACTOR": "Atualizar dois fatores", - "UPDATE_TWO_FACTOR_MESSAGE": "Continuar adiante anulará qualquer autenticador configurado anteriormente", - "UPDATE": "Atualização", - "DISABLE_TWO_FACTOR": "Desativar autenticação de dois fatores", - "DISABLE_TWO_FACTOR_MESSAGE": "Você tem certeza de que deseja desativar a autenticação de dois fatores", - "TWO_FACTOR_DISABLE_FAILED": "Não foi possível desativar dois fatores, por favor tente novamente", + "reconfigure_two_factor_hint": "Atualize seu dispositivo autenticador", + "update_two_factor": "Atualizar dois fatores", + "update_two_factor_message": "Continuar adiante anulará qualquer autenticador configurado anteriormente", + "update": "Atualização", + "disable_two_factor": "Desativar autenticação de dois fatores", + "disable_two_factor_message": "Você tem certeza de que deseja desativar a autenticação de dois fatores", "EXPORT_DATA": "Exportar dados", "select_folder": "Selecione a pasta", "select_zips": "Selecionar zips", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "Você não pode excluir arquivos em um álbum compartilhado", "CONFIRM_SELF_REMOVE_MESSAGE": "Os itens selecionados serão removidos deste álbum. Itens que estão somente neste álbum serão movidos a aba Sem Categoria.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Alguns dos itens que você está removendo foram adicionados por outras pessoas, e você perderá o acesso a eles.", - "sort_by_creation_time_ascending": "Mais antigo", - "sort_by_updation_time_descending": "Última atualização", - "sort_by_name": "Nome", + "oldest": "Mais antigo", + "last_updated": "Última atualização", + "name": "Nome", "FIX_CREATION_TIME": "Corrigir hora", "FIX_CREATION_TIME_IN_PROGRESS": "Corrigindo horário", "CREATION_TIME_UPDATED": "Hora do arquivo atualizado", @@ -594,8 +609,8 @@ "ROTATION": "Rotação", "reset": "Redefinir", "PHOTO_EDITOR": "Editor de Fotos", - "FASTER_UPLOAD": "Envios mais rápidos", - "FASTER_UPLOAD_DESCRIPTION": "Rotas enviam em servidores próximos", + "faster_upload": "Envios mais rápidos", + "faster_upload_description": "Rotas enviam em servidores próximos", "cast_album_to_tv": "Reproduzir álbum na TV", "enter_cast_pin_code": "Digite o código que você vê na TV abaixo para parear este dispositivo.", "pair_device_to_tv": "Parear dispositivos", diff --git a/web/packages/base/locales/pt-PT/translation.json b/web/packages/base/locales/pt-PT/translation.json index 50be8bfb86..26265a8c6b 100644 --- a/web/packages/base/locales/pt-PT/translation.json +++ b/web/packages/base/locales/pt-PT/translation.json @@ -1,8 +1,8 @@ { "intro_slide_1_title": "
Backups privados
para as suas memórias
", - "intro_slide_1": "", - "intro_slide_2_title": "", - "intro_slide_2": "", + "intro_slide_1": "Criptografia de ponta a ponta por padrão", + "intro_slide_2_title": "
Armazenado seguramente
em um local avançado
", + "intro_slide_2": "Feito para ter longevidade", "intro_slide_3_title": "
Disponível
em qualquer lugar
", "intro_slide_3": "Android, iOS, Web, Desktop", "login": "Entrar", @@ -19,7 +19,7 @@ "ENTER_OTT": "Código de verificação", "RESEND_MAIL": "Reenviar código", "VERIFY": "Verificar", - "generic_error": "", + "generic_error": "Ocorreu um erro", "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", @@ -27,29 +27,30 @@ "SENT": "Enviado!", "password": "Palavra-passe", "link_password_description": "Introduza a palavra-passe para desbloquear o álbum", - "unlock": "", + "unlock": "Desbloquear", "SET_PASSPHRASE": "Definir palavra-passe", "VERIFY_PASSPHRASE": "Entrar", "INCORRECT_PASSPHRASE": "Palavra-passe incorreta", - "ENTER_ENC_PASSPHRASE": "", - "PASSPHRASE_DISCLAIMER": "", - "key_generation_in_progress": "", - "PASSPHRASE_HINT": "", - "CONFIRM_PASSPHRASE": "", - "REFERRAL_CODE_HINT": "", - "REFERRAL_INFO": "", - "PASSPHRASE_MATCH_ERROR": "", + "ENTER_ENC_PASSPHRASE": "Inserir uma palavra-passe para encriptar os seus dados", + "PASSPHRASE_DISCLAIMER": "Não guardamos a sua palavra-passe, por isso, se se esquecer dela, não poderemos ajudá-lo a recuperar os seus dados sem uma chave de recuperação.", + "key_generation_in_progress": "Gerar chaves de criptografia...", + "PASSPHRASE_HINT": "Palavra-passe", + "CONFIRM_PASSPHRASE": "Confirmar palavra-passe", + "REFERRAL_CODE_HINT": "Como é que soube do Ente? (opcional)", + "REFERRAL_INFO": "Não monitorizamos as instalações de aplicações. Seria útil se nos dissesse onde nos encontrou!", + "PASSPHRASE_MATCH_ERROR": "As palavras-passe não correspondem", "welcome_to_ente_title": "Bem-vindo ao ", - "welcome_to_ente_subtitle": "", + "welcome_to_ente_subtitle": "Armazenamento criptografado de ponta a ponta de fotos e compartilhamento", "new_album": "Novo álbum", - "create_albums": "", + "create_albums": "Criar álbuns", "enter_album_name": "Nome do álbum", "close_key": "Fechar (Esc)", "enter_file_name": "Nome do ficheiro", "close": "Fechar", + "yes": "", "no": "Não", - "nothing_here": "", - "upload": "", + "nothing_here": "Nada aqui ainda", + "upload": "Carregar", "import": "Importar", "add_photos": "Adicionar fotos", "add_more_photos": "Adicionar mais fotos", @@ -58,544 +59,558 @@ "select_photos": "Selecionar fotos", "FILE_UPLOAD": "Enviar Ficheiro", "UPLOAD_STAGE_MESSAGE": { - "0": "", - "1": "", - "2": "", - "3": "", - "4": "", - "5": "" + "0": "Preparar para carregar", + "1": "Lendo arquivos de metadados do google", + "2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} metadados dos arquivos extraídos", + "3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} arquivos processados", + "4": "Cancelar envio restante", + "5": "Backup concluído" }, - "FILE_NOT_UPLOADED_LIST": "", - "INITIAL_LOAD_DELAY_WARNING": "", - "USER_DOES_NOT_EXIST": "", + "FILE_NOT_UPLOADED_LIST": "Os seguintes arquivos não foram enviados", + "INITIAL_LOAD_DELAY_WARNING": "O primeiro carregamento pode demorar algum tempo", + "USER_DOES_NOT_EXIST": "Desculpe, não foi possível encontrar um utilizador com esse e-mail", "NO_ACCOUNT": "Não possui uma conta", "ACCOUNT_EXISTS": "Já possui uma conta", "CREATE": "Criar", - "download": "", - "download_album": "", - "download_favorites": "", - "download_uncategorized": "", - "download_hidden_items": "", - "download_key": "", - "copy_key": "", - "toggle_fullscreen_key": "", - "zoom_in_out_key": "", - "previous_key": "", - "next_key": "", - "title_photos": "", - "title_auth": "", - "title_accounts": "", - "UPLOAD_FIRST_PHOTO": "", - "IMPORT_YOUR_FOLDERS": "", - "UPLOAD_DROPZONE_MESSAGE": "", - "WATCH_FOLDER_DROPZONE_MESSAGE": "", - "TRASH_FILES_TITLE": "", - "TRASH_FILE_TITLE": "", - "DELETE_FILES_TITLE": "", - "DELETE_FILES_MESSAGE": "", - "delete": "", - "delete_key": "", - "favorite": "", - "favorite_key": "", - "unfavorite_key": "", - "multi_folder_upload": "", - "upload_to_choice": "", - "upload_to_single_album": "", - "upload_to_album_per_folder": "", - "session_expired": "", - "session_expired_message": "", - "PASSWORD_GENERATION_FAILED": "", - "CHANGE_PASSWORD": "", - "password_changed_elsewhere": "", - "password_changed_elsewhere_message": "", - "GO_BACK": "", - "recovery_key": "", - "do_this_later": "", - "save_key": "", - "recovery_key_description": "", - "key_not_stored_note": "", - "recovery_key_generation_failed": "", - "FORGOT_PASSWORD": "", - "RECOVER_ACCOUNT": "", - "RECOVERY_KEY_HINT": "", - "RECOVER": "", - "NO_RECOVERY_KEY": "", - "INCORRECT_RECOVERY_KEY": "", - "sorry": "", - "no_recovery_key_message": "", - "no_two_factor_recovery_key_message": "", - "contact_support": "", - "request_feature": "", - "support": "", - "cancel": "", - "logout": "", - "logout_message": "", - "delete_account": "", - "delete_account_manually_message": "", - "CHANGE_EMAIL": "", - "ok": "", - "success": "", - "error": "", - "OFFLINE_MSG": "", - "install": "", - "install_mobile_app": "", - "download_app": "", - "download_app_message": "", - "EXPORT": "", - "SUBSCRIPTION": "", - "SUBSCRIBE": "", - "MANAGEMENT_PORTAL": "", - "MANAGE_FAMILY_PORTAL": "", - "LEAVE_FAMILY_PLAN": "", - "LEAVE": "", - "LEAVE_FAMILY_CONFIRM": "", - "CHOOSE_PLAN": "", - "MANAGE_PLAN": "", - "CURRENT_USAGE": "", - "TWO_MONTHS_FREE": "", - "POPULAR": "", - "free_plan_option": "", - "free_plan_description": "", - "active": "", - "subscription_info_free": "", - "subscription_info_family": "", - "subscription_info_expired": "", - "subscription_info_renewal_cancelled": "", - "subscription_info_storage_quota_exceeded": "", - "subscription_status_renewal_active": "", - "subscription_status_renewal_cancelled": "", - "add_on_valid_till": "", - "subscription_expired": "", - "storage_quota_exceeded": "", - "SUBSCRIPTION_PURCHASE_SUCCESS": "", - "SUBSCRIPTION_PURCHASE_CANCELLED": "", - "SUBSCRIPTION_PURCHASE_FAILED": "", - "SUBSCRIPTION_UPDATE_FAILED": "", - "UPDATE_PAYMENT_METHOD_MESSAGE": "", - "STRIPE_AUTHENTICATION_FAILED": "", - "UPDATE_PAYMENT_METHOD": "", - "MONTHLY": "", - "YEARLY": "", - "MONTH_SHORT": "", - "YEAR": "", - "update_subscription_title": "", - "UPDATE_SUBSCRIPTION_MESSAGE": "", - "UPDATE_SUBSCRIPTION": "", - "CANCEL_SUBSCRIPTION": "", - "CANCEL_SUBSCRIPTION_MESSAGE": "", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", - "SUBSCRIPTION_CANCEL_FAILED": "", - "SUBSCRIPTION_CANCEL_SUCCESS": "", - "REACTIVATE_SUBSCRIPTION": "", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "", - "SUBSCRIPTION_ACTIVATE_SUCCESS": "", - "SUBSCRIPTION_ACTIVATE_FAILED": "", - "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", - "CANCEL_SUBSCRIPTION_ON_MOBILE": "", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", - "MAIL_TO_MANAGE_SUBSCRIPTION": "", - "rename": "", - "rename_file": "", - "rename_album": "", - "delete_album": "", - "delete_album_title": "", - "delete_album_message": "", - "delete_photos": "", - "keep_photos": "", - "share_album": "", - "SHARE_WITH_SELF": "", - "ALREADY_SHARED": "", - "SHARING_BAD_REQUEST_ERROR": "", - "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", - "CREATE_ALBUM_FAILED": "", - "search": "", - "search_results": "", - "no_results": "", - "search_hint": "", - "album": "", - "date": "", - "description": "", - "file_type": "", - "magic": "", - "photos_count_zero": "", - "photos_count_one": "", - "photos_count": "", - "terms_and_conditions": "", - "SELECTED": "", - "people": "", - "indexing_scheduled": "", - "indexing_photos": "", - "indexing_fetching": "", - "indexing_people": "", - "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", - "INFO": "", - "INFO_OPTION": "", - "file_name": "", - "CAPTION_PLACEHOLDER": "", - "location": "", - "view_on_map": "", - "map": "", - "map_settings": "", - "enable_map": "", - "enable_maps_confirm": "", - "enable_maps_confirm_message": "", - "disable_map": "", - "disable_maps_confirm": "", - "disable_maps_confirm_message": "", - "DETAILS": "", - "view_exif": "", - "no_exif": "", - "exif": "", - "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", - "TWO_FACTOR_QR_INSTRUCTION": "", - "ENTER_CODE_MANUALLY": "", - "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", - "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", - "enable": "", - "enabled": "", - "LOST_DEVICE": "", - "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", - "disable": "", - "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", - "EXPORT_DATA": "", - "select_folder": "", - "select_zips": "", - "faq": "", - "takeout_hint": "", - "DESTINATION": "", - "START": "", - "LAST_EXPORT_TIME": "", - "EXPORT_AGAIN": "", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", - "SEND_OTT": "", - "EMAIl_ALREADY_OWNED": "", - "ETAGS_BLOCKED": "", - "LIVE_PHOTOS_DETECTED": "", - "RETRY_FAILED": "", - "FAILED_UPLOADS": "", - "failed_uploads_hint": "", - "SKIPPED_FILES": "", - "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", - "UNSUPPORTED_FILES": "", - "SUCCESSFUL_UPLOADS": "", - "SKIPPED_INFO": "", - "UNSUPPORTED_INFO": "", - "BLOCKED_UPLOADS": "", - "INPROGRESS_METADATA_EXTRACTION": "", - "INPROGRESS_UPLOADS": "", - "TOO_LARGE_UPLOADS": "", - "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", - "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", - "TOO_LARGE_INFO": "", - "THUMBNAIL_GENERATION_FAILED_INFO": "", - "upload_to_album": "", - "add_to_album": "", - "move_to_album": "", - "unhide_to_album": "", - "restore_to_album": "", - "section_all": "", - "section_uncategorized": "", - "section_archive": "", - "section_hidden": "", - "section_trash": "", - "favorites": "", - "archive": "", - "archive_album": "", - "unarchive": "", - "unarchive_album": "", - "hide_collection": "", - "unhide_collection": "", - "MOVE": "", - "add": "", - "REMOVE": "", - "YES_REMOVE": "", - "REMOVE_FROM_COLLECTION": "", - "MOVE_TO_TRASH": "", - "TRASH_FILES_MESSAGE": "", - "TRASH_FILE_MESSAGE": "", - "DELETE_PERMANENTLY": "", - "RESTORE": "", - "empty_trash": "", - "empty_trash_title": "", - "empty_trash_message": "", - "leave_album": "", - "leave_shared_album_title": "", - "leave_shared_album_message": "", - "leave_shared_album": "", - "NOT_FILE_OWNER": "", - "CONFIRM_SELF_REMOVE_MESSAGE": "", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", - "FIX_CREATION_TIME": "", - "FIX_CREATION_TIME_IN_PROGRESS": "", - "CREATION_TIME_UPDATED": "", - "UPDATE_CREATION_TIME_NOT_STARTED": "", - "UPDATE_CREATION_TIME_COMPLETED": "", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", - "CAPTION_CHARACTER_LIMIT": "", - "DATE_TIME_ORIGINAL": "", - "DATE_TIME_DIGITIZED": "", - "METADATA_DATE": "", - "CUSTOM_TIME": "", - "sharing_details": "", - "modify_sharing": "", - "ADD_COLLABORATORS": "", - "ADD_NEW_EMAIL": "", - "shared_with_people_count_zero": "", - "shared_with_people_count_one": "", - "shared_with_people_count": "", - "participants_count_zero": "", - "participants_count_one": "", - "participants_count": "", - "ADD_VIEWERS": "", - "CHANGE_PERMISSIONS_TO_VIEWER": "", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", - "CONVERT_TO_VIEWER": "", - "CONVERT_TO_COLLABORATOR": "", - "CHANGE_PERMISSION": "", - "REMOVE_PARTICIPANT": "", - "CONFIRM_REMOVE": "", - "MANAGE": "", - "ADDED_AS": "", - "COLLABORATOR_RIGHTS": "", - "REMOVE_PARTICIPANT_HEAD": "", - "OWNER": "", - "COLLABORATORS": "", - "ADD_MORE": "", - "VIEWERS": "", - "OR_ADD_EXISTING": "", - "REMOVE_PARTICIPANT_MESSAGE": "", - "NOT_FOUND": "", - "LINK_EXPIRED": "", - "LINK_EXPIRED_MESSAGE": "", - "MANAGE_LINK": "", - "LINK_TOO_MANY_REQUESTS": "", - "FILE_DOWNLOAD": "", - "link_password_lock": "", - "PUBLIC_COLLECT": "", - "LINK_DEVICE_LIMIT": "", - "NO_DEVICE_LIMIT": "", - "LINK_EXPIRY": "", - "NEVER": "", - "DISABLE_FILE_DOWNLOAD": "", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "", - "SHARED_USING": "", - "SHARING_REFERRAL_CODE": "", - "LIVE": "", - "DISABLE_PASSWORD": "", - "DISABLE_PASSWORD_MESSAGE": "", - "PASSWORD_LOCK": "", - "LOCK": "", - "file": "", - "folder": "", - "google_takeout": "", - "DEDUPLICATE_FILES": "", - "NO_DUPLICATES_FOUND": "", - "FILES": "", - "EACH": "", - "DEDUPLICATE_BASED_ON_SIZE": "", - "STOP_ALL_UPLOADS_MESSAGE": "", - "STOP_UPLOADS_HEADER": "", - "YES_STOP_UPLOADS": "", - "STOP_DOWNLOADS_HEADER": "", - "YES_STOP_DOWNLOADS": "", - "STOP_ALL_DOWNLOADS_MESSAGE": "", - "albums": "", - "albums_count_one": "", - "albums_count": "", - "all_albums": "", - "all_hidden_albums": "", - "hidden_albums": "", - "hidden_items": "", - "ENTER_TWO_FACTOR_OTP": "", - "create_account": "", - "COPIED": "", - "WATCH_FOLDERS": "", - "upgrade_now": "", - "renew_now": "", - "STORAGE": "", - "USED": "", - "YOU": "", - "FAMILY": "", - "FREE": "", - "OF": "", - "WATCHED_FOLDERS": "", - "NO_FOLDERS_ADDED": "", - "FOLDERS_AUTOMATICALLY_MONITORED": "", - "UPLOAD_NEW_FILES_TO_ENTE": "", - "REMOVE_DELETED_FILES_FROM_ENTE": "", - "ADD_FOLDER": "", - "STOP_WATCHING": "", - "STOP_WATCHING_FOLDER": "", - "STOP_WATCHING_DIALOG_MESSAGE": "", - "YES_STOP": "", - "CHANGE_FOLDER": "", - "FAMILY_PLAN": "", - "debug_logs": "", - "download_logs": "", - "download_logs_message": "", - "WEAK_DEVICE": "", - "drag_and_drop_hint": "", - "AUTHENTICATE": "", - "UPLOADED_TO_SINGLE_COLLECTION": "", - "UPLOADED_TO_SEPARATE_COLLECTIONS": "", - "NEVERMIND": "", - "update_available": "", - "update_installable_message": "", - "install_now": "", - "install_on_next_launch": "", - "update_available_message": "", - "download_and_install": "", - "ignore_this_version": "", - "TODAY": "", - "YESTERDAY": "", - "NAME_PLACEHOLDER": "", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", - "CHOSE_THEME": "", - "more_details": "", - "ml_search": "", - "ml_search_description": "", - "ml_search_footnote": "", - "indexing": "", - "processed": "", - "indexing_status_running": "", - "indexing_status_fetching": "", - "indexing_status_scheduled": "", - "indexing_status_done": "", - "ml_search_disable": "", - "ml_search_disable_confirm": "", - "ml_consent": "", - "ml_consent_title": "", - "ml_consent_description": "", - "ml_consent_confirmation": "", - "labs": "", - "YOURS": "", - "passphrase_strength_weak": "", - "passphrase_strength_moderate": "", - "passphrase_strength_strong": "", - "preferences": "", - "language": "", - "advanced": "", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", - "SUBSCRIPTION_VERIFICATION_ERROR": "", + "download": "Download", + "download_album": "Download album", + "download_favorites": "Download favoritos", + "download_uncategorized": "Download não categorizado", + "download_hidden_items": "Download de itens ocultos", + "download_key": "Download (D)", + "copy_key": "Copiar como PNG (Ctrl/Cmd - C)", + "toggle_fullscreen_key": "Mudar para tela cheia (F)", + "zoom_in_out_key": "Ampliar/Reduzir", + "previous_key": "Anterior (←)", + "next_key": "Seguinte (→)", + "title_photos": "Ente Fotos", + "title_auth": "Ente Auth", + "title_accounts": "Contas Ente", + "UPLOAD_FIRST_PHOTO": "Envie sua primeira foto", + "IMPORT_YOUR_FOLDERS": "Importar suas pastas", + "UPLOAD_DROPZONE_MESSAGE": "Arraste para salvar seus arquivos", + "WATCH_FOLDER_DROPZONE_MESSAGE": "Arraste para adicionar pasta monitorada", + "TRASH_FILES_TITLE": "Apagar arquivos?", + "TRASH_FILE_TITLE": "Apagar arquivo?", + "DELETE_FILES_TITLE": "Apagar imediatamente?", + "DELETE_FILES_MESSAGE": "Os ficheiros selecionados serão permanentemente eliminados da sua conta Ente.", + "delete": "Apagar", + "delete_key": "Apagar (DEL)", + "favorite": "Favorito", + "favorite_key": "Favorito (L)", + "unfavorite_key": "Remover Favorito (L)", + "multi_folder_upload": "Várias pastas detectadas", + "upload_to_choice": "Gostaria de enviá-los para", + "upload_to_single_album": "Um único álbum", + "upload_to_album_per_folder": "Álbuns separados", + "session_expired": "Sessão expirada", + "session_expired_message": "A sua sessão expirou. Por favor, inicie sessão novamente.", + "PASSWORD_GENERATION_FAILED": "O seu navegador não conseguiu gerar uma chave forte que cumpra as normas de encriptação da Ente. Tente utilizar a aplicação móvel ou outro navegador", + "CHANGE_PASSWORD": "Alterar palavra-passe", + "password_changed_elsewhere": "Palavra-passe alterada noutro lugar", + "password_changed_elsewhere_message": "Inicie sessão novamente neste dispositivo para utilizar a sua nova palavra-passe para autenticação.", + "GO_BACK": "Voltar", + "recovery_key": "Chave de recuperação", + "do_this_later": "Fazer isso mais tarde", + "save_key": "Guardar chave", + "recovery_key_description": "Se esquecer sua palavra-passe, a única maneira de recuperar os seus dados é com esta chave.", + "key_not_stored_note": "Não armazenamos essa chave, por favor, guarde esta chave de palavras num lugar seguro", + "recovery_key_generation_failed": "Não foi possível gerar o código de recuperação, tente novamente", + "FORGOT_PASSWORD": "Esqueceu-se da palavra-passe", + "RECOVER_ACCOUNT": "Recuperar conta", + "RECOVERY_KEY_HINT": "Chave de recuperação", + "RECOVER": "Recuperar", + "NO_RECOVERY_KEY": "Não tem chave de recuperação?", + "INCORRECT_RECOVERY_KEY": "Chave de recuperação incorrecta", + "sorry": "Desculpe", + "no_recovery_key_message": "Devido à natureza do nosso protocolo de encriptação de ponta a ponta, os seus dados não podem ser desencriptados sem a sua palavra-passe ou chave de recuperação", + "no_two_factor_recovery_key_message": "Envie uma mensagem de correio eletrónico para {{emailID}} a partir do seu endereço de correio eletrónico registado", + "contact_support": "Contactar o suporte", + "request_feature": "Solicitar recurso", + "support": "Suporte", + "cancel": "Cancelar", + "logout": "Terminar sessão", + "logout_message": "Tem certeza que deseja terminar a sessão?", + "delete_account": "Eliminar conta", + "delete_account_manually_message": "

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

Seu pedido será processado dentro de 72 horas.

", + "CHANGE_EMAIL": "Alterar e-mail", + "ok": "OK", + "success": "Bem-sucedido", + "error": "Erro", + "OFFLINE_MSG": "Está offline, estão a ser mostradas memórias em cache", + "install": "Instalar", + "install_mobile_app": "Instale nosso aplicativo Android ou iOS para fazer backup automático de todas as suas fotos", + "download_app": "Descarregar a aplicação para computador", + "download_app_message": "Desculpe, esta operação só é suportada em nosso aplicativo para computador", + "EXPORT": "Exportar dados", + "SUBSCRIPTION": "Subscrição", + "SUBSCRIBE": "Subscrever", + "MANAGEMENT_PORTAL": "Gerir o método de pagamento", + "MANAGE_FAMILY_PORTAL": "Gerir família", + "LEAVE_FAMILY_PLAN": "Sair do plano familiar", + "LEAVE": "Sair", + "LEAVE_FAMILY_CONFIRM": "Tem certeza que deseja sair do plano familiar?", + "CHOOSE_PLAN": "Escolha seu plano", + "MANAGE_PLAN": "Gerir subscrição", + "CURRENT_USAGE": "O uso atual é {{usage}}", + "TWO_MONTHS_FREE": "Obtenha 2 meses gratuitos em planos anuais", + "POPULAR": "Popular", + "free_plan_option": "Continuar com o plano gratuito", + "free_plan_description": "{{storage}} grátis para sempre", + "active": "Ativo", + "subscription_info_free": "Está a utilizar um plano gratuito", + "subscription_info_family": "Está inscrito num plano familiar gerido por", + "subscription_info_expired": "A sua subscrição expirou, por favor renove", + "subscription_info_renewal_cancelled": "A sua subscrição será cancelada em {{date, date}}", + "subscription_info_storage_quota_exceeded": "Excedeu a sua quota de armazenamento, por favor upgrade", + "subscription_status_renewal_active": "Renovações em {{date, date}}", + "subscription_status_renewal_cancelled": "Termina em {{date, date}}", + "add_on_valid_till": "Seu addon {{storage}} é válido até o momento {{date, date}}", + "subscription_expired": "Subscrição expirou", + "storage_quota_exceeded": "Limite de armazenamento excedido", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

Recebemos o seu pagamento

A sua subscrição é válida até {{date, date}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "A sua compra foi cancelada, por favor tente novamente se quiser subscrever", + "SUBSCRIPTION_PURCHASE_FAILED": "A compra da subscrição falhou, tente novamente", + "SUBSCRIPTION_UPDATE_FAILED": "A atualização da subscrição falhou, tente novamente", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Lamentamos, mas o pagamento falhou quando tentámos cobrar o seu cartão. Actualize o seu método de pagamento e tente novamente", + "STRIPE_AUTHENTICATION_FAILED": "Não foi possível autenticar o seu método de pagamento. Escolha um método de pagamento diferente e tente novamente", + "UPDATE_PAYMENT_METHOD": "Atualizar o método de pagamento", + "MONTHLY": "Mensal", + "YEARLY": "Anual", + "MONTH_SHORT": "mês", + "YEAR": "ano", + "update_subscription_title": "Confirmar alteração de plano", + "UPDATE_SUBSCRIPTION_MESSAGE": "Tem a certeza de que pretende alterar o seu plano?", + "UPDATE_SUBSCRIPTION": "Alterar plano", + "CANCEL_SUBSCRIPTION": "Cancelar subscrição", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Todos os seus dados serão eliminados dos nossos servidores no final deste período de faturação.

Tem a certeza de que pretende cancelar a sua subscrição?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Tem certeza que deseja cancelar sua subscrição?

", + "SUBSCRIPTION_CANCEL_FAILED": "Falha ao cancelar a subscrição", + "SUBSCRIPTION_CANCEL_SUCCESS": "Subscrição cancelada com sucesso", + "REACTIVATE_SUBSCRIPTION": "Reativar subscrição", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Uma vez reativado, será cobrado em {{date, date}}", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Assinatura activada com sucesso ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Falha ao reativar as renovações de subscrição", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Obrigado", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Cancelar a subscrição móvel", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Cancele a sua subscrição a partir da aplicação móvel para ativar uma subscrição aqui", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Contacte-nos através de {{emailID}} para gerir a sua subscrição", + "rename": "Renomear", + "rename_file": "Renomear arquivo", + "rename_album": "Renomear álbum", + "delete_album": "Apagar álbum", + "delete_album_title": "Apagar álbum?", + "delete_album_message": "Eliminar também as fotos (e vídeos) presentes neste álbum de todos os outros álbuns de que fazem parte?", + "delete_photos": "Apagar fotos", + "keep_photos": "Manter fotos", + "share_album": "Partilhar Álbum", + "SHARE_WITH_SELF": "Não podes partilhar contigo mesmo", + "ALREADY_SHARED": "Já está a partilhar isto com o {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Álbum compartilhado não permitido", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "A partilha está desactivada para contas gratuitas", + "CREATE_ALBUM_FAILED": "Falha ao criar o álbum, tente novamente", + "search": "pesquisar", + "search_results": "Resultados de pesquisa", + "no_results": "Nenhum resultado encontrado", + "search_hint": "Procurar por álbuns, datas, descrições, ...", + "album": "Álbum", + "date": "Data", + "description": "Descrição", + "file_type": "Tipo de arquivo", + "magic": "Mágica", + "photos_count_zero": "Sem memórias", + "photos_count_one": "1 memória", + "photos_count": "{{count, number}} memórias", + "terms_and_conditions": "Eu concordo com os termos de serviço e política de privacidade", + "SELECTED": "selecionado", + "people": "Pessoas", + "indexing_scheduled": "Indexação está programada...", + "indexing_photos": "Indexar fotos ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", + "indexing_fetching": "Obtendo índices ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", + "indexing_people": "Indexar pessoas em {{nSyncedFiles, number}} fotos...", + "indexing_done": "Foram indexadas {{nSyncedFiles, number}} fotos", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", + "INFO": "Informações ", + "INFO_OPTION": "Informações (I)", + "file_name": "Nome do arquivo", + "CAPTION_PLACEHOLDER": "Adicionar uma descrição", + "location": "Localização", + "view_on_map": "Ver no OpenStreetMap", + "map": "Mapa", + "enable_map": "Ativar mapas", + "enable_maps_confirm": "Ativar mapas?", + "enable_maps_confirm_message": "

Isso mostrará suas fotos em um mapa do mundo.

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

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

", + "disable_map": "Desativar mapa", + "disable_maps_confirm": "Desativar mapas?", + "disable_maps_confirm_message": "

Isto irá desativar a apresentação das suas fotografias num mapa do mundo.

Pode ativar esta funcionalidade em qualquer altura a partir das Definições.

", + "DETAILS": "Detalhes", + "view_exif": "Ver todos os dados EXIF", + "no_exif": "Sem dados EXIF", + "exif": "Exif", + "ISO": "ISO", + "two_factor": "Dois fatores", + "two_factor_authentication": "Autenticação de dois fatores", + "TWO_FACTOR_QR_INSTRUCTION": "Digitalize o código QR abaixo com o seu aplicativo de autenticador favorito", + "ENTER_CODE_MANUALLY": "Introduza o código manualmente", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Por favor, insira este código no seu aplicativo de autenticação favorito", + "SCAN_QR_CODE": "Ler o código QR em vez disso", + "enable_two_factor": "Ativar dois fatores", + "enable": "Ativar", + "enabled": "Ativado", + "LOST_DEVICE": "Dispositivo de dois fatores perdido", + "INCORRECT_CODE": "Código incorrecto", + "two_factor_info": "Adicionar uma camada adicional de segurança, exigindo mais do que o seu e-mail e palavra-passe para iniciar sessão na sua conta", + "disable": "Desativar", + "reconfigure": "Reconfigurar", + "reconfigure_two_factor_hint": "Atualize seu dispositivo de autenticador", + "update_two_factor": "Atualizar dois fatores", + "update_two_factor_message": "Continuar a avançar anulará quaisquer autenticadores previamente configurados", + "update": "Atualizar", + "disable_two_factor": "Desativar dois fatores", + "disable_two_factor_message": "Tem a certeza de que pretende desativar a autenticação de dois fatores", + "EXPORT_DATA": "Exportar dados", + "select_folder": "Seleccione a pasta", + "select_zips": "Selecionar zips", + "faq": "Perguntas frequentes", + "takeout_hint": "Descompacte todos os zips para a mesma pasta e carregue-os. Ou carregue os zips diretamente. Consulte as FAQ para obter detalhes.", + "DESTINATION": "Destino", + "START": "Iniciar", + "LAST_EXPORT_TIME": "Data da última exportação", + "EXPORT_AGAIN": "Sincronizar novamente", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Armazenamento local não acessível", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "O seu browser ou um addon está a impedir o Ente de guardar dados no armazenamento local. Tente carregar esta página depois de mudar o seu modo de navegação.", + "SEND_OTT": "Enviar códigos OTP", + "EMAIl_ALREADY_OWNED": "Este email já está em uso", + "ETAGS_BLOCKED": "

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

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

", + "LIVE_PHOTOS_DETECTED": "Os ficheiros de fotografia e vídeo das suas Live Photos foram fundidos num único ficheiro", + "RETRY_FAILED": "Repetir envios com falha", + "FAILED_UPLOADS": "Upload falhou ", + "failed_uploads_hint": "Haverá uma opção para tentar novamente quando o upload terminar", + "SKIPPED_FILES": "Uploads ignorados", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Falha ao gerar miniaturas", + "UNSUPPORTED_FILES": "Arquivos não suportados", + "SUCCESSFUL_UPLOADS": "Envios bem sucedidos", + "SKIPPED_INFO": "Saltou estes ficheiros porque existem ficheiros com o mesmo nome e conteúdo no mesmo álbum", + "UNSUPPORTED_INFO": "Ente ainda não suporta estes formatos de arquivo", + "BLOCKED_UPLOADS": "Uploads bloqueados", + "INPROGRESS_METADATA_EXTRACTION": "Em andamento", + "INPROGRESS_UPLOADS": "Uploads em andamento", + "TOO_LARGE_UPLOADS": "Arquivos grandes", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Armazenamento insuficiente", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Estes ficheiros não foram carregados porque excedem o limite máximo de tamanho do seu plano de armazenamento", + "TOO_LARGE_INFO": "Estes ficheiros não foram carregados porque excedem o nosso limite máximo de tamanho de ficheiro", + "THUMBNAIL_GENERATION_FAILED_INFO": "Estes ficheiros foram carregados, mas infelizmente não foi possível gerar as respectivas miniaturas.", + "upload_to_album": "Carregar para o álbum", + "add_to_album": "Adicionar ao álbum", + "move_to_album": "Mover para álbum", + "unhide_to_album": "Mostrar para o álbum", + "restore_to_album": "Restaurar para álbum", + "section_all": "Todos", + "section_uncategorized": "Sem categoria", + "section_archive": "Arquivado", + "section_hidden": "Oculto", + "section_trash": "Lixo", + "favorites": "Favoritos", + "archive": "Arquivar", + "archive_album": "Arquivar álbum", + "unarchive": "Desarquivar", + "unarchive_album": "Desarquivar álbum", + "hide_collection": "Ocultar álbum", + "unhide_collection": "Mostrar álbum", + "MOVE": "Mover", + "add": "Adicionar", + "REMOVE": "Remover", + "YES_REMOVE": "Sim, remover", + "REMOVE_FROM_COLLECTION": "Remover do álbum", + "MOVE_TO_TRASH": "Mover para o lixo", + "TRASH_FILES_MESSAGE": "Os ficheiros selecionados serão removidos de todos os álbuns e movidos para o lixo.", + "TRASH_FILE_MESSAGE": "O ficheiro será removido de todos os álbuns e movido para o lixo.", + "DELETE_PERMANENTLY": "Apagar permanentemente", + "RESTORE": "Restaurar", + "empty_trash": "Esvaziar lixo", + "empty_trash_title": "Esvaziar lixo?", + "empty_trash_message": "Estes ficheiros serão permanentemente eliminados da sua conta Ente.", + "leave_album": "Sair do álbum", + "leave_shared_album_title": "Sair do álbum compartilhado?", + "leave_shared_album_message": "Sairá do álbum e este deixará de ser visível para si.", + "leave_shared_album": "Sim, sair", + "NOT_FILE_OWNER": "Não é possível apagar ficheiros de um álbum partilhado", + "CONFIRM_SELF_REMOVE_MESSAGE": "Os itens selecionados serão removidos deste álbum. Os itens que estão apenas neste álbum serão movidos para Uncategorized.", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Alguns dos itens que está a remover foram adicionados por outras pessoas, pelo que perderá o acesso aos mesmos.", + "oldest": "Mais antigo", + "last_updated": "Última atualização", + "name": "Nome", + "FIX_CREATION_TIME": "Corrigir hora", + "FIX_CREATION_TIME_IN_PROGRESS": "Corrigindo horário", + "CREATION_TIME_UPDATED": "Hora do arquivo atualizado", + "UPDATE_CREATION_TIME_NOT_STARTED": "Selecione a opção que deseja usar", + "UPDATE_CREATION_TIME_COMPLETED": "Todos os arquivos atualizados com sucesso", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "A atualização do horário falhou para alguns arquivos, por favor, tente novamente", + "CAPTION_CHARACTER_LIMIT": "5000 caracteres no máximo", + "DATE_TIME_ORIGINAL": "Exif: Data e Hora Original", + "DATE_TIME_DIGITIZED": "Exif: Data e Hora Digitalizada", + "METADATA_DATE": "Exif: Data de Metadados", + "CUSTOM_TIME": "Tempo personalizado", + "sharing_details": "Detalhes de compartilhamento", + "modify_sharing": "Modificar compartilhamento", + "ADD_COLLABORATORS": "Adicionar colaboradores", + "ADD_NEW_EMAIL": "Adicionar um novo email", + "shared_with_people_count_zero": "Partilhar com pessoas específicas", + "shared_with_people_count_one": "Partilhado com 1 pessoa", + "shared_with_people_count": "Partilhado com {{count, number}} pessoas", + "participants_count_zero": "Nenhum participante", + "participants_count_one": "1 participante", + "participants_count": "{{count, number}} participantes", + "ADD_VIEWERS": "Adicionar visualizações", + "CHANGE_PERMISSIONS_TO_VIEWER": "

{{selectedEmail}} não poderá adicionar mais fotografias ao álbum

Ainda poderão remover fotografias adicionadas por eles

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

{{selectedEmail}} será removido do álbum

Quaisquer fotografias adicionadas por ele também serão removidas do álbum

", + "NOT_FOUND": "404 Página não encontrada", + "LINK_EXPIRED": "Link expirado", + "LINK_EXPIRED_MESSAGE": "Este link expirou ou foi desativado!", + "MANAGE_LINK": "Gerir link", + "LINK_TOO_MANY_REQUESTS": "Desculpe, este álbum foi visualizado em muitos dispositivos!", + "FILE_DOWNLOAD": "Permitir downloads", + "link_password_lock": "Bloqueio da palavra-passe", + "PUBLIC_COLLECT": "Permitir adicionar fotos", + "LINK_DEVICE_LIMIT": "Limite de dispositivos", + "NO_DEVICE_LIMIT": "Nenhum", + "LINK_EXPIRY": "Link expirado", + "NEVER": "Nunca", + "DISABLE_FILE_DOWNLOAD": "Desativar download", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Tem a certeza de que pretende desativar o botão de transferência de ficheiros?

Os espectadores podem ainda tirar capturas de ecrã ou guardar uma cópia das suas fotografias utilizando ferramentas externas.

", + "SHARED_USING": "Partilhado utilizando ", + "SHARING_REFERRAL_CODE": "Use o código {{referralCode}} para obter 10 GB de graça", + "LIVE": "EM DIRETO", + "DISABLE_PASSWORD": "Desativar o bloqueio da palavra-passe", + "DISABLE_PASSWORD_MESSAGE": "Tem a certeza de que pretende desativar o bloqueio de palavra-passe?", + "PASSWORD_LOCK": "Bloqueio da palavra-passe", + "LOCK": "Bloquear", + "file": "Arquivo", + "folder": "Pasta", + "google_takeout": "Google Takeout", + "DEDUPLICATE_FILES": "Arquivos duplicados", + "NO_DUPLICATES_FOUND": "Não existem ficheiros duplicados que possam ser eliminados", + "FILES": "arquivos", + "EACH": "cada", + "DEDUPLICATE_BASED_ON_SIZE": "Os seguintes ficheiros foram agrupados com base nos seus tamanhos. Reveja e elimine os itens que considera duplicados", + "STOP_ALL_UPLOADS_MESSAGE": "Tem a certeza de que pretende parar todos os carregamentos em curso?", + "STOP_UPLOADS_HEADER": "Parar uploads?", + "YES_STOP_UPLOADS": "Sim, parar uploads", + "STOP_DOWNLOADS_HEADER": "Parar downloads?", + "YES_STOP_DOWNLOADS": "Sim, parar downloads", + "STOP_ALL_DOWNLOADS_MESSAGE": "Tem a certeza de que pretende parar todas as transferências em curso?", + "albums": "Álbuns", + "albums_count_one": "1 Álbum", + "albums_count": "{{count, number}} Álbuns", + "all_albums": "Todos os álbuns", + "all_hidden_albums": "Todos os álbuns ocultos", + "hidden_albums": "Álbuns ocultos", + "hidden_items": "Itens ocultos", + "ENTER_TWO_FACTOR_OTP": "Introduzir o código de 6 dígitos da\nsua aplicação de autenticação.", + "create_account": "Criar conta", + "COPIED": "Copiado", + "WATCH_FOLDERS": "Pastas monitoradas", + "upgrade_now": "Atualizar agora", + "renew_now": "Renovar agora", + "STORAGE": "Armazenamento", + "USED": "utilizado", + "YOU": "Tu", + "FAMILY": "Família", + "FREE": "grátis", + "OF": "de", + "WATCHED_FOLDERS": "Pastas monitoradas", + "NO_FOLDERS_ADDED": "Nenhuma pasta adicionada ainda!", + "FOLDERS_AUTOMATICALLY_MONITORED": "As pastas que adicionar aqui serão monitorizadas automaticamente", + "UPLOAD_NEW_FILES_TO_ENTE": "Carregar novos ficheiros para o Ente", + "REMOVE_DELETED_FILES_FROM_ENTE": "Remover ficheiros eliminados do Ente", + "ADD_FOLDER": "Adicionar pasta", + "STOP_WATCHING": "Parar de assistir", + "STOP_WATCHING_FOLDER": "Deixar de ver a pasta?", + "STOP_WATCHING_DIALOG_MESSAGE": "Os seus ficheiros existentes não serão eliminados, mas o Ente deixará de atualizar automaticamente o álbum Ente associado às alterações nesta pasta.", + "YES_STOP": "Sim, parar", + "CHANGE_FOLDER": "Alterar pasta", + "FAMILY_PLAN": "Plano familiar", + "debug_logs": "Logs de depuração", + "download_logs": "Descarregar logs", + "download_logs_message": "

Isto irá descarregar registos de depuração, que pode enviar-nos por correio eletrónico para ajudar a depurar o seu problema.

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

", + "WEAK_DEVICE": "O navegador Web que está a utilizar não é suficientemente potente para encriptar as suas fotografias. Tente iniciar sessão no Ente no seu computador ou descarregue a aplicação móvel/desktop do Ente.", + "drag_and_drop_hint": "Ou arrastar e largar na janela Ente", + "AUTHENTICATE": "Autenticar", + "UPLOADED_TO_SINGLE_COLLECTION": "Carregado para uma coleção única", + "UPLOADED_TO_SEPARATE_COLLECTIONS": "Carregado para colecções separadas", + "NEVERMIND": "Esquecer", + "update_available": "Atualização disponível", + "update_installable_message": "Uma nova versão do Ente está pronta para ser instalada.", + "install_now": "Instalar agora", + "install_on_next_launch": "Instalar na próxima inicialização", + "update_available_message": "Foi lançada uma nova versão do Ente, mas não pode ser descarregada e instalada automaticamente.", + "download_and_install": "Descarregar e instalar", + "ignore_this_version": "Ignorar esta versão", + "TODAY": "Hoje", + "YESTERDAY": "Ontem", + "NAME_PLACEHOLDER": "Nome...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Não foi possível criar álbuns a partir da mistura de arquivos/pastas", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

Arrastou e largou uma mistura de ficheiros e pastas.

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

", + "CHOSE_THEME": "Escolher tema", + "more_details": "Mais detalhes", + "ml_search": "Aprendizagem automática", + "ml_search_description": "O Ente suporta a aprendizagem automática no dispositivo para reconhecimento facial, pesquisa mágica e outras funcionalidades de pesquisa avançadas", + "ml_search_footnote": "A pesquisa mágica permite pesquisar fotografias pelo seu conteúdo, por exemplo, “carro”, “carro vermelho”, “Ferrari", + "indexing": "Indexar", + "processed": "Processado", + "indexing_status_running": "Em execução", + "indexing_status_fetching": "A procurar", + "indexing_status_scheduled": "Agendado", + "indexing_status_done": "Concluído", + "ml_search_disable": "Desativar aprendizado automático", + "ml_search_disable_confirm": "Pretende desativar a aprendizagem automática em todos os seus dispositivos?", + "ml_consent": "Ativar aprendizagem automática", + "ml_consent_title": "Ativar aprendizagem automática?", + "ml_consent_description": "

Se ativar a aprendizagem automática, o Ente extrairá informações como a geometria do rosto de ficheiros, incluindo os partilhados consigo.

Isto acontecerá no seu dispositivo e qualquer informação biométrica gerada será encriptada de ponta a ponta.

Clique aqui para obter mais detalhes sobre esta funcionalidade na nossa política de privacidade

", + "ml_consent_confirmation": "Eu entendo, e desejo ativar a aprendizagem automática", + "labs": "Laboratórios", + "YOURS": "seu", + "passphrase_strength_weak": "Força da palavra-passe: Fraca", + "passphrase_strength_moderate": "Força da palavra-passe: Moderada", + "passphrase_strength_strong": "Força da palavra-passe: Forte", + "preferences": "Preferências", + "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 selecionou não existe.

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

", + "SUBSCRIPTION_VERIFICATION_ERROR": "Falha na verificação da subscrição", "storage_unit": { - "b": "", - "kb": "", - "mb": "", - "gb": "", - "tb": "" + "b": "B", + "kb": "KB", + "mb": "MB", + "gb": "GB", + "tb": "TB" }, "AFTER_TIME": { - "HOUR": "", - "DAY": "", - "WEEK": "", - "MONTH": "", - "YEAR": "" + "HOUR": "após uma hora", + "DAY": "após um dia", + "WEEK": "após uma semana", + "MONTH": "após um mês", + "YEAR": "após um ano" }, - "COPY_LINK": "", - "DONE": "", - "LINK_SHARE_TITLE": "", - "REMOVE_LINK": "", - "CREATE_PUBLIC_SHARING": "", - "PUBLIC_LINK_CREATED": "", - "PUBLIC_LINK_ENABLED": "", - "COLLECT_PHOTOS": "", - "PUBLIC_COLLECT_SUBTEXT": "", - "STOP_EXPORT": "", - "EXPORT_PROGRESS": "", - "MIGRATING_EXPORT": "", - "RENAMING_COLLECTION_FOLDERS": "", - "TRASHING_DELETED_FILES": "", - "TRASHING_DELETED_COLLECTIONS": "", - "CONTINUOUS_EXPORT": "", - "PENDING_ITEMS": "", - "EXPORT_STARTING": "", - "delete_account_reason_label": "", - "delete_account_reason_placeholder": "", + "COPY_LINK": "Copiar link", + "DONE": "Concluído", + "LINK_SHARE_TITLE": "Ou partilhar uma link", + "REMOVE_LINK": "Remover link", + "CREATE_PUBLIC_SHARING": "Criar link público", + "PUBLIC_LINK_CREATED": "Link público criado", + "PUBLIC_LINK_ENABLED": "Link público ativado", + "COLLECT_PHOTOS": "Recolher fotos", + "PUBLIC_COLLECT_SUBTEXT": "Permitir que as pessoas com a ligação também adicionem fotos ao álbum partilhado.", + "STOP_EXPORT": "Parar", + "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} itens sincronizados", + "MIGRATING_EXPORT": "Preparar...", + "RENAMING_COLLECTION_FOLDERS": "Renomear pastas de álbuns...", + "TRASHING_DELETED_FILES": "Eliminar arquivos apagados...", + "TRASHING_DELETED_COLLECTIONS": "Eliminar álbuns apagados...", + "CONTINUOUS_EXPORT": "Sincronização contínua", + "PENDING_ITEMS": "Itens pendentes", + "EXPORT_STARTING": "Iniciar a exportação...", + "delete_account_reason_label": "Qual o principal motivo pelo qual está a eliminar a conta?", + "delete_account_reason_placeholder": "Selecione um motivo", "delete_reason": { - "missing_feature": "", - "behaviour": "", - "found_another_service": "", - "not_listed": "" + "missing_feature": "Falta uma chave que eu preciso", + "behaviour": "O aplicativo ou um determinado recurso não se comportou como era suposto", + "found_another_service": "Encontrei outro serviço que gosto mais", + "not_listed": "O motivo não está na lista" }, - "delete_account_feedback_label": "", - "delete_account_feedback_placeholder": "", - "delete_account_confirm_checkbox_label": "", - "delete_account_confirm": "", - "delete_account_confirm_message": "", - "feedback_required": "", - "feedback_required_found_another_service": "", - "RECOVER_TWO_FACTOR": "", - "at": "", - "AUTH_NEXT": "", - "AUTH_DOWNLOAD_MOBILE_APP": "", - "HIDE": "", - "UNHIDE": "", - "sort_by": "", - "newest_first": "", - "oldest_first": "", - "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", - "pin_album": "", - "unpin_album": "", - "DOWNLOAD_COMPLETE": "", - "DOWNLOADING_COLLECTION": "", - "DOWNLOAD_FAILED": "", - "DOWNLOAD_PROGRESS": "", - "CHRISTMAS": "", - "CHRISTMAS_EVE": "", - "NEW_YEAR": "", - "NEW_YEAR_EVE": "", - "IMAGE": "", - "VIDEO": "", - "LIVE_PHOTO": "", + "delete_account_feedback_label": "Lamentamos a sua partida. Indique-nos a razão para podermos melhorar o serviço.", + "delete_account_feedback_placeholder": "Feedback", + "delete_account_confirm_checkbox_label": "Sim, quero apagar permanentemente esta conta e todos os seus dados", + "delete_account_confirm": "Confirmar eliminação da conta", + "delete_account_confirm_message": "

Esta conta está ligada a outras aplicações Ente, se utilizar alguma.

Os seus dados carregados, em todas as aplicações Ente, serão agendados para eliminação e a sua conta será permanentemente eliminada.

", + "feedback_required": "Por favor, ajude-nos com esta informação", + "feedback_required_found_another_service": "O que o outro serviço faz melhor?", + "RECOVER_TWO_FACTOR": "Recuperar dois fatores", + "at": "em", + "AUTH_NEXT": "seguinte", + "AUTH_DOWNLOAD_MOBILE_APP": "Descarregue a nossa aplicação móvel para gerir os seus segredos", + "HIDE": "Ocultar", + "UNHIDE": "Mostrar", + "sort_by": "Ordenar por", + "newest_first": "Mais recentes primeiro", + "oldest_first": "Mais antigo primeiro", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "Este arquivo não pôde ser visualizado. Clique aqui para fazer o download original.", + "pin_album": "Fixar álbum", + "unpin_album": "Desafixar álbum", + "DOWNLOAD_COMPLETE": "Download concluído", + "DOWNLOADING_COLLECTION": "Fazer download de {{name}}", + "DOWNLOAD_FAILED": "Falha no download", + "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} arquivos", + "CHRISTMAS": "Natal", + "CHRISTMAS_EVE": "Véspera de Natal", + "NEW_YEAR": "Ano Novo", + "NEW_YEAR_EVE": "Véspera de Ano Novo", + "IMAGE": "Imagem", + "VIDEO": "Vídeo", + "LIVE_PHOTO": "Fotos em movimento", "editor": { - "crop": "" + "crop": "Recortar" }, - "CONVERT": "", - "confirm_editor_close": "", - "confirm_editor_close_message": "", - "BRIGHTNESS": "", - "CONTRAST": "", - "SATURATION": "", - "BLUR": "", - "INVERT_COLORS": "", - "ASPECT_RATIO": "", - "SQUARE": "", - "ROTATE_LEFT": "", - "ROTATE_RIGHT": "", - "FLIP_VERTICALLY": "", - "FLIP_HORIZONTALLY": "", - "DOWNLOAD_EDITED": "", - "SAVE_A_COPY_TO_ENTE": "", - "RESTORE_ORIGINAL": "", - "TRANSFORM": "", - "COLORS": "", - "FLIP": "", - "ROTATION": "", - "reset": "", - "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "CONVERT": "Converter", + "confirm_editor_close": "Tem certeza de que deseja fechar o editor?", + "confirm_editor_close_message": "Descarregue a imagem editada ou guarde uma cópia no Ente para manter as alterações.", + "BRIGHTNESS": "Brilho", + "CONTRAST": "Contraste", + "SATURATION": "Saturação", + "BLUR": "Desfoque", + "INVERT_COLORS": "Inverter Cores", + "ASPECT_RATIO": "Proporção da imagem", + "SQUARE": "Quadrado", + "ROTATE_LEFT": "Rodar para a esquerda", + "ROTATE_RIGHT": "Rodar para a direita", + "FLIP_VERTICALLY": "Inverter verticalmente", + "FLIP_HORIZONTALLY": "Inverter horizontalmente", + "DOWNLOAD_EDITED": "Descarregar Editado", + "SAVE_A_COPY_TO_ENTE": "Salvar uma cópia para o Ente", + "RESTORE_ORIGINAL": "Restaurar original", + "TRANSFORM": "Transformar", + "COLORS": "Cores", + "FLIP": "Inverter", + "ROTATION": "Rotação", + "reset": "Restaurar", + "PHOTO_EDITOR": "Editor de Fotos", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/ro-RO/translation.json b/web/packages/base/locales/ro-RO/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/ro-RO/translation.json +++ b/web/packages/base/locales/ro-RO/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/ru-RU/translation.json b/web/packages/base/locales/ru-RU/translation.json index c0664f327e..3c584a7831 100644 --- a/web/packages/base/locales/ru-RU/translation.json +++ b/web/packages/base/locales/ru-RU/translation.json @@ -47,6 +47,7 @@ "close_key": "Закрыть (Esc)", "enter_file_name": "Имя файла", "close": "Закрыть", + "yes": "", "no": "Нет", "nothing_here": "", "upload": "Загрузить", @@ -228,9 +229,26 @@ "indexing_fetching": "Получение индексов ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "Индексирование людей на {{nSyncedFiles, number}} фотографиях...", "indexing_done": "Проиндексировано {{nSyncedFiles, number}} фотографий", - "UNIDENTIFIED_FACES": "Нераспознанные лица", - "OBJECTS": "объекты", - "TEXT": "текст", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "Информация ", "INFO_OPTION": "Информация (I)", "file_name": "Имя файла", @@ -238,7 +256,6 @@ "location": "Местоположение", "view_on_map": "Просмотр на OpenStreetMap", "map": "Карта", - "map_settings": "Настройки карты", "enable_map": "Включить отображение", "enable_maps_confirm": "Включить карты?", "enable_maps_confirm_message": "

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

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

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

", @@ -250,28 +267,26 @@ "no_exif": "Нет данных Exif", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "Двухфакторный", - "TWO_FACTOR_AUTHENTICATION": "Двухфакторная аутентификация", + "two_factor": "Двухфакторный", + "two_factor_authentication": "Двухфакторная аутентификация", "TWO_FACTOR_QR_INSTRUCTION": "Сканируйте QR-код ниже с вашим любимым приложением для проверки подлинности", "ENTER_CODE_MANUALLY": "Введите код вручную", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Пожалуйста, введите этот код в вашем любимом приложении для аутентификации", "SCAN_QR_CODE": "Сканировать QR-код вместо", - "ENABLE_TWO_FACTOR": "Включить двухфакторную аутентификацию", + "enable_two_factor": "Включить двухфакторную аутентификацию", "enable": "Включить", "enabled": "Включено", "LOST_DEVICE": "Потеряно двухфакторное устройство", "INCORRECT_CODE": "Неверный код", - "TWO_FACTOR_INFO": "Добавьте дополнительный уровень безопасности, запросив для входа в свою учетную запись не только адрес электронной почты и пароль", - "DISABLE_TWO_FACTOR_LABEL": "Отключить двухфакторную аутентификацию", - "UPDATE_TWO_FACTOR_LABEL": "Обновите свое устройство аутентификации", + "two_factor_info": "Добавьте дополнительный уровень безопасности, запросив для входа в свою учетную запись не только адрес электронной почты и пароль", "disable": "Отключить", "reconfigure": "Перенастроить", - "UPDATE_TWO_FACTOR": "Обновить двухфакторную аутентификацию", - "UPDATE_TWO_FACTOR_MESSAGE": "Дальнейшая переадресация приведет к аннулированию всех ранее настроенных средств проверки подлинности", - "UPDATE": "Обновить", - "DISABLE_TWO_FACTOR": "Отключить двухфакторную аутентификацию", - "DISABLE_TWO_FACTOR_MESSAGE": "Вы уверены, что хотите отключить двухфакторную аутентификацию", - "TWO_FACTOR_DISABLE_FAILED": "Не удалось отключить два фактора, пожалуйста, повторите попытку", + "reconfigure_two_factor_hint": "Обновите свое устройство аутентификации", + "update_two_factor": "Обновить двухфакторную аутентификацию", + "update_two_factor_message": "Дальнейшая переадресация приведет к аннулированию всех ранее настроенных средств проверки подлинности", + "update": "Обновить", + "disable_two_factor": "Отключить двухфакторную аутентификацию", + "disable_two_factor_message": "Вы уверены, что хотите отключить двухфакторную аутентификацию", "EXPORT_DATA": "Экспортировать данные", "select_folder": "Выбрать папку", "select_zips": "Выберите zip-архив", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "Вы не можете удалить файлы из общего альбома", "CONFIRM_SELF_REMOVE_MESSAGE": "Выбранные элементы будут удалены из этого альбома. Элементы, которые есть только в этом альбоме, будут перемещены в раздел без рубрики.", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Некоторые из удаляемых вами элементов были добавлены другими пользователями, и вы потеряете к ним доступ.", - "sort_by_creation_time_ascending": "Старейший", - "sort_by_updation_time_descending": "Последнее обновление", - "sort_by_name": "Имя", + "oldest": "Старейший", + "last_updated": "Последнее обновление", + "name": "Имя", "FIX_CREATION_TIME": "Назначьте время", "FIX_CREATION_TIME_IN_PROGRESS": "Фиксирующее время", "CREATION_TIME_UPDATED": "Время обновления файла", @@ -594,8 +609,8 @@ "ROTATION": "Вращение", "reset": "Сбросить", "PHOTO_EDITOR": "Редактор фото", - "FASTER_UPLOAD": "Более быстрая загрузка данных", - "FASTER_UPLOAD_DESCRIPTION": "Загрузка маршрута через близлежащие серверы", + "faster_upload": "Более быстрая загрузка данных", + "faster_upload_description": "Загрузка маршрута через близлежащие серверы", "cast_album_to_tv": "Воспроизвести альбом на ТВ", "enter_cast_pin_code": "Введите код, который вы видите на экране телевизора ниже, чтобы выполнить сопряжение с этим устройством.", "pair_device_to_tv": "Сопряжение устройств", diff --git a/web/packages/base/locales/sl-SI/translation.json b/web/packages/base/locales/sl-SI/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/sl-SI/translation.json +++ b/web/packages/base/locales/sl-SI/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/sv-SE/translation.json b/web/packages/base/locales/sv-SE/translation.json index 95bf2fd0aa..7062b7d8f6 100644 --- a/web/packages/base/locales/sv-SE/translation.json +++ b/web/packages/base/locales/sv-SE/translation.json @@ -47,6 +47,7 @@ "close_key": "Stäng (Esc)", "enter_file_name": "Filnamn", "close": "Stäng", + "yes": "", "no": "Nej", "nothing_here": "", "upload": "Ladda upp", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "Filnamn", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "Karta", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "Ingen Exif-data", "exif": "Exif", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "Tvåfaktorsautentisering", + "two_factor": "", + "two_factor_authentication": "Tvåfaktorsautentisering", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "Ange koden manuellt", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "Skanna QR-kod istället", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "Aktivera", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "Felaktig kod", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "Inaktivera tvåfaktorsautentisering", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "Inaktivera", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "Uppdatera", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "Uppdatera", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "Exportera data", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "Namn", + "oldest": "", + "last_updated": "", + "name": "Namn", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "Återställ", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "Spela album på TV", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/ta-IN/translation.json b/web/packages/base/locales/ta-IN/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/ta-IN/translation.json +++ b/web/packages/base/locales/ta-IN/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/te-IN/translation.json b/web/packages/base/locales/te-IN/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/te-IN/translation.json +++ b/web/packages/base/locales/te-IN/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/th-TH/translation.json b/web/packages/base/locales/th-TH/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/th-TH/translation.json +++ b/web/packages/base/locales/th-TH/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/ti-ER/translation.json b/web/packages/base/locales/ti-ER/translation.json index b2563bb505..583f577a3b 100644 --- a/web/packages/base/locales/ti-ER/translation.json +++ b/web/packages/base/locales/ti-ER/translation.json @@ -47,6 +47,7 @@ "close_key": "", "enter_file_name": "", "close": "", + "yes": "", "no": "", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/tr-TR/translation.json b/web/packages/base/locales/tr-TR/translation.json index 700a6c297f..906909e1ef 100644 --- a/web/packages/base/locales/tr-TR/translation.json +++ b/web/packages/base/locales/tr-TR/translation.json @@ -47,6 +47,7 @@ "close_key": "Kapat (Esc)", "enter_file_name": "Dosya adı", "close": "Kapat", + "yes": "", "no": "Hayır", "nothing_here": "", "upload": "", @@ -228,9 +229,26 @@ "indexing_fetching": "", "indexing_people": "", "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "", "INFO_OPTION": "", "file_name": "", @@ -238,7 +256,6 @@ "location": "", "view_on_map": "", "map": "", - "map_settings": "", "enable_map": "", "enable_maps_confirm": "", "enable_maps_confirm_message": "", @@ -250,28 +267,26 @@ "no_exif": "", "exif": "", "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", + "two_factor": "", + "two_factor_authentication": "", "TWO_FACTOR_QR_INSTRUCTION": "", "ENTER_CODE_MANUALLY": "", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", + "enable_two_factor": "", "enable": "", "enabled": "", "LOST_DEVICE": "", "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", + "two_factor_info": "", "disable": "", "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", + "reconfigure_two_factor_hint": "", + "update_two_factor": "", + "update_two_factor_message": "", + "update": "", + "disable_two_factor": "", + "disable_two_factor_message": "", "EXPORT_DATA": "", "select_folder": "", "select_zips": "", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "", "CONFIRM_SELF_REMOVE_MESSAGE": "", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", + "oldest": "", + "last_updated": "", + "name": "", "FIX_CREATION_TIME": "", "FIX_CREATION_TIME_IN_PROGRESS": "", "CREATION_TIME_UPDATED": "", @@ -594,8 +609,8 @@ "ROTATION": "", "reset": "", "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", + "faster_upload": "", + "faster_upload_description": "", "cast_album_to_tv": "", "enter_cast_pin_code": "", "pair_device_to_tv": "", diff --git a/web/packages/base/locales/uk-UA/translation.json b/web/packages/base/locales/uk-UA/translation.json index 57c9c12d67..6803527f25 100644 --- a/web/packages/base/locales/uk-UA/translation.json +++ b/web/packages/base/locales/uk-UA/translation.json @@ -35,7 +35,7 @@ "PASSPHRASE_DISCLAIMER": "Ми не зберігаємо ваш пароль, тому якщо ви забудете його, ми не зможемо допомогти вам відновити ваші дані без ключа відновлення.", "key_generation_in_progress": "Створюємо ключі шифрування...", "PASSPHRASE_HINT": "Пароль", - "CONFIRM_PASSPHRASE": "Підтвердіть пароль", + "CONFIRM_PASSPHRASE": "Підтвердьте пароль", "REFERRAL_CODE_HINT": "Як ви дізналися про Ente? (необов'язково)", "REFERRAL_INFO": "Ми не відстежуємо встановлення застосунку. Але, якщо ви скажете нам, де ви нас знайшли, це допоможе!", "PASSPHRASE_MATCH_ERROR": "Паролі не співпадають", @@ -47,6 +47,7 @@ "close_key": "Закрити (Esc)", "enter_file_name": "Назва файлу", "close": "Закрити", + "yes": "", "no": "Ні", "nothing_here": "Тут поки що нічого немає", "upload": "Вивантажити", @@ -103,546 +104,560 @@ "upload_to_single_album": "Один альбом", "upload_to_album_per_folder": "Окремі альбоми", "session_expired": "Час сеансу минув", - "session_expired_message": "", - "PASSWORD_GENERATION_FAILED": "", - "CHANGE_PASSWORD": "", - "password_changed_elsewhere": "", - "password_changed_elsewhere_message": "", - "GO_BACK": "", - "recovery_key": "", - "do_this_later": "", - "save_key": "", - "recovery_key_description": "", - "key_not_stored_note": "", - "recovery_key_generation_failed": "", - "FORGOT_PASSWORD": "", - "RECOVER_ACCOUNT": "", - "RECOVERY_KEY_HINT": "", - "RECOVER": "", - "NO_RECOVERY_KEY": "", - "INCORRECT_RECOVERY_KEY": "", - "sorry": "", - "no_recovery_key_message": "", - "no_two_factor_recovery_key_message": "", - "contact_support": "", - "request_feature": "", - "support": "", - "cancel": "", - "logout": "", - "logout_message": "", - "delete_account": "", - "delete_account_manually_message": "", - "CHANGE_EMAIL": "", - "ok": "", - "success": "", - "error": "", - "OFFLINE_MSG": "", - "install": "", - "install_mobile_app": "", - "download_app": "", - "download_app_message": "", - "EXPORT": "", - "SUBSCRIPTION": "", - "SUBSCRIBE": "", - "MANAGEMENT_PORTAL": "", - "MANAGE_FAMILY_PORTAL": "", - "LEAVE_FAMILY_PLAN": "", - "LEAVE": "", - "LEAVE_FAMILY_CONFIRM": "", - "CHOOSE_PLAN": "", - "MANAGE_PLAN": "", - "CURRENT_USAGE": "", - "TWO_MONTHS_FREE": "", + "session_expired_message": "Ваш сеанс закінчився, увійдіть знову, щоби продовжити", + "PASSWORD_GENERATION_FAILED": "Ваш браузер не зміг згенерувати надійний ключ, який відповідає стандартам шифрування Ente, спробуйте скористатися мобільним застосунком або іншим браузером", + "CHANGE_PASSWORD": "Змінити пароль", + "password_changed_elsewhere": "Пароль змінено в іншому місці", + "password_changed_elsewhere_message": "Увійдіть ще раз на цьому пристрої, щоби використати новий пароль для автентифікації.", + "GO_BACK": "Повернутися", + "recovery_key": "Ключ відновлення", + "do_this_later": "Зробити це пізніше", + "save_key": "Зберегти ключ", + "recovery_key_description": "Якщо ви забудете свій пароль, то єдиний спосіб відновити ваші дані – за допомогою цього ключа.", + "key_not_stored_note": "Ми не зберігаємо цей ключ, тому зберігайте його в безпечному місці", + "recovery_key_generation_failed": "Не вдалося згенерувати код відновлення, спробуйте ще раз", + "FORGOT_PASSWORD": "Нагадати пароль", + "RECOVER_ACCOUNT": "Відновити обліковий запис", + "RECOVERY_KEY_HINT": "Ключ відновлення", + "RECOVER": "Відновити", + "NO_RECOVERY_KEY": "Немає ключа відновлення?", + "INCORRECT_RECOVERY_KEY": "Невірний ключ відновлення", + "sorry": "Пробачте", + "no_recovery_key_message": "Через природу нашого кінцевого протоколу шифрування, ваші дані не можуть бути розшифровані без вашого пароля або ключа відновлення", + "no_two_factor_recovery_key_message": "Надішліть листа на {{emailID}} з вашої зареєстрованої поштової адреси", + "contact_support": "Звернутися до служби підтримки", + "request_feature": "Запропонувати функцію", + "support": "Підтримка", + "cancel": "Скасувати", + "logout": "Вийти", + "logout_message": "Ви впевнені, що хочете вийти з облікового запису?", + "delete_account": "Видалити обліковий запис", + "delete_account_manually_message": "

Надішліть листа на {{emailID}} з вашої зареєстрованої поштової адреси.

Ваш запит буде оброблено протягом 72 годин.

", + "CHANGE_EMAIL": "Змінити поштову адресу", + "ok": "Гаразд", + "success": "Успішно", + "error": "Помилка", + "OFFLINE_MSG": "Ви не в мережі, показуються кешовані спогади", + "install": "Встановити", + "install_mobile_app": "Встановіть наш Android або iOS застосунок для автоматичного резервного копіювання всіх ваших фотографій", + "download_app": "Завантажити настільний застосунок", + "download_app_message": "На жаль, ця операція підтримується тільки для нашого настільного застосунку", + "EXPORT": "Експортувати дані", + "SUBSCRIPTION": "Підписка", + "SUBSCRIBE": "Підписатися", + "MANAGEMENT_PORTAL": "Керувати методом оплати", + "MANAGE_FAMILY_PORTAL": "Керувати сім'єю", + "LEAVE_FAMILY_PLAN": "Покинути сімейний план", + "LEAVE": "Покинути", + "LEAVE_FAMILY_CONFIRM": "Ви впевнені, що хочете залишити сімейний план?", + "CHOOSE_PLAN": "Оберіть свій план", + "MANAGE_PLAN": "Керувати вашою підпискою", + "CURRENT_USAGE": "Поточне використання – {{usage}}", + "TWO_MONTHS_FREE": "Отримуйте 2 місяці безплатно на щорічних планах", "POPULAR": "Популярне", "free_plan_option": "Продовжити з безплатним планом", "free_plan_description": "Безплатно {{storage}} назавжди", "active": "Активний", "subscription_info_free": "Ви на безплатному плані", "subscription_info_family": "Ви на сімейному плані, яким керує", - "subscription_info_expired": "", - "subscription_info_renewal_cancelled": "", - "subscription_info_storage_quota_exceeded": "", - "subscription_status_renewal_active": "", - "subscription_status_renewal_cancelled": "", - "add_on_valid_till": "", - "subscription_expired": "", - "storage_quota_exceeded": "", - "SUBSCRIPTION_PURCHASE_SUCCESS": "", - "SUBSCRIPTION_PURCHASE_CANCELLED": "", - "SUBSCRIPTION_PURCHASE_FAILED": "", - "SUBSCRIPTION_UPDATE_FAILED": "", - "UPDATE_PAYMENT_METHOD_MESSAGE": "", - "STRIPE_AUTHENTICATION_FAILED": "", - "UPDATE_PAYMENT_METHOD": "", - "MONTHLY": "", - "YEARLY": "", - "MONTH_SHORT": "", - "YEAR": "", - "update_subscription_title": "", - "UPDATE_SUBSCRIPTION_MESSAGE": "", - "UPDATE_SUBSCRIPTION": "", - "CANCEL_SUBSCRIPTION": "", - "CANCEL_SUBSCRIPTION_MESSAGE": "", - "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "", - "SUBSCRIPTION_CANCEL_FAILED": "", - "SUBSCRIPTION_CANCEL_SUCCESS": "", - "REACTIVATE_SUBSCRIPTION": "", - "REACTIVATE_SUBSCRIPTION_MESSAGE": "", - "SUBSCRIPTION_ACTIVATE_SUCCESS": "", - "SUBSCRIPTION_ACTIVATE_FAILED": "", - "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "", - "CANCEL_SUBSCRIPTION_ON_MOBILE": "", - "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "", - "MAIL_TO_MANAGE_SUBSCRIPTION": "", - "rename": "", - "rename_file": "", - "rename_album": "", - "delete_album": "", - "delete_album_title": "", - "delete_album_message": "", - "delete_photos": "", - "keep_photos": "", - "share_album": "", - "SHARE_WITH_SELF": "", - "ALREADY_SHARED": "", - "SHARING_BAD_REQUEST_ERROR": "", - "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "", - "CREATE_ALBUM_FAILED": "", - "search": "", - "search_results": "", - "no_results": "", - "search_hint": "", - "album": "", - "date": "", - "description": "", - "file_type": "", - "magic": "", - "photos_count_zero": "", - "photos_count_one": "", - "photos_count": "", - "terms_and_conditions": "", - "SELECTED": "", - "people": "", - "indexing_scheduled": "", - "indexing_photos": "", - "indexing_fetching": "", - "indexing_people": "", - "indexing_done": "", - "UNIDENTIFIED_FACES": "", - "OBJECTS": "", - "TEXT": "", - "INFO": "", - "INFO_OPTION": "", - "file_name": "", - "CAPTION_PLACEHOLDER": "", - "location": "", - "view_on_map": "", - "map": "", - "map_settings": "", - "enable_map": "", - "enable_maps_confirm": "", - "enable_maps_confirm_message": "", - "disable_map": "", - "disable_maps_confirm": "", - "disable_maps_confirm_message": "", - "DETAILS": "", - "view_exif": "", - "no_exif": "", - "exif": "", - "ISO": "", - "TWO_FACTOR": "", - "TWO_FACTOR_AUTHENTICATION": "", - "TWO_FACTOR_QR_INSTRUCTION": "", - "ENTER_CODE_MANUALLY": "", - "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "", - "SCAN_QR_CODE": "", - "ENABLE_TWO_FACTOR": "", - "enable": "", - "enabled": "", - "LOST_DEVICE": "", - "INCORRECT_CODE": "", - "TWO_FACTOR_INFO": "", - "DISABLE_TWO_FACTOR_LABEL": "", - "UPDATE_TWO_FACTOR_LABEL": "", - "disable": "", - "reconfigure": "", - "UPDATE_TWO_FACTOR": "", - "UPDATE_TWO_FACTOR_MESSAGE": "", - "UPDATE": "", - "DISABLE_TWO_FACTOR": "", - "DISABLE_TWO_FACTOR_MESSAGE": "", - "TWO_FACTOR_DISABLE_FAILED": "", - "EXPORT_DATA": "", - "select_folder": "", - "select_zips": "", - "faq": "", - "takeout_hint": "", - "DESTINATION": "", - "START": "", - "LAST_EXPORT_TIME": "", - "EXPORT_AGAIN": "", - "LOCAL_STORAGE_NOT_ACCESSIBLE": "", - "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "", - "SEND_OTT": "", - "EMAIl_ALREADY_OWNED": "", - "ETAGS_BLOCKED": "", - "LIVE_PHOTOS_DETECTED": "", - "RETRY_FAILED": "", - "FAILED_UPLOADS": "", - "failed_uploads_hint": "", - "SKIPPED_FILES": "", - "THUMBNAIL_GENERATION_FAILED_UPLOADS": "", - "UNSUPPORTED_FILES": "", - "SUCCESSFUL_UPLOADS": "", - "SKIPPED_INFO": "", - "UNSUPPORTED_INFO": "", - "BLOCKED_UPLOADS": "", - "INPROGRESS_METADATA_EXTRACTION": "", - "INPROGRESS_UPLOADS": "", - "TOO_LARGE_UPLOADS": "", - "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "", - "LARGER_THAN_AVAILABLE_STORAGE_INFO": "", - "TOO_LARGE_INFO": "", - "THUMBNAIL_GENERATION_FAILED_INFO": "", - "upload_to_album": "", - "add_to_album": "", - "move_to_album": "", - "unhide_to_album": "", - "restore_to_album": "", - "section_all": "", - "section_uncategorized": "", - "section_archive": "", - "section_hidden": "", - "section_trash": "", - "favorites": "", - "archive": "", - "archive_album": "", - "unarchive": "", - "unarchive_album": "", - "hide_collection": "", - "unhide_collection": "", - "MOVE": "", - "add": "", - "REMOVE": "", - "YES_REMOVE": "", - "REMOVE_FROM_COLLECTION": "", - "MOVE_TO_TRASH": "", - "TRASH_FILES_MESSAGE": "", - "TRASH_FILE_MESSAGE": "", - "DELETE_PERMANENTLY": "", - "RESTORE": "", - "empty_trash": "", - "empty_trash_title": "", - "empty_trash_message": "", - "leave_album": "", - "leave_shared_album_title": "", - "leave_shared_album_message": "", - "leave_shared_album": "", - "NOT_FILE_OWNER": "", - "CONFIRM_SELF_REMOVE_MESSAGE": "", - "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "", - "sort_by_creation_time_ascending": "", - "sort_by_updation_time_descending": "", - "sort_by_name": "", - "FIX_CREATION_TIME": "", - "FIX_CREATION_TIME_IN_PROGRESS": "", - "CREATION_TIME_UPDATED": "", - "UPDATE_CREATION_TIME_NOT_STARTED": "", - "UPDATE_CREATION_TIME_COMPLETED": "", - "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "", - "CAPTION_CHARACTER_LIMIT": "", - "DATE_TIME_ORIGINAL": "", - "DATE_TIME_DIGITIZED": "", - "METADATA_DATE": "", - "CUSTOM_TIME": "", - "sharing_details": "", - "modify_sharing": "", - "ADD_COLLABORATORS": "", - "ADD_NEW_EMAIL": "", - "shared_with_people_count_zero": "", - "shared_with_people_count_one": "", - "shared_with_people_count": "", - "participants_count_zero": "", - "participants_count_one": "", - "participants_count": "", - "ADD_VIEWERS": "", - "CHANGE_PERMISSIONS_TO_VIEWER": "", - "CHANGE_PERMISSIONS_TO_COLLABORATOR": "", - "CONVERT_TO_VIEWER": "", - "CONVERT_TO_COLLABORATOR": "", - "CHANGE_PERMISSION": "", - "REMOVE_PARTICIPANT": "", - "CONFIRM_REMOVE": "", - "MANAGE": "", - "ADDED_AS": "", - "COLLABORATOR_RIGHTS": "", - "REMOVE_PARTICIPANT_HEAD": "", - "OWNER": "", - "COLLABORATORS": "", - "ADD_MORE": "", - "VIEWERS": "", - "OR_ADD_EXISTING": "", - "REMOVE_PARTICIPANT_MESSAGE": "", - "NOT_FOUND": "", - "LINK_EXPIRED": "", - "LINK_EXPIRED_MESSAGE": "", - "MANAGE_LINK": "", - "LINK_TOO_MANY_REQUESTS": "", - "FILE_DOWNLOAD": "", - "link_password_lock": "", - "PUBLIC_COLLECT": "", - "LINK_DEVICE_LIMIT": "", - "NO_DEVICE_LIMIT": "", - "LINK_EXPIRY": "", - "NEVER": "", - "DISABLE_FILE_DOWNLOAD": "", - "DISABLE_FILE_DOWNLOAD_MESSAGE": "", - "SHARED_USING": "", - "SHARING_REFERRAL_CODE": "", - "LIVE": "", - "DISABLE_PASSWORD": "", - "DISABLE_PASSWORD_MESSAGE": "", - "PASSWORD_LOCK": "", - "LOCK": "", - "file": "", - "folder": "", - "google_takeout": "", - "DEDUPLICATE_FILES": "", - "NO_DUPLICATES_FOUND": "", - "FILES": "", - "EACH": "", - "DEDUPLICATE_BASED_ON_SIZE": "", - "STOP_ALL_UPLOADS_MESSAGE": "", - "STOP_UPLOADS_HEADER": "", - "YES_STOP_UPLOADS": "", - "STOP_DOWNLOADS_HEADER": "", - "YES_STOP_DOWNLOADS": "", - "STOP_ALL_DOWNLOADS_MESSAGE": "", - "albums": "", - "albums_count_one": "", - "albums_count": "", - "all_albums": "", - "all_hidden_albums": "", - "hidden_albums": "", - "hidden_items": "", - "ENTER_TWO_FACTOR_OTP": "", - "create_account": "", - "COPIED": "", - "WATCH_FOLDERS": "", - "upgrade_now": "", - "renew_now": "", - "STORAGE": "", - "USED": "", - "YOU": "", - "FAMILY": "", - "FREE": "", - "OF": "", - "WATCHED_FOLDERS": "", - "NO_FOLDERS_ADDED": "", - "FOLDERS_AUTOMATICALLY_MONITORED": "", - "UPLOAD_NEW_FILES_TO_ENTE": "", - "REMOVE_DELETED_FILES_FROM_ENTE": "", - "ADD_FOLDER": "", - "STOP_WATCHING": "", - "STOP_WATCHING_FOLDER": "", - "STOP_WATCHING_DIALOG_MESSAGE": "", - "YES_STOP": "", - "CHANGE_FOLDER": "", - "FAMILY_PLAN": "", - "debug_logs": "", - "download_logs": "", - "download_logs_message": "", - "WEAK_DEVICE": "", - "drag_and_drop_hint": "", - "AUTHENTICATE": "", - "UPLOADED_TO_SINGLE_COLLECTION": "", - "UPLOADED_TO_SEPARATE_COLLECTIONS": "", - "NEVERMIND": "", - "update_available": "", - "update_installable_message": "", - "install_now": "", - "install_on_next_launch": "", - "update_available_message": "", - "download_and_install": "", - "ignore_this_version": "", - "TODAY": "", - "YESTERDAY": "", - "NAME_PLACEHOLDER": "", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "", - "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "", - "CHOSE_THEME": "", - "more_details": "", - "ml_search": "", - "ml_search_description": "", - "ml_search_footnote": "", - "indexing": "", - "processed": "", - "indexing_status_running": "", - "indexing_status_fetching": "", - "indexing_status_scheduled": "", - "indexing_status_done": "", - "ml_search_disable": "", - "ml_search_disable_confirm": "", - "ml_consent": "", - "ml_consent_title": "", - "ml_consent_description": "", - "ml_consent_confirmation": "", - "labs": "", - "YOURS": "", - "passphrase_strength_weak": "", - "passphrase_strength_moderate": "", - "passphrase_strength_strong": "", - "preferences": "", - "language": "", - "advanced": "", - "EXPORT_DIRECTORY_DOES_NOT_EXIST": "", - "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "", - "SUBSCRIPTION_VERIFICATION_ERROR": "", + "subscription_info_expired": "Термін дії вашої підписки закінчився, оновіть її", + "subscription_info_renewal_cancelled": "Вашу підписку буде скасовано {{date, date}}", + "subscription_info_storage_quota_exceeded": "Ви перевищили свій ліміт зберігання, покращте підписку", + "subscription_status_renewal_active": "Оновлення {{date, date}}", + "subscription_status_renewal_cancelled": "Закінчення {{date, date}}", + "add_on_valid_till": "Ваше доповнення {{storage}} дійсне до {{date, date}}", + "subscription_expired": "Термін дії підписки вичерпано", + "storage_quota_exceeded": "Перевищено ліміт сховища", + "SUBSCRIPTION_PURCHASE_SUCCESS": "

Ми отримали вашу оплату

Ваша підписка дійсна до {{date, date}}

", + "SUBSCRIPTION_PURCHASE_CANCELLED": "Ваше придбання було скасовано, спробуйте ще раз, якщо ви хочете підписатися", + "SUBSCRIPTION_PURCHASE_FAILED": "Не вдалося придбати підписку, спробуйте ще раз", + "SUBSCRIPTION_UPDATE_FAILED": "Не вдалося оновити підписку, спробуйте ще раз", + "UPDATE_PAYMENT_METHOD_MESSAGE": "Вибачте, при спробі списання коштів з вашої картки сталася помилка, оновіть спосіб оплати та повторіть спробу", + "STRIPE_AUTHENTICATION_FAILED": "Ми не можемо підтвердити ваш спосіб оплати, оберіть інший спосіб оплати та спробуйте ще раз", + "UPDATE_PAYMENT_METHOD": "Оновити спосіб оплати", + "MONTHLY": "Щомісяця", + "YEARLY": "Щороку", + "MONTH_SHORT": "міс.", + "YEAR": "рік", + "update_subscription_title": "Підтвердити зміну плану", + "UPDATE_SUBSCRIPTION_MESSAGE": "Ви впевнені, що хочете змінити свій план?", + "UPDATE_SUBSCRIPTION": "Змінити тарифний план", + "CANCEL_SUBSCRIPTION": "Скасувати підписку", + "CANCEL_SUBSCRIPTION_MESSAGE": "

Всі ваші дані будуть видалені з наших серверів в кінці цього розрахункового періоду.

Ви впевнені, що хочете скасувати підписку?

", + "CANCEL_SUBSCRIPTION_WITH_ADDON_MESSAGE": "

Ви впевнені, що хочете скасувати підписку?

", + "SUBSCRIPTION_CANCEL_FAILED": "Не вдалося скасувати підписку", + "SUBSCRIPTION_CANCEL_SUCCESS": "Підписку успішно скасовано", + "REACTIVATE_SUBSCRIPTION": "Відновити підписку", + "REACTIVATE_SUBSCRIPTION_MESSAGE": "Після повторної активації, ви отримаєте рахунок {{date, date}}", + "SUBSCRIPTION_ACTIVATE_SUCCESS": "Підписку успішно активовано ", + "SUBSCRIPTION_ACTIVATE_FAILED": "Не вдалося відновити поновлення підписки", + "SUBSCRIPTION_PURCHASE_SUCCESS_TITLE": "Дякуємо", + "CANCEL_SUBSCRIPTION_ON_MOBILE": "Скасувати мобільну підписку", + "CANCEL_SUBSCRIPTION_ON_MOBILE_MESSAGE": "Скасуйте вашу підписку в мобільному застосунку, щоб активувати тут", + "MAIL_TO_MANAGE_SUBSCRIPTION": "Зв'яжіться з {{emailID}} для керування вашою підпискою", + "rename": "Перейменувати", + "rename_file": "Перейменувати файл", + "rename_album": "Перейменувати альбом", + "delete_album": "Видалити альбом", + "delete_album_title": "Видалити альбом?", + "delete_album_message": "Також видалити фотографії (і відео), які є в цьому альбомі, зі всіх інших альбомів, в яких вони є?", + "delete_photos": "Видалити фото", + "keep_photos": "Залишити фото", + "share_album": "Поділитися альбомом", + "SHARE_WITH_SELF": "Упс, ви не можете поділитися із собою", + "ALREADY_SHARED": "Упс, ви вже ділитеся цим з {{email}}", + "SHARING_BAD_REQUEST_ERROR": "Заборонено ділитися альбомом", + "SHARING_DISABLED_FOR_FREE_ACCOUNTS": "Спільний доступ вимкнено для безплатних облікових записів", + "CREATE_ALBUM_FAILED": "Не вдалося створити альбом, спробуйте ще раз", + "search": "пошук", + "search_results": "Результати пошуку", + "no_results": "Нічого не знайдено", + "search_hint": "Пошук альбомів, дат, описів, ...", + "album": "Альбом", + "date": "Дата", + "description": "Опис", + "file_type": "Тип файлу", + "magic": "Магія", + "photos_count_zero": "Немає спогадів", + "photos_count_one": "1 спогад", + "photos_count": "{{count, number}} спогадів", + "terms_and_conditions": "Я приймаю умови й політику приватності", + "SELECTED": "вибрано", + "people": "Люди", + "indexing_scheduled": "Індексація заплановано...", + "indexing_photos": "Індексування фотографій ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", + "indexing_fetching": "Отримання індексів ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", + "indexing_people": "Індексування людей на {{nSyncedFiles, number}} фото...", + "indexing_done": "Індексовано {{nSyncedFiles, number}} фотографій", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", + "INFO": "Інформація ", + "INFO_OPTION": "Інформація (I)", + "file_name": "Назва файлу", + "CAPTION_PLACEHOLDER": "Додати опис", + "location": "Розташування", + "view_on_map": "Переглянути на OpenStreetMap", + "map": "Мапа", + "enable_map": "Увімкнути мапу", + "enable_maps_confirm": "Увімкнути мапи?", + "enable_maps_confirm_message": "

Це покаже ваші фотографії на мапі світу.

Мапа розміщена на сайті OpenStreetMap, а точне розташування ваших фотографій ніколи не розголошується.

Ви можете вимкнути цю функцію будь-коли в налаштуваннях.

", + "disable_map": "Вимкнути мапу", + "disable_maps_confirm": "Вимкнути мапи?", + "disable_maps_confirm_message": "

Це вимкне показ ваших фотографій на мапі світу.

Ви можете увімкнути цю функцію будь-коли в налаштуваннях.

", + "DETAILS": "Подробиці", + "view_exif": "Переглянути всі дані EXIF", + "no_exif": "Немає даних EXIF", + "exif": "Exif", + "ISO": "ISO", + "two_factor": "Двоетапна", + "two_factor_authentication": "Двоетапна перевірка", + "TWO_FACTOR_QR_INSTRUCTION": "Проскануйте QR-код внизу вашим улюбленим застосунком для автентифікації", + "ENTER_CODE_MANUALLY": "Ввести код вручну", + "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "Уведіть цей код у вашому улюбленому застосунку для автентифікації", + "SCAN_QR_CODE": "Натомість просканувати QR-код", + "enable_two_factor": "Увімкнути двоетапну перевірку", + "enable": "Увімкнути", + "enabled": "Увімкнено", + "LOST_DEVICE": "Втрачено пристрій двоетапної перевірки", + "INCORRECT_CODE": "Невірний код", + "two_factor_info": "Додати додатковий рівень безпеки, вимагаючи більше, ніж ваш пошта та пароль, для входу в обліковий запис", + "disable": "Вимкнути", + "reconfigure": "Переналаштувати", + "reconfigure_two_factor_hint": "Оновити ваш пристрій для автентифікації", + "update_two_factor": "Оновити двоетапну перевірку", + "update_two_factor_message": "Продовження руху вперед призведе до анулювання всіх раніше налаштованих автентифікаторів", + "update": "Оновити", + "disable_two_factor": "Вимкнути двоетапну перевірку", + "disable_two_factor_message": "Ви впевнені, що хочете вимкнути двоетапну перевірку", + "EXPORT_DATA": "Експортувати дані", + "select_folder": "Вибрати теку", + "select_zips": "Оберіть zip", + "faq": "ЧаПи", + "takeout_hint": "Розархівуйте всі архіви в одну теку і завантажте їх. Або завантажте архіви безпосередньо. Детальніше дивіться у розділі «ЧаПи».", + "DESTINATION": "Місце призначення", + "START": "Розпочати", + "LAST_EXPORT_TIME": "Час останнього експортування", + "EXPORT_AGAIN": "Синхронізуватися знову", + "LOCAL_STORAGE_NOT_ACCESSIBLE": "Локальне сховище недоступне", + "LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE": "Ваш браузер або доповнення блокує збереження даних Ente у локальне сховище. Спробуйте завантажити цю сторінку після зміни режиму перегляду.", + "SEND_OTT": "Відправити одноразовий пароль", + "EMAIl_ALREADY_OWNED": "Пошта вже використовується", + "ETAGS_BLOCKED": "

Ми не змогли завантажити наступні файли через конфігурацію вашого браузера.

Вимкніть будь-які доповнення, які можуть перешкоджати Ente використовувати eTags, щоб завантажити великі файли, або скористайтеся нашим настільним застосунком для надійнішого імпортування.

", + "LIVE_PHOTOS_DETECTED": "Фото- та відеофайли з ваших «Фото наживо» було об'єднано в один файл", + "RETRY_FAILED": "Спробувати відновити невдалі вивантаження", + "FAILED_UPLOADS": "Не вдалося вивантажити ", + "failed_uploads_hint": "Буде можливість повторити спробу, коли вивантаження завершиться", + "SKIPPED_FILES": "Проігноровані вивантаження", + "THUMBNAIL_GENERATION_FAILED_UPLOADS": "Не вдалося створити мініатюру", + "UNSUPPORTED_FILES": "Непідтримувані файли", + "SUCCESSFUL_UPLOADS": "Успішні вивантаження", + "SKIPPED_INFO": "Пропущені файли мають назву та вміст у тому ж альбомі", + "UNSUPPORTED_INFO": "Ente ще не підтримує ці формати файлів", + "BLOCKED_UPLOADS": "Заблоковані вивантаження", + "INPROGRESS_METADATA_EXTRACTION": "У процесі", + "INPROGRESS_UPLOADS": "Вивантаження триває", + "TOO_LARGE_UPLOADS": "Великі файли", + "LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Недостатньо місця для зберігання", + "LARGER_THAN_AVAILABLE_STORAGE_INFO": "Ці файли не було завантажено, оскільки вони перевищують максимальний розмір для вашого тарифного плану", + "TOO_LARGE_INFO": "Ці файли не були завантажені, оскільки вони перевищують наш максимальний розмір файлу", + "THUMBNAIL_GENERATION_FAILED_INFO": "Ці файли були вивантажені, але, на жаль, ми не змогли створити для них мініатюри.", + "upload_to_album": "Завантажити до альбому", + "add_to_album": "Додати до альбому", + "move_to_album": "Перемістити до альбому", + "unhide_to_album": "Показати в альбомі", + "restore_to_album": "Відновити в альбомі", + "section_all": "Усі", + "section_uncategorized": "Без категорії", + "section_archive": "Архів", + "section_hidden": "Приховано", + "section_trash": "Смітник", + "favorites": "Улюблені", + "archive": "Архів", + "archive_album": "Архівувати альбом", + "unarchive": "Розархівувати", + "unarchive_album": "Розархівувати альбом", + "hide_collection": "Приховати альбом", + "unhide_collection": "Показати альбом", + "MOVE": "Перемістити", + "add": "Додати", + "REMOVE": "Видалити", + "YES_REMOVE": "Так, видалити", + "REMOVE_FROM_COLLECTION": "Видалити з альбому", + "MOVE_TO_TRASH": "Перемістити у смітник", + "TRASH_FILES_MESSAGE": "Вибрані файли буде видалено з усіх альбомів і переміщено в смітник.", + "TRASH_FILE_MESSAGE": "Файл буде видалено з усіх альбомів і переміщено в смітник.", + "DELETE_PERMANENTLY": "Остаточно видалити", + "RESTORE": "Відновити", + "empty_trash": "Очистити смітник", + "empty_trash_title": "Очистити смітник?", + "empty_trash_message": "Ці файли будуть остаточно видалені з облікового запису Ente.", + "leave_album": "Покинути альбом", + "leave_shared_album_title": "Покинути спільний альбом?", + "leave_shared_album_message": "Ви залишите альбом, і він перестане бути видимим для вас.", + "leave_shared_album": "Так, покинути", + "NOT_FILE_OWNER": "Ви не можете видалити файли зі спільного альбому", + "CONFIRM_SELF_REMOVE_MESSAGE": "Вибрані елементи будуть видалені з цього альбому. Елементи, які знаходяться в цьому альбомі, будуть переміщені в категорії «Без категорії».", + "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "Деякі з елементів, які ви видаляєте, були додані іншими людьми, і ви втратите до них доступ.", + "oldest": "Найстаріші", + "last_updated": "Востаннє оновлено", + "name": "Назва", + "FIX_CREATION_TIME": "Час виправлення", + "FIX_CREATION_TIME_IN_PROGRESS": "Час фіксації", + "CREATION_TIME_UPDATED": "Час оновлення файлу", + "UPDATE_CREATION_TIME_NOT_STARTED": "Виберіть варіант, який ви хочете використати", + "UPDATE_CREATION_TIME_COMPLETED": "Успішно оновлено всі файли", + "UPDATE_CREATION_TIME_COMPLETED_WITH_ERROR": "Для деяких файлів не вдалося виконати час оновлення файлу, спробуйте ще раз", + "CAPTION_CHARACTER_LIMIT": "Не більше 5000 символів", + "DATE_TIME_ORIGINAL": "Exif:Датачасоригіналу", + "DATE_TIME_DIGITIZED": "Exif:Датачасвизначені", + "METADATA_DATE": "Exif:Метадані", + "CUSTOM_TIME": "Власний час", + "sharing_details": "Подробиці про спільний доступ", + "modify_sharing": "Змінити спільний доступ", + "ADD_COLLABORATORS": "Додати співавторів", + "ADD_NEW_EMAIL": "Додати нову пошту", + "shared_with_people_count_zero": "Поділитися з конкретними людьми", + "shared_with_people_count_one": "Спільний доступ з 1 особою", + "shared_with_people_count": "Спільний доступ з {{count, number}} людьми", + "participants_count_zero": "Немає учасників", + "participants_count_one": "1 учасник", + "participants_count": "{{count, number}} учасників", + "ADD_VIEWERS": "Додати глядачів", + "CHANGE_PERMISSIONS_TO_VIEWER": "

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

Вони все ще зможуть видаляти додані ними фотографії

", + "CHANGE_PERMISSIONS_TO_COLLABORATOR": "{{selectedEmail}} зможуть додавати фотографії до альбому", + "CONVERT_TO_VIEWER": "Так, перетворити в глядача", + "CONVERT_TO_COLLABORATOR": "Так, перетворити в співавтора", + "CHANGE_PERMISSION": "Змінити дозвіл?", + "REMOVE_PARTICIPANT": "Видалити?", + "CONFIRM_REMOVE": "Так, видалити", + "MANAGE": "Керування", + "ADDED_AS": "Додано як", + "COLLABORATOR_RIGHTS": "Співавтори можуть додавати фотографії та відео до спільного альбому", + "REMOVE_PARTICIPANT_HEAD": "Видалити учасника", + "OWNER": "Власник", + "COLLABORATORS": "Співавтори", + "ADD_MORE": "Додати більше", + "VIEWERS": "Глядачі", + "OR_ADD_EXISTING": "Або виберіть наявний", + "REMOVE_PARTICIPANT_MESSAGE": "

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

Будь-які фото, додані ними, будуть також видалені з альбому

", + "NOT_FOUND": "404: не знайдено", + "LINK_EXPIRED": "Термін дії посилання закінчився", + "LINK_EXPIRED_MESSAGE": "Це посилання прострочене або було вимкнуто!", + "MANAGE_LINK": "Керувати посиланням", + "LINK_TOO_MANY_REQUESTS": "На жаль, цей альбом було переглянуто на занадто багатьох пристроях!", + "FILE_DOWNLOAD": "Дозволити завантаження", + "link_password_lock": "Блокування паролем", + "PUBLIC_COLLECT": "Дозволити додавати фотографії", + "LINK_DEVICE_LIMIT": "Досягнуто ліміту пристрою", + "NO_DEVICE_LIMIT": "Немає", + "LINK_EXPIRY": "Термін дії посилання закінчився", + "NEVER": "Ніколи", + "DISABLE_FILE_DOWNLOAD": "Вимкнути завантаження", + "DISABLE_FILE_DOWNLOAD_MESSAGE": "

Ви впевнені, що хочете вимкнути кнопку завантаження для файлів?

Глядачі все ще можуть робити знімки екрана або зберігати копії ваших фотографій за допомогою зовнішніх інструментів.

", + "SHARED_USING": "Спільний доступ через ", + "SHARING_REFERRAL_CODE": "Використовуйте код {{referralCode}}, щоб отримати 10 Гб безплатно", + "LIVE": "НАЖИВО", + "DISABLE_PASSWORD": "Вимкнути блокування паролем", + "DISABLE_PASSWORD_MESSAGE": "Ви дійсно хочете вимкнути блокування паролем?", + "PASSWORD_LOCK": "Блокування паролем", + "LOCK": "Заблокувати", + "file": "Файл", + "folder": "Тека", + "google_takeout": "Google Takeout", + "DEDUPLICATE_FILES": "Дублювати файли", + "NO_DUPLICATES_FOUND": "У вас немає дубльованих файлів, які можна очистити", + "FILES": "файлів", + "EACH": "кожен", + "DEDUPLICATE_BASED_ON_SIZE": "Наступні файли були об'єднані в групи за розміром, перегляньте і видаліть ті, які, на вашу думку, є дублікатами", + "STOP_ALL_UPLOADS_MESSAGE": "Ви впевнені, що хочете зупинити всі поточні вивантаження?", + "STOP_UPLOADS_HEADER": "Зупинити вивантаження?", + "YES_STOP_UPLOADS": "Так, зупинити завантаження", + "STOP_DOWNLOADS_HEADER": "Зупинити завантаження?", + "YES_STOP_DOWNLOADS": "Так, зупинити завантаження", + "STOP_ALL_DOWNLOADS_MESSAGE": "Ви впевнені, що хочете зупинити всі поточні завантаження?", + "albums": "Альбоми", + "albums_count_one": "1 альбом", + "albums_count": "{{count, number}} альбомів", + "all_albums": "Усі альбоми", + "all_hidden_albums": "Всі приховані альбоми", + "hidden_albums": "Приховані альбоми", + "hidden_items": "Приховані елементи", + "ENTER_TWO_FACTOR_OTP": "Введіть 6-значний код із застосунку автентифікації.", + "create_account": "Створити обліковий запис", + "COPIED": "Скопійовано", + "WATCH_FOLDERS": "Теки для перегляду", + "upgrade_now": "Покращити зараз", + "renew_now": "Оновити зараз", + "STORAGE": "Сховище", + "USED": "використано", + "YOU": "Ви", + "FAMILY": "Сім'я", + "FREE": "вільно", + "OF": "з", + "WATCHED_FOLDERS": "Переглянуті теки", + "NO_FOLDERS_ADDED": "Жодної теки ще не додано!", + "FOLDERS_AUTOMATICALLY_MONITORED": "Теки, які ви додасте сюди, будуть автоматично відстежуватися", + "UPLOAD_NEW_FILES_TO_ENTE": "Вивантажувати нові файли до Ente", + "REMOVE_DELETED_FILES_FROM_ENTE": "Очистити видалені файли з Ente", + "ADD_FOLDER": "Додати теку", + "STOP_WATCHING": "Припинити стежити", + "STOP_WATCHING_FOLDER": "Зупинити перегляд теки?", + "STOP_WATCHING_DIALOG_MESSAGE": "Ваші наявні файли не будуть видалені, але Ente перестане автоматично оновлювати пов'язаний альбом Ente після змін в цій теці.", + "YES_STOP": "Так, зупинити", + "CHANGE_FOLDER": "Змінити теку", + "FAMILY_PLAN": "Сімейний план", + "debug_logs": "Налагоджувальні журнали", + "download_logs": "Завантажити журнали", + "download_logs_message": "

Це призведе до завантаження журналів налагодження, які ви можете надіслати нам, щоб допомогти виправити вашу проблему.

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

", + "WEAK_DEVICE": "Веббраузер, який ви використовуєте, недостатньо потужний для шифрування ваших фотографій. Спробуйте ввійти до Ente на комп'ютері або завантажте мобільний / настільний застосунок Ente.", + "drag_and_drop_hint": "Або перетягніть у вікно Ente", + "AUTHENTICATE": "Підтвердити", + "UPLOADED_TO_SINGLE_COLLECTION": "Завантажено до однієї колекції", + "UPLOADED_TO_SEPARATE_COLLECTIONS": "Завантажено в окремі колекції", + "NEVERMIND": "Неважливо", + "update_available": "Доступне оновлення", + "update_installable_message": "Нова версія Ente готова до встановлення.", + "install_now": "Встановити зараз", + "install_on_next_launch": "Встановити при наступному запуску", + "update_available_message": "Вийшла нова версія Ente, але вона не може бути автоматично завантажена і встановлена.", + "download_and_install": "Завантажити й установити", + "ignore_this_version": "Ігнорувати цю версію", + "TODAY": "Сьогодні", + "YESTERDAY": "Вчора", + "NAME_PLACEHOLDER": "Назва...", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED": "Не вдається створити альбоми зі змішаних файлів / тек", + "ROOT_LEVEL_FILE_WITH_FOLDER_NOT_ALLOWED_MESSAGE": "

Ви перетягнули суміш файлів і тек.

При виборі параметра створення окремих альбомів, вказуйте або тільки файли, або тільки теки

", + "CHOSE_THEME": "Виберіть тему", + "more_details": "Детальніше", + "ml_search": "Машинне навчання", + "ml_search_description": "Ente підтримує машинне навчання на пристрої для розпізнавання облич, магічного пошуку та інших розширених функцій пошуку", + "ml_search_footnote": "Магічний пошук дозволяє шукати фотографії за їхнім вмістом, наприклад, «автомобіль», «червона машина», «Ferrari»", + "indexing": "Індексація", + "processed": "Оброблено", + "indexing_status_running": "Виконується", + "indexing_status_fetching": "Отримання", + "indexing_status_scheduled": "Заплановано", + "indexing_status_done": "Виконано", + "ml_search_disable": "Вимкнути машинне навчання", + "ml_search_disable_confirm": "Ви хочете вимкнути машинне навчання на всіх ваших пристроях?", + "ml_consent": "Увімкнути машинне навчання", + "ml_consent_title": "Увімкнути машинне навчання?", + "ml_consent_description": "

Якщо ви увімкнете машинне навчання, Ente буде витягувати інформацію, наприклад, геометрію обличчя, з файлів, у тому числі з тих, до яких ви надали доступ.

Це буде відбуватися на вашому пристрої, і будь-яка згенерована біометрична інформація буде наскрізно зашифрована.

Клацніть тут, щоби дізнатися більше про цю функцію в нашій політиці приватності

", + "ml_consent_confirmation": "Я розумію, та бажаю увімкнути машинне навчання", + "labs": "Лабораторії", + "YOURS": "ваші", + "passphrase_strength_weak": "Надійність пароля: Слабкий", + "passphrase_strength_moderate": "Надійність пароля: Помірний", + "passphrase_strength_strong": "Надійність пароля: Надійний", + "preferences": "Налаштування", + "language": "Мова", + "advanced": "Додатково", + "EXPORT_DIRECTORY_DOES_NOT_EXIST": "Неправильна тека для експортування", + "EXPORT_DIRECTORY_DOES_NOT_EXIST_MESSAGE": "

Вибраний каталог експорту, якого не існує.

Оберіть вірний каталог.

", + "SUBSCRIPTION_VERIFICATION_ERROR": "Не вдалося перевірити підписку", "storage_unit": { - "b": "", - "kb": "", - "mb": "", - "gb": "", - "tb": "" + "b": "Б", + "kb": "КБ", + "mb": "МБ", + "gb": "ГБ", + "tb": "ТБ" }, "AFTER_TIME": { - "HOUR": "", - "DAY": "", - "WEEK": "", - "MONTH": "", - "YEAR": "" + "HOUR": "через 1 годину", + "DAY": "через 1 день", + "WEEK": "через 1 тиждень", + "MONTH": "через 1 місяць", + "YEAR": "через 1 рік" }, - "COPY_LINK": "", - "DONE": "", - "LINK_SHARE_TITLE": "", - "REMOVE_LINK": "", - "CREATE_PUBLIC_SHARING": "", - "PUBLIC_LINK_CREATED": "", - "PUBLIC_LINK_ENABLED": "", - "COLLECT_PHOTOS": "", - "PUBLIC_COLLECT_SUBTEXT": "", - "STOP_EXPORT": "", - "EXPORT_PROGRESS": "", - "MIGRATING_EXPORT": "", - "RENAMING_COLLECTION_FOLDERS": "", - "TRASHING_DELETED_FILES": "", - "TRASHING_DELETED_COLLECTIONS": "", - "CONTINUOUS_EXPORT": "", - "PENDING_ITEMS": "", - "EXPORT_STARTING": "", - "delete_account_reason_label": "", - "delete_account_reason_placeholder": "", + "COPY_LINK": "Копіювати посилання", + "DONE": "Виконано", + "LINK_SHARE_TITLE": "Або поділіться посиланням", + "REMOVE_LINK": "Вилучити посилання", + "CREATE_PUBLIC_SHARING": "Створити публічне посилання", + "PUBLIC_LINK_CREATED": "Публічне посилання створено", + "PUBLIC_LINK_ENABLED": "Публічне посилання увімкнено", + "COLLECT_PHOTOS": "Зібрати фотографії", + "PUBLIC_COLLECT_SUBTEXT": "Дозволити людям з посиланням також додавати фотографії до спільного альбому.", + "STOP_EXPORT": "Зупинити", + "EXPORT_PROGRESS": "{{progress.success, number}} / {{progress.total, number}} елементів синхронізовано", + "MIGRATING_EXPORT": "Підготування...", + "RENAMING_COLLECTION_FOLDERS": "Перейменування тек альбомів...", + "TRASHING_DELETED_FILES": "Очищення видалених файлів...", + "TRASHING_DELETED_COLLECTIONS": "Очищення видалених альбомів...", + "CONTINUOUS_EXPORT": "Постійна синхронізація", + "PENDING_ITEMS": "Елементи на розгляді", + "EXPORT_STARTING": "Початок експортування...", + "delete_account_reason_label": "Яка основна причина видалення вашого облікового запису?", + "delete_account_reason_placeholder": "Оберіть причину", "delete_reason": { - "missing_feature": "", - "behaviour": "", - "found_another_service": "", - "not_listed": "" + "missing_feature": "Мені бракує ключової функції", + "behaviour": "Застосунок або певна функція не поводяться так, як я думаю, вони повинні", + "found_another_service": "Я знайшов інший сервіс, який подобається мені більше", + "not_listed": "Причина не перерахована" }, - "delete_account_feedback_label": "", - "delete_account_feedback_placeholder": "", - "delete_account_confirm_checkbox_label": "", - "delete_account_confirm": "", - "delete_account_confirm_message": "", - "feedback_required": "", - "feedback_required_found_another_service": "", - "RECOVER_TWO_FACTOR": "", - "at": "", - "AUTH_NEXT": "", - "AUTH_DOWNLOAD_MOBILE_APP": "", - "HIDE": "", - "UNHIDE": "", - "sort_by": "", - "newest_first": "", - "oldest_first": "", - "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "", - "pin_album": "", - "unpin_album": "", - "DOWNLOAD_COMPLETE": "", - "DOWNLOADING_COLLECTION": "", - "DOWNLOAD_FAILED": "", - "DOWNLOAD_PROGRESS": "", - "CHRISTMAS": "", - "CHRISTMAS_EVE": "", - "NEW_YEAR": "", - "NEW_YEAR_EVE": "", - "IMAGE": "", - "VIDEO": "", - "LIVE_PHOTO": "", + "delete_account_feedback_label": "Нам шкода, що ви йдете. Поясніть чому ви залишаєте нас, щоби допомогти нам стати краще.", + "delete_account_feedback_placeholder": "Зворотній зв’язок", + "delete_account_confirm_checkbox_label": "Так, я хочу безповоротно видалити цей обліковий запис та його дані", + "delete_account_confirm": "Підтвердьте видалення облікового запису", + "delete_account_confirm_message": "

Цей обліковий запис пов'язаний з іншими застосунками Ente, якщо ви ними користуєтеся.

Ваші завантажені дані в усіх застосунках Ente будуть заплановані до видалення, а ваш обліковий запис буде видалено назавжди.

", + "feedback_required": "Будь ласка, допоможіть нам із цією інформацією", + "feedback_required_found_another_service": "Що інший сервіс робить краще?", + "RECOVER_TWO_FACTOR": "Відновити двоетапну перевірку", + "at": "о", + "AUTH_NEXT": "далі", + "AUTH_DOWNLOAD_MOBILE_APP": "Завантажте наш мобільний застосунок для керування вашими таємницями", + "HIDE": "Приховати", + "UNHIDE": "Показати", + "sort_by": "Сортувати за", + "newest_first": "Спочатку найновіші", + "oldest_first": "Спочатку найстаріші", + "CONVERSION_FAILED_NOTIFICATION_MESSAGE": "Цей файл не можливо переглянути. Клацніть тут, щоб завантажити оригінал.", + "pin_album": "Закріпити альбом", + "unpin_album": "Відкріпити альбом", + "DOWNLOAD_COMPLETE": "Завантаження завершено", + "DOWNLOADING_COLLECTION": "Завантаження {{name}}", + "DOWNLOAD_FAILED": "Не вдалося завантажити", + "DOWNLOAD_PROGRESS": "{{progress.current}} / {{progress.total}} файлів", + "CHRISTMAS": "Різдво", + "CHRISTMAS_EVE": "Святвечір", + "NEW_YEAR": "Новий рік", + "NEW_YEAR_EVE": "Вечір Нового року", + "IMAGE": "Зображення", + "VIDEO": "Відео", + "LIVE_PHOTO": "Живі фото", "editor": { - "crop": "" + "crop": "Обрізати" }, - "CONVERT": "", - "confirm_editor_close": "", - "confirm_editor_close_message": "", - "BRIGHTNESS": "", - "CONTRAST": "", - "SATURATION": "", - "BLUR": "", - "INVERT_COLORS": "", - "ASPECT_RATIO": "", - "SQUARE": "", - "ROTATE_LEFT": "", - "ROTATE_RIGHT": "", - "FLIP_VERTICALLY": "", - "FLIP_HORIZONTALLY": "", - "DOWNLOAD_EDITED": "", - "SAVE_A_COPY_TO_ENTE": "", - "RESTORE_ORIGINAL": "", - "TRANSFORM": "", - "COLORS": "", - "FLIP": "", - "ROTATION": "", - "reset": "", - "PHOTO_EDITOR": "", - "FASTER_UPLOAD": "", - "FASTER_UPLOAD_DESCRIPTION": "", - "cast_album_to_tv": "", - "enter_cast_pin_code": "", - "pair_device_to_tv": "", - "tv_not_found": "", - "cast_auto_pair": "", - "cast_auto_pair_description": "", - "choose_device_from_browser": "", - "cast_auto_pair_failed": "", - "pair_with_pin": "", - "pair_with_pin_description": "", - "visit_cast_url": "", - "FREEHAND": "", - "APPLY_CROP": "", - "PHOTO_EDIT_REQUIRED_TO_SAVE": "", - "passkeys": "", - "passkey_fetch_failed": "", - "manage_passkey": "", - "delete_passkey": "", - "delete_passkey_confirmation": "", - "rename_passkey": "", - "add_passkey": "", - "enter_passkey_name": "", - "passkeys_description": "", - "created_at": "", - "passkey_add_failed": "", - "passkey_login_failed": "", - "passkey_login_invalid_url": "", - "passkey_login_already_claimed_session": "", - "passkey_login_generic_error": "", - "passkey_login_credential_hint": "", - "passkeys_not_supported": "", - "try_again": "", - "check_status": "", - "passkey_login_instructions": "", - "passkey_login": "", - "passkey": "", - "passkey_verify_description": "", - "waiting_for_verification": "", - "verification_still_pending": "", - "passkey_verified": "", - "redirecting_back_to_app": "", - "redirect_close_instructions": "", - "redirect_again": "", - "autogenerated_first_album_name": "", - "autogenerated_default_album_name": "", - "developer_settings": "", - "server_endpoint": "", - "more_information": "", - "save": "" + "CONVERT": "Перетворити", + "confirm_editor_close": "Ви впевнені, що хочете закрити редактор?", + "confirm_editor_close_message": "Завантажте відредаговане зображення або збережіть копію в Ente для збереження змін.", + "BRIGHTNESS": "Яскравість", + "CONTRAST": "Контрастність", + "SATURATION": "Насиченість", + "BLUR": "Розмиття", + "INVERT_COLORS": "Інвертувати кольори", + "ASPECT_RATIO": "Співвідношення сторін", + "SQUARE": "Квадрат", + "ROTATE_LEFT": "Повернути ліворуч", + "ROTATE_RIGHT": "Повернути праворуч", + "FLIP_VERTICALLY": "Віддзеркалити вертикально", + "FLIP_HORIZONTALLY": "Віддзеркалити горизонтально", + "DOWNLOAD_EDITED": "Завантажити відредагований", + "SAVE_A_COPY_TO_ENTE": "Зберегти копію до Ente", + "RESTORE_ORIGINAL": "Відновити оригінал", + "TRANSFORM": "Перетворити", + "COLORS": "Кольори", + "FLIP": "Перевернути", + "ROTATION": "Поворот", + "reset": "Скинути", + "PHOTO_EDITOR": "Редактор фото", + "faster_upload": "Швидші завантаження", + "faster_upload_description": "Завантаження маршрутів через найближчі сервери", + "cast_album_to_tv": "Відтворення альбому на ТБ", + "enter_cast_pin_code": "Введіть код, який ви бачите на телевізорі нижче, щоб з'єднатися з цим пристроєм.", + "pair_device_to_tv": "З'єднання між пристроями", + "tv_not_found": "Телевізор не знайдено. Ви ввели PIN-код правильно?", + "cast_auto_pair": "Автоматичне створення пари", + "cast_auto_pair_description": "Автоматичне створення пари працює лише з пристроями, що підтримують Chromecast.", + "choose_device_from_browser": "Виберіть пристрій, сумісний з трансляцією, в спливному вікні браузера.", + "cast_auto_pair_failed": "Помилка створення автоматичної пари Chromecast. Спробуйте знову.", + "pair_with_pin": "Під’єднатися через PIN-код", + "pair_with_pin_description": "Під'єднання через PIN-код працює з будь-яким екраном, на якому ви хочете переглянути альбом.", + "visit_cast_url": "Відвідайте {{url}} на пристрої, на якому ви хочете створити пару.", + "FREEHAND": "Довільне малювання", + "APPLY_CROP": "Застосувати обрізання", + "PHOTO_EDIT_REQUIRED_TO_SAVE": "Перед збереженням необхідно виконати принаймні одне перетворення чи коригування кольору.", + "passkeys": "Ключі доступу", + "passkey_fetch_failed": "Не вдалося отримати ваші ключі.", + "manage_passkey": "Керування ключем доступу", + "delete_passkey": "Видалити ключ доступу", + "delete_passkey_confirmation": "Ви впевнені, що хочете видалити цей ключ доступу? Ця дія є незворотною.", + "rename_passkey": "Перейменувати ключ доступу", + "add_passkey": "Додати ключ доступу", + "enter_passkey_name": "Введіть назву ключа доступу", + "passkeys_description": "Ключі доступу – це сучасний і безпечний другий фактор для вашого облікового запису Ente. Вони використовують біометричну автентифікацію на пристрої для зручності та безпеки.", + "created_at": "Створено", + "passkey_add_failed": "Не вдалося додати ключ доступу", + "passkey_login_failed": "Не вдалося ввійти за допомогою ключа доступу", + "passkey_login_invalid_url": "Неприпустима URL-адреса для входу.", + "passkey_login_already_claimed_session": "Цей сеанс вже підтверджено.", + "passkey_login_generic_error": "Сталася помилка під час входу через ключ доступу.", + "passkey_login_credential_hint": "Якщо у вас є ключі доступу на іншому пристрої, ви можете відкрити цю сторінку на цьому пристрої, щоби перевірити.", + "passkeys_not_supported": "Ключі доступу не підтримуються у цьому браузері", + "try_again": "Спробувати знову", + "check_status": "Перевірити стан", + "passkey_login_instructions": "Виконайте кілька кроків з вашого браузера для продовження входу.", + "passkey_login": "Увійти за допомогою ключ доступу", + "passkey": "Ключ доступу", + "passkey_verify_description": "Підтвердьте свій ключ доступу для входу в обліковий запис.", + "waiting_for_verification": "Очікується підтвердження...", + "verification_still_pending": "Перевірка все ще триває", + "passkey_verified": "Ключ доступу перевірено", + "redirecting_back_to_app": "Перенаправлення назад до застосунку...", + "redirect_close_instructions": "Ви можете закрити це вікно після відкриття застосунку.", + "redirect_again": "Перенаправити знову", + "autogenerated_first_album_name": "Мій перший альбом", + "autogenerated_default_album_name": "Новий альбом", + "developer_settings": "Налаштування для розробників", + "server_endpoint": "Кінцева точка сервера", + "more_information": "Додаткова інформація", + "save": "Зберегти" } diff --git a/web/packages/base/locales/zh-CN/translation.json b/web/packages/base/locales/zh-CN/translation.json index c61fa7b3e8..3fbcb1d4ff 100644 --- a/web/packages/base/locales/zh-CN/translation.json +++ b/web/packages/base/locales/zh-CN/translation.json @@ -47,6 +47,7 @@ "close_key": "关闭 (或按Esc键)", "enter_file_name": "文件名", "close": "关闭", + "yes": "", "no": "否", "nothing_here": "这里什么也没有", "upload": "上传", @@ -228,9 +229,26 @@ "indexing_fetching": "获取索引中 ({{nSyncedFiles, number}} / {{nTotalFiles, number}})", "indexing_people": "正在为{{nSyncedFiles, number}}张照片中的人物建立索引...", "indexing_done": "已索引 {{nSyncedFiles, number}} 张照片", - "UNIDENTIFIED_FACES": "身份不明的面孔", - "OBJECTS": "对象", - "TEXT": "文本", + "syncing_wait": "", + "people_empty_too_few": "", + "unnamed_person": "", + "add_a_name": "", + "new_person": "", + "add_name": "", + "rename_person": "", + "reset_person_confirm": "", + "reset_person_confirm_message": "", + "ignore": "", + "ignore_person_confirm": "", + "ignore_person_confirm_message": "", + "ignored": "", + "show_person": "", + "review_suggestions": "", + "saved_choices": "", + "discard_changes": "", + "discard_changes_confirm_message": "", + "people_suggestions_finding": "", + "people_suggestions_empty": "", "INFO": "图片信息 ", "INFO_OPTION": "图片信息 (I)", "file_name": "文件名", @@ -238,7 +256,6 @@ "location": "地理位置", "view_on_map": "在 OpenStreetMap 上查看", "map": "地图", - "map_settings": "地图设置", "enable_map": "启用地图", "enable_maps_confirm": "要启用地图吗?", "enable_maps_confirm_message": "

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

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

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

", @@ -250,28 +267,26 @@ "no_exif": "无 Exif 数据", "exif": "Exif", "ISO": "ISO", - "TWO_FACTOR": "双重认证", - "TWO_FACTOR_AUTHENTICATION": "双重认证", + "two_factor": "双重认证", + "two_factor_authentication": "双重认证", "TWO_FACTOR_QR_INSTRUCTION": "使用您最喜欢的身份验证器应用程序(2FA)扫描下面的二维码", "ENTER_CODE_MANUALLY": "请手动输入代码", "TWO_FACTOR_MANUAL_CODE_INSTRUCTION": "请在您最喜欢的验证器应用中输入此代码", "SCAN_QR_CODE": "改为扫描二维码", - "ENABLE_TWO_FACTOR": "启用双重认证", + "enable_two_factor": "启用双重认证", "enable": "启用", "enabled": "已启用", "LOST_DEVICE": "丢失了双重认证设备", "INCORRECT_CODE": "代码错误", - "TWO_FACTOR_INFO": "登录账户时需要的不仅仅是电子邮件和密码,这增加了额外的安全层", - "DISABLE_TWO_FACTOR_LABEL": "禁用双重认证", - "UPDATE_TWO_FACTOR_LABEL": "更新您的身份验证器设备", + "two_factor_info": "登录账户时需要的不仅仅是电子邮件和密码,这增加了额外的安全层", "disable": "禁用", "reconfigure": "重新配置", - "UPDATE_TWO_FACTOR": "更新双重认证", - "UPDATE_TWO_FACTOR_MESSAGE": "向前继续将使之前配置的任何身份验证器失效", - "UPDATE": "更新", - "DISABLE_TWO_FACTOR": "禁用双重认证", - "DISABLE_TWO_FACTOR_MESSAGE": "您确定要禁用您的双重认证吗?", - "TWO_FACTOR_DISABLE_FAILED": "禁用双重认证失败,请再试一次", + "reconfigure_two_factor_hint": "更新您的身份验证器设备", + "update_two_factor": "更新双重认证", + "update_two_factor_message": "向前继续将使之前配置的任何身份验证器失效", + "update": "更新", + "disable_two_factor": "禁用双重认证", + "disable_two_factor_message": "您确定要禁用您的双重认证吗?", "EXPORT_DATA": "导出数据", "select_folder": "选择文件夹", "select_zips": "选择压缩文件", @@ -341,9 +356,9 @@ "NOT_FILE_OWNER": "您不能删除共享相册中的文件", "CONFIRM_SELF_REMOVE_MESSAGE": "所选项目将从该相册中删除。 仅在此相册中的项目将移至未分类。", "CONFIRM_SELF_AND_OTHER_REMOVE_MESSAGE": "您要删除的某些项目是由其他人添加的,您将无法访问它们。", - "sort_by_creation_time_ascending": "最早的", - "sort_by_updation_time_descending": "最后更新", - "sort_by_name": "名称", + "oldest": "最早的", + "last_updated": "最后更新", + "name": "名称", "FIX_CREATION_TIME": "固定时间", "FIX_CREATION_TIME_IN_PROGRESS": "正在固定时间", "CREATION_TIME_UPDATED": "文件时间已更新", @@ -594,8 +609,8 @@ "ROTATION": "回转", "reset": "重设", "PHOTO_EDITOR": "照片编辑器", - "FASTER_UPLOAD": "更快上传", - "FASTER_UPLOAD_DESCRIPTION": "通过附近的服务器路由上传", + "faster_upload": "更快上传", + "faster_upload_description": "通过附近的服务器路由上传", "cast_album_to_tv": "在电视上播放相册", "enter_cast_pin_code": "输入您在下面的电视上看到的代码来配对此设备。", "pair_device_to_tv": "配对设备", diff --git a/web/packages/base/log.ts b/web/packages/base/log.ts index 10ad52bd3d..01c28c6c99 100644 --- a/web/packages/base/log.ts +++ b/web/packages/base/log.ts @@ -65,8 +65,11 @@ const messageWithError = (message: string, e?: unknown) => { return `${message}: ${es}`; }; -const logError = (message: string, e?: unknown) => { - const m = `[error] ${messageWithError(message, e)}`; +const logError = (message: unknown, e?: unknown) => { + const m = + typeof message == "string" + ? `[error] ${messageWithError(message, e)}` + : `[error] ${messageWithError("Error", message)}`; console.error(m); if (shouldLogToDisk) logToDisk(m); }; @@ -128,6 +131,9 @@ export default { * any arbitrary object that we obtain, say, when in a try-catch handler (in * JavaScript any arbitrary value can be thrown). * + * If only one argument is specified, and it is not a string, then it is + * taken as the error to be printed, paired with a generic message. + * * The log is written to disk and printed to the browser console. */ error: logError, diff --git a/web/packages/gallery/.eslintrc.js b/web/packages/gallery/.eslintrc.js new file mode 100644 index 0000000000..348075cd4f --- /dev/null +++ b/web/packages/gallery/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ["@/build-config/eslintrc-next"], +}; diff --git a/web/packages/gallery/README.md b/web/packages/gallery/README.md new file mode 100644 index 0000000000..49cddae88d --- /dev/null +++ b/web/packages/gallery/README.md @@ -0,0 +1,12 @@ +## @/gallery + +A package for sharing code between our apps that show media (photos, videos) in +a gallery like view. + +Specifically, this is the intersection of code required by both the photos and +public albums apps. + +### Packaging + +This (internal) package exports a React TypeScript library. We rely on the +importing project to transpile and bundle it. diff --git a/web/packages/gallery/package.json b/web/packages/gallery/package.json new file mode 100644 index 0000000000..4281b87fd9 --- /dev/null +++ b/web/packages/gallery/package.json @@ -0,0 +1,6 @@ +{ + "name": "@/gallery", + "version": "0.0.0", + "private": true, + "dependencies": {} +} diff --git a/web/packages/gallery/tsconfig.json b/web/packages/gallery/tsconfig.json new file mode 100644 index 0000000000..b2a1203623 --- /dev/null +++ b/web/packages/gallery/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@/build-config/tsconfig-next.json", + "include": [".", "../../packages/base/global-electron.d.ts"] +} diff --git a/web/packages/gallery/upload.ts b/web/packages/gallery/upload.ts new file mode 100644 index 0000000000..21f0d9246a --- /dev/null +++ b/web/packages/gallery/upload.ts @@ -0,0 +1,95 @@ +import log from "@/base/log"; +import { customAPIOrigin } from "@/base/origins"; +import { nullToUndefined } from "@/utils/transform"; +import { z } from "zod"; + +/** + * Internal in-memory state shared by the functions in this module. + * + * This entire object will be reset on logout. + */ +class UploadState { + /** + * `true` if the workers should be disabled for uploads. + */ + shouldDisableCFUploadProxy = false; +} + +/** State shared by the functions in this module. See {@link UploadState}. */ +let _state = new UploadState(); + +/** + * Reset any internal state maintained by the module. + * + * This is primarily meant as a way for stateful apps (e.g. photos) to clear any + * user specific state on logout. + */ +export const resetUploadState = () => { + _state = new UploadState(); +}; + +/** + * Return true to disable the upload of files via Cloudflare Workers. + * + * These workers were introduced as a way of make file uploads faster: + * https://ente.io/blog/tech/making-uploads-faster/ + * + * By default, that's the route we take. However, there are multiple reasons why + * this might be disabled. + * + * 1. During development and when self-hosting it we disable them to directly + * upload to the S3-compatible URLs returned by the ente API. + * + * 2. In rare cases, the user might have trouble reaching Cloudflare's network + * from their ISP. In such cases, the user can locally turn this off via + * settings. + * + * 3. There is also the original global toggle that was added when this feature + * was introduced. + * + * This function returns the in-memory value. It is updated when #2 changes (if + * we're running in a context where that makes sense). The #3 remote status is + * obtained once, on app start. + */ +export const shouldDisableCFUploadProxy = () => + _state.shouldDisableCFUploadProxy; + +/** + * Update the in-memory value of {@link shouldDisableCFUploadProxy}. + * + * @param savedPreference An optional user preference that the user has + * expressed to disable the proxy. + */ +export const updateShouldDisableCFUploadProxy = async ( + savedPreference?: boolean | undefined, +) => { + _state.shouldDisableCFUploadProxy = + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + savedPreference || (await computeShouldDisableCFUploadProxy()); +}; + +const computeShouldDisableCFUploadProxy = async () => { + // If a custom origin is set, that means we're not running a production + // deployment (maybe we're running locally, or being self-hosted). + // + // In such cases, disable the Cloudflare upload proxy (which won't work for + // self-hosters), and instead just directly use the upload URLs that museum + // gives us. + if (await customAPIOrigin()) return true; + + // See if the global flag to disable this is set. + try { + const res = await fetch("https://static.ente.io/feature_flags.json"); + return ( + StaticFeatureFlags.parse(await res.json()).disableCFUploadProxy ?? + false + ); + } catch (e) { + log.warn("Ignoring error when getting feature_flags.json", e); + return false; + } +}; + +const StaticFeatureFlags = z.object({ + disableCFUploadProxy: z.boolean().nullable().transform(nullToUndefined), +}); diff --git a/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx b/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx index eb52dd7aab..5859c2b8f5 100644 --- a/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx +++ b/web/packages/new/photos/components/CollectionMappingChoiceDialog.tsx @@ -1,3 +1,4 @@ +import { SpaceBetweenFlex } from "@/base/components/mui/Container"; import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import type { ModalVisibilityProps } from "@/base/components/utils/modal"; import type { CollectionMapping } from "@/base/types/ipc"; @@ -12,7 +13,6 @@ import { } from "@mui/material"; import { t } from "i18next"; import React from "react"; -import { SpaceBetweenFlex } from "./mui"; import { DialogCloseIconButton } from "./mui/Dialog"; type CollectionMappingChoiceModalProps = ModalVisibilityProps & { diff --git a/web/packages/new/photos/components/CollectionSelector.tsx b/web/packages/new/photos/components/CollectionSelector.tsx index cb052c7186..3619b3ab0a 100644 --- a/web/packages/new/photos/components/CollectionSelector.tsx +++ b/web/packages/new/photos/components/CollectionSelector.tsx @@ -1,3 +1,4 @@ +import { SpaceBetweenFlex } from "@/base/components/mui/Container"; import type { ModalVisibilityProps } from "@/base/components/utils/modal"; import type { Collection } from "@/media/collection"; import { @@ -24,7 +25,7 @@ import { } from "@mui/material"; import { t } from "i18next"; import React, { useEffect, useState } from "react"; -import { SpaceBetweenFlex, type ButtonishProps } from "./mui"; +import { type ButtonishProps } from "./mui"; import { DialogCloseIconButton } from "./mui/Dialog"; export type CollectionSelectorAction = diff --git a/web/packages/new/photos/components/CollectionsSortOptions.tsx b/web/packages/new/photos/components/CollectionsSortOptions.tsx index d69d43a28f..419224c5a4 100644 --- a/web/packages/new/photos/components/CollectionsSortOptions.tsx +++ b/web/packages/new/photos/components/CollectionsSortOptions.tsx @@ -59,13 +59,13 @@ export const CollectionsSortOptions: React.FC = ({ }} > - {t("sort_by_name")} + {t("name")} - {t("sort_by_creation_time_ascending")} + {t("oldest")} - {t("sort_by_updation_time_descending")} + {t("last_updated")} ); diff --git a/web/packages/new/photos/components/PlaceholderThumbnails.tsx b/web/packages/new/photos/components/PlaceholderThumbnails.tsx index 0fcab06569..d6fab83a28 100644 --- a/web/packages/new/photos/components/PlaceholderThumbnails.tsx +++ b/web/packages/new/photos/components/PlaceholderThumbnails.tsx @@ -1,5 +1,5 @@ +import { Overlay } from "@/base/components/mui/Container"; import { FileType } from "@/media/file-type"; -import { Overlay } from "@ente/shared/components/Container"; import PhotoOutlined from "@mui/icons-material/PhotoOutlined"; import PlayCircleOutlineOutlined from "@mui/icons-material/PlayCircleOutlineOutlined"; import { styled } from "@mui/material"; diff --git a/web/packages/new/photos/components/gallery/BarImpl.tsx b/web/packages/new/photos/components/gallery/BarImpl.tsx index 6821b622b0..29c9d7987c 100644 --- a/web/packages/new/photos/components/gallery/BarImpl.tsx +++ b/web/packages/new/photos/components/gallery/BarImpl.tsx @@ -1,3 +1,4 @@ +import { Overlay } from "@/base/components/mui/Container"; import { useIsSmallWidth } from "@/base/hooks"; import { CollectionsSortOptions } from "@/new/photos/components/CollectionsSortOptions"; import { FilledIconButton } from "@/new/photos/components/mui"; @@ -18,7 +19,6 @@ import type { } from "@/new/photos/services/collection/ui"; import type { Person } from "@/new/photos/services/ml/people"; import { ensure } from "@/utils/ensure"; -import { Overlay } from "@ente/shared/components/Container"; import ArchiveIcon from "@mui/icons-material/Archive"; import ExpandMore from "@mui/icons-material/ExpandMore"; import Favorite from "@mui/icons-material/FavoriteRounded"; diff --git a/web/packages/new/photos/components/gallery/PeopleHeader.tsx b/web/packages/new/photos/components/gallery/PeopleHeader.tsx index 79a17945c3..bda66fa1fb 100644 --- a/web/packages/new/photos/components/gallery/PeopleHeader.tsx +++ b/web/packages/new/photos/components/gallery/PeopleHeader.tsx @@ -1,8 +1,6 @@ -import { - ActivityIndicator, - ErrorIndicator, -} from "@/base/components/mui/ActivityIndicator"; -import { CenteredBox } from "@/base/components/mui/Container"; +import { ActivityErrorIndicator } from "@/base/components/ErrorIndicator"; +import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; +import { CenteredBox, SpaceBetweenFlex } from "@/base/components/mui/Container"; import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; import { LoadingButton } from "@/base/components/mui/LoadingButton"; import { @@ -10,7 +8,6 @@ import { type ModalVisibilityProps, } from "@/base/components/utils/modal"; import { useIsSmallWidth } from "@/base/hooks"; -import { pt } from "@/base/i18n"; import log from "@/base/log"; import { addCGroup, @@ -61,7 +58,7 @@ import { t } from "i18next"; import React, { useEffect, useReducer, useState } from "react"; import type { FaceCluster } from "../../services/ml/cluster"; import { useAppContext } from "../../types/context"; -import { SpaceBetweenFlex, type ButtonishProps } from "../mui"; +import { type ButtonishProps } from "../mui"; import { DialogCloseIconButton } from "../mui/Dialog"; import { SuggestionFaceList } from "../PeopleList"; import { SingleInputDialog } from "../SingleInputForm"; @@ -125,10 +122,8 @@ const CGroupPersonHeader: React.FC = ({ person }) => { const handleReset = () => showMiniDialog({ - title: pt("Reset person?"), - message: pt( - "The name, face groupings and suggestions for this person will be reset", - ), + title: t("reset_person_confirm"), + message: t("reset_person_confirm_message"), continue: { text: t("reset"), color: "primary", @@ -156,7 +151,7 @@ const CGroupPersonHeader: React.FC = ({ person }) => { centerAlign onClick={showSuggestions} > - {pt("Review suggestions")} + {t("review_suggestions")} } @@ -170,17 +165,14 @@ const CGroupPersonHeader: React.FC = ({ person }) => { centerAlign onClick={handleReset} > - {pt("Reset")} + {t("reset")} = ({ return ( <> @@ -223,7 +215,7 @@ const IgnoredPersonHeader: React.FC = ({ centerAlign onClick={handleUndoIgnore} > - {pt("Show person")} + {t("show_person")} @@ -251,12 +243,10 @@ const ClusterPersonHeader: React.FC = ({ const confirmIgnore = () => showMiniDialog({ - title: pt("Ignore person?"), - message: pt( - "This face grouping will not be shown in the people list", - ), + title: t("ignore_person_confirm"), + message: t("ignore_person_confirm_message"), continue: { - text: pt("Ignore"), + text: t("ignore"), color: "primary", action: () => ignoreCluster(cluster), }, @@ -265,13 +255,13 @@ const ClusterPersonHeader: React.FC = ({ return ( <> - + @@ -286,14 +276,14 @@ const ClusterPersonHeader: React.FC = ({ centerAlign onClick={showAddPerson} > - {pt("Add a name")} + {t("add_a_name")} } centerAlign onClick={confirmIgnore} > - {pt("Ignore")} + {t("ignore")} @@ -379,7 +369,7 @@ const AddPersonDialog: React.FC = ({ > - {pt("Add name")} + {t("add_name")} @@ -398,8 +388,8 @@ const AddPersonDialog: React.FC = ({ setOpenNameInput(false)} - title={pt("New person") /* TODO-Cluster */} - label={pt("Add name")} + title={t("new_person")} + label={t("add_name")} placeholder={t("enter_name")} autoComplete="name" autoFocus @@ -439,7 +429,7 @@ const PersonButton: React.FC = ({ const AddPerson: React.FC = ({ onClick }) => ( - {pt("New person")} + {t("new_person")} + ); @@ -606,11 +596,9 @@ const SuggestionsDialog: React.FC = ({ const handleClose = () => { if (hasUnsavedChanges) { showMiniDialog({ - message: pt( - "You have unsaved changes. These will be lost if you close without saving", - ), + message: t("discard_changes_confirm_message"), continue: { - text: pt("Discard changes"), + text: t("discard_changes"), color: "critical", action: resetPersonAndClose, }, @@ -656,8 +644,8 @@ const SuggestionsDialog: React.FC = ({ {state.showChoices - ? pt("Saved choices") - : pt("Review suggestions")} + ? t("saved_choices") + : t("review_suggestions")} {person.name ?? " "} @@ -669,8 +657,8 @@ const SuggestionsDialog: React.FC = ({ onClick={() => dispatch({ type: "toggleHistory" })} aria-label={ !state.showChoices - ? pt("Saved suggestions") - : pt("Review suggestions") + ? t("saved_choices") + : t("review_suggestions") } sx={{ backgroundColor: state.showChoices @@ -690,12 +678,12 @@ const SuggestionsDialog: React.FC = ({ {state.activity == "fetching" ? ( - {pt("Finding similar faces...")} + {t("people_suggestions_finding")} ) : state.fetchFailed ? ( - + ) : state.showChoices ? ( = ({ color="text.muted" sx={{ textAlign: "center" }} > - {pt("No more suggestions for now")} + t{"people_suggestions_empty"} ) : ( @@ -783,7 +771,7 @@ const SuggestionOrChoiceList: React.FC = ({ - + diff --git a/web/packages/new/photos/components/gallery/index.tsx b/web/packages/new/photos/components/gallery/index.tsx index 6b4515874a..9b35c445ba 100644 --- a/web/packages/new/photos/components/gallery/index.tsx +++ b/web/packages/new/photos/components/gallery/index.tsx @@ -7,7 +7,6 @@ * there. */ -import { pt } from "@/base/i18n"; import type { SearchOption } from "@/new/photos/services/search/types"; import { VerticallyCentered } from "@ente/shared/components/Container"; import { Typography } from "@mui/material"; @@ -49,10 +48,8 @@ export const PeopleEmptyState: React.FC = () => { const message = mlStatus?.phase == "done" - ? pt( - "People will be shown here when there are sufficient photos of a person", - ) - : pt("Syncing..."); + ? t("people_empty_too_few") + : t("syncing_wait"); return ( diff --git a/web/packages/new/photos/components/mui/index.tsx b/web/packages/new/photos/components/mui/index.tsx index 735de83bd4..f39034bd11 100644 --- a/web/packages/new/photos/components/mui/index.tsx +++ b/web/packages/new/photos/components/mui/index.tsx @@ -1,4 +1,4 @@ -import { Box, IconButton, styled } from "@mui/material"; +import { IconButton, styled } from "@mui/material"; /** Convenience typed props for a component that acts like a push button. */ export interface ButtonishProps { @@ -11,17 +11,3 @@ export interface ButtonishProps { export const FilledIconButton = styled(IconButton)(({ theme }) => ({ backgroundColor: theme.colors.fill.faint, })); - -/** - * A flexbox with justify content set to space-between and center alignment. - * - * There is also another SpaceBetweenFlex in the old shared package, but that - * one also sets width: 100%. As such, that one should be considered deprecated - * and its uses moved to this one when possible (so that we can then see where - * the width: 100% is essential). - */ -export const SpaceBetweenFlex = styled(Box)` - display: flex; - justify-content: space-between; - align-items: center; -`; diff --git a/web/packages/new/photos/components/MLSettings.tsx b/web/packages/new/photos/components/sidebar/MLSettings.tsx similarity index 84% rename from web/packages/new/photos/components/MLSettings.tsx rename to web/packages/new/photos/components/sidebar/MLSettings.tsx index 8959be3c6a..441c14dd61 100644 --- a/web/packages/new/photos/components/MLSettings.tsx +++ b/web/packages/new/photos/components/sidebar/MLSettings.tsx @@ -1,8 +1,10 @@ -import { EnteDrawer } from "@/base/components/EnteDrawer"; import { MenuItemGroup } from "@/base/components/Menu"; import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator"; -import { Titlebar } from "@/base/components/Titlebar"; -import type { NestedDrawerVisibilityProps } from "@/base/components/utils/modal"; +import { + NestedSidebarDrawer, + SidebarDrawerTitlebar, + type NestedSidebarDrawerVisibilityProps, +} from "@/base/components/mui/SidebarDrawer"; import { disableML, enableML, type MLStatus } from "@/new/photos/services/ml"; import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem"; import { @@ -16,17 +18,16 @@ import { Paper, Stack, Typography, - type DialogProps, } from "@mui/material"; import { t } from "i18next"; import React, { useEffect, useState } from "react"; import { Trans } from "react-i18next"; -import { useAppContext } from "../types/context"; -import { openURL } from "../utils/web"; -import { useMLStatusSnapshot } from "./utils/ml"; -import { useWrapAsyncOperation } from "./utils/use-wrap-async"; +import { useAppContext } from "../../types/context"; +import { openURL } from "../../utils/web"; +import { useMLStatusSnapshot } from "../utils/ml"; +import { useWrapAsyncOperation } from "../utils/use-wrap-async"; -export const MLSettings: React.FC = ({ +export const MLSettings: React.FC = ({ open, onClose, onRootClose, @@ -39,11 +40,6 @@ export const MLSettings: React.FC = ({ onRootClose(); }; - const handleDrawerClose: DialogProps["onClose"] = (_, reason) => { - if (reason == "backdropClick") handleRootClose(); - else onClose(); - }; - const handleEnableML = () => setOpenFaceConsent(true); const handleConsent = useWrapAsyncOperation(async () => { @@ -66,25 +62,20 @@ export const MLSettings: React.FC = ({ } return ( - - + - - + {component} - + = ({ onRootClose={handleRootClose} onConsent={handleConsent} /> - + ); }; @@ -134,7 +125,7 @@ const EnableML: React.FC = ({ onEnable }) => { ); }; -type FaceConsentProps = NestedDrawerVisibilityProps & { +type FaceConsentProps = NestedSidebarDrawerVisibilityProps & { /** Called when the user provides their consent. */ onConsent: () => void; }; @@ -156,11 +147,6 @@ const FaceConsent: React.FC = ({ onRootClose(); }; - const handleDrawerClose: DialogProps["onClose"] = (_, reason) => { - if (reason == "backdropClick") handleRootClose(); - else onClose(); - }; - const privacyPolicyLink = ( = ({ ); return ( - - @@ -233,7 +215,7 @@ const FaceConsent: React.FC = ({ -
+ ); }; diff --git a/web/packages/new/photos/components/sidebar/TwoFactorSettings.tsx b/web/packages/new/photos/components/sidebar/TwoFactorSettings.tsx new file mode 100644 index 0000000000..010bfbe1b6 --- /dev/null +++ b/web/packages/new/photos/components/sidebar/TwoFactorSettings.tsx @@ -0,0 +1,170 @@ +import { MenuItemGroup, MenuSectionTitle } from "@/base/components/Menu"; +import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton"; +import { + NestedSidebarDrawer, + SidebarDrawerTitlebar, + type NestedSidebarDrawerVisibilityProps, +} from "@/base/components/mui/SidebarDrawer"; +import { disable2FA, get2FAStatus } from "@/new/photos/services/user"; +import { useAppContext } from "@/new/photos/types/context"; +import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem"; +import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages"; +import { LS_KEYS, getData, setLSUser } from "@ente/shared/storage/localStorage"; +import LockIcon from "@mui/icons-material/Lock"; +import { Stack, Typography } from "@mui/material"; +import { t } from "i18next"; +import router, { useRouter } from "next/router"; +import { useEffect, useState } from "react"; + +export const TwoFactorSettings: React.FC< + NestedSidebarDrawerVisibilityProps +> = ({ open, onClose, onRootClose }) => { + const [isTwoFactorEnabled, setIsTwoFactorEnabled] = useState(false); + + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const isTwoFactorEnabled = + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + getData(LS_KEYS.USER).isTwoFactorEnabled ?? false; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + setIsTwoFactorEnabled(isTwoFactorEnabled); + }, []); + + useEffect(() => { + if (!open) return; + void (async () => { + const isEnabled = await get2FAStatus(); + setIsTwoFactorEnabled(isEnabled); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + await setLSUser({ + ...getData(LS_KEYS.USER), + isTwoFactorEnabled: isEnabled, + }); + })(); + }, [open]); + + const handleRootClose = () => { + onClose(); + onRootClose(); + }; + + return ( + + + + + {isTwoFactorEnabled ? ( + + ) : ( + + )} + + + ); +}; + +export default TwoFactorSettings; + +type ContentsProps = Pick; + +const SetupDrawerContents: React.FC = ({ onRootClose }) => { + const router = useRouter(); + + const configure = () => { + onRootClose(); + void router.push(PAGES.TWO_FACTOR_SETUP); + }; + + return ( + + theme.colors.text.muted, + }} + /> + + {t("two_factor_info")} + + + {t("enable_two_factor")} + + + ); +}; + +const ManageDrawerContents: React.FC = ({ onRootClose }) => { + const { showMiniDialog } = useAppContext(); + + const confirmDisable = () => + showMiniDialog({ + title: t("disable_two_factor"), + message: t("disable_two_factor_message"), + continue: { + text: t("disable"), + color: "critical", + action: disable, + }, + }); + + const disable = async () => { + await disable2FA(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + await setLSUser({ + ...getData(LS_KEYS.USER), + isTwoFactorEnabled: false, + }); + onRootClose(); + }; + + const confirmReconfigure = () => + showMiniDialog({ + title: t("update_two_factor"), + message: t("update_two_factor_message"), + continue: { + text: t("update"), + color: "primary", + action: reconfigure, + }, + }); + + const reconfigure = async () => { + onRootClose(); + await router.push(PAGES.TWO_FACTOR_SETUP); + }; + + return ( + + + + + + + + + + + + + ); +}; diff --git a/web/packages/new/photos/components/utils/dialog.tsx b/web/packages/new/photos/components/utils/dialog.tsx new file mode 100644 index 0000000000..4a01bb6d97 --- /dev/null +++ b/web/packages/new/photos/components/utils/dialog.tsx @@ -0,0 +1,33 @@ +import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; +import { Link } from "@mui/material"; +import { t } from "i18next"; +import { Trans } from "react-i18next"; + +export const confirmEnableMapsDialogAttributes = ( + onConfirm: () => void, +): MiniDialogAttributes => ({ + title: t("enable_maps_confirm"), + message: ( + + ), + }} + /> + ), + continue: { text: t("enable"), action: onConfirm }, +}); + +export const confirmDisableMapsDialogAttributes = ( + onConfirm: () => void, +): MiniDialogAttributes => ({ + title: t("disable_maps_confirm"), + message: , + continue: { text: t("disable"), color: "critical", action: onConfirm }, +}); diff --git a/web/packages/new/photos/components/utils/use-loading-bar.ts b/web/packages/new/photos/components/utils/use-loading-bar.ts new file mode 100644 index 0000000000..4c83a42349 --- /dev/null +++ b/web/packages/new/photos/components/utils/use-loading-bar.ts @@ -0,0 +1,26 @@ +import { useCallback, useRef } from "react"; +import { type LoadingBarRef } from "react-top-loading-bar"; + +/** + * A convenience hook for returning stable functions tied to a + * {@link LoadingBar} ref. + * + * The {@link LoadingBar} component comes from the "react-top-loading-bar" + * library. To control it, we keep a ref. We want to allow components in our + * React tree to be able to also control the loading bar, but instead of + * exposing the ref directly, we export wrapper functions to start and stop the + * loading bar. This hook returns these functions (and the ref). + */ +export const useLoadingBar = () => { + const loadingBarRef = useRef(); + + const showLoadingBar = useCallback(() => { + loadingBarRef.current?.continuousStart(); + }, []); + + const hideLoadingBar = useCallback(() => { + loadingBarRef.current?.complete(); + }, []); + + return { loadingBarRef, showLoadingBar, hideLoadingBar }; +}; diff --git a/web/packages/new/photos/components/utils/use-wrap-async.ts b/web/packages/new/photos/components/utils/use-wrap-async.ts index 473cd78dd6..bd77821586 100644 --- a/web/packages/new/photos/components/utils/use-wrap-async.ts +++ b/web/packages/new/photos/components/utils/use-wrap-async.ts @@ -15,18 +15,18 @@ import { useAppContext } from "../../types/context"; export const useWrapAsyncOperation = ( f: (...args: T) => Promise, ) => { - const { startLoading, finishLoading, onGenericError } = useAppContext(); + const { showLoadingBar, hideLoadingBar, onGenericError } = useAppContext(); return useCallback( async (...args: T) => { - startLoading(); + showLoadingBar(); try { await f(...args); } catch (e) { onGenericError(e); } finally { - finishLoading(); + hideLoadingBar(); } }, - [f, startLoading, finishLoading, onGenericError], + [f, showLoadingBar, hideLoadingBar, onGenericError], ); }; diff --git a/web/packages/new/photos/services/exif-update.ts b/web/packages/new/photos/services/exif-update.ts deleted file mode 100644 index 64a343ad35..0000000000 --- a/web/packages/new/photos/services/exif-update.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { lowercaseExtension } from "@/base/file"; -import log from "@/base/log"; -import type { EnteFile } from "@/media/file"; -import { FileType } from "@/media/file-type"; -import piexif from "piexifjs"; - -/** - * Return a new stream after applying Exif updates if applicable to the given - * stream, otherwise return the original. - * - * This function is meant to provide a stream that can be used to download (or - * export) a file to the user's computer after applying any Exif updates to the - * original file's data. - * - * - This only updates JPEG files. - * - * - For JPEG files, the DateTimeOriginal Exif entry is updated to reflect the - * time that the user edited within Ente. - * - * @param file The {@link EnteFile} whose data we want. - * - * @param stream A {@link ReadableStream} containing the original data for - * {@link file}. - * - * @returns A new {@link ReadableStream} with updates if any updates were - * needed, otherwise return the original stream. - */ -export const updateExifIfNeededAndPossible = async ( - file: EnteFile, - stream: ReadableStream, -): Promise> => { - // Not needed: Not an image. - if (file.metadata.fileType != FileType.image) return stream; - - // Not needed: Time was not edited. - if (!file.pubMagicMetadata?.data.editedTime) return stream; - - const fileName = file.metadata.title; - const extension = lowercaseExtension(fileName); - // Not possible: Not a JPEG (likely). - if (extension != "jpeg" && extension != "jpg") return stream; - - const blob = await new Response(stream).blob(); - try { - const updatedBlob = await setJPEGExifDateTimeOriginal( - blob, - new Date(file.pubMagicMetadata.data.editedTime / 1000), - ); - return updatedBlob.stream(); - } catch (e) { - log.error(`Failed to modify Exif date for ${fileName}`, e); - // Ignore errors and use the original - we don't want to block the whole - // download or export for an errant file. TODO: This is not always going - // to be the correct choice, but instead trying further hack around with - // the Exif modifications (and all the caveats that come with it), a - // more principled approach is to put our metadata in a sidecar and - // never touch the original. We can then and provide additional tools to - // update the original if the user so wishes from the sidecar. - return blob.stream(); - } -}; - -/** - * Return a new blob with the "DateTimeOriginal" Exif tag set to the given - * {@link date}. - * - * @param jpegBlob A {@link Blob} containing JPEG data. - * - * @param date A {@link Date} to use as the value for the Exif - * "DateTimeOriginal" tag. - * - * @returns A new blob derived from {@link jpegBlob} but with the updated date. - */ -const setJPEGExifDateTimeOriginal = async (jpegBlob: Blob, date: Date) => { - let dataURL = await blobToDataURL(jpegBlob); - // Since we pass a Blob without an associated type, we get back a generic - // data URL of the form "data:application/octet-stream;base64,...". - // - // Modify it to have a `image/jpeg` MIME type. - dataURL = "data:image/jpeg;base64" + dataURL.slice(dataURL.indexOf(",")); - - const exifObj = piexif.load(dataURL); - if (!exifObj.Exif) exifObj.Exif = {}; - exifObj.Exif[piexif.ExifIFD.DateTimeOriginal] = - convertToExifDateFormat(date); - const exifBytes = piexif.dump(exifObj); - const exifInsertedFile = piexif.insert(exifBytes, dataURL); - - return dataURLToBlob(exifInsertedFile); -}; - -/** - * Convert a blob to a `data:` URL. - */ -const blobToDataURL = (blob: Blob) => - new Promise((resolve) => { - const reader = new FileReader(); - // We need to cast to a string here. This should be safe since MDN says: - // - // > the result attribute contains the data as a data: URL representing - // > the file's data as a base64 encoded string. - // > - // > https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL - reader.onload = () => resolve(reader.result as string); - reader.readAsDataURL(blob); - }); - -/** - * Convert a `data:` URL to a blob. - * - * Requires `connect-src data:` in the CSP (since it internally uses `fetch` to - * perform the conversion). - */ -const dataURLToBlob = (dataURI: string) => - fetch(dataURI).then((res) => res.blob()); - -/** - * Convert the given {@link Date} to a format that is expected by Exif for the - * DateTimeOriginal tag. - * - * See: [Note: Exif dates] - * - * --- - * - * TODO: This functionality is deprecated. The library we use here is - * unmaintained and there are no comprehensive other JS libs. - * - * Instead of doing this in this selective way, we should provide a CLI tool - * with better format support and more comprehensive handling of Exif and other - * metadata fields (like captions) that can be used by the user to modify their - * original from the Ente sidecar if they so wish. - */ -const convertToExifDateFormat = (date: Date) => { - const YYYY = zeroPad(date.getFullYear(), 4); - // JavaScript getMonth is zero-indexed, we want one-indexed. - const MM = zeroPad(date.getMonth() + 1, 2); - // JavaScript getDate is NOT zero-indexed, it is already one-indexed. - const DD = zeroPad(date.getDate(), 2); - const HH = zeroPad(date.getHours(), 2); - const mm = zeroPad(date.getMinutes(), 2); - const ss = zeroPad(date.getSeconds(), 2); - - return `${YYYY}:${MM}:${DD} ${HH}:${mm}:${ss}`; -}; - -/** Zero pad the given number to {@link d} digits. */ -const zeroPad = (n: number, d: number) => n.toString().padStart(d, "0"); diff --git a/web/packages/new/photos/services/feature-flags.ts b/web/packages/new/photos/services/feature-flags.ts deleted file mode 100644 index d694522228..0000000000 --- a/web/packages/new/photos/services/feature-flags.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { authenticatedRequestHeaders, ensureOk } from "@/base/http"; -import { localUser } from "@/base/local-user"; -import log from "@/base/log"; -import { apiURL } from "@/base/origins"; -import { nullToUndefined } from "@/utils/transform"; -import { z } from "zod"; - -let _fetchTimeout: ReturnType | undefined; -let _haveFetched = false; - -/** - * Fetch feature flags (potentially user specific) from remote and save them in - * local storage for subsequent lookup. - * - * It fetches only once per session, and so is safe to call as arbitrarily many - * times. Remember to call {@link clearFeatureFlagSessionState} on logout to - * clear any in memory state so that these can be fetched again on the - * subsequent login. - * - * [Note: Feature Flags] - * - * The workflow with feature flags is: - * - * 1. On app start feature flags are fetched once and saved in local storage. If - * this fetch fails, we try again periodically (on every "sync") until - * success. - * - * 2. Attempts to access any individual feature flage (e.g. - * {@link isInternalUser}) returns the corresponding value from local storage - * (substituting a default if needed). - * - * 3. However, if perchance the fetch-on-app-start hasn't completed yet (or had - * failed), then a new fetch is tried. If even this fetch fails, we return - * the default. Otherwise the now fetched result is saved to local storage - * and the corresponding value returned. - */ -export const triggerFeatureFlagsFetchIfNeeded = () => { - if (_haveFetched) return; - if (_fetchTimeout) return; - // Not critical, so fetch these after some delay. - _fetchTimeout = setTimeout(() => { - _fetchTimeout = undefined; - void fetchAndSaveFeatureFlags().then(() => { - _haveFetched = true; - }); - }, 2000); -}; - -export const clearFeatureFlagSessionState = () => { - if (_fetchTimeout) { - clearTimeout(_fetchTimeout); - _fetchTimeout = undefined; - } - _haveFetched = false; -}; - -/** - * Fetch feature flags (potentially user specific) from remote and save them in - * local storage for subsequent lookup. - */ -const fetchAndSaveFeatureFlags = () => - fetchFeatureFlags() - .then((res) => res.text()) - .then(saveFlagJSONString); - -const fetchFeatureFlags = async () => { - const res = await fetch(await apiURL("/remote-store/feature-flags"), { - headers: await authenticatedRequestHeaders(), - }); - ensureOk(res); - return res; -}; - -const saveFlagJSONString = (s: string) => - localStorage.setItem("remoteFeatureFlags", s); - -const remoteFeatureFlags = () => { - const s = localStorage.getItem("remoteFeatureFlags"); - if (!s) return undefined; - return FeatureFlags.parse(JSON.parse(s)); -}; - -const FeatureFlags = z.object({ - internalUser: z.boolean().nullish().transform(nullToUndefined), - betaUser: z.boolean().nullish().transform(nullToUndefined), -}); - -type FeatureFlags = z.infer; - -const remoteFeatureFlagsFetchingIfNeeded = async () => { - let ff = remoteFeatureFlags(); - if (!ff) { - try { - await fetchAndSaveFeatureFlags(); - } catch (e) { - log.warn("Ignoring error when fetching feature flags", e); - } - ff = remoteFeatureFlags(); - } - return ff; -}; - -/** - * Return `true` if the current user is marked as an "internal" user. - * - * 1. Emails that end in `@ente.io` are considered as internal users. - * 2. If the "internalUser" remote feature flag is set, the user is internal. - * 3. Otherwise false. - * - * See also: [Note: Feature Flags]. - */ -export const isInternalUser = async () => { - const user = localUser(); - if (user?.email.endsWith("@ente.io")) return true; - - const flags = await remoteFeatureFlagsFetchingIfNeeded(); - return flags?.internalUser ?? false; -}; - -/** - * Return `true` if the current user is marked as a "beta" user. - * - * See also: [Note: Feature Flags]. - */ -export const isBetaUser = async () => { - const flags = await remoteFeatureFlagsFetchingIfNeeded(); - return flags?.betaUser ?? false; -}; diff --git a/web/packages/new/photos/services/migrations.ts b/web/packages/new/photos/services/migrations.ts index d1d367c88a..472a9c5196 100644 --- a/web/packages/new/photos/services/migrations.ts +++ b/web/packages/new/photos/services/migrations.ts @@ -100,3 +100,10 @@ const m3 = () => removeKV("entityKey/location"), removeKV("latestUpdatedAt/location"), ]); + +// TODO: Not enabled yet since it is not critical. Enable with next batch of changes. +// // Added: Nov 2025 (v1.7.7-beta). Prunable. +// const m4 = () => { +// // Delete the legacy key that used to store the map preference. +// localStorage.removeItem("mapEnabled"); +// }; diff --git a/web/packages/new/photos/services/ml/index.ts b/web/packages/new/photos/services/ml/index.ts index 5e091f9f6a..73280c0f70 100644 --- a/web/packages/new/photos/services/ml/index.ts +++ b/web/packages/new/photos/services/ml/index.ts @@ -41,9 +41,9 @@ import type { CLIPMatches } from "./worker-types"; /** * Internal state of the ML subsystem. * - * This are essentially cached values used by the functions of this module. + * These are essentially cached values used by the functions of this module. * - * This should be cleared on logout. + * They will be cleared on logout. */ class MLState { /** diff --git a/web/packages/new/photos/services/remote-store.ts b/web/packages/new/photos/services/remote-store.ts index 875f0dd3bc..2981e87bdd 100644 --- a/web/packages/new/photos/services/remote-store.ts +++ b/web/packages/new/photos/services/remote-store.ts @@ -2,6 +2,38 @@ import { authenticatedRequestHeaders, ensureOk } from "@/base/http"; import { apiURL } from "@/base/origins"; import { z } from "zod"; +/** + * [Note: Remote store] + * + * The remote store provides a unified interface for persisting varied "remote + * flags": + * + * - User preferences like "mapEnabled" + * + * - Feature flags like "isInternalUser" + * + * There are two APIs to get the current state from remote: + * + * 1. GET /remote-store/feature-flags fetches the combined state (nb: even + * though the name of the endpoint has the word feature-flags, it also + * includes user preferences). + * + * 2. GET /remote-store fetches individual values. + * + * Usually 1 is what we use, since it gets us everything in a single go, and + * which we can also easily cache in local storage by saving the entire response + * JSON blob. + * + * There is a single API (/remote-store/update) to update the state on remote. + */ +export const fetchFeatureFlags = async () => { + const res = await fetch(await apiURL("/remote-store/feature-flags"), { + headers: await authenticatedRequestHeaders(), + }); + ensureOk(res); + return res; +}; + /** * Fetch the value for the given {@link key} from remote store. * diff --git a/web/packages/new/photos/services/settings.ts b/web/packages/new/photos/services/settings.ts new file mode 100644 index 0000000000..92a6a2d149 --- /dev/null +++ b/web/packages/new/photos/services/settings.ts @@ -0,0 +1,247 @@ +/** + * @file Storage (in-memory, local, remote) and update of various settings. + */ + +/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ + +import { localUser } from "@/base/local-user"; +import log from "@/base/log"; +import { updateShouldDisableCFUploadProxy } from "@/gallery/upload"; +import { nullToUndefined } from "@/utils/transform"; +import { z } from "zod"; +import { fetchFeatureFlags, updateRemoteFlag } from "./remote-store"; + +/** + * In-memory flags that tracks various settings. + * + * Some of these are local only, some of these are synced with remote. + * + * [Note: Remote flag lifecycle] + * + * At a high level, this is how the app manages remote flags: + * + * 1. On app start, the initial are read from local storage in + * {@link initSettings}. + * + * 2. During the remote sync, remote flags are fetched and saved in local + * storage, and the in-memory state updated to reflect the latest values + * ({@link syncSettings}). + * + * 3. Updating a value also cause an unconditional fetch and update + * ({@link syncSettings}). + * + * 4. The individual getter functions for the flags (e.g. + * {@link isInternalUser}) return the in-memory values, and so are suitable + * for frequent use during UI rendering. + * + * 5. Everything gets reset to the default state on {@link logoutSettings}. + */ +export interface Settings { + /** + * `true` if the current user is an internal user. + */ + isInternalUser: boolean; + + /** + * `true` if maps are enabled. + */ + mapEnabled: boolean; + + /** + * `true` if the user has saved a preference to disable workers for uploads. + * + * Unlike {@link shouldDisableCFUploadProxy}, whose value reflects other + * factors that are taken into account to determine the effective value of + * this setting, this function returns only the saved user preference. + */ + cfUploadProxyDisabled: boolean; +} + +const defaultSettings = (): Settings => ({ + isInternalUser: false, + mapEnabled: false, + cfUploadProxyDisabled: false, +}); + +/** + * Internal in-memory state shared by the functions in this module. + * + * This entire object will be reset on logout. + */ +class SettingsState { + /** + * An arbitrary token to identify the current login. + * + * It is used to discard stale completions. + */ + id: number; + + constructor() { + this.id = Math.random(); + this.settingsSnapshot = defaultSettings(); + } + + /** + * Subscriptions to {@link Settings} updates. + * + * See {@link settingsSubscribe}. + */ + settingsListeners: (() => void)[] = []; + + /** + * Snapshot of the {@link Settings} returned by the {@link settingsSnapshot} + * function. + */ + settingsSnapshot: Settings; +} + +/** State shared by the functions in this module. See {@link SettingsState}. */ +let _state = new SettingsState(); + +/** + * Read in the locally persisted settings into memory, but otherwise do not + * initiate any network requests to fetch the latest values. + * + * This assumes that the user is already logged in. + */ +export const initSettings = () => { + void updateShouldDisableCFUploadProxy(savedCFProxyDisabled()); + syncSettingsSnapshotWithLocalStorage(); +}; + +export const logoutSettings = () => { + _state = new SettingsState(); +}; + +/** + * Fetch remote flags from remote and save them in local storage for subsequent + * lookup. Then use the results to update our in memory state if needed. + */ +export const syncSettings = async () => { + const id = _state.id; + const jsonString = await fetchFeatureFlags().then((res) => res.text()); + if (_state.id != id) { + log.info("Discarding stale settings sync not for the current login"); + return; + } + saveRemoteFeatureFlagsJSONString(jsonString); + syncSettingsSnapshotWithLocalStorage(); +}; + +const saveRemoteFeatureFlagsJSONString = (s: string) => + localStorage.setItem("remoteFeatureFlags", s); + +const savedRemoteFeatureFlags = () => { + const s = localStorage.getItem("remoteFeatureFlags"); + if (!s) return undefined; + return FeatureFlags.parse(JSON.parse(s)); +}; + +const FeatureFlags = z.object({ + internalUser: z.boolean().nullish().transform(nullToUndefined), + betaUser: z.boolean().nullish().transform(nullToUndefined), + mapEnabled: z.boolean().nullish().transform(nullToUndefined), +}); + +type FeatureFlags = z.infer; + +const syncSettingsSnapshotWithLocalStorage = () => { + const flags = savedRemoteFeatureFlags(); + const settings = defaultSettings(); + settings.isInternalUser = flags?.internalUser || isInternalUserViaEmail(); + settings.mapEnabled = flags?.mapEnabled || false; + settings.cfUploadProxyDisabled = savedCFProxyDisabled(); + setSettingsSnapshot(settings); +}; + +/** + * A function that can be used to subscribe to updates to {@link Settings}. + * + * This, along with {@link settingsSnapshot}, is meant to be used as arguments + * to React's {@link useSyncExternalStore}. + * + * @param callback A function that will be invoked whenever the result of + * {@link settingsSnapshot} changes. + * + * @returns A function that can be used to clear the subscription. + */ +export const settingsSubscribe = (onChange: () => void): (() => void) => { + _state.settingsListeners.push(onChange); + return () => { + _state.settingsListeners = _state.settingsListeners.filter( + (l) => l != onChange, + ); + }; +}; + +/** + * Return the last known, cached {@link Settings}. + * + * This, along with {@link settingsSubscribe}, is meant to be used as + * arguments to React's {@link useSyncExternalStore}. + */ +export const settingsSnapshot = () => _state.settingsSnapshot; + +const setSettingsSnapshot = (snapshot: Settings) => { + _state.settingsSnapshot = snapshot; + _state.settingsListeners.forEach((l) => l()); +}; + +const isInternalUserViaEmail = () => { + const user = localUser(); + return !!user?.email.endsWith("@ente.io"); +}; + +/** + * Return `true` if the current user is marked as an "internal" user. + * + * 1. Emails that end in `@ente.io` are considered as internal users. + * 2. If the "internalUser" remote feature flag is set, the user is internal. + * 3. Otherwise false. + */ +export const isInternalUser = () => settingsSnapshot().isInternalUser; + +/** + * Persist the user's map enabled preference both locally and on remote. + */ +export const updateMapEnabled = async (isEnabled: boolean) => { + await updateRemoteFlag("mapEnabled", isEnabled); + return syncSettings(); +}; + +const cfProxyDisabledKey = "cfProxyDisabled"; + +const saveCFProxyDisabled = (v: boolean) => + v + ? localStorage.setItem(cfProxyDisabledKey, "1") + : localStorage.removeItem(cfProxyDisabledKey); + +const savedCFProxyDisabled = () => { + const v = localStorage.getItem(cfProxyDisabledKey); + if (!v) return false; + if (v == "1") return true; + + // Older versions of the app used to store this flag in a different + // format, so see if this is one of those, and if so, migrate it too. + try { + const value = z + .object({ value: z.boolean() }) + .parse(JSON.parse(v)).value; + saveCFProxyDisabled(value); + return value; + } catch (e) { + log.warn(`Ignoring ${cfProxyDisabledKey} value: ${v}`, e); + localStorage.removeItem(cfProxyDisabledKey); + return false; + } +}; + +/** + * Save the user preference for disabling uploads via Cloudflare Workers, also + * notifying the upload subsystem of the change. + */ +export const updateCFProxyDisabledPreference = async (value: boolean) => { + saveCFProxyDisabled(value); + await updateShouldDisableCFUploadProxy(value); + syncSettingsSnapshotWithLocalStorage(); +}; diff --git a/web/packages/new/photos/services/user.ts b/web/packages/new/photos/services/user.ts index 6e7b08611e..5c20573cab 100644 --- a/web/packages/new/photos/services/user.ts +++ b/web/packages/new/photos/services/user.ts @@ -1,3 +1,10 @@ +import { authenticatedRequestHeaders, ensureOk } from "@/base/http"; +import log from "@/base/log"; +import { apiURL } from "@/base/origins"; +import { LS_KEYS, getData } from "@ente/shared/storage/localStorage"; +import type { User } from "@ente/shared/user/types"; +import { z } from "zod"; + export interface FamilyMember { email: string; usage: number; @@ -10,3 +17,71 @@ export interface FamilyData { expiry: number; members: FamilyMember[]; } + +export function getLocalFamilyData(): FamilyData { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return getData(LS_KEYS.FAMILY_DATA); +} + +// isPartOfFamily return true if the current user is part of some family plan +export function isPartOfFamily(familyData: FamilyData): boolean { + return Boolean( + // eslint-disable-next-line @typescript-eslint/prefer-optional-chain, @typescript-eslint/no-unnecessary-condition + familyData && familyData.members && familyData.members.length > 0, + ); +} + +// hasNonAdminFamilyMembers return true if the admin user has members in his family +export function hasNonAdminFamilyMembers(familyData: FamilyData): boolean { + return Boolean(isPartOfFamily(familyData) && familyData.members.length > 1); +} + +export function isFamilyAdmin(familyData: FamilyData): boolean { + const familyAdmin: FamilyMember = getFamilyPlanAdmin(familyData); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const user: User = getData(LS_KEYS.USER); + return familyAdmin.email === user.email; +} + +export function getFamilyPlanAdmin(familyData: FamilyData): FamilyMember { + if (isPartOfFamily(familyData)) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return familyData.members.find((x) => x.isAdmin)!; + } else { + log.error( + "invalid getFamilyPlanAdmin call - verify user is part of family plan before calling this method", + ); + throw new Error( + "invalid getFamilyPlanAdmin call - verify user is part of family plan before calling this method", + ); + } +} + +export function getTotalFamilyUsage(familyData: FamilyData): number { + return familyData.members.reduce( + (sum, currentMember) => sum + currentMember.usage, + 0, + ); +} + +/** + * Fetch the two-factor status (whether or not it is enabled) from remote. + */ +export const get2FAStatus = async () => { + const res = await fetch(await apiURL("/users/two-factor/status"), { + headers: await authenticatedRequestHeaders(), + }); + ensureOk(res); + return z.object({ status: z.boolean() }).parse(await res.json()).status; +}; + +/** + * Disable two-factor authentication for the current user on remote. + */ +export const disable2FA = async () => + ensureOk( + await fetch(await apiURL("/users/two-factor/disable"), { + method: "POST", + headers: await authenticatedRequestHeaders(), + }), + ); diff --git a/web/packages/new/photos/types/context.ts b/web/packages/new/photos/types/context.ts index 1d156e1cce..4fac591b5d 100644 --- a/web/packages/new/photos/types/context.ts +++ b/web/packages/new/photos/types/context.ts @@ -10,13 +10,14 @@ import type { SetNotificationAttributes } from "./notification"; */ export type AppContextT = AccountsContextT & { /** - * Show the global activity indicator (a green bar at the top of the page). + * Show the global activity indicator (a loading bar at the top of the + * page). */ - startLoading: () => void; + showLoadingBar: () => void; /** - * Hide the global activity indicator. + * Hide the global activity indicator bar. */ - finishLoading: () => void; + hideLoadingBar: () => void; /** * Show a generic error dialog, and log the given error. */ @@ -30,16 +31,12 @@ export type AppContextT = AccountsContextT & { */ setDialogMessage: SetDialogBoxAttributes; setNotificationAttributes: SetNotificationAttributes; - mapEnabled: boolean; - updateMapEnabled: (enabled: boolean) => Promise; watchFolderView: boolean; setWatchFolderView: (isOpen: boolean) => void; watchFolderFiles: FileList; setWatchFolderFiles: (files: FileList) => void; themeColor: THEME_COLOR; setThemeColor: (themeColor: THEME_COLOR) => void; - isCFProxyDisabled: boolean; - setIsCFProxyDisabled: (disabled: boolean) => void; }; /** diff --git a/web/packages/new/photos/types/piexifjs.d.ts b/web/packages/new/photos/types/piexifjs.d.ts deleted file mode 100644 index 211ee9754e..0000000000 --- a/web/packages/new/photos/types/piexifjs.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Types for [piexifjs](https://github.com/hMatoba/piexifjs). - * - * Non exhaustive, only the function we need. - */ -declare module "piexifjs" { - interface ExifObj { - Exif?: Record; - } - - interface Piexifjs { - /** - * Get exif data as object. - * - * @param jpegData a string that starts with "data:image/jpeg;base64," - * (a data URL), "\xff\xd8", or "Exif". - */ - load: (jpegData: string) => ExifObj; - /** - * Get exif as string to insert into JPEG. - * - * @param exifObj An object obtained using {@link load}. - */ - dump: (exifObj: ExifObj) => string; - /** - * Insert exif into JPEG. - * - * If {@link jpegData} is a data URL, returns the modified JPEG as a - * data URL. Else if {@link jpegData} is binary as string, returns JPEG - * as binary as string. - */ - insert: (exifStr: string, jpegData: string) => string; - /** - * Keys for the tags in {@link ExifObj}. - */ - ExifIFD: { - DateTimeOriginal: number; - }; - } - const piexifjs: Piexifjs; - export default piexifjs; -} diff --git a/web/packages/shared/components/Container.tsx b/web/packages/shared/components/Container.tsx index 9a1eb9666e..7852439cb4 100644 --- a/web/packages/shared/components/Container.tsx +++ b/web/packages/shared/components/Container.tsx @@ -32,14 +32,6 @@ export const FluidContainer = styled(FlexWrapper)` flex: 1; `; -export const Overlay = styled(Box)` - position: absolute; - width: 100%; - height: 100%; - top: 0; - left: 0; -`; - export const HorizontalFlex = styled(Box)({ display: "flex", }); diff --git a/web/packages/shared/storage/localStorage/helpers.ts b/web/packages/shared/storage/localStorage/helpers.ts index 7f46b680dd..265546dfc7 100644 --- a/web/packages/shared/storage/localStorage/helpers.ts +++ b/web/packages/shared/storage/localStorage/helpers.ts @@ -19,14 +19,6 @@ export function setJustSignedUp(status: boolean) { setData(LS_KEYS.JUST_SIGNED_UP, { status }); } -export function getLocalMapEnabled(): boolean { - return getData(LS_KEYS.MAP_ENABLED)?.value ?? false; -} - -export function setLocalMapEnabled(value: boolean) { - setData(LS_KEYS.MAP_ENABLED, { value }); -} - export function getLocalReferralSource() { return getData(LS_KEYS.REFERRAL_SOURCE)?.source; } diff --git a/web/packages/shared/storage/localStorage/index.ts b/web/packages/shared/storage/localStorage/index.ts index 2ba7e17f28..17219a867a 100644 --- a/web/packages/shared/storage/localStorage/index.ts +++ b/web/packages/shared/storage/localStorage/index.ts @@ -18,10 +18,8 @@ export enum LS_KEYS { THEME = "theme", // Moved to the new wrapper @/base/local-storage // LOCALE = 'locale', - MAP_ENABLED = "mapEnabled", SRP_SETUP_ATTRIBUTES = "srpSetupAttributes", SRP_ATTRIBUTES = "srpAttributes", - CF_PROXY_DISABLED = "cfProxyDisabled", REFERRAL_SOURCE = "referralSource", } diff --git a/web/yarn.lock b/web/yarn.lock index a3485ab6ec..ab0c8a1aa9 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -3602,11 +3602,6 @@ picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -piexifjs@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/piexifjs/-/piexifjs-1.0.6.tgz#883811d73f447218d0d06e9ed7866d04533e59e0" - integrity sha512-0wVyH0cKohzBQ5Gi2V1BuxYpxWfxF3cSqfFXfPIpl5tl9XLS5z4ogqhUCD20AbHi0h9aJkqXNJnkVev6gwh2ag== - pngjs@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821" @@ -3743,10 +3738,10 @@ react-is@^18.3.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -react-otp-input@^2.3.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/react-otp-input/-/react-otp-input-2.4.0.tgz#0f0a3de1d8c8d564e2e4fbe5d6b7b56e29e3a6e6" - integrity sha512-AIgl7u4sS9BTNCxX1xlaS5fPWay/Zml8Ho5LszXZKXrH1C/TiFsTQGmtl13UecQYO3mSF3HUzG2rrDf0sjEFmg== +react-otp-input@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/react-otp-input/-/react-otp-input-3.1.1.tgz#910169629812c40a614e6c175cc2c5f36102bb61" + integrity sha512-bjPavgJ0/Zmf/AYi4onj8FbH93IjeD+e8pWwxIJreDEWsU1ILR5fs8jEJmMGWSBe/yyvPP6X/W6Mk9UkOCkTPw== react-refresh@^0.14.2: version "0.14.2" @@ -3768,7 +3763,7 @@ react-select@^5.8.0: react-transition-group "^4.3.0" use-isomorphic-layout-effect "^1.1.2" -react-top-loading-bar@^2.0.1: +react-top-loading-bar@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/react-top-loading-bar/-/react-top-loading-bar-2.3.1.tgz#d727eb6aaa412eae52a990e5de9f33e9136ac714" integrity sha512-rQk2Nm+TOBrM1C4E3e6KwT65iXyRSgBHjCkr2FNja1S51WaPulRA5nKj/xazuQ3x89wDDdGsrqkqy0RBIfd0xg==